NetworkManagementService.java revision 2ffa11e4b71c545e34533ef827bdc1a07fbe8246
1/* 2 * Copyright (C) 2007 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.server; 18 19import static android.Manifest.permission.CONNECTIVITY_INTERNAL; 20import static android.Manifest.permission.DUMP; 21import static android.Manifest.permission.SHUTDOWN; 22import static android.net.NetworkStats.SET_DEFAULT; 23import static android.net.NetworkStats.TAG_ALL; 24import static android.net.NetworkStats.TAG_NONE; 25import static android.net.NetworkStats.UID_ALL; 26import static android.net.TrafficStats.UID_TETHERING; 27import static com.android.server.NetworkManagementService.NetdResponseCode.ClatdStatusResult; 28import static com.android.server.NetworkManagementService.NetdResponseCode.GetMarkResult; 29import static com.android.server.NetworkManagementService.NetdResponseCode.InterfaceGetCfgResult; 30import static com.android.server.NetworkManagementService.NetdResponseCode.InterfaceListResult; 31import static com.android.server.NetworkManagementService.NetdResponseCode.IpFwdStatusResult; 32import static com.android.server.NetworkManagementService.NetdResponseCode.TetherDnsFwdTgtListResult; 33import static com.android.server.NetworkManagementService.NetdResponseCode.TetherInterfaceListResult; 34import static com.android.server.NetworkManagementService.NetdResponseCode.TetherStatusResult; 35import static com.android.server.NetworkManagementService.NetdResponseCode.TetheringStatsListResult; 36import static com.android.server.NetworkManagementService.NetdResponseCode.TtyListResult; 37import static com.android.server.NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED; 38 39import android.content.Context; 40import android.net.ConnectivityManager; 41import android.net.INetworkManagementEventObserver; 42import android.net.InterfaceConfiguration; 43import android.net.LinkAddress; 44import android.net.NetworkStats; 45import android.net.NetworkUtils; 46import android.net.RouteInfo; 47import android.net.wifi.WifiConfiguration; 48import android.net.wifi.WifiConfiguration.KeyMgmt; 49import android.os.BatteryStats; 50import android.os.Binder; 51import android.os.Handler; 52import android.os.INetworkActivityListener; 53import android.os.INetworkManagementService; 54import android.os.PowerManager; 55import android.os.Process; 56import android.os.RemoteCallbackList; 57import android.os.RemoteException; 58import android.os.ServiceManager; 59import android.os.SystemClock; 60import android.os.SystemProperties; 61import android.telephony.DataConnectionRealTimeInfo; 62import android.telephony.PhoneStateListener; 63import android.util.Log; 64import android.util.Slog; 65import android.util.SparseBooleanArray; 66 67import com.android.internal.app.IBatteryStats; 68import com.android.internal.net.NetworkStatsFactory; 69import com.android.internal.util.Preconditions; 70import com.android.server.NativeDaemonConnector.Command; 71import com.android.server.NativeDaemonConnector.SensitiveArg; 72import com.android.server.net.LockdownVpnTracker; 73import com.google.android.collect.Maps; 74 75import java.io.BufferedReader; 76import java.io.DataInputStream; 77import java.io.File; 78import java.io.FileDescriptor; 79import java.io.FileInputStream; 80import java.io.IOException; 81import java.io.InputStreamReader; 82import java.io.PrintWriter; 83import java.net.Inet4Address; 84import java.net.InetAddress; 85import java.net.InterfaceAddress; 86import java.net.NetworkInterface; 87import java.net.SocketException; 88import java.util.ArrayList; 89import java.util.HashMap; 90import java.util.List; 91import java.util.Map; 92import java.util.NoSuchElementException; 93import java.util.StringTokenizer; 94import java.util.concurrent.CountDownLatch; 95 96/** 97 * @hide 98 */ 99public class NetworkManagementService extends INetworkManagementService.Stub 100 implements Watchdog.Monitor { 101 private static final String TAG = "NetworkManagementService"; 102 private static final boolean DBG = false; 103 private static final String NETD_TAG = "NetdConnector"; 104 private static final String NETD_SOCKET_NAME = "netd"; 105 106 private static final String ADD = "add"; 107 private static final String REMOVE = "remove"; 108 109 private static final String ALLOW = "allow"; 110 private static final String DENY = "deny"; 111 112 private static final String DEFAULT = "default"; 113 private static final String SECONDARY = "secondary"; 114 115 /** 116 * Name representing {@link #setGlobalAlert(long)} limit when delivered to 117 * {@link INetworkManagementEventObserver#limitReached(String, String)}. 118 */ 119 public static final String LIMIT_GLOBAL_ALERT = "globalAlert"; 120 121 class NetdResponseCode { 122 /* Keep in sync with system/netd/ResponseCode.h */ 123 public static final int InterfaceListResult = 110; 124 public static final int TetherInterfaceListResult = 111; 125 public static final int TetherDnsFwdTgtListResult = 112; 126 public static final int TtyListResult = 113; 127 public static final int TetheringStatsListResult = 114; 128 129 public static final int TetherStatusResult = 210; 130 public static final int IpFwdStatusResult = 211; 131 public static final int InterfaceGetCfgResult = 213; 132 public static final int SoftapStatusResult = 214; 133 public static final int InterfaceRxCounterResult = 216; 134 public static final int InterfaceTxCounterResult = 217; 135 public static final int QuotaCounterResult = 220; 136 public static final int TetheringStatsResult = 221; 137 public static final int DnsProxyQueryResult = 222; 138 public static final int ClatdStatusResult = 223; 139 public static final int GetMarkResult = 225; 140 141 public static final int InterfaceChange = 600; 142 public static final int BandwidthControl = 601; 143 public static final int InterfaceClassActivity = 613; 144 public static final int InterfaceAddressChange = 614; 145 public static final int InterfaceDnsServerInfo = 615; 146 } 147 148 static final int DAEMON_MSG_MOBILE_CONN_REAL_TIME_INFO = 1; 149 150 /** 151 * Binder context for this service 152 */ 153 private final Context mContext; 154 155 /** 156 * connector object for communicating with netd 157 */ 158 private final NativeDaemonConnector mConnector; 159 160 private final Handler mFgHandler; 161 private final Handler mDaemonHandler; 162 private final PhoneStateListener mPhoneStateListener; 163 164 private IBatteryStats mBatteryStats; 165 166 private final Thread mThread; 167 private CountDownLatch mConnectedSignal = new CountDownLatch(1); 168 169 private final RemoteCallbackList<INetworkManagementEventObserver> mObservers = 170 new RemoteCallbackList<INetworkManagementEventObserver>(); 171 172 private final NetworkStatsFactory mStatsFactory = new NetworkStatsFactory(); 173 174 private Object mQuotaLock = new Object(); 175 /** Set of interfaces with active quotas. */ 176 private HashMap<String, Long> mActiveQuotas = Maps.newHashMap(); 177 /** Set of interfaces with active alerts. */ 178 private HashMap<String, Long> mActiveAlerts = Maps.newHashMap(); 179 /** Set of UIDs with active reject rules. */ 180 private SparseBooleanArray mUidRejectOnQuota = new SparseBooleanArray(); 181 182 private Object mIdleTimerLock = new Object(); 183 /** Set of interfaces with active idle timers. */ 184 private static class IdleTimerParams { 185 public final int timeout; 186 public final int type; 187 public int networkCount; 188 189 IdleTimerParams(int timeout, int type) { 190 this.timeout = timeout; 191 this.type = type; 192 this.networkCount = 1; 193 } 194 } 195 private HashMap<String, IdleTimerParams> mActiveIdleTimers = Maps.newHashMap(); 196 197 private volatile boolean mBandwidthControlEnabled; 198 private volatile boolean mFirewallEnabled; 199 200 private boolean mMobileActivityFromRadio = false; 201 private int mLastPowerStateFromRadio = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW; 202 203 private final RemoteCallbackList<INetworkActivityListener> mNetworkActivityListeners = 204 new RemoteCallbackList<INetworkActivityListener>(); 205 private boolean mNetworkActive; 206 207 /** 208 * Constructs a new NetworkManagementService instance 209 * 210 * @param context Binder context for this service 211 */ 212 private NetworkManagementService(Context context, String socket) { 213 mContext = context; 214 215 // make sure this is on the same looper as our NativeDaemonConnector for sync purposes 216 mFgHandler = new Handler(FgThread.get().getLooper()); 217 218 if ("simulator".equals(SystemProperties.get("ro.product.device"))) { 219 mConnector = null; 220 mThread = null; 221 mDaemonHandler = null; 222 mPhoneStateListener = null; 223 return; 224 } 225 226 // Don't need this wake lock, since we now have a time stamp for when 227 // the network actually went inactive. (It might be nice to still do this, 228 // but I don't want to do it through the power manager because that pollutes the 229 // battery stats history with pointless noise.) 230 //PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE); 231 PowerManager.WakeLock wl = null; //pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, NETD_TAG); 232 233 mConnector = new NativeDaemonConnector( 234 new NetdCallbackReceiver(), socket, 10, NETD_TAG, 160, wl, 235 FgThread.get().getLooper()); 236 mThread = new Thread(mConnector, NETD_TAG); 237 238 mDaemonHandler = new Handler(FgThread.get().getLooper()); 239 mPhoneStateListener = new PhoneStateListener(mDaemonHandler.getLooper()) { 240 public void onDataConnectionRealTimeInfoChanged( 241 DataConnectionRealTimeInfo dcRtInfo) { 242 // Disabled for now, until we are getting good data. 243 //notifyInterfaceClassActivity(ConnectivityManager.TYPE_MOBILE, 244 // dcRtInfo.getDcPowerState(), dcRtInfo.getTime(), true); 245 } 246 }; 247 248 // Add ourself to the Watchdog monitors. 249 Watchdog.getInstance().addMonitor(this); 250 } 251 252 static NetworkManagementService create(Context context, 253 String socket) throws InterruptedException { 254 final NetworkManagementService service = new NetworkManagementService(context, socket); 255 final CountDownLatch connectedSignal = service.mConnectedSignal; 256 if (DBG) Slog.d(TAG, "Creating NetworkManagementService"); 257 service.mThread.start(); 258 if (DBG) Slog.d(TAG, "Awaiting socket connection"); 259 connectedSignal.await(); 260 if (DBG) Slog.d(TAG, "Connected"); 261 return service; 262 } 263 264 public static NetworkManagementService create(Context context) throws InterruptedException { 265 return create(context, NETD_SOCKET_NAME); 266 } 267 268 public void systemReady() { 269 prepareNativeDaemon(); 270 if (DBG) Slog.d(TAG, "Prepared"); 271 } 272 273 private IBatteryStats getBatteryStats() { 274 synchronized (this) { 275 if (mBatteryStats != null) { 276 return mBatteryStats; 277 } 278 mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService( 279 BatteryStats.SERVICE_NAME)); 280 return mBatteryStats; 281 } 282 } 283 284 @Override 285 public void registerObserver(INetworkManagementEventObserver observer) { 286 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 287 mObservers.register(observer); 288 } 289 290 @Override 291 public void unregisterObserver(INetworkManagementEventObserver observer) { 292 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 293 mObservers.unregister(observer); 294 } 295 296 /** 297 * Notify our observers of an interface status change 298 */ 299 private void notifyInterfaceStatusChanged(String iface, boolean up) { 300 final int length = mObservers.beginBroadcast(); 301 try { 302 for (int i = 0; i < length; i++) { 303 try { 304 mObservers.getBroadcastItem(i).interfaceStatusChanged(iface, up); 305 } catch (RemoteException e) { 306 } catch (RuntimeException e) { 307 } 308 } 309 } finally { 310 mObservers.finishBroadcast(); 311 } 312 } 313 314 /** 315 * Notify our observers of an interface link state change 316 * (typically, an Ethernet cable has been plugged-in or unplugged). 317 */ 318 private void notifyInterfaceLinkStateChanged(String iface, boolean up) { 319 final int length = mObservers.beginBroadcast(); 320 try { 321 for (int i = 0; i < length; i++) { 322 try { 323 mObservers.getBroadcastItem(i).interfaceLinkStateChanged(iface, up); 324 } catch (RemoteException e) { 325 } catch (RuntimeException e) { 326 } 327 } 328 } finally { 329 mObservers.finishBroadcast(); 330 } 331 } 332 333 /** 334 * Notify our observers of an interface addition. 335 */ 336 private void notifyInterfaceAdded(String iface) { 337 final int length = mObservers.beginBroadcast(); 338 try { 339 for (int i = 0; i < length; i++) { 340 try { 341 mObservers.getBroadcastItem(i).interfaceAdded(iface); 342 } catch (RemoteException e) { 343 } catch (RuntimeException e) { 344 } 345 } 346 } finally { 347 mObservers.finishBroadcast(); 348 } 349 } 350 351 /** 352 * Notify our observers of an interface removal. 353 */ 354 private void notifyInterfaceRemoved(String iface) { 355 // netd already clears out quota and alerts for removed ifaces; update 356 // our sanity-checking state. 357 mActiveAlerts.remove(iface); 358 mActiveQuotas.remove(iface); 359 360 final int length = mObservers.beginBroadcast(); 361 try { 362 for (int i = 0; i < length; i++) { 363 try { 364 mObservers.getBroadcastItem(i).interfaceRemoved(iface); 365 } catch (RemoteException e) { 366 } catch (RuntimeException e) { 367 } 368 } 369 } finally { 370 mObservers.finishBroadcast(); 371 } 372 } 373 374 /** 375 * Notify our observers of a limit reached. 376 */ 377 private void notifyLimitReached(String limitName, String iface) { 378 final int length = mObservers.beginBroadcast(); 379 try { 380 for (int i = 0; i < length; i++) { 381 try { 382 mObservers.getBroadcastItem(i).limitReached(limitName, iface); 383 } catch (RemoteException e) { 384 } catch (RuntimeException e) { 385 } 386 } 387 } finally { 388 mObservers.finishBroadcast(); 389 } 390 } 391 392 /** 393 * Notify our observers of a change in the data activity state of the interface 394 */ 395 private void notifyInterfaceClassActivity(int type, int powerState, long tsNanos, 396 boolean fromRadio) { 397 final boolean isMobile = ConnectivityManager.isNetworkTypeMobile(type); 398 if (isMobile) { 399 if (!fromRadio) { 400 if (mMobileActivityFromRadio) { 401 // If this call is not coming from a report from the radio itself, but we 402 // have previously received reports from the radio, then we will take the 403 // power state to just be whatever the radio last reported. 404 powerState = mLastPowerStateFromRadio; 405 } 406 } else { 407 mMobileActivityFromRadio = true; 408 } 409 if (mLastPowerStateFromRadio != powerState) { 410 mLastPowerStateFromRadio = powerState; 411 try { 412 getBatteryStats().noteMobileRadioPowerState(powerState, tsNanos); 413 } catch (RemoteException e) { 414 } 415 } 416 } 417 418 boolean isActive = powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM 419 || powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH; 420 421 if (!isMobile || fromRadio || !mMobileActivityFromRadio) { 422 // Report the change in data activity. We don't do this if this is a change 423 // on the mobile network, that is not coming from the radio itself, and we 424 // have previously seen change reports from the radio. In that case only 425 // the radio is the authority for the current state. 426 final int length = mObservers.beginBroadcast(); 427 try { 428 for (int i = 0; i < length; i++) { 429 try { 430 mObservers.getBroadcastItem(i).interfaceClassDataActivityChanged( 431 Integer.toString(type), isActive, tsNanos); 432 } catch (RemoteException e) { 433 } catch (RuntimeException e) { 434 } 435 } 436 } finally { 437 mObservers.finishBroadcast(); 438 } 439 } 440 441 boolean report = false; 442 synchronized (mIdleTimerLock) { 443 if (mActiveIdleTimers.isEmpty()) { 444 // If there are no idle timers, we are not monitoring activity, so we 445 // are always considered active. 446 isActive = true; 447 } 448 if (mNetworkActive != isActive) { 449 mNetworkActive = isActive; 450 report = isActive; 451 } 452 } 453 if (report) { 454 reportNetworkActive(); 455 } 456 } 457 458 /** 459 * Prepare native daemon once connected, enabling modules and pushing any 460 * existing in-memory rules. 461 */ 462 private void prepareNativeDaemon() { 463 mBandwidthControlEnabled = false; 464 465 // only enable bandwidth control when support exists 466 final boolean hasKernelSupport = new File("/proc/net/xt_qtaguid/ctrl").exists(); 467 if (hasKernelSupport) { 468 Slog.d(TAG, "enabling bandwidth control"); 469 try { 470 mConnector.execute("bandwidth", "enable"); 471 mBandwidthControlEnabled = true; 472 } catch (NativeDaemonConnectorException e) { 473 Log.wtf(TAG, "problem enabling bandwidth controls", e); 474 } 475 } else { 476 Slog.d(TAG, "not enabling bandwidth control"); 477 } 478 479 SystemProperties.set(PROP_QTAGUID_ENABLED, mBandwidthControlEnabled ? "1" : "0"); 480 481 if (mBandwidthControlEnabled) { 482 try { 483 getBatteryStats().noteNetworkStatsEnabled(); 484 } catch (RemoteException e) { 485 } 486 } 487 488 // push any existing quota or UID rules 489 synchronized (mQuotaLock) { 490 int size = mActiveQuotas.size(); 491 if (size > 0) { 492 Slog.d(TAG, "pushing " + size + " active quota rules"); 493 final HashMap<String, Long> activeQuotas = mActiveQuotas; 494 mActiveQuotas = Maps.newHashMap(); 495 for (Map.Entry<String, Long> entry : activeQuotas.entrySet()) { 496 setInterfaceQuota(entry.getKey(), entry.getValue()); 497 } 498 } 499 500 size = mActiveAlerts.size(); 501 if (size > 0) { 502 Slog.d(TAG, "pushing " + size + " active alert rules"); 503 final HashMap<String, Long> activeAlerts = mActiveAlerts; 504 mActiveAlerts = Maps.newHashMap(); 505 for (Map.Entry<String, Long> entry : activeAlerts.entrySet()) { 506 setInterfaceAlert(entry.getKey(), entry.getValue()); 507 } 508 } 509 510 size = mUidRejectOnQuota.size(); 511 if (size > 0) { 512 Slog.d(TAG, "pushing " + size + " active uid rules"); 513 final SparseBooleanArray uidRejectOnQuota = mUidRejectOnQuota; 514 mUidRejectOnQuota = new SparseBooleanArray(); 515 for (int i = 0; i < uidRejectOnQuota.size(); i++) { 516 setUidNetworkRules(uidRejectOnQuota.keyAt(i), uidRejectOnQuota.valueAt(i)); 517 } 518 } 519 } 520 521 // TODO: Push any existing firewall state 522 setFirewallEnabled(mFirewallEnabled || LockdownVpnTracker.isEnabled()); 523 } 524 525 /** 526 * Notify our observers of a new or updated interface address. 527 */ 528 private void notifyAddressUpdated(String iface, LinkAddress address) { 529 final int length = mObservers.beginBroadcast(); 530 try { 531 for (int i = 0; i < length; i++) { 532 try { 533 mObservers.getBroadcastItem(i).addressUpdated(iface, address); 534 } catch (RemoteException e) { 535 } catch (RuntimeException e) { 536 } 537 } 538 } finally { 539 mObservers.finishBroadcast(); 540 } 541 } 542 543 /** 544 * Notify our observers of a deleted interface address. 545 */ 546 private void notifyAddressRemoved(String iface, LinkAddress address) { 547 final int length = mObservers.beginBroadcast(); 548 try { 549 for (int i = 0; i < length; i++) { 550 try { 551 mObservers.getBroadcastItem(i).addressRemoved(iface, address); 552 } catch (RemoteException e) { 553 } catch (RuntimeException e) { 554 } 555 } 556 } finally { 557 mObservers.finishBroadcast(); 558 } 559 } 560 561 /** 562 * Notify our observers of DNS server information received. 563 */ 564 private void notifyInterfaceDnsServerInfo(String iface, long lifetime, String[] addresses) { 565 final int length = mObservers.beginBroadcast(); 566 try { 567 for (int i = 0; i < length; i++) { 568 try { 569 mObservers.getBroadcastItem(i).interfaceDnsServerInfo(iface, lifetime, 570 addresses); 571 } catch (RemoteException e) { 572 } catch (RuntimeException e) { 573 } 574 } 575 } finally { 576 mObservers.finishBroadcast(); 577 } 578 } 579 580 // 581 // Netd Callback handling 582 // 583 584 private class NetdCallbackReceiver implements INativeDaemonConnectorCallbacks { 585 @Override 586 public void onDaemonConnected() { 587 // event is dispatched from internal NDC thread, so we prepare the 588 // daemon back on main thread. 589 if (mConnectedSignal != null) { 590 mConnectedSignal.countDown(); 591 mConnectedSignal = null; 592 } else { 593 mFgHandler.post(new Runnable() { 594 @Override 595 public void run() { 596 prepareNativeDaemon(); 597 } 598 }); 599 } 600 } 601 602 @Override 603 public boolean onCheckHoldWakeLock(int code) { 604 return code == NetdResponseCode.InterfaceClassActivity; 605 } 606 607 @Override 608 public boolean onEvent(int code, String raw, String[] cooked) { 609 String errorMessage = String.format("Invalid event from daemon (%s)", raw); 610 switch (code) { 611 case NetdResponseCode.InterfaceChange: 612 /* 613 * a network interface change occured 614 * Format: "NNN Iface added <name>" 615 * "NNN Iface removed <name>" 616 * "NNN Iface changed <name> <up/down>" 617 * "NNN Iface linkstatus <name> <up/down>" 618 */ 619 if (cooked.length < 4 || !cooked[1].equals("Iface")) { 620 throw new IllegalStateException(errorMessage); 621 } 622 if (cooked[2].equals("added")) { 623 notifyInterfaceAdded(cooked[3]); 624 return true; 625 } else if (cooked[2].equals("removed")) { 626 notifyInterfaceRemoved(cooked[3]); 627 return true; 628 } else if (cooked[2].equals("changed") && cooked.length == 5) { 629 notifyInterfaceStatusChanged(cooked[3], cooked[4].equals("up")); 630 return true; 631 } else if (cooked[2].equals("linkstate") && cooked.length == 5) { 632 notifyInterfaceLinkStateChanged(cooked[3], cooked[4].equals("up")); 633 return true; 634 } 635 throw new IllegalStateException(errorMessage); 636 // break; 637 case NetdResponseCode.BandwidthControl: 638 /* 639 * Bandwidth control needs some attention 640 * Format: "NNN limit alert <alertName> <ifaceName>" 641 */ 642 if (cooked.length < 5 || !cooked[1].equals("limit")) { 643 throw new IllegalStateException(errorMessage); 644 } 645 if (cooked[2].equals("alert")) { 646 notifyLimitReached(cooked[3], cooked[4]); 647 return true; 648 } 649 throw new IllegalStateException(errorMessage); 650 // break; 651 case NetdResponseCode.InterfaceClassActivity: 652 /* 653 * An network interface class state changed (active/idle) 654 * Format: "NNN IfaceClass <active/idle> <label>" 655 */ 656 if (cooked.length < 4 || !cooked[1].equals("IfaceClass")) { 657 throw new IllegalStateException(errorMessage); 658 } 659 long timestampNanos = 0; 660 if (cooked.length == 5) { 661 try { 662 timestampNanos = Long.parseLong(cooked[4]); 663 } catch(NumberFormatException ne) {} 664 } else { 665 timestampNanos = SystemClock.elapsedRealtimeNanos(); 666 } 667 boolean isActive = cooked[2].equals("active"); 668 notifyInterfaceClassActivity(Integer.parseInt(cooked[3]), 669 isActive ? DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH 670 : DataConnectionRealTimeInfo.DC_POWER_STATE_LOW, timestampNanos, false); 671 return true; 672 // break; 673 case NetdResponseCode.InterfaceAddressChange: 674 /* 675 * A network address change occurred 676 * Format: "NNN Address updated <addr> <iface> <flags> <scope>" 677 * "NNN Address removed <addr> <iface> <flags> <scope>" 678 */ 679 if (cooked.length < 7 || !cooked[1].equals("Address")) { 680 throw new IllegalStateException(errorMessage); 681 } 682 683 String iface = cooked[4]; 684 LinkAddress address; 685 try { 686 int flags = Integer.parseInt(cooked[5]); 687 int scope = Integer.parseInt(cooked[6]); 688 address = new LinkAddress(cooked[3], flags, scope); 689 } catch(NumberFormatException e) { // Non-numeric lifetime or scope. 690 throw new IllegalStateException(errorMessage, e); 691 } catch(IllegalArgumentException e) { // Malformed/invalid IP address. 692 throw new IllegalStateException(errorMessage, e); 693 } 694 695 if (cooked[2].equals("updated")) { 696 notifyAddressUpdated(iface, address); 697 } else { 698 notifyAddressRemoved(iface, address); 699 } 700 return true; 701 // break; 702 case NetdResponseCode.InterfaceDnsServerInfo: 703 /* 704 * Information about available DNS servers has been received. 705 * Format: "NNN DnsInfo servers <interface> <lifetime> <servers>" 706 */ 707 long lifetime; // Actually a 32-bit unsigned integer. 708 709 if (cooked.length == 6 && 710 cooked[1].equals("DnsInfo") && 711 cooked[2].equals("servers")) { 712 try { 713 lifetime = Long.parseLong(cooked[4]); 714 } catch (NumberFormatException e) { 715 throw new IllegalStateException(errorMessage); 716 } 717 String[] servers = cooked[5].split(","); 718 notifyInterfaceDnsServerInfo(cooked[3], lifetime, servers); 719 } 720 return true; 721 // break; 722 default: break; 723 } 724 return false; 725 } 726 } 727 728 729 // 730 // INetworkManagementService members 731 // 732 733 @Override 734 public String[] listInterfaces() { 735 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 736 try { 737 return NativeDaemonEvent.filterMessageList( 738 mConnector.executeForList("interface", "list"), InterfaceListResult); 739 } catch (NativeDaemonConnectorException e) { 740 throw e.rethrowAsParcelableException(); 741 } 742 } 743 744 @Override 745 public InterfaceConfiguration getInterfaceConfig(String iface) { 746 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 747 748 final NativeDaemonEvent event; 749 try { 750 event = mConnector.execute("interface", "getcfg", iface); 751 } catch (NativeDaemonConnectorException e) { 752 throw e.rethrowAsParcelableException(); 753 } 754 755 event.checkCode(InterfaceGetCfgResult); 756 757 // Rsp: 213 xx:xx:xx:xx:xx:xx yyy.yyy.yyy.yyy zzz flag1 flag2 flag3 758 final StringTokenizer st = new StringTokenizer(event.getMessage()); 759 760 InterfaceConfiguration cfg; 761 try { 762 cfg = new InterfaceConfiguration(); 763 cfg.setHardwareAddress(st.nextToken(" ")); 764 InetAddress addr = null; 765 int prefixLength = 0; 766 try { 767 addr = NetworkUtils.numericToInetAddress(st.nextToken()); 768 } catch (IllegalArgumentException iae) { 769 Slog.e(TAG, "Failed to parse ipaddr", iae); 770 } 771 772 try { 773 prefixLength = Integer.parseInt(st.nextToken()); 774 } catch (NumberFormatException nfe) { 775 Slog.e(TAG, "Failed to parse prefixLength", nfe); 776 } 777 778 cfg.setLinkAddress(new LinkAddress(addr, prefixLength)); 779 while (st.hasMoreTokens()) { 780 cfg.setFlag(st.nextToken()); 781 } 782 } catch (NoSuchElementException nsee) { 783 throw new IllegalStateException("Invalid response from daemon: " + event); 784 } 785 return cfg; 786 } 787 788 @Override 789 public void setInterfaceConfig(String iface, InterfaceConfiguration cfg) { 790 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 791 LinkAddress linkAddr = cfg.getLinkAddress(); 792 if (linkAddr == null || linkAddr.getAddress() == null) { 793 throw new IllegalStateException("Null LinkAddress given"); 794 } 795 796 final Command cmd = new Command("interface", "setcfg", iface, 797 linkAddr.getAddress().getHostAddress(), 798 linkAddr.getNetworkPrefixLength()); 799 for (String flag : cfg.getFlags()) { 800 cmd.appendArg(flag); 801 } 802 803 try { 804 mConnector.execute(cmd); 805 } catch (NativeDaemonConnectorException e) { 806 throw e.rethrowAsParcelableException(); 807 } 808 } 809 810 @Override 811 public void setInterfaceDown(String iface) { 812 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 813 final InterfaceConfiguration ifcg = getInterfaceConfig(iface); 814 ifcg.setInterfaceDown(); 815 setInterfaceConfig(iface, ifcg); 816 } 817 818 @Override 819 public void setInterfaceUp(String iface) { 820 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 821 final InterfaceConfiguration ifcg = getInterfaceConfig(iface); 822 ifcg.setInterfaceUp(); 823 setInterfaceConfig(iface, ifcg); 824 } 825 826 @Override 827 public void setInterfaceIpv6PrivacyExtensions(String iface, boolean enable) { 828 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 829 try { 830 mConnector.execute( 831 "interface", "ipv6privacyextensions", iface, enable ? "enable" : "disable"); 832 } catch (NativeDaemonConnectorException e) { 833 throw e.rethrowAsParcelableException(); 834 } 835 } 836 837 /* TODO: This is right now a IPv4 only function. Works for wifi which loses its 838 IPv6 addresses on interface down, but we need to do full clean up here */ 839 @Override 840 public void clearInterfaceAddresses(String iface) { 841 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 842 try { 843 mConnector.execute("interface", "clearaddrs", iface); 844 } catch (NativeDaemonConnectorException e) { 845 throw e.rethrowAsParcelableException(); 846 } 847 } 848 849 @Override 850 public void enableIpv6(String iface) { 851 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 852 try { 853 mConnector.execute("interface", "ipv6", iface, "enable"); 854 } catch (NativeDaemonConnectorException e) { 855 throw e.rethrowAsParcelableException(); 856 } 857 } 858 859 @Override 860 public void disableIpv6(String iface) { 861 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 862 try { 863 mConnector.execute("interface", "ipv6", iface, "disable"); 864 } catch (NativeDaemonConnectorException e) { 865 throw e.rethrowAsParcelableException(); 866 } 867 } 868 869 @Override 870 public void addRoute(String interfaceName, RouteInfo route) { 871 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 872 modifyRoute(interfaceName, ADD, route, DEFAULT); 873 } 874 875 @Override 876 public void removeRoute(String interfaceName, RouteInfo route) { 877 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 878 modifyRoute(interfaceName, REMOVE, route, DEFAULT); 879 } 880 881 @Override 882 public void addSecondaryRoute(String interfaceName, RouteInfo route) { 883 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 884 modifyRoute(interfaceName, ADD, route, SECONDARY); 885 } 886 887 @Override 888 public void removeSecondaryRoute(String interfaceName, RouteInfo route) { 889 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 890 modifyRoute(interfaceName, REMOVE, route, SECONDARY); 891 } 892 893 private void modifyRoute(String interfaceName, String action, RouteInfo route, String type) { 894 final Command cmd = new Command("interface", "route", action, interfaceName, type); 895 896 // create triplet: dest-ip-addr prefixlength gateway-ip-addr 897 final LinkAddress la = route.getDestination(); 898 cmd.appendArg(la.getAddress().getHostAddress()); 899 cmd.appendArg(la.getNetworkPrefixLength()); 900 901 if (route.getGateway() == null) { 902 if (la.getAddress() instanceof Inet4Address) { 903 cmd.appendArg("0.0.0.0"); 904 } else { 905 cmd.appendArg("::0"); 906 } 907 } else { 908 cmd.appendArg(route.getGateway().getHostAddress()); 909 } 910 911 try { 912 mConnector.execute(cmd); 913 } catch (NativeDaemonConnectorException e) { 914 throw e.rethrowAsParcelableException(); 915 } 916 } 917 918 private ArrayList<String> readRouteList(String filename) { 919 FileInputStream fstream = null; 920 ArrayList<String> list = new ArrayList<String>(); 921 922 try { 923 fstream = new FileInputStream(filename); 924 DataInputStream in = new DataInputStream(fstream); 925 BufferedReader br = new BufferedReader(new InputStreamReader(in)); 926 String s; 927 928 // throw away the title line 929 930 while (((s = br.readLine()) != null) && (s.length() != 0)) { 931 list.add(s); 932 } 933 } catch (IOException ex) { 934 // return current list, possibly empty 935 } finally { 936 if (fstream != null) { 937 try { 938 fstream.close(); 939 } catch (IOException ex) {} 940 } 941 } 942 943 return list; 944 } 945 946 @Override 947 public RouteInfo[] getRoutes(String interfaceName) { 948 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 949 ArrayList<RouteInfo> routes = new ArrayList<RouteInfo>(); 950 951 // v4 routes listed as: 952 // iface dest-addr gateway-addr flags refcnt use metric netmask mtu window IRTT 953 for (String s : readRouteList("/proc/net/route")) { 954 String[] fields = s.split("\t"); 955 956 if (fields.length > 7) { 957 String iface = fields[0]; 958 959 if (interfaceName.equals(iface)) { 960 String dest = fields[1]; 961 String gate = fields[2]; 962 String flags = fields[3]; // future use? 963 String mask = fields[7]; 964 try { 965 // address stored as a hex string, ex: 0014A8C0 966 InetAddress destAddr = 967 NetworkUtils.intToInetAddress((int)Long.parseLong(dest, 16)); 968 int prefixLength = 969 NetworkUtils.netmaskIntToPrefixLength( 970 (int)Long.parseLong(mask, 16)); 971 LinkAddress linkAddress = new LinkAddress(destAddr, prefixLength); 972 973 // address stored as a hex string, ex 0014A8C0 974 InetAddress gatewayAddr = 975 NetworkUtils.intToInetAddress((int)Long.parseLong(gate, 16)); 976 977 RouteInfo route = new RouteInfo(linkAddress, gatewayAddr); 978 routes.add(route); 979 } catch (Exception e) { 980 Log.e(TAG, "Error parsing route " + s + " : " + e); 981 continue; 982 } 983 } 984 } 985 } 986 987 // v6 routes listed as: 988 // dest-addr prefixlength ?? ?? gateway-addr ?? ?? ?? ?? iface 989 for (String s : readRouteList("/proc/net/ipv6_route")) { 990 String[]fields = s.split("\\s+"); 991 if (fields.length > 9) { 992 String iface = fields[9].trim(); 993 if (interfaceName.equals(iface)) { 994 String dest = fields[0]; 995 String prefix = fields[1]; 996 String gate = fields[4]; 997 998 try { 999 // prefix length stored as a hex string, ex 40 1000 int prefixLength = Integer.parseInt(prefix, 16); 1001 1002 // address stored as a 32 char hex string 1003 // ex fe800000000000000000000000000000 1004 InetAddress destAddr = NetworkUtils.hexToInet6Address(dest); 1005 LinkAddress linkAddress = new LinkAddress(destAddr, prefixLength); 1006 1007 InetAddress gateAddr = NetworkUtils.hexToInet6Address(gate); 1008 1009 RouteInfo route = new RouteInfo(linkAddress, gateAddr); 1010 routes.add(route); 1011 } catch (Exception e) { 1012 Log.e(TAG, "Error parsing route " + s + " : " + e); 1013 continue; 1014 } 1015 } 1016 } 1017 } 1018 return routes.toArray(new RouteInfo[routes.size()]); 1019 } 1020 1021 @Override 1022 public void setMtu(String iface, int mtu) { 1023 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1024 1025 final NativeDaemonEvent event; 1026 try { 1027 event = mConnector.execute("interface", "setmtu", iface, mtu); 1028 } catch (NativeDaemonConnectorException e) { 1029 throw e.rethrowAsParcelableException(); 1030 } 1031 } 1032 1033 @Override 1034 public void shutdown() { 1035 // TODO: remove from aidl if nobody calls externally 1036 mContext.enforceCallingOrSelfPermission(SHUTDOWN, TAG); 1037 1038 Slog.d(TAG, "Shutting down"); 1039 } 1040 1041 @Override 1042 public boolean getIpForwardingEnabled() throws IllegalStateException{ 1043 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1044 1045 final NativeDaemonEvent event; 1046 try { 1047 event = mConnector.execute("ipfwd", "status"); 1048 } catch (NativeDaemonConnectorException e) { 1049 throw e.rethrowAsParcelableException(); 1050 } 1051 1052 // 211 Forwarding enabled 1053 event.checkCode(IpFwdStatusResult); 1054 return event.getMessage().endsWith("enabled"); 1055 } 1056 1057 @Override 1058 public void setIpForwardingEnabled(boolean enable) { 1059 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1060 try { 1061 mConnector.execute("ipfwd", enable ? "enable" : "disable"); 1062 } catch (NativeDaemonConnectorException e) { 1063 throw e.rethrowAsParcelableException(); 1064 } 1065 } 1066 1067 @Override 1068 public void startTethering(String[] dhcpRange) { 1069 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1070 // cmd is "tether start first_start first_stop second_start second_stop ..." 1071 // an odd number of addrs will fail 1072 1073 final Command cmd = new Command("tether", "start"); 1074 for (String d : dhcpRange) { 1075 cmd.appendArg(d); 1076 } 1077 1078 try { 1079 mConnector.execute(cmd); 1080 } catch (NativeDaemonConnectorException e) { 1081 throw e.rethrowAsParcelableException(); 1082 } 1083 } 1084 1085 @Override 1086 public void stopTethering() { 1087 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1088 try { 1089 mConnector.execute("tether", "stop"); 1090 } catch (NativeDaemonConnectorException e) { 1091 throw e.rethrowAsParcelableException(); 1092 } 1093 } 1094 1095 @Override 1096 public boolean isTetheringStarted() { 1097 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1098 1099 final NativeDaemonEvent event; 1100 try { 1101 event = mConnector.execute("tether", "status"); 1102 } catch (NativeDaemonConnectorException e) { 1103 throw e.rethrowAsParcelableException(); 1104 } 1105 1106 // 210 Tethering services started 1107 event.checkCode(TetherStatusResult); 1108 return event.getMessage().endsWith("started"); 1109 } 1110 1111 @Override 1112 public void tetherInterface(String iface) { 1113 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1114 try { 1115 mConnector.execute("tether", "interface", "add", iface); 1116 } catch (NativeDaemonConnectorException e) { 1117 throw e.rethrowAsParcelableException(); 1118 } 1119 } 1120 1121 @Override 1122 public void untetherInterface(String iface) { 1123 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1124 try { 1125 mConnector.execute("tether", "interface", "remove", iface); 1126 } catch (NativeDaemonConnectorException e) { 1127 throw e.rethrowAsParcelableException(); 1128 } 1129 } 1130 1131 @Override 1132 public String[] listTetheredInterfaces() { 1133 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1134 try { 1135 return NativeDaemonEvent.filterMessageList( 1136 mConnector.executeForList("tether", "interface", "list"), 1137 TetherInterfaceListResult); 1138 } catch (NativeDaemonConnectorException e) { 1139 throw e.rethrowAsParcelableException(); 1140 } 1141 } 1142 1143 @Override 1144 public void setDnsForwarders(String[] dns) { 1145 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1146 1147 final Command cmd = new Command("tether", "dns", "set"); 1148 for (String s : dns) { 1149 cmd.appendArg(NetworkUtils.numericToInetAddress(s).getHostAddress()); 1150 } 1151 1152 try { 1153 mConnector.execute(cmd); 1154 } catch (NativeDaemonConnectorException e) { 1155 throw e.rethrowAsParcelableException(); 1156 } 1157 } 1158 1159 @Override 1160 public String[] getDnsForwarders() { 1161 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1162 try { 1163 return NativeDaemonEvent.filterMessageList( 1164 mConnector.executeForList("tether", "dns", "list"), TetherDnsFwdTgtListResult); 1165 } catch (NativeDaemonConnectorException e) { 1166 throw e.rethrowAsParcelableException(); 1167 } 1168 } 1169 1170 private List<InterfaceAddress> excludeLinkLocal(List<InterfaceAddress> addresses) { 1171 ArrayList<InterfaceAddress> filtered = new ArrayList<InterfaceAddress>(addresses.size()); 1172 for (InterfaceAddress ia : addresses) { 1173 if (!ia.getAddress().isLinkLocalAddress()) 1174 filtered.add(ia); 1175 } 1176 return filtered; 1177 } 1178 1179 private void modifyNat(String action, String internalInterface, String externalInterface) 1180 throws SocketException { 1181 final Command cmd = new Command("nat", action, internalInterface, externalInterface); 1182 1183 final NetworkInterface internalNetworkInterface = NetworkInterface.getByName( 1184 internalInterface); 1185 if (internalNetworkInterface == null) { 1186 cmd.appendArg("0"); 1187 } else { 1188 // Don't touch link-local routes, as link-local addresses aren't routable, 1189 // kernel creates link-local routes on all interfaces automatically 1190 List<InterfaceAddress> interfaceAddresses = excludeLinkLocal( 1191 internalNetworkInterface.getInterfaceAddresses()); 1192 cmd.appendArg(interfaceAddresses.size()); 1193 for (InterfaceAddress ia : interfaceAddresses) { 1194 InetAddress addr = NetworkUtils.getNetworkPart( 1195 ia.getAddress(), ia.getNetworkPrefixLength()); 1196 cmd.appendArg(addr.getHostAddress() + "/" + ia.getNetworkPrefixLength()); 1197 } 1198 } 1199 1200 try { 1201 mConnector.execute(cmd); 1202 } catch (NativeDaemonConnectorException e) { 1203 throw e.rethrowAsParcelableException(); 1204 } 1205 } 1206 1207 @Override 1208 public void enableNat(String internalInterface, String externalInterface) { 1209 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1210 try { 1211 modifyNat("enable", internalInterface, externalInterface); 1212 } catch (SocketException e) { 1213 throw new IllegalStateException(e); 1214 } 1215 } 1216 1217 @Override 1218 public void disableNat(String internalInterface, String externalInterface) { 1219 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1220 try { 1221 modifyNat("disable", internalInterface, externalInterface); 1222 } catch (SocketException e) { 1223 throw new IllegalStateException(e); 1224 } 1225 } 1226 1227 @Override 1228 public String[] listTtys() { 1229 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1230 try { 1231 return NativeDaemonEvent.filterMessageList( 1232 mConnector.executeForList("list_ttys"), TtyListResult); 1233 } catch (NativeDaemonConnectorException e) { 1234 throw e.rethrowAsParcelableException(); 1235 } 1236 } 1237 1238 @Override 1239 public void attachPppd( 1240 String tty, String localAddr, String remoteAddr, String dns1Addr, String dns2Addr) { 1241 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1242 try { 1243 mConnector.execute("pppd", "attach", tty, 1244 NetworkUtils.numericToInetAddress(localAddr).getHostAddress(), 1245 NetworkUtils.numericToInetAddress(remoteAddr).getHostAddress(), 1246 NetworkUtils.numericToInetAddress(dns1Addr).getHostAddress(), 1247 NetworkUtils.numericToInetAddress(dns2Addr).getHostAddress()); 1248 } catch (NativeDaemonConnectorException e) { 1249 throw e.rethrowAsParcelableException(); 1250 } 1251 } 1252 1253 @Override 1254 public void detachPppd(String tty) { 1255 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1256 try { 1257 mConnector.execute("pppd", "detach", tty); 1258 } catch (NativeDaemonConnectorException e) { 1259 throw e.rethrowAsParcelableException(); 1260 } 1261 } 1262 1263 @Override 1264 public void startAccessPoint( 1265 WifiConfiguration wifiConfig, String wlanIface) { 1266 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1267 try { 1268 wifiFirmwareReload(wlanIface, "AP"); 1269 if (wifiConfig == null) { 1270 mConnector.execute("softap", "set", wlanIface); 1271 } else { 1272 mConnector.execute("softap", "set", wlanIface, wifiConfig.SSID, 1273 "broadcast", "6", getSecurityType(wifiConfig), 1274 new SensitiveArg(wifiConfig.preSharedKey)); 1275 } 1276 mConnector.execute("softap", "startap"); 1277 } catch (NativeDaemonConnectorException e) { 1278 throw e.rethrowAsParcelableException(); 1279 } 1280 } 1281 1282 private static String getSecurityType(WifiConfiguration wifiConfig) { 1283 switch (wifiConfig.getAuthType()) { 1284 case KeyMgmt.WPA_PSK: 1285 return "wpa-psk"; 1286 case KeyMgmt.WPA2_PSK: 1287 return "wpa2-psk"; 1288 default: 1289 return "open"; 1290 } 1291 } 1292 1293 /* @param mode can be "AP", "STA" or "P2P" */ 1294 @Override 1295 public void wifiFirmwareReload(String wlanIface, String mode) { 1296 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1297 try { 1298 mConnector.execute("softap", "fwreload", wlanIface, mode); 1299 } catch (NativeDaemonConnectorException e) { 1300 throw e.rethrowAsParcelableException(); 1301 } 1302 } 1303 1304 @Override 1305 public void stopAccessPoint(String wlanIface) { 1306 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1307 try { 1308 mConnector.execute("softap", "stopap"); 1309 wifiFirmwareReload(wlanIface, "STA"); 1310 } catch (NativeDaemonConnectorException e) { 1311 throw e.rethrowAsParcelableException(); 1312 } 1313 } 1314 1315 @Override 1316 public void setAccessPoint(WifiConfiguration wifiConfig, String wlanIface) { 1317 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1318 try { 1319 if (wifiConfig == null) { 1320 mConnector.execute("softap", "set", wlanIface); 1321 } else { 1322 mConnector.execute("softap", "set", wlanIface, wifiConfig.SSID, 1323 "broadcast", "6", getSecurityType(wifiConfig), 1324 new SensitiveArg(wifiConfig.preSharedKey)); 1325 } 1326 } catch (NativeDaemonConnectorException e) { 1327 throw e.rethrowAsParcelableException(); 1328 } 1329 } 1330 1331 @Override 1332 public void addIdleTimer(String iface, int timeout, final int type) { 1333 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1334 1335 if (DBG) Slog.d(TAG, "Adding idletimer"); 1336 1337 synchronized (mIdleTimerLock) { 1338 IdleTimerParams params = mActiveIdleTimers.get(iface); 1339 if (params != null) { 1340 // the interface already has idletimer, update network count 1341 params.networkCount++; 1342 return; 1343 } 1344 1345 try { 1346 mConnector.execute("idletimer", "add", iface, Integer.toString(timeout), 1347 Integer.toString(type)); 1348 } catch (NativeDaemonConnectorException e) { 1349 throw e.rethrowAsParcelableException(); 1350 } 1351 mActiveIdleTimers.put(iface, new IdleTimerParams(timeout, type)); 1352 1353 // Networks start up. 1354 if (ConnectivityManager.isNetworkTypeMobile(type)) { 1355 mNetworkActive = false; 1356 } 1357 mDaemonHandler.post(new Runnable() { 1358 @Override public void run() { 1359 notifyInterfaceClassActivity(type, 1360 DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH, 1361 SystemClock.elapsedRealtimeNanos(), false); 1362 } 1363 }); 1364 } 1365 } 1366 1367 @Override 1368 public void removeIdleTimer(String iface) { 1369 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1370 1371 if (DBG) Slog.d(TAG, "Removing idletimer"); 1372 1373 synchronized (mIdleTimerLock) { 1374 final IdleTimerParams params = mActiveIdleTimers.get(iface); 1375 if (params == null || --(params.networkCount) > 0) { 1376 return; 1377 } 1378 1379 try { 1380 mConnector.execute("idletimer", "remove", iface, 1381 Integer.toString(params.timeout), Integer.toString(params.type)); 1382 } catch (NativeDaemonConnectorException e) { 1383 throw e.rethrowAsParcelableException(); 1384 } 1385 mActiveIdleTimers.remove(iface); 1386 mDaemonHandler.post(new Runnable() { 1387 @Override public void run() { 1388 notifyInterfaceClassActivity(params.type, 1389 DataConnectionRealTimeInfo.DC_POWER_STATE_LOW, 1390 SystemClock.elapsedRealtimeNanos(), false); 1391 } 1392 }); 1393 } 1394 } 1395 1396 @Override 1397 public NetworkStats getNetworkStatsSummaryDev() { 1398 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1399 try { 1400 return mStatsFactory.readNetworkStatsSummaryDev(); 1401 } catch (IOException e) { 1402 throw new IllegalStateException(e); 1403 } 1404 } 1405 1406 @Override 1407 public NetworkStats getNetworkStatsSummaryXt() { 1408 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1409 try { 1410 return mStatsFactory.readNetworkStatsSummaryXt(); 1411 } catch (IOException e) { 1412 throw new IllegalStateException(e); 1413 } 1414 } 1415 1416 @Override 1417 public NetworkStats getNetworkStatsDetail() { 1418 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1419 try { 1420 return mStatsFactory.readNetworkStatsDetail(UID_ALL, null, TAG_ALL, null); 1421 } catch (IOException e) { 1422 throw new IllegalStateException(e); 1423 } 1424 } 1425 1426 @Override 1427 public void setInterfaceQuota(String iface, long quotaBytes) { 1428 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1429 1430 // silently discard when control disabled 1431 // TODO: eventually migrate to be always enabled 1432 if (!mBandwidthControlEnabled) return; 1433 1434 synchronized (mQuotaLock) { 1435 if (mActiveQuotas.containsKey(iface)) { 1436 throw new IllegalStateException("iface " + iface + " already has quota"); 1437 } 1438 1439 try { 1440 // TODO: support quota shared across interfaces 1441 mConnector.execute("bandwidth", "setiquota", iface, quotaBytes); 1442 mActiveQuotas.put(iface, quotaBytes); 1443 } catch (NativeDaemonConnectorException e) { 1444 throw e.rethrowAsParcelableException(); 1445 } 1446 } 1447 } 1448 1449 @Override 1450 public void removeInterfaceQuota(String iface) { 1451 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1452 1453 // silently discard when control disabled 1454 // TODO: eventually migrate to be always enabled 1455 if (!mBandwidthControlEnabled) return; 1456 1457 synchronized (mQuotaLock) { 1458 if (!mActiveQuotas.containsKey(iface)) { 1459 // TODO: eventually consider throwing 1460 return; 1461 } 1462 1463 mActiveQuotas.remove(iface); 1464 mActiveAlerts.remove(iface); 1465 1466 try { 1467 // TODO: support quota shared across interfaces 1468 mConnector.execute("bandwidth", "removeiquota", iface); 1469 } catch (NativeDaemonConnectorException e) { 1470 throw e.rethrowAsParcelableException(); 1471 } 1472 } 1473 } 1474 1475 @Override 1476 public void setInterfaceAlert(String iface, long alertBytes) { 1477 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1478 1479 // silently discard when control disabled 1480 // TODO: eventually migrate to be always enabled 1481 if (!mBandwidthControlEnabled) return; 1482 1483 // quick sanity check 1484 if (!mActiveQuotas.containsKey(iface)) { 1485 throw new IllegalStateException("setting alert requires existing quota on iface"); 1486 } 1487 1488 synchronized (mQuotaLock) { 1489 if (mActiveAlerts.containsKey(iface)) { 1490 throw new IllegalStateException("iface " + iface + " already has alert"); 1491 } 1492 1493 try { 1494 // TODO: support alert shared across interfaces 1495 mConnector.execute("bandwidth", "setinterfacealert", iface, alertBytes); 1496 mActiveAlerts.put(iface, alertBytes); 1497 } catch (NativeDaemonConnectorException e) { 1498 throw e.rethrowAsParcelableException(); 1499 } 1500 } 1501 } 1502 1503 @Override 1504 public void removeInterfaceAlert(String iface) { 1505 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1506 1507 // silently discard when control disabled 1508 // TODO: eventually migrate to be always enabled 1509 if (!mBandwidthControlEnabled) return; 1510 1511 synchronized (mQuotaLock) { 1512 if (!mActiveAlerts.containsKey(iface)) { 1513 // TODO: eventually consider throwing 1514 return; 1515 } 1516 1517 try { 1518 // TODO: support alert shared across interfaces 1519 mConnector.execute("bandwidth", "removeinterfacealert", iface); 1520 mActiveAlerts.remove(iface); 1521 } catch (NativeDaemonConnectorException e) { 1522 throw e.rethrowAsParcelableException(); 1523 } 1524 } 1525 } 1526 1527 @Override 1528 public void setGlobalAlert(long alertBytes) { 1529 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1530 1531 // silently discard when control disabled 1532 // TODO: eventually migrate to be always enabled 1533 if (!mBandwidthControlEnabled) return; 1534 1535 try { 1536 mConnector.execute("bandwidth", "setglobalalert", alertBytes); 1537 } catch (NativeDaemonConnectorException e) { 1538 throw e.rethrowAsParcelableException(); 1539 } 1540 } 1541 1542 @Override 1543 public void setUidNetworkRules(int uid, boolean rejectOnQuotaInterfaces) { 1544 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1545 1546 // silently discard when control disabled 1547 // TODO: eventually migrate to be always enabled 1548 if (!mBandwidthControlEnabled) return; 1549 1550 synchronized (mQuotaLock) { 1551 final boolean oldRejectOnQuota = mUidRejectOnQuota.get(uid, false); 1552 if (oldRejectOnQuota == rejectOnQuotaInterfaces) { 1553 // TODO: eventually consider throwing 1554 return; 1555 } 1556 1557 try { 1558 mConnector.execute("bandwidth", 1559 rejectOnQuotaInterfaces ? "addnaughtyapps" : "removenaughtyapps", uid); 1560 if (rejectOnQuotaInterfaces) { 1561 mUidRejectOnQuota.put(uid, true); 1562 } else { 1563 mUidRejectOnQuota.delete(uid); 1564 } 1565 } catch (NativeDaemonConnectorException e) { 1566 throw e.rethrowAsParcelableException(); 1567 } 1568 } 1569 } 1570 1571 @Override 1572 public boolean isBandwidthControlEnabled() { 1573 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1574 return mBandwidthControlEnabled; 1575 } 1576 1577 @Override 1578 public NetworkStats getNetworkStatsUidDetail(int uid) { 1579 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1580 try { 1581 return mStatsFactory.readNetworkStatsDetail(uid, null, TAG_ALL, null); 1582 } catch (IOException e) { 1583 throw new IllegalStateException(e); 1584 } 1585 } 1586 1587 @Override 1588 public NetworkStats getNetworkStatsTethering() { 1589 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1590 1591 final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 1); 1592 try { 1593 final NativeDaemonEvent[] events = mConnector.executeForList( 1594 "bandwidth", "gettetherstats"); 1595 for (NativeDaemonEvent event : events) { 1596 if (event.getCode() != TetheringStatsListResult) continue; 1597 1598 // 114 ifaceIn ifaceOut rx_bytes rx_packets tx_bytes tx_packets 1599 final StringTokenizer tok = new StringTokenizer(event.getMessage()); 1600 try { 1601 final String ifaceIn = tok.nextToken(); 1602 final String ifaceOut = tok.nextToken(); 1603 1604 final NetworkStats.Entry entry = new NetworkStats.Entry(); 1605 entry.iface = ifaceOut; 1606 entry.uid = UID_TETHERING; 1607 entry.set = SET_DEFAULT; 1608 entry.tag = TAG_NONE; 1609 entry.rxBytes = Long.parseLong(tok.nextToken()); 1610 entry.rxPackets = Long.parseLong(tok.nextToken()); 1611 entry.txBytes = Long.parseLong(tok.nextToken()); 1612 entry.txPackets = Long.parseLong(tok.nextToken()); 1613 stats.combineValues(entry); 1614 } catch (NoSuchElementException e) { 1615 throw new IllegalStateException("problem parsing tethering stats: " + event); 1616 } catch (NumberFormatException e) { 1617 throw new IllegalStateException("problem parsing tethering stats: " + event); 1618 } 1619 } 1620 } catch (NativeDaemonConnectorException e) { 1621 throw e.rethrowAsParcelableException(); 1622 } 1623 return stats; 1624 } 1625 1626 @Override 1627 public void setDefaultInterfaceForDns(String iface) { 1628 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1629 try { 1630 mConnector.execute("resolver", "setdefaultif", iface); 1631 } catch (NativeDaemonConnectorException e) { 1632 throw e.rethrowAsParcelableException(); 1633 } 1634 } 1635 1636 @Override 1637 public void setDnsServersForInterface(String iface, String[] servers, String domains) { 1638 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1639 1640 final Command cmd = new Command("resolver", "setifdns", iface, 1641 (domains == null ? "" : domains)); 1642 1643 for (String s : servers) { 1644 InetAddress a = NetworkUtils.numericToInetAddress(s); 1645 if (a.isAnyLocalAddress() == false) { 1646 cmd.appendArg(a.getHostAddress()); 1647 } 1648 } 1649 1650 try { 1651 mConnector.execute(cmd); 1652 } catch (NativeDaemonConnectorException e) { 1653 throw e.rethrowAsParcelableException(); 1654 } 1655 } 1656 1657 @Override 1658 public void setUidRangeRoute(String iface, int uid_start, int uid_end) { 1659 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1660 try { 1661 mConnector.execute("interface", "fwmark", 1662 "uid", "add", iface, uid_start, uid_end); 1663 } catch (NativeDaemonConnectorException e) { 1664 throw e.rethrowAsParcelableException(); 1665 } 1666 } 1667 1668 @Override 1669 public void clearUidRangeRoute(String iface, int uid_start, int uid_end) { 1670 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1671 try { 1672 mConnector.execute("interface", "fwmark", 1673 "uid", "remove", iface, uid_start, uid_end); 1674 } catch (NativeDaemonConnectorException e) { 1675 throw e.rethrowAsParcelableException(); 1676 } 1677 } 1678 1679 @Override 1680 public void setMarkedForwarding(String iface) { 1681 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1682 try { 1683 mConnector.execute("interface", "fwmark", "rule", "add", iface); 1684 } catch (NativeDaemonConnectorException e) { 1685 throw e.rethrowAsParcelableException(); 1686 } 1687 } 1688 1689 @Override 1690 public void clearMarkedForwarding(String iface) { 1691 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1692 try { 1693 mConnector.execute("interface", "fwmark", "rule", "remove", iface); 1694 } catch (NativeDaemonConnectorException e) { 1695 throw e.rethrowAsParcelableException(); 1696 } 1697 } 1698 1699 @Override 1700 public int getMarkForUid(int uid) { 1701 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1702 final NativeDaemonEvent event; 1703 try { 1704 event = mConnector.execute("interface", "fwmark", "get", "mark", uid); 1705 } catch (NativeDaemonConnectorException e) { 1706 throw e.rethrowAsParcelableException(); 1707 } 1708 event.checkCode(GetMarkResult); 1709 return Integer.parseInt(event.getMessage()); 1710 } 1711 1712 @Override 1713 public int getMarkForProtect() { 1714 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1715 final NativeDaemonEvent event; 1716 try { 1717 event = mConnector.execute("interface", "fwmark", "get", "protect"); 1718 } catch (NativeDaemonConnectorException e) { 1719 throw e.rethrowAsParcelableException(); 1720 } 1721 event.checkCode(GetMarkResult); 1722 return Integer.parseInt(event.getMessage()); 1723 } 1724 1725 @Override 1726 public void setMarkedForwardingRoute(String iface, RouteInfo route) { 1727 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1728 try { 1729 LinkAddress dest = route.getDestination(); 1730 mConnector.execute("interface", "fwmark", "route", "add", iface, 1731 dest.getAddress().getHostAddress(), dest.getNetworkPrefixLength()); 1732 } catch (NativeDaemonConnectorException e) { 1733 throw e.rethrowAsParcelableException(); 1734 } 1735 } 1736 1737 @Override 1738 public void clearMarkedForwardingRoute(String iface, RouteInfo route) { 1739 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1740 try { 1741 LinkAddress dest = route.getDestination(); 1742 mConnector.execute("interface", "fwmark", "route", "remove", iface, 1743 dest.getAddress().getHostAddress(), dest.getNetworkPrefixLength()); 1744 } catch (NativeDaemonConnectorException e) { 1745 throw e.rethrowAsParcelableException(); 1746 } 1747 } 1748 1749 @Override 1750 public void setHostExemption(LinkAddress host) { 1751 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1752 try { 1753 mConnector.execute("interface", "fwmark", "exempt", "add", host); 1754 } catch (NativeDaemonConnectorException e) { 1755 throw e.rethrowAsParcelableException(); 1756 } 1757 } 1758 1759 @Override 1760 public void clearHostExemption(LinkAddress host) { 1761 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1762 try { 1763 mConnector.execute("interface", "fwmark", "exempt", "remove", host); 1764 } catch (NativeDaemonConnectorException e) { 1765 throw e.rethrowAsParcelableException(); 1766 } 1767 } 1768 1769 @Override 1770 public void setDnsInterfaceForUidRange(String iface, int uid_start, int uid_end) { 1771 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1772 try { 1773 mConnector.execute("resolver", "setifaceforuidrange", iface, uid_start, uid_end); 1774 } catch (NativeDaemonConnectorException e) { 1775 throw e.rethrowAsParcelableException(); 1776 } 1777 } 1778 1779 @Override 1780 public void clearDnsInterfaceForUidRange(String iface, int uid_start, int uid_end) { 1781 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1782 try { 1783 mConnector.execute("resolver", "clearifaceforuidrange", iface, uid_start, uid_end); 1784 } catch (NativeDaemonConnectorException e) { 1785 throw e.rethrowAsParcelableException(); 1786 } 1787 } 1788 1789 @Override 1790 public void clearDnsInterfaceMaps() { 1791 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1792 try { 1793 mConnector.execute("resolver", "clearifacemapping"); 1794 } catch (NativeDaemonConnectorException e) { 1795 throw e.rethrowAsParcelableException(); 1796 } 1797 } 1798 1799 1800 @Override 1801 public void flushDefaultDnsCache() { 1802 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1803 try { 1804 mConnector.execute("resolver", "flushdefaultif"); 1805 } catch (NativeDaemonConnectorException e) { 1806 throw e.rethrowAsParcelableException(); 1807 } 1808 } 1809 1810 @Override 1811 public void flushInterfaceDnsCache(String iface) { 1812 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1813 try { 1814 mConnector.execute("resolver", "flushif", iface); 1815 } catch (NativeDaemonConnectorException e) { 1816 throw e.rethrowAsParcelableException(); 1817 } 1818 } 1819 1820 @Override 1821 public void setFirewallEnabled(boolean enabled) { 1822 enforceSystemUid(); 1823 try { 1824 mConnector.execute("firewall", enabled ? "enable" : "disable"); 1825 mFirewallEnabled = enabled; 1826 } catch (NativeDaemonConnectorException e) { 1827 throw e.rethrowAsParcelableException(); 1828 } 1829 } 1830 1831 @Override 1832 public boolean isFirewallEnabled() { 1833 enforceSystemUid(); 1834 return mFirewallEnabled; 1835 } 1836 1837 @Override 1838 public void setFirewallInterfaceRule(String iface, boolean allow) { 1839 enforceSystemUid(); 1840 Preconditions.checkState(mFirewallEnabled); 1841 final String rule = allow ? ALLOW : DENY; 1842 try { 1843 mConnector.execute("firewall", "set_interface_rule", iface, rule); 1844 } catch (NativeDaemonConnectorException e) { 1845 throw e.rethrowAsParcelableException(); 1846 } 1847 } 1848 1849 @Override 1850 public void setFirewallEgressSourceRule(String addr, boolean allow) { 1851 enforceSystemUid(); 1852 Preconditions.checkState(mFirewallEnabled); 1853 final String rule = allow ? ALLOW : DENY; 1854 try { 1855 mConnector.execute("firewall", "set_egress_source_rule", addr, rule); 1856 } catch (NativeDaemonConnectorException e) { 1857 throw e.rethrowAsParcelableException(); 1858 } 1859 } 1860 1861 @Override 1862 public void setFirewallEgressDestRule(String addr, int port, boolean allow) { 1863 enforceSystemUid(); 1864 Preconditions.checkState(mFirewallEnabled); 1865 final String rule = allow ? ALLOW : DENY; 1866 try { 1867 mConnector.execute("firewall", "set_egress_dest_rule", addr, port, rule); 1868 } catch (NativeDaemonConnectorException e) { 1869 throw e.rethrowAsParcelableException(); 1870 } 1871 } 1872 1873 @Override 1874 public void setFirewallUidRule(int uid, boolean allow) { 1875 enforceSystemUid(); 1876 Preconditions.checkState(mFirewallEnabled); 1877 final String rule = allow ? ALLOW : DENY; 1878 try { 1879 mConnector.execute("firewall", "set_uid_rule", uid, rule); 1880 } catch (NativeDaemonConnectorException e) { 1881 throw e.rethrowAsParcelableException(); 1882 } 1883 } 1884 1885 private static void enforceSystemUid() { 1886 final int uid = Binder.getCallingUid(); 1887 if (uid != Process.SYSTEM_UID) { 1888 throw new SecurityException("Only available to AID_SYSTEM"); 1889 } 1890 } 1891 1892 @Override 1893 public void setDnsInterfaceForPid(String iface, int pid) throws IllegalStateException { 1894 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1895 try { 1896 mConnector.execute("resolver", "setifaceforpid", iface, pid); 1897 } catch (NativeDaemonConnectorException e) { 1898 throw new IllegalStateException( 1899 "Error communicating with native deamon to set interface for pid" + iface, e); 1900 } 1901 } 1902 1903 @Override 1904 public void clearDnsInterfaceForPid(int pid) throws IllegalStateException { 1905 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1906 try { 1907 mConnector.execute("resolver", "clearifaceforpid", pid); 1908 } catch (NativeDaemonConnectorException e) { 1909 throw new IllegalStateException( 1910 "Error communicating with native deamon to clear interface for pid " + pid, e); 1911 } 1912 } 1913 1914 @Override 1915 public void startClatd(String interfaceName) throws IllegalStateException { 1916 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1917 1918 try { 1919 mConnector.execute("clatd", "start", interfaceName); 1920 } catch (NativeDaemonConnectorException e) { 1921 throw e.rethrowAsParcelableException(); 1922 } 1923 } 1924 1925 @Override 1926 public void stopClatd() throws IllegalStateException { 1927 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1928 1929 try { 1930 mConnector.execute("clatd", "stop"); 1931 } catch (NativeDaemonConnectorException e) { 1932 throw e.rethrowAsParcelableException(); 1933 } 1934 } 1935 1936 @Override 1937 public boolean isClatdStarted() { 1938 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1939 1940 final NativeDaemonEvent event; 1941 try { 1942 event = mConnector.execute("clatd", "status"); 1943 } catch (NativeDaemonConnectorException e) { 1944 throw e.rethrowAsParcelableException(); 1945 } 1946 1947 event.checkCode(ClatdStatusResult); 1948 return event.getMessage().endsWith("started"); 1949 } 1950 1951 @Override 1952 public void registerNetworkActivityListener(INetworkActivityListener listener) { 1953 mNetworkActivityListeners.register(listener); 1954 } 1955 1956 @Override 1957 public void unregisterNetworkActivityListener(INetworkActivityListener listener) { 1958 mNetworkActivityListeners.unregister(listener); 1959 } 1960 1961 @Override 1962 public boolean isNetworkActive() { 1963 synchronized (mNetworkActivityListeners) { 1964 return mNetworkActive || mActiveIdleTimers.isEmpty(); 1965 } 1966 } 1967 1968 private void reportNetworkActive() { 1969 final int length = mNetworkActivityListeners.beginBroadcast(); 1970 try { 1971 for (int i = 0; i < length; i++) { 1972 try { 1973 mNetworkActivityListeners.getBroadcastItem(i).onNetworkActive(); 1974 } catch (RemoteException e) { 1975 } catch (RuntimeException e) { 1976 } 1977 } 1978 } finally { 1979 mNetworkActivityListeners.finishBroadcast(); 1980 } 1981 } 1982 1983 /** {@inheritDoc} */ 1984 @Override 1985 public void monitor() { 1986 if (mConnector != null) { 1987 mConnector.monitor(); 1988 } 1989 } 1990 1991 @Override 1992 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1993 mContext.enforceCallingOrSelfPermission(DUMP, TAG); 1994 1995 pw.println("NetworkManagementService NativeDaemonConnector Log:"); 1996 mConnector.dump(fd, pw, args); 1997 pw.println(); 1998 1999 pw.print("Bandwidth control enabled: "); pw.println(mBandwidthControlEnabled); 2000 pw.print("mMobileActivityFromRadio="); pw.print(mMobileActivityFromRadio); 2001 pw.print(" mLastPowerStateFromRadio="); pw.println(mLastPowerStateFromRadio); 2002 pw.print("mNetworkActive="); pw.println(mNetworkActive); 2003 2004 synchronized (mQuotaLock) { 2005 pw.print("Active quota ifaces: "); pw.println(mActiveQuotas.toString()); 2006 pw.print("Active alert ifaces: "); pw.println(mActiveAlerts.toString()); 2007 } 2008 2009 synchronized (mUidRejectOnQuota) { 2010 pw.print("UID reject on quota ifaces: ["); 2011 final int size = mUidRejectOnQuota.size(); 2012 for (int i = 0; i < size; i++) { 2013 pw.print(mUidRejectOnQuota.keyAt(i)); 2014 if (i < size - 1) pw.print(","); 2015 } 2016 pw.println("]"); 2017 } 2018 2019 synchronized (mIdleTimerLock) { 2020 pw.println("Idle timers:"); 2021 for (HashMap.Entry<String, IdleTimerParams> ent : mActiveIdleTimers.entrySet()) { 2022 pw.print(" "); pw.print(ent.getKey()); pw.println(":"); 2023 IdleTimerParams params = ent.getValue(); 2024 pw.print(" timeout="); pw.print(params.timeout); 2025 pw.print(" type="); pw.print(params.type); 2026 pw.print(" networkCount="); pw.println(params.networkCount); 2027 } 2028 } 2029 2030 pw.print("Firewall enabled: "); pw.println(mFirewallEnabled); 2031 } 2032} 2033