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