blob: 648dfff5c5461b73f1feafd591bd53bcead902c0 [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
Jeff Sharkey4529bb62011-12-14 10:31:54 -080019import static android.Manifest.permission.CONNECTIVITY_INTERNAL;
Jeff Sharkey47eb1022011-08-25 17:48:52 -070020import static android.Manifest.permission.DUMP;
Jeff Sharkeyaf75c332011-11-18 12:41:12 -080021import static android.Manifest.permission.SHUTDOWN;
Jeff Sharkeyb5d55e32011-08-10 17:53:27 -070022import static android.net.NetworkStats.SET_DEFAULT;
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -070023import static android.net.NetworkStats.TAG_NONE;
24import static android.net.NetworkStats.UID_ALL;
Jeff Sharkeyae2c1812011-10-04 13:11:40 -070025import static android.net.TrafficStats.UID_TETHERING;
Jeff Sharkeyba2896e2011-11-30 18:13:54 -080026import static com.android.server.NetworkManagementService.NetdResponseCode.InterfaceGetCfgResult;
27import static com.android.server.NetworkManagementService.NetdResponseCode.InterfaceListResult;
28import static com.android.server.NetworkManagementService.NetdResponseCode.InterfaceRxThrottleResult;
29import static com.android.server.NetworkManagementService.NetdResponseCode.InterfaceTxThrottleResult;
30import static com.android.server.NetworkManagementService.NetdResponseCode.IpFwdStatusResult;
31import static com.android.server.NetworkManagementService.NetdResponseCode.TetherDnsFwdTgtListResult;
32import static com.android.server.NetworkManagementService.NetdResponseCode.TetherInterfaceListResult;
33import static com.android.server.NetworkManagementService.NetdResponseCode.TetherStatusResult;
34import static com.android.server.NetworkManagementService.NetdResponseCode.TetheringStatsResult;
35import static com.android.server.NetworkManagementService.NetdResponseCode.TtyListResult;
Jeff Sharkeya63ba592011-07-19 23:47:12 -070036import static com.android.server.NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED;
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -070037
San Mehat873f2142010-01-14 10:25:07 -080038import android.content.Context;
San Mehat4d02d002010-01-22 16:07:46 -080039import android.net.INetworkManagementEventObserver;
Jeff Sharkeyeedcb952011-05-17 14:55:15 -070040import android.net.InterfaceConfiguration;
Robert Greenwalted126402011-01-28 15:34:55 -080041import android.net.LinkAddress;
Jeff Sharkeyeedcb952011-05-17 14:55:15 -070042import android.net.NetworkStats;
Robert Greenwalted126402011-01-28 15:34:55 -080043import android.net.NetworkUtils;
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -070044import android.net.RouteInfo;
Irfan Sheriff9ab518ad2010-03-12 15:48:17 -080045import android.net.wifi.WifiConfiguration;
46import android.net.wifi.WifiConfiguration.KeyMgmt;
Jeff Sharkeyb24a7852012-05-01 15:19:37 -070047import android.os.Handler;
San Mehat873f2142010-01-14 10:25:07 -080048import android.os.INetworkManagementService;
Jeff Sharkey3df273e2011-12-15 15:47:12 -080049import android.os.RemoteCallbackList;
50import android.os.RemoteException;
Jeff Sharkey9a13f362011-04-26 16:25:36 -070051import android.os.SystemClock;
Marco Nelissen62dbb222010-02-18 10:56:30 -080052import android.os.SystemProperties;
Irfan Sheriff9ab518ad2010-03-12 15:48:17 -080053import android.util.Log;
Joe Onorato8a9b2202010-02-26 18:56:32 -080054import android.util.Slog;
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -070055import android.util.SparseBooleanArray;
San Mehat873f2142010-01-14 10:25:07 -080056
Jeff Sharkey1059c3c2011-10-04 16:54:49 -070057import com.android.internal.net.NetworkStatsFactory;
Jeff Sharkeyba2896e2011-11-30 18:13:54 -080058import com.android.server.NativeDaemonConnector.Command;
Jeff Sharkeyb24a7852012-05-01 15:19:37 -070059import com.google.android.collect.Maps;
Jeff Sharkey4414cea2011-06-24 17:05:24 -070060
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -070061import java.io.BufferedReader;
62import java.io.DataInputStream;
San Mehat873f2142010-01-14 10:25:07 -080063import java.io.File;
Jeff Sharkey47eb1022011-08-25 17:48:52 -070064import java.io.FileDescriptor;
Jeff Sharkey9a13f362011-04-26 16:25:36 -070065import java.io.FileInputStream;
Jeff Sharkey9a13f362011-04-26 16:25:36 -070066import java.io.IOException;
Jeff Sharkey9a13f362011-04-26 16:25:36 -070067import java.io.InputStreamReader;
Jeff Sharkey47eb1022011-08-25 17:48:52 -070068import java.io.PrintWriter;
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -070069import java.net.Inet4Address;
Jeff Sharkeyeedcb952011-05-17 14:55:15 -070070import java.net.InetAddress;
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -070071import java.net.InterfaceAddress;
72import java.net.NetworkInterface;
73import java.net.SocketException;
Jeff Sharkeyeedcb952011-05-17 14:55:15 -070074import java.util.ArrayList;
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -070075import java.util.Collection;
Jeff Sharkeyb24a7852012-05-01 15:19:37 -070076import java.util.HashMap;
77import java.util.Map;
Jeff Sharkeyeedcb952011-05-17 14:55:15 -070078import java.util.NoSuchElementException;
79import java.util.StringTokenizer;
Robert Greenwalte5c3afb2010-09-22 14:32:35 -070080import java.util.concurrent.CountDownLatch;
fredc0f420372012-04-12 00:02:00 -070081import android.bluetooth.BluetoothTetheringDataTracker;
San Mehat873f2142010-01-14 10:25:07 -080082
83/**
84 * @hide
85 */
Jeff Sharkey8e9992a2011-08-23 18:37:23 -070086public class NetworkManagementService extends INetworkManagementService.Stub
87 implements Watchdog.Monitor {
Jeff Sharkeyeedcb952011-05-17 14:55:15 -070088 private static final String TAG = "NetworkManagementService";
Dianne Hackborncef65ee2010-09-30 18:27:22 -070089 private static final boolean DBG = false;
Kenny Root305bcbf2010-09-03 07:56:38 -070090 private static final String NETD_TAG = "NetdConnector";
91
Jeff Sharkeyba2896e2011-11-30 18:13:54 -080092 private static final String ADD = "add";
93 private static final String REMOVE = "remove";
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -070094
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -070095 private static final String DEFAULT = "default";
96 private static final String SECONDARY = "secondary";
97
Jeff Sharkey8e9992a2011-08-23 18:37:23 -070098 /**
99 * Name representing {@link #setGlobalAlert(long)} limit when delivered to
100 * {@link INetworkManagementEventObserver#limitReached(String, String)}.
101 */
102 public static final String LIMIT_GLOBAL_ALERT = "globalAlert";
103
San Mehat873f2142010-01-14 10:25:07 -0800104 class NetdResponseCode {
JP Abgrall12b933d2011-07-14 18:09:22 -0700105 /* Keep in sync with system/netd/ResponseCode.h */
San Mehat873f2142010-01-14 10:25:07 -0800106 public static final int InterfaceListResult = 110;
107 public static final int TetherInterfaceListResult = 111;
108 public static final int TetherDnsFwdTgtListResult = 112;
San Mehat72759df2010-01-19 13:50:37 -0800109 public static final int TtyListResult = 113;
San Mehat873f2142010-01-14 10:25:07 -0800110
111 public static final int TetherStatusResult = 210;
112 public static final int IpFwdStatusResult = 211;
San Mehated4fc8a2010-01-22 12:28:36 -0800113 public static final int InterfaceGetCfgResult = 213;
Robert Greenwalte3253922010-02-18 09:23:25 -0800114 public static final int SoftapStatusResult = 214;
San Mehat91cac642010-03-31 14:31:36 -0700115 public static final int InterfaceRxCounterResult = 216;
116 public static final int InterfaceTxCounterResult = 217;
117 public static final int InterfaceRxThrottleResult = 218;
118 public static final int InterfaceTxThrottleResult = 219;
Jeff Sharkeycdd02c5d2011-09-16 01:52:49 -0700119 public static final int QuotaCounterResult = 220;
120 public static final int TetheringStatsResult = 221;
Selim Gurun84c00c62012-02-27 15:42:38 -0800121 public static final int DnsProxyQueryResult = 222;
Robert Greenwalte3253922010-02-18 09:23:25 -0800122
123 public static final int InterfaceChange = 600;
JP Abgrall12b933d2011-07-14 18:09:22 -0700124 public static final int BandwidthControl = 601;
San Mehat873f2142010-01-14 10:25:07 -0800125 }
126
127 /**
128 * Binder context for this service
129 */
130 private Context mContext;
131
132 /**
133 * connector object for communicating with netd
134 */
135 private NativeDaemonConnector mConnector;
136
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700137 private final Handler mMainHandler = new Handler();
138
Robert Greenwalte5c3afb2010-09-22 14:32:35 -0700139 private Thread mThread;
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700140 private CountDownLatch mConnectedSignal = new CountDownLatch(1);
Robert Greenwalte5c3afb2010-09-22 14:32:35 -0700141
Jeff Sharkey3df273e2011-12-15 15:47:12 -0800142 private final RemoteCallbackList<INetworkManagementEventObserver> mObservers =
143 new RemoteCallbackList<INetworkManagementEventObserver>();
San Mehat4d02d002010-01-22 16:07:46 -0800144
Jeff Sharkey1059c3c2011-10-04 16:54:49 -0700145 private final NetworkStatsFactory mStatsFactory = new NetworkStatsFactory();
146
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -0700147 private Object mQuotaLock = new Object();
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -0700148 /** Set of interfaces with active quotas. */
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700149 private HashMap<String, Long> mActiveQuotas = Maps.newHashMap();
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -0700150 /** Set of interfaces with active alerts. */
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700151 private HashMap<String, Long> mActiveAlerts = Maps.newHashMap();
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -0700152 /** Set of UIDs with active reject rules. */
153 private SparseBooleanArray mUidRejectOnQuota = new SparseBooleanArray();
154
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -0700155 private volatile boolean mBandwidthControlEnabled;
Jeff Sharkey350083e2011-06-29 10:45:16 -0700156
San Mehat873f2142010-01-14 10:25:07 -0800157 /**
158 * Constructs a new NetworkManagementService instance
159 *
160 * @param context Binder context for this service
161 */
Jeff Sharkey1059c3c2011-10-04 16:54:49 -0700162 private NetworkManagementService(Context context) {
San Mehat873f2142010-01-14 10:25:07 -0800163 mContext = context;
San Mehat4d02d002010-01-22 16:07:46 -0800164
Marco Nelissen62dbb222010-02-18 10:56:30 -0800165 if ("simulator".equals(SystemProperties.get("ro.product.device"))) {
166 return;
167 }
168
San Mehat873f2142010-01-14 10:25:07 -0800169 mConnector = new NativeDaemonConnector(
Robert Greenwalt5a0c3202012-05-22 16:07:46 -0700170 new NetdCallbackReceiver(), "netd", 10, NETD_TAG, 160);
Robert Greenwalte5c3afb2010-09-22 14:32:35 -0700171 mThread = new Thread(mConnector, NETD_TAG);
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -0700172
173 // Add ourself to the Watchdog monitors.
174 Watchdog.getInstance().addMonitor(this);
Robert Greenwalte5c3afb2010-09-22 14:32:35 -0700175 }
176
177 public static NetworkManagementService create(Context context) throws InterruptedException {
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700178 final NetworkManagementService service = new NetworkManagementService(context);
179 final CountDownLatch connectedSignal = service.mConnectedSignal;
Robert Greenwalte5c3afb2010-09-22 14:32:35 -0700180 if (DBG) Slog.d(TAG, "Creating NetworkManagementService");
181 service.mThread.start();
182 if (DBG) Slog.d(TAG, "Awaiting socket connection");
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700183 connectedSignal.await();
Robert Greenwalte5c3afb2010-09-22 14:32:35 -0700184 if (DBG) Slog.d(TAG, "Connected");
185 return service;
San Mehat873f2142010-01-14 10:25:07 -0800186 }
187
Jeff Sharkey350083e2011-06-29 10:45:16 -0700188 public void systemReady() {
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700189 prepareNativeDaemon();
190 if (DBG) Slog.d(TAG, "Prepared");
Jeff Sharkey350083e2011-06-29 10:45:16 -0700191 }
192
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800193 @Override
Jeff Sharkey3df273e2011-12-15 15:47:12 -0800194 public void registerObserver(INetworkManagementEventObserver observer) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -0800195 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Jeff Sharkey3df273e2011-12-15 15:47:12 -0800196 mObservers.register(observer);
San Mehat4d02d002010-01-22 16:07:46 -0800197 }
198
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800199 @Override
Jeff Sharkey3df273e2011-12-15 15:47:12 -0800200 public void unregisterObserver(INetworkManagementEventObserver observer) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -0800201 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Jeff Sharkey3df273e2011-12-15 15:47:12 -0800202 mObservers.unregister(observer);
San Mehat4d02d002010-01-22 16:07:46 -0800203 }
204
205 /**
Mike J. Chen6143f5f2011-06-23 15:17:51 -0700206 * Notify our observers of an interface status change
San Mehat4d02d002010-01-22 16:07:46 -0800207 */
Mike J. Chen6143f5f2011-06-23 15:17:51 -0700208 private void notifyInterfaceStatusChanged(String iface, boolean up) {
Jeff Sharkey3df273e2011-12-15 15:47:12 -0800209 final int length = mObservers.beginBroadcast();
210 for (int i = 0; i < length; i++) {
San Mehat4d02d002010-01-22 16:07:46 -0800211 try {
Jeff Sharkey3df273e2011-12-15 15:47:12 -0800212 mObservers.getBroadcastItem(i).interfaceStatusChanged(iface, up);
213 } catch (RemoteException e) {
Mike J. Chen6143f5f2011-06-23 15:17:51 -0700214 }
215 }
Jeff Sharkey3df273e2011-12-15 15:47:12 -0800216 mObservers.finishBroadcast();
Mike J. Chen6143f5f2011-06-23 15:17:51 -0700217 }
218
219 /**
Mike J. Chenf59c7d02011-06-23 15:33:15 -0700220 * Notify our observers of an interface link state change
Mike J. Chen6143f5f2011-06-23 15:17:51 -0700221 * (typically, an Ethernet cable has been plugged-in or unplugged).
222 */
223 private void notifyInterfaceLinkStateChanged(String iface, boolean up) {
Jeff Sharkey3df273e2011-12-15 15:47:12 -0800224 final int length = mObservers.beginBroadcast();
225 for (int i = 0; i < length; i++) {
Mike J. Chen6143f5f2011-06-23 15:17:51 -0700226 try {
Jeff Sharkey3df273e2011-12-15 15:47:12 -0800227 mObservers.getBroadcastItem(i).interfaceLinkStateChanged(iface, up);
228 } catch (RemoteException e) {
San Mehat4d02d002010-01-22 16:07:46 -0800229 }
230 }
Jeff Sharkey3df273e2011-12-15 15:47:12 -0800231 mObservers.finishBroadcast();
San Mehat4d02d002010-01-22 16:07:46 -0800232 }
233
234 /**
235 * Notify our observers of an interface addition.
236 */
237 private void notifyInterfaceAdded(String iface) {
Jeff Sharkey3df273e2011-12-15 15:47:12 -0800238 final int length = mObservers.beginBroadcast();
239 for (int i = 0; i < length; i++) {
San Mehat4d02d002010-01-22 16:07:46 -0800240 try {
Jeff Sharkey3df273e2011-12-15 15:47:12 -0800241 mObservers.getBroadcastItem(i).interfaceAdded(iface);
242 } catch (RemoteException e) {
San Mehat4d02d002010-01-22 16:07:46 -0800243 }
244 }
Jeff Sharkey3df273e2011-12-15 15:47:12 -0800245 mObservers.finishBroadcast();
San Mehat4d02d002010-01-22 16:07:46 -0800246 }
247
248 /**
249 * Notify our observers of an interface removal.
250 */
251 private void notifyInterfaceRemoved(String iface) {
Jeff Sharkey89b8a212011-10-11 11:58:11 -0700252 // netd already clears out quota and alerts for removed ifaces; update
253 // our sanity-checking state.
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700254 mActiveAlerts.remove(iface);
255 mActiveQuotas.remove(iface);
Jeff Sharkey89b8a212011-10-11 11:58:11 -0700256
Jeff Sharkey3df273e2011-12-15 15:47:12 -0800257 final int length = mObservers.beginBroadcast();
258 for (int i = 0; i < length; i++) {
San Mehat4d02d002010-01-22 16:07:46 -0800259 try {
Jeff Sharkey3df273e2011-12-15 15:47:12 -0800260 mObservers.getBroadcastItem(i).interfaceRemoved(iface);
261 } catch (RemoteException e) {
San Mehat4d02d002010-01-22 16:07:46 -0800262 }
263 }
Jeff Sharkey3df273e2011-12-15 15:47:12 -0800264 mObservers.finishBroadcast();
San Mehat4d02d002010-01-22 16:07:46 -0800265 }
266
Robert Greenwalte5c3afb2010-09-22 14:32:35 -0700267 /**
JP Abgrall12b933d2011-07-14 18:09:22 -0700268 * Notify our observers of a limit reached.
269 */
270 private void notifyLimitReached(String limitName, String iface) {
Jeff Sharkey3df273e2011-12-15 15:47:12 -0800271 final int length = mObservers.beginBroadcast();
272 for (int i = 0; i < length; i++) {
JP Abgrall12b933d2011-07-14 18:09:22 -0700273 try {
Jeff Sharkey3df273e2011-12-15 15:47:12 -0800274 mObservers.getBroadcastItem(i).limitReached(limitName, iface);
275 } catch (RemoteException e) {
JP Abgrall12b933d2011-07-14 18:09:22 -0700276 }
277 }
Jeff Sharkey3df273e2011-12-15 15:47:12 -0800278 mObservers.finishBroadcast();
JP Abgrall12b933d2011-07-14 18:09:22 -0700279 }
280
281 /**
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700282 * Prepare native daemon once connected, enabling modules and pushing any
283 * existing in-memory rules.
Robert Greenwalte5c3afb2010-09-22 14:32:35 -0700284 */
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700285 private void prepareNativeDaemon() {
286 mBandwidthControlEnabled = false;
Robert Greenwalte5c3afb2010-09-22 14:32:35 -0700287
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700288 // only enable bandwidth control when support exists
289 final boolean hasKernelSupport = new File("/proc/net/xt_qtaguid/ctrl").exists();
290 if (hasKernelSupport) {
291 Slog.d(TAG, "enabling bandwidth control");
292 try {
293 mConnector.execute("bandwidth", "enable");
294 mBandwidthControlEnabled = true;
295 } catch (NativeDaemonConnectorException e) {
296 Log.wtf(TAG, "problem enabling bandwidth controls", e);
297 }
298 } else {
299 Slog.d(TAG, "not enabling bandwidth control");
300 }
301
302 SystemProperties.set(PROP_QTAGUID_ENABLED, mBandwidthControlEnabled ? "1" : "0");
303
304 // push any existing quota or UID rules
305 synchronized (mQuotaLock) {
306 int size = mActiveQuotas.size();
307 if (size > 0) {
308 Slog.d(TAG, "pushing " + size + " active quota rules");
309 final HashMap<String, Long> activeQuotas = mActiveQuotas;
310 mActiveQuotas = Maps.newHashMap();
311 for (Map.Entry<String, Long> entry : activeQuotas.entrySet()) {
312 setInterfaceQuota(entry.getKey(), entry.getValue());
313 }
314 }
315
316 size = mActiveAlerts.size();
317 if (size > 0) {
318 Slog.d(TAG, "pushing " + size + " active alert rules");
319 final HashMap<String, Long> activeAlerts = mActiveAlerts;
320 mActiveAlerts = Maps.newHashMap();
321 for (Map.Entry<String, Long> entry : activeAlerts.entrySet()) {
322 setInterfaceAlert(entry.getKey(), entry.getValue());
323 }
324 }
325
326 size = mUidRejectOnQuota.size();
327 if (size > 0) {
328 Slog.d(TAG, "pushing " + size + " active uid rules");
329 final SparseBooleanArray uidRejectOnQuota = mUidRejectOnQuota;
330 mUidRejectOnQuota = new SparseBooleanArray();
331 for (int i = 0; i < uidRejectOnQuota.size(); i++) {
332 setUidNetworkRules(uidRejectOnQuota.keyAt(i), uidRejectOnQuota.valueAt(i));
333 }
334 }
335 }
336 }
San Mehat4d02d002010-01-22 16:07:46 -0800337
San Mehat873f2142010-01-14 10:25:07 -0800338 //
339 // Netd Callback handling
340 //
341
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700342 private class NetdCallbackReceiver implements INativeDaemonConnectorCallbacks {
343 @Override
San Mehat873f2142010-01-14 10:25:07 -0800344 public void onDaemonConnected() {
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700345 // event is dispatched from internal NDC thread, so we prepare the
346 // daemon back on main thread.
347 if (mConnectedSignal != null) {
348 mConnectedSignal.countDown();
349 mConnectedSignal = null;
350 } else {
351 mMainHandler.post(new Runnable() {
352 @Override
353 public void run() {
354 prepareNativeDaemon();
355 }
356 });
357 }
San Mehat873f2142010-01-14 10:25:07 -0800358 }
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -0700359
Jeff Sharkeyb24a7852012-05-01 15:19:37 -0700360 @Override
San Mehat873f2142010-01-14 10:25:07 -0800361 public boolean onEvent(int code, String raw, String[] cooked) {
JP Abgrall12b933d2011-07-14 18:09:22 -0700362 switch (code) {
363 case NetdResponseCode.InterfaceChange:
364 /*
365 * a network interface change occured
366 * Format: "NNN Iface added <name>"
367 * "NNN Iface removed <name>"
368 * "NNN Iface changed <name> <up/down>"
369 * "NNN Iface linkstatus <name> <up/down>"
370 */
371 if (cooked.length < 4 || !cooked[1].equals("Iface")) {
372 throw new IllegalStateException(
373 String.format("Invalid event from daemon (%s)", raw));
374 }
375 if (cooked[2].equals("added")) {
376 notifyInterfaceAdded(cooked[3]);
377 return true;
378 } else if (cooked[2].equals("removed")) {
379 notifyInterfaceRemoved(cooked[3]);
380 return true;
381 } else if (cooked[2].equals("changed") && cooked.length == 5) {
382 notifyInterfaceStatusChanged(cooked[3], cooked[4].equals("up"));
383 return true;
384 } else if (cooked[2].equals("linkstate") && cooked.length == 5) {
385 notifyInterfaceLinkStateChanged(cooked[3], cooked[4].equals("up"));
386 return true;
387 }
Robert Greenwalte3253922010-02-18 09:23:25 -0800388 throw new IllegalStateException(
389 String.format("Invalid event from daemon (%s)", raw));
JP Abgrall12b933d2011-07-14 18:09:22 -0700390 // break;
391 case NetdResponseCode.BandwidthControl:
392 /*
393 * Bandwidth control needs some attention
394 * Format: "NNN limit alert <alertName> <ifaceName>"
395 */
396 if (cooked.length < 5 || !cooked[1].equals("limit")) {
397 throw new IllegalStateException(
398 String.format("Invalid event from daemon (%s)", raw));
399 }
400 if (cooked[2].equals("alert")) {
401 notifyLimitReached(cooked[3], cooked[4]);
402 return true;
403 }
404 throw new IllegalStateException(
405 String.format("Invalid event from daemon (%s)", raw));
406 // break;
407 default: break;
Robert Greenwalte3253922010-02-18 09:23:25 -0800408 }
409 return false;
San Mehat873f2142010-01-14 10:25:07 -0800410 }
411 }
412
San Mehated4fc8a2010-01-22 12:28:36 -0800413
San Mehat873f2142010-01-14 10:25:07 -0800414 //
415 // INetworkManagementService members
416 //
417
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800418 @Override
419 public String[] listInterfaces() {
Jeff Sharkey4529bb62011-12-14 10:31:54 -0800420 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Kenny Roota80ce062010-06-01 13:23:53 -0700421 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -0800422 return NativeDaemonEvent.filterMessageList(
423 mConnector.executeForList("interface", "list"), InterfaceListResult);
Kenny Roota80ce062010-06-01 13:23:53 -0700424 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -0800425 throw e.rethrowAsParcelableException();
Kenny Roota80ce062010-06-01 13:23:53 -0700426 }
San Mehated4fc8a2010-01-22 12:28:36 -0800427 }
428
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800429 @Override
430 public InterfaceConfiguration getInterfaceConfig(String iface) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -0800431 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Jeff Sharkeyba2896e2011-11-30 18:13:54 -0800432
433 final NativeDaemonEvent event;
Kenny Roota80ce062010-06-01 13:23:53 -0700434 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -0800435 event = mConnector.execute("interface", "getcfg", iface);
Kenny Roota80ce062010-06-01 13:23:53 -0700436 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -0800437 throw e.rethrowAsParcelableException();
Kenny Roota80ce062010-06-01 13:23:53 -0700438 }
San Mehated4fc8a2010-01-22 12:28:36 -0800439
Jeff Sharkeyba2896e2011-11-30 18:13:54 -0800440 event.checkCode(InterfaceGetCfgResult);
441
442 // Rsp: 213 xx:xx:xx:xx:xx:xx yyy.yyy.yyy.yyy zzz flag1 flag2 flag3
443 final StringTokenizer st = new StringTokenizer(event.getMessage());
San Mehated4fc8a2010-01-22 12:28:36 -0800444
Kenny Roota80ce062010-06-01 13:23:53 -0700445 InterfaceConfiguration cfg;
San Mehated4fc8a2010-01-22 12:28:36 -0800446 try {
Kenny Roota80ce062010-06-01 13:23:53 -0700447 cfg = new InterfaceConfiguration();
Jeff Sharkeyddba1062011-11-29 18:37:04 -0800448 cfg.setHardwareAddress(st.nextToken(" "));
Robert Greenwalted126402011-01-28 15:34:55 -0800449 InetAddress addr = null;
Robert Greenwalt2d2afd12011-02-01 15:30:46 -0800450 int prefixLength = 0;
Kenny Roota80ce062010-06-01 13:23:53 -0700451 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -0800452 addr = NetworkUtils.numericToInetAddress(st.nextToken());
Robert Greenwalte5903732011-02-22 16:00:42 -0800453 } catch (IllegalArgumentException iae) {
454 Slog.e(TAG, "Failed to parse ipaddr", iae);
Kenny Roota80ce062010-06-01 13:23:53 -0700455 }
456
457 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -0800458 prefixLength = Integer.parseInt(st.nextToken());
Robert Greenwalt2d2afd12011-02-01 15:30:46 -0800459 } catch (NumberFormatException nfe) {
460 Slog.e(TAG, "Failed to parse prefixLength", nfe);
Kenny Roota80ce062010-06-01 13:23:53 -0700461 }
Robert Greenwalt04808c22010-12-13 17:01:41 -0800462
Jeff Sharkeyddba1062011-11-29 18:37:04 -0800463 cfg.setLinkAddress(new LinkAddress(addr, prefixLength));
464 while (st.hasMoreTokens()) {
465 cfg.setFlag(st.nextToken());
466 }
Kenny Roota80ce062010-06-01 13:23:53 -0700467 } catch (NoSuchElementException nsee) {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -0800468 throw new IllegalStateException("Invalid response from daemon: " + event);
San Mehated4fc8a2010-01-22 12:28:36 -0800469 }
San Mehated4fc8a2010-01-22 12:28:36 -0800470 return cfg;
471 }
472
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800473 @Override
474 public void setInterfaceConfig(String iface, InterfaceConfiguration cfg) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -0800475 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Jeff Sharkeyddba1062011-11-29 18:37:04 -0800476 LinkAddress linkAddr = cfg.getLinkAddress();
Robert Greenwalt2d2afd12011-02-01 15:30:46 -0800477 if (linkAddr == null || linkAddr.getAddress() == null) {
478 throw new IllegalStateException("Null LinkAddress given");
Robert Greenwalted126402011-01-28 15:34:55 -0800479 }
Jeff Sharkeyba2896e2011-11-30 18:13:54 -0800480
481 final Command cmd = new Command("interface", "setcfg", iface,
Robert Greenwalt2d2afd12011-02-01 15:30:46 -0800482 linkAddr.getAddress().getHostAddress(),
Jeff Sharkeyba2896e2011-11-30 18:13:54 -0800483 linkAddr.getNetworkPrefixLength());
484 for (String flag : cfg.getFlags()) {
485 cmd.appendArg(flag);
486 }
487
Kenny Roota80ce062010-06-01 13:23:53 -0700488 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -0800489 mConnector.execute(cmd);
Kenny Roota80ce062010-06-01 13:23:53 -0700490 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -0800491 throw e.rethrowAsParcelableException();
Kenny Roota80ce062010-06-01 13:23:53 -0700492 }
San Mehat873f2142010-01-14 10:25:07 -0800493 }
494
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800495 @Override
496 public void setInterfaceDown(String iface) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -0800497 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Jeff Sharkey31c6e482011-11-18 17:09:01 -0800498 final InterfaceConfiguration ifcg = getInterfaceConfig(iface);
Jeff Sharkeyddba1062011-11-29 18:37:04 -0800499 ifcg.setInterfaceDown();
Jeff Sharkey31c6e482011-11-18 17:09:01 -0800500 setInterfaceConfig(iface, ifcg);
Irfan Sheriff7244c972011-08-05 20:40:45 -0700501 }
502
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800503 @Override
504 public void setInterfaceUp(String iface) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -0800505 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Jeff Sharkey31c6e482011-11-18 17:09:01 -0800506 final InterfaceConfiguration ifcg = getInterfaceConfig(iface);
Jeff Sharkeyddba1062011-11-29 18:37:04 -0800507 ifcg.setInterfaceUp();
Jeff Sharkey31c6e482011-11-18 17:09:01 -0800508 setInterfaceConfig(iface, ifcg);
Irfan Sheriff7244c972011-08-05 20:40:45 -0700509 }
510
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800511 @Override
512 public void setInterfaceIpv6PrivacyExtensions(String iface, boolean enable) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -0800513 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Irfan Sheriff73293612011-09-14 12:31:56 -0700514 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -0800515 mConnector.execute(
516 "interface", "ipv6privacyextensions", iface, enable ? "enable" : "disable");
Irfan Sheriff73293612011-09-14 12:31:56 -0700517 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -0800518 throw e.rethrowAsParcelableException();
Irfan Sheriff73293612011-09-14 12:31:56 -0700519 }
520 }
521
Irfan Sherifff5600612011-06-16 10:26:28 -0700522 /* TODO: This is right now a IPv4 only function. Works for wifi which loses its
523 IPv6 addresses on interface down, but we need to do full clean up here */
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800524 @Override
525 public void clearInterfaceAddresses(String iface) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -0800526 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Irfan Sherifff5600612011-06-16 10:26:28 -0700527 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -0800528 mConnector.execute("interface", "clearaddrs", iface);
Irfan Sherifff5600612011-06-16 10:26:28 -0700529 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -0800530 throw e.rethrowAsParcelableException();
Irfan Sherifff5600612011-06-16 10:26:28 -0700531 }
532 }
533
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800534 @Override
535 public void enableIpv6(String iface) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -0800536 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
repo sync7960d9f2011-09-29 12:40:02 -0700537 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -0800538 mConnector.execute("interface", "ipv6", iface, "enable");
repo sync7960d9f2011-09-29 12:40:02 -0700539 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -0800540 throw e.rethrowAsParcelableException();
repo sync7960d9f2011-09-29 12:40:02 -0700541 }
542 }
543
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800544 @Override
545 public void disableIpv6(String iface) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -0800546 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
repo sync7960d9f2011-09-29 12:40:02 -0700547 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -0800548 mConnector.execute("interface", "ipv6", iface, "disable");
repo sync7960d9f2011-09-29 12:40:02 -0700549 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -0800550 throw e.rethrowAsParcelableException();
repo sync7960d9f2011-09-29 12:40:02 -0700551 }
552 }
553
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800554 @Override
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -0700555 public void addRoute(String interfaceName, RouteInfo route) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -0800556 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -0700557 modifyRoute(interfaceName, ADD, route, DEFAULT);
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -0700558 }
559
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800560 @Override
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -0700561 public void removeRoute(String interfaceName, RouteInfo route) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -0800562 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -0700563 modifyRoute(interfaceName, REMOVE, route, DEFAULT);
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -0700564 }
565
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800566 @Override
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -0700567 public void addSecondaryRoute(String interfaceName, RouteInfo route) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -0800568 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -0700569 modifyRoute(interfaceName, ADD, route, SECONDARY);
570 }
571
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800572 @Override
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -0700573 public void removeSecondaryRoute(String interfaceName, RouteInfo route) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -0800574 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -0700575 modifyRoute(interfaceName, REMOVE, route, SECONDARY);
576 }
577
Jeff Sharkeyba2896e2011-11-30 18:13:54 -0800578 private void modifyRoute(String interfaceName, String action, RouteInfo route, String type) {
579 final Command cmd = new Command("interface", "route", action, interfaceName, type);
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -0700580
581 // create triplet: dest-ip-addr prefixlength gateway-ip-addr
Jeff Sharkeyba2896e2011-11-30 18:13:54 -0800582 final LinkAddress la = route.getDestination();
583 cmd.appendArg(la.getAddress().getHostAddress());
584 cmd.appendArg(la.getNetworkPrefixLength());
585
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -0700586 if (route.getGateway() == null) {
587 if (la.getAddress() instanceof Inet4Address) {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -0800588 cmd.appendArg("0.0.0.0");
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -0700589 } else {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -0800590 cmd.appendArg("::0");
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -0700591 }
592 } else {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -0800593 cmd.appendArg(route.getGateway().getHostAddress());
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -0700594 }
595
Jeff Sharkeyba2896e2011-11-30 18:13:54 -0800596 try {
597 mConnector.execute(cmd);
598 } catch (NativeDaemonConnectorException e) {
599 throw e.rethrowAsParcelableException();
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -0700600 }
601 }
602
603 private ArrayList<String> readRouteList(String filename) {
604 FileInputStream fstream = null;
605 ArrayList<String> list = new ArrayList<String>();
606
607 try {
608 fstream = new FileInputStream(filename);
609 DataInputStream in = new DataInputStream(fstream);
610 BufferedReader br = new BufferedReader(new InputStreamReader(in));
611 String s;
612
613 // throw away the title line
614
615 while (((s = br.readLine()) != null) && (s.length() != 0)) {
616 list.add(s);
617 }
618 } catch (IOException ex) {
619 // return current list, possibly empty
620 } finally {
621 if (fstream != null) {
622 try {
623 fstream.close();
624 } catch (IOException ex) {}
625 }
626 }
627
628 return list;
629 }
630
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800631 @Override
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -0700632 public RouteInfo[] getRoutes(String interfaceName) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -0800633 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -0700634 ArrayList<RouteInfo> routes = new ArrayList<RouteInfo>();
635
636 // v4 routes listed as:
637 // iface dest-addr gateway-addr flags refcnt use metric netmask mtu window IRTT
638 for (String s : readRouteList("/proc/net/route")) {
639 String[] fields = s.split("\t");
640
641 if (fields.length > 7) {
642 String iface = fields[0];
643
644 if (interfaceName.equals(iface)) {
645 String dest = fields[1];
646 String gate = fields[2];
647 String flags = fields[3]; // future use?
648 String mask = fields[7];
649 try {
650 // address stored as a hex string, ex: 0014A8C0
651 InetAddress destAddr =
652 NetworkUtils.intToInetAddress((int)Long.parseLong(dest, 16));
653 int prefixLength =
654 NetworkUtils.netmaskIntToPrefixLength(
655 (int)Long.parseLong(mask, 16));
656 LinkAddress linkAddress = new LinkAddress(destAddr, prefixLength);
657
658 // address stored as a hex string, ex 0014A8C0
659 InetAddress gatewayAddr =
660 NetworkUtils.intToInetAddress((int)Long.parseLong(gate, 16));
661
662 RouteInfo route = new RouteInfo(linkAddress, gatewayAddr);
663 routes.add(route);
664 } catch (Exception e) {
665 Log.e(TAG, "Error parsing route " + s + " : " + e);
666 continue;
667 }
668 }
669 }
670 }
671
672 // v6 routes listed as:
673 // dest-addr prefixlength ?? ?? gateway-addr ?? ?? ?? ?? iface
674 for (String s : readRouteList("/proc/net/ipv6_route")) {
675 String[]fields = s.split("\\s+");
676 if (fields.length > 9) {
677 String iface = fields[9].trim();
678 if (interfaceName.equals(iface)) {
679 String dest = fields[0];
680 String prefix = fields[1];
681 String gate = fields[4];
682
683 try {
684 // prefix length stored as a hex string, ex 40
685 int prefixLength = Integer.parseInt(prefix, 16);
686
687 // address stored as a 32 char hex string
688 // ex fe800000000000000000000000000000
689 InetAddress destAddr = NetworkUtils.hexToInet6Address(dest);
690 LinkAddress linkAddress = new LinkAddress(destAddr, prefixLength);
691
692 InetAddress gateAddr = NetworkUtils.hexToInet6Address(gate);
693
694 RouteInfo route = new RouteInfo(linkAddress, gateAddr);
695 routes.add(route);
696 } catch (Exception e) {
697 Log.e(TAG, "Error parsing route " + s + " : " + e);
698 continue;
699 }
700 }
701 }
702 }
Jeff Sharkeyba2896e2011-11-30 18:13:54 -0800703 return routes.toArray(new RouteInfo[routes.size()]);
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -0700704 }
705
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800706 @Override
San Mehat873f2142010-01-14 10:25:07 -0800707 public void shutdown() {
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800708 // TODO: remove from aidl if nobody calls externally
709 mContext.enforceCallingOrSelfPermission(SHUTDOWN, TAG);
San Mehat873f2142010-01-14 10:25:07 -0800710
Joe Onorato8a9b2202010-02-26 18:56:32 -0800711 Slog.d(TAG, "Shutting down");
San Mehat873f2142010-01-14 10:25:07 -0800712 }
713
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800714 @Override
San Mehat873f2142010-01-14 10:25:07 -0800715 public boolean getIpForwardingEnabled() throws IllegalStateException{
Jeff Sharkey4529bb62011-12-14 10:31:54 -0800716 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
San Mehat873f2142010-01-14 10:25:07 -0800717
Jeff Sharkeyba2896e2011-11-30 18:13:54 -0800718 final NativeDaemonEvent event;
Kenny Roota80ce062010-06-01 13:23:53 -0700719 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -0800720 event = mConnector.execute("ipfwd", "status");
Kenny Roota80ce062010-06-01 13:23:53 -0700721 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -0800722 throw e.rethrowAsParcelableException();
Kenny Roota80ce062010-06-01 13:23:53 -0700723 }
San Mehat873f2142010-01-14 10:25:07 -0800724
Jeff Sharkeyba2896e2011-11-30 18:13:54 -0800725 // 211 Forwarding enabled
726 event.checkCode(IpFwdStatusResult);
727 return event.getMessage().endsWith("enabled");
San Mehat873f2142010-01-14 10:25:07 -0800728 }
729
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800730 @Override
731 public void setIpForwardingEnabled(boolean enable) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -0800732 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Jeff Sharkey31c6e482011-11-18 17:09:01 -0800733 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -0800734 mConnector.execute("ipfwd", enable ? "enable" : "disable");
Jeff Sharkey31c6e482011-11-18 17:09:01 -0800735 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -0800736 throw e.rethrowAsParcelableException();
Jeff Sharkey31c6e482011-11-18 17:09:01 -0800737 }
San Mehat873f2142010-01-14 10:25:07 -0800738 }
739
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800740 @Override
741 public void startTethering(String[] dhcpRange) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -0800742 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Robert Greenwaltbfb7bfa2010-03-24 16:03:21 -0700743 // cmd is "tether start first_start first_stop second_start second_stop ..."
744 // an odd number of addrs will fail
Jeff Sharkeyba2896e2011-11-30 18:13:54 -0800745
746 final Command cmd = new Command("tether", "start");
Robert Greenwaltbfb7bfa2010-03-24 16:03:21 -0700747 for (String d : dhcpRange) {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -0800748 cmd.appendArg(d);
Robert Greenwaltbfb7bfa2010-03-24 16:03:21 -0700749 }
Kenny Roota80ce062010-06-01 13:23:53 -0700750
751 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -0800752 mConnector.execute(cmd);
Kenny Roota80ce062010-06-01 13:23:53 -0700753 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -0800754 throw e.rethrowAsParcelableException();
Kenny Roota80ce062010-06-01 13:23:53 -0700755 }
San Mehat873f2142010-01-14 10:25:07 -0800756 }
757
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800758 @Override
759 public void stopTethering() {
Jeff Sharkey4529bb62011-12-14 10:31:54 -0800760 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Kenny Roota80ce062010-06-01 13:23:53 -0700761 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -0800762 mConnector.execute("tether", "stop");
Kenny Roota80ce062010-06-01 13:23:53 -0700763 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -0800764 throw e.rethrowAsParcelableException();
Kenny Roota80ce062010-06-01 13:23:53 -0700765 }
San Mehat873f2142010-01-14 10:25:07 -0800766 }
767
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800768 @Override
769 public boolean isTetheringStarted() {
Jeff Sharkey4529bb62011-12-14 10:31:54 -0800770 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
San Mehat873f2142010-01-14 10:25:07 -0800771
Jeff Sharkeyba2896e2011-11-30 18:13:54 -0800772 final NativeDaemonEvent event;
Kenny Roota80ce062010-06-01 13:23:53 -0700773 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -0800774 event = mConnector.execute("tether", "status");
Kenny Roota80ce062010-06-01 13:23:53 -0700775 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -0800776 throw e.rethrowAsParcelableException();
Kenny Roota80ce062010-06-01 13:23:53 -0700777 }
San Mehat873f2142010-01-14 10:25:07 -0800778
Jeff Sharkeyba2896e2011-11-30 18:13:54 -0800779 // 210 Tethering services started
780 event.checkCode(TetherStatusResult);
781 return event.getMessage().endsWith("started");
San Mehat873f2142010-01-14 10:25:07 -0800782 }
Matthew Xiefe19f122012-07-12 16:03:32 -0700783
784 // TODO(BT) Remove
fredc0f420372012-04-12 00:02:00 -0700785 public void startReverseTethering(String iface)
786 throws IllegalStateException {
787 if (DBG) Slog.d(TAG, "startReverseTethering in");
Matthew Xiefe19f122012-07-12 16:03:32 -0700788 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
fredc0f420372012-04-12 00:02:00 -0700789 // cmd is "tether start first_start first_stop second_start second_stop ..."
790 // an odd number of addrs will fail
791 String cmd = "tether start-reverse";
792 cmd += " " + iface;
793 if (DBG) Slog.d(TAG, "startReverseTethering cmd: " + cmd);
794 try {
795 mConnector.doCommand(cmd);
796 } catch (NativeDaemonConnectorException e) {
797 throw new IllegalStateException("Unable to communicate to native daemon");
798 }
799 BluetoothTetheringDataTracker.getInstance().startReverseTether(iface);
800
801 }
Matthew Xiefe19f122012-07-12 16:03:32 -0700802
803 // TODO(BT) Remove
fredc0f420372012-04-12 00:02:00 -0700804 public void stopReverseTethering() throws IllegalStateException {
Matthew Xiefe19f122012-07-12 16:03:32 -0700805 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
fredc0f420372012-04-12 00:02:00 -0700806 try {
807 mConnector.doCommand("tether stop-reverse");
808 } catch (NativeDaemonConnectorException e) {
809 throw new IllegalStateException("Unable to communicate to native daemon to stop tether");
810 }
811 BluetoothTetheringDataTracker.getInstance().stopReverseTether();
812 }
San Mehat873f2142010-01-14 10:25:07 -0800813
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800814 @Override
815 public void tetherInterface(String iface) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -0800816 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Kenny Roota80ce062010-06-01 13:23:53 -0700817 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -0800818 mConnector.execute("tether", "interface", "add", iface);
Kenny Roota80ce062010-06-01 13:23:53 -0700819 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -0800820 throw e.rethrowAsParcelableException();
Kenny Roota80ce062010-06-01 13:23:53 -0700821 }
San Mehat873f2142010-01-14 10:25:07 -0800822 }
823
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800824 @Override
San Mehat873f2142010-01-14 10:25:07 -0800825 public void untetherInterface(String iface) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -0800826 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Kenny Roota80ce062010-06-01 13:23:53 -0700827 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -0800828 mConnector.execute("tether", "interface", "remove", iface);
Kenny Roota80ce062010-06-01 13:23:53 -0700829 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -0800830 throw e.rethrowAsParcelableException();
Kenny Roota80ce062010-06-01 13:23:53 -0700831 }
San Mehat873f2142010-01-14 10:25:07 -0800832 }
833
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800834 @Override
835 public String[] listTetheredInterfaces() {
Jeff Sharkey4529bb62011-12-14 10:31:54 -0800836 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Kenny Roota80ce062010-06-01 13:23:53 -0700837 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -0800838 return NativeDaemonEvent.filterMessageList(
839 mConnector.executeForList("tether", "interface", "list"),
840 TetherInterfaceListResult);
Kenny Roota80ce062010-06-01 13:23:53 -0700841 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -0800842 throw e.rethrowAsParcelableException();
Kenny Roota80ce062010-06-01 13:23:53 -0700843 }
San Mehat873f2142010-01-14 10:25:07 -0800844 }
845
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800846 @Override
847 public void setDnsForwarders(String[] dns) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -0800848 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Jeff Sharkeyba2896e2011-11-30 18:13:54 -0800849
850 final Command cmd = new Command("tether", "dns", "set");
851 for (String s : dns) {
852 cmd.appendArg(NetworkUtils.numericToInetAddress(s).getHostAddress());
853 }
854
San Mehat873f2142010-01-14 10:25:07 -0800855 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -0800856 mConnector.execute(cmd);
857 } catch (NativeDaemonConnectorException e) {
858 throw e.rethrowAsParcelableException();
San Mehat873f2142010-01-14 10:25:07 -0800859 }
860 }
861
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800862 @Override
863 public String[] getDnsForwarders() {
Jeff Sharkey4529bb62011-12-14 10:31:54 -0800864 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Kenny Roota80ce062010-06-01 13:23:53 -0700865 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -0800866 return NativeDaemonEvent.filterMessageList(
867 mConnector.executeForList("tether", "dns", "list"), TetherDnsFwdTgtListResult);
Kenny Roota80ce062010-06-01 13:23:53 -0700868 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -0800869 throw e.rethrowAsParcelableException();
Kenny Roota80ce062010-06-01 13:23:53 -0700870 }
San Mehat873f2142010-01-14 10:25:07 -0800871 }
872
Jeff Sharkeyba2896e2011-11-30 18:13:54 -0800873 private void modifyNat(String action, String internalInterface, String externalInterface)
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -0700874 throws SocketException {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -0800875 final Command cmd = new Command("nat", action, internalInterface, externalInterface);
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -0700876
Jeff Sharkeyba2896e2011-11-30 18:13:54 -0800877 final NetworkInterface internalNetworkInterface = NetworkInterface.getByName(
878 internalInterface);
Robert Greenwalte83d1812011-11-21 14:44:39 -0800879 if (internalNetworkInterface == null) {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -0800880 cmd.appendArg("0");
Robert Greenwalte83d1812011-11-21 14:44:39 -0800881 } else {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -0800882 Collection<InterfaceAddress> interfaceAddresses = internalNetworkInterface
883 .getInterfaceAddresses();
884 cmd.appendArg(interfaceAddresses.size());
Robert Greenwalte83d1812011-11-21 14:44:39 -0800885 for (InterfaceAddress ia : interfaceAddresses) {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -0800886 InetAddress addr = NetworkUtils.getNetworkPart(
887 ia.getAddress(), ia.getNetworkPrefixLength());
888 cmd.appendArg(addr.getHostAddress() + "/" + ia.getNetworkPrefixLength());
Robert Greenwalte83d1812011-11-21 14:44:39 -0800889 }
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -0700890 }
891
Jeff Sharkey31c6e482011-11-18 17:09:01 -0800892 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -0800893 mConnector.execute(cmd);
Jeff Sharkey31c6e482011-11-18 17:09:01 -0800894 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -0800895 throw e.rethrowAsParcelableException();
Jeff Sharkey31c6e482011-11-18 17:09:01 -0800896 }
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -0700897 }
898
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800899 @Override
900 public void enableNat(String internalInterface, String externalInterface) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -0800901 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Kenny Roota80ce062010-06-01 13:23:53 -0700902 try {
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -0700903 modifyNat("enable", internalInterface, externalInterface);
Jeff Sharkeyba2896e2011-11-30 18:13:54 -0800904 } catch (SocketException e) {
905 throw new IllegalStateException(e);
Kenny Roota80ce062010-06-01 13:23:53 -0700906 }
San Mehat873f2142010-01-14 10:25:07 -0800907 }
908
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800909 @Override
910 public void disableNat(String internalInterface, String externalInterface) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -0800911 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Kenny Roota80ce062010-06-01 13:23:53 -0700912 try {
Robert Greenwalt3b28e9a2011-11-02 14:37:19 -0700913 modifyNat("disable", internalInterface, externalInterface);
Jeff Sharkeyba2896e2011-11-30 18:13:54 -0800914 } catch (SocketException e) {
915 throw new IllegalStateException(e);
Kenny Roota80ce062010-06-01 13:23:53 -0700916 }
San Mehat873f2142010-01-14 10:25:07 -0800917 }
San Mehat72759df2010-01-19 13:50:37 -0800918
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800919 @Override
920 public String[] listTtys() {
Jeff Sharkey4529bb62011-12-14 10:31:54 -0800921 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Kenny Roota80ce062010-06-01 13:23:53 -0700922 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -0800923 return NativeDaemonEvent.filterMessageList(
924 mConnector.executeForList("list_ttys"), TtyListResult);
Kenny Roota80ce062010-06-01 13:23:53 -0700925 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -0800926 throw e.rethrowAsParcelableException();
Kenny Roota80ce062010-06-01 13:23:53 -0700927 }
San Mehat72759df2010-01-19 13:50:37 -0800928 }
929
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800930 @Override
931 public void attachPppd(
932 String tty, String localAddr, String remoteAddr, String dns1Addr, String dns2Addr) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -0800933 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
San Mehat72759df2010-01-19 13:50:37 -0800934 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -0800935 mConnector.execute("pppd", "attach", tty,
Robert Greenwalte5903732011-02-22 16:00:42 -0800936 NetworkUtils.numericToInetAddress(localAddr).getHostAddress(),
937 NetworkUtils.numericToInetAddress(remoteAddr).getHostAddress(),
938 NetworkUtils.numericToInetAddress(dns1Addr).getHostAddress(),
Jeff Sharkeyba2896e2011-11-30 18:13:54 -0800939 NetworkUtils.numericToInetAddress(dns2Addr).getHostAddress());
Kenny Roota80ce062010-06-01 13:23:53 -0700940 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -0800941 throw e.rethrowAsParcelableException();
San Mehat72759df2010-01-19 13:50:37 -0800942 }
943 }
944
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800945 @Override
946 public void detachPppd(String tty) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -0800947 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Kenny Roota80ce062010-06-01 13:23:53 -0700948 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -0800949 mConnector.execute("pppd", "detach", tty);
Kenny Roota80ce062010-06-01 13:23:53 -0700950 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -0800951 throw e.rethrowAsParcelableException();
Kenny Roota80ce062010-06-01 13:23:53 -0700952 }
San Mehat72759df2010-01-19 13:50:37 -0800953 }
Robert Greenwaltce1200d2010-02-18 11:25:54 -0800954
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800955 @Override
956 public void startAccessPoint(
Irfan Sheriff90542752012-06-19 15:44:35 -0700957 WifiConfiguration wifiConfig, String wlanIface) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -0800958 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Kenny Roota80ce062010-06-01 13:23:53 -0700959 try {
Irfan Sheriffcb30b222011-07-29 20:54:52 -0700960 wifiFirmwareReload(wlanIface, "AP");
Kenny Roota80ce062010-06-01 13:23:53 -0700961 if (wifiConfig == null) {
Irfan Sheriff90542752012-06-19 15:44:35 -0700962 mConnector.execute("softap", "set", wlanIface);
Kenny Roota80ce062010-06-01 13:23:53 -0700963 } else {
Irfan Sheriff90542752012-06-19 15:44:35 -0700964 mConnector.execute("softap", "set", wlanIface, wifiConfig.SSID,
Jeff Sharkeyba2896e2011-11-30 18:13:54 -0800965 getSecurityType(wifiConfig), wifiConfig.preSharedKey);
Kenny Roota80ce062010-06-01 13:23:53 -0700966 }
Jeff Sharkeyba2896e2011-11-30 18:13:54 -0800967 mConnector.execute("softap", "startap");
Kenny Roota80ce062010-06-01 13:23:53 -0700968 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -0800969 throw e.rethrowAsParcelableException();
Irfan Sheriff9ab518ad2010-03-12 15:48:17 -0800970 }
Irfan Sheriff5321aef2010-02-12 12:35:59 -0800971 }
972
Jeff Sharkeyba2896e2011-11-30 18:13:54 -0800973 private static String getSecurityType(WifiConfiguration wifiConfig) {
Irfan Sheriffec8d23a2011-02-16 17:00:33 -0800974 switch (wifiConfig.getAuthType()) {
975 case KeyMgmt.WPA_PSK:
976 return "wpa-psk";
977 case KeyMgmt.WPA2_PSK:
978 return "wpa2-psk";
979 default:
980 return "open";
981 }
982 }
983
Irfan Sheriffcb30b222011-07-29 20:54:52 -0700984 /* @param mode can be "AP", "STA" or "P2P" */
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800985 @Override
986 public void wifiFirmwareReload(String wlanIface, String mode) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -0800987 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Irfan Sheriffcb30b222011-07-29 20:54:52 -0700988 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -0800989 mConnector.execute("softap", "fwreload", wlanIface, mode);
Irfan Sheriffcb30b222011-07-29 20:54:52 -0700990 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -0800991 throw e.rethrowAsParcelableException();
Irfan Sheriffcb30b222011-07-29 20:54:52 -0700992 }
993 }
994
Jeff Sharkeyaf75c332011-11-18 12:41:12 -0800995 @Override
996 public void stopAccessPoint(String wlanIface) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -0800997 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Kenny Roota80ce062010-06-01 13:23:53 -0700998 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -0800999 mConnector.execute("softap", "stopap");
Irfan Sheriffcb30b222011-07-29 20:54:52 -07001000 wifiFirmwareReload(wlanIface, "STA");
Kenny Roota80ce062010-06-01 13:23:53 -07001001 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -08001002 throw e.rethrowAsParcelableException();
Kenny Roota80ce062010-06-01 13:23:53 -07001003 }
Irfan Sheriff5321aef2010-02-12 12:35:59 -08001004 }
1005
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001006 @Override
Irfan Sheriff90542752012-06-19 15:44:35 -07001007 public void setAccessPoint(WifiConfiguration wifiConfig, String wlanIface) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001008 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Kenny Roota80ce062010-06-01 13:23:53 -07001009 try {
1010 if (wifiConfig == null) {
Irfan Sheriff90542752012-06-19 15:44:35 -07001011 mConnector.execute("softap", "set", wlanIface);
Kenny Roota80ce062010-06-01 13:23:53 -07001012 } else {
Irfan Sheriff90542752012-06-19 15:44:35 -07001013 mConnector.execute("softap", "set", wlanIface, wifiConfig.SSID,
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001014 getSecurityType(wifiConfig), wifiConfig.preSharedKey);
Kenny Roota80ce062010-06-01 13:23:53 -07001015 }
1016 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -08001017 throw e.rethrowAsParcelableException();
Irfan Sheriffc2f54c22010-03-18 14:02:22 -07001018 }
1019 }
San Mehat91cac642010-03-31 14:31:36 -07001020
Jeff Sharkeyeedcb952011-05-17 14:55:15 -07001021 @Override
Jeff Sharkeye8914c32012-05-01 16:26:09 -07001022 public NetworkStats getNetworkStatsSummaryDev() {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001023 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Jeff Sharkeye8914c32012-05-01 16:26:09 -07001024 return mStatsFactory.readNetworkStatsSummaryDev();
1025 }
1026
1027 @Override
1028 public NetworkStats getNetworkStatsSummaryXt() {
1029 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1030 return mStatsFactory.readNetworkStatsSummaryXt();
Jeff Sharkeyae2c1812011-10-04 13:11:40 -07001031 }
1032
Jeff Sharkeyeedcb952011-05-17 14:55:15 -07001033 @Override
Jeff Sharkey9a13f362011-04-26 16:25:36 -07001034 public NetworkStats getNetworkStatsDetail() {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001035 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Jeff Sharkey1059c3c2011-10-04 16:54:49 -07001036 return mStatsFactory.readNetworkStatsDetail(UID_ALL);
San Mehat91cac642010-03-31 14:31:36 -07001037 }
1038
Jeff Sharkeyeedcb952011-05-17 14:55:15 -07001039 @Override
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001040 public void setInterfaceQuota(String iface, long quotaBytes) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001041 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001042
Jeff Sharkey350083e2011-06-29 10:45:16 -07001043 // silently discard when control disabled
1044 // TODO: eventually migrate to be always enabled
1045 if (!mBandwidthControlEnabled) return;
1046
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001047 synchronized (mQuotaLock) {
Jeff Sharkeyb24a7852012-05-01 15:19:37 -07001048 if (mActiveQuotas.containsKey(iface)) {
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001049 throw new IllegalStateException("iface " + iface + " already has quota");
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001050 }
1051
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001052 try {
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001053 // TODO: support quota shared across interfaces
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001054 mConnector.execute("bandwidth", "setiquota", iface, quotaBytes);
Jeff Sharkeyb24a7852012-05-01 15:19:37 -07001055 mActiveQuotas.put(iface, quotaBytes);
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001056 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -08001057 throw e.rethrowAsParcelableException();
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001058 }
Ashish Sharma50fd36d2011-06-15 19:34:53 -07001059 }
1060 }
1061
1062 @Override
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001063 public void removeInterfaceQuota(String iface) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001064 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001065
Jeff Sharkey350083e2011-06-29 10:45:16 -07001066 // silently discard when control disabled
1067 // TODO: eventually migrate to be always enabled
1068 if (!mBandwidthControlEnabled) return;
1069
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001070 synchronized (mQuotaLock) {
Jeff Sharkeyb24a7852012-05-01 15:19:37 -07001071 if (!mActiveQuotas.containsKey(iface)) {
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001072 // TODO: eventually consider throwing
1073 return;
1074 }
1075
Jeff Sharkeyb24a7852012-05-01 15:19:37 -07001076 mActiveQuotas.remove(iface);
1077 mActiveAlerts.remove(iface);
Jeff Sharkey38ddeaa2011-11-08 13:04:22 -08001078
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001079 try {
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001080 // TODO: support quota shared across interfaces
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001081 mConnector.execute("bandwidth", "removeiquota", iface);
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001082 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -08001083 throw e.rethrowAsParcelableException();
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001084 }
1085 }
1086 }
1087
1088 @Override
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001089 public void setInterfaceAlert(String iface, long alertBytes) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001090 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001091
1092 // silently discard when control disabled
1093 // TODO: eventually migrate to be always enabled
1094 if (!mBandwidthControlEnabled) return;
1095
1096 // quick sanity check
Jeff Sharkeyb24a7852012-05-01 15:19:37 -07001097 if (!mActiveQuotas.containsKey(iface)) {
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001098 throw new IllegalStateException("setting alert requires existing quota on iface");
1099 }
1100
1101 synchronized (mQuotaLock) {
Jeff Sharkeyb24a7852012-05-01 15:19:37 -07001102 if (mActiveAlerts.containsKey(iface)) {
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001103 throw new IllegalStateException("iface " + iface + " already has alert");
1104 }
1105
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001106 try {
1107 // TODO: support alert shared across interfaces
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001108 mConnector.execute("bandwidth", "setinterfacealert", iface, alertBytes);
Jeff Sharkeyb24a7852012-05-01 15:19:37 -07001109 mActiveAlerts.put(iface, alertBytes);
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001110 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -08001111 throw e.rethrowAsParcelableException();
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001112 }
1113 }
1114 }
1115
1116 @Override
1117 public void removeInterfaceAlert(String iface) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001118 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001119
1120 // silently discard when control disabled
1121 // TODO: eventually migrate to be always enabled
1122 if (!mBandwidthControlEnabled) return;
1123
1124 synchronized (mQuotaLock) {
Jeff Sharkeyb24a7852012-05-01 15:19:37 -07001125 if (!mActiveAlerts.containsKey(iface)) {
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001126 // TODO: eventually consider throwing
1127 return;
1128 }
1129
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001130 try {
1131 // TODO: support alert shared across interfaces
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001132 mConnector.execute("bandwidth", "removeinterfacealert", iface);
Jeff Sharkeyb24a7852012-05-01 15:19:37 -07001133 mActiveAlerts.remove(iface);
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001134 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -08001135 throw e.rethrowAsParcelableException();
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001136 }
1137 }
1138 }
1139
1140 @Override
1141 public void setGlobalAlert(long alertBytes) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001142 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001143
1144 // silently discard when control disabled
1145 // TODO: eventually migrate to be always enabled
1146 if (!mBandwidthControlEnabled) return;
1147
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001148 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001149 mConnector.execute("bandwidth", "setglobalalert", alertBytes);
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001150 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -08001151 throw e.rethrowAsParcelableException();
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001152 }
1153 }
1154
1155 @Override
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001156 public void setUidNetworkRules(int uid, boolean rejectOnQuotaInterfaces) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001157 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001158
Jeff Sharkey350083e2011-06-29 10:45:16 -07001159 // silently discard when control disabled
1160 // TODO: eventually migrate to be always enabled
1161 if (!mBandwidthControlEnabled) return;
1162
Jeff Sharkeyb24a7852012-05-01 15:19:37 -07001163 synchronized (mQuotaLock) {
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001164 final boolean oldRejectOnQuota = mUidRejectOnQuota.get(uid, false);
1165 if (oldRejectOnQuota == rejectOnQuotaInterfaces) {
1166 // TODO: eventually consider throwing
1167 return;
1168 }
1169
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001170 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001171 mConnector.execute("bandwidth",
1172 rejectOnQuotaInterfaces ? "addnaughtyapps" : "removenaughtyapps", uid);
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001173 if (rejectOnQuotaInterfaces) {
1174 mUidRejectOnQuota.put(uid, true);
1175 } else {
1176 mUidRejectOnQuota.delete(uid);
1177 }
1178 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -08001179 throw e.rethrowAsParcelableException();
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001180 }
Ashish Sharma50fd36d2011-06-15 19:34:53 -07001181 }
1182 }
1183
Jeff Sharkey63d27a92011-08-03 17:04:22 -07001184 @Override
1185 public boolean isBandwidthControlEnabled() {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001186 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Jeff Sharkey63d27a92011-08-03 17:04:22 -07001187 return mBandwidthControlEnabled;
1188 }
1189
1190 @Override
Jeff Sharkeyeedcb952011-05-17 14:55:15 -07001191 public NetworkStats getNetworkStatsUidDetail(int uid) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001192 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Jeff Sharkey1059c3c2011-10-04 16:54:49 -07001193 return mStatsFactory.readNetworkStatsDetail(uid);
Jeff Sharkeyeedcb952011-05-17 14:55:15 -07001194 }
1195
Jeff Sharkeycdd02c5d2011-09-16 01:52:49 -07001196 @Override
1197 public NetworkStats getNetworkStatsTethering(String[] ifacePairs) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001198 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Jeff Sharkeycdd02c5d2011-09-16 01:52:49 -07001199
1200 if (ifacePairs.length % 2 != 0) {
1201 throw new IllegalArgumentException(
1202 "unexpected ifacePairs; length=" + ifacePairs.length);
1203 }
1204
1205 final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 1);
1206 for (int i = 0; i < ifacePairs.length; i += 2) {
1207 final String ifaceIn = ifacePairs[i];
1208 final String ifaceOut = ifacePairs[i + 1];
1209 if (ifaceIn != null && ifaceOut != null) {
1210 stats.combineValues(getNetworkStatsTethering(ifaceIn, ifaceOut));
1211 }
1212 }
1213 return stats;
1214 }
1215
1216 private NetworkStats.Entry getNetworkStatsTethering(String ifaceIn, String ifaceOut) {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001217 final NativeDaemonEvent event;
Jeff Sharkeycdd02c5d2011-09-16 01:52:49 -07001218 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001219 event = mConnector.execute("bandwidth", "gettetherstats", ifaceIn, ifaceOut);
Jeff Sharkeycdd02c5d2011-09-16 01:52:49 -07001220 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -08001221 throw e.rethrowAsParcelableException();
Jeff Sharkeycdd02c5d2011-09-16 01:52:49 -07001222 }
1223
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001224 event.checkCode(TetheringStatsResult);
Jeff Sharkeycdd02c5d2011-09-16 01:52:49 -07001225
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001226 // 221 ifaceIn ifaceOut rx_bytes rx_packets tx_bytes tx_packets
1227 final StringTokenizer tok = new StringTokenizer(event.getMessage());
1228 tok.nextToken();
1229 tok.nextToken();
Jeff Sharkeycdd02c5d2011-09-16 01:52:49 -07001230
1231 try {
1232 final NetworkStats.Entry entry = new NetworkStats.Entry();
1233 entry.iface = ifaceIn;
Jeff Sharkey905b5892011-09-30 15:19:49 -07001234 entry.uid = UID_TETHERING;
Jeff Sharkeycdd02c5d2011-09-16 01:52:49 -07001235 entry.set = SET_DEFAULT;
1236 entry.tag = TAG_NONE;
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001237 entry.rxBytes = Long.parseLong(tok.nextToken());
1238 entry.rxPackets = Long.parseLong(tok.nextToken());
1239 entry.txBytes = Long.parseLong(tok.nextToken());
1240 entry.txPackets = Long.parseLong(tok.nextToken());
Jeff Sharkeycdd02c5d2011-09-16 01:52:49 -07001241 return entry;
1242 } catch (NumberFormatException e) {
1243 throw new IllegalStateException(
1244 "problem parsing tethering stats for " + ifaceIn + " " + ifaceOut + ": " + e);
1245 }
1246 }
1247
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001248 @Override
San Mehatf0db6e12010-04-07 15:22:10 -07001249 public void setInterfaceThrottle(String iface, int rxKbps, int txKbps) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001250 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Kenny Roota80ce062010-06-01 13:23:53 -07001251 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001252 mConnector.execute("interface", "setthrottle", iface, rxKbps, txKbps);
Kenny Roota80ce062010-06-01 13:23:53 -07001253 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -08001254 throw e.rethrowAsParcelableException();
Kenny Roota80ce062010-06-01 13:23:53 -07001255 }
San Mehat91cac642010-03-31 14:31:36 -07001256 }
1257
1258 private int getInterfaceThrottle(String iface, boolean rx) {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001259 final NativeDaemonEvent event;
San Mehat91cac642010-03-31 14:31:36 -07001260 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001261 event = mConnector.execute("interface", "getthrottle", iface, rx ? "rx" : "tx");
1262 } catch (NativeDaemonConnectorException e) {
1263 throw e.rethrowAsParcelableException();
San Mehat91cac642010-03-31 14:31:36 -07001264 }
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001265
1266 if (rx) {
1267 event.checkCode(InterfaceRxThrottleResult);
1268 } else {
1269 event.checkCode(InterfaceTxThrottleResult);
1270 }
1271
1272 try {
1273 return Integer.parseInt(event.getMessage());
1274 } catch (NumberFormatException e) {
1275 throw new IllegalStateException("unexpected response:" + event);
1276 }
San Mehat91cac642010-03-31 14:31:36 -07001277 }
1278
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001279 @Override
San Mehat91cac642010-03-31 14:31:36 -07001280 public int getInterfaceRxThrottle(String iface) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001281 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
San Mehat91cac642010-03-31 14:31:36 -07001282 return getInterfaceThrottle(iface, true);
1283 }
1284
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001285 @Override
San Mehat91cac642010-03-31 14:31:36 -07001286 public int getInterfaceTxThrottle(String iface) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001287 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
San Mehat91cac642010-03-31 14:31:36 -07001288 return getInterfaceThrottle(iface, false);
1289 }
Jeff Sharkey9a13f362011-04-26 16:25:36 -07001290
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001291 @Override
1292 public void setDefaultInterfaceForDns(String iface) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001293 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Mattias Falk7475c0c2011-04-04 16:10:36 +02001294 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001295 mConnector.execute("resolver", "setdefaultif", iface);
Mattias Falk7475c0c2011-04-04 16:10:36 +02001296 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -08001297 throw e.rethrowAsParcelableException();
Mattias Falk7475c0c2011-04-04 16:10:36 +02001298 }
1299 }
1300
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001301 @Override
1302 public void setDnsServersForInterface(String iface, String[] servers) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001303 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001304
1305 final Command cmd = new Command("resolver", "setifdns", iface);
1306 for (String s : servers) {
1307 InetAddress a = NetworkUtils.numericToInetAddress(s);
1308 if (a.isAnyLocalAddress() == false) {
1309 cmd.appendArg(a.getHostAddress());
Mattias Falk7475c0c2011-04-04 16:10:36 +02001310 }
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001311 }
1312
1313 try {
1314 mConnector.execute(cmd);
Mattias Falk7475c0c2011-04-04 16:10:36 +02001315 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -08001316 throw e.rethrowAsParcelableException();
Mattias Falk7475c0c2011-04-04 16:10:36 +02001317 }
1318 }
1319
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001320 @Override
1321 public void flushDefaultDnsCache() {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001322 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Mattias Falk7475c0c2011-04-04 16:10:36 +02001323 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001324 mConnector.execute("resolver", "flushdefaultif");
Mattias Falk7475c0c2011-04-04 16:10:36 +02001325 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -08001326 throw e.rethrowAsParcelableException();
Mattias Falk7475c0c2011-04-04 16:10:36 +02001327 }
1328 }
1329
Jeff Sharkeyaf75c332011-11-18 12:41:12 -08001330 @Override
1331 public void flushInterfaceDnsCache(String iface) {
Jeff Sharkey4529bb62011-12-14 10:31:54 -08001332 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
Mattias Falk7475c0c2011-04-04 16:10:36 +02001333 try {
Jeff Sharkeyba2896e2011-11-30 18:13:54 -08001334 mConnector.execute("resolver", "flushif", iface);
Mattias Falk7475c0c2011-04-04 16:10:36 +02001335 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey276642b2011-12-01 11:24:24 -08001336 throw e.rethrowAsParcelableException();
Mattias Falk7475c0c2011-04-04 16:10:36 +02001337 }
1338 }
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07001339
1340 /** {@inheritDoc} */
1341 public void monitor() {
1342 if (mConnector != null) {
1343 mConnector.monitor();
1344 }
1345 }
Jeff Sharkey47eb1022011-08-25 17:48:52 -07001346
1347 @Override
1348 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1349 mContext.enforceCallingOrSelfPermission(DUMP, TAG);
1350
Robert Greenwalt470fd722012-01-18 12:51:15 -08001351 pw.println("NetworkManagementService NativeDaemonConnector Log:");
1352 mConnector.dump(fd, pw, args);
1353 pw.println();
1354
Jeff Sharkey47eb1022011-08-25 17:48:52 -07001355 pw.print("Bandwidth control enabled: "); pw.println(mBandwidthControlEnabled);
1356
1357 synchronized (mQuotaLock) {
Jeff Sharkeyb24a7852012-05-01 15:19:37 -07001358 pw.print("Active quota ifaces: "); pw.println(mActiveQuotas.toString());
1359 pw.print("Active alert ifaces: "); pw.println(mActiveAlerts.toString());
Jeff Sharkey47eb1022011-08-25 17:48:52 -07001360 }
1361
1362 synchronized (mUidRejectOnQuota) {
1363 pw.print("UID reject on quota ifaces: [");
1364 final int size = mUidRejectOnQuota.size();
1365 for (int i = 0; i < size; i++) {
1366 pw.print(mUidRejectOnQuota.keyAt(i));
1367 if (i < size - 1) pw.print(",");
1368 }
1369 pw.println("]");
1370 }
1371 }
San Mehat873f2142010-01-14 10:25:07 -08001372}