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