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