ConnectivityService.java revision 5ff886e5319c519a6b644a999680ea651e208981
1/* 2 * Copyright (C) 2008 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.MANAGE_NETWORK_POLICY; 20import static android.net.ConnectivityManager.isNetworkTypeValid; 21import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL; 22import static android.net.NetworkPolicyManager.RULE_REJECT_METERED; 23 24import android.bluetooth.BluetoothTetheringDataTracker; 25import android.content.ContentResolver; 26import android.content.Context; 27import android.content.Intent; 28import android.content.pm.PackageManager; 29import android.database.ContentObserver; 30import android.net.ConnectivityManager; 31import android.net.DummyDataStateTracker; 32import android.net.EthernetDataTracker; 33import android.net.IConnectivityManager; 34import android.net.INetworkPolicyListener; 35import android.net.INetworkPolicyManager; 36import android.net.LinkProperties; 37import android.net.MobileDataStateTracker; 38import android.net.NetworkConfig; 39import android.net.NetworkInfo; 40import android.net.NetworkInfo.DetailedState; 41import android.net.NetworkState; 42import android.net.NetworkStateTracker; 43import android.net.NetworkUtils; 44import android.net.Proxy; 45import android.net.ProxyProperties; 46import android.net.RouteInfo; 47import android.net.vpn.VpnManager; 48import android.net.wifi.WifiStateTracker; 49import android.os.Binder; 50import android.os.FileUtils; 51import android.os.Handler; 52import android.os.HandlerThread; 53import android.os.IBinder; 54import android.os.INetworkManagementService; 55import android.os.Looper; 56import android.os.Message; 57import android.os.ParcelFileDescriptor; 58import android.os.PowerManager; 59import android.os.RemoteException; 60import android.os.ServiceManager; 61import android.os.SystemProperties; 62import android.provider.Settings; 63import android.text.TextUtils; 64import android.util.EventLog; 65import android.util.Slog; 66import android.util.SparseIntArray; 67 68import com.android.internal.net.VpnConfig; 69import com.android.internal.telephony.Phone; 70import com.android.server.connectivity.Tethering; 71import com.android.server.connectivity.Vpn; 72 73import com.google.android.collect.Lists; 74import com.google.android.collect.Sets; 75 76import java.io.FileDescriptor; 77import java.io.IOException; 78import java.io.PrintWriter; 79import java.net.InetAddress; 80import java.net.UnknownHostException; 81import java.util.ArrayList; 82import java.util.Arrays; 83import java.util.Collection; 84import java.util.GregorianCalendar; 85import java.util.HashSet; 86import java.util.List; 87import java.util.concurrent.atomic.AtomicBoolean; 88 89/** 90 * @hide 91 */ 92public class ConnectivityService extends IConnectivityManager.Stub { 93 94 private static final boolean DBG = true; 95 private static final String TAG = "ConnectivityService"; 96 97 private static final boolean LOGD_RULES = false; 98 99 // how long to wait before switching back to a radio's default network 100 private static final int RESTORE_DEFAULT_NETWORK_DELAY = 1 * 60 * 1000; 101 // system property that can override the above value 102 private static final String NETWORK_RESTORE_DELAY_PROP_NAME = 103 "android.telephony.apn-restore"; 104 105 // used in recursive route setting to add gateways for the host for which 106 // a host route was requested. 107 private static final int MAX_HOSTROUTE_CYCLE_COUNT = 10; 108 109 private Tethering mTethering; 110 private boolean mTetheringConfigValid = false; 111 112 private Vpn mVpn; 113 114 /** Lock around {@link #mUidRules} and {@link #mMeteredIfaces}. */ 115 private Object mRulesLock = new Object(); 116 /** Currently active network rules by UID. */ 117 private SparseIntArray mUidRules = new SparseIntArray(); 118 /** Set of ifaces that are costly. */ 119 private HashSet<String> mMeteredIfaces = Sets.newHashSet(); 120 121 /** 122 * Sometimes we want to refer to the individual network state 123 * trackers separately, and sometimes we just want to treat them 124 * abstractly. 125 */ 126 private NetworkStateTracker mNetTrackers[]; 127 128 /** 129 * A per Net list of the PID's that requested access to the net 130 * used both as a refcount and for per-PID DNS selection 131 */ 132 private List mNetRequestersPids[]; 133 134 private WifiWatchdogService mWifiWatchdogService; 135 136 // priority order of the nettrackers 137 // (excluding dynamically set mNetworkPreference) 138 // TODO - move mNetworkTypePreference into this 139 private int[] mPriorityList; 140 141 private Context mContext; 142 private int mNetworkPreference; 143 private int mActiveDefaultNetwork = -1; 144 // 0 is full bad, 100 is full good 145 private int mDefaultInetCondition = 0; 146 private int mDefaultInetConditionPublished = 0; 147 private boolean mInetConditionChangeInFlight = false; 148 private int mDefaultConnectionSequence = 0; 149 150 private int mNumDnsEntries; 151 152 private boolean mTestMode; 153 private static ConnectivityService sServiceInstance; 154 155 private AtomicBoolean mBackgroundDataEnabled = new AtomicBoolean(true); 156 157 private INetworkManagementService mNetd; 158 private INetworkPolicyManager mPolicyManager; 159 160 private static final int ENABLED = 1; 161 private static final int DISABLED = 0; 162 163 // Share the event space with NetworkStateTracker (which can't see this 164 // internal class but sends us events). If you change these, change 165 // NetworkStateTracker.java too. 166 private static final int MIN_NETWORK_STATE_TRACKER_EVENT = 1; 167 private static final int MAX_NETWORK_STATE_TRACKER_EVENT = 100; 168 169 /** 170 * used internally as a delayed event to make us switch back to the 171 * default network 172 */ 173 private static final int EVENT_RESTORE_DEFAULT_NETWORK = 174 MAX_NETWORK_STATE_TRACKER_EVENT + 1; 175 176 /** 177 * used internally to change our mobile data enabled flag 178 */ 179 private static final int EVENT_CHANGE_MOBILE_DATA_ENABLED = 180 MAX_NETWORK_STATE_TRACKER_EVENT + 2; 181 182 /** 183 * used internally to change our network preference setting 184 * arg1 = networkType to prefer 185 */ 186 private static final int EVENT_SET_NETWORK_PREFERENCE = 187 MAX_NETWORK_STATE_TRACKER_EVENT + 3; 188 189 /** 190 * used internally to synchronize inet condition reports 191 * arg1 = networkType 192 * arg2 = condition (0 bad, 100 good) 193 */ 194 private static final int EVENT_INET_CONDITION_CHANGE = 195 MAX_NETWORK_STATE_TRACKER_EVENT + 4; 196 197 /** 198 * used internally to mark the end of inet condition hold periods 199 * arg1 = networkType 200 */ 201 private static final int EVENT_INET_CONDITION_HOLD_END = 202 MAX_NETWORK_STATE_TRACKER_EVENT + 5; 203 204 /** 205 * used internally to set the background data preference 206 * arg1 = TRUE for enabled, FALSE for disabled 207 */ 208 private static final int EVENT_SET_BACKGROUND_DATA = 209 MAX_NETWORK_STATE_TRACKER_EVENT + 6; 210 211 /** 212 * used internally to set enable/disable cellular data 213 * arg1 = ENBALED or DISABLED 214 */ 215 private static final int EVENT_SET_MOBILE_DATA = 216 MAX_NETWORK_STATE_TRACKER_EVENT + 7; 217 218 /** 219 * used internally to clear a wakelock when transitioning 220 * from one net to another 221 */ 222 private static final int EVENT_CLEAR_NET_TRANSITION_WAKELOCK = 223 MAX_NETWORK_STATE_TRACKER_EVENT + 8; 224 225 /** 226 * used internally to reload global proxy settings 227 */ 228 private static final int EVENT_APPLY_GLOBAL_HTTP_PROXY = 229 MAX_NETWORK_STATE_TRACKER_EVENT + 9; 230 231 /** 232 * used internally to set external dependency met/unmet 233 * arg1 = ENABLED (met) or DISABLED (unmet) 234 * arg2 = NetworkType 235 */ 236 private static final int EVENT_SET_DEPENDENCY_MET = 237 MAX_NETWORK_STATE_TRACKER_EVENT + 10; 238 239 private Handler mHandler; 240 241 // list of DeathRecipients used to make sure features are turned off when 242 // a process dies 243 private List mFeatureUsers; 244 245 private boolean mSystemReady; 246 private Intent mInitialBroadcast; 247 248 private PowerManager.WakeLock mNetTransitionWakeLock; 249 private String mNetTransitionWakeLockCausedBy = ""; 250 private int mNetTransitionWakeLockSerialNumber; 251 private int mNetTransitionWakeLockTimeout; 252 253 private InetAddress mDefaultDns; 254 255 // used in DBG mode to track inet condition reports 256 private static final int INET_CONDITION_LOG_MAX_SIZE = 15; 257 private ArrayList mInetLog; 258 259 // track the current default http proxy - tell the world if we get a new one (real change) 260 private ProxyProperties mDefaultProxy = null; 261 // track the global proxy. 262 private ProxyProperties mGlobalProxy = null; 263 private final Object mGlobalProxyLock = new Object(); 264 265 private SettingsObserver mSettingsObserver; 266 267 NetworkConfig[] mNetConfigs; 268 int mNetworksDefined; 269 270 private static class RadioAttributes { 271 public int mSimultaneity; 272 public int mType; 273 public RadioAttributes(String init) { 274 String fragments[] = init.split(","); 275 mType = Integer.parseInt(fragments[0]); 276 mSimultaneity = Integer.parseInt(fragments[1]); 277 } 278 } 279 RadioAttributes[] mRadioAttributes; 280 281 public ConnectivityService( 282 Context context, INetworkManagementService netd, INetworkPolicyManager policyManager) { 283 if (DBG) log("ConnectivityService starting up"); 284 285 HandlerThread handlerThread = new HandlerThread("ConnectivityServiceThread"); 286 handlerThread.start(); 287 mHandler = new MyHandler(handlerThread.getLooper()); 288 289 mBackgroundDataEnabled.set(Settings.Secure.getInt(context.getContentResolver(), 290 Settings.Secure.BACKGROUND_DATA, 1) == 1); 291 292 // setup our unique device name 293 if (TextUtils.isEmpty(SystemProperties.get("net.hostname"))) { 294 String id = Settings.Secure.getString(context.getContentResolver(), 295 Settings.Secure.ANDROID_ID); 296 if (id != null && id.length() > 0) { 297 String name = new String("android_").concat(id); 298 SystemProperties.set("net.hostname", name); 299 } 300 } 301 302 // read our default dns server ip 303 String dns = Settings.Secure.getString(context.getContentResolver(), 304 Settings.Secure.DEFAULT_DNS_SERVER); 305 if (dns == null || dns.length() == 0) { 306 dns = context.getResources().getString( 307 com.android.internal.R.string.config_default_dns_server); 308 } 309 try { 310 mDefaultDns = NetworkUtils.numericToInetAddress(dns); 311 } catch (IllegalArgumentException e) { 312 loge("Error setting defaultDns using " + dns); 313 } 314 315 mContext = checkNotNull(context, "missing Context"); 316 mNetd = checkNotNull(netd, "missing INetworkManagementService"); 317 mPolicyManager = checkNotNull(policyManager, "missing INetworkPolicyManager"); 318 319 try { 320 mPolicyManager.registerListener(mPolicyListener); 321 } catch (RemoteException e) { 322 // ouch, no rules updates means some processes may never get network 323 Slog.e(TAG, "unable to register INetworkPolicyListener", e); 324 } 325 326 final PowerManager powerManager = (PowerManager) context.getSystemService( 327 Context.POWER_SERVICE); 328 mNetTransitionWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG); 329 mNetTransitionWakeLockTimeout = mContext.getResources().getInteger( 330 com.android.internal.R.integer.config_networkTransitionTimeout); 331 332 mNetTrackers = new NetworkStateTracker[ 333 ConnectivityManager.MAX_NETWORK_TYPE+1]; 334 335 mNetworkPreference = getPersistedNetworkPreference(); 336 337 mRadioAttributes = new RadioAttributes[ConnectivityManager.MAX_RADIO_TYPE+1]; 338 mNetConfigs = new NetworkConfig[ConnectivityManager.MAX_NETWORK_TYPE+1]; 339 340 // Load device network attributes from resources 341 String[] raStrings = context.getResources().getStringArray( 342 com.android.internal.R.array.radioAttributes); 343 for (String raString : raStrings) { 344 RadioAttributes r = new RadioAttributes(raString); 345 if (r.mType > ConnectivityManager.MAX_RADIO_TYPE) { 346 loge("Error in radioAttributes - ignoring attempt to define type " + r.mType); 347 continue; 348 } 349 if (mRadioAttributes[r.mType] != null) { 350 loge("Error in radioAttributes - ignoring attempt to redefine type " + 351 r.mType); 352 continue; 353 } 354 mRadioAttributes[r.mType] = r; 355 } 356 357 String[] naStrings = context.getResources().getStringArray( 358 com.android.internal.R.array.networkAttributes); 359 for (String naString : naStrings) { 360 try { 361 NetworkConfig n = new NetworkConfig(naString); 362 if (n.type > ConnectivityManager.MAX_NETWORK_TYPE) { 363 loge("Error in networkAttributes - ignoring attempt to define type " + 364 n.type); 365 continue; 366 } 367 if (mNetConfigs[n.type] != null) { 368 loge("Error in networkAttributes - ignoring attempt to redefine type " + 369 n.type); 370 continue; 371 } 372 if (mRadioAttributes[n.radio] == null) { 373 loge("Error in networkAttributes - ignoring attempt to use undefined " + 374 "radio " + n.radio + " in network type " + n.type); 375 continue; 376 } 377 mNetConfigs[n.type] = n; 378 mNetworksDefined++; 379 } catch(Exception e) { 380 // ignore it - leave the entry null 381 } 382 } 383 384 // high priority first 385 mPriorityList = new int[mNetworksDefined]; 386 { 387 int insertionPoint = mNetworksDefined-1; 388 int currentLowest = 0; 389 int nextLowest = 0; 390 while (insertionPoint > -1) { 391 for (NetworkConfig na : mNetConfigs) { 392 if (na == null) continue; 393 if (na.priority < currentLowest) continue; 394 if (na.priority > currentLowest) { 395 if (na.priority < nextLowest || nextLowest == 0) { 396 nextLowest = na.priority; 397 } 398 continue; 399 } 400 mPriorityList[insertionPoint--] = na.type; 401 } 402 currentLowest = nextLowest; 403 nextLowest = 0; 404 } 405 } 406 407 mNetRequestersPids = new ArrayList[ConnectivityManager.MAX_NETWORK_TYPE+1]; 408 for (int i : mPriorityList) { 409 mNetRequestersPids[i] = new ArrayList(); 410 } 411 412 mFeatureUsers = new ArrayList(); 413 414 mNumDnsEntries = 0; 415 416 mTestMode = SystemProperties.get("cm.test.mode").equals("true") 417 && SystemProperties.get("ro.build.type").equals("eng"); 418 /* 419 * Create the network state trackers for Wi-Fi and mobile 420 * data. Maybe this could be done with a factory class, 421 * but it's not clear that it's worth it, given that 422 * the number of different network types is not going 423 * to change very often. 424 */ 425 for (int netType : mPriorityList) { 426 switch (mNetConfigs[netType].radio) { 427 case ConnectivityManager.TYPE_WIFI: 428 if (DBG) log("Starting Wifi Service."); 429 WifiStateTracker wst = new WifiStateTracker(); 430 WifiService wifiService = new WifiService(context); 431 ServiceManager.addService(Context.WIFI_SERVICE, wifiService); 432 wifiService.checkAndStartWifi(); 433 mNetTrackers[ConnectivityManager.TYPE_WIFI] = wst; 434 wst.startMonitoring(context, mHandler); 435 436 //TODO: as part of WWS refactor, create only when needed 437 mWifiWatchdogService = new WifiWatchdogService(context); 438 439 break; 440 case ConnectivityManager.TYPE_MOBILE: 441 mNetTrackers[netType] = new MobileDataStateTracker(netType, 442 mNetConfigs[netType].name); 443 mNetTrackers[netType].startMonitoring(context, mHandler); 444 break; 445 case ConnectivityManager.TYPE_DUMMY: 446 mNetTrackers[netType] = new DummyDataStateTracker(netType, 447 mNetConfigs[netType].name); 448 mNetTrackers[netType].startMonitoring(context, mHandler); 449 break; 450 case ConnectivityManager.TYPE_BLUETOOTH: 451 mNetTrackers[netType] = BluetoothTetheringDataTracker.getInstance(); 452 mNetTrackers[netType].startMonitoring(context, mHandler); 453 break; 454 case ConnectivityManager.TYPE_ETHERNET: 455 mNetTrackers[netType] = EthernetDataTracker.getInstance(); 456 mNetTrackers[netType].startMonitoring(context, mHandler); 457 break; 458 default: 459 loge("Trying to create a DataStateTracker for an unknown radio type " + 460 mNetConfigs[netType].radio); 461 continue; 462 } 463 } 464 465 IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE); 466 INetworkManagementService nmService = INetworkManagementService.Stub.asInterface(b); 467 468 mTethering = new Tethering(mContext, nmService, mHandler.getLooper()); 469 mTetheringConfigValid = ((mTethering.getTetherableUsbRegexs().length != 0 || 470 mTethering.getTetherableWifiRegexs().length != 0 || 471 mTethering.getTetherableBluetoothRegexs().length != 0) && 472 mTethering.getUpstreamIfaceTypes().length != 0); 473 474 mVpn = new Vpn(mContext, new VpnCallback()); 475 476 try { 477 nmService.registerObserver(mTethering); 478 nmService.registerObserver(mVpn); 479 } catch (RemoteException e) { 480 loge("Error registering observer :" + e); 481 } 482 483 if (DBG) { 484 mInetLog = new ArrayList(); 485 } 486 487 mSettingsObserver = new SettingsObserver(mHandler, EVENT_APPLY_GLOBAL_HTTP_PROXY); 488 mSettingsObserver.observe(mContext); 489 490 loadGlobalProxy(); 491 492 VpnManager.startVpnService(context); 493 } 494 495 496 /** 497 * Sets the preferred network. 498 * @param preference the new preference 499 */ 500 public void setNetworkPreference(int preference) { 501 enforceChangePermission(); 502 503 mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_NETWORK_PREFERENCE, preference, 0)); 504 } 505 506 public int getNetworkPreference() { 507 enforceAccessPermission(); 508 int preference; 509 synchronized(this) { 510 preference = mNetworkPreference; 511 } 512 return preference; 513 } 514 515 private void handleSetNetworkPreference(int preference) { 516 if (ConnectivityManager.isNetworkTypeValid(preference) && 517 mNetConfigs[preference] != null && 518 mNetConfigs[preference].isDefault()) { 519 if (mNetworkPreference != preference) { 520 final ContentResolver cr = mContext.getContentResolver(); 521 Settings.Secure.putInt(cr, Settings.Secure.NETWORK_PREFERENCE, preference); 522 synchronized(this) { 523 mNetworkPreference = preference; 524 } 525 enforcePreference(); 526 } 527 } 528 } 529 530 private int getPersistedNetworkPreference() { 531 final ContentResolver cr = mContext.getContentResolver(); 532 533 final int networkPrefSetting = Settings.Secure 534 .getInt(cr, Settings.Secure.NETWORK_PREFERENCE, -1); 535 if (networkPrefSetting != -1) { 536 return networkPrefSetting; 537 } 538 539 return ConnectivityManager.DEFAULT_NETWORK_PREFERENCE; 540 } 541 542 /** 543 * Make the state of network connectivity conform to the preference settings 544 * In this method, we only tear down a non-preferred network. Establishing 545 * a connection to the preferred network is taken care of when we handle 546 * the disconnect event from the non-preferred network 547 * (see {@link #handleDisconnect(NetworkInfo)}). 548 */ 549 private void enforcePreference() { 550 if (mNetTrackers[mNetworkPreference].getNetworkInfo().isConnected()) 551 return; 552 553 if (!mNetTrackers[mNetworkPreference].isAvailable()) 554 return; 555 556 for (int t=0; t <= ConnectivityManager.MAX_RADIO_TYPE; t++) { 557 if (t != mNetworkPreference && mNetTrackers[t] != null && 558 mNetTrackers[t].getNetworkInfo().isConnected()) { 559 if (DBG) { 560 log("tearing down " + mNetTrackers[t].getNetworkInfo() + 561 " in enforcePreference"); 562 } 563 teardown(mNetTrackers[t]); 564 } 565 } 566 } 567 568 private boolean teardown(NetworkStateTracker netTracker) { 569 if (netTracker.teardown()) { 570 netTracker.setTeardownRequested(true); 571 return true; 572 } else { 573 return false; 574 } 575 } 576 577 /** 578 * Check if UID should be blocked from using the network represented by the 579 * given {@link NetworkStateTracker}. 580 */ 581 private boolean isNetworkBlocked(NetworkStateTracker tracker, int uid) { 582 final String iface = tracker.getLinkProperties().getInterfaceName(); 583 584 final boolean networkCostly; 585 final int uidRules; 586 synchronized (mRulesLock) { 587 networkCostly = mMeteredIfaces.contains(iface); 588 uidRules = mUidRules.get(uid, RULE_ALLOW_ALL); 589 } 590 591 if (networkCostly && (uidRules & RULE_REJECT_METERED) != 0) { 592 return true; 593 } 594 595 // no restrictive rules; network is visible 596 return false; 597 } 598 599 /** 600 * Return a filtered {@link NetworkInfo}, potentially marked 601 * {@link DetailedState#BLOCKED} based on 602 * {@link #isNetworkBlocked(NetworkStateTracker, int)}. 603 */ 604 private NetworkInfo getFilteredNetworkInfo(NetworkStateTracker tracker, int uid) { 605 NetworkInfo info = tracker.getNetworkInfo(); 606 if (isNetworkBlocked(tracker, uid)) { 607 // network is blocked; clone and override state 608 info = new NetworkInfo(info); 609 info.setDetailedState(DetailedState.BLOCKED, null, null); 610 } 611 return info; 612 } 613 614 /** 615 * Return NetworkInfo for the active (i.e., connected) network interface. 616 * It is assumed that at most one network is active at a time. If more 617 * than one is active, it is indeterminate which will be returned. 618 * @return the info for the active network, or {@code null} if none is 619 * active 620 */ 621 @Override 622 public NetworkInfo getActiveNetworkInfo() { 623 enforceAccessPermission(); 624 final int uid = Binder.getCallingUid(); 625 return getNetworkInfo(mActiveDefaultNetwork, uid); 626 } 627 628 @Override 629 public NetworkInfo getActiveNetworkInfoForUid(int uid) { 630 enforceConnectivityInternalPermission(); 631 return getNetworkInfo(mActiveDefaultNetwork, uid); 632 } 633 634 @Override 635 public NetworkInfo getNetworkInfo(int networkType) { 636 enforceAccessPermission(); 637 final int uid = Binder.getCallingUid(); 638 return getNetworkInfo(networkType, uid); 639 } 640 641 private NetworkInfo getNetworkInfo(int networkType, int uid) { 642 NetworkInfo info = null; 643 if (isNetworkTypeValid(networkType)) { 644 final NetworkStateTracker tracker = mNetTrackers[networkType]; 645 if (tracker != null) { 646 info = getFilteredNetworkInfo(tracker, uid); 647 } 648 } 649 return info; 650 } 651 652 @Override 653 public NetworkInfo[] getAllNetworkInfo() { 654 enforceAccessPermission(); 655 final int uid = Binder.getCallingUid(); 656 final ArrayList<NetworkInfo> result = Lists.newArrayList(); 657 synchronized (mRulesLock) { 658 for (NetworkStateTracker tracker : mNetTrackers) { 659 if (tracker != null) { 660 result.add(getFilteredNetworkInfo(tracker, uid)); 661 } 662 } 663 } 664 return result.toArray(new NetworkInfo[result.size()]); 665 } 666 667 /** 668 * Return LinkProperties for the active (i.e., connected) default 669 * network interface. It is assumed that at most one default network 670 * is active at a time. If more than one is active, it is indeterminate 671 * which will be returned. 672 * @return the ip properties for the active network, or {@code null} if 673 * none is active 674 */ 675 @Override 676 public LinkProperties getActiveLinkProperties() { 677 return getLinkProperties(mActiveDefaultNetwork); 678 } 679 680 @Override 681 public LinkProperties getLinkProperties(int networkType) { 682 enforceAccessPermission(); 683 if (isNetworkTypeValid(networkType)) { 684 final NetworkStateTracker tracker = mNetTrackers[networkType]; 685 if (tracker != null) { 686 return tracker.getLinkProperties(); 687 } 688 } 689 return null; 690 } 691 692 @Override 693 public NetworkState[] getAllNetworkState() { 694 enforceAccessPermission(); 695 final int uid = Binder.getCallingUid(); 696 final ArrayList<NetworkState> result = Lists.newArrayList(); 697 synchronized (mRulesLock) { 698 for (NetworkStateTracker tracker : mNetTrackers) { 699 if (tracker != null) { 700 final NetworkInfo info = getFilteredNetworkInfo(tracker, uid); 701 result.add(new NetworkState( 702 info, tracker.getLinkProperties(), tracker.getLinkCapabilities())); 703 } 704 } 705 } 706 return result.toArray(new NetworkState[result.size()]); 707 } 708 709 public boolean setRadios(boolean turnOn) { 710 boolean result = true; 711 enforceChangePermission(); 712 for (NetworkStateTracker t : mNetTrackers) { 713 if (t != null) result = t.setRadio(turnOn) && result; 714 } 715 return result; 716 } 717 718 public boolean setRadio(int netType, boolean turnOn) { 719 enforceChangePermission(); 720 if (!ConnectivityManager.isNetworkTypeValid(netType)) { 721 return false; 722 } 723 NetworkStateTracker tracker = mNetTrackers[netType]; 724 return tracker != null && tracker.setRadio(turnOn); 725 } 726 727 /** 728 * Used to notice when the calling process dies so we can self-expire 729 * 730 * Also used to know if the process has cleaned up after itself when 731 * our auto-expire timer goes off. The timer has a link to an object. 732 * 733 */ 734 private class FeatureUser implements IBinder.DeathRecipient { 735 int mNetworkType; 736 String mFeature; 737 IBinder mBinder; 738 int mPid; 739 int mUid; 740 long mCreateTime; 741 742 FeatureUser(int type, String feature, IBinder binder) { 743 super(); 744 mNetworkType = type; 745 mFeature = feature; 746 mBinder = binder; 747 mPid = getCallingPid(); 748 mUid = getCallingUid(); 749 mCreateTime = System.currentTimeMillis(); 750 751 try { 752 mBinder.linkToDeath(this, 0); 753 } catch (RemoteException e) { 754 binderDied(); 755 } 756 } 757 758 void unlinkDeathRecipient() { 759 mBinder.unlinkToDeath(this, 0); 760 } 761 762 public void binderDied() { 763 log("ConnectivityService FeatureUser binderDied(" + 764 mNetworkType + ", " + mFeature + ", " + mBinder + "), created " + 765 (System.currentTimeMillis() - mCreateTime) + " mSec ago"); 766 stopUsingNetworkFeature(this, false); 767 } 768 769 public void expire() { 770 log("ConnectivityService FeatureUser expire(" + 771 mNetworkType + ", " + mFeature + ", " + mBinder +"), created " + 772 (System.currentTimeMillis() - mCreateTime) + " mSec ago"); 773 stopUsingNetworkFeature(this, false); 774 } 775 776 public String toString() { 777 return "FeatureUser("+mNetworkType+","+mFeature+","+mPid+","+mUid+"), created " + 778 (System.currentTimeMillis() - mCreateTime) + " mSec ago"; 779 } 780 } 781 782 // javadoc from interface 783 public int startUsingNetworkFeature(int networkType, String feature, 784 IBinder binder) { 785 if (DBG) { 786 log("startUsingNetworkFeature for net " + networkType + ": " + feature); 787 } 788 enforceChangePermission(); 789 if (!ConnectivityManager.isNetworkTypeValid(networkType) || 790 mNetConfigs[networkType] == null) { 791 return Phone.APN_REQUEST_FAILED; 792 } 793 794 FeatureUser f = new FeatureUser(networkType, feature, binder); 795 796 // TODO - move this into the MobileDataStateTracker 797 int usedNetworkType = networkType; 798 if(networkType == ConnectivityManager.TYPE_MOBILE) { 799 usedNetworkType = convertFeatureToNetworkType(feature); 800 if (usedNetworkType < 0) { 801 Slog.e(TAG, "Can't match any netTracker!"); 802 usedNetworkType = networkType; 803 } 804 } 805 NetworkStateTracker network = mNetTrackers[usedNetworkType]; 806 if (network != null) { 807 Integer currentPid = new Integer(getCallingPid()); 808 if (usedNetworkType != networkType) { 809 NetworkStateTracker radio = mNetTrackers[networkType]; 810 NetworkInfo ni = network.getNetworkInfo(); 811 812 if (ni.isAvailable() == false) { 813 if (DBG) log("special network not available"); 814 if (!TextUtils.equals(feature,Phone.FEATURE_ENABLE_DUN_ALWAYS)) { 815 return Phone.APN_TYPE_NOT_AVAILABLE; 816 } else { 817 // else make the attempt anyway - probably giving REQUEST_STARTED below 818 } 819 } 820 821 synchronized(this) { 822 mFeatureUsers.add(f); 823 if (!mNetRequestersPids[usedNetworkType].contains(currentPid)) { 824 // this gets used for per-pid dns when connected 825 mNetRequestersPids[usedNetworkType].add(currentPid); 826 } 827 } 828 829 int restoreTimer = getRestoreDefaultNetworkDelay(usedNetworkType); 830 831 if (restoreTimer >= 0) { 832 mHandler.sendMessageDelayed( 833 mHandler.obtainMessage(EVENT_RESTORE_DEFAULT_NETWORK, f), restoreTimer); 834 } 835 836 if ((ni.isConnectedOrConnecting() == true) && 837 !network.isTeardownRequested()) { 838 if (ni.isConnected() == true) { 839 // add the pid-specific dns 840 handleDnsConfigurationChange(networkType); 841 if (DBG) log("special network already active"); 842 return Phone.APN_ALREADY_ACTIVE; 843 } 844 if (DBG) log("special network already connecting"); 845 return Phone.APN_REQUEST_STARTED; 846 } 847 848 // check if the radio in play can make another contact 849 // assume if cannot for now 850 851 if (DBG) log("reconnecting to special network"); 852 network.reconnect(); 853 return Phone.APN_REQUEST_STARTED; 854 } else { 855 // need to remember this unsupported request so we respond appropriately on stop 856 synchronized(this) { 857 mFeatureUsers.add(f); 858 if (!mNetRequestersPids[usedNetworkType].contains(currentPid)) { 859 // this gets used for per-pid dns when connected 860 mNetRequestersPids[usedNetworkType].add(currentPid); 861 } 862 } 863 return -1; 864 } 865 } 866 return Phone.APN_TYPE_NOT_AVAILABLE; 867 } 868 869 // javadoc from interface 870 public int stopUsingNetworkFeature(int networkType, String feature) { 871 enforceChangePermission(); 872 873 int pid = getCallingPid(); 874 int uid = getCallingUid(); 875 876 FeatureUser u = null; 877 boolean found = false; 878 879 synchronized(this) { 880 for (int i = 0; i < mFeatureUsers.size() ; i++) { 881 u = (FeatureUser)mFeatureUsers.get(i); 882 if (uid == u.mUid && pid == u.mPid && 883 networkType == u.mNetworkType && 884 TextUtils.equals(feature, u.mFeature)) { 885 found = true; 886 break; 887 } 888 } 889 } 890 if (found && u != null) { 891 // stop regardless of how many other time this proc had called start 892 return stopUsingNetworkFeature(u, true); 893 } else { 894 // none found! 895 if (DBG) log("ignoring stopUsingNetworkFeature - not a live request"); 896 return 1; 897 } 898 } 899 900 private int stopUsingNetworkFeature(FeatureUser u, boolean ignoreDups) { 901 int networkType = u.mNetworkType; 902 String feature = u.mFeature; 903 int pid = u.mPid; 904 int uid = u.mUid; 905 906 NetworkStateTracker tracker = null; 907 boolean callTeardown = false; // used to carry our decision outside of sync block 908 909 if (DBG) { 910 log("stopUsingNetworkFeature for net " + networkType + 911 ": " + feature); 912 } 913 914 if (!ConnectivityManager.isNetworkTypeValid(networkType)) { 915 return -1; 916 } 917 918 // need to link the mFeatureUsers list with the mNetRequestersPids state in this 919 // sync block 920 synchronized(this) { 921 // check if this process still has an outstanding start request 922 if (!mFeatureUsers.contains(u)) { 923 if (DBG) log("ignoring - this process has no outstanding requests"); 924 return 1; 925 } 926 u.unlinkDeathRecipient(); 927 mFeatureUsers.remove(mFeatureUsers.indexOf(u)); 928 // If we care about duplicate requests, check for that here. 929 // 930 // This is done to support the extension of a request - the app 931 // can request we start the network feature again and renew the 932 // auto-shutoff delay. Normal "stop" calls from the app though 933 // do not pay attention to duplicate requests - in effect the 934 // API does not refcount and a single stop will counter multiple starts. 935 if (ignoreDups == false) { 936 for (int i = 0; i < mFeatureUsers.size() ; i++) { 937 FeatureUser x = (FeatureUser)mFeatureUsers.get(i); 938 if (x.mUid == u.mUid && x.mPid == u.mPid && 939 x.mNetworkType == u.mNetworkType && 940 TextUtils.equals(x.mFeature, u.mFeature)) { 941 if (DBG) log("ignoring stopUsingNetworkFeature as dup is found"); 942 return 1; 943 } 944 } 945 } 946 947 // TODO - move to MobileDataStateTracker 948 int usedNetworkType = networkType; 949 if (networkType == ConnectivityManager.TYPE_MOBILE) { 950 usedNetworkType = convertFeatureToNetworkType(feature); 951 if (usedNetworkType < 0) { 952 usedNetworkType = networkType; 953 } 954 } 955 tracker = mNetTrackers[usedNetworkType]; 956 if (tracker == null) { 957 if (DBG) log("ignoring - no known tracker for net type " + usedNetworkType); 958 return -1; 959 } 960 if (usedNetworkType != networkType) { 961 Integer currentPid = new Integer(pid); 962 mNetRequestersPids[usedNetworkType].remove(currentPid); 963 reassessPidDns(pid, true); 964 if (mNetRequestersPids[usedNetworkType].size() != 0) { 965 if (DBG) log("not tearing down special network - " + 966 "others still using it"); 967 return 1; 968 } 969 callTeardown = true; 970 } else { 971 if (DBG) log("not a known feature - dropping"); 972 } 973 } 974 if (DBG) log("Doing network teardown"); 975 if (callTeardown) { 976 tracker.teardown(); 977 return 1; 978 } else { 979 return -1; 980 } 981 } 982 983 /** 984 * @deprecated use requestRouteToHostAddress instead 985 * 986 * Ensure that a network route exists to deliver traffic to the specified 987 * host via the specified network interface. 988 * @param networkType the type of the network over which traffic to the 989 * specified host is to be routed 990 * @param hostAddress the IP address of the host to which the route is 991 * desired 992 * @return {@code true} on success, {@code false} on failure 993 */ 994 public boolean requestRouteToHost(int networkType, int hostAddress) { 995 InetAddress inetAddress = NetworkUtils.intToInetAddress(hostAddress); 996 997 if (inetAddress == null) { 998 return false; 999 } 1000 1001 return requestRouteToHostAddress(networkType, inetAddress.getAddress()); 1002 } 1003 1004 /** 1005 * Ensure that a network route exists to deliver traffic to the specified 1006 * host via the specified network interface. 1007 * @param networkType the type of the network over which traffic to the 1008 * specified host is to be routed 1009 * @param hostAddress the IP address of the host to which the route is 1010 * desired 1011 * @return {@code true} on success, {@code false} on failure 1012 */ 1013 public boolean requestRouteToHostAddress(int networkType, byte[] hostAddress) { 1014 enforceChangePermission(); 1015 if (!ConnectivityManager.isNetworkTypeValid(networkType)) { 1016 return false; 1017 } 1018 NetworkStateTracker tracker = mNetTrackers[networkType]; 1019 1020 if (tracker == null || !tracker.getNetworkInfo().isConnected() || 1021 tracker.isTeardownRequested()) { 1022 if (DBG) { 1023 log("requestRouteToHostAddress on down network " + 1024 "(" + networkType + ") - dropped"); 1025 } 1026 return false; 1027 } 1028 try { 1029 InetAddress addr = InetAddress.getByAddress(hostAddress); 1030 return addHostRoute(tracker, addr, 0); 1031 } catch (UnknownHostException e) {} 1032 return false; 1033 } 1034 1035 /** 1036 * Ensure that a network route exists to deliver traffic to the specified 1037 * host via the mobile data network. 1038 * @param hostAddress the IP address of the host to which the route is desired, 1039 * in network byte order. 1040 * TODO - deprecate 1041 * @return {@code true} on success, {@code false} on failure 1042 */ 1043 private boolean addHostRoute(NetworkStateTracker nt, InetAddress hostAddress, int cycleCount) { 1044 LinkProperties lp = nt.getLinkProperties(); 1045 if ((lp == null) || (hostAddress == null)) return false; 1046 1047 String interfaceName = lp.getInterfaceName(); 1048 if (DBG) { 1049 log("Requested host route to " + hostAddress + "(" + interfaceName + "), cycleCount=" + 1050 cycleCount); 1051 } 1052 if (interfaceName == null) { 1053 if (DBG) loge("addHostRoute failed due to null interface name"); 1054 return false; 1055 } 1056 1057 RouteInfo bestRoute = RouteInfo.selectBestRoute(lp.getRoutes(), hostAddress); 1058 InetAddress gatewayAddress = null; 1059 if (bestRoute != null) { 1060 gatewayAddress = bestRoute.getGateway(); 1061 // if the best route is ourself, don't relf-reference, just add the host route 1062 if (hostAddress.equals(gatewayAddress)) gatewayAddress = null; 1063 } 1064 if (gatewayAddress != null) { 1065 if (cycleCount > MAX_HOSTROUTE_CYCLE_COUNT) { 1066 loge("Error adding hostroute - too much recursion"); 1067 return false; 1068 } 1069 if (!addHostRoute(nt, gatewayAddress, cycleCount+1)) return false; 1070 } 1071 1072 RouteInfo route = RouteInfo.makeHostRoute(hostAddress, gatewayAddress); 1073 1074 try { 1075 mNetd.addRoute(interfaceName, route); 1076 return true; 1077 } catch (Exception ex) { 1078 return false; 1079 } 1080 } 1081 1082 // TODO support the removal of single host routes. Keep a ref count of them so we 1083 // aren't over-zealous 1084 private boolean removeHostRoute(NetworkStateTracker nt, InetAddress hostAddress) { 1085 return false; 1086 } 1087 1088 /** 1089 * @see ConnectivityManager#getBackgroundDataSetting() 1090 */ 1091 public boolean getBackgroundDataSetting() { 1092 return mBackgroundDataEnabled.get(); 1093 } 1094 1095 /** 1096 * @see ConnectivityManager#setBackgroundDataSetting(boolean) 1097 */ 1098 public void setBackgroundDataSetting(boolean allowBackgroundDataUsage) { 1099 mContext.enforceCallingOrSelfPermission( 1100 android.Manifest.permission.CHANGE_BACKGROUND_DATA_SETTING, 1101 "ConnectivityService"); 1102 1103 mBackgroundDataEnabled.set(allowBackgroundDataUsage); 1104 1105 mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_BACKGROUND_DATA, 1106 (allowBackgroundDataUsage ? ENABLED : DISABLED), 0)); 1107 } 1108 1109 private void handleSetBackgroundData(boolean enabled) { 1110 Settings.Secure.putInt(mContext.getContentResolver(), 1111 Settings.Secure.BACKGROUND_DATA, enabled ? 1 : 0); 1112 Intent broadcast = new Intent( 1113 ConnectivityManager.ACTION_BACKGROUND_DATA_SETTING_CHANGED); 1114 mContext.sendBroadcast(broadcast); 1115 } 1116 1117 /** 1118 * @see ConnectivityManager#getMobileDataEnabled() 1119 */ 1120 public boolean getMobileDataEnabled() { 1121 // TODO: This detail should probably be in DataConnectionTracker's 1122 // which is where we store the value and maybe make this 1123 // asynchronous. 1124 enforceAccessPermission(); 1125 boolean retVal = Settings.Secure.getInt(mContext.getContentResolver(), 1126 Settings.Secure.MOBILE_DATA, 1) == 1; 1127 if (DBG) log("getMobileDataEnabled returning " + retVal); 1128 return retVal; 1129 } 1130 1131 public void setDataDependency(int networkType, boolean met) { 1132 enforceChangePermission(); 1133 if (DBG) { 1134 log("setDataDependency(" + networkType + ", " + met + ")"); 1135 } 1136 mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_DEPENDENCY_MET, 1137 (met ? ENABLED : DISABLED), networkType)); 1138 } 1139 1140 private void handleSetDependencyMet(int networkType, boolean met) { 1141 if (mNetTrackers[networkType] != null) { 1142 if (DBG) { 1143 log("handleSetDependencyMet(" + networkType + ", " + met + ")"); 1144 } 1145 mNetTrackers[networkType].setDependencyMet(met); 1146 } 1147 } 1148 1149 private INetworkPolicyListener mPolicyListener = new INetworkPolicyListener.Stub() { 1150 @Override 1151 public void onUidRulesChanged(int uid, int uidRules) { 1152 // only someone like NPMS should only be calling us 1153 mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 1154 1155 if (LOGD_RULES) { 1156 Slog.d(TAG, "onUidRulesChanged(uid=" + uid + ", uidRules=" + uidRules + ")"); 1157 } 1158 1159 synchronized (mRulesLock) { 1160 // skip update when we've already applied rules 1161 final int oldRules = mUidRules.get(uid, RULE_ALLOW_ALL); 1162 if (oldRules == uidRules) return; 1163 1164 mUidRules.put(uid, uidRules); 1165 } 1166 1167 // TODO: dispatch into NMS to push rules towards kernel module 1168 // TODO: notify UID when it has requested targeted updates 1169 } 1170 1171 @Override 1172 public void onMeteredIfacesChanged(String[] meteredIfaces) { 1173 // only someone like NPMS should only be calling us 1174 mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 1175 1176 if (LOGD_RULES) { 1177 Slog.d(TAG, 1178 "onMeteredIfacesChanged(ifaces=" + Arrays.toString(meteredIfaces) + ")"); 1179 } 1180 1181 synchronized (mRulesLock) { 1182 mMeteredIfaces.clear(); 1183 for (String iface : meteredIfaces) { 1184 mMeteredIfaces.add(iface); 1185 } 1186 } 1187 } 1188 }; 1189 1190 /** 1191 * @see ConnectivityManager#setMobileDataEnabled(boolean) 1192 */ 1193 public void setMobileDataEnabled(boolean enabled) { 1194 enforceChangePermission(); 1195 if (DBG) log("setMobileDataEnabled(" + enabled + ")"); 1196 1197 mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_MOBILE_DATA, 1198 (enabled ? ENABLED : DISABLED), 0)); 1199 } 1200 1201 private void handleSetMobileData(boolean enabled) { 1202 if (mNetTrackers[ConnectivityManager.TYPE_MOBILE] != null) { 1203 if (DBG) { 1204 Slog.d(TAG, mNetTrackers[ConnectivityManager.TYPE_MOBILE].toString() + enabled); 1205 } 1206 mNetTrackers[ConnectivityManager.TYPE_MOBILE].setDataEnable(enabled); 1207 } 1208 } 1209 1210 private void enforceAccessPermission() { 1211 mContext.enforceCallingOrSelfPermission( 1212 android.Manifest.permission.ACCESS_NETWORK_STATE, 1213 "ConnectivityService"); 1214 } 1215 1216 private void enforceChangePermission() { 1217 mContext.enforceCallingOrSelfPermission( 1218 android.Manifest.permission.CHANGE_NETWORK_STATE, 1219 "ConnectivityService"); 1220 } 1221 1222 // TODO Make this a special check when it goes public 1223 private void enforceTetherChangePermission() { 1224 mContext.enforceCallingOrSelfPermission( 1225 android.Manifest.permission.CHANGE_NETWORK_STATE, 1226 "ConnectivityService"); 1227 } 1228 1229 private void enforceTetherAccessPermission() { 1230 mContext.enforceCallingOrSelfPermission( 1231 android.Manifest.permission.ACCESS_NETWORK_STATE, 1232 "ConnectivityService"); 1233 } 1234 1235 private void enforceConnectivityInternalPermission() { 1236 mContext.enforceCallingOrSelfPermission( 1237 android.Manifest.permission.CONNECTIVITY_INTERNAL, 1238 "ConnectivityService"); 1239 } 1240 1241 /** 1242 * Handle a {@code DISCONNECTED} event. If this pertains to the non-active 1243 * network, we ignore it. If it is for the active network, we send out a 1244 * broadcast. But first, we check whether it might be possible to connect 1245 * to a different network. 1246 * @param info the {@code NetworkInfo} for the network 1247 */ 1248 private void handleDisconnect(NetworkInfo info) { 1249 1250 int prevNetType = info.getType(); 1251 1252 mNetTrackers[prevNetType].setTeardownRequested(false); 1253 /* 1254 * If the disconnected network is not the active one, then don't report 1255 * this as a loss of connectivity. What probably happened is that we're 1256 * getting the disconnect for a network that we explicitly disabled 1257 * in accordance with network preference policies. 1258 */ 1259 if (!mNetConfigs[prevNetType].isDefault()) { 1260 List pids = mNetRequestersPids[prevNetType]; 1261 for (int i = 0; i<pids.size(); i++) { 1262 Integer pid = (Integer)pids.get(i); 1263 // will remove them because the net's no longer connected 1264 // need to do this now as only now do we know the pids and 1265 // can properly null things that are no longer referenced. 1266 reassessPidDns(pid.intValue(), false); 1267 } 1268 } 1269 1270 Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION); 1271 intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info); 1272 if (info.isFailover()) { 1273 intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true); 1274 info.setFailover(false); 1275 } 1276 if (info.getReason() != null) { 1277 intent.putExtra(ConnectivityManager.EXTRA_REASON, info.getReason()); 1278 } 1279 if (info.getExtraInfo() != null) { 1280 intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO, 1281 info.getExtraInfo()); 1282 } 1283 1284 if (mNetConfigs[prevNetType].isDefault()) { 1285 tryFailover(prevNetType); 1286 if (mActiveDefaultNetwork != -1) { 1287 NetworkInfo switchTo = mNetTrackers[mActiveDefaultNetwork].getNetworkInfo(); 1288 intent.putExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO, switchTo); 1289 } else { 1290 mDefaultInetConditionPublished = 0; // we're not connected anymore 1291 intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true); 1292 } 1293 } 1294 intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION, mDefaultInetConditionPublished); 1295 1296 // Reset interface if no other connections are using the same interface 1297 boolean doReset = true; 1298 LinkProperties linkProperties = mNetTrackers[prevNetType].getLinkProperties(); 1299 if (linkProperties != null) { 1300 String oldIface = linkProperties.getInterfaceName(); 1301 if (TextUtils.isEmpty(oldIface) == false) { 1302 for (NetworkStateTracker networkStateTracker : mNetTrackers) { 1303 if (networkStateTracker == null) continue; 1304 NetworkInfo networkInfo = networkStateTracker.getNetworkInfo(); 1305 if (networkInfo.isConnected() && networkInfo.getType() != prevNetType) { 1306 LinkProperties l = networkStateTracker.getLinkProperties(); 1307 if (l == null) continue; 1308 if (oldIface.equals(l.getInterfaceName())) { 1309 doReset = false; 1310 break; 1311 } 1312 } 1313 } 1314 } 1315 } 1316 1317 // do this before we broadcast the change 1318 handleConnectivityChange(prevNetType, doReset); 1319 1320 sendStickyBroadcast(intent); 1321 /* 1322 * If the failover network is already connected, then immediately send 1323 * out a followup broadcast indicating successful failover 1324 */ 1325 if (mActiveDefaultNetwork != -1) { 1326 sendConnectedBroadcast(mNetTrackers[mActiveDefaultNetwork].getNetworkInfo()); 1327 } 1328 } 1329 1330 private void tryFailover(int prevNetType) { 1331 /* 1332 * If this is a default network, check if other defaults are available. 1333 * Try to reconnect on all available and let them hash it out when 1334 * more than one connects. 1335 */ 1336 if (mNetConfigs[prevNetType].isDefault()) { 1337 if (mActiveDefaultNetwork == prevNetType) { 1338 mActiveDefaultNetwork = -1; 1339 } 1340 1341 // don't signal a reconnect for anything lower or equal priority than our 1342 // current connected default 1343 // TODO - don't filter by priority now - nice optimization but risky 1344// int currentPriority = -1; 1345// if (mActiveDefaultNetwork != -1) { 1346// currentPriority = mNetConfigs[mActiveDefaultNetwork].mPriority; 1347// } 1348 for (int checkType=0; checkType <= ConnectivityManager.MAX_NETWORK_TYPE; checkType++) { 1349 if (checkType == prevNetType) continue; 1350 if (mNetConfigs[checkType] == null) continue; 1351 if (!mNetConfigs[checkType].isDefault()) continue; 1352 1353// Enabling the isAvailable() optimization caused mobile to not get 1354// selected if it was in the middle of error handling. Specifically 1355// a moble connection that took 30 seconds to complete the DEACTIVATE_DATA_CALL 1356// would not be available and we wouldn't get connected to anything. 1357// So removing the isAvailable() optimization below for now. TODO: This 1358// optimization should work and we need to investigate why it doesn't work. 1359// This could be related to how DEACTIVATE_DATA_CALL is reporting its 1360// complete before it is really complete. 1361// if (!mNetTrackers[checkType].isAvailable()) continue; 1362 1363// if (currentPriority >= mNetConfigs[checkType].mPriority) continue; 1364 1365 NetworkStateTracker checkTracker = mNetTrackers[checkType]; 1366 NetworkInfo checkInfo = checkTracker.getNetworkInfo(); 1367 if (!checkInfo.isConnectedOrConnecting() || checkTracker.isTeardownRequested()) { 1368 checkInfo.setFailover(true); 1369 checkTracker.reconnect(); 1370 } 1371 if (DBG) log("Attempting to switch to " + checkInfo.getTypeName()); 1372 } 1373 } 1374 } 1375 1376 private void sendConnectedBroadcast(NetworkInfo info) { 1377 sendGeneralBroadcast(info, ConnectivityManager.CONNECTIVITY_ACTION); 1378 } 1379 1380 private void sendInetConditionBroadcast(NetworkInfo info) { 1381 sendGeneralBroadcast(info, ConnectivityManager.INET_CONDITION_ACTION); 1382 } 1383 1384 private void sendGeneralBroadcast(NetworkInfo info, String bcastType) { 1385 Intent intent = new Intent(bcastType); 1386 intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info); 1387 if (info.isFailover()) { 1388 intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true); 1389 info.setFailover(false); 1390 } 1391 if (info.getReason() != null) { 1392 intent.putExtra(ConnectivityManager.EXTRA_REASON, info.getReason()); 1393 } 1394 if (info.getExtraInfo() != null) { 1395 intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO, 1396 info.getExtraInfo()); 1397 } 1398 intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION, mDefaultInetConditionPublished); 1399 sendStickyBroadcast(intent); 1400 } 1401 1402 /** 1403 * Called when an attempt to fail over to another network has failed. 1404 * @param info the {@link NetworkInfo} for the failed network 1405 */ 1406 private void handleConnectionFailure(NetworkInfo info) { 1407 mNetTrackers[info.getType()].setTeardownRequested(false); 1408 1409 String reason = info.getReason(); 1410 String extraInfo = info.getExtraInfo(); 1411 1412 String reasonText; 1413 if (reason == null) { 1414 reasonText = "."; 1415 } else { 1416 reasonText = " (" + reason + ")."; 1417 } 1418 loge("Attempt to connect to " + info.getTypeName() + " failed" + reasonText); 1419 1420 Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION); 1421 intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info); 1422 if (getActiveNetworkInfo() == null) { 1423 intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true); 1424 } 1425 if (reason != null) { 1426 intent.putExtra(ConnectivityManager.EXTRA_REASON, reason); 1427 } 1428 if (extraInfo != null) { 1429 intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO, extraInfo); 1430 } 1431 if (info.isFailover()) { 1432 intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true); 1433 info.setFailover(false); 1434 } 1435 1436 if (mNetConfigs[info.getType()].isDefault()) { 1437 tryFailover(info.getType()); 1438 if (mActiveDefaultNetwork != -1) { 1439 NetworkInfo switchTo = mNetTrackers[mActiveDefaultNetwork].getNetworkInfo(); 1440 intent.putExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO, switchTo); 1441 } else { 1442 mDefaultInetConditionPublished = 0; 1443 intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true); 1444 } 1445 } 1446 1447 intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION, mDefaultInetConditionPublished); 1448 sendStickyBroadcast(intent); 1449 /* 1450 * If the failover network is already connected, then immediately send 1451 * out a followup broadcast indicating successful failover 1452 */ 1453 if (mActiveDefaultNetwork != -1) { 1454 sendConnectedBroadcast(mNetTrackers[mActiveDefaultNetwork].getNetworkInfo()); 1455 } 1456 } 1457 1458 private void sendStickyBroadcast(Intent intent) { 1459 synchronized(this) { 1460 if (!mSystemReady) { 1461 mInitialBroadcast = new Intent(intent); 1462 } 1463 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 1464 mContext.sendStickyBroadcast(intent); 1465 } 1466 } 1467 1468 void systemReady() { 1469 synchronized(this) { 1470 mSystemReady = true; 1471 if (mInitialBroadcast != null) { 1472 mContext.sendStickyBroadcast(mInitialBroadcast); 1473 mInitialBroadcast = null; 1474 } 1475 } 1476 // load the global proxy at startup 1477 mHandler.sendMessage(mHandler.obtainMessage(EVENT_APPLY_GLOBAL_HTTP_PROXY)); 1478 } 1479 1480 private void handleConnect(NetworkInfo info) { 1481 int type = info.getType(); 1482 1483 // snapshot isFailover, because sendConnectedBroadcast() resets it 1484 boolean isFailover = info.isFailover(); 1485 NetworkStateTracker thisNet = mNetTrackers[type]; 1486 1487 // if this is a default net and other default is running 1488 // kill the one not preferred 1489 if (mNetConfigs[type].isDefault()) { 1490 if (mActiveDefaultNetwork != -1 && mActiveDefaultNetwork != type) { 1491 if ((type != mNetworkPreference && 1492 mNetConfigs[mActiveDefaultNetwork].priority > 1493 mNetConfigs[type].priority) || 1494 mNetworkPreference == mActiveDefaultNetwork) { 1495 // don't accept this one 1496 if (DBG) { 1497 log("Not broadcasting CONNECT_ACTION " + 1498 "to torn down network " + info.getTypeName()); 1499 } 1500 teardown(thisNet); 1501 return; 1502 } else { 1503 // tear down the other 1504 NetworkStateTracker otherNet = 1505 mNetTrackers[mActiveDefaultNetwork]; 1506 if (DBG) { 1507 log("Policy requires " + otherNet.getNetworkInfo().getTypeName() + 1508 " teardown"); 1509 } 1510 if (!teardown(otherNet)) { 1511 loge("Network declined teardown request"); 1512 teardown(thisNet); 1513 return; 1514 } 1515 } 1516 } 1517 synchronized (ConnectivityService.this) { 1518 // have a new default network, release the transition wakelock in a second 1519 // if it's held. The second pause is to allow apps to reconnect over the 1520 // new network 1521 if (mNetTransitionWakeLock.isHeld()) { 1522 mHandler.sendMessageDelayed(mHandler.obtainMessage( 1523 EVENT_CLEAR_NET_TRANSITION_WAKELOCK, 1524 mNetTransitionWakeLockSerialNumber, 0), 1525 1000); 1526 } 1527 } 1528 mActiveDefaultNetwork = type; 1529 // this will cause us to come up initially as unconnected and switching 1530 // to connected after our normal pause unless somebody reports us as reall 1531 // disconnected 1532 mDefaultInetConditionPublished = 0; 1533 mDefaultConnectionSequence++; 1534 mInetConditionChangeInFlight = false; 1535 // Don't do this - if we never sign in stay, grey 1536 //reportNetworkCondition(mActiveDefaultNetwork, 100); 1537 } 1538 thisNet.setTeardownRequested(false); 1539 updateNetworkSettings(thisNet); 1540 handleConnectivityChange(type, false); 1541 sendConnectedBroadcast(info); 1542 } 1543 1544 /** 1545 * After a change in the connectivity state of a network. We're mainly 1546 * concerned with making sure that the list of DNS servers is set up 1547 * according to which networks are connected, and ensuring that the 1548 * right routing table entries exist. 1549 */ 1550 private void handleConnectivityChange(int netType, boolean doReset) { 1551 /* 1552 * If a non-default network is enabled, add the host routes that 1553 * will allow it's DNS servers to be accessed. 1554 */ 1555 handleDnsConfigurationChange(netType); 1556 1557 if (mNetTrackers[netType].getNetworkInfo().isConnected()) { 1558 if (mNetConfigs[netType].isDefault()) { 1559 handleApplyDefaultProxy(netType); 1560 addDefaultRoute(mNetTrackers[netType]); 1561 } else { 1562 // many radios add a default route even when we don't want one. 1563 // remove the default route unless we need it for our active network 1564 if (mActiveDefaultNetwork != -1) { 1565 LinkProperties defaultLinkProperties = 1566 mNetTrackers[mActiveDefaultNetwork].getLinkProperties(); 1567 LinkProperties newLinkProperties = 1568 mNetTrackers[netType].getLinkProperties(); 1569 String defaultIface = defaultLinkProperties.getInterfaceName(); 1570 if (defaultIface != null && 1571 !defaultIface.equals(newLinkProperties.getInterfaceName())) { 1572 removeDefaultRoute(mNetTrackers[netType]); 1573 } 1574 } 1575 addPrivateDnsRoutes(mNetTrackers[netType]); 1576 } 1577 } else { 1578 if (mNetConfigs[netType].isDefault()) { 1579 removeDefaultRoute(mNetTrackers[netType]); 1580 } else { 1581 removePrivateDnsRoutes(mNetTrackers[netType]); 1582 } 1583 } 1584 1585 if (doReset) { 1586 LinkProperties linkProperties = mNetTrackers[netType].getLinkProperties(); 1587 if (linkProperties != null) { 1588 String iface = linkProperties.getInterfaceName(); 1589 if (TextUtils.isEmpty(iface) == false) { 1590 if (DBG) log("resetConnections(" + iface + ")"); 1591 NetworkUtils.resetConnections(iface); 1592 } 1593 } 1594 } 1595 } 1596 1597 private void addPrivateDnsRoutes(NetworkStateTracker nt) { 1598 boolean privateDnsRouteSet = nt.isPrivateDnsRouteSet(); 1599 LinkProperties p = nt.getLinkProperties(); 1600 if (p == null) return; 1601 String interfaceName = p.getInterfaceName(); 1602 1603 if (DBG) { 1604 log("addPrivateDnsRoutes for " + nt + 1605 "(" + interfaceName + ") - mPrivateDnsRouteSet = " + privateDnsRouteSet); 1606 } 1607 if (interfaceName != null && !privateDnsRouteSet) { 1608 Collection<InetAddress> dnsList = p.getDnses(); 1609 for (InetAddress dns : dnsList) { 1610 addHostRoute(nt, dns, 0); 1611 } 1612 nt.privateDnsRouteSet(true); 1613 } 1614 } 1615 1616 private void removePrivateDnsRoutes(NetworkStateTracker nt) { 1617 LinkProperties p = nt.getLinkProperties(); 1618 if (p == null) return; 1619 String interfaceName = p.getInterfaceName(); 1620 boolean privateDnsRouteSet = nt.isPrivateDnsRouteSet(); 1621 if (interfaceName != null && privateDnsRouteSet) { 1622 if (DBG) { 1623 log("removePrivateDnsRoutes for " + nt.getNetworkInfo().getTypeName() + 1624 " (" + interfaceName + ")"); 1625 } 1626 1627 Collection<InetAddress> dnsList = p.getDnses(); 1628 for (InetAddress dns : dnsList) { 1629 if (DBG) log(" removing " + dns); 1630 RouteInfo route = RouteInfo.makeHostRoute(dns); 1631 try { 1632 mNetd.removeRoute(interfaceName, route); 1633 } catch (Exception ex) { 1634 loge("error (" + ex + ") removing dns route " + route); 1635 } 1636 } 1637 nt.privateDnsRouteSet(false); 1638 } 1639 } 1640 1641 1642 private void addDefaultRoute(NetworkStateTracker nt) { 1643 LinkProperties p = nt.getLinkProperties(); 1644 if (p == null) return; 1645 String interfaceName = p.getInterfaceName(); 1646 if (TextUtils.isEmpty(interfaceName)) return; 1647 1648 for (RouteInfo route : p.getRoutes()) { 1649 //TODO - handle non-default routes 1650 if (route.isDefaultRoute()) { 1651 if (DBG) log("adding default route " + route); 1652 InetAddress gateway = route.getGateway(); 1653 if (addHostRoute(nt, gateway, 0)) { 1654 try { 1655 mNetd.addRoute(interfaceName, route); 1656 } catch (Exception e) { 1657 loge("error adding default route " + route); 1658 continue; 1659 } 1660 if (DBG) { 1661 NetworkInfo networkInfo = nt.getNetworkInfo(); 1662 log("addDefaultRoute for " + networkInfo.getTypeName() + 1663 " (" + interfaceName + "), GatewayAddr=" + 1664 gateway.getHostAddress()); 1665 } 1666 } else { 1667 loge("error adding host route for default route " + route); 1668 } 1669 } 1670 } 1671 } 1672 1673 1674 public void removeDefaultRoute(NetworkStateTracker nt) { 1675 LinkProperties p = nt.getLinkProperties(); 1676 if (p == null) return; 1677 String interfaceName = p.getInterfaceName(); 1678 1679 if (interfaceName == null) return; 1680 1681 for (RouteInfo route : p.getRoutes()) { 1682 //TODO - handle non-default routes 1683 if (route.isDefaultRoute()) { 1684 try { 1685 mNetd.removeRoute(interfaceName, route); 1686 } catch (Exception ex) { 1687 loge("error (" + ex + ") removing default route " + route); 1688 continue; 1689 } 1690 if (DBG) { 1691 NetworkInfo networkInfo = nt.getNetworkInfo(); 1692 log("removeDefaultRoute for " + networkInfo.getTypeName() + " (" + 1693 interfaceName + ")"); 1694 } 1695 } 1696 } 1697 } 1698 1699 /** 1700 * Reads the network specific TCP buffer sizes from SystemProperties 1701 * net.tcp.buffersize.[default|wifi|umts|edge|gprs] and set them for system 1702 * wide use 1703 */ 1704 public void updateNetworkSettings(NetworkStateTracker nt) { 1705 String key = nt.getTcpBufferSizesPropName(); 1706 String bufferSizes = SystemProperties.get(key); 1707 1708 if (bufferSizes.length() == 0) { 1709 loge(key + " not found in system properties. Using defaults"); 1710 1711 // Setting to default values so we won't be stuck to previous values 1712 key = "net.tcp.buffersize.default"; 1713 bufferSizes = SystemProperties.get(key); 1714 } 1715 1716 // Set values in kernel 1717 if (bufferSizes.length() != 0) { 1718 if (DBG) { 1719 log("Setting TCP values: [" + bufferSizes 1720 + "] which comes from [" + key + "]"); 1721 } 1722 setBufferSize(bufferSizes); 1723 } 1724 } 1725 1726 /** 1727 * Writes TCP buffer sizes to /sys/kernel/ipv4/tcp_[r/w]mem_[min/def/max] 1728 * which maps to /proc/sys/net/ipv4/tcp_rmem and tcpwmem 1729 * 1730 * @param bufferSizes in the format of "readMin, readInitial, readMax, 1731 * writeMin, writeInitial, writeMax" 1732 */ 1733 private void setBufferSize(String bufferSizes) { 1734 try { 1735 String[] values = bufferSizes.split(","); 1736 1737 if (values.length == 6) { 1738 final String prefix = "/sys/kernel/ipv4/tcp_"; 1739 FileUtils.stringToFile(prefix + "rmem_min", values[0]); 1740 FileUtils.stringToFile(prefix + "rmem_def", values[1]); 1741 FileUtils.stringToFile(prefix + "rmem_max", values[2]); 1742 FileUtils.stringToFile(prefix + "wmem_min", values[3]); 1743 FileUtils.stringToFile(prefix + "wmem_def", values[4]); 1744 FileUtils.stringToFile(prefix + "wmem_max", values[5]); 1745 } else { 1746 loge("Invalid buffersize string: " + bufferSizes); 1747 } 1748 } catch (IOException e) { 1749 loge("Can't set tcp buffer sizes:" + e); 1750 } 1751 } 1752 1753 /** 1754 * Adjust the per-process dns entries (net.dns<x>.<pid>) based 1755 * on the highest priority active net which this process requested. 1756 * If there aren't any, clear it out 1757 */ 1758 private void reassessPidDns(int myPid, boolean doBump) 1759 { 1760 if (DBG) log("reassessPidDns for pid " + myPid); 1761 for(int i : mPriorityList) { 1762 if (mNetConfigs[i].isDefault()) { 1763 continue; 1764 } 1765 NetworkStateTracker nt = mNetTrackers[i]; 1766 if (nt.getNetworkInfo().isConnected() && 1767 !nt.isTeardownRequested()) { 1768 LinkProperties p = nt.getLinkProperties(); 1769 if (p == null) continue; 1770 List pids = mNetRequestersPids[i]; 1771 for (int j=0; j<pids.size(); j++) { 1772 Integer pid = (Integer)pids.get(j); 1773 if (pid.intValue() == myPid) { 1774 Collection<InetAddress> dnses = p.getDnses(); 1775 writePidDns(dnses, myPid); 1776 if (doBump) { 1777 bumpDns(); 1778 } 1779 return; 1780 } 1781 } 1782 } 1783 } 1784 // nothing found - delete 1785 for (int i = 1; ; i++) { 1786 String prop = "net.dns" + i + "." + myPid; 1787 if (SystemProperties.get(prop).length() == 0) { 1788 if (doBump) { 1789 bumpDns(); 1790 } 1791 return; 1792 } 1793 SystemProperties.set(prop, ""); 1794 } 1795 } 1796 1797 // return true if results in a change 1798 private boolean writePidDns(Collection <InetAddress> dnses, int pid) { 1799 int j = 1; 1800 boolean changed = false; 1801 for (InetAddress dns : dnses) { 1802 String dnsString = dns.getHostAddress(); 1803 if (changed || !dnsString.equals(SystemProperties.get("net.dns" + j + "." + pid))) { 1804 changed = true; 1805 SystemProperties.set("net.dns" + j++ + "." + pid, dns.getHostAddress()); 1806 } 1807 } 1808 return changed; 1809 } 1810 1811 private void bumpDns() { 1812 /* 1813 * Bump the property that tells the name resolver library to reread 1814 * the DNS server list from the properties. 1815 */ 1816 String propVal = SystemProperties.get("net.dnschange"); 1817 int n = 0; 1818 if (propVal.length() != 0) { 1819 try { 1820 n = Integer.parseInt(propVal); 1821 } catch (NumberFormatException e) {} 1822 } 1823 SystemProperties.set("net.dnschange", "" + (n+1)); 1824 /* 1825 * Tell the VMs to toss their DNS caches 1826 */ 1827 Intent intent = new Intent(Intent.ACTION_CLEAR_DNS_CACHE); 1828 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); 1829 /* 1830 * Connectivity events can happen before boot has completed ... 1831 */ 1832 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 1833 mContext.sendBroadcast(intent); 1834 } 1835 1836 private void handleDnsConfigurationChange(int netType) { 1837 // add default net's dns entries 1838 NetworkStateTracker nt = mNetTrackers[netType]; 1839 if (nt != null && nt.getNetworkInfo().isConnected() && !nt.isTeardownRequested()) { 1840 LinkProperties p = nt.getLinkProperties(); 1841 if (p == null) return; 1842 Collection<InetAddress> dnses = p.getDnses(); 1843 boolean changed = false; 1844 if (mNetConfigs[netType].isDefault()) { 1845 int j = 1; 1846 if (dnses.size() == 0 && mDefaultDns != null) { 1847 String dnsString = mDefaultDns.getHostAddress(); 1848 if (!dnsString.equals(SystemProperties.get("net.dns1"))) { 1849 if (DBG) { 1850 log("no dns provided - using " + dnsString); 1851 } 1852 changed = true; 1853 SystemProperties.set("net.dns1", dnsString); 1854 } 1855 j++; 1856 } else { 1857 for (InetAddress dns : dnses) { 1858 String dnsString = dns.getHostAddress(); 1859 if (!changed && dnsString.equals(SystemProperties.get("net.dns" + j))) { 1860 j++; 1861 continue; 1862 } 1863 if (DBG) { 1864 log("adding dns " + dns + " for " + 1865 nt.getNetworkInfo().getTypeName()); 1866 } 1867 changed = true; 1868 SystemProperties.set("net.dns" + j++, dnsString); 1869 } 1870 } 1871 for (int k=j ; k<mNumDnsEntries; k++) { 1872 if (changed || !TextUtils.isEmpty(SystemProperties.get("net.dns" + k))) { 1873 if (DBG) log("erasing net.dns" + k); 1874 changed = true; 1875 SystemProperties.set("net.dns" + k, ""); 1876 } 1877 } 1878 mNumDnsEntries = j; 1879 } else { 1880 // set per-pid dns for attached secondary nets 1881 List pids = mNetRequestersPids[netType]; 1882 for (int y=0; y< pids.size(); y++) { 1883 Integer pid = (Integer)pids.get(y); 1884 changed = writePidDns(dnses, pid.intValue()); 1885 } 1886 } 1887 if (changed) bumpDns(); 1888 } 1889 } 1890 1891 private int getRestoreDefaultNetworkDelay(int networkType) { 1892 String restoreDefaultNetworkDelayStr = SystemProperties.get( 1893 NETWORK_RESTORE_DELAY_PROP_NAME); 1894 if(restoreDefaultNetworkDelayStr != null && 1895 restoreDefaultNetworkDelayStr.length() != 0) { 1896 try { 1897 return Integer.valueOf(restoreDefaultNetworkDelayStr); 1898 } catch (NumberFormatException e) { 1899 } 1900 } 1901 // if the system property isn't set, use the value for the apn type 1902 int ret = RESTORE_DEFAULT_NETWORK_DELAY; 1903 1904 if ((networkType <= ConnectivityManager.MAX_NETWORK_TYPE) && 1905 (mNetConfigs[networkType] != null)) { 1906 ret = mNetConfigs[networkType].restoreTime; 1907 } 1908 return ret; 1909 } 1910 1911 @Override 1912 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1913 if (mContext.checkCallingOrSelfPermission( 1914 android.Manifest.permission.DUMP) 1915 != PackageManager.PERMISSION_GRANTED) { 1916 pw.println("Permission Denial: can't dump ConnectivityService " + 1917 "from from pid=" + Binder.getCallingPid() + ", uid=" + 1918 Binder.getCallingUid()); 1919 return; 1920 } 1921 pw.println(); 1922 for (NetworkStateTracker nst : mNetTrackers) { 1923 if (nst != null) { 1924 if (nst.getNetworkInfo().isConnected()) { 1925 pw.println("Active network: " + nst.getNetworkInfo(). 1926 getTypeName()); 1927 } 1928 pw.println(nst.getNetworkInfo()); 1929 pw.println(nst); 1930 pw.println(); 1931 } 1932 } 1933 1934 pw.println("Network Requester Pids:"); 1935 for (int net : mPriorityList) { 1936 String pidString = net + ": "; 1937 for (Object pid : mNetRequestersPids[net]) { 1938 pidString = pidString + pid.toString() + ", "; 1939 } 1940 pw.println(pidString); 1941 } 1942 pw.println(); 1943 1944 pw.println("FeatureUsers:"); 1945 for (Object requester : mFeatureUsers) { 1946 pw.println(requester.toString()); 1947 } 1948 pw.println(); 1949 1950 synchronized (this) { 1951 pw.println("NetworkTranstionWakeLock is currently " + 1952 (mNetTransitionWakeLock.isHeld() ? "" : "not ") + "held."); 1953 pw.println("It was last requested for "+mNetTransitionWakeLockCausedBy); 1954 } 1955 pw.println(); 1956 1957 mTethering.dump(fd, pw, args); 1958 1959 if (mInetLog != null) { 1960 pw.println(); 1961 pw.println("Inet condition reports:"); 1962 for(int i = 0; i < mInetLog.size(); i++) { 1963 pw.println(mInetLog.get(i)); 1964 } 1965 } 1966 } 1967 1968 // must be stateless - things change under us. 1969 private class MyHandler extends Handler { 1970 public MyHandler(Looper looper) { 1971 super(looper); 1972 } 1973 1974 @Override 1975 public void handleMessage(Message msg) { 1976 NetworkInfo info; 1977 switch (msg.what) { 1978 case NetworkStateTracker.EVENT_STATE_CHANGED: 1979 info = (NetworkInfo) msg.obj; 1980 int type = info.getType(); 1981 NetworkInfo.State state = info.getState(); 1982 1983 if (DBG) log("ConnectivityChange for " + 1984 info.getTypeName() + ": " + 1985 state + "/" + info.getDetailedState()); 1986 1987 // Connectivity state changed: 1988 // [31-13] Reserved for future use 1989 // [12-9] Network subtype (for mobile network, as defined 1990 // by TelephonyManager) 1991 // [8-3] Detailed state ordinal (as defined by 1992 // NetworkInfo.DetailedState) 1993 // [2-0] Network type (as defined by ConnectivityManager) 1994 int eventLogParam = (info.getType() & 0x7) | 1995 ((info.getDetailedState().ordinal() & 0x3f) << 3) | 1996 (info.getSubtype() << 9); 1997 EventLog.writeEvent(EventLogTags.CONNECTIVITY_STATE_CHANGED, 1998 eventLogParam); 1999 2000 if (info.getDetailedState() == 2001 NetworkInfo.DetailedState.FAILED) { 2002 handleConnectionFailure(info); 2003 } else if (state == NetworkInfo.State.DISCONNECTED) { 2004 handleDisconnect(info); 2005 } else if (state == NetworkInfo.State.SUSPENDED) { 2006 // TODO: need to think this over. 2007 // the logic here is, handle SUSPENDED the same as 2008 // DISCONNECTED. The only difference being we are 2009 // broadcasting an intent with NetworkInfo that's 2010 // suspended. This allows the applications an 2011 // opportunity to handle DISCONNECTED and SUSPENDED 2012 // differently, or not. 2013 handleDisconnect(info); 2014 } else if (state == NetworkInfo.State.CONNECTED) { 2015 handleConnect(info); 2016 } 2017 break; 2018 case NetworkStateTracker.EVENT_CONFIGURATION_CHANGED: 2019 info = (NetworkInfo) msg.obj; 2020 handleConnectivityChange(info.getType(), true); 2021 break; 2022 case EVENT_CLEAR_NET_TRANSITION_WAKELOCK: 2023 String causedBy = null; 2024 synchronized (ConnectivityService.this) { 2025 if (msg.arg1 == mNetTransitionWakeLockSerialNumber && 2026 mNetTransitionWakeLock.isHeld()) { 2027 mNetTransitionWakeLock.release(); 2028 causedBy = mNetTransitionWakeLockCausedBy; 2029 } 2030 } 2031 if (causedBy != null) { 2032 log("NetTransition Wakelock for " + causedBy + " released by timeout"); 2033 } 2034 break; 2035 case EVENT_RESTORE_DEFAULT_NETWORK: 2036 FeatureUser u = (FeatureUser)msg.obj; 2037 u.expire(); 2038 break; 2039 case EVENT_INET_CONDITION_CHANGE: 2040 { 2041 int netType = msg.arg1; 2042 int condition = msg.arg2; 2043 handleInetConditionChange(netType, condition); 2044 break; 2045 } 2046 case EVENT_INET_CONDITION_HOLD_END: 2047 { 2048 int netType = msg.arg1; 2049 int sequence = msg.arg2; 2050 handleInetConditionHoldEnd(netType, sequence); 2051 break; 2052 } 2053 case EVENT_SET_NETWORK_PREFERENCE: 2054 { 2055 int preference = msg.arg1; 2056 handleSetNetworkPreference(preference); 2057 break; 2058 } 2059 case EVENT_SET_BACKGROUND_DATA: 2060 { 2061 boolean enabled = (msg.arg1 == ENABLED); 2062 handleSetBackgroundData(enabled); 2063 break; 2064 } 2065 case EVENT_SET_MOBILE_DATA: 2066 { 2067 boolean enabled = (msg.arg1 == ENABLED); 2068 handleSetMobileData(enabled); 2069 break; 2070 } 2071 case EVENT_APPLY_GLOBAL_HTTP_PROXY: 2072 { 2073 handleDeprecatedGlobalHttpProxy(); 2074 break; 2075 } 2076 case EVENT_SET_DEPENDENCY_MET: 2077 { 2078 boolean met = (msg.arg1 == ENABLED); 2079 handleSetDependencyMet(msg.arg2, met); 2080 break; 2081 } 2082 } 2083 } 2084 } 2085 2086 // javadoc from interface 2087 public int tether(String iface) { 2088 enforceTetherChangePermission(); 2089 2090 if (isTetheringSupported()) { 2091 return mTethering.tether(iface); 2092 } else { 2093 return ConnectivityManager.TETHER_ERROR_UNSUPPORTED; 2094 } 2095 } 2096 2097 // javadoc from interface 2098 public int untether(String iface) { 2099 enforceTetherChangePermission(); 2100 2101 if (isTetheringSupported()) { 2102 return mTethering.untether(iface); 2103 } else { 2104 return ConnectivityManager.TETHER_ERROR_UNSUPPORTED; 2105 } 2106 } 2107 2108 // javadoc from interface 2109 public int getLastTetherError(String iface) { 2110 enforceTetherAccessPermission(); 2111 2112 if (isTetheringSupported()) { 2113 return mTethering.getLastTetherError(iface); 2114 } else { 2115 return ConnectivityManager.TETHER_ERROR_UNSUPPORTED; 2116 } 2117 } 2118 2119 // TODO - proper iface API for selection by property, inspection, etc 2120 public String[] getTetherableUsbRegexs() { 2121 enforceTetherAccessPermission(); 2122 if (isTetheringSupported()) { 2123 return mTethering.getTetherableUsbRegexs(); 2124 } else { 2125 return new String[0]; 2126 } 2127 } 2128 2129 public String[] getTetherableWifiRegexs() { 2130 enforceTetherAccessPermission(); 2131 if (isTetheringSupported()) { 2132 return mTethering.getTetherableWifiRegexs(); 2133 } else { 2134 return new String[0]; 2135 } 2136 } 2137 2138 public String[] getTetherableBluetoothRegexs() { 2139 enforceTetherAccessPermission(); 2140 if (isTetheringSupported()) { 2141 return mTethering.getTetherableBluetoothRegexs(); 2142 } else { 2143 return new String[0]; 2144 } 2145 } 2146 2147 // TODO - move iface listing, queries, etc to new module 2148 // javadoc from interface 2149 public String[] getTetherableIfaces() { 2150 enforceTetherAccessPermission(); 2151 return mTethering.getTetherableIfaces(); 2152 } 2153 2154 public String[] getTetheredIfaces() { 2155 enforceTetherAccessPermission(); 2156 return mTethering.getTetheredIfaces(); 2157 } 2158 2159 public String[] getTetheringErroredIfaces() { 2160 enforceTetherAccessPermission(); 2161 return mTethering.getErroredIfaces(); 2162 } 2163 2164 // if ro.tether.denied = true we default to no tethering 2165 // gservices could set the secure setting to 1 though to enable it on a build where it 2166 // had previously been turned off. 2167 public boolean isTetheringSupported() { 2168 enforceTetherAccessPermission(); 2169 int defaultVal = (SystemProperties.get("ro.tether.denied").equals("true") ? 0 : 1); 2170 boolean tetherEnabledInSettings = (Settings.Secure.getInt(mContext.getContentResolver(), 2171 Settings.Secure.TETHER_SUPPORTED, defaultVal) != 0); 2172 return tetherEnabledInSettings && mTetheringConfigValid; 2173 } 2174 2175 // An API NetworkStateTrackers can call when they lose their network. 2176 // This will automatically be cleared after X seconds or a network becomes CONNECTED, 2177 // whichever happens first. The timer is started by the first caller and not 2178 // restarted by subsequent callers. 2179 public void requestNetworkTransitionWakelock(String forWhom) { 2180 enforceConnectivityInternalPermission(); 2181 synchronized (this) { 2182 if (mNetTransitionWakeLock.isHeld()) return; 2183 mNetTransitionWakeLockSerialNumber++; 2184 mNetTransitionWakeLock.acquire(); 2185 mNetTransitionWakeLockCausedBy = forWhom; 2186 } 2187 mHandler.sendMessageDelayed(mHandler.obtainMessage( 2188 EVENT_CLEAR_NET_TRANSITION_WAKELOCK, 2189 mNetTransitionWakeLockSerialNumber, 0), 2190 mNetTransitionWakeLockTimeout); 2191 return; 2192 } 2193 2194 // 100 percent is full good, 0 is full bad. 2195 public void reportInetCondition(int networkType, int percentage) { 2196 if (DBG) log("reportNetworkCondition(" + networkType + ", " + percentage + ")"); 2197 mContext.enforceCallingOrSelfPermission( 2198 android.Manifest.permission.STATUS_BAR, 2199 "ConnectivityService"); 2200 2201 if (DBG) { 2202 int pid = getCallingPid(); 2203 int uid = getCallingUid(); 2204 String s = pid + "(" + uid + ") reports inet is " + 2205 (percentage > 50 ? "connected" : "disconnected") + " (" + percentage + ") on " + 2206 "network Type " + networkType + " at " + GregorianCalendar.getInstance().getTime(); 2207 mInetLog.add(s); 2208 while(mInetLog.size() > INET_CONDITION_LOG_MAX_SIZE) { 2209 mInetLog.remove(0); 2210 } 2211 } 2212 mHandler.sendMessage(mHandler.obtainMessage( 2213 EVENT_INET_CONDITION_CHANGE, networkType, percentage)); 2214 } 2215 2216 private void handleInetConditionChange(int netType, int condition) { 2217 if (DBG) { 2218 log("Inet connectivity change, net=" + 2219 netType + ", condition=" + condition + 2220 ",mActiveDefaultNetwork=" + mActiveDefaultNetwork); 2221 } 2222 if (mActiveDefaultNetwork == -1) { 2223 if (DBG) log("no active default network - aborting"); 2224 return; 2225 } 2226 if (mActiveDefaultNetwork != netType) { 2227 if (DBG) log("given net not default - aborting"); 2228 return; 2229 } 2230 mDefaultInetCondition = condition; 2231 int delay; 2232 if (mInetConditionChangeInFlight == false) { 2233 if (DBG) log("starting a change hold"); 2234 // setup a new hold to debounce this 2235 if (mDefaultInetCondition > 50) { 2236 delay = Settings.Secure.getInt(mContext.getContentResolver(), 2237 Settings.Secure.INET_CONDITION_DEBOUNCE_UP_DELAY, 500); 2238 } else { 2239 delay = Settings.Secure.getInt(mContext.getContentResolver(), 2240 Settings.Secure.INET_CONDITION_DEBOUNCE_DOWN_DELAY, 3000); 2241 } 2242 mInetConditionChangeInFlight = true; 2243 mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_INET_CONDITION_HOLD_END, 2244 mActiveDefaultNetwork, mDefaultConnectionSequence), delay); 2245 } else { 2246 // we've set the new condition, when this hold ends that will get 2247 // picked up 2248 if (DBG) log("currently in hold - not setting new end evt"); 2249 } 2250 } 2251 2252 private void handleInetConditionHoldEnd(int netType, int sequence) { 2253 if (DBG) { 2254 log("Inet hold end, net=" + netType + 2255 ", condition =" + mDefaultInetCondition + 2256 ", published condition =" + mDefaultInetConditionPublished); 2257 } 2258 mInetConditionChangeInFlight = false; 2259 2260 if (mActiveDefaultNetwork == -1) { 2261 if (DBG) log("no active default network - aborting"); 2262 return; 2263 } 2264 if (mDefaultConnectionSequence != sequence) { 2265 if (DBG) log("event hold for obsolete network - aborting"); 2266 return; 2267 } 2268 if (mDefaultInetConditionPublished == mDefaultInetCondition) { 2269 if (DBG) log("no change in condition - aborting"); 2270 return; 2271 } 2272 NetworkInfo networkInfo = mNetTrackers[mActiveDefaultNetwork].getNetworkInfo(); 2273 if (networkInfo.isConnected() == false) { 2274 if (DBG) log("default network not connected - aborting"); 2275 return; 2276 } 2277 mDefaultInetConditionPublished = mDefaultInetCondition; 2278 sendInetConditionBroadcast(networkInfo); 2279 return; 2280 } 2281 2282 public synchronized ProxyProperties getProxy() { 2283 if (mGlobalProxy != null) return mGlobalProxy; 2284 if (mDefaultProxy != null) return mDefaultProxy; 2285 return null; 2286 } 2287 2288 public void setGlobalProxy(ProxyProperties proxyProperties) { 2289 enforceChangePermission(); 2290 synchronized (mGlobalProxyLock) { 2291 if (proxyProperties == mGlobalProxy) return; 2292 if (proxyProperties != null && proxyProperties.equals(mGlobalProxy)) return; 2293 if (mGlobalProxy != null && mGlobalProxy.equals(proxyProperties)) return; 2294 2295 String host = ""; 2296 int port = 0; 2297 String exclList = ""; 2298 if (proxyProperties != null && !TextUtils.isEmpty(proxyProperties.getHost())) { 2299 mGlobalProxy = new ProxyProperties(proxyProperties); 2300 host = mGlobalProxy.getHost(); 2301 port = mGlobalProxy.getPort(); 2302 exclList = mGlobalProxy.getExclusionList(); 2303 } else { 2304 mGlobalProxy = null; 2305 } 2306 ContentResolver res = mContext.getContentResolver(); 2307 Settings.Secure.putString(res, Settings.Secure.GLOBAL_HTTP_PROXY_HOST, host); 2308 Settings.Secure.putInt(res, Settings.Secure.GLOBAL_HTTP_PROXY_PORT, port); 2309 Settings.Secure.putString(res, Settings.Secure.GLOBAL_HTTP_PROXY_EXCLUSION_LIST, 2310 exclList); 2311 } 2312 2313 if (mGlobalProxy == null) { 2314 proxyProperties = mDefaultProxy; 2315 } 2316 sendProxyBroadcast(proxyProperties); 2317 } 2318 2319 private void loadGlobalProxy() { 2320 ContentResolver res = mContext.getContentResolver(); 2321 String host = Settings.Secure.getString(res, Settings.Secure.GLOBAL_HTTP_PROXY_HOST); 2322 int port = Settings.Secure.getInt(res, Settings.Secure.GLOBAL_HTTP_PROXY_PORT, 0); 2323 String exclList = Settings.Secure.getString(res, 2324 Settings.Secure.GLOBAL_HTTP_PROXY_EXCLUSION_LIST); 2325 if (!TextUtils.isEmpty(host)) { 2326 ProxyProperties proxyProperties = new ProxyProperties(host, port, exclList); 2327 synchronized (mGlobalProxyLock) { 2328 mGlobalProxy = proxyProperties; 2329 } 2330 } 2331 } 2332 2333 public ProxyProperties getGlobalProxy() { 2334 synchronized (mGlobalProxyLock) { 2335 return mGlobalProxy; 2336 } 2337 } 2338 2339 private void handleApplyDefaultProxy(int type) { 2340 // check if new default - push it out to all VM if so 2341 ProxyProperties proxy = mNetTrackers[type].getLinkProperties().getHttpProxy(); 2342 synchronized (this) { 2343 if (mDefaultProxy != null && mDefaultProxy.equals(proxy)) return; 2344 if (mDefaultProxy == proxy) return; 2345 if (!TextUtils.isEmpty(proxy.getHost())) { 2346 mDefaultProxy = proxy; 2347 } else { 2348 mDefaultProxy = null; 2349 } 2350 } 2351 if (DBG) log("changing default proxy to " + proxy); 2352 if ((proxy == null && mGlobalProxy == null) || proxy.equals(mGlobalProxy)) return; 2353 if (mGlobalProxy != null) return; 2354 sendProxyBroadcast(proxy); 2355 } 2356 2357 private void handleDeprecatedGlobalHttpProxy() { 2358 String proxy = Settings.Secure.getString(mContext.getContentResolver(), 2359 Settings.Secure.HTTP_PROXY); 2360 if (!TextUtils.isEmpty(proxy)) { 2361 String data[] = proxy.split(":"); 2362 String proxyHost = data[0]; 2363 int proxyPort = 8080; 2364 if (data.length > 1) { 2365 try { 2366 proxyPort = Integer.parseInt(data[1]); 2367 } catch (NumberFormatException e) { 2368 return; 2369 } 2370 } 2371 ProxyProperties p = new ProxyProperties(data[0], proxyPort, ""); 2372 setGlobalProxy(p); 2373 } 2374 } 2375 2376 private void sendProxyBroadcast(ProxyProperties proxy) { 2377 if (proxy == null) proxy = new ProxyProperties("", 0, ""); 2378 log("sending Proxy Broadcast for " + proxy); 2379 Intent intent = new Intent(Proxy.PROXY_CHANGE_ACTION); 2380 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING | 2381 Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 2382 intent.putExtra(Proxy.EXTRA_PROXY_INFO, proxy); 2383 mContext.sendStickyBroadcast(intent); 2384 } 2385 2386 private static class SettingsObserver extends ContentObserver { 2387 private int mWhat; 2388 private Handler mHandler; 2389 SettingsObserver(Handler handler, int what) { 2390 super(handler); 2391 mHandler = handler; 2392 mWhat = what; 2393 } 2394 2395 void observe(Context context) { 2396 ContentResolver resolver = context.getContentResolver(); 2397 resolver.registerContentObserver(Settings.Secure.getUriFor( 2398 Settings.Secure.HTTP_PROXY), false, this); 2399 } 2400 2401 @Override 2402 public void onChange(boolean selfChange) { 2403 mHandler.obtainMessage(mWhat).sendToTarget(); 2404 } 2405 } 2406 2407 private void log(String s) { 2408 Slog.d(TAG, s); 2409 } 2410 2411 private void loge(String s) { 2412 Slog.e(TAG, s); 2413 } 2414 2415 int convertFeatureToNetworkType(String feature){ 2416 int networkType = -1; 2417 if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_MMS)) { 2418 networkType = ConnectivityManager.TYPE_MOBILE_MMS; 2419 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_SUPL)) { 2420 networkType = ConnectivityManager.TYPE_MOBILE_SUPL; 2421 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_DUN) || 2422 TextUtils.equals(feature, Phone.FEATURE_ENABLE_DUN_ALWAYS)) { 2423 networkType = ConnectivityManager.TYPE_MOBILE_DUN; 2424 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_HIPRI)) { 2425 networkType = ConnectivityManager.TYPE_MOBILE_HIPRI; 2426 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_FOTA)) { 2427 networkType = ConnectivityManager.TYPE_MOBILE_FOTA; 2428 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_IMS)) { 2429 networkType = ConnectivityManager.TYPE_MOBILE_IMS; 2430 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_CBS)) { 2431 networkType = ConnectivityManager.TYPE_MOBILE_CBS; 2432 } 2433 return networkType; 2434 } 2435 2436 private static <T> T checkNotNull(T value, String message) { 2437 if (value == null) { 2438 throw new NullPointerException(message); 2439 } 2440 return value; 2441 } 2442 2443 /** 2444 * Protect a socket from VPN routing rules. This method is used by 2445 * VpnBuilder and not available in ConnectivityManager. Permission 2446 * checks are done in Vpn class. 2447 * @hide 2448 */ 2449 @Override 2450 public void protectVpn(ParcelFileDescriptor socket) { 2451 mVpn.protect(socket, getDefaultInterface()); 2452 } 2453 2454 /** 2455 * Prepare for a VPN application. This method is used by VpnDialogs 2456 * and not available in ConnectivityManager. Permission checks are 2457 * done in Vpn class. 2458 * @hide 2459 */ 2460 @Override 2461 public String prepareVpn(String packageName) { 2462 return mVpn.prepare(packageName); 2463 } 2464 2465 /** 2466 * Configure a TUN interface and return its file descriptor. Parameters 2467 * are encoded and opaque to this class. This method is used by VpnBuilder 2468 * and not available in ConnectivityManager. Permission checks are done 2469 * in Vpn class. 2470 * @hide 2471 */ 2472 @Override 2473 public ParcelFileDescriptor establishVpn(VpnConfig config) { 2474 return mVpn.establish(config); 2475 } 2476 2477 private String getDefaultInterface() { 2478 if (ConnectivityManager.isNetworkTypeValid(mActiveDefaultNetwork)) { 2479 NetworkStateTracker tracker = mNetTrackers[mActiveDefaultNetwork]; 2480 if (tracker != null) { 2481 LinkProperties properties = tracker.getLinkProperties(); 2482 if (properties != null) { 2483 return properties.getInterfaceName(); 2484 } 2485 } 2486 } 2487 throw new IllegalStateException("No default interface"); 2488 } 2489 2490 /** 2491 * Callback for VPN subsystem. Currently VPN is not adapted to the service 2492 * through NetworkStateTracker since it works differently. For example, it 2493 * needs to override DNS servers but never takes the default routes. It 2494 * relies on another data network, and it could keep existing connections 2495 * alive after reconnecting, switching between networks, or even resuming 2496 * from deep sleep. Calls from applications should be done synchronously 2497 * to avoid race conditions. As these are all hidden APIs, refactoring can 2498 * be done whenever a better abstraction is developed. 2499 */ 2500 public class VpnCallback { 2501 2502 private VpnCallback() { 2503 } 2504 2505 public synchronized void override(String[] dnsServers) { 2506 // TODO: override DNS servers and http proxy. 2507 } 2508 2509 public synchronized void restore() { 2510 // TODO: restore VPN changes. 2511 } 2512 } 2513} 2514