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