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