blob: b05705eb1224ab5c4a5117774e7a1b1028117750 [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 Sharkey47eb1022011-08-25 17:48:52 -070019import static android.Manifest.permission.DUMP;
Jeff Sharkey350083e2011-06-29 10:45:16 -070020import static android.Manifest.permission.MANAGE_NETWORK_POLICY;
Jeff Sharkeyb5d55e32011-08-10 17:53:27 -070021import static android.net.NetworkStats.SET_DEFAULT;
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -070022import static android.net.NetworkStats.TAG_NONE;
23import static android.net.NetworkStats.UID_ALL;
Jeff Sharkeyae2c1812011-10-04 13:11:40 -070024import static android.net.TrafficStats.UID_TETHERING;
Jeff Sharkey350083e2011-06-29 10:45:16 -070025import static android.provider.Settings.Secure.NETSTATS_ENABLED;
Jeff Sharkeya63ba592011-07-19 23:47:12 -070026import static com.android.server.NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED;
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -070027
San Mehat873f2142010-01-14 10:25:07 -080028import android.content.Context;
San Mehat873f2142010-01-14 10:25:07 -080029import android.content.pm.PackageManager;
San Mehat4d02d002010-01-22 16:07:46 -080030import android.net.INetworkManagementEventObserver;
Jeff Sharkeyeedcb952011-05-17 14:55:15 -070031import android.net.InterfaceConfiguration;
Robert Greenwalted126402011-01-28 15:34:55 -080032import android.net.LinkAddress;
Jeff Sharkeyeedcb952011-05-17 14:55:15 -070033import android.net.NetworkStats;
Robert Greenwalted126402011-01-28 15:34:55 -080034import android.net.NetworkUtils;
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -070035import android.net.RouteInfo;
Irfan Sheriff9ab518ad2010-03-12 15:48:17 -080036import android.net.wifi.WifiConfiguration;
37import android.net.wifi.WifiConfiguration.KeyMgmt;
Jeff Sharkeyeedcb952011-05-17 14:55:15 -070038import android.os.Binder;
San Mehat873f2142010-01-14 10:25:07 -080039import android.os.INetworkManagementService;
Jeff Sharkey9a13f362011-04-26 16:25:36 -070040import android.os.SystemClock;
Marco Nelissen62dbb222010-02-18 10:56:30 -080041import android.os.SystemProperties;
Jeff Sharkey350083e2011-06-29 10:45:16 -070042import android.provider.Settings;
Irfan Sheriff9ab518ad2010-03-12 15:48:17 -080043import android.util.Log;
Joe Onorato8a9b2202010-02-26 18:56:32 -080044import android.util.Slog;
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -070045import android.util.SparseBooleanArray;
San Mehat873f2142010-01-14 10:25:07 -080046
Jeff Sharkey1059c3c2011-10-04 16:54:49 -070047import com.android.internal.net.NetworkStatsFactory;
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -070048import com.google.android.collect.Sets;
Jeff Sharkey4414cea2011-06-24 17:05:24 -070049
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -070050import java.io.BufferedReader;
51import java.io.DataInputStream;
San Mehat873f2142010-01-14 10:25:07 -080052import java.io.File;
Jeff Sharkey47eb1022011-08-25 17:48:52 -070053import java.io.FileDescriptor;
Jeff Sharkey9a13f362011-04-26 16:25:36 -070054import java.io.FileInputStream;
Jeff Sharkey9a13f362011-04-26 16:25:36 -070055import java.io.IOException;
Jeff Sharkey9a13f362011-04-26 16:25:36 -070056import java.io.InputStreamReader;
Jeff Sharkey47eb1022011-08-25 17:48:52 -070057import java.io.PrintWriter;
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -070058import java.net.Inet4Address;
Jeff Sharkeyeedcb952011-05-17 14:55:15 -070059import java.net.InetAddress;
60import java.util.ArrayList;
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -070061import java.util.HashSet;
Jeff Sharkeyeedcb952011-05-17 14:55:15 -070062import java.util.NoSuchElementException;
63import java.util.StringTokenizer;
Robert Greenwalte5c3afb2010-09-22 14:32:35 -070064import java.util.concurrent.CountDownLatch;
San Mehat873f2142010-01-14 10:25:07 -080065
66/**
67 * @hide
68 */
Jeff Sharkey8e9992a2011-08-23 18:37:23 -070069public class NetworkManagementService extends INetworkManagementService.Stub
70 implements Watchdog.Monitor {
Jeff Sharkeyeedcb952011-05-17 14:55:15 -070071 private static final String TAG = "NetworkManagementService";
Dianne Hackborncef65ee2010-09-30 18:27:22 -070072 private static final boolean DBG = false;
Kenny Root305bcbf2010-09-03 07:56:38 -070073 private static final String NETD_TAG = "NetdConnector";
74
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -070075 private static final int ADD = 1;
76 private static final int REMOVE = 2;
77
Jeff Sharkey8e9992a2011-08-23 18:37:23 -070078 /**
79 * Name representing {@link #setGlobalAlert(long)} limit when delivered to
80 * {@link INetworkManagementEventObserver#limitReached(String, String)}.
81 */
82 public static final String LIMIT_GLOBAL_ALERT = "globalAlert";
83
San Mehat873f2142010-01-14 10:25:07 -080084 class NetdResponseCode {
JP Abgrall12b933d2011-07-14 18:09:22 -070085 /* Keep in sync with system/netd/ResponseCode.h */
San Mehat873f2142010-01-14 10:25:07 -080086 public static final int InterfaceListResult = 110;
87 public static final int TetherInterfaceListResult = 111;
88 public static final int TetherDnsFwdTgtListResult = 112;
San Mehat72759df2010-01-19 13:50:37 -080089 public static final int TtyListResult = 113;
San Mehat873f2142010-01-14 10:25:07 -080090
91 public static final int TetherStatusResult = 210;
92 public static final int IpFwdStatusResult = 211;
San Mehated4fc8a2010-01-22 12:28:36 -080093 public static final int InterfaceGetCfgResult = 213;
Robert Greenwalte3253922010-02-18 09:23:25 -080094 public static final int SoftapStatusResult = 214;
San Mehat91cac642010-03-31 14:31:36 -070095 public static final int InterfaceRxCounterResult = 216;
96 public static final int InterfaceTxCounterResult = 217;
97 public static final int InterfaceRxThrottleResult = 218;
98 public static final int InterfaceTxThrottleResult = 219;
Jeff Sharkeycdd02c5d2011-09-16 01:52:49 -070099 public static final int QuotaCounterResult = 220;
100 public static final int TetheringStatsResult = 221;
Robert Greenwalte3253922010-02-18 09:23:25 -0800101
102 public static final int InterfaceChange = 600;
JP Abgrall12b933d2011-07-14 18:09:22 -0700103 public static final int BandwidthControl = 601;
San Mehat873f2142010-01-14 10:25:07 -0800104 }
105
106 /**
107 * Binder context for this service
108 */
109 private Context mContext;
110
111 /**
112 * connector object for communicating with netd
113 */
114 private NativeDaemonConnector mConnector;
115
Robert Greenwalte5c3afb2010-09-22 14:32:35 -0700116 private Thread mThread;
117 private final CountDownLatch mConnectedSignal = new CountDownLatch(1);
118
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -0700119 // TODO: replace with RemoteCallbackList
San Mehat4d02d002010-01-22 16:07:46 -0800120 private ArrayList<INetworkManagementEventObserver> mObservers;
121
Jeff Sharkey1059c3c2011-10-04 16:54:49 -0700122 private final NetworkStatsFactory mStatsFactory = new NetworkStatsFactory();
123
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -0700124 private Object mQuotaLock = new Object();
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -0700125 /** Set of interfaces with active quotas. */
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -0700126 private HashSet<String> mActiveQuotaIfaces = Sets.newHashSet();
127 /** Set of interfaces with active alerts. */
128 private HashSet<String> mActiveAlertIfaces = Sets.newHashSet();
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -0700129 /** Set of UIDs with active reject rules. */
130 private SparseBooleanArray mUidRejectOnQuota = new SparseBooleanArray();
131
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -0700132 private volatile boolean mBandwidthControlEnabled;
Jeff Sharkey350083e2011-06-29 10:45:16 -0700133
San Mehat873f2142010-01-14 10:25:07 -0800134 /**
135 * Constructs a new NetworkManagementService instance
136 *
137 * @param context Binder context for this service
138 */
Jeff Sharkey1059c3c2011-10-04 16:54:49 -0700139 private NetworkManagementService(Context context) {
San Mehat873f2142010-01-14 10:25:07 -0800140 mContext = context;
San Mehat4d02d002010-01-22 16:07:46 -0800141 mObservers = new ArrayList<INetworkManagementEventObserver>();
142
Marco Nelissen62dbb222010-02-18 10:56:30 -0800143 if ("simulator".equals(SystemProperties.get("ro.product.device"))) {
144 return;
145 }
146
San Mehat873f2142010-01-14 10:25:07 -0800147 mConnector = new NativeDaemonConnector(
Kenny Root305bcbf2010-09-03 07:56:38 -0700148 new NetdCallbackReceiver(), "netd", 10, NETD_TAG);
Robert Greenwalte5c3afb2010-09-22 14:32:35 -0700149 mThread = new Thread(mConnector, NETD_TAG);
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -0700150
151 // Add ourself to the Watchdog monitors.
152 Watchdog.getInstance().addMonitor(this);
Robert Greenwalte5c3afb2010-09-22 14:32:35 -0700153 }
154
155 public static NetworkManagementService create(Context context) throws InterruptedException {
Jeff Sharkey1059c3c2011-10-04 16:54:49 -0700156 NetworkManagementService service = new NetworkManagementService(context);
Robert Greenwalte5c3afb2010-09-22 14:32:35 -0700157 if (DBG) Slog.d(TAG, "Creating NetworkManagementService");
158 service.mThread.start();
159 if (DBG) Slog.d(TAG, "Awaiting socket connection");
160 service.mConnectedSignal.await();
161 if (DBG) Slog.d(TAG, "Connected");
162 return service;
San Mehat873f2142010-01-14 10:25:07 -0800163 }
164
Jeff Sharkey350083e2011-06-29 10:45:16 -0700165 public void systemReady() {
Jeff Sharkey350083e2011-06-29 10:45:16 -0700166 // only enable bandwidth control when support exists, and requested by
167 // system setting.
Jeff Sharkey350083e2011-06-29 10:45:16 -0700168 final boolean hasKernelSupport = new File("/proc/net/xt_qtaguid/ctrl").exists();
169 final boolean shouldEnable =
Jeff Sharkey05355c32011-08-09 14:44:19 -0700170 Settings.Secure.getInt(mContext.getContentResolver(), NETSTATS_ENABLED, 1) != 0;
Jeff Sharkey350083e2011-06-29 10:45:16 -0700171
Jeff Sharkey350083e2011-06-29 10:45:16 -0700172 if (hasKernelSupport && shouldEnable) {
173 Slog.d(TAG, "enabling bandwidth control");
174 try {
175 mConnector.doCommand("bandwidth enable");
176 mBandwidthControlEnabled = true;
177 } catch (NativeDaemonConnectorException e) {
Jeff Sharkey1059c3c2011-10-04 16:54:49 -0700178 Log.wtf(TAG, "problem enabling bandwidth controls", e);
Jeff Sharkey350083e2011-06-29 10:45:16 -0700179 }
180 } else {
181 Slog.d(TAG, "not enabling bandwidth control");
182 }
Jeff Sharkey62a2c8f2011-07-13 15:24:02 -0700183
Jeff Sharkeya63ba592011-07-19 23:47:12 -0700184 SystemProperties.set(PROP_QTAGUID_ENABLED, mBandwidthControlEnabled ? "1" : "0");
Jeff Sharkey350083e2011-06-29 10:45:16 -0700185 }
186
San Mehat4d02d002010-01-22 16:07:46 -0800187 public void registerObserver(INetworkManagementEventObserver obs) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800188 Slog.d(TAG, "Registering observer");
San Mehat4d02d002010-01-22 16:07:46 -0800189 mObservers.add(obs);
190 }
191
192 public void unregisterObserver(INetworkManagementEventObserver obs) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800193 Slog.d(TAG, "Unregistering observer");
San Mehat4d02d002010-01-22 16:07:46 -0800194 mObservers.remove(mObservers.indexOf(obs));
195 }
196
197 /**
Mike J. Chen6143f5f2011-06-23 15:17:51 -0700198 * Notify our observers of an interface status change
San Mehat4d02d002010-01-22 16:07:46 -0800199 */
Mike J. Chen6143f5f2011-06-23 15:17:51 -0700200 private void notifyInterfaceStatusChanged(String iface, boolean up) {
San Mehat4d02d002010-01-22 16:07:46 -0800201 for (INetworkManagementEventObserver obs : mObservers) {
202 try {
Mike J. Chen6143f5f2011-06-23 15:17:51 -0700203 obs.interfaceStatusChanged(iface, up);
204 } catch (Exception ex) {
205 Slog.w(TAG, "Observer notifier failed", ex);
206 }
207 }
208 }
209
210 /**
Mike J. Chenf59c7d02011-06-23 15:33:15 -0700211 * Notify our observers of an interface link state change
Mike J. Chen6143f5f2011-06-23 15:17:51 -0700212 * (typically, an Ethernet cable has been plugged-in or unplugged).
213 */
214 private void notifyInterfaceLinkStateChanged(String iface, boolean up) {
215 for (INetworkManagementEventObserver obs : mObservers) {
216 try {
217 obs.interfaceLinkStateChanged(iface, up);
San Mehat4d02d002010-01-22 16:07:46 -0800218 } catch (Exception ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800219 Slog.w(TAG, "Observer notifier failed", ex);
San Mehat4d02d002010-01-22 16:07:46 -0800220 }
221 }
222 }
223
224 /**
225 * Notify our observers of an interface addition.
226 */
227 private void notifyInterfaceAdded(String iface) {
228 for (INetworkManagementEventObserver obs : mObservers) {
229 try {
230 obs.interfaceAdded(iface);
231 } catch (Exception ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800232 Slog.w(TAG, "Observer notifier failed", ex);
San Mehat4d02d002010-01-22 16:07:46 -0800233 }
234 }
235 }
236
237 /**
238 * Notify our observers of an interface removal.
239 */
240 private void notifyInterfaceRemoved(String iface) {
241 for (INetworkManagementEventObserver obs : mObservers) {
242 try {
243 obs.interfaceRemoved(iface);
244 } catch (Exception ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800245 Slog.w(TAG, "Observer notifier failed", ex);
San Mehat4d02d002010-01-22 16:07:46 -0800246 }
247 }
248 }
249
Robert Greenwalte5c3afb2010-09-22 14:32:35 -0700250 /**
JP Abgrall12b933d2011-07-14 18:09:22 -0700251 * Notify our observers of a limit reached.
252 */
253 private void notifyLimitReached(String limitName, String iface) {
254 for (INetworkManagementEventObserver obs : mObservers) {
255 try {
256 obs.limitReached(limitName, iface);
JP Abgrall12b933d2011-07-14 18:09:22 -0700257 } catch (Exception ex) {
258 Slog.w(TAG, "Observer notifier failed", ex);
259 }
260 }
261 }
262
263 /**
Robert Greenwalte5c3afb2010-09-22 14:32:35 -0700264 * Let us know the daemon is connected
265 */
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -0700266 protected void onDaemonConnected() {
Robert Greenwalte5c3afb2010-09-22 14:32:35 -0700267 if (DBG) Slog.d(TAG, "onConnected");
268 mConnectedSignal.countDown();
269 }
270
San Mehat4d02d002010-01-22 16:07:46 -0800271
San Mehat873f2142010-01-14 10:25:07 -0800272 //
273 // Netd Callback handling
274 //
275
276 class NetdCallbackReceiver implements INativeDaemonConnectorCallbacks {
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -0700277 /** {@inheritDoc} */
San Mehat873f2142010-01-14 10:25:07 -0800278 public void onDaemonConnected() {
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -0700279 NetworkManagementService.this.onDaemonConnected();
San Mehat873f2142010-01-14 10:25:07 -0800280 }
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -0700281
282 /** {@inheritDoc} */
San Mehat873f2142010-01-14 10:25:07 -0800283 public boolean onEvent(int code, String raw, String[] cooked) {
JP Abgrall12b933d2011-07-14 18:09:22 -0700284 switch (code) {
285 case NetdResponseCode.InterfaceChange:
286 /*
287 * a network interface change occured
288 * Format: "NNN Iface added <name>"
289 * "NNN Iface removed <name>"
290 * "NNN Iface changed <name> <up/down>"
291 * "NNN Iface linkstatus <name> <up/down>"
292 */
293 if (cooked.length < 4 || !cooked[1].equals("Iface")) {
294 throw new IllegalStateException(
295 String.format("Invalid event from daemon (%s)", raw));
296 }
297 if (cooked[2].equals("added")) {
298 notifyInterfaceAdded(cooked[3]);
299 return true;
300 } else if (cooked[2].equals("removed")) {
301 notifyInterfaceRemoved(cooked[3]);
302 return true;
303 } else if (cooked[2].equals("changed") && cooked.length == 5) {
304 notifyInterfaceStatusChanged(cooked[3], cooked[4].equals("up"));
305 return true;
306 } else if (cooked[2].equals("linkstate") && cooked.length == 5) {
307 notifyInterfaceLinkStateChanged(cooked[3], cooked[4].equals("up"));
308 return true;
309 }
Robert Greenwalte3253922010-02-18 09:23:25 -0800310 throw new IllegalStateException(
311 String.format("Invalid event from daemon (%s)", raw));
JP Abgrall12b933d2011-07-14 18:09:22 -0700312 // break;
313 case NetdResponseCode.BandwidthControl:
314 /*
315 * Bandwidth control needs some attention
316 * Format: "NNN limit alert <alertName> <ifaceName>"
317 */
318 if (cooked.length < 5 || !cooked[1].equals("limit")) {
319 throw new IllegalStateException(
320 String.format("Invalid event from daemon (%s)", raw));
321 }
322 if (cooked[2].equals("alert")) {
323 notifyLimitReached(cooked[3], cooked[4]);
324 return true;
325 }
326 throw new IllegalStateException(
327 String.format("Invalid event from daemon (%s)", raw));
328 // break;
329 default: break;
Robert Greenwalte3253922010-02-18 09:23:25 -0800330 }
331 return false;
San Mehat873f2142010-01-14 10:25:07 -0800332 }
333 }
334
San Mehated4fc8a2010-01-22 12:28:36 -0800335
San Mehat873f2142010-01-14 10:25:07 -0800336 //
337 // INetworkManagementService members
338 //
339
340 public String[] listInterfaces() throws IllegalStateException {
341 mContext.enforceCallingOrSelfPermission(
342 android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
343
Kenny Roota80ce062010-06-01 13:23:53 -0700344 try {
345 return mConnector.doListCommand("interface list", NetdResponseCode.InterfaceListResult);
346 } catch (NativeDaemonConnectorException e) {
347 throw new IllegalStateException(
348 "Cannot communicate with native daemon to list interfaces");
349 }
San Mehated4fc8a2010-01-22 12:28:36 -0800350 }
351
352 public InterfaceConfiguration getInterfaceConfig(String iface) throws IllegalStateException {
Kenny Roota80ce062010-06-01 13:23:53 -0700353 String rsp;
354 try {
355 rsp = mConnector.doCommand("interface getcfg " + iface).get(0);
356 } catch (NativeDaemonConnectorException e) {
357 throw new IllegalStateException(
358 "Cannot communicate with native daemon to get interface config");
359 }
Joe Onorato8a9b2202010-02-26 18:56:32 -0800360 Slog.d(TAG, String.format("rsp <%s>", rsp));
San Mehated4fc8a2010-01-22 12:28:36 -0800361
Robert Greenwalt2d2afd12011-02-01 15:30:46 -0800362 // Rsp: 213 xx:xx:xx:xx:xx:xx yyy.yyy.yyy.yyy zzz [flag1 flag2 flag3]
San Mehated4fc8a2010-01-22 12:28:36 -0800363 StringTokenizer st = new StringTokenizer(rsp);
364
Kenny Roota80ce062010-06-01 13:23:53 -0700365 InterfaceConfiguration cfg;
San Mehated4fc8a2010-01-22 12:28:36 -0800366 try {
Kenny Roota80ce062010-06-01 13:23:53 -0700367 try {
368 int code = Integer.parseInt(st.nextToken(" "));
369 if (code != NetdResponseCode.InterfaceGetCfgResult) {
370 throw new IllegalStateException(
371 String.format("Expected code %d, but got %d",
372 NetdResponseCode.InterfaceGetCfgResult, code));
373 }
374 } catch (NumberFormatException nfe) {
San Mehated4fc8a2010-01-22 12:28:36 -0800375 throw new IllegalStateException(
Kenny Roota80ce062010-06-01 13:23:53 -0700376 String.format("Invalid response from daemon (%s)", rsp));
San Mehated4fc8a2010-01-22 12:28:36 -0800377 }
Kenny Roota80ce062010-06-01 13:23:53 -0700378
379 cfg = new InterfaceConfiguration();
380 cfg.hwAddr = st.nextToken(" ");
Robert Greenwalted126402011-01-28 15:34:55 -0800381 InetAddress addr = null;
Robert Greenwalt2d2afd12011-02-01 15:30:46 -0800382 int prefixLength = 0;
Kenny Roota80ce062010-06-01 13:23:53 -0700383 try {
Robert Greenwalte5903732011-02-22 16:00:42 -0800384 addr = NetworkUtils.numericToInetAddress(st.nextToken(" "));
385 } catch (IllegalArgumentException iae) {
386 Slog.e(TAG, "Failed to parse ipaddr", iae);
Kenny Roota80ce062010-06-01 13:23:53 -0700387 }
388
389 try {
Robert Greenwalt2d2afd12011-02-01 15:30:46 -0800390 prefixLength = Integer.parseInt(st.nextToken(" "));
391 } catch (NumberFormatException nfe) {
392 Slog.e(TAG, "Failed to parse prefixLength", nfe);
Kenny Roota80ce062010-06-01 13:23:53 -0700393 }
Robert Greenwalt04808c22010-12-13 17:01:41 -0800394
Robert Greenwalt2d2afd12011-02-01 15:30:46 -0800395 cfg.addr = new LinkAddress(addr, prefixLength);
Kenny Roota80ce062010-06-01 13:23:53 -0700396 cfg.interfaceFlags = st.nextToken("]").trim() +"]";
397 } catch (NoSuchElementException nsee) {
San Mehated4fc8a2010-01-22 12:28:36 -0800398 throw new IllegalStateException(
399 String.format("Invalid response from daemon (%s)", rsp));
400 }
Joe Onorato8a9b2202010-02-26 18:56:32 -0800401 Slog.d(TAG, String.format("flags <%s>", cfg.interfaceFlags));
San Mehated4fc8a2010-01-22 12:28:36 -0800402 return cfg;
403 }
404
405 public void setInterfaceConfig(
406 String iface, InterfaceConfiguration cfg) throws IllegalStateException {
Robert Greenwalted126402011-01-28 15:34:55 -0800407 LinkAddress linkAddr = cfg.addr;
Robert Greenwalt2d2afd12011-02-01 15:30:46 -0800408 if (linkAddr == null || linkAddr.getAddress() == null) {
409 throw new IllegalStateException("Null LinkAddress given");
Robert Greenwalted126402011-01-28 15:34:55 -0800410 }
Robert Greenwalt2d2afd12011-02-01 15:30:46 -0800411 String cmd = String.format("interface setcfg %s %s %d %s", iface,
412 linkAddr.getAddress().getHostAddress(),
413 linkAddr.getNetworkPrefixLength(),
414 cfg.interfaceFlags);
Kenny Roota80ce062010-06-01 13:23:53 -0700415 try {
416 mConnector.doCommand(cmd);
417 } catch (NativeDaemonConnectorException e) {
418 throw new IllegalStateException(
Robert Greenwalt81d5ad52010-12-16 11:27:38 -0800419 "Unable to communicate with native daemon to interface setcfg - " + e);
Kenny Roota80ce062010-06-01 13:23:53 -0700420 }
San Mehat873f2142010-01-14 10:25:07 -0800421 }
422
Irfan Sheriff7244c972011-08-05 20:40:45 -0700423 public void setInterfaceDown(String iface) throws IllegalStateException {
424 try {
425 InterfaceConfiguration ifcg = getInterfaceConfig(iface);
426 ifcg.interfaceFlags = ifcg.interfaceFlags.replace("up", "down");
427 setInterfaceConfig(iface, ifcg);
428 } catch (NativeDaemonConnectorException e) {
429 throw new IllegalStateException(
430 "Unable to communicate with native daemon for interface down - " + e);
431 }
432 }
433
434 public void setInterfaceUp(String iface) throws IllegalStateException {
435 try {
436 InterfaceConfiguration ifcg = getInterfaceConfig(iface);
437 ifcg.interfaceFlags = ifcg.interfaceFlags.replace("down", "up");
438 setInterfaceConfig(iface, ifcg);
439 } catch (NativeDaemonConnectorException e) {
440 throw new IllegalStateException(
441 "Unable to communicate with native daemon for interface up - " + e);
442 }
443 }
444
Irfan Sheriff73293612011-09-14 12:31:56 -0700445 public void setInterfaceIpv6PrivacyExtensions(String iface, boolean enable)
446 throws IllegalStateException {
447 String cmd = String.format("interface ipv6privacyextensions %s %s", iface,
448 enable ? "enable" : "disable");
449 try {
450 mConnector.doCommand(cmd);
451 } catch (NativeDaemonConnectorException e) {
452 throw new IllegalStateException(
453 "Unable to communicate with native daemon to set ipv6privacyextensions - " + e);
454 }
455 }
456
457
458
Irfan Sherifff5600612011-06-16 10:26:28 -0700459 /* TODO: This is right now a IPv4 only function. Works for wifi which loses its
460 IPv6 addresses on interface down, but we need to do full clean up here */
461 public void clearInterfaceAddresses(String iface) throws IllegalStateException {
462 String cmd = String.format("interface clearaddrs %s", iface);
463 try {
464 mConnector.doCommand(cmd);
465 } catch (NativeDaemonConnectorException e) {
466 throw new IllegalStateException(
467 "Unable to communicate with native daemon to interface clearallips - " + e);
468 }
469 }
470
repo sync7960d9f2011-09-29 12:40:02 -0700471 public void enableIpv6(String iface) throws IllegalStateException {
472 mContext.enforceCallingOrSelfPermission(
473 android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
474 try {
475 mConnector.doCommand(String.format("interface ipv6 %s enable", iface));
476 } catch (NativeDaemonConnectorException e) {
477 throw new IllegalStateException(
478 "Unable to communicate to native daemon for enabling ipv6");
479 }
480 }
481
482 public void disableIpv6(String iface) throws IllegalStateException {
483 mContext.enforceCallingOrSelfPermission(
484 android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
485 try {
486 mConnector.doCommand(String.format("interface ipv6 %s disable", iface));
487 } catch (NativeDaemonConnectorException e) {
488 throw new IllegalStateException(
489 "Unable to communicate to native daemon for disabling ipv6");
490 }
491 }
492
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -0700493 public void addRoute(String interfaceName, RouteInfo route) {
494 modifyRoute(interfaceName, ADD, route);
495 }
496
497 public void removeRoute(String interfaceName, RouteInfo route) {
498 modifyRoute(interfaceName, REMOVE, route);
499 }
500
501 private void modifyRoute(String interfaceName, int action, RouteInfo route) {
502 ArrayList<String> rsp;
503
504 StringBuilder cmd;
505
506 switch (action) {
507 case ADD:
508 {
509 cmd = new StringBuilder("interface route add " + interfaceName);
510 break;
511 }
512 case REMOVE:
513 {
514 cmd = new StringBuilder("interface route remove " + interfaceName);
515 break;
516 }
517 default:
518 throw new IllegalStateException("Unknown action type " + action);
519 }
520
521 // create triplet: dest-ip-addr prefixlength gateway-ip-addr
522 LinkAddress la = route.getDestination();
523 cmd.append(' ');
524 cmd.append(la.getAddress().getHostAddress());
525 cmd.append(' ');
526 cmd.append(la.getNetworkPrefixLength());
527 cmd.append(' ');
528 if (route.getGateway() == null) {
529 if (la.getAddress() instanceof Inet4Address) {
530 cmd.append("0.0.0.0");
531 } else {
532 cmd.append ("::0");
533 }
534 } else {
535 cmd.append(route.getGateway().getHostAddress());
536 }
537 try {
538 rsp = mConnector.doCommand(cmd.toString());
539 } catch (NativeDaemonConnectorException e) {
540 throw new IllegalStateException(
541 "Unable to communicate with native dameon to add routes - "
542 + e);
543 }
544
Wink Savillec9acde92011-09-21 11:05:43 -0700545 if (DBG) {
546 for (String line : rsp) {
547 Log.v(TAG, "add route response is " + line);
548 }
Robert Greenwalt59b1a4e2011-05-10 15:05:02 -0700549 }
550 }
551
552 private ArrayList<String> readRouteList(String filename) {
553 FileInputStream fstream = null;
554 ArrayList<String> list = new ArrayList<String>();
555
556 try {
557 fstream = new FileInputStream(filename);
558 DataInputStream in = new DataInputStream(fstream);
559 BufferedReader br = new BufferedReader(new InputStreamReader(in));
560 String s;
561
562 // throw away the title line
563
564 while (((s = br.readLine()) != null) && (s.length() != 0)) {
565 list.add(s);
566 }
567 } catch (IOException ex) {
568 // return current list, possibly empty
569 } finally {
570 if (fstream != null) {
571 try {
572 fstream.close();
573 } catch (IOException ex) {}
574 }
575 }
576
577 return list;
578 }
579
580 public RouteInfo[] getRoutes(String interfaceName) {
581 ArrayList<RouteInfo> routes = new ArrayList<RouteInfo>();
582
583 // v4 routes listed as:
584 // iface dest-addr gateway-addr flags refcnt use metric netmask mtu window IRTT
585 for (String s : readRouteList("/proc/net/route")) {
586 String[] fields = s.split("\t");
587
588 if (fields.length > 7) {
589 String iface = fields[0];
590
591 if (interfaceName.equals(iface)) {
592 String dest = fields[1];
593 String gate = fields[2];
594 String flags = fields[3]; // future use?
595 String mask = fields[7];
596 try {
597 // address stored as a hex string, ex: 0014A8C0
598 InetAddress destAddr =
599 NetworkUtils.intToInetAddress((int)Long.parseLong(dest, 16));
600 int prefixLength =
601 NetworkUtils.netmaskIntToPrefixLength(
602 (int)Long.parseLong(mask, 16));
603 LinkAddress linkAddress = new LinkAddress(destAddr, prefixLength);
604
605 // address stored as a hex string, ex 0014A8C0
606 InetAddress gatewayAddr =
607 NetworkUtils.intToInetAddress((int)Long.parseLong(gate, 16));
608
609 RouteInfo route = new RouteInfo(linkAddress, gatewayAddr);
610 routes.add(route);
611 } catch (Exception e) {
612 Log.e(TAG, "Error parsing route " + s + " : " + e);
613 continue;
614 }
615 }
616 }
617 }
618
619 // v6 routes listed as:
620 // dest-addr prefixlength ?? ?? gateway-addr ?? ?? ?? ?? iface
621 for (String s : readRouteList("/proc/net/ipv6_route")) {
622 String[]fields = s.split("\\s+");
623 if (fields.length > 9) {
624 String iface = fields[9].trim();
625 if (interfaceName.equals(iface)) {
626 String dest = fields[0];
627 String prefix = fields[1];
628 String gate = fields[4];
629
630 try {
631 // prefix length stored as a hex string, ex 40
632 int prefixLength = Integer.parseInt(prefix, 16);
633
634 // address stored as a 32 char hex string
635 // ex fe800000000000000000000000000000
636 InetAddress destAddr = NetworkUtils.hexToInet6Address(dest);
637 LinkAddress linkAddress = new LinkAddress(destAddr, prefixLength);
638
639 InetAddress gateAddr = NetworkUtils.hexToInet6Address(gate);
640
641 RouteInfo route = new RouteInfo(linkAddress, gateAddr);
642 routes.add(route);
643 } catch (Exception e) {
644 Log.e(TAG, "Error parsing route " + s + " : " + e);
645 continue;
646 }
647 }
648 }
649 }
650 return (RouteInfo[]) routes.toArray(new RouteInfo[0]);
651 }
652
San Mehat873f2142010-01-14 10:25:07 -0800653 public void shutdown() {
654 if (mContext.checkCallingOrSelfPermission(
655 android.Manifest.permission.SHUTDOWN)
656 != PackageManager.PERMISSION_GRANTED) {
657 throw new SecurityException("Requires SHUTDOWN permission");
658 }
659
Joe Onorato8a9b2202010-02-26 18:56:32 -0800660 Slog.d(TAG, "Shutting down");
San Mehat873f2142010-01-14 10:25:07 -0800661 }
662
663 public boolean getIpForwardingEnabled() throws IllegalStateException{
664 mContext.enforceCallingOrSelfPermission(
665 android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
666
Kenny Roota80ce062010-06-01 13:23:53 -0700667 ArrayList<String> rsp;
668 try {
669 rsp = mConnector.doCommand("ipfwd status");
670 } catch (NativeDaemonConnectorException e) {
671 throw new IllegalStateException(
672 "Unable to communicate with native daemon to ipfwd status");
673 }
San Mehat873f2142010-01-14 10:25:07 -0800674
675 for (String line : rsp) {
Kenny Roota80ce062010-06-01 13:23:53 -0700676 String[] tok = line.split(" ");
677 if (tok.length < 3) {
678 Slog.e(TAG, "Malformed response from native daemon: " + line);
679 return false;
680 }
681
San Mehat873f2142010-01-14 10:25:07 -0800682 int code = Integer.parseInt(tok[0]);
683 if (code == NetdResponseCode.IpFwdStatusResult) {
684 // 211 Forwarding <enabled/disabled>
Kenny Roota80ce062010-06-01 13:23:53 -0700685 return "enabled".equals(tok[2]);
San Mehat873f2142010-01-14 10:25:07 -0800686 } else {
687 throw new IllegalStateException(String.format("Unexpected response code %d", code));
688 }
689 }
690 throw new IllegalStateException("Got an empty response");
691 }
692
693 public void setIpForwardingEnabled(boolean enable) throws IllegalStateException {
694 mContext.enforceCallingOrSelfPermission(
695 android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
696 mConnector.doCommand(String.format("ipfwd %sable", (enable ? "en" : "dis")));
697 }
698
Robert Greenwaltbfb7bfa2010-03-24 16:03:21 -0700699 public void startTethering(String[] dhcpRange)
San Mehat873f2142010-01-14 10:25:07 -0800700 throws IllegalStateException {
701 mContext.enforceCallingOrSelfPermission(
702 android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
Robert Greenwaltbfb7bfa2010-03-24 16:03:21 -0700703 // cmd is "tether start first_start first_stop second_start second_stop ..."
704 // an odd number of addrs will fail
705 String cmd = "tether start";
706 for (String d : dhcpRange) {
707 cmd += " " + d;
708 }
Kenny Roota80ce062010-06-01 13:23:53 -0700709
710 try {
711 mConnector.doCommand(cmd);
712 } catch (NativeDaemonConnectorException e) {
713 throw new IllegalStateException("Unable to communicate to native daemon");
714 }
San Mehat873f2142010-01-14 10:25:07 -0800715 }
716
717 public void stopTethering() throws IllegalStateException {
718 mContext.enforceCallingOrSelfPermission(
719 android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
Kenny Roota80ce062010-06-01 13:23:53 -0700720 try {
721 mConnector.doCommand("tether stop");
722 } catch (NativeDaemonConnectorException e) {
723 throw new IllegalStateException("Unable to communicate to native daemon to stop tether");
724 }
San Mehat873f2142010-01-14 10:25:07 -0800725 }
726
727 public boolean isTetheringStarted() throws IllegalStateException {
728 mContext.enforceCallingOrSelfPermission(
729 android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
730
Kenny Roota80ce062010-06-01 13:23:53 -0700731 ArrayList<String> rsp;
732 try {
733 rsp = mConnector.doCommand("tether status");
734 } catch (NativeDaemonConnectorException e) {
735 throw new IllegalStateException(
736 "Unable to communicate to native daemon to get tether status");
737 }
San Mehat873f2142010-01-14 10:25:07 -0800738
739 for (String line : rsp) {
Kenny Roota80ce062010-06-01 13:23:53 -0700740 String[] tok = line.split(" ");
741 if (tok.length < 3) {
742 throw new IllegalStateException("Malformed response for tether status: " + line);
743 }
San Mehat873f2142010-01-14 10:25:07 -0800744 int code = Integer.parseInt(tok[0]);
745 if (code == NetdResponseCode.TetherStatusResult) {
746 // XXX: Tethering services <started/stopped> <TBD>...
Kenny Roota80ce062010-06-01 13:23:53 -0700747 return "started".equals(tok[2]);
San Mehat873f2142010-01-14 10:25:07 -0800748 } else {
749 throw new IllegalStateException(String.format("Unexpected response code %d", code));
750 }
751 }
752 throw new IllegalStateException("Got an empty response");
753 }
754
755 public void tetherInterface(String iface) throws IllegalStateException {
756 mContext.enforceCallingOrSelfPermission(
757 android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
Kenny Roota80ce062010-06-01 13:23:53 -0700758 try {
759 mConnector.doCommand("tether interface add " + iface);
760 } catch (NativeDaemonConnectorException e) {
761 throw new IllegalStateException(
762 "Unable to communicate to native daemon for adding tether interface");
763 }
San Mehat873f2142010-01-14 10:25:07 -0800764 }
765
766 public void untetherInterface(String iface) {
767 mContext.enforceCallingOrSelfPermission(
768 android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
Kenny Roota80ce062010-06-01 13:23:53 -0700769 try {
770 mConnector.doCommand("tether interface remove " + iface);
771 } catch (NativeDaemonConnectorException e) {
772 throw new IllegalStateException(
773 "Unable to communicate to native daemon for removing tether interface");
774 }
San Mehat873f2142010-01-14 10:25:07 -0800775 }
776
777 public String[] listTetheredInterfaces() throws IllegalStateException {
778 mContext.enforceCallingOrSelfPermission(
779 android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
Kenny Roota80ce062010-06-01 13:23:53 -0700780 try {
781 return mConnector.doListCommand(
782 "tether interface list", NetdResponseCode.TetherInterfaceListResult);
783 } catch (NativeDaemonConnectorException e) {
784 throw new IllegalStateException(
785 "Unable to communicate to native daemon for listing tether interfaces");
786 }
San Mehat873f2142010-01-14 10:25:07 -0800787 }
788
789 public void setDnsForwarders(String[] dns) throws IllegalStateException {
790 mContext.enforceCallingOrSelfPermission(
791 android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
792 try {
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800793 String cmd = "tether dns set";
San Mehat873f2142010-01-14 10:25:07 -0800794 for (String s : dns) {
Robert Greenwalte5903732011-02-22 16:00:42 -0800795 cmd += " " + NetworkUtils.numericToInetAddress(s).getHostAddress();
San Mehat873f2142010-01-14 10:25:07 -0800796 }
Kenny Roota80ce062010-06-01 13:23:53 -0700797 try {
798 mConnector.doCommand(cmd);
799 } catch (NativeDaemonConnectorException e) {
800 throw new IllegalStateException(
801 "Unable to communicate to native daemon for setting tether dns");
802 }
Robert Greenwalte5903732011-02-22 16:00:42 -0800803 } catch (IllegalArgumentException e) {
San Mehat873f2142010-01-14 10:25:07 -0800804 throw new IllegalStateException("Error resolving dns name", e);
805 }
806 }
807
808 public String[] getDnsForwarders() throws IllegalStateException {
809 mContext.enforceCallingOrSelfPermission(
810 android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
Kenny Roota80ce062010-06-01 13:23:53 -0700811 try {
812 return mConnector.doListCommand(
813 "tether dns list", NetdResponseCode.TetherDnsFwdTgtListResult);
814 } catch (NativeDaemonConnectorException e) {
815 throw new IllegalStateException(
816 "Unable to communicate to native daemon for listing tether dns");
817 }
San Mehat873f2142010-01-14 10:25:07 -0800818 }
819
820 public void enableNat(String internalInterface, String externalInterface)
821 throws IllegalStateException {
822 mContext.enforceCallingOrSelfPermission(
823 android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
Kenny Roota80ce062010-06-01 13:23:53 -0700824 try {
825 mConnector.doCommand(
826 String.format("nat enable %s %s", internalInterface, externalInterface));
827 } catch (NativeDaemonConnectorException e) {
828 throw new IllegalStateException(
829 "Unable to communicate to native daemon for enabling NAT interface");
830 }
San Mehat873f2142010-01-14 10:25:07 -0800831 }
832
833 public void disableNat(String internalInterface, String externalInterface)
834 throws IllegalStateException {
835 mContext.enforceCallingOrSelfPermission(
836 android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
Kenny Roota80ce062010-06-01 13:23:53 -0700837 try {
838 mConnector.doCommand(
839 String.format("nat disable %s %s", internalInterface, externalInterface));
840 } catch (NativeDaemonConnectorException e) {
841 throw new IllegalStateException(
842 "Unable to communicate to native daemon for disabling NAT interface");
843 }
San Mehat873f2142010-01-14 10:25:07 -0800844 }
San Mehat72759df2010-01-19 13:50:37 -0800845
846 public String[] listTtys() throws IllegalStateException {
847 mContext.enforceCallingOrSelfPermission(
848 android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
Kenny Roota80ce062010-06-01 13:23:53 -0700849 try {
850 return mConnector.doListCommand("list_ttys", NetdResponseCode.TtyListResult);
851 } catch (NativeDaemonConnectorException e) {
852 throw new IllegalStateException(
853 "Unable to communicate to native daemon for listing TTYs");
854 }
San Mehat72759df2010-01-19 13:50:37 -0800855 }
856
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800857 public void attachPppd(String tty, String localAddr, String remoteAddr, String dns1Addr,
858 String dns2Addr) throws IllegalStateException {
San Mehat72759df2010-01-19 13:50:37 -0800859 try {
860 mContext.enforceCallingOrSelfPermission(
861 android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
Robert Greenwaltd0e18ff2010-01-26 11:40:34 -0800862 mConnector.doCommand(String.format("pppd attach %s %s %s %s %s", tty,
Robert Greenwalte5903732011-02-22 16:00:42 -0800863 NetworkUtils.numericToInetAddress(localAddr).getHostAddress(),
864 NetworkUtils.numericToInetAddress(remoteAddr).getHostAddress(),
865 NetworkUtils.numericToInetAddress(dns1Addr).getHostAddress(),
866 NetworkUtils.numericToInetAddress(dns2Addr).getHostAddress()));
867 } catch (IllegalArgumentException e) {
San Mehat72759df2010-01-19 13:50:37 -0800868 throw new IllegalStateException("Error resolving addr", e);
Kenny Roota80ce062010-06-01 13:23:53 -0700869 } catch (NativeDaemonConnectorException e) {
870 throw new IllegalStateException("Error communicating to native daemon to attach pppd", e);
San Mehat72759df2010-01-19 13:50:37 -0800871 }
872 }
873
874 public void detachPppd(String tty) throws IllegalStateException {
875 mContext.enforceCallingOrSelfPermission(
876 android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
Kenny Roota80ce062010-06-01 13:23:53 -0700877 try {
878 mConnector.doCommand(String.format("pppd detach %s", tty));
879 } catch (NativeDaemonConnectorException e) {
880 throw new IllegalStateException("Error communicating to native daemon to detach pppd", e);
881 }
San Mehat72759df2010-01-19 13:50:37 -0800882 }
Robert Greenwaltce1200d2010-02-18 11:25:54 -0800883
Irfan Sheriffc2f54c22010-03-18 14:02:22 -0700884 public void startAccessPoint(WifiConfiguration wifiConfig, String wlanIface, String softapIface)
Irfan Sheriff5321aef2010-02-12 12:35:59 -0800885 throws IllegalStateException {
886 mContext.enforceCallingOrSelfPermission(
887 android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
888 mContext.enforceCallingOrSelfPermission(
Irfan Sheriffc2f54c22010-03-18 14:02:22 -0700889 android.Manifest.permission.CHANGE_WIFI_STATE, "NetworkManagementService");
Kenny Roota80ce062010-06-01 13:23:53 -0700890 try {
Irfan Sheriffcb30b222011-07-29 20:54:52 -0700891 wifiFirmwareReload(wlanIface, "AP");
Kenny Roota80ce062010-06-01 13:23:53 -0700892 mConnector.doCommand(String.format("softap start " + wlanIface));
893 if (wifiConfig == null) {
894 mConnector.doCommand(String.format("softap set " + wlanIface + " " + softapIface));
895 } else {
896 /**
897 * softap set arg1 arg2 arg3 [arg4 arg5 arg6 arg7 arg8]
898 * argv1 - wlan interface
899 * argv2 - softap interface
900 * argv3 - SSID
901 * argv4 - Security
902 * argv5 - Key
903 * argv6 - Channel
904 * argv7 - Preamble
905 * argv8 - Max SCB
906 */
Irfan Sheriffec8d23a2011-02-16 17:00:33 -0800907 String str = String.format("softap set " + wlanIface + " " + softapIface +
908 " %s %s %s", convertQuotedString(wifiConfig.SSID),
909 getSecurityType(wifiConfig),
910 convertQuotedString(wifiConfig.preSharedKey));
Kenny Roota80ce062010-06-01 13:23:53 -0700911 mConnector.doCommand(str);
912 }
913 mConnector.doCommand(String.format("softap startap"));
914 } catch (NativeDaemonConnectorException e) {
915 throw new IllegalStateException("Error communicating to native daemon to start softap", e);
Irfan Sheriff9ab518ad2010-03-12 15:48:17 -0800916 }
Irfan Sheriff5321aef2010-02-12 12:35:59 -0800917 }
918
Irfan Sheriffa6e559e2010-05-24 14:55:42 -0700919 private String convertQuotedString(String s) {
Irfan Sheriff7baec0f2010-05-26 17:16:47 -0700920 if (s == null) {
921 return s;
922 }
923 /* Replace \ with \\, then " with \" and add quotes at end */
924 return '"' + s.replaceAll("\\\\","\\\\\\\\").replaceAll("\"","\\\\\"") + '"';
Irfan Sheriffa6e559e2010-05-24 14:55:42 -0700925 }
926
Irfan Sheriffec8d23a2011-02-16 17:00:33 -0800927 private String getSecurityType(WifiConfiguration wifiConfig) {
928 switch (wifiConfig.getAuthType()) {
929 case KeyMgmt.WPA_PSK:
930 return "wpa-psk";
931 case KeyMgmt.WPA2_PSK:
932 return "wpa2-psk";
933 default:
934 return "open";
935 }
936 }
937
Irfan Sheriffcb30b222011-07-29 20:54:52 -0700938 /* @param mode can be "AP", "STA" or "P2P" */
939 public void wifiFirmwareReload(String wlanIface, String mode) throws IllegalStateException {
940 mContext.enforceCallingOrSelfPermission(
941 android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
942 mContext.enforceCallingOrSelfPermission(
943 android.Manifest.permission.CHANGE_WIFI_STATE, "NetworkManagementService");
944
945 try {
946 mConnector.doCommand(String.format("softap fwreload " + wlanIface + " " + mode));
947 } catch (NativeDaemonConnectorException e) {
948 throw new IllegalStateException("Error communicating to native daemon ", e);
949 }
950 }
951
Irfan Sheriff23eb2972011-07-22 15:21:10 -0700952 public void stopAccessPoint(String wlanIface) throws IllegalStateException {
Irfan Sheriff5321aef2010-02-12 12:35:59 -0800953 mContext.enforceCallingOrSelfPermission(
954 android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
955 mContext.enforceCallingOrSelfPermission(
Irfan Sheriffc2f54c22010-03-18 14:02:22 -0700956 android.Manifest.permission.CHANGE_WIFI_STATE, "NetworkManagementService");
Kenny Roota80ce062010-06-01 13:23:53 -0700957 try {
958 mConnector.doCommand("softap stopap");
Irfan Sheriff23eb2972011-07-22 15:21:10 -0700959 mConnector.doCommand("softap stop " + wlanIface);
Irfan Sheriffcb30b222011-07-29 20:54:52 -0700960 wifiFirmwareReload(wlanIface, "STA");
Kenny Roota80ce062010-06-01 13:23:53 -0700961 } catch (NativeDaemonConnectorException e) {
962 throw new IllegalStateException("Error communicating to native daemon to stop soft AP",
963 e);
964 }
Irfan Sheriff5321aef2010-02-12 12:35:59 -0800965 }
966
Irfan Sheriffc2f54c22010-03-18 14:02:22 -0700967 public void setAccessPoint(WifiConfiguration wifiConfig, String wlanIface, String softapIface)
968 throws IllegalStateException {
969 mContext.enforceCallingOrSelfPermission(
970 android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
971 mContext.enforceCallingOrSelfPermission(
972 android.Manifest.permission.CHANGE_WIFI_STATE, "NetworkManagementService");
Kenny Roota80ce062010-06-01 13:23:53 -0700973 try {
974 if (wifiConfig == null) {
975 mConnector.doCommand(String.format("softap set " + wlanIface + " " + softapIface));
976 } else {
977 String str = String.format("softap set " + wlanIface + " " + softapIface
978 + " %s %s %s", convertQuotedString(wifiConfig.SSID),
Irfan Sheriffec8d23a2011-02-16 17:00:33 -0800979 getSecurityType(wifiConfig),
Kenny Roota80ce062010-06-01 13:23:53 -0700980 convertQuotedString(wifiConfig.preSharedKey));
981 mConnector.doCommand(str);
982 }
983 } catch (NativeDaemonConnectorException e) {
984 throw new IllegalStateException("Error communicating to native daemon to set soft AP",
985 e);
Irfan Sheriffc2f54c22010-03-18 14:02:22 -0700986 }
987 }
San Mehat91cac642010-03-31 14:31:36 -0700988
989 private long getInterfaceCounter(String iface, boolean rx) {
990 mContext.enforceCallingOrSelfPermission(
991 android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
992 try {
Kenny Roota80ce062010-06-01 13:23:53 -0700993 String rsp;
994 try {
995 rsp = mConnector.doCommand(
996 String.format("interface read%scounter %s", (rx ? "rx" : "tx"), iface)).get(0);
997 } catch (NativeDaemonConnectorException e1) {
998 Slog.e(TAG, "Error communicating with native daemon", e1);
999 return -1;
1000 }
1001
1002 String[] tok = rsp.split(" ");
1003 if (tok.length < 2) {
1004 Slog.e(TAG, String.format("Malformed response for reading %s interface",
1005 (rx ? "rx" : "tx")));
1006 return -1;
1007 }
1008
San Mehat91cac642010-03-31 14:31:36 -07001009 int code;
1010 try {
1011 code = Integer.parseInt(tok[0]);
1012 } catch (NumberFormatException nfe) {
1013 Slog.e(TAG, String.format("Error parsing code %s", tok[0]));
1014 return -1;
1015 }
1016 if ((rx && code != NetdResponseCode.InterfaceRxCounterResult) || (
1017 !rx && code != NetdResponseCode.InterfaceTxCounterResult)) {
1018 Slog.e(TAG, String.format("Unexpected response code %d", code));
1019 return -1;
1020 }
1021 return Long.parseLong(tok[1]);
1022 } catch (Exception e) {
1023 Slog.e(TAG, String.format(
1024 "Failed to read interface %s counters", (rx ? "rx" : "tx")), e);
1025 }
1026 return -1;
1027 }
1028
Jeff Sharkeyeedcb952011-05-17 14:55:15 -07001029 @Override
Jeff Sharkey9a13f362011-04-26 16:25:36 -07001030 public NetworkStats getNetworkStatsSummary() {
1031 mContext.enforceCallingOrSelfPermission(
1032 android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
Jeff Sharkey1059c3c2011-10-04 16:54:49 -07001033 return mStatsFactory.readNetworkStatsSummary();
Jeff Sharkeyae2c1812011-10-04 13:11:40 -07001034 }
1035
Jeff Sharkeyeedcb952011-05-17 14:55:15 -07001036 @Override
Jeff Sharkey9a13f362011-04-26 16:25:36 -07001037 public NetworkStats getNetworkStatsDetail() {
1038 mContext.enforceCallingOrSelfPermission(
1039 android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
Jeff Sharkey1059c3c2011-10-04 16:54:49 -07001040 return mStatsFactory.readNetworkStatsDetail(UID_ALL);
San Mehat91cac642010-03-31 14:31:36 -07001041 }
1042
Jeff Sharkeyeedcb952011-05-17 14:55:15 -07001043 @Override
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001044 public void setInterfaceQuota(String iface, long quotaBytes) {
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001045 mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
1046
Jeff Sharkey350083e2011-06-29 10:45:16 -07001047 // silently discard when control disabled
1048 // TODO: eventually migrate to be always enabled
1049 if (!mBandwidthControlEnabled) return;
1050
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001051 synchronized (mQuotaLock) {
1052 if (mActiveQuotaIfaces.contains(iface)) {
1053 throw new IllegalStateException("iface " + iface + " already has quota");
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001054 }
1055
1056 final StringBuilder command = new StringBuilder();
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001057 command.append("bandwidth setiquota ").append(iface).append(" ").append(quotaBytes);
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001058
1059 try {
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001060 // TODO: support quota shared across interfaces
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001061 mConnector.doCommand(command.toString());
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001062 mActiveQuotaIfaces.add(iface);
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001063 } catch (NativeDaemonConnectorException e) {
1064 throw new IllegalStateException("Error communicating to native daemon", e);
1065 }
Ashish Sharma50fd36d2011-06-15 19:34:53 -07001066 }
1067 }
1068
1069 @Override
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001070 public void removeInterfaceQuota(String iface) {
1071 mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
1072
Jeff Sharkey350083e2011-06-29 10:45:16 -07001073 // silently discard when control disabled
1074 // TODO: eventually migrate to be always enabled
1075 if (!mBandwidthControlEnabled) return;
1076
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001077 synchronized (mQuotaLock) {
1078 if (!mActiveQuotaIfaces.contains(iface)) {
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001079 // TODO: eventually consider throwing
1080 return;
1081 }
1082
1083 final StringBuilder command = new StringBuilder();
1084 command.append("bandwidth removeiquota ").append(iface);
1085
1086 try {
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001087 // TODO: support quota shared across interfaces
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001088 mConnector.doCommand(command.toString());
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001089 mActiveQuotaIfaces.remove(iface);
1090 mActiveAlertIfaces.remove(iface);
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001091 } catch (NativeDaemonConnectorException e) {
1092 throw new IllegalStateException("Error communicating to native daemon", e);
1093 }
1094 }
1095 }
1096
1097 @Override
Jeff Sharkey41ff7ec2011-07-25 15:21:22 -07001098 public void setInterfaceAlert(String iface, long alertBytes) {
1099 mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
1100
1101 // silently discard when control disabled
1102 // TODO: eventually migrate to be always enabled
1103 if (!mBandwidthControlEnabled) return;
1104
1105 // quick sanity check
1106 if (!mActiveQuotaIfaces.contains(iface)) {
1107 throw new IllegalStateException("setting alert requires existing quota on iface");
1108 }
1109
1110 synchronized (mQuotaLock) {
1111 if (mActiveAlertIfaces.contains(iface)) {
1112 throw new IllegalStateException("iface " + iface + " already has alert");
1113 }
1114
1115 final StringBuilder command = new StringBuilder();
1116 command.append("bandwidth setinterfacealert ").append(iface).append(" ").append(
1117 alertBytes);
1118
1119 try {
1120 // TODO: support alert shared across interfaces
1121 mConnector.doCommand(command.toString());
1122 mActiveAlertIfaces.add(iface);
1123 } catch (NativeDaemonConnectorException e) {
1124 throw new IllegalStateException("Error communicating to native daemon", e);
1125 }
1126 }
1127 }
1128
1129 @Override
1130 public void removeInterfaceAlert(String iface) {
1131 mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
1132
1133 // silently discard when control disabled
1134 // TODO: eventually migrate to be always enabled
1135 if (!mBandwidthControlEnabled) return;
1136
1137 synchronized (mQuotaLock) {
1138 if (!mActiveAlertIfaces.contains(iface)) {
1139 // TODO: eventually consider throwing
1140 return;
1141 }
1142
1143 final StringBuilder command = new StringBuilder();
1144 command.append("bandwidth removeinterfacealert ").append(iface);
1145
1146 try {
1147 // TODO: support alert shared across interfaces
1148 mConnector.doCommand(command.toString());
1149 mActiveAlertIfaces.remove(iface);
1150 } catch (NativeDaemonConnectorException e) {
1151 throw new IllegalStateException("Error communicating to native daemon", e);
1152 }
1153 }
1154 }
1155
1156 @Override
1157 public void setGlobalAlert(long alertBytes) {
1158 mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
1159
1160 // silently discard when control disabled
1161 // TODO: eventually migrate to be always enabled
1162 if (!mBandwidthControlEnabled) return;
1163
1164 final StringBuilder command = new StringBuilder();
1165 command.append("bandwidth setglobalalert ").append(alertBytes);
1166
1167 try {
1168 mConnector.doCommand(command.toString());
1169 } catch (NativeDaemonConnectorException e) {
1170 throw new IllegalStateException("Error communicating to native daemon", e);
1171 }
1172 }
1173
1174 @Override
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001175 public void setUidNetworkRules(int uid, boolean rejectOnQuotaInterfaces) {
1176 mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
1177
Jeff Sharkey350083e2011-06-29 10:45:16 -07001178 // silently discard when control disabled
1179 // TODO: eventually migrate to be always enabled
1180 if (!mBandwidthControlEnabled) return;
1181
Jeff Sharkeyb3f19ca2011-06-29 23:54:13 -07001182 synchronized (mUidRejectOnQuota) {
1183 final boolean oldRejectOnQuota = mUidRejectOnQuota.get(uid, false);
1184 if (oldRejectOnQuota == rejectOnQuotaInterfaces) {
1185 // TODO: eventually consider throwing
1186 return;
1187 }
1188
1189 final StringBuilder command = new StringBuilder();
1190 command.append("bandwidth");
1191 if (rejectOnQuotaInterfaces) {
1192 command.append(" addnaughtyapps");
1193 } else {
1194 command.append(" removenaughtyapps");
1195 }
1196 command.append(" ").append(uid);
1197
1198 try {
1199 mConnector.doCommand(command.toString());
1200 if (rejectOnQuotaInterfaces) {
1201 mUidRejectOnQuota.put(uid, true);
1202 } else {
1203 mUidRejectOnQuota.delete(uid);
1204 }
1205 } catch (NativeDaemonConnectorException e) {
1206 throw new IllegalStateException("Error communicating to native daemon", e);
1207 }
Ashish Sharma50fd36d2011-06-15 19:34:53 -07001208 }
1209 }
1210
Jeff Sharkey63d27a92011-08-03 17:04:22 -07001211 @Override
1212 public boolean isBandwidthControlEnabled() {
1213 mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
1214 return mBandwidthControlEnabled;
1215 }
1216
1217 @Override
Jeff Sharkeyeedcb952011-05-17 14:55:15 -07001218 public NetworkStats getNetworkStatsUidDetail(int uid) {
1219 if (Binder.getCallingUid() != uid) {
1220 mContext.enforceCallingOrSelfPermission(
1221 android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
1222 }
Jeff Sharkey1059c3c2011-10-04 16:54:49 -07001223 return mStatsFactory.readNetworkStatsDetail(uid);
Jeff Sharkeyeedcb952011-05-17 14:55:15 -07001224 }
1225
Jeff Sharkeycdd02c5d2011-09-16 01:52:49 -07001226 @Override
1227 public NetworkStats getNetworkStatsTethering(String[] ifacePairs) {
1228 mContext.enforceCallingOrSelfPermission(
1229 android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
1230
1231 if (ifacePairs.length % 2 != 0) {
1232 throw new IllegalArgumentException(
1233 "unexpected ifacePairs; length=" + ifacePairs.length);
1234 }
1235
1236 final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 1);
1237 for (int i = 0; i < ifacePairs.length; i += 2) {
1238 final String ifaceIn = ifacePairs[i];
1239 final String ifaceOut = ifacePairs[i + 1];
1240 if (ifaceIn != null && ifaceOut != null) {
1241 stats.combineValues(getNetworkStatsTethering(ifaceIn, ifaceOut));
1242 }
1243 }
1244 return stats;
1245 }
1246
1247 private NetworkStats.Entry getNetworkStatsTethering(String ifaceIn, String ifaceOut) {
1248 final StringBuilder command = new StringBuilder();
1249 command.append("bandwidth gettetherstats ").append(ifaceIn).append(" ").append(ifaceOut);
1250
1251 final String rsp;
1252 try {
1253 rsp = mConnector.doCommand(command.toString()).get(0);
1254 } catch (NativeDaemonConnectorException e) {
1255 throw new IllegalStateException("Error communicating to native daemon", e);
1256 }
1257
1258 final String[] tok = rsp.split(" ");
1259 /* Expecting: "code ifaceIn ifaceOut rx_bytes rx_packets tx_bytes tx_packets" */
1260 if (tok.length != 7) {
1261 throw new IllegalStateException("Native daemon returned unexpected result: " + rsp);
1262 }
1263
1264 final int code;
1265 try {
1266 code = Integer.parseInt(tok[0]);
1267 } catch (NumberFormatException e) {
1268 throw new IllegalStateException(
1269 "Failed to parse native daemon return code for " + ifaceIn + " " + ifaceOut);
1270 }
1271 if (code != NetdResponseCode.TetheringStatsResult) {
1272 throw new IllegalStateException(
1273 "Unexpected return code from native daemon for " + ifaceIn + " " + ifaceOut);
1274 }
1275
1276 try {
1277 final NetworkStats.Entry entry = new NetworkStats.Entry();
1278 entry.iface = ifaceIn;
Jeff Sharkey905b5892011-09-30 15:19:49 -07001279 entry.uid = UID_TETHERING;
Jeff Sharkeycdd02c5d2011-09-16 01:52:49 -07001280 entry.set = SET_DEFAULT;
1281 entry.tag = TAG_NONE;
1282 entry.rxBytes = Long.parseLong(tok[3]);
1283 entry.rxPackets = Long.parseLong(tok[4]);
1284 entry.txBytes = Long.parseLong(tok[5]);
1285 entry.txPackets = Long.parseLong(tok[6]);
1286 return entry;
1287 } catch (NumberFormatException e) {
1288 throw new IllegalStateException(
1289 "problem parsing tethering stats for " + ifaceIn + " " + ifaceOut + ": " + e);
1290 }
1291 }
1292
San Mehatf0db6e12010-04-07 15:22:10 -07001293 public void setInterfaceThrottle(String iface, int rxKbps, int txKbps) {
San Mehat91cac642010-03-31 14:31:36 -07001294 mContext.enforceCallingOrSelfPermission(
1295 android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
Kenny Roota80ce062010-06-01 13:23:53 -07001296 try {
1297 mConnector.doCommand(String.format(
1298 "interface setthrottle %s %d %d", iface, rxKbps, txKbps));
1299 } catch (NativeDaemonConnectorException e) {
1300 Slog.e(TAG, "Error communicating with native daemon to set throttle", e);
1301 }
San Mehat91cac642010-03-31 14:31:36 -07001302 }
1303
1304 private int getInterfaceThrottle(String iface, boolean rx) {
1305 mContext.enforceCallingOrSelfPermission(
1306 android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
1307 try {
Kenny Roota80ce062010-06-01 13:23:53 -07001308 String rsp;
1309 try {
1310 rsp = mConnector.doCommand(
1311 String.format("interface getthrottle %s %s", iface,
1312 (rx ? "rx" : "tx"))).get(0);
1313 } catch (NativeDaemonConnectorException e) {
1314 Slog.e(TAG, "Error communicating with native daemon to getthrottle", e);
1315 return -1;
1316 }
1317
1318 String[] tok = rsp.split(" ");
1319 if (tok.length < 2) {
1320 Slog.e(TAG, "Malformed response to getthrottle command");
1321 return -1;
1322 }
1323
San Mehat91cac642010-03-31 14:31:36 -07001324 int code;
1325 try {
1326 code = Integer.parseInt(tok[0]);
1327 } catch (NumberFormatException nfe) {
1328 Slog.e(TAG, String.format("Error parsing code %s", tok[0]));
1329 return -1;
1330 }
1331 if ((rx && code != NetdResponseCode.InterfaceRxThrottleResult) || (
1332 !rx && code != NetdResponseCode.InterfaceTxThrottleResult)) {
1333 Slog.e(TAG, String.format("Unexpected response code %d", code));
1334 return -1;
1335 }
1336 return Integer.parseInt(tok[1]);
1337 } catch (Exception e) {
1338 Slog.e(TAG, String.format(
1339 "Failed to read interface %s throttle value", (rx ? "rx" : "tx")), e);
1340 }
1341 return -1;
1342 }
1343
1344 public int getInterfaceRxThrottle(String iface) {
1345 return getInterfaceThrottle(iface, true);
1346 }
1347
1348 public int getInterfaceTxThrottle(String iface) {
1349 return getInterfaceThrottle(iface, false);
1350 }
Jeff Sharkey9a13f362011-04-26 16:25:36 -07001351
Mattias Falk7475c0c2011-04-04 16:10:36 +02001352 public void setDefaultInterfaceForDns(String iface) throws IllegalStateException {
1353 mContext.enforceCallingOrSelfPermission(
1354 android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
1355 try {
1356 String cmd = "resolver setdefaultif " + iface;
1357
1358 mConnector.doCommand(cmd);
1359 } catch (NativeDaemonConnectorException e) {
1360 throw new IllegalStateException(
1361 "Error communicating with native daemon to set default interface", e);
1362 }
1363 }
1364
1365 public void setDnsServersForInterface(String iface, String[] servers)
1366 throws IllegalStateException {
1367 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.CHANGE_NETWORK_STATE,
1368 "NetworkManagementService");
1369 try {
1370 String cmd = "resolver setifdns " + iface;
1371 for (String s : servers) {
Robert Greenwalt572b7042011-07-25 17:00:13 -07001372 InetAddress a = NetworkUtils.numericToInetAddress(s);
1373 if (a.isAnyLocalAddress() == false) {
1374 cmd += " " + a.getHostAddress();
Mattias Falk7475c0c2011-04-04 16:10:36 +02001375 }
1376 }
Mattias Falk7475c0c2011-04-04 16:10:36 +02001377 mConnector.doCommand(cmd);
Robert Greenwalt572b7042011-07-25 17:00:13 -07001378 } catch (IllegalArgumentException e) {
1379 throw new IllegalStateException("Error setting dnsn for interface", e);
Mattias Falk7475c0c2011-04-04 16:10:36 +02001380 } catch (NativeDaemonConnectorException e) {
1381 throw new IllegalStateException(
Robert Greenwalt572b7042011-07-25 17:00:13 -07001382 "Error communicating with native daemon to set dns for interface", e);
Mattias Falk7475c0c2011-04-04 16:10:36 +02001383 }
1384 }
1385
1386 public void flushDefaultDnsCache() throws IllegalStateException {
1387 mContext.enforceCallingOrSelfPermission(
1388 android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
1389 try {
1390 String cmd = "resolver flushdefaultif";
1391
1392 mConnector.doCommand(cmd);
1393 } catch (NativeDaemonConnectorException e) {
1394 throw new IllegalStateException(
1395 "Error communicating with native deamon to flush default interface", e);
1396 }
1397 }
1398
1399 public void flushInterfaceDnsCache(String iface) throws IllegalStateException {
1400 mContext.enforceCallingOrSelfPermission(
1401 android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
1402 try {
1403 String cmd = "resolver flushif " + iface;
1404
1405 mConnector.doCommand(cmd);
1406 } catch (NativeDaemonConnectorException e) {
1407 throw new IllegalStateException(
Robert Greenwalt572b7042011-07-25 17:00:13 -07001408 "Error communicating with native daemon to flush interface " + iface, e);
Mattias Falk7475c0c2011-04-04 16:10:36 +02001409 }
1410 }
Jeff Sharkeyfa23c5a2011-08-09 21:44:24 -07001411
1412 /** {@inheritDoc} */
1413 public void monitor() {
1414 if (mConnector != null) {
1415 mConnector.monitor();
1416 }
1417 }
Jeff Sharkey47eb1022011-08-25 17:48:52 -07001418
1419 @Override
1420 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1421 mContext.enforceCallingOrSelfPermission(DUMP, TAG);
1422
1423 pw.print("Bandwidth control enabled: "); pw.println(mBandwidthControlEnabled);
1424
1425 synchronized (mQuotaLock) {
1426 pw.print("Active quota ifaces: "); pw.println(mActiveQuotaIfaces.toString());
1427 pw.print("Active alert ifaces: "); pw.println(mActiveAlertIfaces.toString());
1428 }
1429
1430 synchronized (mUidRejectOnQuota) {
1431 pw.print("UID reject on quota ifaces: [");
1432 final int size = mUidRejectOnQuota.size();
1433 for (int i = 0; i < size; i++) {
1434 pw.print(mUidRejectOnQuota.keyAt(i));
1435 if (i < size - 1) pw.print(",");
1436 }
1437 pw.println("]");
1438 }
1439 }
San Mehat873f2142010-01-14 10:25:07 -08001440}