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