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.DUMP;
21 import static android.Manifest.permission.NETWORK_SETTINGS;
22 import static android.Manifest.permission.NETWORK_STACK;
23 import static android.Manifest.permission.SHUTDOWN;
24 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_DOZABLE;
25 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_DOZABLE;
26 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_NONE;
27 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_POWERSAVE;
28 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_STANDBY;
29 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NONE;
30 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_POWERSAVE;
31 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_STANDBY;
32 import static android.net.NetworkPolicyManager.FIREWALL_RULE_ALLOW;
33 import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT;
34 import static android.net.NetworkPolicyManager.FIREWALL_RULE_DENY;
35 import static android.net.NetworkPolicyManager.FIREWALL_TYPE_BLACKLIST;
36 import static android.net.NetworkPolicyManager.FIREWALL_TYPE_WHITELIST;
37 import static android.net.NetworkStats.SET_DEFAULT;
38 import static android.net.NetworkStats.STATS_PER_UID;
39 import static android.net.NetworkStats.TAG_ALL;
40 import static android.net.NetworkStats.TAG_NONE;
41 import static android.net.NetworkStats.UID_ALL;
42 import static android.net.TrafficStats.UID_TETHERING;
43 import static com.android.server.NetworkManagementService.NetdResponseCode.ClatdStatusResult;
44 import static com.android.server.NetworkManagementService.NetdResponseCode.InterfaceGetCfgResult;
45 import static com.android.server.NetworkManagementService.NetdResponseCode.InterfaceListResult;
46 import static com.android.server.NetworkManagementService.NetdResponseCode.IpFwdStatusResult;
47 import static com.android.server.NetworkManagementService.NetdResponseCode.TetherDnsFwdTgtListResult;
48 import static com.android.server.NetworkManagementService.NetdResponseCode.TetherInterfaceListResult;
49 import static com.android.server.NetworkManagementService.NetdResponseCode.TetherStatusResult;
50 import static com.android.server.NetworkManagementService.NetdResponseCode.TetheringStatsListResult;
51 import static com.android.server.NetworkManagementService.NetdResponseCode.TtyListResult;
52 import static com.android.server.NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED;
53 
54 import android.annotation.NonNull;
55 import android.app.ActivityManager;
56 import android.content.ContentResolver;
57 import android.content.Context;
58 import android.net.ConnectivityManager;
59 import android.net.INetd;
60 import android.net.INetworkManagementEventObserver;
61 import android.net.ITetheringStatsProvider;
62 import android.net.InterfaceConfiguration;
63 import android.net.IpPrefix;
64 import android.net.LinkAddress;
65 import android.net.Network;
66 import android.net.NetworkPolicyManager;
67 import android.net.NetworkStats;
68 import android.net.NetworkUtils;
69 import android.net.RouteInfo;
70 import android.net.UidRange;
71 import android.net.util.NetdService;
72 import android.net.wifi.WifiConfiguration;
73 import android.net.wifi.WifiConfiguration.KeyMgmt;
74 import android.os.BatteryStats;
75 import android.os.Binder;
76 import android.os.Handler;
77 import android.os.IBinder;
78 import android.os.INetworkActivityListener;
79 import android.os.INetworkManagementService;
80 import android.os.PersistableBundle;
81 import android.os.PowerManager;
82 import android.os.Process;
83 import android.os.RemoteCallbackList;
84 import android.os.RemoteException;
85 import android.os.ServiceManager;
86 import android.os.ServiceSpecificException;
87 import android.os.StrictMode;
88 import android.os.SystemClock;
89 import android.os.SystemProperties;
90 import android.os.Trace;
91 import android.provider.Settings;
92 import android.telephony.DataConnectionRealTimeInfo;
93 import android.telephony.PhoneStateListener;
94 import android.telephony.SubscriptionManager;
95 import android.telephony.TelephonyManager;
96 import android.text.TextUtils;
97 import android.util.Log;
98 import android.util.Slog;
99 import android.util.SparseBooleanArray;
100 import android.util.SparseIntArray;
101 
102 import com.android.internal.annotations.GuardedBy;
103 import com.android.internal.annotations.VisibleForTesting;
104 import com.android.internal.app.IBatteryStats;
105 import com.android.internal.net.NetworkStatsFactory;
106 import com.android.internal.util.DumpUtils;
107 import com.android.internal.util.HexDump;
108 import com.android.internal.util.Preconditions;
109 import com.android.server.NativeDaemonConnector.Command;
110 import com.android.server.NativeDaemonConnector.SensitiveArg;
111 import com.google.android.collect.Maps;
112 
113 import java.io.BufferedReader;
114 import java.io.DataInputStream;
115 import java.io.File;
116 import java.io.FileDescriptor;
117 import java.io.FileInputStream;
118 import java.io.IOException;
119 import java.io.InputStreamReader;
120 import java.io.PrintWriter;
121 import java.net.InetAddress;
122 import java.net.InterfaceAddress;
123 import java.net.NetworkInterface;
124 import java.net.SocketException;
125 import java.util.ArrayList;
126 import java.util.Arrays;
127 import java.util.HashMap;
128 import java.util.List;
129 import java.util.Map;
130 import java.util.NoSuchElementException;
131 import java.util.StringTokenizer;
132 import java.util.concurrent.CountDownLatch;
133 
134 /**
135  * @hide
136  */
137 public class NetworkManagementService extends INetworkManagementService.Stub
138         implements Watchdog.Monitor {
139 
140     /**
141      * Helper class that encapsulates NetworkManagementService dependencies and makes them
142      * easier to mock in unit tests.
143      */
144     static class SystemServices {
getService(String name)145         public IBinder getService(String name) {
146             return ServiceManager.getService(name);
147         }
registerLocalService(NetworkManagementInternal nmi)148         public void registerLocalService(NetworkManagementInternal nmi) {
149             LocalServices.addService(NetworkManagementInternal.class, nmi);
150         }
getNetd()151         public INetd getNetd() {
152             return NetdService.get();
153         }
154     }
155 
156     private static final String TAG = "NetworkManagement";
157     private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
158     private static final String NETD_TAG = "NetdConnector";
159     static final String NETD_SERVICE_NAME = "netd";
160 
161     private static final int MAX_UID_RANGES_PER_COMMAND = 10;
162 
163     /**
164      * Name representing {@link #setGlobalAlert(long)} limit when delivered to
165      * {@link INetworkManagementEventObserver#limitReached(String, String)}.
166      */
167     public static final String LIMIT_GLOBAL_ALERT = "globalAlert";
168 
169     /**
170      * String to pass to netd to indicate that a network is only accessible
171      * to apps that have the CHANGE_NETWORK_STATE permission.
172      */
173     public static final String PERMISSION_NETWORK = "NETWORK";
174 
175     /**
176      * String to pass to netd to indicate that a network is only
177      * accessible to system apps and those with the CONNECTIVITY_INTERNAL
178      * permission.
179      */
180     public static final String PERMISSION_SYSTEM = "SYSTEM";
181 
182     static class NetdResponseCode {
183         /* Keep in sync with system/netd/server/ResponseCode.h */
184         public static final int InterfaceListResult       = 110;
185         public static final int TetherInterfaceListResult = 111;
186         public static final int TetherDnsFwdTgtListResult = 112;
187         public static final int TtyListResult             = 113;
188         public static final int TetheringStatsListResult  = 114;
189 
190         public static final int TetherStatusResult        = 210;
191         public static final int IpFwdStatusResult         = 211;
192         public static final int InterfaceGetCfgResult     = 213;
193         public static final int SoftapStatusResult        = 214;
194         public static final int InterfaceRxCounterResult  = 216;
195         public static final int InterfaceTxCounterResult  = 217;
196         public static final int QuotaCounterResult        = 220;
197         public static final int TetheringStatsResult      = 221;
198         public static final int DnsProxyQueryResult       = 222;
199         public static final int ClatdStatusResult         = 223;
200 
201         public static final int InterfaceChange           = 600;
202         public static final int BandwidthControl          = 601;
203         public static final int InterfaceClassActivity    = 613;
204         public static final int InterfaceAddressChange    = 614;
205         public static final int InterfaceDnsServerInfo    = 615;
206         public static final int RouteChange               = 616;
207         public static final int StrictCleartext           = 617;
208     }
209 
210     /**
211      * String indicating a softap command.
212      */
213     static final String SOFT_AP_COMMAND = "softap";
214 
215     /**
216      * String passed back to netd connector indicating softap command success.
217      */
218     static final String SOFT_AP_COMMAND_SUCCESS = "Ok";
219 
220     static final int DAEMON_MSG_MOBILE_CONN_REAL_TIME_INFO = 1;
221 
222     /**
223      * Binder context for this service
224      */
225     private final Context mContext;
226 
227     /**
228      * connector object for communicating with netd
229      */
230     private final NativeDaemonConnector mConnector;
231 
232     private final Handler mFgHandler;
233     private final Handler mDaemonHandler;
234 
235     private final SystemServices mServices;
236 
237     private INetd mNetdService;
238 
239     private IBatteryStats mBatteryStats;
240 
241     private final Thread mThread;
242     private CountDownLatch mConnectedSignal = new CountDownLatch(1);
243 
244     private final RemoteCallbackList<INetworkManagementEventObserver> mObservers =
245             new RemoteCallbackList<>();
246 
247     private final NetworkStatsFactory mStatsFactory = new NetworkStatsFactory();
248 
249     @GuardedBy("mTetheringStatsProviders")
250     private final HashMap<ITetheringStatsProvider, String>
251             mTetheringStatsProviders = Maps.newHashMap();
252 
253     /**
254      * If both locks need to be held, then they should be obtained in the order:
255      * first {@link #mQuotaLock} and then {@link #mRulesLock}.
256      */
257     private final Object mQuotaLock = new Object();
258     private final Object mRulesLock = new Object();
259 
260     /** Set of interfaces with active quotas. */
261     @GuardedBy("mQuotaLock")
262     private HashMap<String, Long> mActiveQuotas = Maps.newHashMap();
263     /** Set of interfaces with active alerts. */
264     @GuardedBy("mQuotaLock")
265     private HashMap<String, Long> mActiveAlerts = Maps.newHashMap();
266     /** Set of UIDs blacklisted on metered networks. */
267     @GuardedBy("mRulesLock")
268     private SparseBooleanArray mUidRejectOnMetered = new SparseBooleanArray();
269     /** Set of UIDs whitelisted on metered networks. */
270     @GuardedBy("mRulesLock")
271     private SparseBooleanArray mUidAllowOnMetered = new SparseBooleanArray();
272     /** Set of UIDs with cleartext penalties. */
273     @GuardedBy("mQuotaLock")
274     private SparseIntArray mUidCleartextPolicy = new SparseIntArray();
275     /** Set of UIDs that are to be blocked/allowed by firewall controller. */
276     @GuardedBy("mRulesLock")
277     private SparseIntArray mUidFirewallRules = new SparseIntArray();
278     /**
279      * Set of UIDs that are to be blocked/allowed by firewall controller.  This set of Ids matches
280      * to application idles.
281      */
282     @GuardedBy("mRulesLock")
283     private SparseIntArray mUidFirewallStandbyRules = new SparseIntArray();
284     /**
285      * Set of UIDs that are to be blocked/allowed by firewall controller.  This set of Ids matches
286      * to device idles.
287      */
288     @GuardedBy("mRulesLock")
289     private SparseIntArray mUidFirewallDozableRules = new SparseIntArray();
290     /**
291      * Set of UIDs that are to be blocked/allowed by firewall controller.  This set of Ids matches
292      * to device on power-save mode.
293      */
294     @GuardedBy("mRulesLock")
295     private SparseIntArray mUidFirewallPowerSaveRules = new SparseIntArray();
296     /** Set of states for the child firewall chains. True if the chain is active. */
297     @GuardedBy("mRulesLock")
298     final SparseBooleanArray mFirewallChainStates = new SparseBooleanArray();
299 
300     @GuardedBy("mQuotaLock")
301     private volatile boolean mDataSaverMode;
302 
303     private final Object mIdleTimerLock = new Object();
304     /** Set of interfaces with active idle timers. */
305     private static class IdleTimerParams {
306         public final int timeout;
307         public final int type;
308         public int networkCount;
309 
IdleTimerParams(int timeout, int type)310         IdleTimerParams(int timeout, int type) {
311             this.timeout = timeout;
312             this.type = type;
313             this.networkCount = 1;
314         }
315     }
316     private HashMap<String, IdleTimerParams> mActiveIdleTimers = Maps.newHashMap();
317 
318     private volatile boolean mBandwidthControlEnabled;
319     private volatile boolean mFirewallEnabled;
320     private volatile boolean mStrictEnabled;
321 
322     private boolean mMobileActivityFromRadio = false;
323     private int mLastPowerStateFromRadio = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
324     private int mLastPowerStateFromWifi = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
325 
326     private final RemoteCallbackList<INetworkActivityListener> mNetworkActivityListeners =
327             new RemoteCallbackList<>();
328     private boolean mNetworkActive;
329 
330     /**
331      * Constructs a new NetworkManagementService instance
332      *
333      * @param context  Binder context for this service
334      */
NetworkManagementService( Context context, String socket, SystemServices services)335     private NetworkManagementService(
336             Context context, String socket, SystemServices services) {
337         mContext = context;
338         mServices = services;
339 
340         // make sure this is on the same looper as our NativeDaemonConnector for sync purposes
341         mFgHandler = new Handler(FgThread.get().getLooper());
342 
343         // Don't need this wake lock, since we now have a time stamp for when
344         // the network actually went inactive.  (It might be nice to still do this,
345         // but I don't want to do it through the power manager because that pollutes the
346         // battery stats history with pointless noise.)
347         //PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
348         PowerManager.WakeLock wl = null; //pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, NETD_TAG);
349 
350         mConnector = new NativeDaemonConnector(
351                 new NetdCallbackReceiver(), socket, 10, NETD_TAG, 160, wl,
352                 FgThread.get().getLooper());
353         mThread = new Thread(mConnector, NETD_TAG);
354 
355         mDaemonHandler = new Handler(FgThread.get().getLooper());
356 
357         // Add ourself to the Watchdog monitors.
358         Watchdog.getInstance().addMonitor(this);
359 
360         mServices.registerLocalService(new LocalService());
361 
362         synchronized (mTetheringStatsProviders) {
363             mTetheringStatsProviders.put(new NetdTetheringStatsProvider(), "netd");
364         }
365     }
366 
367     @VisibleForTesting
NetworkManagementService()368     NetworkManagementService() {
369         mConnector = null;
370         mContext = null;
371         mDaemonHandler = null;
372         mFgHandler = null;
373         mThread = null;
374         mServices = null;
375     }
376 
create(Context context, String socket, SystemServices services)377     static NetworkManagementService create(Context context, String socket, SystemServices services)
378             throws InterruptedException {
379         final NetworkManagementService service =
380                 new NetworkManagementService(context, socket, services);
381         final CountDownLatch connectedSignal = service.mConnectedSignal;
382         if (DBG) Slog.d(TAG, "Creating NetworkManagementService");
383         service.mThread.start();
384         if (DBG) Slog.d(TAG, "Awaiting socket connection");
385         connectedSignal.await();
386         if (DBG) Slog.d(TAG, "Connected");
387         if (DBG) Slog.d(TAG, "Connecting native netd service");
388         service.connectNativeNetdService();
389         if (DBG) Slog.d(TAG, "Connected");
390         return service;
391     }
392 
create(Context context)393     public static NetworkManagementService create(Context context) throws InterruptedException {
394         return create(context, NETD_SERVICE_NAME, new SystemServices());
395     }
396 
systemReady()397     public void systemReady() {
398         if (DBG) {
399             final long start = System.currentTimeMillis();
400             prepareNativeDaemon();
401             final long delta = System.currentTimeMillis() - start;
402             Slog.d(TAG, "Prepared in " + delta + "ms");
403             return;
404         } else {
405             prepareNativeDaemon();
406         }
407     }
408 
getBatteryStats()409     private IBatteryStats getBatteryStats() {
410         synchronized (this) {
411             if (mBatteryStats != null) {
412                 return mBatteryStats;
413             }
414             mBatteryStats =
415                     IBatteryStats.Stub.asInterface(mServices.getService(BatteryStats.SERVICE_NAME));
416             return mBatteryStats;
417         }
418     }
419 
420     @Override
registerObserver(INetworkManagementEventObserver observer)421     public void registerObserver(INetworkManagementEventObserver observer) {
422         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
423         mObservers.register(observer);
424     }
425 
426     @Override
unregisterObserver(INetworkManagementEventObserver observer)427     public void unregisterObserver(INetworkManagementEventObserver observer) {
428         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
429         mObservers.unregister(observer);
430     }
431 
432     @FunctionalInterface
433     private interface NetworkManagementEventCallback {
sendCallback(INetworkManagementEventObserver o)434         public void sendCallback(INetworkManagementEventObserver o) throws RemoteException;
435     }
436 
invokeForAllObservers(NetworkManagementEventCallback eventCallback)437     private void invokeForAllObservers(NetworkManagementEventCallback eventCallback) {
438         final int length = mObservers.beginBroadcast();
439         try {
440             for (int i = 0; i < length; i++) {
441                 try {
442                     eventCallback.sendCallback(mObservers.getBroadcastItem(i));
443                 } catch (RemoteException | RuntimeException e) {
444                 }
445             }
446         } finally {
447             mObservers.finishBroadcast();
448         }
449     }
450 
451     /**
452      * Notify our observers of an interface status change
453      */
notifyInterfaceStatusChanged(String iface, boolean up)454     private void notifyInterfaceStatusChanged(String iface, boolean up) {
455         invokeForAllObservers(o -> o.interfaceStatusChanged(iface, up));
456     }
457 
458     /**
459      * Notify our observers of an interface link state change
460      * (typically, an Ethernet cable has been plugged-in or unplugged).
461      */
notifyInterfaceLinkStateChanged(String iface, boolean up)462     private void notifyInterfaceLinkStateChanged(String iface, boolean up) {
463         invokeForAllObservers(o -> o.interfaceLinkStateChanged(iface, up));
464     }
465 
466     /**
467      * Notify our observers of an interface addition.
468      */
notifyInterfaceAdded(String iface)469     private void notifyInterfaceAdded(String iface) {
470         invokeForAllObservers(o -> o.interfaceAdded(iface));
471     }
472 
473     /**
474      * Notify our observers of an interface removal.
475      */
notifyInterfaceRemoved(String iface)476     private void notifyInterfaceRemoved(String iface) {
477         // netd already clears out quota and alerts for removed ifaces; update
478         // our sanity-checking state.
479         mActiveAlerts.remove(iface);
480         mActiveQuotas.remove(iface);
481 
482         invokeForAllObservers(o -> o.interfaceRemoved(iface));
483     }
484 
485     /**
486      * Notify our observers of a limit reached.
487      */
notifyLimitReached(String limitName, String iface)488     private void notifyLimitReached(String limitName, String iface) {
489         invokeForAllObservers(o -> o.limitReached(limitName, iface));
490     }
491 
492     /**
493      * Notify our observers of a change in the data activity state of the interface
494      */
notifyInterfaceClassActivity(int type, int powerState, long tsNanos, int uid, boolean fromRadio)495     private void notifyInterfaceClassActivity(int type, int powerState, long tsNanos,
496             int uid, boolean fromRadio) {
497         final boolean isMobile = ConnectivityManager.isNetworkTypeMobile(type);
498         if (isMobile) {
499             if (!fromRadio) {
500                 if (mMobileActivityFromRadio) {
501                     // If this call is not coming from a report from the radio itself, but we
502                     // have previously received reports from the radio, then we will take the
503                     // power state to just be whatever the radio last reported.
504                     powerState = mLastPowerStateFromRadio;
505                 }
506             } else {
507                 mMobileActivityFromRadio = true;
508             }
509             if (mLastPowerStateFromRadio != powerState) {
510                 mLastPowerStateFromRadio = powerState;
511                 try {
512                     getBatteryStats().noteMobileRadioPowerState(powerState, tsNanos, uid);
513                 } catch (RemoteException e) {
514                 }
515             }
516         }
517 
518         if (ConnectivityManager.isNetworkTypeWifi(type)) {
519             if (mLastPowerStateFromWifi != powerState) {
520                 mLastPowerStateFromWifi = powerState;
521                 try {
522                     getBatteryStats().noteWifiRadioPowerState(powerState, tsNanos, uid);
523                 } catch (RemoteException e) {
524                 }
525             }
526         }
527 
528         boolean isActive = powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM
529                 || powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH;
530 
531         if (!isMobile || fromRadio || !mMobileActivityFromRadio) {
532             // Report the change in data activity.  We don't do this if this is a change
533             // on the mobile network, that is not coming from the radio itself, and we
534             // have previously seen change reports from the radio.  In that case only
535             // the radio is the authority for the current state.
536             final boolean active = isActive;
537             invokeForAllObservers(o -> o.interfaceClassDataActivityChanged(
538                     Integer.toString(type), active, tsNanos));
539         }
540 
541         boolean report = false;
542         synchronized (mIdleTimerLock) {
543             if (mActiveIdleTimers.isEmpty()) {
544                 // If there are no idle timers, we are not monitoring activity, so we
545                 // are always considered active.
546                 isActive = true;
547             }
548             if (mNetworkActive != isActive) {
549                 mNetworkActive = isActive;
550                 report = isActive;
551             }
552         }
553         if (report) {
554             reportNetworkActive();
555         }
556     }
557 
558     @Override
registerTetheringStatsProvider(ITetheringStatsProvider provider, String name)559     public void registerTetheringStatsProvider(ITetheringStatsProvider provider, String name) {
560         mContext.enforceCallingOrSelfPermission(NETWORK_STACK, TAG);
561         Preconditions.checkNotNull(provider);
562         synchronized(mTetheringStatsProviders) {
563             mTetheringStatsProviders.put(provider, name);
564         }
565     }
566 
567     @Override
unregisterTetheringStatsProvider(ITetheringStatsProvider provider)568     public void unregisterTetheringStatsProvider(ITetheringStatsProvider provider) {
569         mContext.enforceCallingOrSelfPermission(NETWORK_STACK, TAG);
570         synchronized(mTetheringStatsProviders) {
571             mTetheringStatsProviders.remove(provider);
572         }
573     }
574 
575     @Override
tetherLimitReached(ITetheringStatsProvider provider)576     public void tetherLimitReached(ITetheringStatsProvider provider) {
577         mContext.enforceCallingOrSelfPermission(NETWORK_STACK, TAG);
578         synchronized(mTetheringStatsProviders) {
579             if (!mTetheringStatsProviders.containsKey(provider)) {
580                 return;
581             }
582             // No current code examines the interface parameter in a global alert. Just pass null.
583             notifyLimitReached(LIMIT_GLOBAL_ALERT, null);
584         }
585     }
586 
587     // Sync the state of the given chain with the native daemon.
syncFirewallChainLocked(int chain, String name)588     private void syncFirewallChainLocked(int chain, String name) {
589         SparseIntArray rules;
590         synchronized (mRulesLock) {
591             final SparseIntArray uidFirewallRules = getUidFirewallRulesLR(chain);
592             // Make a copy of the current rules, and then clear them. This is because
593             // setFirewallUidRuleInternal only pushes down rules to the native daemon if they
594             // are different from the current rules stored in the mUidFirewall*Rules array for
595             // the specified chain. If we don't clear the rules, setFirewallUidRuleInternal
596             // will do nothing.
597             rules = uidFirewallRules.clone();
598             uidFirewallRules.clear();
599         }
600         if (rules.size() > 0) {
601             // Now push the rules. setFirewallUidRuleInternal will push each of these down to the
602             // native daemon, and also add them to the mUidFirewall*Rules array for the specified
603             // chain.
604             if (DBG) Slog.d(TAG, "Pushing " + rules.size() + " active firewall "
605                     + name + "UID rules");
606             for (int i = 0; i < rules.size(); i++) {
607                 setFirewallUidRuleLocked(chain, rules.keyAt(i), rules.valueAt(i));
608             }
609         }
610     }
611 
connectNativeNetdService()612     private void connectNativeNetdService() {
613         mNetdService = mServices.getNetd();
614     }
615 
616     /**
617      * Prepare native daemon once connected, enabling modules and pushing any
618      * existing in-memory rules.
619      */
prepareNativeDaemon()620     private void prepareNativeDaemon() {
621 
622         mBandwidthControlEnabled = false;
623 
624         // only enable bandwidth control when support exists
625         final boolean hasKernelSupport = new File("/proc/net/xt_qtaguid/ctrl").exists();
626 
627         // push any existing quota or UID rules
628         synchronized (mQuotaLock) {
629 
630             if (hasKernelSupport) {
631                 Slog.d(TAG, "enabling bandwidth control");
632                 try {
633                     mConnector.execute("bandwidth", "enable");
634                     mBandwidthControlEnabled = true;
635                 } catch (NativeDaemonConnectorException e) {
636                     Log.wtf(TAG, "problem enabling bandwidth controls", e);
637                 }
638             } else {
639                 Slog.i(TAG, "not enabling bandwidth control");
640             }
641 
642             SystemProperties.set(PROP_QTAGUID_ENABLED, mBandwidthControlEnabled ? "1" : "0");
643 
644             try {
645                 mConnector.execute("strict", "enable");
646                 mStrictEnabled = true;
647             } catch (NativeDaemonConnectorException e) {
648                 Log.wtf(TAG, "Failed strict enable", e);
649             }
650 
651             setDataSaverModeEnabled(mDataSaverMode);
652 
653             int size = mActiveQuotas.size();
654             if (size > 0) {
655                 if (DBG) Slog.d(TAG, "Pushing " + size + " active quota rules");
656                 final HashMap<String, Long> activeQuotas = mActiveQuotas;
657                 mActiveQuotas = Maps.newHashMap();
658                 for (Map.Entry<String, Long> entry : activeQuotas.entrySet()) {
659                     setInterfaceQuota(entry.getKey(), entry.getValue());
660                 }
661             }
662 
663             size = mActiveAlerts.size();
664             if (size > 0) {
665                 if (DBG) Slog.d(TAG, "Pushing " + size + " active alert rules");
666                 final HashMap<String, Long> activeAlerts = mActiveAlerts;
667                 mActiveAlerts = Maps.newHashMap();
668                 for (Map.Entry<String, Long> entry : activeAlerts.entrySet()) {
669                     setInterfaceAlert(entry.getKey(), entry.getValue());
670                 }
671             }
672 
673             SparseBooleanArray uidRejectOnQuota = null;
674             SparseBooleanArray uidAcceptOnQuota = null;
675             synchronized (mRulesLock) {
676                 size = mUidRejectOnMetered.size();
677                 if (size > 0) {
678                     if (DBG) Slog.d(TAG, "Pushing " + size + " UIDs to metered blacklist rules");
679                     uidRejectOnQuota = mUidRejectOnMetered;
680                     mUidRejectOnMetered = new SparseBooleanArray();
681                 }
682 
683                 size = mUidAllowOnMetered.size();
684                 if (size > 0) {
685                     if (DBG) Slog.d(TAG, "Pushing " + size + " UIDs to metered whitelist rules");
686                     uidAcceptOnQuota = mUidAllowOnMetered;
687                     mUidAllowOnMetered = new SparseBooleanArray();
688                 }
689             }
690             if (uidRejectOnQuota != null) {
691                 for (int i = 0; i < uidRejectOnQuota.size(); i++) {
692                     setUidMeteredNetworkBlacklist(uidRejectOnQuota.keyAt(i),
693                             uidRejectOnQuota.valueAt(i));
694                 }
695             }
696             if (uidAcceptOnQuota != null) {
697                 for (int i = 0; i < uidAcceptOnQuota.size(); i++) {
698                     setUidMeteredNetworkWhitelist(uidAcceptOnQuota.keyAt(i),
699                             uidAcceptOnQuota.valueAt(i));
700                 }
701             }
702 
703             size = mUidCleartextPolicy.size();
704             if (size > 0) {
705                 if (DBG) Slog.d(TAG, "Pushing " + size + " active UID cleartext policies");
706                 final SparseIntArray local = mUidCleartextPolicy;
707                 mUidCleartextPolicy = new SparseIntArray();
708                 for (int i = 0; i < local.size(); i++) {
709                     setUidCleartextNetworkPolicy(local.keyAt(i), local.valueAt(i));
710                 }
711             }
712 
713             setFirewallEnabled(mFirewallEnabled);
714 
715             syncFirewallChainLocked(FIREWALL_CHAIN_NONE, "");
716             syncFirewallChainLocked(FIREWALL_CHAIN_STANDBY, "standby ");
717             syncFirewallChainLocked(FIREWALL_CHAIN_DOZABLE, "dozable ");
718             syncFirewallChainLocked(FIREWALL_CHAIN_POWERSAVE, "powersave ");
719 
720             final int[] chains =
721                     {FIREWALL_CHAIN_STANDBY, FIREWALL_CHAIN_DOZABLE, FIREWALL_CHAIN_POWERSAVE};
722             for (int chain : chains) {
723                 if (getFirewallChainState(chain)) {
724                     setFirewallChainEnabled(chain, true);
725                 }
726             }
727         }
728 
729         if (mBandwidthControlEnabled) {
730             try {
731                 getBatteryStats().noteNetworkStatsEnabled();
732             } catch (RemoteException e) {
733             }
734         }
735 
736     }
737 
738     /**
739      * Notify our observers of a new or updated interface address.
740      */
notifyAddressUpdated(String iface, LinkAddress address)741     private void notifyAddressUpdated(String iface, LinkAddress address) {
742         invokeForAllObservers(o -> o.addressUpdated(iface, address));
743     }
744 
745     /**
746      * Notify our observers of a deleted interface address.
747      */
notifyAddressRemoved(String iface, LinkAddress address)748     private void notifyAddressRemoved(String iface, LinkAddress address) {
749         invokeForAllObservers(o -> o.addressRemoved(iface, address));
750     }
751 
752     /**
753      * Notify our observers of DNS server information received.
754      */
notifyInterfaceDnsServerInfo(String iface, long lifetime, String[] addresses)755     private void notifyInterfaceDnsServerInfo(String iface, long lifetime, String[] addresses) {
756         invokeForAllObservers(o -> o.interfaceDnsServerInfo(iface, lifetime, addresses));
757     }
758 
759     /**
760      * Notify our observers of a route change.
761      */
notifyRouteChange(String action, RouteInfo route)762     private void notifyRouteChange(String action, RouteInfo route) {
763         if (action.equals("updated")) {
764             invokeForAllObservers(o -> o.routeUpdated(route));
765         } else {
766             invokeForAllObservers(o -> o.routeRemoved(route));
767         }
768     }
769 
770     //
771     // Netd Callback handling
772     //
773 
774     private class NetdCallbackReceiver implements INativeDaemonConnectorCallbacks {
775         @Override
onDaemonConnected()776         public void onDaemonConnected() {
777             Slog.i(TAG, "onDaemonConnected()");
778             // event is dispatched from internal NDC thread, so we prepare the
779             // daemon back on main thread.
780             if (mConnectedSignal != null) {
781                 // The system is booting and we're connecting to netd for the first time.
782                 mConnectedSignal.countDown();
783                 mConnectedSignal = null;
784             } else {
785                 // We're reconnecting to netd after the socket connection
786                 // was interrupted (e.g., if it crashed).
787                 mFgHandler.post(new Runnable() {
788                     @Override
789                     public void run() {
790                         connectNativeNetdService();
791                         prepareNativeDaemon();
792                     }
793                 });
794             }
795         }
796 
797         @Override
onCheckHoldWakeLock(int code)798         public boolean onCheckHoldWakeLock(int code) {
799             return code == NetdResponseCode.InterfaceClassActivity;
800         }
801 
802         @Override
onEvent(int code, String raw, String[] cooked)803         public boolean onEvent(int code, String raw, String[] cooked) {
804             String errorMessage = String.format("Invalid event from daemon (%s)", raw);
805             switch (code) {
806             case NetdResponseCode.InterfaceChange:
807                     /*
808                      * a network interface change occured
809                      * Format: "NNN Iface added <name>"
810                      *         "NNN Iface removed <name>"
811                      *         "NNN Iface changed <name> <up/down>"
812                      *         "NNN Iface linkstatus <name> <up/down>"
813                      */
814                     if (cooked.length < 4 || !cooked[1].equals("Iface")) {
815                         throw new IllegalStateException(errorMessage);
816                     }
817                     if (cooked[2].equals("added")) {
818                         notifyInterfaceAdded(cooked[3]);
819                         return true;
820                     } else if (cooked[2].equals("removed")) {
821                         notifyInterfaceRemoved(cooked[3]);
822                         return true;
823                     } else if (cooked[2].equals("changed") && cooked.length == 5) {
824                         notifyInterfaceStatusChanged(cooked[3], cooked[4].equals("up"));
825                         return true;
826                     } else if (cooked[2].equals("linkstate") && cooked.length == 5) {
827                         notifyInterfaceLinkStateChanged(cooked[3], cooked[4].equals("up"));
828                         return true;
829                     }
830                     throw new IllegalStateException(errorMessage);
831                     // break;
832             case NetdResponseCode.BandwidthControl:
833                     /*
834                      * Bandwidth control needs some attention
835                      * Format: "NNN limit alert <alertName> <ifaceName>"
836                      */
837                     if (cooked.length < 5 || !cooked[1].equals("limit")) {
838                         throw new IllegalStateException(errorMessage);
839                     }
840                     if (cooked[2].equals("alert")) {
841                         notifyLimitReached(cooked[3], cooked[4]);
842                         return true;
843                     }
844                     throw new IllegalStateException(errorMessage);
845                     // break;
846             case NetdResponseCode.InterfaceClassActivity:
847                     /*
848                      * An network interface class state changed (active/idle)
849                      * Format: "NNN IfaceClass <active/idle> <label>"
850                      */
851                     if (cooked.length < 4 || !cooked[1].equals("IfaceClass")) {
852                         throw new IllegalStateException(errorMessage);
853                     }
854                     long timestampNanos = 0;
855                     int processUid = -1;
856                     if (cooked.length >= 5) {
857                         try {
858                             timestampNanos = Long.parseLong(cooked[4]);
859                             if (cooked.length == 6) {
860                                 processUid = Integer.parseInt(cooked[5]);
861                             }
862                         } catch(NumberFormatException ne) {}
863                     } else {
864                         timestampNanos = SystemClock.elapsedRealtimeNanos();
865                     }
866                     boolean isActive = cooked[2].equals("active");
867                     notifyInterfaceClassActivity(Integer.parseInt(cooked[3]),
868                             isActive ? DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH
869                             : DataConnectionRealTimeInfo.DC_POWER_STATE_LOW,
870                             timestampNanos, processUid, false);
871                     return true;
872                     // break;
873             case NetdResponseCode.InterfaceAddressChange:
874                     /*
875                      * A network address change occurred
876                      * Format: "NNN Address updated <addr> <iface> <flags> <scope>"
877                      *         "NNN Address removed <addr> <iface> <flags> <scope>"
878                      */
879                     if (cooked.length < 7 || !cooked[1].equals("Address")) {
880                         throw new IllegalStateException(errorMessage);
881                     }
882 
883                     String iface = cooked[4];
884                     LinkAddress address;
885                     try {
886                         int flags = Integer.parseInt(cooked[5]);
887                         int scope = Integer.parseInt(cooked[6]);
888                         address = new LinkAddress(cooked[3], flags, scope);
889                     } catch(NumberFormatException e) {     // Non-numeric lifetime or scope.
890                         throw new IllegalStateException(errorMessage, e);
891                     } catch(IllegalArgumentException e) {  // Malformed/invalid IP address.
892                         throw new IllegalStateException(errorMessage, e);
893                     }
894 
895                     if (cooked[2].equals("updated")) {
896                         notifyAddressUpdated(iface, address);
897                     } else {
898                         notifyAddressRemoved(iface, address);
899                     }
900                     return true;
901                     // break;
902             case NetdResponseCode.InterfaceDnsServerInfo:
903                     /*
904                      * Information about available DNS servers has been received.
905                      * Format: "NNN DnsInfo servers <interface> <lifetime> <servers>"
906                      */
907                     long lifetime;  // Actually a 32-bit unsigned integer.
908 
909                     if (cooked.length == 6 &&
910                         cooked[1].equals("DnsInfo") &&
911                         cooked[2].equals("servers")) {
912                         try {
913                             lifetime = Long.parseLong(cooked[4]);
914                         } catch (NumberFormatException e) {
915                             throw new IllegalStateException(errorMessage);
916                         }
917                         String[] servers = cooked[5].split(",");
918                         notifyInterfaceDnsServerInfo(cooked[3], lifetime, servers);
919                     }
920                     return true;
921                     // break;
922             case NetdResponseCode.RouteChange:
923                     /*
924                      * A route has been updated or removed.
925                      * Format: "NNN Route <updated|removed> <dst> [via <gateway] [dev <iface>]"
926                      */
927                     if (!cooked[1].equals("Route") || cooked.length < 6) {
928                         throw new IllegalStateException(errorMessage);
929                     }
930 
931                     String via = null;
932                     String dev = null;
933                     boolean valid = true;
934                     for (int i = 4; (i + 1) < cooked.length && valid; i += 2) {
935                         if (cooked[i].equals("dev")) {
936                             if (dev == null) {
937                                 dev = cooked[i+1];
938                             } else {
939                                 valid = false;  // Duplicate interface.
940                             }
941                         } else if (cooked[i].equals("via")) {
942                             if (via == null) {
943                                 via = cooked[i+1];
944                             } else {
945                                 valid = false;  // Duplicate gateway.
946                             }
947                         } else {
948                             valid = false;      // Unknown syntax.
949                         }
950                     }
951                     if (valid) {
952                         try {
953                             // InetAddress.parseNumericAddress(null) inexplicably returns ::1.
954                             InetAddress gateway = null;
955                             if (via != null) gateway = InetAddress.parseNumericAddress(via);
956                             RouteInfo route = new RouteInfo(new IpPrefix(cooked[3]), gateway, dev);
957                             notifyRouteChange(cooked[2], route);
958                             return true;
959                         } catch (IllegalArgumentException e) {}
960                     }
961                     throw new IllegalStateException(errorMessage);
962                     // break;
963             case NetdResponseCode.StrictCleartext:
964                 final int uid = Integer.parseInt(cooked[1]);
965                 final byte[] firstPacket = HexDump.hexStringToByteArray(cooked[2]);
966                 try {
967                     ActivityManager.getService().notifyCleartextNetwork(uid, firstPacket);
968                 } catch (RemoteException ignored) {
969                 }
970                 break;
971             default: break;
972             }
973             return false;
974         }
975     }
976 
977 
978     //
979     // INetworkManagementService members
980     //
981     @Override
getNetdService()982     public INetd getNetdService() throws RemoteException {
983         final CountDownLatch connectedSignal = mConnectedSignal;
984         if (connectedSignal != null) {
985             try {
986                 connectedSignal.await();
987             } catch (InterruptedException ignored) {}
988         }
989 
990         return mNetdService;
991     }
992 
993     @Override
listInterfaces()994     public String[] listInterfaces() {
995         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
996         try {
997             return NativeDaemonEvent.filterMessageList(
998                     mConnector.executeForList("interface", "list"), InterfaceListResult);
999         } catch (NativeDaemonConnectorException e) {
1000             throw e.rethrowAsParcelableException();
1001         }
1002     }
1003 
1004     @Override
getInterfaceConfig(String iface)1005     public InterfaceConfiguration getInterfaceConfig(String iface) {
1006         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1007 
1008         final NativeDaemonEvent event;
1009         try {
1010             event = mConnector.execute("interface", "getcfg", iface);
1011         } catch (NativeDaemonConnectorException e) {
1012             throw e.rethrowAsParcelableException();
1013         }
1014 
1015         event.checkCode(InterfaceGetCfgResult);
1016 
1017         // Rsp: 213 xx:xx:xx:xx:xx:xx yyy.yyy.yyy.yyy zzz flag1 flag2 flag3
1018         final StringTokenizer st = new StringTokenizer(event.getMessage());
1019 
1020         InterfaceConfiguration cfg;
1021         try {
1022             cfg = new InterfaceConfiguration();
1023             cfg.setHardwareAddress(st.nextToken(" "));
1024             InetAddress addr = null;
1025             int prefixLength = 0;
1026             try {
1027                 addr = NetworkUtils.numericToInetAddress(st.nextToken());
1028             } catch (IllegalArgumentException iae) {
1029                 Slog.e(TAG, "Failed to parse ipaddr", iae);
1030             }
1031 
1032             try {
1033                 prefixLength = Integer.parseInt(st.nextToken());
1034             } catch (NumberFormatException nfe) {
1035                 Slog.e(TAG, "Failed to parse prefixLength", nfe);
1036             }
1037 
1038             cfg.setLinkAddress(new LinkAddress(addr, prefixLength));
1039             while (st.hasMoreTokens()) {
1040                 cfg.setFlag(st.nextToken());
1041             }
1042         } catch (NoSuchElementException nsee) {
1043             throw new IllegalStateException("Invalid response from daemon: " + event);
1044         }
1045         return cfg;
1046     }
1047 
1048     @Override
setInterfaceConfig(String iface, InterfaceConfiguration cfg)1049     public void setInterfaceConfig(String iface, InterfaceConfiguration cfg) {
1050         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1051         LinkAddress linkAddr = cfg.getLinkAddress();
1052         if (linkAddr == null || linkAddr.getAddress() == null) {
1053             throw new IllegalStateException("Null LinkAddress given");
1054         }
1055 
1056         final Command cmd = new Command("interface", "setcfg", iface,
1057                 linkAddr.getAddress().getHostAddress(),
1058                 linkAddr.getPrefixLength());
1059         for (String flag : cfg.getFlags()) {
1060             cmd.appendArg(flag);
1061         }
1062 
1063         try {
1064             mConnector.execute(cmd);
1065         } catch (NativeDaemonConnectorException e) {
1066             throw e.rethrowAsParcelableException();
1067         }
1068     }
1069 
1070     @Override
setInterfaceDown(String iface)1071     public void setInterfaceDown(String iface) {
1072         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1073         final InterfaceConfiguration ifcg = getInterfaceConfig(iface);
1074         ifcg.setInterfaceDown();
1075         setInterfaceConfig(iface, ifcg);
1076     }
1077 
1078     @Override
setInterfaceUp(String iface)1079     public void setInterfaceUp(String iface) {
1080         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1081         final InterfaceConfiguration ifcg = getInterfaceConfig(iface);
1082         ifcg.setInterfaceUp();
1083         setInterfaceConfig(iface, ifcg);
1084     }
1085 
1086     @Override
setInterfaceIpv6PrivacyExtensions(String iface, boolean enable)1087     public void setInterfaceIpv6PrivacyExtensions(String iface, boolean enable) {
1088         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1089         try {
1090             mConnector.execute(
1091                     "interface", "ipv6privacyextensions", iface, enable ? "enable" : "disable");
1092         } catch (NativeDaemonConnectorException e) {
1093             throw e.rethrowAsParcelableException();
1094         }
1095     }
1096 
1097     /* TODO: This is right now a IPv4 only function. Works for wifi which loses its
1098        IPv6 addresses on interface down, but we need to do full clean up here */
1099     @Override
clearInterfaceAddresses(String iface)1100     public void clearInterfaceAddresses(String iface) {
1101         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1102         try {
1103             mConnector.execute("interface", "clearaddrs", iface);
1104         } catch (NativeDaemonConnectorException e) {
1105             throw e.rethrowAsParcelableException();
1106         }
1107     }
1108 
1109     @Override
enableIpv6(String iface)1110     public void enableIpv6(String iface) {
1111         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1112         try {
1113             mConnector.execute("interface", "ipv6", iface, "enable");
1114         } catch (NativeDaemonConnectorException e) {
1115             throw e.rethrowAsParcelableException();
1116         }
1117     }
1118 
1119     @Override
setIPv6AddrGenMode(String iface, int mode)1120     public void setIPv6AddrGenMode(String iface, int mode) throws ServiceSpecificException {
1121         try {
1122             mNetdService.setIPv6AddrGenMode(iface, mode);
1123         } catch (RemoteException e) {
1124             throw e.rethrowAsRuntimeException();
1125         }
1126     }
1127 
1128     @Override
disableIpv6(String iface)1129     public void disableIpv6(String iface) {
1130         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1131         try {
1132             mConnector.execute("interface", "ipv6", iface, "disable");
1133         } catch (NativeDaemonConnectorException e) {
1134             throw e.rethrowAsParcelableException();
1135         }
1136     }
1137 
1138     @Override
addRoute(int netId, RouteInfo route)1139     public void addRoute(int netId, RouteInfo route) {
1140         modifyRoute("add", "" + netId, route);
1141     }
1142 
1143     @Override
removeRoute(int netId, RouteInfo route)1144     public void removeRoute(int netId, RouteInfo route) {
1145         modifyRoute("remove", "" + netId, route);
1146     }
1147 
modifyRoute(String action, String netId, RouteInfo route)1148     private void modifyRoute(String action, String netId, RouteInfo route) {
1149         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1150 
1151         final Command cmd = new Command("network", "route", action, netId);
1152 
1153         // create triplet: interface dest-ip-addr/prefixlength gateway-ip-addr
1154         cmd.appendArg(route.getInterface());
1155         cmd.appendArg(route.getDestination().toString());
1156 
1157         switch (route.getType()) {
1158             case RouteInfo.RTN_UNICAST:
1159                 if (route.hasGateway()) {
1160                     cmd.appendArg(route.getGateway().getHostAddress());
1161                 }
1162                 break;
1163             case RouteInfo.RTN_UNREACHABLE:
1164                 cmd.appendArg("unreachable");
1165                 break;
1166             case RouteInfo.RTN_THROW:
1167                 cmd.appendArg("throw");
1168                 break;
1169         }
1170 
1171         try {
1172             mConnector.execute(cmd);
1173         } catch (NativeDaemonConnectorException e) {
1174             throw e.rethrowAsParcelableException();
1175         }
1176     }
1177 
readRouteList(String filename)1178     private ArrayList<String> readRouteList(String filename) {
1179         FileInputStream fstream = null;
1180         ArrayList<String> list = new ArrayList<>();
1181 
1182         try {
1183             fstream = new FileInputStream(filename);
1184             DataInputStream in = new DataInputStream(fstream);
1185             BufferedReader br = new BufferedReader(new InputStreamReader(in));
1186             String s;
1187 
1188             // throw away the title line
1189 
1190             while (((s = br.readLine()) != null) && (s.length() != 0)) {
1191                 list.add(s);
1192             }
1193         } catch (IOException ex) {
1194             // return current list, possibly empty
1195         } finally {
1196             if (fstream != null) {
1197                 try {
1198                     fstream.close();
1199                 } catch (IOException ex) {}
1200             }
1201         }
1202 
1203         return list;
1204     }
1205 
1206     @Override
setMtu(String iface, int mtu)1207     public void setMtu(String iface, int mtu) {
1208         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1209 
1210         final NativeDaemonEvent event;
1211         try {
1212             event = mConnector.execute("interface", "setmtu", iface, mtu);
1213         } catch (NativeDaemonConnectorException e) {
1214             throw e.rethrowAsParcelableException();
1215         }
1216     }
1217 
1218     @Override
shutdown()1219     public void shutdown() {
1220         // TODO: remove from aidl if nobody calls externally
1221         mContext.enforceCallingOrSelfPermission(SHUTDOWN, TAG);
1222 
1223         Slog.i(TAG, "Shutting down");
1224     }
1225 
1226     @Override
getIpForwardingEnabled()1227     public boolean getIpForwardingEnabled() throws IllegalStateException{
1228         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1229 
1230         final NativeDaemonEvent event;
1231         try {
1232             event = mConnector.execute("ipfwd", "status");
1233         } catch (NativeDaemonConnectorException e) {
1234             throw e.rethrowAsParcelableException();
1235         }
1236 
1237         // 211 Forwarding enabled
1238         event.checkCode(IpFwdStatusResult);
1239         return event.getMessage().endsWith("enabled");
1240     }
1241 
1242     @Override
setIpForwardingEnabled(boolean enable)1243     public void setIpForwardingEnabled(boolean enable) {
1244         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1245         try {
1246             mConnector.execute("ipfwd", enable ? "enable" : "disable", "tethering");
1247         } catch (NativeDaemonConnectorException e) {
1248             throw e.rethrowAsParcelableException();
1249         }
1250     }
1251 
1252     @Override
startTethering(String[] dhcpRange)1253     public void startTethering(String[] dhcpRange) {
1254         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1255         // cmd is "tether start first_start first_stop second_start second_stop ..."
1256         // an odd number of addrs will fail
1257 
1258         final Command cmd = new Command("tether", "start");
1259         for (String d : dhcpRange) {
1260             cmd.appendArg(d);
1261         }
1262 
1263         try {
1264             mConnector.execute(cmd);
1265         } catch (NativeDaemonConnectorException e) {
1266             throw e.rethrowAsParcelableException();
1267         }
1268     }
1269 
1270     @Override
stopTethering()1271     public void stopTethering() {
1272         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1273         try {
1274             mConnector.execute("tether", "stop");
1275         } catch (NativeDaemonConnectorException e) {
1276             throw e.rethrowAsParcelableException();
1277         }
1278     }
1279 
1280     @Override
isTetheringStarted()1281     public boolean isTetheringStarted() {
1282         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1283 
1284         final NativeDaemonEvent event;
1285         try {
1286             event = mConnector.execute("tether", "status");
1287         } catch (NativeDaemonConnectorException e) {
1288             throw e.rethrowAsParcelableException();
1289         }
1290 
1291         // 210 Tethering services started
1292         event.checkCode(TetherStatusResult);
1293         return event.getMessage().endsWith("started");
1294     }
1295 
1296     @Override
tetherInterface(String iface)1297     public void tetherInterface(String iface) {
1298         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1299         try {
1300             mConnector.execute("tether", "interface", "add", iface);
1301         } catch (NativeDaemonConnectorException e) {
1302             throw e.rethrowAsParcelableException();
1303         }
1304         List<RouteInfo> routes = new ArrayList<>();
1305         // The RouteInfo constructor truncates the LinkAddress to a network prefix, thus making it
1306         // suitable to use as a route destination.
1307         routes.add(new RouteInfo(getInterfaceConfig(iface).getLinkAddress(), null, iface));
1308         addInterfaceToLocalNetwork(iface, routes);
1309     }
1310 
1311     @Override
untetherInterface(String iface)1312     public void untetherInterface(String iface) {
1313         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1314         try {
1315             mConnector.execute("tether", "interface", "remove", iface);
1316         } catch (NativeDaemonConnectorException e) {
1317             throw e.rethrowAsParcelableException();
1318         } finally {
1319             removeInterfaceFromLocalNetwork(iface);
1320         }
1321     }
1322 
1323     @Override
listTetheredInterfaces()1324     public String[] listTetheredInterfaces() {
1325         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1326         try {
1327             return NativeDaemonEvent.filterMessageList(
1328                     mConnector.executeForList("tether", "interface", "list"),
1329                     TetherInterfaceListResult);
1330         } catch (NativeDaemonConnectorException e) {
1331             throw e.rethrowAsParcelableException();
1332         }
1333     }
1334 
1335     @Override
setDnsForwarders(Network network, String[] dns)1336     public void setDnsForwarders(Network network, String[] dns) {
1337         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1338 
1339         int netId = (network != null) ? network.netId : ConnectivityManager.NETID_UNSET;
1340         final Command cmd = new Command("tether", "dns", "set", netId);
1341 
1342         for (String s : dns) {
1343             cmd.appendArg(NetworkUtils.numericToInetAddress(s).getHostAddress());
1344         }
1345 
1346         try {
1347             mConnector.execute(cmd);
1348         } catch (NativeDaemonConnectorException e) {
1349             throw e.rethrowAsParcelableException();
1350         }
1351     }
1352 
1353     @Override
getDnsForwarders()1354     public String[] getDnsForwarders() {
1355         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1356         try {
1357             return NativeDaemonEvent.filterMessageList(
1358                     mConnector.executeForList("tether", "dns", "list"), TetherDnsFwdTgtListResult);
1359         } catch (NativeDaemonConnectorException e) {
1360             throw e.rethrowAsParcelableException();
1361         }
1362     }
1363 
excludeLinkLocal(List<InterfaceAddress> addresses)1364     private List<InterfaceAddress> excludeLinkLocal(List<InterfaceAddress> addresses) {
1365         ArrayList<InterfaceAddress> filtered = new ArrayList<>(addresses.size());
1366         for (InterfaceAddress ia : addresses) {
1367             if (!ia.getAddress().isLinkLocalAddress())
1368                 filtered.add(ia);
1369         }
1370         return filtered;
1371     }
1372 
modifyInterfaceForward(boolean add, String fromIface, String toIface)1373     private void modifyInterfaceForward(boolean add, String fromIface, String toIface) {
1374         final Command cmd = new Command("ipfwd", add ? "add" : "remove", fromIface, toIface);
1375         try {
1376             mConnector.execute(cmd);
1377         } catch (NativeDaemonConnectorException e) {
1378             throw e.rethrowAsParcelableException();
1379         }
1380     }
1381 
1382     @Override
startInterfaceForwarding(String fromIface, String toIface)1383     public void startInterfaceForwarding(String fromIface, String toIface) {
1384         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1385         modifyInterfaceForward(true, fromIface, toIface);
1386     }
1387 
1388     @Override
stopInterfaceForwarding(String fromIface, String toIface)1389     public void stopInterfaceForwarding(String fromIface, String toIface) {
1390         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1391         modifyInterfaceForward(false, fromIface, toIface);
1392     }
1393 
modifyNat(String action, String internalInterface, String externalInterface)1394     private void modifyNat(String action, String internalInterface, String externalInterface)
1395             throws SocketException {
1396         final Command cmd = new Command("nat", action, internalInterface, externalInterface);
1397 
1398         final NetworkInterface internalNetworkInterface = NetworkInterface.getByName(
1399                 internalInterface);
1400         if (internalNetworkInterface == null) {
1401             cmd.appendArg("0");
1402         } else {
1403             // Don't touch link-local routes, as link-local addresses aren't routable,
1404             // kernel creates link-local routes on all interfaces automatically
1405             List<InterfaceAddress> interfaceAddresses = excludeLinkLocal(
1406                     internalNetworkInterface.getInterfaceAddresses());
1407             cmd.appendArg(interfaceAddresses.size());
1408             for (InterfaceAddress ia : interfaceAddresses) {
1409                 InetAddress addr = NetworkUtils.getNetworkPart(
1410                         ia.getAddress(), ia.getNetworkPrefixLength());
1411                 cmd.appendArg(addr.getHostAddress() + "/" + ia.getNetworkPrefixLength());
1412             }
1413         }
1414 
1415         try {
1416             mConnector.execute(cmd);
1417         } catch (NativeDaemonConnectorException e) {
1418             throw e.rethrowAsParcelableException();
1419         }
1420     }
1421 
1422     @Override
enableNat(String internalInterface, String externalInterface)1423     public void enableNat(String internalInterface, String externalInterface) {
1424         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1425         try {
1426             modifyNat("enable", internalInterface, externalInterface);
1427         } catch (SocketException e) {
1428             throw new IllegalStateException(e);
1429         }
1430     }
1431 
1432     @Override
disableNat(String internalInterface, String externalInterface)1433     public void disableNat(String internalInterface, String externalInterface) {
1434         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1435         try {
1436             modifyNat("disable", internalInterface, externalInterface);
1437         } catch (SocketException e) {
1438             throw new IllegalStateException(e);
1439         }
1440     }
1441 
1442     @Override
listTtys()1443     public String[] listTtys() {
1444         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1445         try {
1446             return NativeDaemonEvent.filterMessageList(
1447                     mConnector.executeForList("list_ttys"), TtyListResult);
1448         } catch (NativeDaemonConnectorException e) {
1449             throw e.rethrowAsParcelableException();
1450         }
1451     }
1452 
1453     @Override
attachPppd( String tty, String localAddr, String remoteAddr, String dns1Addr, String dns2Addr)1454     public void attachPppd(
1455             String tty, String localAddr, String remoteAddr, String dns1Addr, String dns2Addr) {
1456         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1457         try {
1458             mConnector.execute("pppd", "attach", tty,
1459                     NetworkUtils.numericToInetAddress(localAddr).getHostAddress(),
1460                     NetworkUtils.numericToInetAddress(remoteAddr).getHostAddress(),
1461                     NetworkUtils.numericToInetAddress(dns1Addr).getHostAddress(),
1462                     NetworkUtils.numericToInetAddress(dns2Addr).getHostAddress());
1463         } catch (NativeDaemonConnectorException e) {
1464             throw e.rethrowAsParcelableException();
1465         }
1466     }
1467 
1468     @Override
detachPppd(String tty)1469     public void detachPppd(String tty) {
1470         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1471         try {
1472             mConnector.execute("pppd", "detach", tty);
1473         } catch (NativeDaemonConnectorException e) {
1474             throw e.rethrowAsParcelableException();
1475         }
1476     }
1477 
1478     @Override
addIdleTimer(String iface, int timeout, final int type)1479     public void addIdleTimer(String iface, int timeout, final int type) {
1480         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1481 
1482         if (DBG) Slog.d(TAG, "Adding idletimer");
1483 
1484         synchronized (mIdleTimerLock) {
1485             IdleTimerParams params = mActiveIdleTimers.get(iface);
1486             if (params != null) {
1487                 // the interface already has idletimer, update network count
1488                 params.networkCount++;
1489                 return;
1490             }
1491 
1492             try {
1493                 mConnector.execute("idletimer", "add", iface, Integer.toString(timeout),
1494                         Integer.toString(type));
1495             } catch (NativeDaemonConnectorException e) {
1496                 throw e.rethrowAsParcelableException();
1497             }
1498             mActiveIdleTimers.put(iface, new IdleTimerParams(timeout, type));
1499 
1500             // Networks start up.
1501             if (ConnectivityManager.isNetworkTypeMobile(type)) {
1502                 mNetworkActive = false;
1503             }
1504             mDaemonHandler.post(new Runnable() {
1505                 @Override public void run() {
1506                     notifyInterfaceClassActivity(type,
1507                             DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH,
1508                             SystemClock.elapsedRealtimeNanos(), -1, false);
1509                 }
1510             });
1511         }
1512     }
1513 
1514     @Override
removeIdleTimer(String iface)1515     public void removeIdleTimer(String iface) {
1516         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1517 
1518         if (DBG) Slog.d(TAG, "Removing idletimer");
1519 
1520         synchronized (mIdleTimerLock) {
1521             final IdleTimerParams params = mActiveIdleTimers.get(iface);
1522             if (params == null || --(params.networkCount) > 0) {
1523                 return;
1524             }
1525 
1526             try {
1527                 mConnector.execute("idletimer", "remove", iface,
1528                         Integer.toString(params.timeout), Integer.toString(params.type));
1529             } catch (NativeDaemonConnectorException e) {
1530                 throw e.rethrowAsParcelableException();
1531             }
1532             mActiveIdleTimers.remove(iface);
1533             mDaemonHandler.post(new Runnable() {
1534                 @Override public void run() {
1535                     notifyInterfaceClassActivity(params.type,
1536                             DataConnectionRealTimeInfo.DC_POWER_STATE_LOW,
1537                             SystemClock.elapsedRealtimeNanos(), -1, false);
1538                 }
1539             });
1540         }
1541     }
1542 
1543     @Override
getNetworkStatsSummaryDev()1544     public NetworkStats getNetworkStatsSummaryDev() {
1545         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1546         try {
1547             return mStatsFactory.readNetworkStatsSummaryDev();
1548         } catch (IOException e) {
1549             throw new IllegalStateException(e);
1550         }
1551     }
1552 
1553     @Override
getNetworkStatsSummaryXt()1554     public NetworkStats getNetworkStatsSummaryXt() {
1555         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1556         try {
1557             return mStatsFactory.readNetworkStatsSummaryXt();
1558         } catch (IOException e) {
1559             throw new IllegalStateException(e);
1560         }
1561     }
1562 
1563     @Override
getNetworkStatsDetail()1564     public NetworkStats getNetworkStatsDetail() {
1565         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1566         try {
1567             return mStatsFactory.readNetworkStatsDetail(UID_ALL, null, TAG_ALL, null);
1568         } catch (IOException e) {
1569             throw new IllegalStateException(e);
1570         }
1571     }
1572 
1573     @Override
setInterfaceQuota(String iface, long quotaBytes)1574     public void setInterfaceQuota(String iface, long quotaBytes) {
1575         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1576 
1577         // silently discard when control disabled
1578         // TODO: eventually migrate to be always enabled
1579         if (!mBandwidthControlEnabled) return;
1580 
1581         synchronized (mQuotaLock) {
1582             if (mActiveQuotas.containsKey(iface)) {
1583                 throw new IllegalStateException("iface " + iface + " already has quota");
1584             }
1585 
1586             try {
1587                 // TODO: support quota shared across interfaces
1588                 mConnector.execute("bandwidth", "setiquota", iface, quotaBytes);
1589                 mActiveQuotas.put(iface, quotaBytes);
1590             } catch (NativeDaemonConnectorException e) {
1591                 throw e.rethrowAsParcelableException();
1592             }
1593 
1594             synchronized (mTetheringStatsProviders) {
1595                 for (ITetheringStatsProvider provider : mTetheringStatsProviders.keySet()) {
1596                     try {
1597                         provider.setInterfaceQuota(iface, quotaBytes);
1598                     } catch (RemoteException e) {
1599                         Log.e(TAG, "Problem setting tethering data limit on provider " +
1600                                 mTetheringStatsProviders.get(provider) + ": " + e);
1601                     }
1602                 }
1603             }
1604         }
1605     }
1606 
1607     @Override
removeInterfaceQuota(String iface)1608     public void removeInterfaceQuota(String iface) {
1609         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1610 
1611         // silently discard when control disabled
1612         // TODO: eventually migrate to be always enabled
1613         if (!mBandwidthControlEnabled) return;
1614 
1615         synchronized (mQuotaLock) {
1616             if (!mActiveQuotas.containsKey(iface)) {
1617                 // TODO: eventually consider throwing
1618                 return;
1619             }
1620 
1621             mActiveQuotas.remove(iface);
1622             mActiveAlerts.remove(iface);
1623 
1624             try {
1625                 // TODO: support quota shared across interfaces
1626                 mConnector.execute("bandwidth", "removeiquota", iface);
1627             } catch (NativeDaemonConnectorException e) {
1628                 throw e.rethrowAsParcelableException();
1629             }
1630 
1631             synchronized (mTetheringStatsProviders) {
1632                 for (ITetheringStatsProvider provider : mTetheringStatsProviders.keySet()) {
1633                     try {
1634                         provider.setInterfaceQuota(iface, ITetheringStatsProvider.QUOTA_UNLIMITED);
1635                     } catch (RemoteException e) {
1636                         Log.e(TAG, "Problem removing tethering data limit on provider " +
1637                                 mTetheringStatsProviders.get(provider) + ": " + e);
1638                     }
1639                 }
1640             }
1641         }
1642     }
1643 
1644     @Override
setInterfaceAlert(String iface, long alertBytes)1645     public void setInterfaceAlert(String iface, long alertBytes) {
1646         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1647 
1648         // silently discard when control disabled
1649         // TODO: eventually migrate to be always enabled
1650         if (!mBandwidthControlEnabled) return;
1651 
1652         // quick sanity check
1653         if (!mActiveQuotas.containsKey(iface)) {
1654             throw new IllegalStateException("setting alert requires existing quota on iface");
1655         }
1656 
1657         synchronized (mQuotaLock) {
1658             if (mActiveAlerts.containsKey(iface)) {
1659                 throw new IllegalStateException("iface " + iface + " already has alert");
1660             }
1661 
1662             try {
1663                 // TODO: support alert shared across interfaces
1664                 mConnector.execute("bandwidth", "setinterfacealert", iface, alertBytes);
1665                 mActiveAlerts.put(iface, alertBytes);
1666             } catch (NativeDaemonConnectorException e) {
1667                 throw e.rethrowAsParcelableException();
1668             }
1669         }
1670     }
1671 
1672     @Override
removeInterfaceAlert(String iface)1673     public void removeInterfaceAlert(String iface) {
1674         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1675 
1676         // silently discard when control disabled
1677         // TODO: eventually migrate to be always enabled
1678         if (!mBandwidthControlEnabled) return;
1679 
1680         synchronized (mQuotaLock) {
1681             if (!mActiveAlerts.containsKey(iface)) {
1682                 // TODO: eventually consider throwing
1683                 return;
1684             }
1685 
1686             try {
1687                 // TODO: support alert shared across interfaces
1688                 mConnector.execute("bandwidth", "removeinterfacealert", iface);
1689                 mActiveAlerts.remove(iface);
1690             } catch (NativeDaemonConnectorException e) {
1691                 throw e.rethrowAsParcelableException();
1692             }
1693         }
1694     }
1695 
1696     @Override
setGlobalAlert(long alertBytes)1697     public void setGlobalAlert(long alertBytes) {
1698         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1699 
1700         // silently discard when control disabled
1701         // TODO: eventually migrate to be always enabled
1702         if (!mBandwidthControlEnabled) return;
1703 
1704         try {
1705             mConnector.execute("bandwidth", "setglobalalert", alertBytes);
1706         } catch (NativeDaemonConnectorException e) {
1707             throw e.rethrowAsParcelableException();
1708         }
1709     }
1710 
setUidOnMeteredNetworkList(int uid, boolean blacklist, boolean enable)1711     private void setUidOnMeteredNetworkList(int uid, boolean blacklist, boolean enable) {
1712         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1713 
1714         // silently discard when control disabled
1715         // TODO: eventually migrate to be always enabled
1716         if (!mBandwidthControlEnabled) return;
1717 
1718         final String chain = blacklist ? "naughtyapps" : "niceapps";
1719         final String suffix = enable ? "add" : "remove";
1720 
1721         synchronized (mQuotaLock) {
1722             boolean oldEnable;
1723             SparseBooleanArray quotaList;
1724             synchronized (mRulesLock) {
1725                 quotaList = blacklist ? mUidRejectOnMetered : mUidAllowOnMetered;
1726                 oldEnable = quotaList.get(uid, false);
1727             }
1728             if (oldEnable == enable) {
1729                 // TODO: eventually consider throwing
1730                 return;
1731             }
1732 
1733             Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "inetd bandwidth");
1734             try {
1735                 mConnector.execute("bandwidth", suffix + chain, uid);
1736                 synchronized (mRulesLock) {
1737                     if (enable) {
1738                         quotaList.put(uid, true);
1739                     } else {
1740                         quotaList.delete(uid);
1741                     }
1742                 }
1743             } catch (NativeDaemonConnectorException e) {
1744                 throw e.rethrowAsParcelableException();
1745             } finally {
1746                 Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
1747             }
1748         }
1749     }
1750 
1751     @Override
setUidMeteredNetworkBlacklist(int uid, boolean enable)1752     public void setUidMeteredNetworkBlacklist(int uid, boolean enable) {
1753         setUidOnMeteredNetworkList(uid, true, enable);
1754     }
1755 
1756     @Override
setUidMeteredNetworkWhitelist(int uid, boolean enable)1757     public void setUidMeteredNetworkWhitelist(int uid, boolean enable) {
1758         setUidOnMeteredNetworkList(uid, false, enable);
1759     }
1760 
1761     @Override
setDataSaverModeEnabled(boolean enable)1762     public boolean setDataSaverModeEnabled(boolean enable) {
1763         mContext.enforceCallingOrSelfPermission(NETWORK_SETTINGS, TAG);
1764 
1765         if (DBG) Log.d(TAG, "setDataSaverMode: " + enable);
1766         synchronized (mQuotaLock) {
1767             if (mDataSaverMode == enable) {
1768                 Log.w(TAG, "setDataSaverMode(): already " + mDataSaverMode);
1769                 return true;
1770             }
1771             Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "bandwidthEnableDataSaver");
1772             try {
1773                 final boolean changed = mNetdService.bandwidthEnableDataSaver(enable);
1774                 if (changed) {
1775                     mDataSaverMode = enable;
1776                 } else {
1777                     Log.w(TAG, "setDataSaverMode(" + enable + "): netd command silently failed");
1778                 }
1779                 return changed;
1780             } catch (RemoteException e) {
1781                 Log.w(TAG, "setDataSaverMode(" + enable + "): netd command failed", e);
1782                 return false;
1783             } finally {
1784                 Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
1785             }
1786         }
1787     }
1788 
1789     @Override
setAllowOnlyVpnForUids(boolean add, UidRange[] uidRanges)1790     public void setAllowOnlyVpnForUids(boolean add, UidRange[] uidRanges)
1791             throws ServiceSpecificException {
1792         mContext.enforceCallingOrSelfPermission(NETWORK_STACK, TAG);
1793 
1794         try {
1795             mNetdService.networkRejectNonSecureVpn(add, uidRanges);
1796         } catch (ServiceSpecificException e) {
1797             Log.w(TAG, "setAllowOnlyVpnForUids(" + add + ", " + Arrays.toString(uidRanges) + ")"
1798                     + ": netd command failed", e);
1799             throw e;
1800         } catch (RemoteException e) {
1801             Log.w(TAG, "setAllowOnlyVpnForUids(" + add + ", " + Arrays.toString(uidRanges) + ")"
1802                     + ": netd command failed", e);
1803             throw e.rethrowAsRuntimeException();
1804         }
1805     }
1806 
applyUidCleartextNetworkPolicy(int uid, int policy)1807     private void applyUidCleartextNetworkPolicy(int uid, int policy) {
1808         final String policyString;
1809         switch (policy) {
1810             case StrictMode.NETWORK_POLICY_ACCEPT:
1811                 policyString = "accept";
1812                 break;
1813             case StrictMode.NETWORK_POLICY_LOG:
1814                 policyString = "log";
1815                 break;
1816             case StrictMode.NETWORK_POLICY_REJECT:
1817                 policyString = "reject";
1818                 break;
1819             default:
1820                 throw new IllegalArgumentException("Unknown policy " + policy);
1821         }
1822 
1823         try {
1824             mConnector.execute("strict", "set_uid_cleartext_policy", uid, policyString);
1825             mUidCleartextPolicy.put(uid, policy);
1826         } catch (NativeDaemonConnectorException e) {
1827             throw e.rethrowAsParcelableException();
1828         }
1829     }
1830 
1831     @Override
setUidCleartextNetworkPolicy(int uid, int policy)1832     public void setUidCleartextNetworkPolicy(int uid, int policy) {
1833         if (Binder.getCallingUid() != uid) {
1834             mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1835         }
1836 
1837         synchronized (mQuotaLock) {
1838             final int oldPolicy = mUidCleartextPolicy.get(uid, StrictMode.NETWORK_POLICY_ACCEPT);
1839             if (oldPolicy == policy) {
1840                 // This also ensures we won't needlessly apply an ACCEPT policy if we've just
1841                 // enabled strict and the underlying iptables rules are empty.
1842                 return;
1843             }
1844 
1845             if (!mStrictEnabled) {
1846                 // Module isn't enabled yet; stash the requested policy away to
1847                 // apply later once the daemon is connected.
1848                 mUidCleartextPolicy.put(uid, policy);
1849                 return;
1850             }
1851 
1852             // netd does not keep state on strict mode policies, and cannot replace a non-accept
1853             // policy without deleting it first. Rather than add state to netd, just always send
1854             // it an accept policy when switching between two non-accept policies.
1855             // TODO: consider keeping state in netd so we can simplify this code.
1856             if (oldPolicy != StrictMode.NETWORK_POLICY_ACCEPT &&
1857                     policy != StrictMode.NETWORK_POLICY_ACCEPT) {
1858                 applyUidCleartextNetworkPolicy(uid, StrictMode.NETWORK_POLICY_ACCEPT);
1859             }
1860 
1861             applyUidCleartextNetworkPolicy(uid, policy);
1862         }
1863     }
1864 
1865     @Override
isBandwidthControlEnabled()1866     public boolean isBandwidthControlEnabled() {
1867         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1868         return mBandwidthControlEnabled;
1869     }
1870 
1871     @Override
getNetworkStatsUidDetail(int uid, String[] ifaces)1872     public NetworkStats getNetworkStatsUidDetail(int uid, String[] ifaces) {
1873         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1874         try {
1875             return mStatsFactory.readNetworkStatsDetail(uid, ifaces, TAG_ALL, null);
1876         } catch (IOException e) {
1877             throw new IllegalStateException(e);
1878         }
1879     }
1880 
1881     private class NetdTetheringStatsProvider extends ITetheringStatsProvider.Stub {
1882         @Override
getTetherStats(int how)1883         public NetworkStats getTetherStats(int how) {
1884             // We only need to return per-UID stats. Per-device stats are already counted by
1885             // interface counters.
1886             if (how != STATS_PER_UID) {
1887                 return new NetworkStats(SystemClock.elapsedRealtime(), 0);
1888             }
1889 
1890             final PersistableBundle bundle;
1891             try {
1892                 bundle = mNetdService.tetherGetStats();
1893             } catch (RemoteException | ServiceSpecificException e) {
1894                 throw new IllegalStateException("problem parsing tethering stats: ", e);
1895             }
1896 
1897             final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(),
1898                     bundle.size());
1899             final NetworkStats.Entry entry = new NetworkStats.Entry();
1900 
1901             for (String iface : bundle.keySet()) {
1902                 long[] statsArray = bundle.getLongArray(iface);
1903                 try {
1904                     entry.iface = iface;
1905                     entry.uid = UID_TETHERING;
1906                     entry.set = SET_DEFAULT;
1907                     entry.tag = TAG_NONE;
1908                     entry.rxBytes   = statsArray[INetd.TETHER_STATS_RX_BYTES];
1909                     entry.rxPackets = statsArray[INetd.TETHER_STATS_RX_PACKETS];
1910                     entry.txBytes   = statsArray[INetd.TETHER_STATS_TX_BYTES];
1911                     entry.txPackets = statsArray[INetd.TETHER_STATS_TX_PACKETS];
1912                     stats.combineValues(entry);
1913                 } catch (ArrayIndexOutOfBoundsException e) {
1914                     throw new IllegalStateException("invalid tethering stats for " + iface, e);
1915                 }
1916             }
1917 
1918             return stats;
1919         }
1920 
1921         @Override
setInterfaceQuota(String iface, long quotaBytes)1922         public void setInterfaceQuota(String iface, long quotaBytes) {
1923             // Do nothing. netd is already informed of quota changes in setInterfaceQuota.
1924         }
1925     }
1926 
1927     @Override
getNetworkStatsTethering(int how)1928     public NetworkStats getNetworkStatsTethering(int how) {
1929         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1930 
1931         final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 1);
1932         synchronized (mTetheringStatsProviders) {
1933             for (ITetheringStatsProvider provider: mTetheringStatsProviders.keySet()) {
1934                 try {
1935                     stats.combineAllValues(provider.getTetherStats(how));
1936                 } catch (RemoteException e) {
1937                     Log.e(TAG, "Problem reading tethering stats from " +
1938                             mTetheringStatsProviders.get(provider) + ": " + e);
1939                 }
1940             }
1941         }
1942         return stats;
1943     }
1944 
1945     @Override
setDnsConfigurationForNetwork(int netId, String[] servers, String[] domains, int[] params, String tlsHostname, String[] tlsServers)1946     public void setDnsConfigurationForNetwork(int netId, String[] servers, String[] domains,
1947                     int[] params, String tlsHostname, String[] tlsServers) {
1948         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1949 
1950         final String[] tlsFingerprints = new String[0];
1951         try {
1952             mNetdService.setResolverConfiguration(
1953                     netId, servers, domains, params, tlsHostname, tlsServers, tlsFingerprints);
1954         } catch (RemoteException e) {
1955             throw new RuntimeException(e);
1956         }
1957     }
1958 
1959     @Override
addVpnUidRanges(int netId, UidRange[] ranges)1960     public void addVpnUidRanges(int netId, UidRange[] ranges) {
1961         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1962         Object[] argv = new Object[3 + MAX_UID_RANGES_PER_COMMAND];
1963         argv[0] = "users";
1964         argv[1] = "add";
1965         argv[2] = netId;
1966         int argc = 3;
1967         // Avoid overly long commands by limiting number of UID ranges per command.
1968         for (int i = 0; i < ranges.length; i++) {
1969             argv[argc++] = ranges[i].toString();
1970             if (i == (ranges.length - 1) || argc == argv.length) {
1971                 try {
1972                     mConnector.execute("network", Arrays.copyOf(argv, argc));
1973                 } catch (NativeDaemonConnectorException e) {
1974                     throw e.rethrowAsParcelableException();
1975                 }
1976                 argc = 3;
1977             }
1978         }
1979     }
1980 
1981     @Override
removeVpnUidRanges(int netId, UidRange[] ranges)1982     public void removeVpnUidRanges(int netId, UidRange[] ranges) {
1983         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1984         Object[] argv = new Object[3 + MAX_UID_RANGES_PER_COMMAND];
1985         argv[0] = "users";
1986         argv[1] = "remove";
1987         argv[2] = netId;
1988         int argc = 3;
1989         // Avoid overly long commands by limiting number of UID ranges per command.
1990         for (int i = 0; i < ranges.length; i++) {
1991             argv[argc++] = ranges[i].toString();
1992             if (i == (ranges.length - 1) || argc == argv.length) {
1993                 try {
1994                     mConnector.execute("network", Arrays.copyOf(argv, argc));
1995                 } catch (NativeDaemonConnectorException e) {
1996                     throw e.rethrowAsParcelableException();
1997                 }
1998                 argc = 3;
1999             }
2000         }
2001     }
2002 
2003     @Override
setFirewallEnabled(boolean enabled)2004     public void setFirewallEnabled(boolean enabled) {
2005         enforceSystemUid();
2006         try {
2007             mConnector.execute("firewall", "enable", enabled ? "whitelist" : "blacklist");
2008             mFirewallEnabled = enabled;
2009         } catch (NativeDaemonConnectorException e) {
2010             throw e.rethrowAsParcelableException();
2011         }
2012     }
2013 
2014     @Override
isFirewallEnabled()2015     public boolean isFirewallEnabled() {
2016         enforceSystemUid();
2017         return mFirewallEnabled;
2018     }
2019 
2020     @Override
setFirewallInterfaceRule(String iface, boolean allow)2021     public void setFirewallInterfaceRule(String iface, boolean allow) {
2022         enforceSystemUid();
2023         Preconditions.checkState(mFirewallEnabled);
2024         final String rule = allow ? "allow" : "deny";
2025         try {
2026             mConnector.execute("firewall", "set_interface_rule", iface, rule);
2027         } catch (NativeDaemonConnectorException e) {
2028             throw e.rethrowAsParcelableException();
2029         }
2030     }
2031 
closeSocketsForFirewallChainLocked(int chain, String chainName)2032     private void closeSocketsForFirewallChainLocked(int chain, String chainName) {
2033         // UID ranges to close sockets on.
2034         UidRange[] ranges;
2035         // UID ranges whose sockets we won't touch.
2036         int[] exemptUids;
2037 
2038         int numUids = 0;
2039 
2040         if (getFirewallType(chain) == FIREWALL_TYPE_WHITELIST) {
2041             // Close all sockets on all non-system UIDs...
2042             ranges = new UidRange[] {
2043                 // TODO: is there a better way of finding all existing users? If so, we could
2044                 // specify their ranges here.
2045                 new UidRange(Process.FIRST_APPLICATION_UID, Integer.MAX_VALUE),
2046             };
2047             // ... except for the UIDs that have allow rules.
2048             synchronized (mRulesLock) {
2049                 final SparseIntArray rules = getUidFirewallRulesLR(chain);
2050                 exemptUids = new int[rules.size()];
2051                 for (int i = 0; i < exemptUids.length; i++) {
2052                     if (rules.valueAt(i) == NetworkPolicyManager.FIREWALL_RULE_ALLOW) {
2053                         exemptUids[numUids] = rules.keyAt(i);
2054                         numUids++;
2055                     }
2056                 }
2057             }
2058             // Normally, whitelist chains only contain deny rules, so numUids == exemptUids.length.
2059             // But the code does not guarantee this in any way, and at least in one case - if we add
2060             // a UID rule to the firewall, and then disable the firewall - the chains can contain
2061             // the wrong type of rule. In this case, don't close connections that we shouldn't.
2062             //
2063             // TODO: tighten up this code by ensuring we never set the wrong type of rule, and
2064             // fix setFirewallEnabled to grab mQuotaLock and clear rules.
2065             if (numUids != exemptUids.length) {
2066                 exemptUids = Arrays.copyOf(exemptUids, numUids);
2067             }
2068         } else {
2069             // Close sockets for every UID that has a deny rule...
2070             synchronized (mRulesLock) {
2071                 final SparseIntArray rules = getUidFirewallRulesLR(chain);
2072                 ranges = new UidRange[rules.size()];
2073                 for (int i = 0; i < ranges.length; i++) {
2074                     if (rules.valueAt(i) == NetworkPolicyManager.FIREWALL_RULE_DENY) {
2075                         int uid = rules.keyAt(i);
2076                         ranges[numUids] = new UidRange(uid, uid);
2077                         numUids++;
2078                     }
2079                 }
2080             }
2081             // As above; usually numUids == ranges.length, but not always.
2082             if (numUids != ranges.length) {
2083                 ranges = Arrays.copyOf(ranges, numUids);
2084             }
2085             // ... with no exceptions.
2086             exemptUids = new int[0];
2087         }
2088 
2089         try {
2090             mNetdService.socketDestroy(ranges, exemptUids);
2091         } catch(RemoteException | ServiceSpecificException e) {
2092             Slog.e(TAG, "Error closing sockets after enabling chain " + chainName + ": " + e);
2093         }
2094     }
2095 
2096     @Override
setFirewallChainEnabled(int chain, boolean enable)2097     public void setFirewallChainEnabled(int chain, boolean enable) {
2098         enforceSystemUid();
2099         synchronized (mQuotaLock) {
2100             synchronized (mRulesLock) {
2101                 if (getFirewallChainState(chain) == enable) {
2102                     // All is the same, nothing to do.  This relies on the fact that netd has child
2103                     // chains default detached.
2104                     return;
2105                 }
2106                 setFirewallChainState(chain, enable);
2107             }
2108 
2109             final String operation = enable ? "enable_chain" : "disable_chain";
2110             final String chainName;
2111             switch(chain) {
2112                 case FIREWALL_CHAIN_STANDBY:
2113                     chainName = FIREWALL_CHAIN_NAME_STANDBY;
2114                     break;
2115                 case FIREWALL_CHAIN_DOZABLE:
2116                     chainName = FIREWALL_CHAIN_NAME_DOZABLE;
2117                     break;
2118                 case FIREWALL_CHAIN_POWERSAVE:
2119                     chainName = FIREWALL_CHAIN_NAME_POWERSAVE;
2120                     break;
2121                 default:
2122                     throw new IllegalArgumentException("Bad child chain: " + chain);
2123             }
2124 
2125             try {
2126                 mConnector.execute("firewall", operation, chainName);
2127             } catch (NativeDaemonConnectorException e) {
2128                 throw e.rethrowAsParcelableException();
2129             }
2130 
2131             // Close any sockets that were opened by the affected UIDs. This has to be done after
2132             // disabling network connectivity, in case they react to the socket close by reopening
2133             // the connection and race with the iptables commands that enable the firewall. All
2134             // whitelist and blacklist chains allow RSTs through.
2135             if (enable) {
2136                 if (DBG) Slog.d(TAG, "Closing sockets after enabling chain " + chainName);
2137                 closeSocketsForFirewallChainLocked(chain, chainName);
2138             }
2139         }
2140     }
2141 
getFirewallType(int chain)2142     private int getFirewallType(int chain) {
2143         switch (chain) {
2144             case FIREWALL_CHAIN_STANDBY:
2145                 return FIREWALL_TYPE_BLACKLIST;
2146             case FIREWALL_CHAIN_DOZABLE:
2147                 return FIREWALL_TYPE_WHITELIST;
2148             case FIREWALL_CHAIN_POWERSAVE:
2149                 return FIREWALL_TYPE_WHITELIST;
2150             default:
2151                 return isFirewallEnabled() ? FIREWALL_TYPE_WHITELIST : FIREWALL_TYPE_BLACKLIST;
2152         }
2153     }
2154 
2155     @Override
setFirewallUidRules(int chain, int[] uids, int[] rules)2156     public void setFirewallUidRules(int chain, int[] uids, int[] rules) {
2157         enforceSystemUid();
2158         synchronized (mQuotaLock) {
2159             synchronized (mRulesLock) {
2160                 SparseIntArray uidFirewallRules = getUidFirewallRulesLR(chain);
2161                 SparseIntArray newRules = new SparseIntArray();
2162                 // apply new set of rules
2163                 for (int index = uids.length - 1; index >= 0; --index) {
2164                     int uid = uids[index];
2165                     int rule = rules[index];
2166                     updateFirewallUidRuleLocked(chain, uid, rule);
2167                     newRules.put(uid, rule);
2168                 }
2169                 // collect the rules to remove.
2170                 SparseIntArray rulesToRemove = new SparseIntArray();
2171                 for (int index = uidFirewallRules.size() - 1; index >= 0; --index) {
2172                     int uid = uidFirewallRules.keyAt(index);
2173                     if (newRules.indexOfKey(uid) < 0) {
2174                         rulesToRemove.put(uid, FIREWALL_RULE_DEFAULT);
2175                     }
2176                 }
2177                 // remove dead rules
2178                 for (int index = rulesToRemove.size() - 1; index >= 0; --index) {
2179                     int uid = rulesToRemove.keyAt(index);
2180                     updateFirewallUidRuleLocked(chain, uid, FIREWALL_RULE_DEFAULT);
2181                 }
2182             }
2183             try {
2184                 switch (chain) {
2185                     case FIREWALL_CHAIN_DOZABLE:
2186                         mNetdService.firewallReplaceUidChain("fw_dozable", true, uids);
2187                         break;
2188                     case FIREWALL_CHAIN_STANDBY:
2189                         mNetdService.firewallReplaceUidChain("fw_standby", false, uids);
2190                         break;
2191                     case FIREWALL_CHAIN_POWERSAVE:
2192                         mNetdService.firewallReplaceUidChain("fw_powersave", true, uids);
2193                         break;
2194                     case FIREWALL_CHAIN_NONE:
2195                     default:
2196                         Slog.d(TAG, "setFirewallUidRules() called on invalid chain: " + chain);
2197                 }
2198             } catch (RemoteException e) {
2199                 Slog.w(TAG, "Error flushing firewall chain " + chain, e);
2200             }
2201         }
2202     }
2203 
2204     @Override
setFirewallUidRule(int chain, int uid, int rule)2205     public void setFirewallUidRule(int chain, int uid, int rule) {
2206         enforceSystemUid();
2207         synchronized (mQuotaLock) {
2208             setFirewallUidRuleLocked(chain, uid, rule);
2209         }
2210     }
2211 
setFirewallUidRuleLocked(int chain, int uid, int rule)2212     private void setFirewallUidRuleLocked(int chain, int uid, int rule) {
2213         if (updateFirewallUidRuleLocked(chain, uid, rule)) {
2214             try {
2215                 mConnector.execute("firewall", "set_uid_rule", getFirewallChainName(chain), uid,
2216                         getFirewallRuleName(chain, rule));
2217             } catch (NativeDaemonConnectorException e) {
2218                 throw e.rethrowAsParcelableException();
2219             }
2220         }
2221     }
2222 
2223     // TODO: now that netd supports batching, NMS should not keep these data structures anymore...
updateFirewallUidRuleLocked(int chain, int uid, int rule)2224     private boolean updateFirewallUidRuleLocked(int chain, int uid, int rule) {
2225         synchronized (mRulesLock) {
2226             SparseIntArray uidFirewallRules = getUidFirewallRulesLR(chain);
2227 
2228             final int oldUidFirewallRule = uidFirewallRules.get(uid, FIREWALL_RULE_DEFAULT);
2229             if (DBG) {
2230                 Slog.d(TAG, "oldRule = " + oldUidFirewallRule
2231                         + ", newRule=" + rule + " for uid=" + uid + " on chain " + chain);
2232             }
2233             if (oldUidFirewallRule == rule) {
2234                 if (DBG) Slog.d(TAG, "!!!!! Skipping change");
2235                 // TODO: eventually consider throwing
2236                 return false;
2237             }
2238 
2239             String ruleName = getFirewallRuleName(chain, rule);
2240             String oldRuleName = getFirewallRuleName(chain, oldUidFirewallRule);
2241 
2242             if (rule == NetworkPolicyManager.FIREWALL_RULE_DEFAULT) {
2243                 uidFirewallRules.delete(uid);
2244             } else {
2245                 uidFirewallRules.put(uid, rule);
2246             }
2247             return !ruleName.equals(oldRuleName);
2248         }
2249     }
2250 
getFirewallRuleName(int chain, int rule)2251     private @NonNull String getFirewallRuleName(int chain, int rule) {
2252         String ruleName;
2253         if (getFirewallType(chain) == FIREWALL_TYPE_WHITELIST) {
2254             if (rule == NetworkPolicyManager.FIREWALL_RULE_ALLOW) {
2255                 ruleName = "allow";
2256             } else {
2257                 ruleName = "deny";
2258             }
2259         } else { // Blacklist mode
2260             if (rule == NetworkPolicyManager.FIREWALL_RULE_DENY) {
2261                 ruleName = "deny";
2262             } else {
2263                 ruleName = "allow";
2264             }
2265         }
2266         return ruleName;
2267     }
2268 
getUidFirewallRulesLR(int chain)2269     private @NonNull SparseIntArray getUidFirewallRulesLR(int chain) {
2270         switch (chain) {
2271             case FIREWALL_CHAIN_STANDBY:
2272                 return mUidFirewallStandbyRules;
2273             case FIREWALL_CHAIN_DOZABLE:
2274                 return mUidFirewallDozableRules;
2275             case FIREWALL_CHAIN_POWERSAVE:
2276                 return mUidFirewallPowerSaveRules;
2277             case FIREWALL_CHAIN_NONE:
2278                 return mUidFirewallRules;
2279             default:
2280                 throw new IllegalArgumentException("Unknown chain:" + chain);
2281         }
2282     }
2283 
getFirewallChainName(int chain)2284     public @NonNull String getFirewallChainName(int chain) {
2285         switch (chain) {
2286             case FIREWALL_CHAIN_STANDBY:
2287                 return FIREWALL_CHAIN_NAME_STANDBY;
2288             case FIREWALL_CHAIN_DOZABLE:
2289                 return FIREWALL_CHAIN_NAME_DOZABLE;
2290             case FIREWALL_CHAIN_POWERSAVE:
2291                 return FIREWALL_CHAIN_NAME_POWERSAVE;
2292             case FIREWALL_CHAIN_NONE:
2293                 return FIREWALL_CHAIN_NAME_NONE;
2294             default:
2295                 throw new IllegalArgumentException("Unknown chain:" + chain);
2296         }
2297     }
2298 
enforceSystemUid()2299     private static void enforceSystemUid() {
2300         final int uid = Binder.getCallingUid();
2301         if (uid != Process.SYSTEM_UID) {
2302             throw new SecurityException("Only available to AID_SYSTEM");
2303         }
2304     }
2305 
2306     @Override
startClatd(String interfaceName)2307     public void startClatd(String interfaceName) throws IllegalStateException {
2308         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2309 
2310         try {
2311             mConnector.execute("clatd", "start", interfaceName);
2312         } catch (NativeDaemonConnectorException e) {
2313             throw e.rethrowAsParcelableException();
2314         }
2315     }
2316 
2317     @Override
stopClatd(String interfaceName)2318     public void stopClatd(String interfaceName) throws IllegalStateException {
2319         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2320 
2321         try {
2322             mConnector.execute("clatd", "stop", interfaceName);
2323         } catch (NativeDaemonConnectorException e) {
2324             throw e.rethrowAsParcelableException();
2325         }
2326     }
2327 
2328     @Override
isClatdStarted(String interfaceName)2329     public boolean isClatdStarted(String interfaceName) {
2330         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2331 
2332         final NativeDaemonEvent event;
2333         try {
2334             event = mConnector.execute("clatd", "status", interfaceName);
2335         } catch (NativeDaemonConnectorException e) {
2336             throw e.rethrowAsParcelableException();
2337         }
2338 
2339         event.checkCode(ClatdStatusResult);
2340         return event.getMessage().endsWith("started");
2341     }
2342 
2343     @Override
registerNetworkActivityListener(INetworkActivityListener listener)2344     public void registerNetworkActivityListener(INetworkActivityListener listener) {
2345         mNetworkActivityListeners.register(listener);
2346     }
2347 
2348     @Override
unregisterNetworkActivityListener(INetworkActivityListener listener)2349     public void unregisterNetworkActivityListener(INetworkActivityListener listener) {
2350         mNetworkActivityListeners.unregister(listener);
2351     }
2352 
2353     @Override
isNetworkActive()2354     public boolean isNetworkActive() {
2355         synchronized (mNetworkActivityListeners) {
2356             return mNetworkActive || mActiveIdleTimers.isEmpty();
2357         }
2358     }
2359 
reportNetworkActive()2360     private void reportNetworkActive() {
2361         final int length = mNetworkActivityListeners.beginBroadcast();
2362         try {
2363             for (int i = 0; i < length; i++) {
2364                 try {
2365                     mNetworkActivityListeners.getBroadcastItem(i).onNetworkActive();
2366                 } catch (RemoteException | RuntimeException e) {
2367                 }
2368             }
2369         } finally {
2370             mNetworkActivityListeners.finishBroadcast();
2371         }
2372     }
2373 
2374     /** {@inheritDoc} */
2375     @Override
monitor()2376     public void monitor() {
2377         if (mConnector != null) {
2378             mConnector.monitor();
2379         }
2380     }
2381 
2382     @Override
dump(FileDescriptor fd, PrintWriter pw, String[] args)2383     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
2384         if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
2385 
2386         pw.println("NetworkManagementService NativeDaemonConnector Log:");
2387         mConnector.dump(fd, pw, args);
2388         pw.println();
2389 
2390         pw.print("Bandwidth control enabled: "); pw.println(mBandwidthControlEnabled);
2391         pw.print("mMobileActivityFromRadio="); pw.print(mMobileActivityFromRadio);
2392                 pw.print(" mLastPowerStateFromRadio="); pw.println(mLastPowerStateFromRadio);
2393         pw.print("mNetworkActive="); pw.println(mNetworkActive);
2394 
2395         synchronized (mQuotaLock) {
2396             pw.print("Active quota ifaces: "); pw.println(mActiveQuotas.toString());
2397             pw.print("Active alert ifaces: "); pw.println(mActiveAlerts.toString());
2398             pw.print("Data saver mode: "); pw.println(mDataSaverMode);
2399             synchronized (mRulesLock) {
2400                 dumpUidRuleOnQuotaLocked(pw, "blacklist", mUidRejectOnMetered);
2401                 dumpUidRuleOnQuotaLocked(pw, "whitelist", mUidAllowOnMetered);
2402             }
2403         }
2404 
2405         synchronized (mRulesLock) {
2406             dumpUidFirewallRule(pw, "", mUidFirewallRules);
2407 
2408             pw.print("UID firewall standby chain enabled: "); pw.println(
2409                     getFirewallChainState(FIREWALL_CHAIN_STANDBY));
2410             dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_STANDBY, mUidFirewallStandbyRules);
2411 
2412             pw.print("UID firewall dozable chain enabled: "); pw.println(
2413                     getFirewallChainState(FIREWALL_CHAIN_DOZABLE));
2414             dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_DOZABLE, mUidFirewallDozableRules);
2415 
2416             pw.println("UID firewall powersave chain enabled: " +
2417                     getFirewallChainState(FIREWALL_CHAIN_POWERSAVE));
2418             dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_POWERSAVE, mUidFirewallPowerSaveRules);
2419         }
2420 
2421         synchronized (mIdleTimerLock) {
2422             pw.println("Idle timers:");
2423             for (HashMap.Entry<String, IdleTimerParams> ent : mActiveIdleTimers.entrySet()) {
2424                 pw.print("  "); pw.print(ent.getKey()); pw.println(":");
2425                 IdleTimerParams params = ent.getValue();
2426                 pw.print("    timeout="); pw.print(params.timeout);
2427                 pw.print(" type="); pw.print(params.type);
2428                 pw.print(" networkCount="); pw.println(params.networkCount);
2429             }
2430         }
2431 
2432         pw.print("Firewall enabled: "); pw.println(mFirewallEnabled);
2433         pw.print("Netd service status: " );
2434         if (mNetdService == null) {
2435             pw.println("disconnected");
2436         } else {
2437             try {
2438                 final boolean alive = mNetdService.isAlive();
2439                 pw.println(alive ? "alive": "dead");
2440             } catch (RemoteException e) {
2441                 pw.println("unreachable");
2442             }
2443         }
2444     }
2445 
dumpUidRuleOnQuotaLocked(PrintWriter pw, String name, SparseBooleanArray list)2446     private void dumpUidRuleOnQuotaLocked(PrintWriter pw, String name, SparseBooleanArray list) {
2447         pw.print("UID bandwith control ");
2448         pw.print(name);
2449         pw.print(" rule: [");
2450         final int size = list.size();
2451         for (int i = 0; i < size; i++) {
2452             pw.print(list.keyAt(i));
2453             if (i < size - 1) pw.print(",");
2454         }
2455         pw.println("]");
2456     }
2457 
dumpUidFirewallRule(PrintWriter pw, String name, SparseIntArray rules)2458     private void dumpUidFirewallRule(PrintWriter pw, String name, SparseIntArray rules) {
2459         pw.print("UID firewall ");
2460         pw.print(name);
2461         pw.print(" rule: [");
2462         final int size = rules.size();
2463         for (int i = 0; i < size; i++) {
2464             pw.print(rules.keyAt(i));
2465             pw.print(":");
2466             pw.print(rules.valueAt(i));
2467             if (i < size - 1) pw.print(",");
2468         }
2469         pw.println("]");
2470     }
2471 
2472     @Override
createPhysicalNetwork(int netId, String permission)2473     public void createPhysicalNetwork(int netId, String permission) {
2474         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2475 
2476         try {
2477             if (permission != null) {
2478                 mConnector.execute("network", "create", netId, permission);
2479             } else {
2480                 mConnector.execute("network", "create", netId);
2481             }
2482         } catch (NativeDaemonConnectorException e) {
2483             throw e.rethrowAsParcelableException();
2484         }
2485     }
2486 
2487     @Override
createVirtualNetwork(int netId, boolean hasDNS, boolean secure)2488     public void createVirtualNetwork(int netId, boolean hasDNS, boolean secure) {
2489         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2490 
2491         try {
2492             mConnector.execute("network", "create", netId, "vpn", hasDNS ? "1" : "0",
2493                     secure ? "1" : "0");
2494         } catch (NativeDaemonConnectorException e) {
2495             throw e.rethrowAsParcelableException();
2496         }
2497     }
2498 
2499     @Override
removeNetwork(int netId)2500     public void removeNetwork(int netId) {
2501         mContext.enforceCallingOrSelfPermission(NETWORK_STACK, TAG);
2502 
2503         try {
2504             mNetdService.networkDestroy(netId);
2505         } catch (ServiceSpecificException e) {
2506             Log.w(TAG, "removeNetwork(" + netId + "): ", e);
2507             throw e;
2508         } catch (RemoteException e) {
2509             Log.w(TAG, "removeNetwork(" + netId + "): ", e);
2510             throw e.rethrowAsRuntimeException();
2511         }
2512     }
2513 
2514     @Override
addInterfaceToNetwork(String iface, int netId)2515     public void addInterfaceToNetwork(String iface, int netId) {
2516         modifyInterfaceInNetwork("add", "" + netId, iface);
2517     }
2518 
2519     @Override
removeInterfaceFromNetwork(String iface, int netId)2520     public void removeInterfaceFromNetwork(String iface, int netId) {
2521         modifyInterfaceInNetwork("remove", "" + netId, iface);
2522     }
2523 
modifyInterfaceInNetwork(String action, String netId, String iface)2524     private void modifyInterfaceInNetwork(String action, String netId, String iface) {
2525         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2526         try {
2527             mConnector.execute("network", "interface", action, netId, iface);
2528         } catch (NativeDaemonConnectorException e) {
2529             throw e.rethrowAsParcelableException();
2530         }
2531     }
2532 
2533     @Override
addLegacyRouteForNetId(int netId, RouteInfo routeInfo, int uid)2534     public void addLegacyRouteForNetId(int netId, RouteInfo routeInfo, int uid) {
2535         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2536 
2537         final Command cmd = new Command("network", "route", "legacy", uid, "add", netId);
2538 
2539         // create triplet: interface dest-ip-addr/prefixlength gateway-ip-addr
2540         final LinkAddress la = routeInfo.getDestinationLinkAddress();
2541         cmd.appendArg(routeInfo.getInterface());
2542         cmd.appendArg(la.getAddress().getHostAddress() + "/" + la.getPrefixLength());
2543         if (routeInfo.hasGateway()) {
2544             cmd.appendArg(routeInfo.getGateway().getHostAddress());
2545         }
2546 
2547         try {
2548             mConnector.execute(cmd);
2549         } catch (NativeDaemonConnectorException e) {
2550             throw e.rethrowAsParcelableException();
2551         }
2552     }
2553 
2554     @Override
setDefaultNetId(int netId)2555     public void setDefaultNetId(int netId) {
2556         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2557 
2558         try {
2559             mConnector.execute("network", "default", "set", netId);
2560         } catch (NativeDaemonConnectorException e) {
2561             throw e.rethrowAsParcelableException();
2562         }
2563     }
2564 
2565     @Override
clearDefaultNetId()2566     public void clearDefaultNetId() {
2567         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2568 
2569         try {
2570             mConnector.execute("network", "default", "clear");
2571         } catch (NativeDaemonConnectorException e) {
2572             throw e.rethrowAsParcelableException();
2573         }
2574     }
2575 
2576     @Override
setNetworkPermission(int netId, String permission)2577     public void setNetworkPermission(int netId, String permission) {
2578         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2579 
2580         try {
2581             if (permission != null) {
2582                 mConnector.execute("network", "permission", "network", "set", permission, netId);
2583             } else {
2584                 mConnector.execute("network", "permission", "network", "clear", netId);
2585             }
2586         } catch (NativeDaemonConnectorException e) {
2587             throw e.rethrowAsParcelableException();
2588         }
2589     }
2590 
2591 
2592     @Override
setPermission(String permission, int[] uids)2593     public void setPermission(String permission, int[] uids) {
2594         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2595 
2596         Object[] argv = new Object[4 + MAX_UID_RANGES_PER_COMMAND];
2597         argv[0] = "permission";
2598         argv[1] = "user";
2599         argv[2] = "set";
2600         argv[3] = permission;
2601         int argc = 4;
2602         // Avoid overly long commands by limiting number of UIDs per command.
2603         for (int i = 0; i < uids.length; ++i) {
2604             argv[argc++] = uids[i];
2605             if (i == uids.length - 1 || argc == argv.length) {
2606                 try {
2607                     mConnector.execute("network", Arrays.copyOf(argv, argc));
2608                 } catch (NativeDaemonConnectorException e) {
2609                     throw e.rethrowAsParcelableException();
2610                 }
2611                 argc = 4;
2612             }
2613         }
2614     }
2615 
2616     @Override
clearPermission(int[] uids)2617     public void clearPermission(int[] uids) {
2618         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2619 
2620         Object[] argv = new Object[3 + MAX_UID_RANGES_PER_COMMAND];
2621         argv[0] = "permission";
2622         argv[1] = "user";
2623         argv[2] = "clear";
2624         int argc = 3;
2625         // Avoid overly long commands by limiting number of UIDs per command.
2626         for (int i = 0; i < uids.length; ++i) {
2627             argv[argc++] = uids[i];
2628             if (i == uids.length - 1 || argc == argv.length) {
2629                 try {
2630                     mConnector.execute("network", Arrays.copyOf(argv, argc));
2631                 } catch (NativeDaemonConnectorException e) {
2632                     throw e.rethrowAsParcelableException();
2633                 }
2634                 argc = 3;
2635             }
2636         }
2637     }
2638 
2639     @Override
allowProtect(int uid)2640     public void allowProtect(int uid) {
2641         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2642 
2643         try {
2644             mConnector.execute("network", "protect", "allow", uid);
2645         } catch (NativeDaemonConnectorException e) {
2646             throw e.rethrowAsParcelableException();
2647         }
2648     }
2649 
2650     @Override
denyProtect(int uid)2651     public void denyProtect(int uid) {
2652         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2653 
2654         try {
2655             mConnector.execute("network", "protect", "deny", uid);
2656         } catch (NativeDaemonConnectorException e) {
2657             throw e.rethrowAsParcelableException();
2658         }
2659     }
2660 
2661     @Override
addInterfaceToLocalNetwork(String iface, List<RouteInfo> routes)2662     public void addInterfaceToLocalNetwork(String iface, List<RouteInfo> routes) {
2663         modifyInterfaceInNetwork("add", "local", iface);
2664 
2665         for (RouteInfo route : routes) {
2666             if (!route.isDefaultRoute()) {
2667                 modifyRoute("add", "local", route);
2668             }
2669         }
2670     }
2671 
2672     @Override
removeInterfaceFromLocalNetwork(String iface)2673     public void removeInterfaceFromLocalNetwork(String iface) {
2674         modifyInterfaceInNetwork("remove", "local", iface);
2675     }
2676 
2677     @Override
removeRoutesFromLocalNetwork(List<RouteInfo> routes)2678     public int removeRoutesFromLocalNetwork(List<RouteInfo> routes) {
2679         int failures = 0;
2680 
2681         for (RouteInfo route : routes) {
2682             try {
2683                 modifyRoute("remove", "local", route);
2684             } catch (IllegalStateException e) {
2685                 failures++;
2686             }
2687         }
2688 
2689         return failures;
2690     }
2691 
2692     @Override
isNetworkRestricted(int uid)2693     public boolean isNetworkRestricted(int uid) {
2694         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2695         return isNetworkRestrictedInternal(uid);
2696     }
2697 
isNetworkRestrictedInternal(int uid)2698     private boolean isNetworkRestrictedInternal(int uid) {
2699         synchronized (mRulesLock) {
2700             if (getFirewallChainState(FIREWALL_CHAIN_STANDBY)
2701                     && mUidFirewallStandbyRules.get(uid) == FIREWALL_RULE_DENY) {
2702                 if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of app standby mode");
2703                 return true;
2704             }
2705             if (getFirewallChainState(FIREWALL_CHAIN_DOZABLE)
2706                     && mUidFirewallDozableRules.get(uid) != FIREWALL_RULE_ALLOW) {
2707                 if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of device idle mode");
2708                 return true;
2709             }
2710             if (getFirewallChainState(FIREWALL_CHAIN_POWERSAVE)
2711                     && mUidFirewallPowerSaveRules.get(uid) != FIREWALL_RULE_ALLOW) {
2712                 if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of power saver mode");
2713                 return true;
2714             }
2715             if (mUidRejectOnMetered.get(uid)) {
2716                 if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of no metered data"
2717                         + " in the background");
2718                 return true;
2719             }
2720             if (mDataSaverMode && !mUidAllowOnMetered.get(uid)) {
2721                 if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of data saver mode");
2722                 return true;
2723             }
2724             return false;
2725         }
2726     }
2727 
setFirewallChainState(int chain, boolean state)2728     private void setFirewallChainState(int chain, boolean state) {
2729         synchronized (mRulesLock) {
2730             mFirewallChainStates.put(chain, state);
2731         }
2732     }
2733 
getFirewallChainState(int chain)2734     private boolean getFirewallChainState(int chain) {
2735         synchronized (mRulesLock) {
2736             return mFirewallChainStates.get(chain);
2737         }
2738     }
2739 
2740     @VisibleForTesting
2741     class LocalService extends NetworkManagementInternal {
2742         @Override
isNetworkRestrictedForUid(int uid)2743         public boolean isNetworkRestrictedForUid(int uid) {
2744             return isNetworkRestrictedInternal(uid);
2745         }
2746     }
2747 
2748     @VisibleForTesting
getInjector()2749     Injector getInjector() {
2750         return new Injector();
2751     }
2752 
2753     @VisibleForTesting
2754     class Injector {
setDataSaverMode(boolean dataSaverMode)2755         void setDataSaverMode(boolean dataSaverMode) {
2756             mDataSaverMode = dataSaverMode;
2757         }
2758 
setFirewallChainState(int chain, boolean state)2759         void setFirewallChainState(int chain, boolean state) {
2760             NetworkManagementService.this.setFirewallChainState(chain, state);
2761         }
2762 
setFirewallRule(int chain, int uid, int rule)2763         void setFirewallRule(int chain, int uid, int rule) {
2764             synchronized (mRulesLock) {
2765                 getUidFirewallRulesLR(chain).put(uid, rule);
2766             }
2767         }
2768 
setUidOnMeteredNetworkList(boolean blacklist, int uid, boolean enable)2769         void setUidOnMeteredNetworkList(boolean blacklist, int uid, boolean enable) {
2770             synchronized (mRulesLock) {
2771                 if (blacklist) {
2772                     mUidRejectOnMetered.put(uid, enable);
2773                 } else {
2774                     mUidAllowOnMetered.put(uid, enable);
2775                 }
2776             }
2777         }
2778 
reset()2779         void reset() {
2780             synchronized (mRulesLock) {
2781                 setDataSaverMode(false);
2782                 final int[] chains = {
2783                         FIREWALL_CHAIN_DOZABLE,
2784                         FIREWALL_CHAIN_STANDBY,
2785                         FIREWALL_CHAIN_POWERSAVE
2786                 };
2787                 for (int chain : chains) {
2788                     setFirewallChainState(chain, false);
2789                     getUidFirewallRulesLR(chain).clear();
2790                 }
2791                 mUidAllowOnMetered.clear();
2792                 mUidRejectOnMetered.clear();
2793             }
2794         }
2795     }
2796 }
2797