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