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