blob: 840b7af19890c6cb15b648eedea6dc81484ccf00 [file] [log] [blame]
San Mehat873f2142010-01-14 10:25:07 -08001/*
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
17package com.android.server;
18
paulhu79ebe4f2019-12-06 16:45:38 +080019import static android.Manifest.permission.CONNECTIVITY_INTERNAL;
Sehee Parka9139bc2017-12-22 13:54:05 +090020import static android.Manifest.permission.NETWORK_SETTINGS;
paulhu59148b72019-08-12 16:25:11 +080021import static android.Manifest.permission.OBSERVE_NETWORK_POLICY;
Jeff Sharkeyaf75c332011-11-18 12:41:12 -080022import static android.Manifest.permission.SHUTDOWN;
Remi NGUYEN VANf9a8c2e2019-02-13 18:28:35 +090023import static android.net.INetd.FIREWALL_BLACKLIST;
24import static android.net.INetd.FIREWALL_CHAIN_DOZABLE;
25import static android.net.INetd.FIREWALL_CHAIN_NONE;
26import static android.net.INetd.FIREWALL_CHAIN_POWERSAVE;
27import static android.net.INetd.FIREWALL_CHAIN_STANDBY;
28import static android.net.INetd.FIREWALL_RULE_ALLOW;
29import static android.net.INetd.FIREWALL_RULE_DENY;
30import static android.net.INetd.FIREWALL_WHITELIST;
Xiaohui Chenb41c9f72015-06-17 15:55:37 -070031import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_DOZABLE;
Felipe Leme011b98f2016-02-10 17:28:31 -080032import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_POWERSAVE;
Xiaohui Chenb41c9f72015-06-17 15:55:37 -070033import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_STANDBY;
Xiaohui Chenb41c9f72015-06-17 15:55:37 -070034import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT;
Jeff Sharkeyb5d55e32011-08-10 17:53:27 -070035import static android.net.NetworkStats.SET_DEFAULT;
Lorenzo Colittif1912ca2017-08-17 19:23:08 +090036import static android.net.NetworkStats.STATS_PER_UID;
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -070037import static android.net.NetworkStats.TAG_NONE;
Jeff Sharkeyae2c1812011-10-04 13:11:40 -070038import static android.net.TrafficStats.UID_TETHERING;
Lorenzo Colitti9307ca22019-01-12 01:54:23 +090039
Jeff Sharkeya63ba592011-07-19 23:47:12 -070040import static com.android.server.NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED;
Erik Klineb2cfdfb2017-01-18 20:54:14 +090041
Xiaohui Chenb41c9f72015-06-17 15:55:37 -070042import android.annotation.NonNull;
Sudheer Shankadc589ac2016-11-10 15:30:17 -080043import android.app.ActivityManager;
San Mehat873f2142010-01-14 10:25:07 -080044import android.content.Context;
Dianne Hackborn77b987f2014-02-26 16:20:52 -080045import android.net.ConnectivityManager;
Lorenzo Colitti58967ba2016-02-02 17:21:21 +090046import android.net.INetd;
Remi NGUYEN VAN9ebc3fc2019-01-29 19:12:13 +090047import android.net.INetdUnsolicitedEventListener;
San Mehat4d02d002010-01-22 16:07:46 -080048import android.net.INetworkManagementEventObserver;
Lorenzo Colitti07f13042017-07-10 19:06:57 +090049import android.net.ITetheringStatsProvider;
Remi NGUYEN VAN9ebc3fc2019-01-29 19:12:13 +090050import android.net.InetAddresses;
Jeff Sharkeyeedcb952011-05-17 14:55:15 -070051import android.net.InterfaceConfiguration;
Luke Huang14f75442018-08-15 19:22:54 +080052import android.net.InterfaceConfigurationParcel;
Lorenzo Colittic18cbfd2014-06-13 21:21:03 +090053import android.net.IpPrefix;
Robert Greenwalted126402011-01-28 15:34:55 -080054import android.net.LinkAddress;
Lorenzo Colittib57edc52014-08-22 17:10:50 -070055import android.net.Network;
Amith Yamasani15e472352015-04-24 19:06:07 -070056import android.net.NetworkPolicyManager;
paulhu59148b72019-08-12 16:25:11 +080057import android.net.NetworkStack;
Jeff Sharkeyeedcb952011-05-17 14:55:15 -070058import android.net.NetworkStats;
Robert Greenwalted126402011-01-28 15:34:55 -080059import android.net.NetworkUtils;
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -070060import android.net.RouteInfo;
Lorenzo Colitti9307ca22019-01-12 01:54:23 +090061import android.net.TetherStatsParcel;
Paul Jensen6bc2c2c2014-05-07 15:27:40 -040062import android.net.UidRange;
Lorenzo Colitticc7f1db2019-03-18 23:50:34 +090063import android.net.UidRangeParcel;
Remi NGUYEN VAN231b52b2019-01-29 15:38:52 +090064import android.net.util.NetdService;
Dianne Hackborn91268cf2013-06-13 19:06:50 -070065import android.os.BatteryStats;
Jeff Sharkeyf56e2432012-09-06 17:54:29 -070066import android.os.Binder;
Jeff Sharkeyb24a7852012-05-01 15:19:37 -070067import android.os.Handler;
Lorenzo Colittia0868002017-07-11 02:29:28 +090068import android.os.IBinder;
Dianne Hackborn77b987f2014-02-26 16:20:52 -080069import android.os.INetworkActivityListener;
San Mehat873f2142010-01-14 10:25:07 -080070import android.os.INetworkManagementService;
Jeff Sharkeyf56e2432012-09-06 17:54:29 -070071import android.os.Process;
Jeff Sharkey3df273e2011-12-15 15:47:12 -080072import android.os.RemoteCallbackList;
73import android.os.RemoteException;
Jeff Sharkey7a1c3fc2013-06-04 12:29:00 -070074import android.os.ServiceManager;
Lorenzo Colitti4cb42402016-04-24 12:52:00 +090075import android.os.ServiceSpecificException;
Jeff Sharkey605eb792014-11-04 13:34:06 -080076import android.os.StrictMode;
Jeff Sharkey9a13f362011-04-26 16:25:36 -070077import android.os.SystemClock;
Marco Nelissen62dbb222010-02-18 10:56:30 -080078import android.os.SystemProperties;
Felipe Leme29e72ea2016-09-08 13:26:55 -070079import android.os.Trace;
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -070080import android.telephony.DataConnectionRealTimeInfo;
Lorenzo Colitticc7f1db2019-03-18 23:50:34 +090081import android.text.TextUtils;
Irfan Sheriff9ab518ad2010-03-12 15:48:17 -080082import android.util.Log;
Joe Onorato8a9b2202010-02-26 18:56:32 -080083import android.util.Slog;
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -070084import android.util.SparseBooleanArray;
Jeff Sharkey605eb792014-11-04 13:34:06 -080085import android.util.SparseIntArray;
Bookatz0b028b12018-05-31 16:51:17 -070086import android.util.StatsLog;
San Mehat873f2142010-01-14 10:25:07 -080087
Jeff Sharkey605eb792014-11-04 13:34:06 -080088import com.android.internal.annotations.GuardedBy;
Sudheer Shanka62f5c172017-03-17 16:25:55 -070089import com.android.internal.annotations.VisibleForTesting;
Jeff Sharkey7a1c3fc2013-06-04 12:29:00 -070090import com.android.internal.app.IBatteryStats;
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -060091import com.android.internal.util.DumpUtils;
Jeff Sharkey605eb792014-11-04 13:34:06 -080092import com.android.internal.util.HexDump;
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -070093import com.android.internal.util.Preconditions;
Lorenzo Colitti9307ca22019-01-12 01:54:23 +090094
Jeff Sharkeyb24a7852012-05-01 15:19:37 -070095import com.google.android.collect.Maps;
Jeff Sharkey4414cea2011-06-24 17:05:24 -070096
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -070097import java.io.BufferedReader;
98import java.io.DataInputStream;
Jeff Sharkey47eb1022011-08-25 17:48:52 -070099import java.io.FileDescriptor;
Jeff Sharkey9a13f362011-04-26 16:25:36 -0700100import java.io.FileInputStream;
Jeff Sharkey9a13f362011-04-26 16:25:36 -0700101import java.io.IOException;
Jeff Sharkey9a13f362011-04-26 16:25:36 -0700102import java.io.InputStreamReader;
Jeff Sharkey47eb1022011-08-25 17:48:52 -0700103import java.io.PrintWriter;
Jeff Sharkeyeedcb952011-05-17 14:55:15 -0700104import java.net.InetAddress;
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -0700105import java.net.InterfaceAddress;
Jeff Sharkeyeedcb952011-05-17 14:55:15 -0700106import java.util.ArrayList;
Paul Jensen6bc2c2c2014-05-07 15:27:40 -0400107import java.util.Arrays;
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700108import java.util.HashMap;
jiaguo1da35f72014-01-09 16:39:59 +0800109import java.util.List;
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700110import java.util.Map;
San Mehat873f2142010-01-14 10:25:07 -0800111
112/**
113 * @hide
114 */
Luke Huang909b31a2019-03-16 21:21:16 +0800115public class NetworkManagementService extends INetworkManagementService.Stub {
Lorenzo Colittia0868002017-07-11 02:29:28 +0900116
117 /**
118 * Helper class that encapsulates NetworkManagementService dependencies and makes them
119 * easier to mock in unit tests.
120 */
121 static class SystemServices {
122 public IBinder getService(String name) {
123 return ServiceManager.getService(name);
124 }
125 public void registerLocalService(NetworkManagementInternal nmi) {
126 LocalServices.addService(NetworkManagementInternal.class, nmi);
127 }
128 public INetd getNetd() {
129 return NetdService.get();
130 }
131 }
132
Amith Yamasani15e472352015-04-24 19:06:07 -0700133 private static final String TAG = "NetworkManagement";
134 private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
Kenny Root305bcbf2010-09-03 07:56:38 -0700135
Paul Jensen6bc2c2c2014-05-07 15:27:40 -0400136 private static final int MAX_UID_RANGES_PER_COMMAND = 10;
137
Jeff Sharkey8e9992a2011-08-23 18:37:23 -0700138 /**
139 * Name representing {@link #setGlobalAlert(long)} limit when delivered to
140 * {@link INetworkManagementEventObserver#limitReached(String, String)}.
141 */
142 public static final String LIMIT_GLOBAL_ALERT = "globalAlert";
143
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -0700144 static final int DAEMON_MSG_MOBILE_CONN_REAL_TIME_INFO = 1;
145
Luke Huang8a462ec2018-08-24 20:33:16 +0800146 static final boolean MODIFY_OPERATION_ADD = true;
147 static final boolean MODIFY_OPERATION_REMOVE = false;
148
San Mehat873f2142010-01-14 10:25:07 -0800149 /**
150 * Binder context for this service
151 */
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -0700152 private final Context mContext;
San Mehat873f2142010-01-14 10:25:07 -0800153
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -0700154 private final Handler mDaemonHandler;
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700155
Lorenzo Colittia0868002017-07-11 02:29:28 +0900156 private final SystemServices mServices;
157
Lorenzo Colitti58967ba2016-02-02 17:21:21 +0900158 private INetd mNetdService;
159
Remi NGUYEN VAN9ebc3fc2019-01-29 19:12:13 +0900160 private final NetdUnsolicitedEventListener mNetdUnsolicitedEventListener;
Luke Huangd290dd52018-09-04 17:08:18 +0800161
Dianne Hackborne13c4c02014-02-11 17:18:35 -0800162 private IBatteryStats mBatteryStats;
163
Remi NGUYEN VAN9ebc3fc2019-01-29 19:12:13 +0900164 private final RemoteCallbackList<INetworkManagementEventObserver> mObservers =
165 new RemoteCallbackList<>();
166
Lorenzo Colitti07f13042017-07-10 19:06:57 +0900167 @GuardedBy("mTetheringStatsProviders")
168 private final HashMap<ITetheringStatsProvider, String>
169 mTetheringStatsProviders = Maps.newHashMap();
170
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700171 /**
172 * If both locks need to be held, then they should be obtained in the order:
173 * first {@link #mQuotaLock} and then {@link #mRulesLock}.
174 */
Andrew Scull45f533c2017-05-19 15:37:20 +0100175 private final Object mQuotaLock = new Object();
Andrew Scull519291f2017-05-23 13:11:03 +0100176 private final Object mRulesLock = new Object();
Jeff Sharkey605eb792014-11-04 13:34:06 -0800177
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -0700178 /** Set of interfaces with active quotas. */
Jeff Sharkey605eb792014-11-04 13:34:06 -0800179 @GuardedBy("mQuotaLock")
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700180 private HashMap<String, Long> mActiveQuotas = Maps.newHashMap();
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -0700181 /** Set of interfaces with active alerts. */
Jeff Sharkey605eb792014-11-04 13:34:06 -0800182 @GuardedBy("mQuotaLock")
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700183 private HashMap<String, Long> mActiveAlerts = Maps.newHashMap();
Felipe Leme65be3022016-03-22 14:53:13 -0700184 /** Set of UIDs blacklisted on metered networks. */
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700185 @GuardedBy("mRulesLock")
Felipe Leme65be3022016-03-22 14:53:13 -0700186 private SparseBooleanArray mUidRejectOnMetered = new SparseBooleanArray();
187 /** Set of UIDs whitelisted on metered networks. */
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700188 @GuardedBy("mRulesLock")
Felipe Leme65be3022016-03-22 14:53:13 -0700189 private SparseBooleanArray mUidAllowOnMetered = new SparseBooleanArray();
Jeff Sharkey605eb792014-11-04 13:34:06 -0800190 /** Set of UIDs with cleartext penalties. */
191 @GuardedBy("mQuotaLock")
192 private SparseIntArray mUidCleartextPolicy = new SparseIntArray();
Amith Yamasani15e472352015-04-24 19:06:07 -0700193 /** Set of UIDs that are to be blocked/allowed by firewall controller. */
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700194 @GuardedBy("mRulesLock")
Amith Yamasani15e472352015-04-24 19:06:07 -0700195 private SparseIntArray mUidFirewallRules = new SparseIntArray();
Xiaohui Chenb41c9f72015-06-17 15:55:37 -0700196 /**
197 * Set of UIDs that are to be blocked/allowed by firewall controller. This set of Ids matches
198 * to application idles.
199 */
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700200 @GuardedBy("mRulesLock")
Xiaohui Chenb41c9f72015-06-17 15:55:37 -0700201 private SparseIntArray mUidFirewallStandbyRules = new SparseIntArray();
202 /**
203 * Set of UIDs that are to be blocked/allowed by firewall controller. This set of Ids matches
204 * to device idles.
205 */
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700206 @GuardedBy("mRulesLock")
Xiaohui Chenb41c9f72015-06-17 15:55:37 -0700207 private SparseIntArray mUidFirewallDozableRules = new SparseIntArray();
Felipe Leme011b98f2016-02-10 17:28:31 -0800208 /**
209 * Set of UIDs that are to be blocked/allowed by firewall controller. This set of Ids matches
210 * to device on power-save mode.
211 */
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700212 @GuardedBy("mRulesLock")
Felipe Leme011b98f2016-02-10 17:28:31 -0800213 private SparseIntArray mUidFirewallPowerSaveRules = new SparseIntArray();
Xiaohui Chen8dca36d2015-06-19 12:44:59 -0700214 /** Set of states for the child firewall chains. True if the chain is active. */
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700215 @GuardedBy("mRulesLock")
Xiaohui Chen8dca36d2015-06-19 12:44:59 -0700216 final SparseBooleanArray mFirewallChainStates = new SparseBooleanArray();
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -0700217
Felipe Leme65be3022016-03-22 14:53:13 -0700218 @GuardedBy("mQuotaLock")
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700219 private volatile boolean mDataSaverMode;
Felipe Leme65be3022016-03-22 14:53:13 -0700220
Andrew Scull45f533c2017-05-19 15:37:20 +0100221 private final Object mIdleTimerLock = new Object();
Haoyu Bai04124232012-06-28 15:26:19 -0700222 /** Set of interfaces with active idle timers. */
223 private static class IdleTimerParams {
224 public final int timeout;
Dianne Hackborn77b987f2014-02-26 16:20:52 -0800225 public final int type;
Haoyu Bai04124232012-06-28 15:26:19 -0700226 public int networkCount;
227
Dianne Hackborn77b987f2014-02-26 16:20:52 -0800228 IdleTimerParams(int timeout, int type) {
Haoyu Bai04124232012-06-28 15:26:19 -0700229 this.timeout = timeout;
Dianne Hackborn77b987f2014-02-26 16:20:52 -0800230 this.type = type;
Haoyu Bai04124232012-06-28 15:26:19 -0700231 this.networkCount = 1;
232 }
233 }
234 private HashMap<String, IdleTimerParams> mActiveIdleTimers = Maps.newHashMap();
235
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -0700236 private volatile boolean mFirewallEnabled;
Jeff Sharkey605eb792014-11-04 13:34:06 -0800237 private volatile boolean mStrictEnabled;
Jeff Sharkey350083e2011-06-29 10:45:16 -0700238
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -0700239 private boolean mMobileActivityFromRadio = false;
240 private int mLastPowerStateFromRadio = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
Adam Lesinskie08af192015-03-25 16:42:59 -0700241 private int mLastPowerStateFromWifi = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -0700242
Dianne Hackborn77b987f2014-02-26 16:20:52 -0800243 private final RemoteCallbackList<INetworkActivityListener> mNetworkActivityListeners =
Christopher Wiley212b95f2016-08-02 11:38:57 -0700244 new RemoteCallbackList<>();
Dianne Hackborn77b987f2014-02-26 16:20:52 -0800245 private boolean mNetworkActive;
246
San Mehat873f2142010-01-14 10:25:07 -0800247 /**
248 * Constructs a new NetworkManagementService instance
249 *
250 * @param context Binder context for this service
251 */
Lorenzo Colittia0868002017-07-11 02:29:28 +0900252 private NetworkManagementService(
Luke Huang909b31a2019-03-16 21:21:16 +0800253 Context context, SystemServices services) {
San Mehat873f2142010-01-14 10:25:07 -0800254 mContext = context;
Lorenzo Colittia0868002017-07-11 02:29:28 +0900255 mServices = services;
San Mehat4d02d002010-01-22 16:07:46 -0800256
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -0700257 mDaemonHandler = new Handler(FgThread.get().getLooper());
Wink Saville67e07892014-06-18 16:43:14 -0700258
Remi NGUYEN VAN9ebc3fc2019-01-29 19:12:13 +0900259 mNetdUnsolicitedEventListener = new NetdUnsolicitedEventListener();
260
Lorenzo Colittia0868002017-07-11 02:29:28 +0900261 mServices.registerLocalService(new LocalService());
Lorenzo Colitti8228eb32017-07-19 06:17:33 +0900262
Lorenzo Colitti07f13042017-07-10 19:06:57 +0900263 synchronized (mTetheringStatsProviders) {
264 mTetheringStatsProviders.put(new NetdTetheringStatsProvider(), "netd");
265 }
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700266 }
267
268 @VisibleForTesting
269 NetworkManagementService() {
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700270 mContext = null;
271 mDaemonHandler = null;
Lorenzo Colittia0868002017-07-11 02:29:28 +0900272 mServices = null;
Remi NGUYEN VAN9ebc3fc2019-01-29 19:12:13 +0900273 mNetdUnsolicitedEventListener = null;
Robert Greenwalte5c3afb2010-09-22 14:32:35 -0700274 }
275
Luke Huang909b31a2019-03-16 21:21:16 +0800276 static NetworkManagementService create(Context context, SystemServices services)
Felipe Leme03e689d2016-03-02 16:17:38 -0800277 throws InterruptedException {
Lorenzo Colittia0868002017-07-11 02:29:28 +0900278 final NetworkManagementService service =
Luke Huang909b31a2019-03-16 21:21:16 +0800279 new NetworkManagementService(context, services);
Robert Greenwalte5c3afb2010-09-22 14:32:35 -0700280 if (DBG) Slog.d(TAG, "Creating NetworkManagementService");
Lorenzo Colitti8c253ad2017-07-19 00:23:44 +0900281 if (DBG) Slog.d(TAG, "Connecting native netd service");
bohu07cc3bb2016-05-03 15:58:01 -0700282 service.connectNativeNetdService();
Lorenzo Colitti8c253ad2017-07-19 00:23:44 +0900283 if (DBG) Slog.d(TAG, "Connected");
Robert Greenwalte5c3afb2010-09-22 14:32:35 -0700284 return service;
San Mehat873f2142010-01-14 10:25:07 -0800285 }
286
Lorenzo Colitti7421a012013-08-20 22:51:24 +0900287 public static NetworkManagementService create(Context context) throws InterruptedException {
Luke Huang909b31a2019-03-16 21:21:16 +0800288 return create(context, new SystemServices());
Lorenzo Colitti7421a012013-08-20 22:51:24 +0900289 }
290
Jeff Sharkey350083e2011-06-29 10:45:16 -0700291 public void systemReady() {
Felipe Leme03e689d2016-03-02 16:17:38 -0800292 if (DBG) {
293 final long start = System.currentTimeMillis();
294 prepareNativeDaemon();
295 final long delta = System.currentTimeMillis() - start;
296 Slog.d(TAG, "Prepared in " + delta + "ms");
297 return;
298 } else {
299 prepareNativeDaemon();
300 }
Jeff Sharkey350083e2011-06-29 10:45:16 -0700301 }
302
Dianne Hackborne13c4c02014-02-11 17:18:35 -0800303 private IBatteryStats getBatteryStats() {
304 synchronized (this) {
305 if (mBatteryStats != null) {
306 return mBatteryStats;
307 }
Lorenzo Colittia0868002017-07-11 02:29:28 +0900308 mBatteryStats =
309 IBatteryStats.Stub.asInterface(mServices.getService(BatteryStats.SERVICE_NAME));
Dianne Hackborne13c4c02014-02-11 17:18:35 -0800310 return mBatteryStats;
311 }
312 }
313
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800314 @Override
Jeff Sharkey3df273e2011-12-15 15:47:12 -0800315 public void registerObserver(INetworkManagementEventObserver observer) {
paulhu59148b72019-08-12 16:25:11 +0800316 NetworkStack.checkNetworkStackPermission(mContext);
Remi NGUYEN VAN9ebc3fc2019-01-29 19:12:13 +0900317 mObservers.register(observer);
San Mehat4d02d002010-01-22 16:07:46 -0800318 }
319
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800320 @Override
Jeff Sharkey3df273e2011-12-15 15:47:12 -0800321 public void unregisterObserver(INetworkManagementEventObserver observer) {
paulhu59148b72019-08-12 16:25:11 +0800322 NetworkStack.checkNetworkStackPermission(mContext);
Remi NGUYEN VAN9ebc3fc2019-01-29 19:12:13 +0900323 mObservers.unregister(observer);
San Mehat4d02d002010-01-22 16:07:46 -0800324 }
325
Erik Klineb2cfdfb2017-01-18 20:54:14 +0900326 @FunctionalInterface
327 private interface NetworkManagementEventCallback {
328 public void sendCallback(INetworkManagementEventObserver o) throws RemoteException;
329 }
330
Remi NGUYEN VAN9ebc3fc2019-01-29 19:12:13 +0900331 private void invokeForAllObservers(NetworkManagementEventCallback eventCallback) {
332 final int length = mObservers.beginBroadcast();
333 try {
334 for (int i = 0; i < length; i++) {
335 try {
336 eventCallback.sendCallback(mObservers.getBroadcastItem(i));
337 } catch (RemoteException | RuntimeException e) {
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -0700338 }
Remi NGUYEN VAN9ebc3fc2019-01-29 19:12:13 +0900339 }
340 } finally {
341 mObservers.finishBroadcast();
342 }
343 }
344
345 /**
346 * Notify our observers of an interface status change
347 */
348 private void notifyInterfaceStatusChanged(String iface, boolean up) {
349 invokeForAllObservers(o -> o.interfaceStatusChanged(iface, up));
350 }
351
352 /**
353 * Notify our observers of an interface link state change
354 * (typically, an Ethernet cable has been plugged-in or unplugged).
355 */
356 private void notifyInterfaceLinkStateChanged(String iface, boolean up) {
357 invokeForAllObservers(o -> o.interfaceLinkStateChanged(iface, up));
358 }
359
360 /**
361 * Notify our observers of an interface addition.
362 */
363 private void notifyInterfaceAdded(String iface) {
364 invokeForAllObservers(o -> o.interfaceAdded(iface));
365 }
366
367 /**
368 * Notify our observers of an interface removal.
369 */
370 private void notifyInterfaceRemoved(String iface) {
371 // netd already clears out quota and alerts for removed ifaces; update
372 // our sanity-checking state.
373 mActiveAlerts.remove(iface);
374 mActiveQuotas.remove(iface);
375 invokeForAllObservers(o -> o.interfaceRemoved(iface));
376 }
377
378 /**
379 * Notify our observers of a limit reached.
380 */
381 private void notifyLimitReached(String limitName, String iface) {
382 invokeForAllObservers(o -> o.limitReached(limitName, iface));
383 }
384
385 /**
386 * Notify our observers of a change in the data activity state of the interface
387 */
388 private void notifyInterfaceClassActivity(int type, boolean isActive, long tsNanos,
389 int uid, boolean fromRadio) {
390 final boolean isMobile = ConnectivityManager.isNetworkTypeMobile(type);
391 int powerState = isActive
392 ? DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH
393 : DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
394 if (isMobile) {
395 if (!fromRadio) {
396 if (mMobileActivityFromRadio) {
397 // If this call is not coming from a report from the radio itself, but we
398 // have previously received reports from the radio, then we will take the
399 // power state to just be whatever the radio last reported.
400 powerState = mLastPowerStateFromRadio;
401 }
402 } else {
403 mMobileActivityFromRadio = true;
404 }
405 if (mLastPowerStateFromRadio != powerState) {
406 mLastPowerStateFromRadio = powerState;
407 try {
408 getBatteryStats().noteMobileRadioPowerState(powerState, tsNanos, uid);
409 } catch (RemoteException e) {
Robert Greenwalt2c9f5472014-04-21 14:50:28 -0700410 }
Bookatz0b028b12018-05-31 16:51:17 -0700411 StatsLog.write_non_chained(StatsLog.MOBILE_RADIO_POWER_STATE_CHANGED, uid, null,
412 powerState);
Haoyu Baidb3c8672012-06-20 14:29:57 -0700413 }
Remi NGUYEN VAN9ebc3fc2019-01-29 19:12:13 +0900414 }
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -0700415
Remi NGUYEN VAN9ebc3fc2019-01-29 19:12:13 +0900416 if (ConnectivityManager.isNetworkTypeWifi(type)) {
417 if (mLastPowerStateFromWifi != powerState) {
418 mLastPowerStateFromWifi = powerState;
419 try {
420 getBatteryStats().noteWifiRadioPowerState(powerState, tsNanos, uid);
421 } catch (RemoteException e) {
Adam Lesinskie08af192015-03-25 16:42:59 -0700422 }
Bookatz0b028b12018-05-31 16:51:17 -0700423 StatsLog.write_non_chained(StatsLog.WIFI_RADIO_POWER_STATE_CHANGED, uid, null,
424 powerState);
Adam Lesinskie08af192015-03-25 16:42:59 -0700425 }
Dianne Hackborn77b987f2014-02-26 16:20:52 -0800426 }
Lorenzo Colittid8bc8292019-01-24 13:28:50 +0900427
Remi NGUYEN VAN9ebc3fc2019-01-29 19:12:13 +0900428 if (!isMobile || fromRadio || !mMobileActivityFromRadio) {
429 // Report the change in data activity. We don't do this if this is a change
430 // on the mobile network, that is not coming from the radio itself, and we
431 // have previously seen change reports from the radio. In that case only
432 // the radio is the authority for the current state.
433 final boolean active = isActive;
434 invokeForAllObservers(o -> o.interfaceClassDataActivityChanged(
435 Integer.toString(type), active, tsNanos));
Lorenzo Colittid8bc8292019-01-24 13:28:50 +0900436 }
437
Remi NGUYEN VAN9ebc3fc2019-01-29 19:12:13 +0900438 boolean report = false;
439 synchronized (mIdleTimerLock) {
440 if (mActiveIdleTimers.isEmpty()) {
441 // If there are no idle timers, we are not monitoring activity, so we
442 // are always considered active.
443 isActive = true;
444 }
445 if (mNetworkActive != isActive) {
446 mNetworkActive = isActive;
447 report = isActive;
448 }
449 }
450 if (report) {
451 reportNetworkActive();
Dianne Hackborn77b987f2014-02-26 16:20:52 -0800452 }
Haoyu Baidb3c8672012-06-20 14:29:57 -0700453 }
454
Lorenzo Colitti07f13042017-07-10 19:06:57 +0900455 @Override
456 public void registerTetheringStatsProvider(ITetheringStatsProvider provider, String name) {
paulhu59148b72019-08-12 16:25:11 +0800457 NetworkStack.checkNetworkStackPermission(mContext);
Lorenzo Colitti07f13042017-07-10 19:06:57 +0900458 Preconditions.checkNotNull(provider);
459 synchronized(mTetheringStatsProviders) {
460 mTetheringStatsProviders.put(provider, name);
461 }
462 }
463
464 @Override
465 public void unregisterTetheringStatsProvider(ITetheringStatsProvider provider) {
paulhu59148b72019-08-12 16:25:11 +0800466 NetworkStack.checkNetworkStackPermission(mContext);
Lorenzo Colitti07f13042017-07-10 19:06:57 +0900467 synchronized(mTetheringStatsProviders) {
468 mTetheringStatsProviders.remove(provider);
469 }
470 }
471
Lorenzo Colitti9f0baa92017-08-15 19:25:51 +0900472 @Override
473 public void tetherLimitReached(ITetheringStatsProvider provider) {
paulhu59148b72019-08-12 16:25:11 +0800474 NetworkStack.checkNetworkStackPermission(mContext);
Lorenzo Colitti9f0baa92017-08-15 19:25:51 +0900475 synchronized(mTetheringStatsProviders) {
476 if (!mTetheringStatsProviders.containsKey(provider)) {
477 return;
478 }
479 // No current code examines the interface parameter in a global alert. Just pass null.
Remi NGUYEN VAN9ebc3fc2019-01-29 19:12:13 +0900480 mDaemonHandler.post(() -> notifyLimitReached(LIMIT_GLOBAL_ALERT, null));
Lorenzo Colitti9f0baa92017-08-15 19:25:51 +0900481 }
482 }
483
Lorenzo Colitti9eb844e2016-03-23 23:22:49 +0900484 // Sync the state of the given chain with the native daemon.
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700485 private void syncFirewallChainLocked(int chain, String name) {
486 SparseIntArray rules;
487 synchronized (mRulesLock) {
488 final SparseIntArray uidFirewallRules = getUidFirewallRulesLR(chain);
Lorenzo Colitti9eb844e2016-03-23 23:22:49 +0900489 // Make a copy of the current rules, and then clear them. This is because
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700490 // setFirewallUidRuleInternal only pushes down rules to the native daemon if they
491 // are different from the current rules stored in the mUidFirewall*Rules array for
492 // the specified chain. If we don't clear the rules, setFirewallUidRuleInternal
493 // will do nothing.
494 rules = uidFirewallRules.clone();
Lorenzo Colitti9eb844e2016-03-23 23:22:49 +0900495 uidFirewallRules.clear();
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700496 }
497 if (rules.size() > 0) {
Lorenzo Colitti9eb844e2016-03-23 23:22:49 +0900498 // Now push the rules. setFirewallUidRuleInternal will push each of these down to the
499 // native daemon, and also add them to the mUidFirewall*Rules array for the specified
500 // chain.
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700501 if (DBG) Slog.d(TAG, "Pushing " + rules.size() + " active firewall "
502 + name + "UID rules");
Lorenzo Colitti9eb844e2016-03-23 23:22:49 +0900503 for (int i = 0; i < rules.size(); i++) {
Felipe Lemea701cad2016-05-12 09:58:14 -0700504 setFirewallUidRuleLocked(chain, rules.keyAt(i), rules.valueAt(i));
Lorenzo Colitti9eb844e2016-03-23 23:22:49 +0900505 }
506 }
507 }
508
bohu07cc3bb2016-05-03 15:58:01 -0700509 private void connectNativeNetdService() {
Lorenzo Colittia0868002017-07-11 02:29:28 +0900510 mNetdService = mServices.getNetd();
Luke Huangd290dd52018-09-04 17:08:18 +0800511 try {
Remi NGUYEN VAN9ebc3fc2019-01-29 19:12:13 +0900512 mNetdService.registerUnsolicitedEventListener(mNetdUnsolicitedEventListener);
513 if (DBG) Slog.d(TAG, "Register unsolicited event listener");
Luke Huangd290dd52018-09-04 17:08:18 +0800514 } catch (RemoteException | ServiceSpecificException e) {
Remi NGUYEN VAN9ebc3fc2019-01-29 19:12:13 +0900515 Slog.e(TAG, "Failed to set Netd unsolicited event listener " + e);
Luke Huangd290dd52018-09-04 17:08:18 +0800516 }
bohu07cc3bb2016-05-03 15:58:01 -0700517 }
518
519 /**
520 * Prepare native daemon once connected, enabling modules and pushing any
521 * existing in-memory rules.
522 */
523 private void prepareNativeDaemon() {
Lorenzo Colitti58967ba2016-02-02 17:21:21 +0900524
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700525 // push any existing quota or UID rules
526 synchronized (mQuotaLock) {
Felipe Leme65be3022016-03-22 14:53:13 -0700527
Luke Huang56a03a02018-09-07 12:02:16 +0800528 // Netd unconditionally enable bandwidth control
529 SystemProperties.set(PROP_QTAGUID_ENABLED, "1");
Lorenzo Colitti8c253ad2017-07-19 00:23:44 +0900530
Luke Huang473eb872018-07-26 17:33:14 +0800531 mStrictEnabled = true;
Lorenzo Colitti8c253ad2017-07-19 00:23:44 +0900532
Felipe Leme65be3022016-03-22 14:53:13 -0700533 setDataSaverModeEnabled(mDataSaverMode);
534
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700535 int size = mActiveQuotas.size();
536 if (size > 0) {
Felipe Leme03e689d2016-03-02 16:17:38 -0800537 if (DBG) Slog.d(TAG, "Pushing " + size + " active quota rules");
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700538 final HashMap<String, Long> activeQuotas = mActiveQuotas;
539 mActiveQuotas = Maps.newHashMap();
540 for (Map.Entry<String, Long> entry : activeQuotas.entrySet()) {
541 setInterfaceQuota(entry.getKey(), entry.getValue());
542 }
543 }
544
545 size = mActiveAlerts.size();
546 if (size > 0) {
Felipe Leme03e689d2016-03-02 16:17:38 -0800547 if (DBG) Slog.d(TAG, "Pushing " + size + " active alert rules");
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700548 final HashMap<String, Long> activeAlerts = mActiveAlerts;
549 mActiveAlerts = Maps.newHashMap();
550 for (Map.Entry<String, Long> entry : activeAlerts.entrySet()) {
551 setInterfaceAlert(entry.getKey(), entry.getValue());
552 }
553 }
554
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700555 SparseBooleanArray uidRejectOnQuota = null;
556 SparseBooleanArray uidAcceptOnQuota = null;
557 synchronized (mRulesLock) {
558 size = mUidRejectOnMetered.size();
559 if (size > 0) {
560 if (DBG) Slog.d(TAG, "Pushing " + size + " UIDs to metered blacklist rules");
561 uidRejectOnQuota = mUidRejectOnMetered;
562 mUidRejectOnMetered = new SparseBooleanArray();
563 }
564
565 size = mUidAllowOnMetered.size();
566 if (size > 0) {
567 if (DBG) Slog.d(TAG, "Pushing " + size + " UIDs to metered whitelist rules");
568 uidAcceptOnQuota = mUidAllowOnMetered;
569 mUidAllowOnMetered = new SparseBooleanArray();
570 }
571 }
572 if (uidRejectOnQuota != null) {
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700573 for (int i = 0; i < uidRejectOnQuota.size(); i++) {
Felipe Leme65be3022016-03-22 14:53:13 -0700574 setUidMeteredNetworkBlacklist(uidRejectOnQuota.keyAt(i),
575 uidRejectOnQuota.valueAt(i));
576 }
577 }
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700578 if (uidAcceptOnQuota != null) {
Felipe Leme65be3022016-03-22 14:53:13 -0700579 for (int i = 0; i < uidAcceptOnQuota.size(); i++) {
580 setUidMeteredNetworkWhitelist(uidAcceptOnQuota.keyAt(i),
581 uidAcceptOnQuota.valueAt(i));
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700582 }
583 }
Jeff Sharkey605eb792014-11-04 13:34:06 -0800584
585 size = mUidCleartextPolicy.size();
586 if (size > 0) {
Felipe Leme03e689d2016-03-02 16:17:38 -0800587 if (DBG) Slog.d(TAG, "Pushing " + size + " active UID cleartext policies");
Jeff Sharkey605eb792014-11-04 13:34:06 -0800588 final SparseIntArray local = mUidCleartextPolicy;
589 mUidCleartextPolicy = new SparseIntArray();
590 for (int i = 0; i < local.size(); i++) {
591 setUidCleartextNetworkPolicy(local.keyAt(i), local.valueAt(i));
592 }
593 }
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -0700594
Robin Leec3736bc2017-03-10 16:19:54 +0000595 setFirewallEnabled(mFirewallEnabled);
Amith Yamasani15e472352015-04-24 19:06:07 -0700596
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700597 syncFirewallChainLocked(FIREWALL_CHAIN_NONE, "");
598 syncFirewallChainLocked(FIREWALL_CHAIN_STANDBY, "standby ");
599 syncFirewallChainLocked(FIREWALL_CHAIN_DOZABLE, "dozable ");
600 syncFirewallChainLocked(FIREWALL_CHAIN_POWERSAVE, "powersave ");
Xiaohui Chenb41c9f72015-06-17 15:55:37 -0700601
Sudheer Shanka62f5c172017-03-17 16:25:55 -0700602 final int[] chains =
603 {FIREWALL_CHAIN_STANDBY, FIREWALL_CHAIN_DOZABLE, FIREWALL_CHAIN_POWERSAVE};
604 for (int chain : chains) {
605 if (getFirewallChainState(chain)) {
606 setFirewallChainEnabled(chain, true);
607 }
Felipe Leme011b98f2016-02-10 17:28:31 -0800608 }
Amith Yamasani15e472352015-04-24 19:06:07 -0700609 }
Lorenzo Colitti8c253ad2017-07-19 00:23:44 +0900610
Luke Huang56a03a02018-09-07 12:02:16 +0800611
612 try {
613 getBatteryStats().noteNetworkStatsEnabled();
614 } catch (RemoteException e) {
Lorenzo Colitti8c253ad2017-07-19 00:23:44 +0900615 }
616
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700617 }
San Mehat4d02d002010-01-22 16:07:46 -0800618
Remi NGUYEN VAN9ebc3fc2019-01-29 19:12:13 +0900619 /**
620 * Notify our observers of a new or updated interface address.
621 */
622 private void notifyAddressUpdated(String iface, LinkAddress address) {
623 invokeForAllObservers(o -> o.addressUpdated(iface, address));
624 }
625
626 /**
627 * Notify our observers of a deleted interface address.
628 */
629 private void notifyAddressRemoved(String iface, LinkAddress address) {
630 invokeForAllObservers(o -> o.addressRemoved(iface, address));
631 }
632
633 /**
634 * Notify our observers of DNS server information received.
635 */
636 private void notifyInterfaceDnsServerInfo(String iface, long lifetime, String[] addresses) {
637 invokeForAllObservers(o -> o.interfaceDnsServerInfo(iface, lifetime, addresses));
638 }
639
640 /**
641 * Notify our observers of a route change.
642 */
643 private void notifyRouteChange(boolean updated, RouteInfo route) {
644 if (updated) {
645 invokeForAllObservers(o -> o.routeUpdated(route));
646 } else {
647 invokeForAllObservers(o -> o.routeRemoved(route));
648 }
649 }
650
651 private class NetdUnsolicitedEventListener extends INetdUnsolicitedEventListener.Stub {
652 @Override
653 public void onInterfaceClassActivityChanged(boolean isActive,
654 int label, long timestamp, int uid) throws RemoteException {
655 final long timestampNanos;
656 if (timestamp <= 0) {
657 timestampNanos = SystemClock.elapsedRealtimeNanos();
658 } else {
659 timestampNanos = timestamp;
660 }
661 mDaemonHandler.post(() ->
662 notifyInterfaceClassActivity(label, isActive, timestampNanos, uid, false));
663 }
664
665 @Override
666 public void onQuotaLimitReached(String alertName, String ifName)
667 throws RemoteException {
668 mDaemonHandler.post(() -> notifyLimitReached(alertName, ifName));
669 }
670
671 @Override
672 public void onInterfaceDnsServerInfo(String ifName,
673 long lifetime, String[] servers) throws RemoteException {
674 mDaemonHandler.post(() -> notifyInterfaceDnsServerInfo(ifName, lifetime, servers));
675 }
676
677 @Override
678 public void onInterfaceAddressUpdated(String addr,
679 String ifName, int flags, int scope) throws RemoteException {
680 final LinkAddress address = new LinkAddress(addr, flags, scope);
681 mDaemonHandler.post(() -> notifyAddressUpdated(ifName, address));
682 }
683
684 @Override
685 public void onInterfaceAddressRemoved(String addr,
686 String ifName, int flags, int scope) throws RemoteException {
687 final LinkAddress address = new LinkAddress(addr, flags, scope);
688 mDaemonHandler.post(() -> notifyAddressRemoved(ifName, address));
689 }
690
691 @Override
692 public void onInterfaceAdded(String ifName) throws RemoteException {
693 mDaemonHandler.post(() -> notifyInterfaceAdded(ifName));
694 }
695
696 @Override
697 public void onInterfaceRemoved(String ifName) throws RemoteException {
698 mDaemonHandler.post(() -> notifyInterfaceRemoved(ifName));
699 }
700
701 @Override
702 public void onInterfaceChanged(String ifName, boolean up)
703 throws RemoteException {
704 mDaemonHandler.post(() -> notifyInterfaceStatusChanged(ifName, up));
705 }
706
707 @Override
708 public void onInterfaceLinkStateChanged(String ifName, boolean up)
709 throws RemoteException {
710 mDaemonHandler.post(() -> notifyInterfaceLinkStateChanged(ifName, up));
711 }
712
713 @Override
714 public void onRouteChanged(boolean updated,
715 String route, String gateway, String ifName) throws RemoteException {
716 final RouteInfo processRoute = new RouteInfo(new IpPrefix(route),
717 ("".equals(gateway)) ? null : InetAddresses.parseNumericAddress(gateway),
718 ifName);
719 mDaemonHandler.post(() -> notifyRouteChange(updated, processRoute));
720 }
721
722 @Override
723 public void onStrictCleartextDetected(int uid, String hex) throws RemoteException {
724 // Don't need to post to mDaemonHandler because the only thing
725 // that notifyCleartextNetwork does is post to a handler
726 ActivityManager.getService().notifyCleartextNetwork(uid,
727 HexDump.hexStringToByteArray(hex));
728 }
Remi NGUYEN VANeec0ed42019-04-09 14:01:51 +0900729
730 @Override
731 public int getInterfaceVersion() {
732 return INetdUnsolicitedEventListener.VERSION;
733 }
Remi NGUYEN VAN9ebc3fc2019-01-29 19:12:13 +0900734 }
735
San Mehat873f2142010-01-14 10:25:07 -0800736 //
San Mehat873f2142010-01-14 10:25:07 -0800737 // INetworkManagementService members
738 //
Erik Kline4e37b702016-07-05 11:34:21 +0900739 @Override
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800740 public String[] listInterfaces() {
paulhu79ebe4f2019-12-06 16:45:38 +0800741 // TODO: Remove CONNECTIVITY_INTERNAL after bluetooth tethering has no longer called these
742 // APIs.
743 NetworkStack.checkNetworkStackPermissionOr(mContext, CONNECTIVITY_INTERNAL);
Kenny Roota80ce062010-06-01 13:23:53 -0700744 try {
Luke Huang1b4f92f2018-12-12 15:59:31 +0800745 return mNetdService.interfaceGetList();
Luke Huang14f75442018-08-15 19:22:54 +0800746 } catch (RemoteException | ServiceSpecificException e) {
747 throw new IllegalStateException(e);
Kenny Roota80ce062010-06-01 13:23:53 -0700748 }
San Mehated4fc8a2010-01-22 12:28:36 -0800749 }
750
Lorenzo Colitticc7f1db2019-03-18 23:50:34 +0900751 /**
752 * Convert InterfaceConfiguration to InterfaceConfigurationParcel with given ifname.
753 */
754 private static InterfaceConfigurationParcel toStableParcel(InterfaceConfiguration cfg,
755 String iface) {
756 InterfaceConfigurationParcel cfgParcel = new InterfaceConfigurationParcel();
757 cfgParcel.ifName = iface;
758 String hwAddr = cfg.getHardwareAddress();
759 if (!TextUtils.isEmpty(hwAddr)) {
760 cfgParcel.hwAddr = hwAddr;
761 } else {
762 cfgParcel.hwAddr = "";
763 }
764 cfgParcel.ipv4Addr = cfg.getLinkAddress().getAddress().getHostAddress();
765 cfgParcel.prefixLength = cfg.getLinkAddress().getPrefixLength();
766 ArrayList<String> flags = new ArrayList<>();
767 for (String flag : cfg.getFlags()) {
768 flags.add(flag);
769 }
770 cfgParcel.flags = flags.toArray(new String[0]);
771
772 return cfgParcel;
773 }
774
775 /**
776 * Construct InterfaceConfiguration from InterfaceConfigurationParcel.
777 */
778 public static InterfaceConfiguration fromStableParcel(InterfaceConfigurationParcel p) {
779 InterfaceConfiguration cfg = new InterfaceConfiguration();
780 cfg.setHardwareAddress(p.hwAddr);
781
782 final InetAddress addr = NetworkUtils.numericToInetAddress(p.ipv4Addr);
783 cfg.setLinkAddress(new LinkAddress(addr, p.prefixLength));
784 for (String flag : p.flags) {
785 cfg.setFlag(flag);
786 }
787
788 return cfg;
789 }
790
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800791 @Override
792 public InterfaceConfiguration getInterfaceConfig(String iface) {
paulhu79ebe4f2019-12-06 16:45:38 +0800793 // TODO: Remove CONNECTIVITY_INTERNAL after bluetooth tethering has no longer called these
794 // APIs.
795 NetworkStack.checkNetworkStackPermissionOr(mContext, CONNECTIVITY_INTERNAL);
Luke Huang14f75442018-08-15 19:22:54 +0800796 final InterfaceConfigurationParcel result;
Kenny Roota80ce062010-06-01 13:23:53 -0700797 try {
Luke Huang14f75442018-08-15 19:22:54 +0800798 result = mNetdService.interfaceGetCfg(iface);
799 } catch (RemoteException | ServiceSpecificException e) {
800 throw new IllegalStateException(e);
Kenny Roota80ce062010-06-01 13:23:53 -0700801 }
San Mehated4fc8a2010-01-22 12:28:36 -0800802
San Mehated4fc8a2010-01-22 12:28:36 -0800803 try {
Lorenzo Colitticc7f1db2019-03-18 23:50:34 +0900804 final InterfaceConfiguration cfg = fromStableParcel(result);
Luke Huang14f75442018-08-15 19:22:54 +0800805 return cfg;
806 } catch (IllegalArgumentException iae) {
807 throw new IllegalStateException("Invalid InterfaceConfigurationParcel", iae);
San Mehated4fc8a2010-01-22 12:28:36 -0800808 }
San Mehated4fc8a2010-01-22 12:28:36 -0800809 }
810
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800811 @Override
812 public void setInterfaceConfig(String iface, InterfaceConfiguration cfg) {
paulhu79ebe4f2019-12-06 16:45:38 +0800813 // TODO: Remove CONNECTIVITY_INTERNAL after bluetooth tethering has no longer called these
814 // APIs.
815 NetworkStack.checkNetworkStackPermissionOr(mContext, CONNECTIVITY_INTERNAL);
Jeff Sharkeyddba1062011-11-29 18:37:04 -0800816 LinkAddress linkAddr = cfg.getLinkAddress();
Robert Greenwalt2d2afd12011-02-01 15:30:46 -0800817 if (linkAddr == null || linkAddr.getAddress() == null) {
818 throw new IllegalStateException("Null LinkAddress given");
Robert Greenwalted126402011-01-28 15:34:55 -0800819 }
Jeff Sharkeyba2896e2011-11-30 18:13:54 -0800820
Lorenzo Colitticc7f1db2019-03-18 23:50:34 +0900821 final InterfaceConfigurationParcel cfgParcel = toStableParcel(cfg, iface);
Jeff Sharkeyba2896e2011-11-30 18:13:54 -0800822
Kenny Roota80ce062010-06-01 13:23:53 -0700823 try {
Luke Huang14f75442018-08-15 19:22:54 +0800824 mNetdService.interfaceSetCfg(cfgParcel);
825 } catch (RemoteException | ServiceSpecificException e) {
826 throw new IllegalStateException(e);
Kenny Roota80ce062010-06-01 13:23:53 -0700827 }
San Mehat873f2142010-01-14 10:25:07 -0800828 }
829
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800830 @Override
831 public void setInterfaceDown(String iface) {
paulhu59148b72019-08-12 16:25:11 +0800832 NetworkStack.checkNetworkStackPermission(mContext);
Jeff Sharkey31c6e482011-11-18 17:09:01 -0800833 final InterfaceConfiguration ifcg = getInterfaceConfig(iface);
Jeff Sharkeyddba1062011-11-29 18:37:04 -0800834 ifcg.setInterfaceDown();
Jeff Sharkey31c6e482011-11-18 17:09:01 -0800835 setInterfaceConfig(iface, ifcg);
Irfan Sheriff7244c972011-08-05 20:40:45 -0700836 }
837
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800838 @Override
839 public void setInterfaceUp(String iface) {
paulhu59148b72019-08-12 16:25:11 +0800840 NetworkStack.checkNetworkStackPermission(mContext);
Jeff Sharkey31c6e482011-11-18 17:09:01 -0800841 final InterfaceConfiguration ifcg = getInterfaceConfig(iface);
Jeff Sharkeyddba1062011-11-29 18:37:04 -0800842 ifcg.setInterfaceUp();
Jeff Sharkey31c6e482011-11-18 17:09:01 -0800843 setInterfaceConfig(iface, ifcg);
Irfan Sheriff7244c972011-08-05 20:40:45 -0700844 }
845
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800846 @Override
847 public void setInterfaceIpv6PrivacyExtensions(String iface, boolean enable) {
paulhu59148b72019-08-12 16:25:11 +0800848 NetworkStack.checkNetworkStackPermission(mContext);
Irfan Sheriff73293612011-09-14 12:31:56 -0700849 try {
Luke Huang14f75442018-08-15 19:22:54 +0800850 mNetdService.interfaceSetIPv6PrivacyExtensions(iface, enable);
851 } catch (RemoteException | ServiceSpecificException e) {
852 throw new IllegalStateException(e);
Irfan Sheriff73293612011-09-14 12:31:56 -0700853 }
854 }
855
Irfan Sherifff5600612011-06-16 10:26:28 -0700856 /* TODO: This is right now a IPv4 only function. Works for wifi which loses its
857 IPv6 addresses on interface down, but we need to do full clean up here */
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800858 @Override
859 public void clearInterfaceAddresses(String iface) {
paulhu59148b72019-08-12 16:25:11 +0800860 NetworkStack.checkNetworkStackPermission(mContext);
Irfan Sherifff5600612011-06-16 10:26:28 -0700861 try {
Luke Huang14f75442018-08-15 19:22:54 +0800862 mNetdService.interfaceClearAddrs(iface);
863 } catch (RemoteException | ServiceSpecificException e) {
864 throw new IllegalStateException(e);
Irfan Sherifff5600612011-06-16 10:26:28 -0700865 }
866 }
867
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800868 @Override
869 public void enableIpv6(String iface) {
paulhu59148b72019-08-12 16:25:11 +0800870 NetworkStack.checkNetworkStackPermission(mContext);
repo sync7960d9f2011-09-29 12:40:02 -0700871 try {
Luke Huang14f75442018-08-15 19:22:54 +0800872 mNetdService.interfaceSetEnableIPv6(iface, true);
873 } catch (RemoteException | ServiceSpecificException e) {
874 throw new IllegalStateException(e);
repo sync7960d9f2011-09-29 12:40:02 -0700875 }
876 }
877
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800878 @Override
Joel Scherpelz2db10742017-06-07 15:38:38 +0900879 public void setIPv6AddrGenMode(String iface, int mode) throws ServiceSpecificException {
880 try {
881 mNetdService.setIPv6AddrGenMode(iface, mode);
882 } catch (RemoteException e) {
883 throw e.rethrowAsRuntimeException();
884 }
885 }
886
887 @Override
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800888 public void disableIpv6(String iface) {
paulhu59148b72019-08-12 16:25:11 +0800889 NetworkStack.checkNetworkStackPermission(mContext);
repo sync7960d9f2011-09-29 12:40:02 -0700890 try {
Luke Huang14f75442018-08-15 19:22:54 +0800891 mNetdService.interfaceSetEnableIPv6(iface, false);
892 } catch (RemoteException | ServiceSpecificException e) {
893 throw new IllegalStateException(e);
repo sync7960d9f2011-09-29 12:40:02 -0700894 }
895 }
896
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800897 @Override
Sreeram Ramachandranb2829fa2014-04-15 19:07:12 -0700898 public void addRoute(int netId, RouteInfo route) {
Luke Huang8a462ec2018-08-24 20:33:16 +0800899 modifyRoute(MODIFY_OPERATION_ADD, netId, route);
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -0700900 }
901
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800902 @Override
Sreeram Ramachandranb2829fa2014-04-15 19:07:12 -0700903 public void removeRoute(int netId, RouteInfo route) {
Luke Huang8a462ec2018-08-24 20:33:16 +0800904 modifyRoute(MODIFY_OPERATION_REMOVE, netId, route);
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -0700905 }
906
Luke Huang8a462ec2018-08-24 20:33:16 +0800907 private void modifyRoute(boolean add, int netId, RouteInfo route) {
paulhu59148b72019-08-12 16:25:11 +0800908 NetworkStack.checkNetworkStackPermission(mContext);
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -0700909
Luke Huang8a462ec2018-08-24 20:33:16 +0800910 final String ifName = route.getInterface();
911 final String dst = route.getDestination().toString();
912 final String nextHop;
Lorenzo Colitti4b0f8e62014-09-19 01:49:05 +0900913
914 switch (route.getType()) {
915 case RouteInfo.RTN_UNICAST:
916 if (route.hasGateway()) {
Luke Huang8a462ec2018-08-24 20:33:16 +0800917 nextHop = route.getGateway().getHostAddress();
918 } else {
919 nextHop = INetd.NEXTHOP_NONE;
Lorenzo Colitti4b0f8e62014-09-19 01:49:05 +0900920 }
921 break;
922 case RouteInfo.RTN_UNREACHABLE:
Luke Huang8a462ec2018-08-24 20:33:16 +0800923 nextHop = INetd.NEXTHOP_UNREACHABLE;
Lorenzo Colitti4b0f8e62014-09-19 01:49:05 +0900924 break;
925 case RouteInfo.RTN_THROW:
Luke Huang8a462ec2018-08-24 20:33:16 +0800926 nextHop = INetd.NEXTHOP_THROW;
927 break;
928 default:
929 nextHop = INetd.NEXTHOP_NONE;
Lorenzo Colitti4b0f8e62014-09-19 01:49:05 +0900930 break;
Sreeram Ramachandran1fbcb272014-05-22 16:30:48 -0700931 }
Jeff Sharkeyba2896e2011-11-30 18:13:54 -0800932 try {
Luke Huang8a462ec2018-08-24 20:33:16 +0800933 if (add) {
934 mNetdService.networkAddRoute(netId, ifName, dst, nextHop);
935 } else {
936 mNetdService.networkRemoveRoute(netId, ifName, dst, nextHop);
937 }
938 } catch (RemoteException | ServiceSpecificException e) {
939 throw new IllegalStateException(e);
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -0700940 }
941 }
942
943 private ArrayList<String> readRouteList(String filename) {
944 FileInputStream fstream = null;
Christopher Wiley212b95f2016-08-02 11:38:57 -0700945 ArrayList<String> list = new ArrayList<>();
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -0700946
947 try {
948 fstream = new FileInputStream(filename);
949 DataInputStream in = new DataInputStream(fstream);
950 BufferedReader br = new BufferedReader(new InputStreamReader(in));
951 String s;
952
953 // throw away the title line
954
955 while (((s = br.readLine()) != null) && (s.length() != 0)) {
956 list.add(s);
957 }
958 } catch (IOException ex) {
959 // return current list, possibly empty
960 } finally {
961 if (fstream != null) {
962 try {
963 fstream.close();
964 } catch (IOException ex) {}
965 }
966 }
967
968 return list;
969 }
970
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800971 @Override
sy.yun9d9b74a2013-09-02 05:24:09 +0900972 public void setMtu(String iface, int mtu) {
paulhu59148b72019-08-12 16:25:11 +0800973 NetworkStack.checkNetworkStackPermission(mContext);
sy.yun9d9b74a2013-09-02 05:24:09 +0900974
sy.yun9d9b74a2013-09-02 05:24:09 +0900975 try {
Luke Huang14f75442018-08-15 19:22:54 +0800976 mNetdService.interfaceSetMtu(iface, mtu);
977 } catch (RemoteException | ServiceSpecificException e) {
978 throw new IllegalStateException(e);
sy.yun9d9b74a2013-09-02 05:24:09 +0900979 }
980 }
981
982 @Override
San Mehat873f2142010-01-14 10:25:07 -0800983 public void shutdown() {
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800984 // TODO: remove from aidl if nobody calls externally
985 mContext.enforceCallingOrSelfPermission(SHUTDOWN, TAG);
San Mehat873f2142010-01-14 10:25:07 -0800986
Felipe Leme03e689d2016-03-02 16:17:38 -0800987 Slog.i(TAG, "Shutting down");
San Mehat873f2142010-01-14 10:25:07 -0800988 }
989
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800990 @Override
San Mehat873f2142010-01-14 10:25:07 -0800991 public boolean getIpForwardingEnabled() throws IllegalStateException{
paulhu59148b72019-08-12 16:25:11 +0800992 NetworkStack.checkNetworkStackPermission(mContext);
San Mehat873f2142010-01-14 10:25:07 -0800993
Kenny Roota80ce062010-06-01 13:23:53 -0700994 try {
Luke Huang4db488b2018-08-16 15:37:31 +0800995 final boolean isEnabled = mNetdService.ipfwdEnabled();
996 return isEnabled;
997 } catch (RemoteException | ServiceSpecificException e) {
998 throw new IllegalStateException(e);
Kenny Roota80ce062010-06-01 13:23:53 -0700999 }
San Mehat873f2142010-01-14 10:25:07 -08001000 }
1001
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001002 @Override
1003 public void setIpForwardingEnabled(boolean enable) {
paulhu59148b72019-08-12 16:25:11 +08001004 NetworkStack.checkNetworkStackPermission(mContext);
Jeff Sharkey31c6e482011-11-18 17:09:01 -08001005 try {
Luke Huang4db488b2018-08-16 15:37:31 +08001006 if (enable) {
1007 mNetdService.ipfwdEnableForwarding("tethering");
1008 } else {
1009 mNetdService.ipfwdDisableForwarding("tethering");
1010 }
1011 } catch (RemoteException | ServiceSpecificException e) {
1012 throw new IllegalStateException(e);
Jeff Sharkey31c6e482011-11-18 17:09:01 -08001013 }
San Mehat873f2142010-01-14 10:25:07 -08001014 }
1015
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001016 @Override
1017 public void startTethering(String[] dhcpRange) {
Luke Huangb0d52462019-03-21 14:43:08 +08001018 startTetheringWithConfiguration(true, dhcpRange);
1019 }
1020
1021 @Override
1022 public void startTetheringWithConfiguration(boolean usingLegacyDnsProxy, String[] dhcpRange) {
paulhu59148b72019-08-12 16:25:11 +08001023 NetworkStack.checkNetworkStackPermission(mContext);
Robert Greenwaltbfb7bfa2010-03-24 16:03:21 -07001024 // an odd number of addrs will fail
Kenny Roota80ce062010-06-01 13:23:53 -07001025 try {
Luke Huangb0d52462019-03-21 14:43:08 +08001026 mNetdService.tetherStartWithConfiguration(usingLegacyDnsProxy, dhcpRange);
Luke Huang4a32bf42018-08-21 19:09:45 +08001027 } catch (RemoteException | ServiceSpecificException e) {
1028 throw new IllegalStateException(e);
Kenny Roota80ce062010-06-01 13:23:53 -07001029 }
San Mehat873f2142010-01-14 10:25:07 -08001030 }
1031
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001032 @Override
1033 public void stopTethering() {
paulhu59148b72019-08-12 16:25:11 +08001034 NetworkStack.checkNetworkStackPermission(mContext);
Kenny Roota80ce062010-06-01 13:23:53 -07001035 try {
Luke Huang4a32bf42018-08-21 19:09:45 +08001036 mNetdService.tetherStop();
1037 } catch (RemoteException | ServiceSpecificException e) {
1038 throw new IllegalStateException(e);
Kenny Roota80ce062010-06-01 13:23:53 -07001039 }
San Mehat873f2142010-01-14 10:25:07 -08001040 }
1041
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001042 @Override
1043 public boolean isTetheringStarted() {
paulhu59148b72019-08-12 16:25:11 +08001044 NetworkStack.checkNetworkStackPermission(mContext);
San Mehat873f2142010-01-14 10:25:07 -08001045
Kenny Roota80ce062010-06-01 13:23:53 -07001046 try {
Luke Huang4a32bf42018-08-21 19:09:45 +08001047 final boolean isEnabled = mNetdService.tetherIsEnabled();
1048 return isEnabled;
1049 } catch (RemoteException | ServiceSpecificException e) {
1050 throw new IllegalStateException(e);
Kenny Roota80ce062010-06-01 13:23:53 -07001051 }
San Mehat873f2142010-01-14 10:25:07 -08001052 }
Matthew Xiefe19f122012-07-12 16:03:32 -07001053
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001054 @Override
1055 public void tetherInterface(String iface) {
paulhu59148b72019-08-12 16:25:11 +08001056 NetworkStack.checkNetworkStackPermission(mContext);
Kenny Roota80ce062010-06-01 13:23:53 -07001057 try {
Luke Huang4a32bf42018-08-21 19:09:45 +08001058 mNetdService.tetherInterfaceAdd(iface);
1059 } catch (RemoteException | ServiceSpecificException e) {
1060 throw new IllegalStateException(e);
Kenny Roota80ce062010-06-01 13:23:53 -07001061 }
Christopher Wiley212b95f2016-08-02 11:38:57 -07001062 List<RouteInfo> routes = new ArrayList<>();
Sreeram Ramachandrana77760d2014-07-17 17:09:07 -07001063 // The RouteInfo constructor truncates the LinkAddress to a network prefix, thus making it
1064 // suitable to use as a route destination.
1065 routes.add(new RouteInfo(getInterfaceConfig(iface).getLinkAddress(), null, iface));
1066 addInterfaceToLocalNetwork(iface, routes);
San Mehat873f2142010-01-14 10:25:07 -08001067 }
1068
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001069 @Override
San Mehat873f2142010-01-14 10:25:07 -08001070 public void untetherInterface(String iface) {
paulhu59148b72019-08-12 16:25:11 +08001071 NetworkStack.checkNetworkStackPermission(mContext);
Kenny Roota80ce062010-06-01 13:23:53 -07001072 try {
Luke Huang4a32bf42018-08-21 19:09:45 +08001073 mNetdService.tetherInterfaceRemove(iface);
1074 } catch (RemoteException | ServiceSpecificException e) {
1075 throw new IllegalStateException(e);
Erik Kline1f4278a2016-08-16 16:46:33 +09001076 } finally {
1077 removeInterfaceFromLocalNetwork(iface);
Kenny Roota80ce062010-06-01 13:23:53 -07001078 }
San Mehat873f2142010-01-14 10:25:07 -08001079 }
1080
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001081 @Override
1082 public String[] listTetheredInterfaces() {
paulhu59148b72019-08-12 16:25:11 +08001083 NetworkStack.checkNetworkStackPermission(mContext);
Kenny Roota80ce062010-06-01 13:23:53 -07001084 try {
Luke Huang1b4f92f2018-12-12 15:59:31 +08001085 return mNetdService.tetherInterfaceList();
Luke Huang4a32bf42018-08-21 19:09:45 +08001086 } catch (RemoteException | ServiceSpecificException e) {
1087 throw new IllegalStateException(e);
Kenny Roota80ce062010-06-01 13:23:53 -07001088 }
San Mehat873f2142010-01-14 10:25:07 -08001089 }
1090
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001091 @Override
Lorenzo Colittib57edc52014-08-22 17:10:50 -07001092 public void setDnsForwarders(Network network, String[] dns) {
paulhu59148b72019-08-12 16:25:11 +08001093 NetworkStack.checkNetworkStackPermission(mContext);
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001094
Lorenzo Colittib57edc52014-08-22 17:10:50 -07001095 int netId = (network != null) ? network.netId : ConnectivityManager.NETID_UNSET;
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001096
San Mehat873f2142010-01-14 10:25:07 -08001097 try {
Luke Huang4a32bf42018-08-21 19:09:45 +08001098 mNetdService.tetherDnsSet(netId, dns);
1099 } catch (RemoteException | ServiceSpecificException e) {
1100 throw new IllegalStateException(e);
San Mehat873f2142010-01-14 10:25:07 -08001101 }
1102 }
1103
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001104 @Override
1105 public String[] getDnsForwarders() {
paulhu59148b72019-08-12 16:25:11 +08001106 NetworkStack.checkNetworkStackPermission(mContext);
Kenny Roota80ce062010-06-01 13:23:53 -07001107 try {
Luke Huang1b4f92f2018-12-12 15:59:31 +08001108 return mNetdService.tetherDnsList();
Luke Huang4a32bf42018-08-21 19:09:45 +08001109 } catch (RemoteException | ServiceSpecificException e) {
1110 throw new IllegalStateException(e);
Kenny Roota80ce062010-06-01 13:23:53 -07001111 }
San Mehat873f2142010-01-14 10:25:07 -08001112 }
1113
jiaguo1da35f72014-01-09 16:39:59 +08001114 private List<InterfaceAddress> excludeLinkLocal(List<InterfaceAddress> addresses) {
Christopher Wiley212b95f2016-08-02 11:38:57 -07001115 ArrayList<InterfaceAddress> filtered = new ArrayList<>(addresses.size());
jiaguo1da35f72014-01-09 16:39:59 +08001116 for (InterfaceAddress ia : addresses) {
1117 if (!ia.getAddress().isLinkLocalAddress())
1118 filtered.add(ia);
1119 }
1120 return filtered;
1121 }
1122
Lorenzo Colitti35e36db2015-02-26 01:25:36 +09001123 private void modifyInterfaceForward(boolean add, String fromIface, String toIface) {
Lorenzo Colitti35e36db2015-02-26 01:25:36 +09001124 try {
Luke Huang4db488b2018-08-16 15:37:31 +08001125 if (add) {
1126 mNetdService.ipfwdAddInterfaceForward(fromIface, toIface);
1127 } else {
1128 mNetdService.ipfwdRemoveInterfaceForward(fromIface, toIface);
1129 }
1130 } catch (RemoteException | ServiceSpecificException e) {
1131 throw new IllegalStateException(e);
Lorenzo Colitti35e36db2015-02-26 01:25:36 +09001132 }
1133 }
1134
1135 @Override
1136 public void startInterfaceForwarding(String fromIface, String toIface) {
paulhu59148b72019-08-12 16:25:11 +08001137 NetworkStack.checkNetworkStackPermission(mContext);
Lorenzo Colitti35e36db2015-02-26 01:25:36 +09001138 modifyInterfaceForward(true, fromIface, toIface);
1139 }
1140
1141 @Override
1142 public void stopInterfaceForwarding(String fromIface, String toIface) {
paulhu59148b72019-08-12 16:25:11 +08001143 NetworkStack.checkNetworkStackPermission(mContext);
Lorenzo Colitti35e36db2015-02-26 01:25:36 +09001144 modifyInterfaceForward(false, fromIface, toIface);
1145 }
1146
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001147 @Override
1148 public void enableNat(String internalInterface, String externalInterface) {
paulhu59148b72019-08-12 16:25:11 +08001149 NetworkStack.checkNetworkStackPermission(mContext);
Kenny Roota80ce062010-06-01 13:23:53 -07001150 try {
Luke Huanga31e0732018-10-22 13:23:10 +09001151 mNetdService.tetherAddForward(internalInterface, externalInterface);
1152 } catch (RemoteException | ServiceSpecificException e) {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001153 throw new IllegalStateException(e);
Kenny Roota80ce062010-06-01 13:23:53 -07001154 }
San Mehat873f2142010-01-14 10:25:07 -08001155 }
1156
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001157 @Override
1158 public void disableNat(String internalInterface, String externalInterface) {
paulhu59148b72019-08-12 16:25:11 +08001159 NetworkStack.checkNetworkStackPermission(mContext);
Kenny Roota80ce062010-06-01 13:23:53 -07001160 try {
Luke Huanga31e0732018-10-22 13:23:10 +09001161 mNetdService.tetherRemoveForward(internalInterface, externalInterface);
1162 } catch (RemoteException | ServiceSpecificException e) {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001163 throw new IllegalStateException(e);
Kenny Roota80ce062010-06-01 13:23:53 -07001164 }
San Mehat873f2142010-01-14 10:25:07 -08001165 }
San Mehat72759df2010-01-19 13:50:37 -08001166
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001167 @Override
Dianne Hackborn77b987f2014-02-26 16:20:52 -08001168 public void addIdleTimer(String iface, int timeout, final int type) {
paulhu59148b72019-08-12 16:25:11 +08001169 NetworkStack.checkNetworkStackPermission(mContext);
Haoyu Bai04124232012-06-28 15:26:19 -07001170
1171 if (DBG) Slog.d(TAG, "Adding idletimer");
1172
1173 synchronized (mIdleTimerLock) {
1174 IdleTimerParams params = mActiveIdleTimers.get(iface);
1175 if (params != null) {
1176 // the interface already has idletimer, update network count
1177 params.networkCount++;
1178 return;
1179 }
1180
1181 try {
Luke Huanga62d0492018-07-27 20:08:21 +08001182 mNetdService.idletimerAddInterface(iface, timeout, Integer.toString(type));
1183 } catch (RemoteException | ServiceSpecificException e) {
1184 throw new IllegalStateException(e);
Haoyu Bai04124232012-06-28 15:26:19 -07001185 }
Dianne Hackborn77b987f2014-02-26 16:20:52 -08001186 mActiveIdleTimers.put(iface, new IdleTimerParams(timeout, type));
1187
Dianne Hackborne13c4c02014-02-11 17:18:35 -08001188 // Networks start up.
Dianne Hackborn77b987f2014-02-26 16:20:52 -08001189 if (ConnectivityManager.isNetworkTypeMobile(type)) {
1190 mNetworkActive = false;
1191 }
Remi NGUYEN VAN9ebc3fc2019-01-29 19:12:13 +09001192 mDaemonHandler.post(() -> notifyInterfaceClassActivity(type, true,
1193 SystemClock.elapsedRealtimeNanos(), -1, false));
Haoyu Bai04124232012-06-28 15:26:19 -07001194 }
1195 }
1196
1197 @Override
1198 public void removeIdleTimer(String iface) {
paulhu59148b72019-08-12 16:25:11 +08001199 NetworkStack.checkNetworkStackPermission(mContext);
Haoyu Bai04124232012-06-28 15:26:19 -07001200
1201 if (DBG) Slog.d(TAG, "Removing idletimer");
1202
1203 synchronized (mIdleTimerLock) {
Dianne Hackborn77b987f2014-02-26 16:20:52 -08001204 final IdleTimerParams params = mActiveIdleTimers.get(iface);
Haoyu Bai04124232012-06-28 15:26:19 -07001205 if (params == null || --(params.networkCount) > 0) {
1206 return;
1207 }
1208
1209 try {
Luke Huanga62d0492018-07-27 20:08:21 +08001210 mNetdService.idletimerRemoveInterface(iface,
1211 params.timeout, Integer.toString(params.type));
1212 } catch (RemoteException | ServiceSpecificException e) {
1213 throw new IllegalStateException(e);
Haoyu Bai04124232012-06-28 15:26:19 -07001214 }
1215 mActiveIdleTimers.remove(iface);
Remi NGUYEN VAN9ebc3fc2019-01-29 19:12:13 +09001216 mDaemonHandler.post(() -> notifyInterfaceClassActivity(params.type, false,
1217 SystemClock.elapsedRealtimeNanos(), -1, false));
Haoyu Bai04124232012-06-28 15:26:19 -07001218 }
1219 }
1220
1221 @Override
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001222 public void setInterfaceQuota(String iface, long quotaBytes) {
paulhu59148b72019-08-12 16:25:11 +08001223 NetworkStack.checkNetworkStackPermission(mContext);
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001224
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001225 synchronized (mQuotaLock) {
Jeff Sharkeyb24a7852012-05-01 15:19:37 -07001226 if (mActiveQuotas.containsKey(iface)) {
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001227 throw new IllegalStateException("iface " + iface + " already has quota");
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001228 }
1229
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001230 try {
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001231 // TODO: support quota shared across interfaces
Luke Huangc7bea8662018-08-07 16:04:26 +08001232 mNetdService.bandwidthSetInterfaceQuota(iface, quotaBytes);
1233
Jeff Sharkeyb24a7852012-05-01 15:19:37 -07001234 mActiveQuotas.put(iface, quotaBytes);
Luke Huangc7bea8662018-08-07 16:04:26 +08001235 } catch (RemoteException | ServiceSpecificException e) {
1236 throw new IllegalStateException(e);
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001237 }
Lorenzo Colitti50b60fc2017-08-11 13:47:49 +09001238
1239 synchronized (mTetheringStatsProviders) {
1240 for (ITetheringStatsProvider provider : mTetheringStatsProviders.keySet()) {
1241 try {
1242 provider.setInterfaceQuota(iface, quotaBytes);
1243 } catch (RemoteException e) {
1244 Log.e(TAG, "Problem setting tethering data limit on provider " +
1245 mTetheringStatsProviders.get(provider) + ": " + e);
1246 }
1247 }
1248 }
Ashish Sharma50fd36d2011-06-15 19:34:53 -07001249 }
1250 }
1251
1252 @Override
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001253 public void removeInterfaceQuota(String iface) {
paulhu59148b72019-08-12 16:25:11 +08001254 NetworkStack.checkNetworkStackPermission(mContext);
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001255
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001256 synchronized (mQuotaLock) {
Jeff Sharkeyb24a7852012-05-01 15:19:37 -07001257 if (!mActiveQuotas.containsKey(iface)) {
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001258 // TODO: eventually consider throwing
1259 return;
1260 }
1261
Jeff Sharkeyb24a7852012-05-01 15:19:37 -07001262 mActiveQuotas.remove(iface);
1263 mActiveAlerts.remove(iface);
Jeff Sharkey38ddeaa2011-11-08 13:04:22 -08001264
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001265 try {
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001266 // TODO: support quota shared across interfaces
Luke Huangc7bea8662018-08-07 16:04:26 +08001267 mNetdService.bandwidthRemoveInterfaceQuota(iface);
1268 } catch (RemoteException | ServiceSpecificException e) {
1269 throw new IllegalStateException(e);
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001270 }
Lorenzo Colitti50b60fc2017-08-11 13:47:49 +09001271
1272 synchronized (mTetheringStatsProviders) {
1273 for (ITetheringStatsProvider provider : mTetheringStatsProviders.keySet()) {
1274 try {
1275 provider.setInterfaceQuota(iface, ITetheringStatsProvider.QUOTA_UNLIMITED);
1276 } catch (RemoteException e) {
1277 Log.e(TAG, "Problem removing tethering data limit on provider " +
1278 mTetheringStatsProviders.get(provider) + ": " + e);
1279 }
1280 }
1281 }
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001282 }
1283 }
1284
1285 @Override
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001286 public void setInterfaceAlert(String iface, long alertBytes) {
paulhu59148b72019-08-12 16:25:11 +08001287 NetworkStack.checkNetworkStackPermission(mContext);
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001288
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001289 // quick sanity check
Jeff Sharkeyb24a7852012-05-01 15:19:37 -07001290 if (!mActiveQuotas.containsKey(iface)) {
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001291 throw new IllegalStateException("setting alert requires existing quota on iface");
1292 }
1293
1294 synchronized (mQuotaLock) {
Jeff Sharkeyb24a7852012-05-01 15:19:37 -07001295 if (mActiveAlerts.containsKey(iface)) {
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001296 throw new IllegalStateException("iface " + iface + " already has alert");
1297 }
1298
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001299 try {
1300 // TODO: support alert shared across interfaces
Luke Huangc7bea8662018-08-07 16:04:26 +08001301 mNetdService.bandwidthSetInterfaceAlert(iface, alertBytes);
Jeff Sharkeyb24a7852012-05-01 15:19:37 -07001302 mActiveAlerts.put(iface, alertBytes);
Luke Huangc7bea8662018-08-07 16:04:26 +08001303 } catch (RemoteException | ServiceSpecificException e) {
1304 throw new IllegalStateException(e);
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001305 }
1306 }
1307 }
1308
1309 @Override
1310 public void removeInterfaceAlert(String iface) {
paulhu59148b72019-08-12 16:25:11 +08001311 NetworkStack.checkNetworkStackPermission(mContext);
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001312
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001313 synchronized (mQuotaLock) {
Jeff Sharkeyb24a7852012-05-01 15:19:37 -07001314 if (!mActiveAlerts.containsKey(iface)) {
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001315 // TODO: eventually consider throwing
1316 return;
1317 }
1318
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001319 try {
1320 // TODO: support alert shared across interfaces
Luke Huangc7bea8662018-08-07 16:04:26 +08001321 mNetdService.bandwidthRemoveInterfaceAlert(iface);
Jeff Sharkeyb24a7852012-05-01 15:19:37 -07001322 mActiveAlerts.remove(iface);
Luke Huangc7bea8662018-08-07 16:04:26 +08001323 } catch (RemoteException | ServiceSpecificException e) {
1324 throw new IllegalStateException(e);
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001325 }
1326 }
1327 }
1328
1329 @Override
1330 public void setGlobalAlert(long alertBytes) {
paulhu59148b72019-08-12 16:25:11 +08001331 NetworkStack.checkNetworkStackPermission(mContext);
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001332
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001333 try {
Luke Huangc7bea8662018-08-07 16:04:26 +08001334 mNetdService.bandwidthSetGlobalAlert(alertBytes);
1335 } catch (RemoteException | ServiceSpecificException e) {
1336 throw new IllegalStateException(e);
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001337 }
1338 }
1339
Sudheer Shanka62f5c172017-03-17 16:25:55 -07001340 private void setUidOnMeteredNetworkList(int uid, boolean blacklist, boolean enable) {
paulhu59148b72019-08-12 16:25:11 +08001341 NetworkStack.checkNetworkStackPermission(mContext);
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001342
Jeff Sharkeyb24a7852012-05-01 15:19:37 -07001343 synchronized (mQuotaLock) {
Sudheer Shanka62f5c172017-03-17 16:25:55 -07001344 boolean oldEnable;
1345 SparseBooleanArray quotaList;
1346 synchronized (mRulesLock) {
1347 quotaList = blacklist ? mUidRejectOnMetered : mUidAllowOnMetered;
1348 oldEnable = quotaList.get(uid, false);
1349 }
Felipe Leme65be3022016-03-22 14:53:13 -07001350 if (oldEnable == enable) {
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001351 // TODO: eventually consider throwing
1352 return;
1353 }
1354
Felipe Leme29e72ea2016-09-08 13:26:55 -07001355 Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "inetd bandwidth");
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001356 try {
Luke Huangc7bea8662018-08-07 16:04:26 +08001357 if (blacklist) {
1358 if (enable) {
1359 mNetdService.bandwidthAddNaughtyApp(uid);
1360 } else {
1361 mNetdService.bandwidthRemoveNaughtyApp(uid);
1362 }
1363 } else {
1364 if (enable) {
1365 mNetdService.bandwidthAddNiceApp(uid);
1366 } else {
1367 mNetdService.bandwidthRemoveNiceApp(uid);
1368 }
1369 }
Sudheer Shanka62f5c172017-03-17 16:25:55 -07001370 synchronized (mRulesLock) {
1371 if (enable) {
1372 quotaList.put(uid, true);
1373 } else {
1374 quotaList.delete(uid);
1375 }
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001376 }
Luke Huangc7bea8662018-08-07 16:04:26 +08001377 } catch (RemoteException | ServiceSpecificException e) {
1378 throw new IllegalStateException(e);
Felipe Leme29e72ea2016-09-08 13:26:55 -07001379 } finally {
1380 Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001381 }
Ashish Sharma50fd36d2011-06-15 19:34:53 -07001382 }
1383 }
1384
Jeff Sharkey63d27a92011-08-03 17:04:22 -07001385 @Override
Felipe Leme65be3022016-03-22 14:53:13 -07001386 public void setUidMeteredNetworkBlacklist(int uid, boolean enable) {
Sudheer Shanka62f5c172017-03-17 16:25:55 -07001387 setUidOnMeteredNetworkList(uid, true, enable);
Felipe Leme65be3022016-03-22 14:53:13 -07001388 }
1389
1390 @Override
1391 public void setUidMeteredNetworkWhitelist(int uid, boolean enable) {
Sudheer Shanka62f5c172017-03-17 16:25:55 -07001392 setUidOnMeteredNetworkList(uid, false, enable);
Felipe Leme65be3022016-03-22 14:53:13 -07001393 }
1394
1395 @Override
1396 public boolean setDataSaverModeEnabled(boolean enable) {
Sehee Parka9139bc2017-12-22 13:54:05 +09001397 mContext.enforceCallingOrSelfPermission(NETWORK_SETTINGS, TAG);
1398
Felipe Leme65be3022016-03-22 14:53:13 -07001399 if (DBG) Log.d(TAG, "setDataSaverMode: " + enable);
1400 synchronized (mQuotaLock) {
1401 if (mDataSaverMode == enable) {
1402 Log.w(TAG, "setDataSaverMode(): already " + mDataSaverMode);
1403 return true;
1404 }
Felipe Leme29e72ea2016-09-08 13:26:55 -07001405 Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "bandwidthEnableDataSaver");
Felipe Leme65be3022016-03-22 14:53:13 -07001406 try {
1407 final boolean changed = mNetdService.bandwidthEnableDataSaver(enable);
1408 if (changed) {
1409 mDataSaverMode = enable;
1410 } else {
1411 Log.w(TAG, "setDataSaverMode(" + enable + "): netd command silently failed");
1412 }
1413 return changed;
1414 } catch (RemoteException e) {
1415 Log.w(TAG, "setDataSaverMode(" + enable + "): netd command failed", e);
1416 return false;
Felipe Leme29e72ea2016-09-08 13:26:55 -07001417 } finally {
1418 Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
Felipe Leme65be3022016-03-22 14:53:13 -07001419 }
1420 }
1421 }
1422
Lorenzo Colitticc7f1db2019-03-18 23:50:34 +09001423 private static UidRangeParcel makeUidRangeParcel(int start, int stop) {
1424 UidRangeParcel range = new UidRangeParcel();
1425 range.start = start;
1426 range.stop = stop;
1427 return range;
1428 }
1429
1430 private static UidRangeParcel[] toStableParcels(UidRange[] ranges) {
1431 UidRangeParcel[] stableRanges = new UidRangeParcel[ranges.length];
1432 for (int i = 0; i < ranges.length; i++) {
1433 stableRanges[i] = makeUidRangeParcel(ranges[i].start, ranges[i].stop);
1434 }
1435 return stableRanges;
1436 }
1437
Felipe Leme65be3022016-03-22 14:53:13 -07001438 @Override
Robin Lee17e61832016-05-09 13:46:28 +01001439 public void setAllowOnlyVpnForUids(boolean add, UidRange[] uidRanges)
1440 throws ServiceSpecificException {
paulhu59148b72019-08-12 16:25:11 +08001441 NetworkStack.checkNetworkStackPermission(mContext);
Robin Lee17e61832016-05-09 13:46:28 +01001442 try {
Lorenzo Colitticc7f1db2019-03-18 23:50:34 +09001443 mNetdService.networkRejectNonSecureVpn(add, toStableParcels(uidRanges));
Robin Lee17e61832016-05-09 13:46:28 +01001444 } catch (ServiceSpecificException e) {
1445 Log.w(TAG, "setAllowOnlyVpnForUids(" + add + ", " + Arrays.toString(uidRanges) + ")"
1446 + ": netd command failed", e);
1447 throw e;
1448 } catch (RemoteException e) {
1449 Log.w(TAG, "setAllowOnlyVpnForUids(" + add + ", " + Arrays.toString(uidRanges) + ")"
1450 + ": netd command failed", e);
1451 throw e.rethrowAsRuntimeException();
1452 }
1453 }
1454
Lorenzo Colitti8c253ad2017-07-19 00:23:44 +09001455 private void applyUidCleartextNetworkPolicy(int uid, int policy) {
Luke Huang473eb872018-07-26 17:33:14 +08001456 final int policyValue;
Lorenzo Colitti8c253ad2017-07-19 00:23:44 +09001457 switch (policy) {
1458 case StrictMode.NETWORK_POLICY_ACCEPT:
Luke Huang473eb872018-07-26 17:33:14 +08001459 policyValue = INetd.PENALTY_POLICY_ACCEPT;
Lorenzo Colitti8c253ad2017-07-19 00:23:44 +09001460 break;
1461 case StrictMode.NETWORK_POLICY_LOG:
Luke Huang473eb872018-07-26 17:33:14 +08001462 policyValue = INetd.PENALTY_POLICY_LOG;
Lorenzo Colitti8c253ad2017-07-19 00:23:44 +09001463 break;
1464 case StrictMode.NETWORK_POLICY_REJECT:
Luke Huang473eb872018-07-26 17:33:14 +08001465 policyValue = INetd.PENALTY_POLICY_REJECT;
Lorenzo Colitti8c253ad2017-07-19 00:23:44 +09001466 break;
1467 default:
1468 throw new IllegalArgumentException("Unknown policy " + policy);
1469 }
1470
1471 try {
Luke Huang473eb872018-07-26 17:33:14 +08001472 mNetdService.strictUidCleartextPenalty(uid, policyValue);
Lorenzo Colitti8c253ad2017-07-19 00:23:44 +09001473 mUidCleartextPolicy.put(uid, policy);
Luke Huang473eb872018-07-26 17:33:14 +08001474 } catch (RemoteException | ServiceSpecificException e) {
1475 throw new IllegalStateException(e);
Lorenzo Colitti8c253ad2017-07-19 00:23:44 +09001476 }
1477 }
1478
Robin Lee17e61832016-05-09 13:46:28 +01001479 @Override
Jeff Sharkey605eb792014-11-04 13:34:06 -08001480 public void setUidCleartextNetworkPolicy(int uid, int policy) {
1481 if (Binder.getCallingUid() != uid) {
paulhu59148b72019-08-12 16:25:11 +08001482 NetworkStack.checkNetworkStackPermission(mContext);
Jeff Sharkey605eb792014-11-04 13:34:06 -08001483 }
1484
1485 synchronized (mQuotaLock) {
1486 final int oldPolicy = mUidCleartextPolicy.get(uid, StrictMode.NETWORK_POLICY_ACCEPT);
1487 if (oldPolicy == policy) {
Lorenzo Colitti8c253ad2017-07-19 00:23:44 +09001488 // This also ensures we won't needlessly apply an ACCEPT policy if we've just
1489 // enabled strict and the underlying iptables rules are empty.
Jeff Sharkey605eb792014-11-04 13:34:06 -08001490 return;
1491 }
1492
Luke Huang473eb872018-07-26 17:33:14 +08001493 // TODO: remove this code after removing prepareNativeDaemon()
Jeff Sharkey605eb792014-11-04 13:34:06 -08001494 if (!mStrictEnabled) {
1495 // Module isn't enabled yet; stash the requested policy away to
1496 // apply later once the daemon is connected.
1497 mUidCleartextPolicy.put(uid, policy);
1498 return;
1499 }
1500
Lorenzo Colitti8c253ad2017-07-19 00:23:44 +09001501 // netd does not keep state on strict mode policies, and cannot replace a non-accept
1502 // policy without deleting it first. Rather than add state to netd, just always send
1503 // it an accept policy when switching between two non-accept policies.
Lorenzo Colitti26364f12017-08-20 11:54:57 +09001504 // TODO: consider keeping state in netd so we can simplify this code.
Lorenzo Colitti8c253ad2017-07-19 00:23:44 +09001505 if (oldPolicy != StrictMode.NETWORK_POLICY_ACCEPT &&
1506 policy != StrictMode.NETWORK_POLICY_ACCEPT) {
Lorenzo Colitti26364f12017-08-20 11:54:57 +09001507 applyUidCleartextNetworkPolicy(uid, StrictMode.NETWORK_POLICY_ACCEPT);
Jeff Sharkey605eb792014-11-04 13:34:06 -08001508 }
Lorenzo Colitti26364f12017-08-20 11:54:57 +09001509
1510 applyUidCleartextNetworkPolicy(uid, policy);
Jeff Sharkey605eb792014-11-04 13:34:06 -08001511 }
1512 }
1513
1514 @Override
Jeff Sharkey63d27a92011-08-03 17:04:22 -07001515 public boolean isBandwidthControlEnabled() {
Luke Huang56a03a02018-09-07 12:02:16 +08001516 return true;
Jeff Sharkey63d27a92011-08-03 17:04:22 -07001517 }
1518
Lorenzo Colitti07f13042017-07-10 19:06:57 +09001519 private class NetdTetheringStatsProvider extends ITetheringStatsProvider.Stub {
1520 @Override
Lorenzo Colittif1912ca2017-08-17 19:23:08 +09001521 public NetworkStats getTetherStats(int how) {
1522 // We only need to return per-UID stats. Per-device stats are already counted by
1523 // interface counters.
1524 if (how != STATS_PER_UID) {
1525 return new NetworkStats(SystemClock.elapsedRealtime(), 0);
1526 }
1527
Luke Huang13b79e82018-09-26 14:53:42 +08001528 final TetherStatsParcel[] tetherStatsVec;
Lorenzo Colitti07f13042017-07-10 19:06:57 +09001529 try {
Luke Huang13b79e82018-09-26 14:53:42 +08001530 tetherStatsVec = mNetdService.tetherGetStats();
Lorenzo Colitti563dc452017-09-01 17:12:34 +09001531 } catch (RemoteException | ServiceSpecificException e) {
1532 throw new IllegalStateException("problem parsing tethering stats: ", e);
Lorenzo Colitti07f13042017-07-10 19:06:57 +09001533 }
Jeff Sharkeye4984be2013-09-10 21:03:27 -07001534
Lorenzo Colitti563dc452017-09-01 17:12:34 +09001535 final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(),
Luke Huang13b79e82018-09-26 14:53:42 +08001536 tetherStatsVec.length);
Lorenzo Colitti563dc452017-09-01 17:12:34 +09001537 final NetworkStats.Entry entry = new NetworkStats.Entry();
1538
Luke Huang13b79e82018-09-26 14:53:42 +08001539 for (TetherStatsParcel tetherStats : tetherStatsVec) {
Jeff Sharkeye4984be2013-09-10 21:03:27 -07001540 try {
Luke Huang13b79e82018-09-26 14:53:42 +08001541 entry.iface = tetherStats.iface;
Jeff Sharkeye4984be2013-09-10 21:03:27 -07001542 entry.uid = UID_TETHERING;
1543 entry.set = SET_DEFAULT;
1544 entry.tag = TAG_NONE;
Luke Huang13b79e82018-09-26 14:53:42 +08001545 entry.rxBytes = tetherStats.rxBytes;
1546 entry.rxPackets = tetherStats.rxPackets;
1547 entry.txBytes = tetherStats.txBytes;
1548 entry.txPackets = tetherStats.txPackets;
Jeff Sharkeye4984be2013-09-10 21:03:27 -07001549 stats.combineValues(entry);
Lorenzo Colitti563dc452017-09-01 17:12:34 +09001550 } catch (ArrayIndexOutOfBoundsException e) {
Luke Huang13b79e82018-09-26 14:53:42 +08001551 throw new IllegalStateException("invalid tethering stats " + e);
Jeff Sharkeye4984be2013-09-10 21:03:27 -07001552 }
1553 }
Lorenzo Colitti563dc452017-09-01 17:12:34 +09001554
Lorenzo Colitti07f13042017-07-10 19:06:57 +09001555 return stats;
1556 }
Lorenzo Colitti50b60fc2017-08-11 13:47:49 +09001557
1558 @Override
1559 public void setInterfaceQuota(String iface, long quotaBytes) {
1560 // Do nothing. netd is already informed of quota changes in setInterfaceQuota.
1561 }
Lorenzo Colitti07f13042017-07-10 19:06:57 +09001562 }
1563
1564 @Override
Lorenzo Colittif1912ca2017-08-17 19:23:08 +09001565 public NetworkStats getNetworkStatsTethering(int how) {
paulhu59148b72019-08-12 16:25:11 +08001566 NetworkStack.checkNetworkStackPermission(mContext);
Lorenzo Colitti07f13042017-07-10 19:06:57 +09001567
1568 final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 1);
1569 synchronized (mTetheringStatsProviders) {
1570 for (ITetheringStatsProvider provider: mTetheringStatsProviders.keySet()) {
1571 try {
Lorenzo Colittif1912ca2017-08-17 19:23:08 +09001572 stats.combineAllValues(provider.getTetherStats(how));
Lorenzo Colitti07f13042017-07-10 19:06:57 +09001573 } catch (RemoteException e) {
1574 Log.e(TAG, "Problem reading tethering stats from " +
1575 mTetheringStatsProviders.get(provider) + ": " + e);
1576 }
1577 }
Jeff Sharkeycdd02c5d2011-09-16 01:52:49 -07001578 }
Jeff Sharkeye4984be2013-09-10 21:03:27 -07001579 return stats;
Jeff Sharkeycdd02c5d2011-09-16 01:52:49 -07001580 }
1581
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001582 @Override
Paul Jensen6bc2c2c2014-05-07 15:27:40 -04001583 public void addVpnUidRanges(int netId, UidRange[] ranges) {
paulhu59148b72019-08-12 16:25:11 +08001584 NetworkStack.checkNetworkStackPermission(mContext);
Luke Huang8a462ec2018-08-24 20:33:16 +08001585
1586 try {
Lorenzo Colitticc7f1db2019-03-18 23:50:34 +09001587 mNetdService.networkAddUidRanges(netId, toStableParcels(ranges));
Luke Huang8a462ec2018-08-24 20:33:16 +08001588 } catch (RemoteException | ServiceSpecificException e) {
1589 throw new IllegalStateException(e);
Chad Brubaker3277620a2013-06-12 13:37:30 -07001590 }
1591 }
1592
1593 @Override
Paul Jensen6bc2c2c2014-05-07 15:27:40 -04001594 public void removeVpnUidRanges(int netId, UidRange[] ranges) {
paulhu59148b72019-08-12 16:25:11 +08001595 NetworkStack.checkNetworkStackPermission(mContext);
Luke Huang8a462ec2018-08-24 20:33:16 +08001596 try {
Lorenzo Colitticc7f1db2019-03-18 23:50:34 +09001597 mNetdService.networkRemoveUidRanges(netId, toStableParcels(ranges));
Luke Huang8a462ec2018-08-24 20:33:16 +08001598 } catch (RemoteException | ServiceSpecificException e) {
1599 throw new IllegalStateException(e);
Chad Brubakercca54c42013-06-27 17:41:38 -07001600 }
1601 }
1602
1603 @Override
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -07001604 public void setFirewallEnabled(boolean enabled) {
Jeff Sharkeyf56e2432012-09-06 17:54:29 -07001605 enforceSystemUid();
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -07001606 try {
Luke Huanga241db92018-07-31 20:15:24 +08001607 mNetdService.firewallSetFirewallType(
1608 enabled ? INetd.FIREWALL_WHITELIST : INetd.FIREWALL_BLACKLIST);
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -07001609 mFirewallEnabled = enabled;
Luke Huanga241db92018-07-31 20:15:24 +08001610 } catch (RemoteException | ServiceSpecificException e) {
1611 throw new IllegalStateException(e);
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -07001612 }
1613 }
1614
1615 @Override
1616 public boolean isFirewallEnabled() {
Jeff Sharkeyf56e2432012-09-06 17:54:29 -07001617 enforceSystemUid();
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -07001618 return mFirewallEnabled;
1619 }
1620
1621 @Override
Jeff Sharkey2c092982012-08-24 11:44:40 -07001622 public void setFirewallInterfaceRule(String iface, boolean allow) {
Jeff Sharkeyf56e2432012-09-06 17:54:29 -07001623 enforceSystemUid();
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -07001624 Preconditions.checkState(mFirewallEnabled);
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -07001625 try {
Luke Huanga241db92018-07-31 20:15:24 +08001626 mNetdService.firewallSetInterfaceRule(iface,
1627 allow ? INetd.FIREWALL_RULE_ALLOW : INetd.FIREWALL_RULE_DENY);
1628 } catch (RemoteException | ServiceSpecificException e) {
1629 throw new IllegalStateException(e);
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -07001630 }
1631 }
1632
Lorenzo Colitti3fef7232016-04-29 18:00:03 +09001633 private void closeSocketsForFirewallChainLocked(int chain, String chainName) {
Lorenzo Colitti4cb42402016-04-24 12:52:00 +09001634 // UID ranges to close sockets on.
Lorenzo Colitticc7f1db2019-03-18 23:50:34 +09001635 UidRangeParcel[] ranges;
Lorenzo Colitti4cb42402016-04-24 12:52:00 +09001636 // UID ranges whose sockets we won't touch.
1637 int[] exemptUids;
1638
Lorenzo Colitti4cb42402016-04-24 12:52:00 +09001639 int numUids = 0;
Luke Huanga241db92018-07-31 20:15:24 +08001640 if (DBG) Slog.d(TAG, "Closing sockets after enabling chain " + chainName);
Remi NGUYEN VANf9a8c2e2019-02-13 18:28:35 +09001641 if (getFirewallType(chain) == FIREWALL_WHITELIST) {
Lorenzo Colitti4cb42402016-04-24 12:52:00 +09001642 // Close all sockets on all non-system UIDs...
Lorenzo Colitticc7f1db2019-03-18 23:50:34 +09001643 ranges = new UidRangeParcel[] {
Lorenzo Colitti4cb42402016-04-24 12:52:00 +09001644 // TODO: is there a better way of finding all existing users? If so, we could
1645 // specify their ranges here.
Lorenzo Colitticc7f1db2019-03-18 23:50:34 +09001646 makeUidRangeParcel(Process.FIRST_APPLICATION_UID, Integer.MAX_VALUE),
Lorenzo Colitti4cb42402016-04-24 12:52:00 +09001647 };
1648 // ... except for the UIDs that have allow rules.
Sudheer Shanka62f5c172017-03-17 16:25:55 -07001649 synchronized (mRulesLock) {
1650 final SparseIntArray rules = getUidFirewallRulesLR(chain);
1651 exemptUids = new int[rules.size()];
1652 for (int i = 0; i < exemptUids.length; i++) {
Remi NGUYEN VANf9a8c2e2019-02-13 18:28:35 +09001653 if (rules.valueAt(i) == FIREWALL_RULE_ALLOW) {
Sudheer Shanka62f5c172017-03-17 16:25:55 -07001654 exemptUids[numUids] = rules.keyAt(i);
1655 numUids++;
1656 }
Lorenzo Colitti4cb42402016-04-24 12:52:00 +09001657 }
1658 }
1659 // Normally, whitelist chains only contain deny rules, so numUids == exemptUids.length.
1660 // But the code does not guarantee this in any way, and at least in one case - if we add
1661 // a UID rule to the firewall, and then disable the firewall - the chains can contain
1662 // the wrong type of rule. In this case, don't close connections that we shouldn't.
1663 //
1664 // TODO: tighten up this code by ensuring we never set the wrong type of rule, and
1665 // fix setFirewallEnabled to grab mQuotaLock and clear rules.
1666 if (numUids != exemptUids.length) {
1667 exemptUids = Arrays.copyOf(exemptUids, numUids);
1668 }
1669 } else {
1670 // Close sockets for every UID that has a deny rule...
Sudheer Shanka62f5c172017-03-17 16:25:55 -07001671 synchronized (mRulesLock) {
1672 final SparseIntArray rules = getUidFirewallRulesLR(chain);
Lorenzo Colitticc7f1db2019-03-18 23:50:34 +09001673 ranges = new UidRangeParcel[rules.size()];
Sudheer Shanka62f5c172017-03-17 16:25:55 -07001674 for (int i = 0; i < ranges.length; i++) {
Remi NGUYEN VANf9a8c2e2019-02-13 18:28:35 +09001675 if (rules.valueAt(i) == FIREWALL_RULE_DENY) {
Sudheer Shanka62f5c172017-03-17 16:25:55 -07001676 int uid = rules.keyAt(i);
Lorenzo Colitticc7f1db2019-03-18 23:50:34 +09001677 ranges[numUids] = makeUidRangeParcel(uid, uid);
Sudheer Shanka62f5c172017-03-17 16:25:55 -07001678 numUids++;
1679 }
Lorenzo Colitti4cb42402016-04-24 12:52:00 +09001680 }
1681 }
1682 // As above; usually numUids == ranges.length, but not always.
1683 if (numUids != ranges.length) {
1684 ranges = Arrays.copyOf(ranges, numUids);
1685 }
1686 // ... with no exceptions.
1687 exemptUids = new int[0];
1688 }
1689
1690 try {
1691 mNetdService.socketDestroy(ranges, exemptUids);
1692 } catch(RemoteException | ServiceSpecificException e) {
1693 Slog.e(TAG, "Error closing sockets after enabling chain " + chainName + ": " + e);
1694 }
1695 }
1696
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -07001697 @Override
Xiaohui Chenb41c9f72015-06-17 15:55:37 -07001698 public void setFirewallChainEnabled(int chain, boolean enable) {
Jeff Sharkeyf56e2432012-09-06 17:54:29 -07001699 enforceSystemUid();
Xiaohui Chen8dca36d2015-06-19 12:44:59 -07001700 synchronized (mQuotaLock) {
Sudheer Shanka62f5c172017-03-17 16:25:55 -07001701 synchronized (mRulesLock) {
1702 if (getFirewallChainState(chain) == enable) {
1703 // All is the same, nothing to do. This relies on the fact that netd has child
1704 // chains default detached.
1705 return;
1706 }
1707 setFirewallChainState(chain, enable);
Xiaohui Chenb41c9f72015-06-17 15:55:37 -07001708 }
Xiaohui Chen8dca36d2015-06-19 12:44:59 -07001709
Luke Huang615e1022018-10-25 11:54:05 +09001710 final String chainName = getFirewallChainName(chain);
Luke Huanga241db92018-07-31 20:15:24 +08001711 if (chain == FIREWALL_CHAIN_NONE) {
Luke Huang615e1022018-10-25 11:54:05 +09001712 throw new IllegalArgumentException("Bad child chain: " + chainName);
Lorenzo Colitti4cb42402016-04-24 12:52:00 +09001713 }
1714
Xiaohui Chen8dca36d2015-06-19 12:44:59 -07001715 try {
Luke Huanga241db92018-07-31 20:15:24 +08001716 mNetdService.firewallEnableChildChain(chain, enable);
1717 } catch (RemoteException | ServiceSpecificException e) {
1718 throw new IllegalStateException(e);
Xiaohui Chen8dca36d2015-06-19 12:44:59 -07001719 }
Lorenzo Colitti4cb42402016-04-24 12:52:00 +09001720
1721 // Close any sockets that were opened by the affected UIDs. This has to be done after
1722 // disabling network connectivity, in case they react to the socket close by reopening
1723 // the connection and race with the iptables commands that enable the firewall. All
1724 // whitelist and blacklist chains allow RSTs through.
1725 if (enable) {
Luke Huang615e1022018-10-25 11:54:05 +09001726 closeSocketsForFirewallChainLocked(chain, chainName);
Lorenzo Colitti4cb42402016-04-24 12:52:00 +09001727 }
Amith Yamasani15e472352015-04-24 19:06:07 -07001728 }
Xiaohui Chenb41c9f72015-06-17 15:55:37 -07001729 }
1730
Luke Huanga241db92018-07-31 20:15:24 +08001731 private String getFirewallChainName(int chain) {
1732 switch (chain) {
1733 case FIREWALL_CHAIN_STANDBY:
1734 return FIREWALL_CHAIN_NAME_STANDBY;
1735 case FIREWALL_CHAIN_DOZABLE:
1736 return FIREWALL_CHAIN_NAME_DOZABLE;
1737 case FIREWALL_CHAIN_POWERSAVE:
1738 return FIREWALL_CHAIN_NAME_POWERSAVE;
1739 default:
1740 throw new IllegalArgumentException("Bad child chain: " + chain);
1741 }
1742 }
1743
Xiaohui Chenb41c9f72015-06-17 15:55:37 -07001744 private int getFirewallType(int chain) {
1745 switch (chain) {
1746 case FIREWALL_CHAIN_STANDBY:
Remi NGUYEN VANf9a8c2e2019-02-13 18:28:35 +09001747 return FIREWALL_BLACKLIST;
Xiaohui Chenb41c9f72015-06-17 15:55:37 -07001748 case FIREWALL_CHAIN_DOZABLE:
Remi NGUYEN VANf9a8c2e2019-02-13 18:28:35 +09001749 return FIREWALL_WHITELIST;
Felipe Leme011b98f2016-02-10 17:28:31 -08001750 case FIREWALL_CHAIN_POWERSAVE:
Remi NGUYEN VANf9a8c2e2019-02-13 18:28:35 +09001751 return FIREWALL_WHITELIST;
Xiaohui Chenb41c9f72015-06-17 15:55:37 -07001752 default:
Remi NGUYEN VANf9a8c2e2019-02-13 18:28:35 +09001753 return isFirewallEnabled() ? FIREWALL_WHITELIST : FIREWALL_BLACKLIST;
Xiaohui Chenb41c9f72015-06-17 15:55:37 -07001754 }
1755 }
1756
1757 @Override
1758 public void setFirewallUidRules(int chain, int[] uids, int[] rules) {
1759 enforceSystemUid();
Xiaohui Chen8dca36d2015-06-19 12:44:59 -07001760 synchronized (mQuotaLock) {
Sudheer Shanka62f5c172017-03-17 16:25:55 -07001761 synchronized (mRulesLock) {
1762 SparseIntArray uidFirewallRules = getUidFirewallRulesLR(chain);
1763 SparseIntArray newRules = new SparseIntArray();
1764 // apply new set of rules
1765 for (int index = uids.length - 1; index >= 0; --index) {
1766 int uid = uids[index];
1767 int rule = rules[index];
1768 updateFirewallUidRuleLocked(chain, uid, rule);
1769 newRules.put(uid, rule);
Xiaohui Chen8dca36d2015-06-19 12:44:59 -07001770 }
Sudheer Shanka62f5c172017-03-17 16:25:55 -07001771 // collect the rules to remove.
1772 SparseIntArray rulesToRemove = new SparseIntArray();
1773 for (int index = uidFirewallRules.size() - 1; index >= 0; --index) {
1774 int uid = uidFirewallRules.keyAt(index);
1775 if (newRules.indexOfKey(uid) < 0) {
1776 rulesToRemove.put(uid, FIREWALL_RULE_DEFAULT);
1777 }
1778 }
1779 // remove dead rules
1780 for (int index = rulesToRemove.size() - 1; index >= 0; --index) {
1781 int uid = rulesToRemove.keyAt(index);
1782 updateFirewallUidRuleLocked(chain, uid, FIREWALL_RULE_DEFAULT);
1783 }
Felipe Lemea701cad2016-05-12 09:58:14 -07001784 }
1785 try {
1786 switch (chain) {
1787 case FIREWALL_CHAIN_DOZABLE:
1788 mNetdService.firewallReplaceUidChain("fw_dozable", true, uids);
1789 break;
1790 case FIREWALL_CHAIN_STANDBY:
1791 mNetdService.firewallReplaceUidChain("fw_standby", false, uids);
1792 break;
1793 case FIREWALL_CHAIN_POWERSAVE:
1794 mNetdService.firewallReplaceUidChain("fw_powersave", true, uids);
1795 break;
1796 case FIREWALL_CHAIN_NONE:
1797 default:
1798 Slog.d(TAG, "setFirewallUidRules() called on invalid chain: " + chain);
1799 }
1800 } catch (RemoteException e) {
1801 Slog.w(TAG, "Error flushing firewall chain " + chain, e);
Xiaohui Chen8dca36d2015-06-19 12:44:59 -07001802 }
Xiaohui Chenb41c9f72015-06-17 15:55:37 -07001803 }
1804 }
1805
1806 @Override
1807 public void setFirewallUidRule(int chain, int uid, int rule) {
1808 enforceSystemUid();
Felipe Lemea701cad2016-05-12 09:58:14 -07001809 synchronized (mQuotaLock) {
1810 setFirewallUidRuleLocked(chain, uid, rule);
1811 }
Xiaohui Chenb41c9f72015-06-17 15:55:37 -07001812 }
1813
Felipe Lemea701cad2016-05-12 09:58:14 -07001814 private void setFirewallUidRuleLocked(int chain, int uid, int rule) {
1815 if (updateFirewallUidRuleLocked(chain, uid, rule)) {
Luke Huanga241db92018-07-31 20:15:24 +08001816 final int ruleType = getFirewallRuleType(chain, rule);
Amith Yamasani15e472352015-04-24 19:06:07 -07001817 try {
Luke Huanga241db92018-07-31 20:15:24 +08001818 mNetdService.firewallSetUidRule(chain, uid, ruleType);
1819 } catch (RemoteException | ServiceSpecificException e) {
1820 throw new IllegalStateException(e);
Amith Yamasani15e472352015-04-24 19:06:07 -07001821 }
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -07001822 }
1823 }
1824
Felipe Lemea701cad2016-05-12 09:58:14 -07001825 // TODO: now that netd supports batching, NMS should not keep these data structures anymore...
1826 private boolean updateFirewallUidRuleLocked(int chain, int uid, int rule) {
Sudheer Shanka62f5c172017-03-17 16:25:55 -07001827 synchronized (mRulesLock) {
1828 SparseIntArray uidFirewallRules = getUidFirewallRulesLR(chain);
Felipe Lemea701cad2016-05-12 09:58:14 -07001829
Sudheer Shanka62f5c172017-03-17 16:25:55 -07001830 final int oldUidFirewallRule = uidFirewallRules.get(uid, FIREWALL_RULE_DEFAULT);
1831 if (DBG) {
1832 Slog.d(TAG, "oldRule = " + oldUidFirewallRule
1833 + ", newRule=" + rule + " for uid=" + uid + " on chain " + chain);
1834 }
1835 if (oldUidFirewallRule == rule) {
1836 if (DBG) Slog.d(TAG, "!!!!! Skipping change");
1837 // TODO: eventually consider throwing
1838 return false;
1839 }
Felipe Lemea701cad2016-05-12 09:58:14 -07001840
Sudheer Shanka62f5c172017-03-17 16:25:55 -07001841 String ruleName = getFirewallRuleName(chain, rule);
1842 String oldRuleName = getFirewallRuleName(chain, oldUidFirewallRule);
Felipe Lemea701cad2016-05-12 09:58:14 -07001843
Sudheer Shanka62f5c172017-03-17 16:25:55 -07001844 if (rule == NetworkPolicyManager.FIREWALL_RULE_DEFAULT) {
1845 uidFirewallRules.delete(uid);
1846 } else {
1847 uidFirewallRules.put(uid, rule);
1848 }
1849 return !ruleName.equals(oldRuleName);
Felipe Lemea701cad2016-05-12 09:58:14 -07001850 }
Felipe Lemea701cad2016-05-12 09:58:14 -07001851 }
1852
Xiaohui Chen8dca36d2015-06-19 12:44:59 -07001853 private @NonNull String getFirewallRuleName(int chain, int rule) {
1854 String ruleName;
Remi NGUYEN VANf9a8c2e2019-02-13 18:28:35 +09001855 if (getFirewallType(chain) == FIREWALL_WHITELIST) {
1856 if (rule == FIREWALL_RULE_ALLOW) {
Xiaohui Chen8dca36d2015-06-19 12:44:59 -07001857 ruleName = "allow";
1858 } else {
1859 ruleName = "deny";
1860 }
1861 } else { // Blacklist mode
Remi NGUYEN VANf9a8c2e2019-02-13 18:28:35 +09001862 if (rule == FIREWALL_RULE_DENY) {
Xiaohui Chen8dca36d2015-06-19 12:44:59 -07001863 ruleName = "deny";
1864 } else {
1865 ruleName = "allow";
1866 }
1867 }
1868 return ruleName;
1869 }
1870
Andreas Gampeaae5aa32018-07-20 12:55:38 -07001871 @GuardedBy("mRulesLock")
Sudheer Shanka62f5c172017-03-17 16:25:55 -07001872 private @NonNull SparseIntArray getUidFirewallRulesLR(int chain) {
Xiaohui Chenb41c9f72015-06-17 15:55:37 -07001873 switch (chain) {
1874 case FIREWALL_CHAIN_STANDBY:
1875 return mUidFirewallStandbyRules;
1876 case FIREWALL_CHAIN_DOZABLE:
1877 return mUidFirewallDozableRules;
Felipe Leme011b98f2016-02-10 17:28:31 -08001878 case FIREWALL_CHAIN_POWERSAVE:
1879 return mUidFirewallPowerSaveRules;
Xiaohui Chenb41c9f72015-06-17 15:55:37 -07001880 case FIREWALL_CHAIN_NONE:
1881 return mUidFirewallRules;
1882 default:
1883 throw new IllegalArgumentException("Unknown chain:" + chain);
1884 }
1885 }
1886
Luke Huanga241db92018-07-31 20:15:24 +08001887 private int getFirewallRuleType(int chain, int rule) {
Luke Huang615e1022018-10-25 11:54:05 +09001888 if (rule == NetworkPolicyManager.FIREWALL_RULE_DEFAULT) {
Remi NGUYEN VANf9a8c2e2019-02-13 18:28:35 +09001889 return getFirewallType(chain) == FIREWALL_WHITELIST
Luke Huang615e1022018-10-25 11:54:05 +09001890 ? INetd.FIREWALL_RULE_DENY : INetd.FIREWALL_RULE_ALLOW;
Xiaohui Chenb41c9f72015-06-17 15:55:37 -07001891 }
Luke Huang615e1022018-10-25 11:54:05 +09001892 return rule;
Xiaohui Chenb41c9f72015-06-17 15:55:37 -07001893 }
1894
Jeff Sharkeyf56e2432012-09-06 17:54:29 -07001895 private static void enforceSystemUid() {
1896 final int uid = Binder.getCallingUid();
1897 if (uid != Process.SYSTEM_UID) {
1898 throw new SecurityException("Only available to AID_SYSTEM");
1899 }
1900 }
1901
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -07001902 @Override
Dianne Hackborn77b987f2014-02-26 16:20:52 -08001903 public void registerNetworkActivityListener(INetworkActivityListener listener) {
1904 mNetworkActivityListeners.register(listener);
1905 }
1906
1907 @Override
1908 public void unregisterNetworkActivityListener(INetworkActivityListener listener) {
1909 mNetworkActivityListeners.unregister(listener);
1910 }
1911
1912 @Override
1913 public boolean isNetworkActive() {
1914 synchronized (mNetworkActivityListeners) {
1915 return mNetworkActive || mActiveIdleTimers.isEmpty();
1916 }
1917 }
1918
1919 private void reportNetworkActive() {
1920 final int length = mNetworkActivityListeners.beginBroadcast();
Robert Greenwalt2c9f5472014-04-21 14:50:28 -07001921 try {
1922 for (int i = 0; i < length; i++) {
1923 try {
1924 mNetworkActivityListeners.getBroadcastItem(i).onNetworkActive();
Felipe Leme03e689d2016-03-02 16:17:38 -08001925 } catch (RemoteException | RuntimeException e) {
Robert Greenwalt2c9f5472014-04-21 14:50:28 -07001926 }
Dianne Hackborn77b987f2014-02-26 16:20:52 -08001927 }
Robert Greenwalt2c9f5472014-04-21 14:50:28 -07001928 } finally {
1929 mNetworkActivityListeners.finishBroadcast();
Dianne Hackborn77b987f2014-02-26 16:20:52 -08001930 }
Dianne Hackborn77b987f2014-02-26 16:20:52 -08001931 }
1932
Jeff Sharkey47eb1022011-08-25 17:48:52 -07001933 @Override
1934 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -06001935 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
Jeff Sharkey47eb1022011-08-25 17:48:52 -07001936
Dianne Hackborn2ffa11e2014-04-21 15:56:18 -07001937 pw.print("mMobileActivityFromRadio="); pw.print(mMobileActivityFromRadio);
1938 pw.print(" mLastPowerStateFromRadio="); pw.println(mLastPowerStateFromRadio);
1939 pw.print("mNetworkActive="); pw.println(mNetworkActive);
Jeff Sharkey47eb1022011-08-25 17:48:52 -07001940
1941 synchronized (mQuotaLock) {
Jeff Sharkeyb24a7852012-05-01 15:19:37 -07001942 pw.print("Active quota ifaces: "); pw.println(mActiveQuotas.toString());
1943 pw.print("Active alert ifaces: "); pw.println(mActiveAlerts.toString());
Felipe Leme65be3022016-03-22 14:53:13 -07001944 pw.print("Data saver mode: "); pw.println(mDataSaverMode);
Sudheer Shanka62f5c172017-03-17 16:25:55 -07001945 synchronized (mRulesLock) {
1946 dumpUidRuleOnQuotaLocked(pw, "blacklist", mUidRejectOnMetered);
1947 dumpUidRuleOnQuotaLocked(pw, "whitelist", mUidAllowOnMetered);
1948 }
Jeff Sharkey47eb1022011-08-25 17:48:52 -07001949 }
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -07001950
Sudheer Shanka62f5c172017-03-17 16:25:55 -07001951 synchronized (mRulesLock) {
Felipe Leme011b98f2016-02-10 17:28:31 -08001952 dumpUidFirewallRule(pw, "", mUidFirewallRules);
Amith Yamasani15e472352015-04-24 19:06:07 -07001953
Sudheer Shanka62f5c172017-03-17 16:25:55 -07001954 pw.print("UID firewall standby chain enabled: "); pw.println(
1955 getFirewallChainState(FIREWALL_CHAIN_STANDBY));
Felipe Leme011b98f2016-02-10 17:28:31 -08001956 dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_STANDBY, mUidFirewallStandbyRules);
Xiaohui Chenb41c9f72015-06-17 15:55:37 -07001957
Sudheer Shanka62f5c172017-03-17 16:25:55 -07001958 pw.print("UID firewall dozable chain enabled: "); pw.println(
1959 getFirewallChainState(FIREWALL_CHAIN_DOZABLE));
Felipe Leme011b98f2016-02-10 17:28:31 -08001960 dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_DOZABLE, mUidFirewallDozableRules);
Felipe Leme011b98f2016-02-10 17:28:31 -08001961
Sudheer Shanka62f5c172017-03-17 16:25:55 -07001962 pw.println("UID firewall powersave chain enabled: " +
1963 getFirewallChainState(FIREWALL_CHAIN_POWERSAVE));
Felipe Leme011b98f2016-02-10 17:28:31 -08001964 dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_POWERSAVE, mUidFirewallPowerSaveRules);
Xiaohui Chenb41c9f72015-06-17 15:55:37 -07001965 }
1966
Dianne Hackborn77b987f2014-02-26 16:20:52 -08001967 synchronized (mIdleTimerLock) {
1968 pw.println("Idle timers:");
1969 for (HashMap.Entry<String, IdleTimerParams> ent : mActiveIdleTimers.entrySet()) {
1970 pw.print(" "); pw.print(ent.getKey()); pw.println(":");
1971 IdleTimerParams params = ent.getValue();
1972 pw.print(" timeout="); pw.print(params.timeout);
1973 pw.print(" type="); pw.print(params.type);
1974 pw.print(" networkCount="); pw.println(params.networkCount);
1975 }
1976 }
1977
Jeff Sharkeyc268f0b2012-08-24 10:25:31 -07001978 pw.print("Firewall enabled: "); pw.println(mFirewallEnabled);
Felipe Leme65be3022016-03-22 14:53:13 -07001979 pw.print("Netd service status: " );
1980 if (mNetdService == null) {
1981 pw.println("disconnected");
1982 } else {
1983 try {
1984 final boolean alive = mNetdService.isAlive();
1985 pw.println(alive ? "alive": "dead");
1986 } catch (RemoteException e) {
1987 pw.println("unreachable");
1988 }
1989 }
1990 }
1991
1992 private void dumpUidRuleOnQuotaLocked(PrintWriter pw, String name, SparseBooleanArray list) {
1993 pw.print("UID bandwith control ");
1994 pw.print(name);
1995 pw.print(" rule: [");
1996 final int size = list.size();
1997 for (int i = 0; i < size; i++) {
1998 pw.print(list.keyAt(i));
1999 if (i < size - 1) pw.print(",");
2000 }
2001 pw.println("]");
Jeff Sharkey47eb1022011-08-25 17:48:52 -07002002 }
Robert Greenwalt9ba9c582014-03-19 17:56:12 -07002003
Felipe Leme011b98f2016-02-10 17:28:31 -08002004 private void dumpUidFirewallRule(PrintWriter pw, String name, SparseIntArray rules) {
Lorenzo Colitti4cb42402016-04-24 12:52:00 +09002005 pw.print("UID firewall ");
Felipe Leme011b98f2016-02-10 17:28:31 -08002006 pw.print(name);
2007 pw.print(" rule: [");
2008 final int size = rules.size();
2009 for (int i = 0; i < size; i++) {
2010 pw.print(rules.keyAt(i));
2011 pw.print(":");
2012 pw.print(rules.valueAt(i));
2013 if (i < size - 1) pw.print(",");
2014 }
2015 pw.println("]");
2016 }
2017
Robert Greenwalt568891d2014-04-04 13:38:00 -07002018 @Override
Paul Jensen992f2522014-04-28 10:33:11 -04002019 public void addInterfaceToNetwork(String iface, int netId) {
Luke Huang8a462ec2018-08-24 20:33:16 +08002020 modifyInterfaceInNetwork(MODIFY_OPERATION_ADD, netId, iface);
Paul Jensen992f2522014-04-28 10:33:11 -04002021 }
2022
2023 @Override
2024 public void removeInterfaceFromNetwork(String iface, int netId) {
Luke Huang8a462ec2018-08-24 20:33:16 +08002025 modifyInterfaceInNetwork(MODIFY_OPERATION_REMOVE, netId, iface);
Sreeram Ramachandrana77760d2014-07-17 17:09:07 -07002026 }
Paul Jensen992f2522014-04-28 10:33:11 -04002027
Luke Huang8a462ec2018-08-24 20:33:16 +08002028 private void modifyInterfaceInNetwork(boolean add, int netId, String iface) {
paulhu59148b72019-08-12 16:25:11 +08002029 NetworkStack.checkNetworkStackPermission(mContext);
Paul Jensen992f2522014-04-28 10:33:11 -04002030 try {
Luke Huang8a462ec2018-08-24 20:33:16 +08002031 if (add) {
2032 mNetdService.networkAddInterface(netId, iface);
2033 } else {
2034 mNetdService.networkRemoveInterface(netId, iface);
2035 }
2036 } catch (RemoteException | ServiceSpecificException e) {
2037 throw new IllegalStateException(e);
Paul Jensen992f2522014-04-28 10:33:11 -04002038 }
2039 }
2040
2041 @Override
Robert Greenwalt913c8952014-04-07 17:36:35 -07002042 public void addLegacyRouteForNetId(int netId, RouteInfo routeInfo, int uid) {
paulhu59148b72019-08-12 16:25:11 +08002043 NetworkStack.checkNetworkStackPermission(mContext);
Robert Greenwalt568891d2014-04-04 13:38:00 -07002044
Sreeram Ramachandrancc91c7b2014-06-03 18:41:43 -07002045 final LinkAddress la = routeInfo.getDestinationLinkAddress();
Luke Huang8a462ec2018-08-24 20:33:16 +08002046 final String ifName = routeInfo.getInterface();
2047 final String dst = la.toString();
2048 final String nextHop;
Robert Greenwalt568891d2014-04-04 13:38:00 -07002049
Luke Huang8a462ec2018-08-24 20:33:16 +08002050 if (routeInfo.hasGateway()) {
2051 nextHop = routeInfo.getGateway().getHostAddress();
2052 } else {
2053 nextHop = "";
2054 }
Robert Greenwalt568891d2014-04-04 13:38:00 -07002055 try {
Luke Huang8a462ec2018-08-24 20:33:16 +08002056 mNetdService.networkAddLegacyRoute(netId, ifName, dst, nextHop, uid);
2057 } catch (RemoteException | ServiceSpecificException e) {
2058 throw new IllegalStateException(e);
Robert Greenwalt568891d2014-04-04 13:38:00 -07002059 }
2060 }
2061
2062 @Override
Sreeram Ramachandranf047f2a2014-04-15 16:04:26 -07002063 public void setDefaultNetId(int netId) {
paulhu59148b72019-08-12 16:25:11 +08002064 NetworkStack.checkNetworkStackPermission(mContext);
Robert Greenwalt568891d2014-04-04 13:38:00 -07002065
2066 try {
Luke Huang8a462ec2018-08-24 20:33:16 +08002067 mNetdService.networkSetDefault(netId);
2068 } catch (RemoteException | ServiceSpecificException e) {
2069 throw new IllegalStateException(e);
Robert Greenwalt568891d2014-04-04 13:38:00 -07002070 }
2071 }
2072
2073 @Override
2074 public void clearDefaultNetId() {
paulhu59148b72019-08-12 16:25:11 +08002075 NetworkStack.checkNetworkStackPermission(mContext);
Robert Greenwalt568891d2014-04-04 13:38:00 -07002076
2077 try {
Luke Huang8a462ec2018-08-24 20:33:16 +08002078 mNetdService.networkClearDefault();
2079 } catch (RemoteException | ServiceSpecificException e) {
2080 throw new IllegalStateException(e);
Robert Greenwalt568891d2014-04-04 13:38:00 -07002081 }
2082 }
2083
2084 @Override
Luke Huang8a462ec2018-08-24 20:33:16 +08002085 public void setNetworkPermission(int netId, int permission) {
paulhu59148b72019-08-12 16:25:11 +08002086 NetworkStack.checkNetworkStackPermission(mContext);
Paul Jensen487ffe72015-07-24 15:57:11 -04002087
2088 try {
Luke Huang8a462ec2018-08-24 20:33:16 +08002089 mNetdService.networkSetPermissionForNetwork(netId, permission);
2090 } catch (RemoteException | ServiceSpecificException e) {
2091 throw new IllegalStateException(e);
Paul Jensen487ffe72015-07-24 15:57:11 -04002092 }
2093 }
2094
Paul Jensen6bc2c2c2014-05-07 15:27:40 -04002095 @Override
2096 public void allowProtect(int uid) {
paulhu59148b72019-08-12 16:25:11 +08002097 NetworkStack.checkNetworkStackPermission(mContext);
Paul Jensen6bc2c2c2014-05-07 15:27:40 -04002098
2099 try {
Luke Huang8a462ec2018-08-24 20:33:16 +08002100 mNetdService.networkSetProtectAllow(uid);
2101 } catch (RemoteException | ServiceSpecificException e) {
2102 throw new IllegalStateException(e);
Paul Jensen6bc2c2c2014-05-07 15:27:40 -04002103 }
2104 }
2105
2106 @Override
2107 public void denyProtect(int uid) {
paulhu59148b72019-08-12 16:25:11 +08002108 NetworkStack.checkNetworkStackPermission(mContext);
Paul Jensen6bc2c2c2014-05-07 15:27:40 -04002109
2110 try {
Luke Huang8a462ec2018-08-24 20:33:16 +08002111 mNetdService.networkSetProtectDeny(uid);
2112 } catch (RemoteException | ServiceSpecificException e) {
2113 throw new IllegalStateException(e);
Paul Jensen6bc2c2c2014-05-07 15:27:40 -04002114 }
2115 }
2116
Sreeram Ramachandrana77760d2014-07-17 17:09:07 -07002117 @Override
2118 public void addInterfaceToLocalNetwork(String iface, List<RouteInfo> routes) {
Luke Huang706d7ab2018-10-16 15:42:15 +08002119 modifyInterfaceInNetwork(MODIFY_OPERATION_ADD, INetd.LOCAL_NET_ID, iface);
Sreeram Ramachandrana77760d2014-07-17 17:09:07 -07002120
2121 for (RouteInfo route : routes) {
2122 if (!route.isDefaultRoute()) {
Luke Huang706d7ab2018-10-16 15:42:15 +08002123 modifyRoute(MODIFY_OPERATION_ADD, INetd.LOCAL_NET_ID, route);
Sreeram Ramachandrana77760d2014-07-17 17:09:07 -07002124 }
2125 }
Jimmy Chen086779d2019-03-07 14:15:36 +08002126
2127 // IPv6 link local should be activated always.
2128 modifyRoute(MODIFY_OPERATION_ADD, INetd.LOCAL_NET_ID,
2129 new RouteInfo(new IpPrefix("fe80::/64"), null, iface));
Sreeram Ramachandrana77760d2014-07-17 17:09:07 -07002130 }
2131
2132 @Override
2133 public void removeInterfaceFromLocalNetwork(String iface) {
Luke Huang706d7ab2018-10-16 15:42:15 +08002134 modifyInterfaceInNetwork(MODIFY_OPERATION_REMOVE, INetd.LOCAL_NET_ID, iface);
Sreeram Ramachandrana77760d2014-07-17 17:09:07 -07002135 }
Erik Kline6599ee82016-07-17 21:28:39 +09002136
2137 @Override
2138 public int removeRoutesFromLocalNetwork(List<RouteInfo> routes) {
2139 int failures = 0;
2140
2141 for (RouteInfo route : routes) {
2142 try {
Luke Huang706d7ab2018-10-16 15:42:15 +08002143 modifyRoute(MODIFY_OPERATION_REMOVE, INetd.LOCAL_NET_ID, route);
Erik Kline6599ee82016-07-17 21:28:39 +09002144 } catch (IllegalStateException e) {
2145 failures++;
2146 }
2147 }
2148
2149 return failures;
2150 }
Sudheer Shanka62f5c172017-03-17 16:25:55 -07002151
Sudheer Shankab8f23162017-08-04 13:30:10 -07002152 @Override
2153 public boolean isNetworkRestricted(int uid) {
paulhu59148b72019-08-12 16:25:11 +08002154 mContext.enforceCallingOrSelfPermission(OBSERVE_NETWORK_POLICY, TAG);
Sudheer Shankab8f23162017-08-04 13:30:10 -07002155 return isNetworkRestrictedInternal(uid);
2156 }
2157
2158 private boolean isNetworkRestrictedInternal(int uid) {
2159 synchronized (mRulesLock) {
2160 if (getFirewallChainState(FIREWALL_CHAIN_STANDBY)
2161 && mUidFirewallStandbyRules.get(uid) == FIREWALL_RULE_DENY) {
2162 if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of app standby mode");
2163 return true;
2164 }
2165 if (getFirewallChainState(FIREWALL_CHAIN_DOZABLE)
2166 && mUidFirewallDozableRules.get(uid) != FIREWALL_RULE_ALLOW) {
2167 if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of device idle mode");
2168 return true;
2169 }
2170 if (getFirewallChainState(FIREWALL_CHAIN_POWERSAVE)
2171 && mUidFirewallPowerSaveRules.get(uid) != FIREWALL_RULE_ALLOW) {
2172 if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of power saver mode");
2173 return true;
2174 }
2175 if (mUidRejectOnMetered.get(uid)) {
2176 if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of no metered data"
2177 + " in the background");
2178 return true;
2179 }
2180 if (mDataSaverMode && !mUidAllowOnMetered.get(uid)) {
2181 if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of data saver mode");
2182 return true;
2183 }
2184 return false;
2185 }
2186 }
2187
Sudheer Shanka62f5c172017-03-17 16:25:55 -07002188 private void setFirewallChainState(int chain, boolean state) {
2189 synchronized (mRulesLock) {
2190 mFirewallChainStates.put(chain, state);
2191 }
2192 }
2193
2194 private boolean getFirewallChainState(int chain) {
2195 synchronized (mRulesLock) {
2196 return mFirewallChainStates.get(chain);
2197 }
2198 }
2199
2200 @VisibleForTesting
2201 class LocalService extends NetworkManagementInternal {
2202 @Override
2203 public boolean isNetworkRestrictedForUid(int uid) {
Sudheer Shankab8f23162017-08-04 13:30:10 -07002204 return isNetworkRestrictedInternal(uid);
Sudheer Shanka62f5c172017-03-17 16:25:55 -07002205 }
2206 }
2207
2208 @VisibleForTesting
2209 Injector getInjector() {
2210 return new Injector();
2211 }
2212
2213 @VisibleForTesting
2214 class Injector {
2215 void setDataSaverMode(boolean dataSaverMode) {
2216 mDataSaverMode = dataSaverMode;
2217 }
2218
2219 void setFirewallChainState(int chain, boolean state) {
2220 NetworkManagementService.this.setFirewallChainState(chain, state);
2221 }
2222
2223 void setFirewallRule(int chain, int uid, int rule) {
2224 synchronized (mRulesLock) {
2225 getUidFirewallRulesLR(chain).put(uid, rule);
2226 }
2227 }
2228
2229 void setUidOnMeteredNetworkList(boolean blacklist, int uid, boolean enable) {
2230 synchronized (mRulesLock) {
2231 if (blacklist) {
2232 mUidRejectOnMetered.put(uid, enable);
2233 } else {
2234 mUidAllowOnMetered.put(uid, enable);
2235 }
2236 }
2237 }
2238
2239 void reset() {
2240 synchronized (mRulesLock) {
2241 setDataSaverMode(false);
2242 final int[] chains = {
2243 FIREWALL_CHAIN_DOZABLE,
2244 FIREWALL_CHAIN_STANDBY,
2245 FIREWALL_CHAIN_POWERSAVE
2246 };
2247 for (int chain : chains) {
2248 setFirewallChainState(chain, false);
2249 getUidFirewallRulesLR(chain).clear();
2250 }
2251 mUidAllowOnMetered.clear();
2252 mUidRejectOnMetered.clear();
2253 }
2254 }
2255 }
San Mehat873f2142010-01-14 10:25:07 -08002256}