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