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