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