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