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