NetworkManagementService.java revision b2829fa165124264c7ec06a6e23b08a1d97b99e5
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(int netId, RouteInfo route) { 872 modifyRoute(netId, ADD, route); 873 } 874 875 @Override 876 public void removeRoute(int netId, RouteInfo route) { 877 modifyRoute(netId, REMOVE, route); 878 } 879 880 private void modifyRoute(int netId, String action, RouteInfo route) { 881 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 882 883 final Command cmd = new Command("network", "route", action, netId); 884 885 // create triplet: interface dest-ip-addr/prefixlength gateway-ip-addr 886 final LinkAddress la = route.getDestination(); 887 cmd.appendArg(route.getInterface()); 888 cmd.appendArg(la.getAddress().getHostAddress() + "/" + la.getNetworkPrefixLength()); 889 cmd.appendArg(route.getGateway().getHostAddress()); 890 891 try { 892 mConnector.execute(cmd); 893 } catch (NativeDaemonConnectorException e) { 894 throw e.rethrowAsParcelableException(); 895 } 896 } 897 898 private ArrayList<String> readRouteList(String filename) { 899 FileInputStream fstream = null; 900 ArrayList<String> list = new ArrayList<String>(); 901 902 try { 903 fstream = new FileInputStream(filename); 904 DataInputStream in = new DataInputStream(fstream); 905 BufferedReader br = new BufferedReader(new InputStreamReader(in)); 906 String s; 907 908 // throw away the title line 909 910 while (((s = br.readLine()) != null) && (s.length() != 0)) { 911 list.add(s); 912 } 913 } catch (IOException ex) { 914 // return current list, possibly empty 915 } finally { 916 if (fstream != null) { 917 try { 918 fstream.close(); 919 } catch (IOException ex) {} 920 } 921 } 922 923 return list; 924 } 925 926 @Override 927 public RouteInfo[] getRoutes(String interfaceName) { 928 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 929 ArrayList<RouteInfo> routes = new ArrayList<RouteInfo>(); 930 931 // v4 routes listed as: 932 // iface dest-addr gateway-addr flags refcnt use metric netmask mtu window IRTT 933 for (String s : readRouteList("/proc/net/route")) { 934 String[] fields = s.split("\t"); 935 936 if (fields.length > 7) { 937 String iface = fields[0]; 938 939 if (interfaceName.equals(iface)) { 940 String dest = fields[1]; 941 String gate = fields[2]; 942 String flags = fields[3]; // future use? 943 String mask = fields[7]; 944 try { 945 // address stored as a hex string, ex: 0014A8C0 946 InetAddress destAddr = 947 NetworkUtils.intToInetAddress((int)Long.parseLong(dest, 16)); 948 int prefixLength = 949 NetworkUtils.netmaskIntToPrefixLength( 950 (int)Long.parseLong(mask, 16)); 951 LinkAddress linkAddress = new LinkAddress(destAddr, prefixLength); 952 953 // address stored as a hex string, ex 0014A8C0 954 InetAddress gatewayAddr = 955 NetworkUtils.intToInetAddress((int)Long.parseLong(gate, 16)); 956 957 RouteInfo route = new RouteInfo(linkAddress, gatewayAddr); 958 routes.add(route); 959 } catch (Exception e) { 960 Log.e(TAG, "Error parsing route " + s + " : " + e); 961 continue; 962 } 963 } 964 } 965 } 966 967 // v6 routes listed as: 968 // dest-addr prefixlength ?? ?? gateway-addr ?? ?? ?? ?? iface 969 for (String s : readRouteList("/proc/net/ipv6_route")) { 970 String[]fields = s.split("\\s+"); 971 if (fields.length > 9) { 972 String iface = fields[9].trim(); 973 if (interfaceName.equals(iface)) { 974 String dest = fields[0]; 975 String prefix = fields[1]; 976 String gate = fields[4]; 977 978 try { 979 // prefix length stored as a hex string, ex 40 980 int prefixLength = Integer.parseInt(prefix, 16); 981 982 // address stored as a 32 char hex string 983 // ex fe800000000000000000000000000000 984 InetAddress destAddr = NetworkUtils.hexToInet6Address(dest); 985 LinkAddress linkAddress = new LinkAddress(destAddr, prefixLength); 986 987 InetAddress gateAddr = NetworkUtils.hexToInet6Address(gate); 988 989 RouteInfo route = new RouteInfo(linkAddress, gateAddr); 990 routes.add(route); 991 } catch (Exception e) { 992 Log.e(TAG, "Error parsing route " + s + " : " + e); 993 continue; 994 } 995 } 996 } 997 } 998 return routes.toArray(new RouteInfo[routes.size()]); 999 } 1000 1001 @Override 1002 public void setMtu(String iface, int mtu) { 1003 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1004 1005 final NativeDaemonEvent event; 1006 try { 1007 event = mConnector.execute("interface", "setmtu", iface, mtu); 1008 } catch (NativeDaemonConnectorException e) { 1009 throw e.rethrowAsParcelableException(); 1010 } 1011 } 1012 1013 @Override 1014 public void shutdown() { 1015 // TODO: remove from aidl if nobody calls externally 1016 mContext.enforceCallingOrSelfPermission(SHUTDOWN, TAG); 1017 1018 Slog.d(TAG, "Shutting down"); 1019 } 1020 1021 @Override 1022 public boolean getIpForwardingEnabled() throws IllegalStateException{ 1023 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1024 1025 final NativeDaemonEvent event; 1026 try { 1027 event = mConnector.execute("ipfwd", "status"); 1028 } catch (NativeDaemonConnectorException e) { 1029 throw e.rethrowAsParcelableException(); 1030 } 1031 1032 // 211 Forwarding enabled 1033 event.checkCode(IpFwdStatusResult); 1034 return event.getMessage().endsWith("enabled"); 1035 } 1036 1037 @Override 1038 public void setIpForwardingEnabled(boolean enable) { 1039 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1040 try { 1041 mConnector.execute("ipfwd", enable ? "enable" : "disable"); 1042 } catch (NativeDaemonConnectorException e) { 1043 throw e.rethrowAsParcelableException(); 1044 } 1045 } 1046 1047 @Override 1048 public void startTethering(String[] dhcpRange) { 1049 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1050 // cmd is "tether start first_start first_stop second_start second_stop ..." 1051 // an odd number of addrs will fail 1052 1053 final Command cmd = new Command("tether", "start"); 1054 for (String d : dhcpRange) { 1055 cmd.appendArg(d); 1056 } 1057 1058 try { 1059 mConnector.execute(cmd); 1060 } catch (NativeDaemonConnectorException e) { 1061 throw e.rethrowAsParcelableException(); 1062 } 1063 } 1064 1065 @Override 1066 public void stopTethering() { 1067 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1068 try { 1069 mConnector.execute("tether", "stop"); 1070 } catch (NativeDaemonConnectorException e) { 1071 throw e.rethrowAsParcelableException(); 1072 } 1073 } 1074 1075 @Override 1076 public boolean isTetheringStarted() { 1077 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1078 1079 final NativeDaemonEvent event; 1080 try { 1081 event = mConnector.execute("tether", "status"); 1082 } catch (NativeDaemonConnectorException e) { 1083 throw e.rethrowAsParcelableException(); 1084 } 1085 1086 // 210 Tethering services started 1087 event.checkCode(TetherStatusResult); 1088 return event.getMessage().endsWith("started"); 1089 } 1090 1091 @Override 1092 public void tetherInterface(String iface) { 1093 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1094 try { 1095 mConnector.execute("tether", "interface", "add", iface); 1096 } catch (NativeDaemonConnectorException e) { 1097 throw e.rethrowAsParcelableException(); 1098 } 1099 } 1100 1101 @Override 1102 public void untetherInterface(String iface) { 1103 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1104 try { 1105 mConnector.execute("tether", "interface", "remove", iface); 1106 } catch (NativeDaemonConnectorException e) { 1107 throw e.rethrowAsParcelableException(); 1108 } 1109 } 1110 1111 @Override 1112 public String[] listTetheredInterfaces() { 1113 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1114 try { 1115 return NativeDaemonEvent.filterMessageList( 1116 mConnector.executeForList("tether", "interface", "list"), 1117 TetherInterfaceListResult); 1118 } catch (NativeDaemonConnectorException e) { 1119 throw e.rethrowAsParcelableException(); 1120 } 1121 } 1122 1123 @Override 1124 public void setDnsForwarders(String[] dns) { 1125 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1126 1127 final Command cmd = new Command("tether", "dns", "set"); 1128 for (String s : dns) { 1129 cmd.appendArg(NetworkUtils.numericToInetAddress(s).getHostAddress()); 1130 } 1131 1132 try { 1133 mConnector.execute(cmd); 1134 } catch (NativeDaemonConnectorException e) { 1135 throw e.rethrowAsParcelableException(); 1136 } 1137 } 1138 1139 @Override 1140 public String[] getDnsForwarders() { 1141 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1142 try { 1143 return NativeDaemonEvent.filterMessageList( 1144 mConnector.executeForList("tether", "dns", "list"), TetherDnsFwdTgtListResult); 1145 } catch (NativeDaemonConnectorException e) { 1146 throw e.rethrowAsParcelableException(); 1147 } 1148 } 1149 1150 private List<InterfaceAddress> excludeLinkLocal(List<InterfaceAddress> addresses) { 1151 ArrayList<InterfaceAddress> filtered = new ArrayList<InterfaceAddress>(addresses.size()); 1152 for (InterfaceAddress ia : addresses) { 1153 if (!ia.getAddress().isLinkLocalAddress()) 1154 filtered.add(ia); 1155 } 1156 return filtered; 1157 } 1158 1159 private void modifyNat(String action, String internalInterface, String externalInterface) 1160 throws SocketException { 1161 final Command cmd = new Command("nat", action, internalInterface, externalInterface); 1162 1163 final NetworkInterface internalNetworkInterface = NetworkInterface.getByName( 1164 internalInterface); 1165 if (internalNetworkInterface == null) { 1166 cmd.appendArg("0"); 1167 } else { 1168 // Don't touch link-local routes, as link-local addresses aren't routable, 1169 // kernel creates link-local routes on all interfaces automatically 1170 List<InterfaceAddress> interfaceAddresses = excludeLinkLocal( 1171 internalNetworkInterface.getInterfaceAddresses()); 1172 cmd.appendArg(interfaceAddresses.size()); 1173 for (InterfaceAddress ia : interfaceAddresses) { 1174 InetAddress addr = NetworkUtils.getNetworkPart( 1175 ia.getAddress(), ia.getNetworkPrefixLength()); 1176 cmd.appendArg(addr.getHostAddress() + "/" + ia.getNetworkPrefixLength()); 1177 } 1178 } 1179 1180 try { 1181 mConnector.execute(cmd); 1182 } catch (NativeDaemonConnectorException e) { 1183 throw e.rethrowAsParcelableException(); 1184 } 1185 } 1186 1187 @Override 1188 public void enableNat(String internalInterface, String externalInterface) { 1189 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1190 try { 1191 modifyNat("enable", internalInterface, externalInterface); 1192 } catch (SocketException e) { 1193 throw new IllegalStateException(e); 1194 } 1195 } 1196 1197 @Override 1198 public void disableNat(String internalInterface, String externalInterface) { 1199 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1200 try { 1201 modifyNat("disable", internalInterface, externalInterface); 1202 } catch (SocketException e) { 1203 throw new IllegalStateException(e); 1204 } 1205 } 1206 1207 @Override 1208 public String[] listTtys() { 1209 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1210 try { 1211 return NativeDaemonEvent.filterMessageList( 1212 mConnector.executeForList("list_ttys"), TtyListResult); 1213 } catch (NativeDaemonConnectorException e) { 1214 throw e.rethrowAsParcelableException(); 1215 } 1216 } 1217 1218 @Override 1219 public void attachPppd( 1220 String tty, String localAddr, String remoteAddr, String dns1Addr, String dns2Addr) { 1221 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1222 try { 1223 mConnector.execute("pppd", "attach", tty, 1224 NetworkUtils.numericToInetAddress(localAddr).getHostAddress(), 1225 NetworkUtils.numericToInetAddress(remoteAddr).getHostAddress(), 1226 NetworkUtils.numericToInetAddress(dns1Addr).getHostAddress(), 1227 NetworkUtils.numericToInetAddress(dns2Addr).getHostAddress()); 1228 } catch (NativeDaemonConnectorException e) { 1229 throw e.rethrowAsParcelableException(); 1230 } 1231 } 1232 1233 @Override 1234 public void detachPppd(String tty) { 1235 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1236 try { 1237 mConnector.execute("pppd", "detach", tty); 1238 } catch (NativeDaemonConnectorException e) { 1239 throw e.rethrowAsParcelableException(); 1240 } 1241 } 1242 1243 @Override 1244 public void startAccessPoint( 1245 WifiConfiguration wifiConfig, String wlanIface) { 1246 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1247 try { 1248 wifiFirmwareReload(wlanIface, "AP"); 1249 if (wifiConfig == null) { 1250 mConnector.execute("softap", "set", wlanIface); 1251 } else { 1252 mConnector.execute("softap", "set", wlanIface, wifiConfig.SSID, 1253 "broadcast", "6", getSecurityType(wifiConfig), 1254 new SensitiveArg(wifiConfig.preSharedKey)); 1255 } 1256 mConnector.execute("softap", "startap"); 1257 } catch (NativeDaemonConnectorException e) { 1258 throw e.rethrowAsParcelableException(); 1259 } 1260 } 1261 1262 private static String getSecurityType(WifiConfiguration wifiConfig) { 1263 switch (wifiConfig.getAuthType()) { 1264 case KeyMgmt.WPA_PSK: 1265 return "wpa-psk"; 1266 case KeyMgmt.WPA2_PSK: 1267 return "wpa2-psk"; 1268 default: 1269 return "open"; 1270 } 1271 } 1272 1273 /* @param mode can be "AP", "STA" or "P2P" */ 1274 @Override 1275 public void wifiFirmwareReload(String wlanIface, String mode) { 1276 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1277 try { 1278 mConnector.execute("softap", "fwreload", wlanIface, mode); 1279 } catch (NativeDaemonConnectorException e) { 1280 throw e.rethrowAsParcelableException(); 1281 } 1282 } 1283 1284 @Override 1285 public void stopAccessPoint(String wlanIface) { 1286 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1287 try { 1288 mConnector.execute("softap", "stopap"); 1289 wifiFirmwareReload(wlanIface, "STA"); 1290 } catch (NativeDaemonConnectorException e) { 1291 throw e.rethrowAsParcelableException(); 1292 } 1293 } 1294 1295 @Override 1296 public void setAccessPoint(WifiConfiguration wifiConfig, String wlanIface) { 1297 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1298 try { 1299 if (wifiConfig == null) { 1300 mConnector.execute("softap", "set", wlanIface); 1301 } else { 1302 mConnector.execute("softap", "set", wlanIface, wifiConfig.SSID, 1303 "broadcast", "6", getSecurityType(wifiConfig), 1304 new SensitiveArg(wifiConfig.preSharedKey)); 1305 } 1306 } catch (NativeDaemonConnectorException e) { 1307 throw e.rethrowAsParcelableException(); 1308 } 1309 } 1310 1311 @Override 1312 public void addIdleTimer(String iface, int timeout, final int type) { 1313 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1314 1315 if (DBG) Slog.d(TAG, "Adding idletimer"); 1316 1317 synchronized (mIdleTimerLock) { 1318 IdleTimerParams params = mActiveIdleTimers.get(iface); 1319 if (params != null) { 1320 // the interface already has idletimer, update network count 1321 params.networkCount++; 1322 return; 1323 } 1324 1325 try { 1326 mConnector.execute("idletimer", "add", iface, Integer.toString(timeout), 1327 Integer.toString(type)); 1328 } catch (NativeDaemonConnectorException e) { 1329 throw e.rethrowAsParcelableException(); 1330 } 1331 mActiveIdleTimers.put(iface, new IdleTimerParams(timeout, type)); 1332 1333 // Networks start up. 1334 if (ConnectivityManager.isNetworkTypeMobile(type)) { 1335 mNetworkActive = false; 1336 } 1337 mDaemonHandler.post(new Runnable() { 1338 @Override public void run() { 1339 notifyInterfaceClassActivity(type, 1340 DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH, 1341 SystemClock.elapsedRealtimeNanos(), false); 1342 } 1343 }); 1344 } 1345 } 1346 1347 @Override 1348 public void removeIdleTimer(String iface) { 1349 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1350 1351 if (DBG) Slog.d(TAG, "Removing idletimer"); 1352 1353 synchronized (mIdleTimerLock) { 1354 final IdleTimerParams params = mActiveIdleTimers.get(iface); 1355 if (params == null || --(params.networkCount) > 0) { 1356 return; 1357 } 1358 1359 try { 1360 mConnector.execute("idletimer", "remove", iface, 1361 Integer.toString(params.timeout), Integer.toString(params.type)); 1362 } catch (NativeDaemonConnectorException e) { 1363 throw e.rethrowAsParcelableException(); 1364 } 1365 mActiveIdleTimers.remove(iface); 1366 mDaemonHandler.post(new Runnable() { 1367 @Override public void run() { 1368 notifyInterfaceClassActivity(params.type, 1369 DataConnectionRealTimeInfo.DC_POWER_STATE_LOW, 1370 SystemClock.elapsedRealtimeNanos(), false); 1371 } 1372 }); 1373 } 1374 } 1375 1376 @Override 1377 public NetworkStats getNetworkStatsSummaryDev() { 1378 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1379 try { 1380 return mStatsFactory.readNetworkStatsSummaryDev(); 1381 } catch (IOException e) { 1382 throw new IllegalStateException(e); 1383 } 1384 } 1385 1386 @Override 1387 public NetworkStats getNetworkStatsSummaryXt() { 1388 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1389 try { 1390 return mStatsFactory.readNetworkStatsSummaryXt(); 1391 } catch (IOException e) { 1392 throw new IllegalStateException(e); 1393 } 1394 } 1395 1396 @Override 1397 public NetworkStats getNetworkStatsDetail() { 1398 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1399 try { 1400 return mStatsFactory.readNetworkStatsDetail(UID_ALL, null, TAG_ALL, null); 1401 } catch (IOException e) { 1402 throw new IllegalStateException(e); 1403 } 1404 } 1405 1406 @Override 1407 public void setInterfaceQuota(String iface, long quotaBytes) { 1408 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1409 1410 // silently discard when control disabled 1411 // TODO: eventually migrate to be always enabled 1412 if (!mBandwidthControlEnabled) return; 1413 1414 synchronized (mQuotaLock) { 1415 if (mActiveQuotas.containsKey(iface)) { 1416 throw new IllegalStateException("iface " + iface + " already has quota"); 1417 } 1418 1419 try { 1420 // TODO: support quota shared across interfaces 1421 mConnector.execute("bandwidth", "setiquota", iface, quotaBytes); 1422 mActiveQuotas.put(iface, quotaBytes); 1423 } catch (NativeDaemonConnectorException e) { 1424 throw e.rethrowAsParcelableException(); 1425 } 1426 } 1427 } 1428 1429 @Override 1430 public void removeInterfaceQuota(String iface) { 1431 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1432 1433 // silently discard when control disabled 1434 // TODO: eventually migrate to be always enabled 1435 if (!mBandwidthControlEnabled) return; 1436 1437 synchronized (mQuotaLock) { 1438 if (!mActiveQuotas.containsKey(iface)) { 1439 // TODO: eventually consider throwing 1440 return; 1441 } 1442 1443 mActiveQuotas.remove(iface); 1444 mActiveAlerts.remove(iface); 1445 1446 try { 1447 // TODO: support quota shared across interfaces 1448 mConnector.execute("bandwidth", "removeiquota", iface); 1449 } catch (NativeDaemonConnectorException e) { 1450 throw e.rethrowAsParcelableException(); 1451 } 1452 } 1453 } 1454 1455 @Override 1456 public void setInterfaceAlert(String iface, long alertBytes) { 1457 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1458 1459 // silently discard when control disabled 1460 // TODO: eventually migrate to be always enabled 1461 if (!mBandwidthControlEnabled) return; 1462 1463 // quick sanity check 1464 if (!mActiveQuotas.containsKey(iface)) { 1465 throw new IllegalStateException("setting alert requires existing quota on iface"); 1466 } 1467 1468 synchronized (mQuotaLock) { 1469 if (mActiveAlerts.containsKey(iface)) { 1470 throw new IllegalStateException("iface " + iface + " already has alert"); 1471 } 1472 1473 try { 1474 // TODO: support alert shared across interfaces 1475 mConnector.execute("bandwidth", "setinterfacealert", iface, alertBytes); 1476 mActiveAlerts.put(iface, alertBytes); 1477 } catch (NativeDaemonConnectorException e) { 1478 throw e.rethrowAsParcelableException(); 1479 } 1480 } 1481 } 1482 1483 @Override 1484 public void removeInterfaceAlert(String iface) { 1485 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1486 1487 // silently discard when control disabled 1488 // TODO: eventually migrate to be always enabled 1489 if (!mBandwidthControlEnabled) return; 1490 1491 synchronized (mQuotaLock) { 1492 if (!mActiveAlerts.containsKey(iface)) { 1493 // TODO: eventually consider throwing 1494 return; 1495 } 1496 1497 try { 1498 // TODO: support alert shared across interfaces 1499 mConnector.execute("bandwidth", "removeinterfacealert", iface); 1500 mActiveAlerts.remove(iface); 1501 } catch (NativeDaemonConnectorException e) { 1502 throw e.rethrowAsParcelableException(); 1503 } 1504 } 1505 } 1506 1507 @Override 1508 public void setGlobalAlert(long alertBytes) { 1509 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1510 1511 // silently discard when control disabled 1512 // TODO: eventually migrate to be always enabled 1513 if (!mBandwidthControlEnabled) return; 1514 1515 try { 1516 mConnector.execute("bandwidth", "setglobalalert", alertBytes); 1517 } catch (NativeDaemonConnectorException e) { 1518 throw e.rethrowAsParcelableException(); 1519 } 1520 } 1521 1522 @Override 1523 public void setUidNetworkRules(int uid, boolean rejectOnQuotaInterfaces) { 1524 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1525 1526 // silently discard when control disabled 1527 // TODO: eventually migrate to be always enabled 1528 if (!mBandwidthControlEnabled) return; 1529 1530 synchronized (mQuotaLock) { 1531 final boolean oldRejectOnQuota = mUidRejectOnQuota.get(uid, false); 1532 if (oldRejectOnQuota == rejectOnQuotaInterfaces) { 1533 // TODO: eventually consider throwing 1534 return; 1535 } 1536 1537 try { 1538 mConnector.execute("bandwidth", 1539 rejectOnQuotaInterfaces ? "addnaughtyapps" : "removenaughtyapps", uid); 1540 if (rejectOnQuotaInterfaces) { 1541 mUidRejectOnQuota.put(uid, true); 1542 } else { 1543 mUidRejectOnQuota.delete(uid); 1544 } 1545 } catch (NativeDaemonConnectorException e) { 1546 throw e.rethrowAsParcelableException(); 1547 } 1548 } 1549 } 1550 1551 @Override 1552 public boolean isBandwidthControlEnabled() { 1553 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1554 return mBandwidthControlEnabled; 1555 } 1556 1557 @Override 1558 public NetworkStats getNetworkStatsUidDetail(int uid) { 1559 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1560 try { 1561 return mStatsFactory.readNetworkStatsDetail(uid, null, TAG_ALL, null); 1562 } catch (IOException e) { 1563 throw new IllegalStateException(e); 1564 } 1565 } 1566 1567 @Override 1568 public NetworkStats getNetworkStatsTethering() { 1569 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1570 1571 final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 1); 1572 try { 1573 final NativeDaemonEvent[] events = mConnector.executeForList( 1574 "bandwidth", "gettetherstats"); 1575 for (NativeDaemonEvent event : events) { 1576 if (event.getCode() != TetheringStatsListResult) continue; 1577 1578 // 114 ifaceIn ifaceOut rx_bytes rx_packets tx_bytes tx_packets 1579 final StringTokenizer tok = new StringTokenizer(event.getMessage()); 1580 try { 1581 final String ifaceIn = tok.nextToken(); 1582 final String ifaceOut = tok.nextToken(); 1583 1584 final NetworkStats.Entry entry = new NetworkStats.Entry(); 1585 entry.iface = ifaceOut; 1586 entry.uid = UID_TETHERING; 1587 entry.set = SET_DEFAULT; 1588 entry.tag = TAG_NONE; 1589 entry.rxBytes = Long.parseLong(tok.nextToken()); 1590 entry.rxPackets = Long.parseLong(tok.nextToken()); 1591 entry.txBytes = Long.parseLong(tok.nextToken()); 1592 entry.txPackets = Long.parseLong(tok.nextToken()); 1593 stats.combineValues(entry); 1594 } catch (NoSuchElementException e) { 1595 throw new IllegalStateException("problem parsing tethering stats: " + event); 1596 } catch (NumberFormatException e) { 1597 throw new IllegalStateException("problem parsing tethering stats: " + event); 1598 } 1599 } 1600 } catch (NativeDaemonConnectorException e) { 1601 throw e.rethrowAsParcelableException(); 1602 } 1603 return stats; 1604 } 1605 1606 @Override 1607 public void setDnsServersForNetwork(int netId, String[] servers, String domains) { 1608 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1609 1610 final Command cmd = new Command("resolver", "setnetdns", netId, 1611 (domains == null ? "" : domains)); 1612 1613 for (String s : servers) { 1614 InetAddress a = NetworkUtils.numericToInetAddress(s); 1615 if (a.isAnyLocalAddress() == false) { 1616 cmd.appendArg(a.getHostAddress()); 1617 } 1618 } 1619 1620 try { 1621 mConnector.execute(cmd); 1622 } catch (NativeDaemonConnectorException e) { 1623 throw e.rethrowAsParcelableException(); 1624 } 1625 } 1626 1627 @Override 1628 public void setUidRangeRoute(String iface, int uid_start, int uid_end, boolean forward_dns) { 1629 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1630 try { 1631 mConnector.execute("interface", "fwmark", 1632 "uid", "add", iface, uid_start, uid_end, forward_dns ? 1 : 0); 1633 } catch (NativeDaemonConnectorException e) { 1634 throw e.rethrowAsParcelableException(); 1635 } 1636 } 1637 1638 @Override 1639 public void clearUidRangeRoute(String iface, int uid_start, int uid_end) { 1640 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1641 try { 1642 mConnector.execute("interface", "fwmark", 1643 "uid", "remove", iface, uid_start, uid_end, 0); 1644 } catch (NativeDaemonConnectorException e) { 1645 throw e.rethrowAsParcelableException(); 1646 } 1647 } 1648 1649 @Override 1650 public void setMarkedForwarding(String iface) { 1651 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1652 try { 1653 mConnector.execute("interface", "fwmark", "rule", "add", iface); 1654 } catch (NativeDaemonConnectorException e) { 1655 throw e.rethrowAsParcelableException(); 1656 } 1657 } 1658 1659 @Override 1660 public void clearMarkedForwarding(String iface) { 1661 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1662 try { 1663 mConnector.execute("interface", "fwmark", "rule", "remove", iface); 1664 } catch (NativeDaemonConnectorException e) { 1665 throw e.rethrowAsParcelableException(); 1666 } 1667 } 1668 1669 @Override 1670 public int getMarkForUid(int uid) { 1671 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1672 final NativeDaemonEvent event; 1673 try { 1674 event = mConnector.execute("interface", "fwmark", "get", "mark", uid); 1675 } catch (NativeDaemonConnectorException e) { 1676 throw e.rethrowAsParcelableException(); 1677 } 1678 event.checkCode(GetMarkResult); 1679 return Integer.parseInt(event.getMessage()); 1680 } 1681 1682 @Override 1683 public int getMarkForProtect() { 1684 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1685 final NativeDaemonEvent event; 1686 try { 1687 event = mConnector.execute("interface", "fwmark", "get", "protect"); 1688 } catch (NativeDaemonConnectorException e) { 1689 throw e.rethrowAsParcelableException(); 1690 } 1691 event.checkCode(GetMarkResult); 1692 return Integer.parseInt(event.getMessage()); 1693 } 1694 1695 @Override 1696 public void setMarkedForwardingRoute(String iface, RouteInfo route) { 1697 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1698 try { 1699 LinkAddress dest = route.getDestination(); 1700 mConnector.execute("interface", "fwmark", "route", "add", iface, 1701 dest.getAddress().getHostAddress(), dest.getNetworkPrefixLength()); 1702 } catch (NativeDaemonConnectorException e) { 1703 throw e.rethrowAsParcelableException(); 1704 } 1705 } 1706 1707 @Override 1708 public void clearMarkedForwardingRoute(String iface, RouteInfo route) { 1709 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1710 try { 1711 LinkAddress dest = route.getDestination(); 1712 mConnector.execute("interface", "fwmark", "route", "remove", iface, 1713 dest.getAddress().getHostAddress(), dest.getNetworkPrefixLength()); 1714 } catch (NativeDaemonConnectorException e) { 1715 throw e.rethrowAsParcelableException(); 1716 } 1717 } 1718 1719 @Override 1720 public void setHostExemption(LinkAddress host) { 1721 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1722 try { 1723 mConnector.execute("interface", "fwmark", "exempt", "add", host); 1724 } catch (NativeDaemonConnectorException e) { 1725 throw e.rethrowAsParcelableException(); 1726 } 1727 } 1728 1729 @Override 1730 public void clearHostExemption(LinkAddress host) { 1731 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1732 try { 1733 mConnector.execute("interface", "fwmark", "exempt", "remove", host); 1734 } catch (NativeDaemonConnectorException e) { 1735 throw e.rethrowAsParcelableException(); 1736 } 1737 } 1738 1739 @Override 1740 public void flushNetworkDnsCache(int netId) { 1741 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1742 try { 1743 mConnector.execute("resolver", "flushnet", netId); 1744 } catch (NativeDaemonConnectorException e) { 1745 throw e.rethrowAsParcelableException(); 1746 } 1747 } 1748 1749 @Override 1750 public void setFirewallEnabled(boolean enabled) { 1751 enforceSystemUid(); 1752 try { 1753 mConnector.execute("firewall", enabled ? "enable" : "disable"); 1754 mFirewallEnabled = enabled; 1755 } catch (NativeDaemonConnectorException e) { 1756 throw e.rethrowAsParcelableException(); 1757 } 1758 } 1759 1760 @Override 1761 public boolean isFirewallEnabled() { 1762 enforceSystemUid(); 1763 return mFirewallEnabled; 1764 } 1765 1766 @Override 1767 public void setFirewallInterfaceRule(String iface, boolean allow) { 1768 enforceSystemUid(); 1769 Preconditions.checkState(mFirewallEnabled); 1770 final String rule = allow ? ALLOW : DENY; 1771 try { 1772 mConnector.execute("firewall", "set_interface_rule", iface, rule); 1773 } catch (NativeDaemonConnectorException e) { 1774 throw e.rethrowAsParcelableException(); 1775 } 1776 } 1777 1778 @Override 1779 public void setFirewallEgressSourceRule(String addr, boolean allow) { 1780 enforceSystemUid(); 1781 Preconditions.checkState(mFirewallEnabled); 1782 final String rule = allow ? ALLOW : DENY; 1783 try { 1784 mConnector.execute("firewall", "set_egress_source_rule", addr, rule); 1785 } catch (NativeDaemonConnectorException e) { 1786 throw e.rethrowAsParcelableException(); 1787 } 1788 } 1789 1790 @Override 1791 public void setFirewallEgressDestRule(String addr, int port, boolean allow) { 1792 enforceSystemUid(); 1793 Preconditions.checkState(mFirewallEnabled); 1794 final String rule = allow ? ALLOW : DENY; 1795 try { 1796 mConnector.execute("firewall", "set_egress_dest_rule", addr, port, rule); 1797 } catch (NativeDaemonConnectorException e) { 1798 throw e.rethrowAsParcelableException(); 1799 } 1800 } 1801 1802 @Override 1803 public void setFirewallUidRule(int uid, boolean allow) { 1804 enforceSystemUid(); 1805 Preconditions.checkState(mFirewallEnabled); 1806 final String rule = allow ? ALLOW : DENY; 1807 try { 1808 mConnector.execute("firewall", "set_uid_rule", uid, rule); 1809 } catch (NativeDaemonConnectorException e) { 1810 throw e.rethrowAsParcelableException(); 1811 } 1812 } 1813 1814 private static void enforceSystemUid() { 1815 final int uid = Binder.getCallingUid(); 1816 if (uid != Process.SYSTEM_UID) { 1817 throw new SecurityException("Only available to AID_SYSTEM"); 1818 } 1819 } 1820 1821 @Override 1822 public void startClatd(String interfaceName) throws IllegalStateException { 1823 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1824 1825 try { 1826 mConnector.execute("clatd", "start", interfaceName); 1827 } catch (NativeDaemonConnectorException e) { 1828 throw e.rethrowAsParcelableException(); 1829 } 1830 } 1831 1832 @Override 1833 public void stopClatd() throws IllegalStateException { 1834 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1835 1836 try { 1837 mConnector.execute("clatd", "stop"); 1838 } catch (NativeDaemonConnectorException e) { 1839 throw e.rethrowAsParcelableException(); 1840 } 1841 } 1842 1843 @Override 1844 public boolean isClatdStarted() { 1845 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1846 1847 final NativeDaemonEvent event; 1848 try { 1849 event = mConnector.execute("clatd", "status"); 1850 } catch (NativeDaemonConnectorException e) { 1851 throw e.rethrowAsParcelableException(); 1852 } 1853 1854 event.checkCode(ClatdStatusResult); 1855 return event.getMessage().endsWith("started"); 1856 } 1857 1858 @Override 1859 public void registerNetworkActivityListener(INetworkActivityListener listener) { 1860 mNetworkActivityListeners.register(listener); 1861 } 1862 1863 @Override 1864 public void unregisterNetworkActivityListener(INetworkActivityListener listener) { 1865 mNetworkActivityListeners.unregister(listener); 1866 } 1867 1868 @Override 1869 public boolean isNetworkActive() { 1870 synchronized (mNetworkActivityListeners) { 1871 return mNetworkActive || mActiveIdleTimers.isEmpty(); 1872 } 1873 } 1874 1875 private void reportNetworkActive() { 1876 final int length = mNetworkActivityListeners.beginBroadcast(); 1877 try { 1878 for (int i = 0; i < length; i++) { 1879 try { 1880 mNetworkActivityListeners.getBroadcastItem(i).onNetworkActive(); 1881 } catch (RemoteException e) { 1882 } catch (RuntimeException e) { 1883 } 1884 } 1885 } finally { 1886 mNetworkActivityListeners.finishBroadcast(); 1887 } 1888 } 1889 1890 /** {@inheritDoc} */ 1891 @Override 1892 public void monitor() { 1893 if (mConnector != null) { 1894 mConnector.monitor(); 1895 } 1896 } 1897 1898 @Override 1899 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1900 mContext.enforceCallingOrSelfPermission(DUMP, TAG); 1901 1902 pw.println("NetworkManagementService NativeDaemonConnector Log:"); 1903 mConnector.dump(fd, pw, args); 1904 pw.println(); 1905 1906 pw.print("Bandwidth control enabled: "); pw.println(mBandwidthControlEnabled); 1907 pw.print("mMobileActivityFromRadio="); pw.print(mMobileActivityFromRadio); 1908 pw.print(" mLastPowerStateFromRadio="); pw.println(mLastPowerStateFromRadio); 1909 pw.print("mNetworkActive="); pw.println(mNetworkActive); 1910 1911 synchronized (mQuotaLock) { 1912 pw.print("Active quota ifaces: "); pw.println(mActiveQuotas.toString()); 1913 pw.print("Active alert ifaces: "); pw.println(mActiveAlerts.toString()); 1914 } 1915 1916 synchronized (mUidRejectOnQuota) { 1917 pw.print("UID reject on quota ifaces: ["); 1918 final int size = mUidRejectOnQuota.size(); 1919 for (int i = 0; i < size; i++) { 1920 pw.print(mUidRejectOnQuota.keyAt(i)); 1921 if (i < size - 1) pw.print(","); 1922 } 1923 pw.println("]"); 1924 } 1925 1926 synchronized (mIdleTimerLock) { 1927 pw.println("Idle timers:"); 1928 for (HashMap.Entry<String, IdleTimerParams> ent : mActiveIdleTimers.entrySet()) { 1929 pw.print(" "); pw.print(ent.getKey()); pw.println(":"); 1930 IdleTimerParams params = ent.getValue(); 1931 pw.print(" timeout="); pw.print(params.timeout); 1932 pw.print(" type="); pw.print(params.type); 1933 pw.print(" networkCount="); pw.println(params.networkCount); 1934 } 1935 } 1936 1937 pw.print("Firewall enabled: "); pw.println(mFirewallEnabled); 1938 } 1939 1940 @Override 1941 public void createNetwork(int netId, String iface) { 1942 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1943 1944 try { 1945 mConnector.execute("network", "create", netId, iface); 1946 } catch (NativeDaemonConnectorException e) { 1947 throw e.rethrowAsParcelableException(); 1948 } 1949 } 1950 1951 @Override 1952 public void removeNetwork(int netId) { 1953 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1954 1955 try { 1956 mConnector.execute("network", "destroy", netId); 1957 } catch (NativeDaemonConnectorException e) { 1958 throw e.rethrowAsParcelableException(); 1959 } 1960 } 1961 1962 @Override 1963 public void addLegacyRouteForNetId(int netId, RouteInfo routeInfo, int uid) { 1964 modifyLegacyRouteForNetId(netId, routeInfo, uid, ADD); 1965 } 1966 1967 @Override 1968 public void removeLegacyRouteForNetId(int netId, RouteInfo routeInfo, int uid) { 1969 modifyLegacyRouteForNetId(netId, routeInfo, uid, REMOVE); 1970 } 1971 1972 private void modifyLegacyRouteForNetId(int netId, RouteInfo routeInfo, int uid, String action) { 1973 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1974 1975 final Command cmd = new Command("network", "legacy", uid, "route", action, netId); 1976 1977 // create quadlet: dest-ip-addr prefixlength gateway-ip-addr iface 1978 final LinkAddress la = routeInfo.getDestination(); 1979 cmd.appendArg(la.getAddress().getHostAddress()); 1980 cmd.appendArg(la.getNetworkPrefixLength()); 1981 cmd.appendArg(routeInfo.getGateway().getHostAddress()); 1982 cmd.appendArg(routeInfo.getInterface()); 1983 1984 try { 1985 mConnector.execute(cmd); 1986 } catch (NativeDaemonConnectorException e) { 1987 throw e.rethrowAsParcelableException(); 1988 } 1989 } 1990 1991 @Override 1992 public void setDefaultNetId(int netId) { 1993 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 1994 1995 try { 1996 mConnector.execute("network", "default", "set", netId); 1997 } catch (NativeDaemonConnectorException e) { 1998 throw e.rethrowAsParcelableException(); 1999 } 2000 } 2001 2002 @Override 2003 public void clearDefaultNetId() { 2004 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 2005 2006 try { 2007 mConnector.execute("network", "default", "clear"); 2008 } catch (NativeDaemonConnectorException e) { 2009 throw e.rethrowAsParcelableException(); 2010 } 2011 } 2012 2013 @Override 2014 public void setPermission(boolean internal, boolean changeNetState, int[] uids) { 2015 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 2016 2017 final Command cmd = new Command("network", "permission", "user", "set"); 2018 if (internal) cmd.appendArg(CONNECTIVITY_INTERNAL); 2019 if (changeNetState) cmd.appendArg(CHANGE_NETWORK_STATE); 2020 for (int i=0; i<uids.length; i++) { 2021 cmd.appendArg(uids[i]); 2022 } 2023 2024 try { 2025 mConnector.execute(cmd); 2026 } catch (NativeDaemonConnectorException e) { 2027 throw e.rethrowAsParcelableException(); 2028 } 2029 } 2030 2031 @Override 2032 public void clearPermission(int[] uids) { 2033 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 2034 2035 final Command cmd = new Command("network", "permission", "user", "clear"); 2036 for (int i=0; i<uids.length; i++) { 2037 cmd.appendArg(uids[i]); 2038 } 2039 2040 try { 2041 mConnector.execute(cmd); 2042 } catch (NativeDaemonConnectorException e) { 2043 throw e.rethrowAsParcelableException(); 2044 } 2045 } 2046} 2047