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.app.Notification; 20import android.app.NotificationManager; 21import android.content.Context; 22import android.content.ContentResolver; 23import android.content.ContextWrapper; 24import android.content.Intent; 25import android.content.pm.PackageManager; 26import android.content.res.Resources; 27import android.content.res.Resources.NotFoundException; 28import android.net.ConnectivityManager; 29import android.net.IConnectivityManager; 30import android.net.MobileDataStateTracker; 31import android.net.NetworkInfo; 32import android.net.NetworkStateTracker; 33import android.net.wifi.WifiStateTracker; 34import android.net.wimax.WimaxManagerConstants; 35import android.os.Binder; 36import android.os.Handler; 37import android.os.IBinder; 38import android.os.Looper; 39import android.os.Message; 40import android.os.RemoteException; 41import android.os.ServiceManager; 42import android.os.SystemProperties; 43import android.provider.Settings; 44import android.text.TextUtils; 45import android.util.EventLog; 46import android.util.Slog; 47import com.android.internal.telephony.Phone; 48import com.android.server.connectivity.Tethering; 49import dalvik.system.DexClassLoader; 50import java.io.FileDescriptor; 51import java.io.PrintWriter; 52import java.lang.reflect.Constructor; 53import java.lang.reflect.Method; 54import java.lang.reflect.Modifier; 55import java.lang.reflect.InvocationTargetException; 56import java.util.ArrayList; 57import java.util.GregorianCalendar; 58import java.util.List; 59 60 61 62/** 63 * @hide 64 */ 65public class ConnectivityService extends IConnectivityManager.Stub { 66 67 private static final boolean DBG = false; 68 private static final String TAG = "ConnectivityService"; 69 70 // how long to wait before switching back to a radio's default network 71 private static final int RESTORE_DEFAULT_NETWORK_DELAY = 1 * 60 * 1000; 72 // system property that can override the above value 73 private static final String NETWORK_RESTORE_DELAY_PROP_NAME = 74 "android.telephony.apn-restore"; 75 76 77 private Tethering mTethering; 78 private boolean mTetheringConfigValid = false; 79 80 /** 81 * Sometimes we want to refer to the individual network state 82 * trackers separately, and sometimes we just want to treat them 83 * abstractly. 84 */ 85 private NetworkStateTracker mNetTrackers[]; 86 87 /** 88 * A per Net list of the PID's that requested access to the net 89 * used both as a refcount and for per-PID DNS selection 90 */ 91 private List mNetRequestersPids[]; 92 93 // priority order of the nettrackers 94 // (excluding dynamically set mNetworkPreference) 95 // TODO - move mNetworkTypePreference into this 96 private int[] mPriorityList; 97 98 private Context mContext; 99 private int mNetworkPreference; 100 private int mActiveDefaultNetwork = -1; 101 // 0 is full bad, 100 is full good 102 private int mDefaultInetCondition = 0; 103 private int mDefaultInetConditionPublished = 0; 104 private boolean mInetConditionChangeInFlight = false; 105 private int mDefaultConnectionSequence = 0; 106 107 private int mNumDnsEntries; 108 109 private boolean mTestMode; 110 private static ConnectivityService sServiceInstance; 111 private static final int ENABLED = 1; 112 private static final int DISABLED = 0; 113 114 // Share the event space with NetworkStateTracker (which can't see this 115 // internal class but sends us events). If you change these, change 116 // NetworkStateTracker.java too. 117 private static final int MIN_NETWORK_STATE_TRACKER_EVENT = 1; 118 private static final int MAX_NETWORK_STATE_TRACKER_EVENT = 100; 119 120 /** 121 * used internally as a delayed event to make us switch back to the 122 * default network 123 */ 124 private static final int EVENT_RESTORE_DEFAULT_NETWORK = 125 MAX_NETWORK_STATE_TRACKER_EVENT + 1; 126 127 /** 128 * used internally to change our mobile data enabled flag 129 */ 130 private static final int EVENT_CHANGE_MOBILE_DATA_ENABLED = 131 MAX_NETWORK_STATE_TRACKER_EVENT + 2; 132 133 /** 134 * used internally to change our network preference setting 135 * arg1 = networkType to prefer 136 */ 137 private static final int EVENT_SET_NETWORK_PREFERENCE = 138 MAX_NETWORK_STATE_TRACKER_EVENT + 3; 139 140 /** 141 * used internally to synchronize inet condition reports 142 * arg1 = networkType 143 * arg2 = condition (0 bad, 100 good) 144 */ 145 private static final int EVENT_INET_CONDITION_CHANGE = 146 MAX_NETWORK_STATE_TRACKER_EVENT + 4; 147 148 /** 149 * used internally to mark the end of inet condition hold periods 150 * arg1 = networkType 151 */ 152 private static final int EVENT_INET_CONDITION_HOLD_END = 153 MAX_NETWORK_STATE_TRACKER_EVENT + 5; 154 155 /** 156 * used internally to set the background data preference 157 * arg1 = TRUE for enabled, FALSE for disabled 158 */ 159 private static final int EVENT_SET_BACKGROUND_DATA = 160 MAX_NETWORK_STATE_TRACKER_EVENT + 6; 161 162 /** 163 * used internally to set enable/disable cellular data 164 * arg1 = ENBALED or DISABLED 165 */ 166 private static final int EVENT_SET_MOBILE_DATA = 167 MAX_NETWORK_STATE_TRACKER_EVENT + 7; 168 169 private Handler mHandler; 170 171 // list of DeathRecipients used to make sure features are turned off when 172 // a process dies 173 private List mFeatureUsers; 174 175 private boolean mSystemReady; 176 private Intent mInitialBroadcast; 177 178 // used in DBG mode to track inet condition reports 179 private static final int INET_CONDITION_LOG_MAX_SIZE = 15; 180 private ArrayList mInetLog; 181 182 private static class NetworkAttributes { 183 /** 184 * Class for holding settings read from resources. 185 */ 186 public String mName; 187 public int mType; 188 public int mRadio; 189 public int mPriority; 190 public NetworkInfo.State mLastState; 191 public NetworkAttributes(String init) { 192 String fragments[] = init.split(","); 193 mName = fragments[0].toLowerCase(); 194 mType = Integer.parseInt(fragments[1]); 195 mRadio = Integer.parseInt(fragments[2]); 196 mPriority = Integer.parseInt(fragments[3]); 197 mLastState = NetworkInfo.State.UNKNOWN; 198 } 199 public boolean isDefault() { 200 return (mType == mRadio); 201 } 202 } 203 NetworkAttributes[] mNetAttributes; 204 int mNetworksDefined; 205 206 private static class RadioAttributes { 207 public int mSimultaneity; 208 public int mType; 209 public RadioAttributes(String init) { 210 String fragments[] = init.split(","); 211 mType = Integer.parseInt(fragments[0]); 212 mSimultaneity = Integer.parseInt(fragments[1]); 213 } 214 } 215 RadioAttributes[] mRadioAttributes; 216 217 private static class ConnectivityThread extends Thread { 218 private Context mContext; 219 220 private ConnectivityThread(Context context) { 221 super("ConnectivityThread"); 222 mContext = context; 223 } 224 225 @Override 226 public void run() { 227 Looper.prepare(); 228 synchronized (this) { 229 sServiceInstance = new ConnectivityService(mContext); 230 notifyAll(); 231 } 232 Looper.loop(); 233 } 234 235 public static ConnectivityService getServiceInstance(Context context) { 236 ConnectivityThread thread = new ConnectivityThread(context); 237 thread.start(); 238 239 synchronized (thread) { 240 while (sServiceInstance == null) { 241 try { 242 // Wait until sServiceInstance has been initialized. 243 thread.wait(); 244 } catch (InterruptedException ignore) { 245 Slog.e(TAG, 246 "Unexpected InterruptedException while waiting"+ 247 " for ConnectivityService thread"); 248 } 249 } 250 } 251 252 return sServiceInstance; 253 } 254 } 255 256 public static ConnectivityService getInstance(Context context) { 257 return ConnectivityThread.getServiceInstance(context); 258 } 259 260 private ConnectivityService(Context context) { 261 if (DBG) Slog.v(TAG, "ConnectivityService starting up"); 262 263 // setup our unique device name 264 String id = Settings.Secure.getString(context.getContentResolver(), 265 Settings.Secure.ANDROID_ID); 266 if (id != null && id.length() > 0) { 267 String name = new String("android_").concat(id); 268 SystemProperties.set("net.hostname", name); 269 } 270 271 mContext = context; 272 mNetTrackers = new NetworkStateTracker[ 273 ConnectivityManager.MAX_NETWORK_TYPE+1]; 274 mHandler = new MyHandler(); 275 276 mNetworkPreference = getPersistedNetworkPreference(); 277 278 mRadioAttributes = new RadioAttributes[ConnectivityManager.MAX_RADIO_TYPE+1]; 279 mNetAttributes = new NetworkAttributes[ConnectivityManager.MAX_NETWORK_TYPE+1]; 280 281 // Load device network attributes from resources 282 String[] raStrings = context.getResources().getStringArray( 283 com.android.internal.R.array.radioAttributes); 284 for (String raString : raStrings) { 285 RadioAttributes r = new RadioAttributes(raString); 286 if (r.mType > ConnectivityManager.MAX_RADIO_TYPE) { 287 Slog.e(TAG, "Error in radioAttributes - ignoring attempt to define type " + r.mType); 288 continue; 289 } 290 if (mRadioAttributes[r.mType] != null) { 291 Slog.e(TAG, "Error in radioAttributes - ignoring attempt to redefine type " + 292 r.mType); 293 continue; 294 } 295 mRadioAttributes[r.mType] = r; 296 } 297 298 String[] naStrings = context.getResources().getStringArray( 299 com.android.internal.R.array.networkAttributes); 300 for (String naString : naStrings) { 301 try { 302 NetworkAttributes n = new NetworkAttributes(naString); 303 if (n.mType > ConnectivityManager.MAX_NETWORK_TYPE) { 304 Slog.e(TAG, "Error in networkAttributes - ignoring attempt to define type " + 305 n.mType); 306 continue; 307 } 308 if (mNetAttributes[n.mType] != null) { 309 Slog.e(TAG, "Error in networkAttributes - ignoring attempt to redefine type " + 310 n.mType); 311 continue; 312 } 313 if (mRadioAttributes[n.mRadio] == null) { 314 Slog.e(TAG, "Error in networkAttributes - ignoring attempt to use undefined " + 315 "radio " + n.mRadio + " in network type " + n.mType); 316 continue; 317 } 318 mNetAttributes[n.mType] = n; 319 mNetworksDefined++; 320 } catch(Exception e) { 321 // ignore it - leave the entry null 322 } 323 } 324 325 // high priority first 326 mPriorityList = new int[mNetworksDefined]; 327 { 328 int insertionPoint = mNetworksDefined-1; 329 int currentLowest = 0; 330 int nextLowest = 0; 331 while (insertionPoint > -1) { 332 for (NetworkAttributes na : mNetAttributes) { 333 if (na == null) continue; 334 if (na.mPriority < currentLowest) continue; 335 if (na.mPriority > currentLowest) { 336 if (na.mPriority < nextLowest || nextLowest == 0) { 337 nextLowest = na.mPriority; 338 } 339 continue; 340 } 341 mPriorityList[insertionPoint--] = na.mType; 342 } 343 currentLowest = nextLowest; 344 nextLowest = 0; 345 } 346 } 347 348 mNetRequestersPids = new ArrayList[ConnectivityManager.MAX_NETWORK_TYPE+1]; 349 for (int i : mPriorityList) { 350 mNetRequestersPids[i] = new ArrayList(); 351 } 352 353 mFeatureUsers = new ArrayList(); 354 355 mNumDnsEntries = 0; 356 357 mTestMode = SystemProperties.get("cm.test.mode").equals("true") 358 && SystemProperties.get("ro.build.type").equals("eng"); 359 /* 360 * Create the network state trackers for Wi-Fi and mobile 361 * data. Maybe this could be done with a factory class, 362 * but it's not clear that it's worth it, given that 363 * the number of different network types is not going 364 * to change very often. 365 */ 366 boolean noMobileData = !getMobileDataEnabled(); 367 for (int netType : mPriorityList) { 368 switch (mNetAttributes[netType].mRadio) { 369 case ConnectivityManager.TYPE_WIFI: 370 if (DBG) Slog.v(TAG, "Starting Wifi Service."); 371 WifiStateTracker wst = new WifiStateTracker(context, mHandler); 372 WifiService wifiService = new WifiService(context, wst); 373 ServiceManager.addService(Context.WIFI_SERVICE, wifiService); 374 wifiService.startWifi(); 375 mNetTrackers[ConnectivityManager.TYPE_WIFI] = wst; 376 wst.startMonitoring(); 377 378 break; 379 case ConnectivityManager.TYPE_MOBILE: 380 mNetTrackers[netType] = new MobileDataStateTracker(context, mHandler, 381 netType, mNetAttributes[netType].mName); 382 mNetTrackers[netType].startMonitoring(); 383 if (noMobileData) { 384 if (DBG) Slog.d(TAG, "tearing down Mobile networks due to setting"); 385 mNetTrackers[netType].teardown(); 386 } 387 break; 388 case ConnectivityManager.TYPE_WIMAX: 389 NetworkStateTracker nst = makeWimaxStateTracker(); 390 if (nst != null) { 391 nst.startMonitoring(); 392 } 393 mNetTrackers[netType] = nst; 394 if (noMobileData) { 395 if (DBG) Slog.d(TAG, "tearing down WiMAX networks due to setting"); 396 mNetTrackers[netType].teardown(); 397 } 398 break; 399 default: 400 Slog.e(TAG, "Trying to create a DataStateTracker for an unknown radio type " + 401 mNetAttributes[netType].mRadio); 402 continue; 403 } 404 } 405 406 mTethering = new Tethering(mContext, mHandler.getLooper()); 407 mTetheringConfigValid = (((mNetTrackers[ConnectivityManager.TYPE_MOBILE_DUN] != null) || 408 !mTethering.isDunRequired()) && 409 (mTethering.getTetherableUsbRegexs().length != 0 || 410 mTethering.getTetherableWifiRegexs().length != 0) && 411 mTethering.getUpstreamIfaceRegexs().length != 0); 412 413 if (DBG) { 414 mInetLog = new ArrayList(); 415 } 416 } 417 418 private NetworkStateTracker makeWimaxStateTracker() { 419 //Initialize Wimax 420 DexClassLoader wimaxClassLoader; 421 Class wimaxStateTrackerClass = null; 422 Class wimaxServiceClass = null; 423 Class wimaxManagerClass; 424 String wimaxJarLocation; 425 String wimaxLibLocation; 426 String wimaxManagerClassName; 427 String wimaxServiceClassName; 428 String wimaxStateTrackerClassName; 429 430 NetworkStateTracker wimaxStateTracker = null; 431 432 boolean isWimaxEnabled = mContext.getResources().getBoolean( 433 com.android.internal.R.bool.config_wimaxEnabled); 434 435 if (isWimaxEnabled) { 436 try { 437 wimaxJarLocation = mContext.getResources().getString( 438 com.android.internal.R.string.config_wimaxServiceJarLocation); 439 wimaxLibLocation = mContext.getResources().getString( 440 com.android.internal.R.string.config_wimaxNativeLibLocation); 441 wimaxManagerClassName = mContext.getResources().getString( 442 com.android.internal.R.string.config_wimaxManagerClassname); 443 wimaxServiceClassName = mContext.getResources().getString( 444 com.android.internal.R.string.config_wimaxServiceClassname); 445 wimaxStateTrackerClassName = mContext.getResources().getString( 446 com.android.internal.R.string.config_wimaxStateTrackerClassname); 447 448 wimaxClassLoader = new DexClassLoader(wimaxJarLocation, 449 new ContextWrapper(mContext).getCacheDir().getAbsolutePath(), 450 wimaxLibLocation,ClassLoader.getSystemClassLoader()); 451 452 try { 453 wimaxManagerClass = wimaxClassLoader.loadClass(wimaxManagerClassName); 454 wimaxStateTrackerClass = wimaxClassLoader.loadClass(wimaxStateTrackerClassName); 455 wimaxServiceClass = wimaxClassLoader.loadClass(wimaxServiceClassName); 456 } catch (ClassNotFoundException ex) { 457 ex.printStackTrace(); 458 return null; 459 } 460 } catch(Resources.NotFoundException ex) { 461 Slog.e(TAG, "Wimax Resources does not exist!!! "); 462 return null; 463 } 464 465 try { 466 Slog.v(TAG, "Starting Wimax Service... "); 467 468 Constructor wmxStTrkrConst = wimaxStateTrackerClass.getConstructor 469 (new Class[] {Context.class,Handler.class}); 470 wimaxStateTracker = (NetworkStateTracker)wmxStTrkrConst.newInstance(mContext,mHandler); 471 472 Constructor wmxSrvConst = wimaxServiceClass.getDeclaredConstructor 473 (new Class[] {Context.class,wimaxStateTrackerClass}); 474 wmxSrvConst.setAccessible(true); 475 IBinder svcInvoker = (IBinder) wmxSrvConst.newInstance(mContext,wimaxStateTracker); 476 wmxSrvConst.setAccessible(false); 477 478 ServiceManager.addService(WimaxManagerConstants.WIMAX_SERVICE, svcInvoker); 479 480 } catch(ClassCastException ex) { 481 ex.printStackTrace(); 482 return null; 483 } catch (NoSuchMethodException ex) { 484 ex.printStackTrace(); 485 return null; 486 } catch (InstantiationException ex) { 487 ex.printStackTrace(); 488 return null; 489 } catch(IllegalAccessException ex) { 490 ex.printStackTrace(); 491 return null; 492 } catch(InvocationTargetException ex) { 493 ex.printStackTrace(); 494 return null; 495 } catch(Exception ex) { 496 ex.printStackTrace(); 497 return null; 498 } 499 } else { 500 Slog.e(TAG, "Wimax is not enabled or not added to the network attributes!!! "); 501 return null; 502 } 503 504 return wimaxStateTracker; 505 } 506 507 /** 508 * Sets the preferred network. 509 * @param preference the new preference 510 */ 511 public void setNetworkPreference(int preference) { 512 enforceChangePermission(); 513 514 mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_NETWORK_PREFERENCE, preference, 0)); 515 } 516 517 public int getNetworkPreference() { 518 enforceAccessPermission(); 519 int preference; 520 synchronized(this) { 521 preference = mNetworkPreference; 522 } 523 return preference; 524 } 525 526 private void handleSetNetworkPreference(int preference) { 527 if (ConnectivityManager.isNetworkTypeValid(preference) && 528 mNetAttributes[preference] != null && 529 mNetAttributes[preference].isDefault()) { 530 if (mNetworkPreference != preference) { 531 final ContentResolver cr = mContext.getContentResolver(); 532 Settings.Secure.putInt(cr, Settings.Secure.NETWORK_PREFERENCE, preference); 533 synchronized(this) { 534 mNetworkPreference = preference; 535 } 536 enforcePreference(); 537 } 538 } 539 } 540 541 private int getPersistedNetworkPreference() { 542 final ContentResolver cr = mContext.getContentResolver(); 543 544 final int networkPrefSetting = Settings.Secure 545 .getInt(cr, Settings.Secure.NETWORK_PREFERENCE, -1); 546 if (networkPrefSetting != -1) { 547 return networkPrefSetting; 548 } 549 550 return ConnectivityManager.DEFAULT_NETWORK_PREFERENCE; 551 } 552 553 /** 554 * Make the state of network connectivity conform to the preference settings 555 * In this method, we only tear down a non-preferred network. Establishing 556 * a connection to the preferred network is taken care of when we handle 557 * the disconnect event from the non-preferred network 558 * (see {@link #handleDisconnect(NetworkInfo)}). 559 */ 560 private void enforcePreference() { 561 if (mNetTrackers[mNetworkPreference].getNetworkInfo().isConnected()) 562 return; 563 564 if (!mNetTrackers[mNetworkPreference].isAvailable()) 565 return; 566 567 for (int t=0; t <= ConnectivityManager.MAX_RADIO_TYPE; t++) { 568 if (t != mNetworkPreference && mNetTrackers[t] != null && 569 mNetTrackers[t].getNetworkInfo().isConnected()) { 570 if (DBG) { 571 Slog.d(TAG, "tearing down " + 572 mNetTrackers[t].getNetworkInfo() + 573 " in enforcePreference"); 574 } 575 teardown(mNetTrackers[t]); 576 } 577 } 578 } 579 580 private boolean teardown(NetworkStateTracker netTracker) { 581 if (netTracker.teardown()) { 582 netTracker.setTeardownRequested(true); 583 return true; 584 } else { 585 return false; 586 } 587 } 588 589 /** 590 * Return NetworkInfo for the active (i.e., connected) network interface. 591 * It is assumed that at most one network is active at a time. If more 592 * than one is active, it is indeterminate which will be returned. 593 * @return the info for the active network, or {@code null} if none is 594 * active 595 */ 596 public NetworkInfo getActiveNetworkInfo() { 597 enforceAccessPermission(); 598 if (mActiveDefaultNetwork != -1) { 599 return mNetTrackers[mActiveDefaultNetwork].getNetworkInfo(); 600 } 601 return null; 602 } 603 604 public NetworkInfo getNetworkInfo(int networkType) { 605 enforceAccessPermission(); 606 if (ConnectivityManager.isNetworkTypeValid(networkType)) { 607 NetworkStateTracker t = mNetTrackers[networkType]; 608 if (t != null) 609 return t.getNetworkInfo(); 610 } 611 return null; 612 } 613 614 public NetworkInfo[] getAllNetworkInfo() { 615 enforceAccessPermission(); 616 NetworkInfo[] result = new NetworkInfo[mNetworksDefined]; 617 int i = 0; 618 for (NetworkStateTracker t : mNetTrackers) { 619 if(t != null) result[i++] = t.getNetworkInfo(); 620 } 621 return result; 622 } 623 624 public boolean setRadios(boolean turnOn) { 625 boolean result = true; 626 enforceChangePermission(); 627 for (NetworkStateTracker t : mNetTrackers) { 628 if (t != null) result = t.setRadio(turnOn) && result; 629 } 630 return result; 631 } 632 633 public boolean setRadio(int netType, boolean turnOn) { 634 enforceChangePermission(); 635 if (!ConnectivityManager.isNetworkTypeValid(netType)) { 636 return false; 637 } 638 NetworkStateTracker tracker = mNetTrackers[netType]; 639 return tracker != null && tracker.setRadio(turnOn); 640 } 641 642 /** 643 * Used to notice when the calling process dies so we can self-expire 644 * 645 * Also used to know if the process has cleaned up after itself when 646 * our auto-expire timer goes off. The timer has a link to an object. 647 * 648 */ 649 private class FeatureUser implements IBinder.DeathRecipient { 650 int mNetworkType; 651 String mFeature; 652 IBinder mBinder; 653 int mPid; 654 int mUid; 655 long mCreateTime; 656 657 FeatureUser(int type, String feature, IBinder binder) { 658 super(); 659 mNetworkType = type; 660 mFeature = feature; 661 mBinder = binder; 662 mPid = getCallingPid(); 663 mUid = getCallingUid(); 664 mCreateTime = System.currentTimeMillis(); 665 666 try { 667 mBinder.linkToDeath(this, 0); 668 } catch (RemoteException e) { 669 binderDied(); 670 } 671 } 672 673 void unlinkDeathRecipient() { 674 mBinder.unlinkToDeath(this, 0); 675 } 676 677 public void binderDied() { 678 Slog.d(TAG, "ConnectivityService FeatureUser binderDied(" + 679 mNetworkType + ", " + mFeature + ", " + mBinder + "), created " + 680 (System.currentTimeMillis() - mCreateTime) + " mSec ago"); 681 stopUsingNetworkFeature(this, false); 682 } 683 684 public void expire() { 685 Slog.d(TAG, "ConnectivityService FeatureUser expire(" + 686 mNetworkType + ", " + mFeature + ", " + mBinder +"), created " + 687 (System.currentTimeMillis() - mCreateTime) + " mSec ago"); 688 stopUsingNetworkFeature(this, false); 689 } 690 691 public String toString() { 692 return "FeatureUser("+mNetworkType+","+mFeature+","+mPid+","+mUid+"), created " + 693 (System.currentTimeMillis() - mCreateTime) + " mSec ago"; 694 } 695 } 696 697 // javadoc from interface 698 public int startUsingNetworkFeature(int networkType, String feature, 699 IBinder binder) { 700 if (DBG) { 701 Slog.d(TAG, "startUsingNetworkFeature for net " + networkType + 702 ": " + feature); 703 } 704 enforceChangePermission(); 705 if (!ConnectivityManager.isNetworkTypeValid(networkType) || 706 mNetAttributes[networkType] == null) { 707 return Phone.APN_REQUEST_FAILED; 708 } 709 710 FeatureUser f = new FeatureUser(networkType, feature, binder); 711 712 // TODO - move this into the MobileDataStateTracker 713 int usedNetworkType = networkType; 714 if(networkType == ConnectivityManager.TYPE_MOBILE) { 715 if (!getMobileDataEnabled()) { 716 if (DBG) Slog.d(TAG, "requested special network with data disabled - rejected"); 717 return Phone.APN_TYPE_NOT_AVAILABLE; 718 } 719 if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_MMS)) { 720 usedNetworkType = ConnectivityManager.TYPE_MOBILE_MMS; 721 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_SUPL)) { 722 usedNetworkType = ConnectivityManager.TYPE_MOBILE_SUPL; 723 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_DUN)) { 724 usedNetworkType = ConnectivityManager.TYPE_MOBILE_DUN; 725 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_HIPRI)) { 726 usedNetworkType = ConnectivityManager.TYPE_MOBILE_HIPRI; 727 } 728 } 729 NetworkStateTracker network = mNetTrackers[usedNetworkType]; 730 if (network != null) { 731 if (usedNetworkType != networkType) { 732 Integer currentPid = new Integer(getCallingPid()); 733 734 NetworkStateTracker radio = mNetTrackers[networkType]; 735 NetworkInfo ni = network.getNetworkInfo(); 736 737 if (ni.isAvailable() == false) { 738 if (DBG) Slog.d(TAG, "special network not available"); 739 return Phone.APN_TYPE_NOT_AVAILABLE; 740 } 741 742 synchronized(this) { 743 mFeatureUsers.add(f); 744 if (!mNetRequestersPids[usedNetworkType].contains(currentPid)) { 745 // this gets used for per-pid dns when connected 746 mNetRequestersPids[usedNetworkType].add(currentPid); 747 } 748 } 749 mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_RESTORE_DEFAULT_NETWORK, 750 f), getRestoreDefaultNetworkDelay()); 751 752 753 if ((ni.isConnectedOrConnecting() == true) && 754 !network.isTeardownRequested()) { 755 if (ni.isConnected() == true) { 756 // add the pid-specific dns 757 handleDnsConfigurationChange(networkType); 758 if (DBG) Slog.d(TAG, "special network already active"); 759 return Phone.APN_ALREADY_ACTIVE; 760 } 761 if (DBG) Slog.d(TAG, "special network already connecting"); 762 return Phone.APN_REQUEST_STARTED; 763 } 764 765 // check if the radio in play can make another contact 766 // assume if cannot for now 767 768 if (DBG) Slog.d(TAG, "reconnecting to special network"); 769 network.reconnect(); 770 return Phone.APN_REQUEST_STARTED; 771 } else { 772 synchronized(this) { 773 mFeatureUsers.add(f); 774 } 775 mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_RESTORE_DEFAULT_NETWORK, 776 f), getRestoreDefaultNetworkDelay()); 777 778 return network.startUsingNetworkFeature(feature, 779 getCallingPid(), getCallingUid()); 780 } 781 } 782 return Phone.APN_TYPE_NOT_AVAILABLE; 783 } 784 785 // javadoc from interface 786 public int stopUsingNetworkFeature(int networkType, String feature) { 787 enforceChangePermission(); 788 789 int pid = getCallingPid(); 790 int uid = getCallingUid(); 791 792 FeatureUser u = null; 793 boolean found = false; 794 795 synchronized(this) { 796 for (int i = 0; i < mFeatureUsers.size() ; i++) { 797 u = (FeatureUser)mFeatureUsers.get(i); 798 if (uid == u.mUid && pid == u.mPid && 799 networkType == u.mNetworkType && 800 TextUtils.equals(feature, u.mFeature)) { 801 found = true; 802 break; 803 } 804 } 805 } 806 if (found && u != null) { 807 // stop regardless of how many other time this proc had called start 808 return stopUsingNetworkFeature(u, true); 809 } else { 810 // none found! 811 if (DBG) Slog.d(TAG, "ignoring stopUsingNetworkFeature - not a live request"); 812 return 1; 813 } 814 } 815 816 private int stopUsingNetworkFeature(FeatureUser u, boolean ignoreDups) { 817 int networkType = u.mNetworkType; 818 String feature = u.mFeature; 819 int pid = u.mPid; 820 int uid = u.mUid; 821 822 NetworkStateTracker tracker = null; 823 boolean callTeardown = false; // used to carry our decision outside of sync block 824 825 if (DBG) { 826 Slog.d(TAG, "stopUsingNetworkFeature for net " + networkType + 827 ": " + feature); 828 } 829 830 if (!ConnectivityManager.isNetworkTypeValid(networkType)) { 831 return -1; 832 } 833 834 // need to link the mFeatureUsers list with the mNetRequestersPids state in this 835 // sync block 836 synchronized(this) { 837 // check if this process still has an outstanding start request 838 if (!mFeatureUsers.contains(u)) { 839 if (DBG) Slog.d(TAG, "ignoring - this process has no outstanding requests"); 840 return 1; 841 } 842 u.unlinkDeathRecipient(); 843 mFeatureUsers.remove(mFeatureUsers.indexOf(u)); 844 // If we care about duplicate requests, check for that here. 845 // 846 // This is done to support the extension of a request - the app 847 // can request we start the network feature again and renew the 848 // auto-shutoff delay. Normal "stop" calls from the app though 849 // do not pay attention to duplicate requests - in effect the 850 // API does not refcount and a single stop will counter multiple starts. 851 if (ignoreDups == false) { 852 for (int i = 0; i < mFeatureUsers.size() ; i++) { 853 FeatureUser x = (FeatureUser)mFeatureUsers.get(i); 854 if (x.mUid == u.mUid && x.mPid == u.mPid && 855 x.mNetworkType == u.mNetworkType && 856 TextUtils.equals(x.mFeature, u.mFeature)) { 857 if (DBG) Slog.d(TAG, "ignoring stopUsingNetworkFeature as dup is found"); 858 return 1; 859 } 860 } 861 } 862 863 // TODO - move to MobileDataStateTracker 864 int usedNetworkType = networkType; 865 if (networkType == ConnectivityManager.TYPE_MOBILE) { 866 if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_MMS)) { 867 usedNetworkType = ConnectivityManager.TYPE_MOBILE_MMS; 868 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_SUPL)) { 869 usedNetworkType = ConnectivityManager.TYPE_MOBILE_SUPL; 870 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_DUN)) { 871 usedNetworkType = ConnectivityManager.TYPE_MOBILE_DUN; 872 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_HIPRI)) { 873 usedNetworkType = ConnectivityManager.TYPE_MOBILE_HIPRI; 874 } 875 } 876 tracker = mNetTrackers[usedNetworkType]; 877 if (tracker == null) { 878 if (DBG) Slog.d(TAG, "ignoring - no known tracker for net type " + usedNetworkType); 879 return -1; 880 } 881 if (usedNetworkType != networkType) { 882 Integer currentPid = new Integer(pid); 883 mNetRequestersPids[usedNetworkType].remove(currentPid); 884 reassessPidDns(pid, true); 885 if (mNetRequestersPids[usedNetworkType].size() != 0) { 886 if (DBG) Slog.d(TAG, "not tearing down special network - " + 887 "others still using it"); 888 return 1; 889 } 890 callTeardown = true; 891 } 892 } 893 if (DBG) Slog.d(TAG, "Doing network teardown"); 894 if (callTeardown) { 895 tracker.teardown(); 896 return 1; 897 } else { 898 // do it the old fashioned way 899 return tracker.stopUsingNetworkFeature(feature, pid, uid); 900 } 901 } 902 903 /** 904 * Ensure that a network route exists to deliver traffic to the specified 905 * host via the specified network interface. 906 * @param networkType the type of the network over which traffic to the 907 * specified host is to be routed 908 * @param hostAddress the IP address of the host to which the route is 909 * desired 910 * @return {@code true} on success, {@code false} on failure 911 */ 912 public boolean requestRouteToHost(int networkType, int hostAddress) { 913 enforceChangePermission(); 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 Slog.d(TAG, "requestRouteToHost on down network (" + networkType + ") - dropped"); 923 } 924 return false; 925 } 926 return tracker.requestRouteToHost(hostAddress); 927 } 928 929 /** 930 * @see ConnectivityManager#getBackgroundDataSetting() 931 */ 932 public boolean getBackgroundDataSetting() { 933 return Settings.Secure.getInt(mContext.getContentResolver(), 934 Settings.Secure.BACKGROUND_DATA, 1) == 1; 935 } 936 937 /** 938 * @see ConnectivityManager#setBackgroundDataSetting(boolean) 939 */ 940 public void setBackgroundDataSetting(boolean allowBackgroundDataUsage) { 941 mContext.enforceCallingOrSelfPermission( 942 android.Manifest.permission.CHANGE_BACKGROUND_DATA_SETTING, 943 "ConnectivityService"); 944 945 mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_BACKGROUND_DATA, 946 (allowBackgroundDataUsage ? ENABLED : DISABLED), 0)); 947 } 948 949 private void handleSetBackgroundData(boolean enabled) { 950 if (enabled != getBackgroundDataSetting()) { 951 Settings.Secure.putInt(mContext.getContentResolver(), 952 Settings.Secure.BACKGROUND_DATA, enabled ? 1 : 0); 953 Intent broadcast = new Intent( 954 ConnectivityManager.ACTION_BACKGROUND_DATA_SETTING_CHANGED); 955 mContext.sendBroadcast(broadcast); 956 } 957 } 958 959 /** 960 * @see ConnectivityManager#getMobileDataEnabled() 961 */ 962 public boolean getMobileDataEnabled() { 963 enforceAccessPermission(); 964 boolean retVal = Settings.Secure.getInt(mContext.getContentResolver(), 965 Settings.Secure.MOBILE_DATA, 1) == 1; 966 if (DBG) Slog.d(TAG, "getMobileDataEnabled returning " + retVal); 967 return retVal; 968 } 969 970 /** 971 * @see ConnectivityManager#setMobileDataEnabled(boolean) 972 */ 973 public void setMobileDataEnabled(boolean enabled) { 974 enforceChangePermission(); 975 if (DBG) Slog.d(TAG, "setMobileDataEnabled(" + enabled + ")"); 976 977 mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_MOBILE_DATA, 978 (enabled ? ENABLED : DISABLED), 0)); 979 } 980 981 private void handleSetMobileData(boolean enabled) { 982 if (getMobileDataEnabled() == enabled) return; 983 984 Settings.Secure.putInt(mContext.getContentResolver(), 985 Settings.Secure.MOBILE_DATA, enabled ? 1 : 0); 986 987 if (enabled) { 988 if (mNetTrackers[ConnectivityManager.TYPE_MOBILE] != null) { 989 if (DBG) { 990 Slog.d(TAG, "starting up " + mNetTrackers[ConnectivityManager.TYPE_MOBILE]); 991 } 992 mNetTrackers[ConnectivityManager.TYPE_MOBILE].reconnect(); 993 } 994 if (mNetTrackers[ConnectivityManager.TYPE_WIMAX] != null) { 995 if (DBG) { 996 Slog.d(TAG, "starting up " + mNetTrackers[ConnectivityManager.TYPE_WIMAX]); 997 } 998 mNetTrackers[ConnectivityManager.TYPE_WIMAX].reconnect(); 999 } 1000 } else { 1001 for (NetworkStateTracker nt : mNetTrackers) { 1002 if (nt == null) continue; 1003 int netType = nt.getNetworkInfo().getType(); 1004 if (mNetAttributes[netType].mRadio == ConnectivityManager.TYPE_MOBILE) { 1005 if (DBG) Slog.d(TAG, "tearing down " + nt); 1006 nt.teardown(); 1007 } 1008 } 1009 if (mNetTrackers[ConnectivityManager.TYPE_WIMAX] != null) { 1010 mNetTrackers[ConnectivityManager.TYPE_WIMAX].teardown(); 1011 } 1012 } 1013 } 1014 1015 private int getNumConnectedNetworks() { 1016 int numConnectedNets = 0; 1017 1018 for (NetworkStateTracker nt : mNetTrackers) { 1019 if (nt != null && nt.getNetworkInfo().isConnected() && 1020 !nt.isTeardownRequested()) { 1021 ++numConnectedNets; 1022 } 1023 } 1024 return numConnectedNets; 1025 } 1026 1027 private void enforceAccessPermission() { 1028 mContext.enforceCallingOrSelfPermission( 1029 android.Manifest.permission.ACCESS_NETWORK_STATE, 1030 "ConnectivityService"); 1031 } 1032 1033 private void enforceChangePermission() { 1034 mContext.enforceCallingOrSelfPermission( 1035 android.Manifest.permission.CHANGE_NETWORK_STATE, 1036 "ConnectivityService"); 1037 } 1038 1039 // TODO Make this a special check when it goes public 1040 private void enforceTetherChangePermission() { 1041 mContext.enforceCallingOrSelfPermission( 1042 android.Manifest.permission.CHANGE_NETWORK_STATE, 1043 "ConnectivityService"); 1044 } 1045 1046 private void enforceTetherAccessPermission() { 1047 mContext.enforceCallingOrSelfPermission( 1048 android.Manifest.permission.ACCESS_NETWORK_STATE, 1049 "ConnectivityService"); 1050 } 1051 1052 /** 1053 * Handle a {@code DISCONNECTED} event. If this pertains to the non-active 1054 * network, we ignore it. If it is for the active network, we send out a 1055 * broadcast. But first, we check whether it might be possible to connect 1056 * to a different network. 1057 * @param info the {@code NetworkInfo} for the network 1058 */ 1059 private void handleDisconnect(NetworkInfo info) { 1060 1061 int prevNetType = info.getType(); 1062 1063 mNetTrackers[prevNetType].setTeardownRequested(false); 1064 /* 1065 * If the disconnected network is not the active one, then don't report 1066 * this as a loss of connectivity. What probably happened is that we're 1067 * getting the disconnect for a network that we explicitly disabled 1068 * in accordance with network preference policies. 1069 */ 1070 if (!mNetAttributes[prevNetType].isDefault()) { 1071 List pids = mNetRequestersPids[prevNetType]; 1072 for (int i = 0; i<pids.size(); i++) { 1073 Integer pid = (Integer)pids.get(i); 1074 // will remove them because the net's no longer connected 1075 // need to do this now as only now do we know the pids and 1076 // can properly null things that are no longer referenced. 1077 reassessPidDns(pid.intValue(), false); 1078 } 1079 } 1080 1081 Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION); 1082 intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info); 1083 if (info.isFailover()) { 1084 intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true); 1085 info.setFailover(false); 1086 } 1087 if (info.getReason() != null) { 1088 intent.putExtra(ConnectivityManager.EXTRA_REASON, info.getReason()); 1089 } 1090 if (info.getExtraInfo() != null) { 1091 intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO, 1092 info.getExtraInfo()); 1093 } 1094 1095 if (mNetAttributes[prevNetType].isDefault()) { 1096 tryFailover(prevNetType); 1097 if (mActiveDefaultNetwork != -1) { 1098 NetworkInfo switchTo = mNetTrackers[mActiveDefaultNetwork].getNetworkInfo(); 1099 intent.putExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO, switchTo); 1100 } else { 1101 mDefaultInetConditionPublished = 0; // we're not connected anymore 1102 intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true); 1103 } 1104 } 1105 intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION, mDefaultInetConditionPublished); 1106 // do this before we broadcast the change 1107 handleConnectivityChange(prevNetType); 1108 1109 sendStickyBroadcast(intent); 1110 /* 1111 * If the failover network is already connected, then immediately send 1112 * out a followup broadcast indicating successful failover 1113 */ 1114 if (mActiveDefaultNetwork != -1) { 1115 sendConnectedBroadcast(mNetTrackers[mActiveDefaultNetwork].getNetworkInfo()); 1116 } 1117 } 1118 1119 private void tryFailover(int prevNetType) { 1120 /* 1121 * If this is a default network, check if other defaults are available 1122 * or active 1123 */ 1124 if (mNetAttributes[prevNetType].isDefault()) { 1125 if (mActiveDefaultNetwork == prevNetType) { 1126 mActiveDefaultNetwork = -1; 1127 } 1128 1129 boolean noMobileData = !getMobileDataEnabled(); 1130 for (int checkType=0; checkType <= ConnectivityManager.MAX_NETWORK_TYPE; checkType++) { 1131 if (checkType == prevNetType) continue; 1132 if (mNetAttributes[checkType] == null) continue; 1133 if (mNetAttributes[checkType].isDefault() == false) continue; 1134 if (mNetAttributes[checkType].mRadio == ConnectivityManager.TYPE_MOBILE && 1135 noMobileData) { 1136 Slog.e(TAG, "not failing over to mobile type " + checkType + 1137 " because Mobile Data Disabled"); 1138 continue; 1139 } 1140 if (mNetAttributes[checkType].mRadio == ConnectivityManager.TYPE_WIMAX && 1141 noMobileData) { 1142 Slog.e(TAG, "not failing over to mobile type " + checkType + 1143 " because Mobile Data Disabled"); 1144 continue; 1145 } 1146 NetworkStateTracker checkTracker = mNetTrackers[checkType]; 1147 NetworkInfo checkInfo = checkTracker.getNetworkInfo(); 1148 if (!checkInfo.isConnectedOrConnecting() || checkTracker.isTeardownRequested()) { 1149 checkInfo.setFailover(true); 1150 checkTracker.reconnect(); 1151 } 1152 if (DBG) Slog.d(TAG, "Attempting to switch to " + checkInfo.getTypeName()); 1153 } 1154 } 1155 } 1156 1157 private void sendConnectedBroadcast(NetworkInfo info) { 1158 sendGeneralBroadcast(info, ConnectivityManager.CONNECTIVITY_ACTION); 1159 } 1160 1161 private void sendInetConditionBroadcast(NetworkInfo info) { 1162 sendGeneralBroadcast(info, ConnectivityManager.INET_CONDITION_ACTION); 1163 } 1164 1165 private void sendGeneralBroadcast(NetworkInfo info, String bcastType) { 1166 Intent intent = new Intent(bcastType); 1167 intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info); 1168 if (info.isFailover()) { 1169 intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true); 1170 info.setFailover(false); 1171 } 1172 if (info.getReason() != null) { 1173 intent.putExtra(ConnectivityManager.EXTRA_REASON, info.getReason()); 1174 } 1175 if (info.getExtraInfo() != null) { 1176 intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO, 1177 info.getExtraInfo()); 1178 } 1179 intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION, mDefaultInetConditionPublished); 1180 sendStickyBroadcast(intent); 1181 } 1182 1183 /** 1184 * Called when an attempt to fail over to another network has failed. 1185 * @param info the {@link NetworkInfo} for the failed network 1186 */ 1187 private void handleConnectionFailure(NetworkInfo info) { 1188 mNetTrackers[info.getType()].setTeardownRequested(false); 1189 1190 String reason = info.getReason(); 1191 String extraInfo = info.getExtraInfo(); 1192 1193 String reasonText; 1194 if (reason == null) { 1195 reasonText = "."; 1196 } else { 1197 reasonText = " (" + reason + ")."; 1198 } 1199 Slog.e(TAG, "Attempt to connect to " + info.getTypeName() + " failed" + reasonText); 1200 1201 Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION); 1202 intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info); 1203 if (getActiveNetworkInfo() == null) { 1204 intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true); 1205 } 1206 if (reason != null) { 1207 intent.putExtra(ConnectivityManager.EXTRA_REASON, reason); 1208 } 1209 if (extraInfo != null) { 1210 intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO, extraInfo); 1211 } 1212 if (info.isFailover()) { 1213 intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true); 1214 info.setFailover(false); 1215 } 1216 1217 if (mNetAttributes[info.getType()].isDefault()) { 1218 tryFailover(info.getType()); 1219 if (mActiveDefaultNetwork != -1) { 1220 NetworkInfo switchTo = mNetTrackers[mActiveDefaultNetwork].getNetworkInfo(); 1221 intent.putExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO, switchTo); 1222 } else { 1223 mDefaultInetConditionPublished = 0; 1224 intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true); 1225 } 1226 } 1227 1228 intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION, mDefaultInetConditionPublished); 1229 sendStickyBroadcast(intent); 1230 /* 1231 * If the failover network is already connected, then immediately send 1232 * out a followup broadcast indicating successful failover 1233 */ 1234 if (mActiveDefaultNetwork != -1) { 1235 sendConnectedBroadcast(mNetTrackers[mActiveDefaultNetwork].getNetworkInfo()); 1236 } 1237 } 1238 1239 private void sendStickyBroadcast(Intent intent) { 1240 synchronized(this) { 1241 if (!mSystemReady) { 1242 mInitialBroadcast = new Intent(intent); 1243 } 1244 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 1245 mContext.sendStickyBroadcast(intent); 1246 } 1247 } 1248 1249 void systemReady() { 1250 synchronized(this) { 1251 mSystemReady = true; 1252 if (mInitialBroadcast != null) { 1253 mContext.sendStickyBroadcast(mInitialBroadcast); 1254 mInitialBroadcast = null; 1255 } 1256 } 1257 } 1258 1259 private void handleConnect(NetworkInfo info) { 1260 int type = info.getType(); 1261 1262 // snapshot isFailover, because sendConnectedBroadcast() resets it 1263 boolean isFailover = info.isFailover(); 1264 NetworkStateTracker thisNet = mNetTrackers[type]; 1265 1266 // if this is a default net and other default is running 1267 // kill the one not preferred 1268 if (mNetAttributes[type].isDefault()) { 1269 if (mActiveDefaultNetwork != -1 && mActiveDefaultNetwork != type) { 1270 if ((type != mNetworkPreference && 1271 mNetAttributes[mActiveDefaultNetwork].mPriority > 1272 mNetAttributes[type].mPriority) || 1273 mNetworkPreference == mActiveDefaultNetwork) { 1274 // don't accept this one 1275 if (DBG) Slog.v(TAG, "Not broadcasting CONNECT_ACTION " + 1276 "to torn down network " + info.getTypeName()); 1277 teardown(thisNet); 1278 return; 1279 } else { 1280 // tear down the other 1281 NetworkStateTracker otherNet = 1282 mNetTrackers[mActiveDefaultNetwork]; 1283 if (DBG) Slog.v(TAG, "Policy requires " + 1284 otherNet.getNetworkInfo().getTypeName() + 1285 " teardown"); 1286 if (!teardown(otherNet)) { 1287 Slog.e(TAG, "Network declined teardown request"); 1288 teardown(thisNet); 1289 return; 1290 } 1291 if (isFailover) { 1292 otherNet.releaseWakeLock(); 1293 } 1294 } 1295 } 1296 mActiveDefaultNetwork = type; 1297 // this will cause us to come up initially as unconnected and switching 1298 // to connected after our normal pause unless somebody reports us as reall 1299 // disconnected 1300 mDefaultInetConditionPublished = 0; 1301 mDefaultConnectionSequence++; 1302 mInetConditionChangeInFlight = false; 1303 // Don't do this - if we never sign in stay, grey 1304 //reportNetworkCondition(mActiveDefaultNetwork, 100); 1305 } 1306 thisNet.setTeardownRequested(false); 1307 thisNet.updateNetworkSettings(); 1308 handleConnectivityChange(type); 1309 sendConnectedBroadcast(info); 1310 } 1311 1312 private void handleScanResultsAvailable(NetworkInfo info) { 1313 int networkType = info.getType(); 1314 if (networkType != ConnectivityManager.TYPE_WIFI) { 1315 if (DBG) Slog.v(TAG, "Got ScanResultsAvailable for " + 1316 info.getTypeName() + " network. Don't know how to handle."); 1317 } 1318 1319 mNetTrackers[networkType].interpretScanResultsAvailable(); 1320 } 1321 1322 private void handleNotificationChange(boolean visible, int id, 1323 Notification notification) { 1324 NotificationManager notificationManager = (NotificationManager) mContext 1325 .getSystemService(Context.NOTIFICATION_SERVICE); 1326 1327 if (visible) { 1328 notificationManager.notify(id, notification); 1329 } else { 1330 notificationManager.cancel(id); 1331 } 1332 } 1333 1334 /** 1335 * After a change in the connectivity state of any network, We're mainly 1336 * concerned with making sure that the list of DNS servers is setupup 1337 * according to which networks are connected, and ensuring that the 1338 * right routing table entries exist. 1339 */ 1340 private void handleConnectivityChange(int netType) { 1341 /* 1342 * If a non-default network is enabled, add the host routes that 1343 * will allow it's DNS servers to be accessed. 1344 */ 1345 handleDnsConfigurationChange(netType); 1346 1347 if (mNetTrackers[netType].getNetworkInfo().isConnected()) { 1348 if (mNetAttributes[netType].isDefault()) { 1349 mNetTrackers[netType].addDefaultRoute(); 1350 } else { 1351 // many radios add a default route even when we don't want one. 1352 // remove the default interface unless we need it for our active network 1353 if (mActiveDefaultNetwork != -1) { 1354 String defaultIface = mNetTrackers[mActiveDefaultNetwork].getInterfaceName(); 1355 if (defaultIface != null && 1356 !defaultIface.equals(mNetTrackers[netType].getInterfaceName())) { 1357 mNetTrackers[netType].removeDefaultRoute(); 1358 } 1359 } 1360 mNetTrackers[netType].addPrivateDnsRoutes(); 1361 } 1362 } else { 1363 if (mNetAttributes[netType].isDefault()) { 1364 mNetTrackers[netType].removeDefaultRoute(); 1365 } else { 1366 mNetTrackers[netType].removePrivateDnsRoutes(); 1367 } 1368 } 1369 } 1370 1371 /** 1372 * Adjust the per-process dns entries (net.dns<x>.<pid>) based 1373 * on the highest priority active net which this process requested. 1374 * If there aren't any, clear it out 1375 */ 1376 private void reassessPidDns(int myPid, boolean doBump) 1377 { 1378 if (DBG) Slog.d(TAG, "reassessPidDns for pid " + myPid); 1379 for(int i : mPriorityList) { 1380 if (mNetAttributes[i].isDefault()) { 1381 continue; 1382 } 1383 NetworkStateTracker nt = mNetTrackers[i]; 1384 if (nt.getNetworkInfo().isConnected() && 1385 !nt.isTeardownRequested()) { 1386 List pids = mNetRequestersPids[i]; 1387 for (int j=0; j<pids.size(); j++) { 1388 Integer pid = (Integer)pids.get(j); 1389 if (pid.intValue() == myPid) { 1390 String[] dnsList = nt.getNameServers(); 1391 writePidDns(dnsList, myPid); 1392 if (doBump) { 1393 bumpDns(); 1394 } 1395 return; 1396 } 1397 } 1398 } 1399 } 1400 // nothing found - delete 1401 for (int i = 1; ; i++) { 1402 String prop = "net.dns" + i + "." + myPid; 1403 if (SystemProperties.get(prop).length() == 0) { 1404 if (doBump) { 1405 bumpDns(); 1406 } 1407 return; 1408 } 1409 SystemProperties.set(prop, ""); 1410 } 1411 } 1412 1413 private void writePidDns(String[] dnsList, int pid) { 1414 int j = 1; 1415 for (String dns : dnsList) { 1416 if (dns != null && !TextUtils.equals(dns, "0.0.0.0")) { 1417 SystemProperties.set("net.dns" + j++ + "." + pid, dns); 1418 } 1419 } 1420 } 1421 1422 private void bumpDns() { 1423 /* 1424 * Bump the property that tells the name resolver library to reread 1425 * the DNS server list from the properties. 1426 */ 1427 String propVal = SystemProperties.get("net.dnschange"); 1428 int n = 0; 1429 if (propVal.length() != 0) { 1430 try { 1431 n = Integer.parseInt(propVal); 1432 } catch (NumberFormatException e) {} 1433 } 1434 SystemProperties.set("net.dnschange", "" + (n+1)); 1435 } 1436 1437 private void handleDnsConfigurationChange(int netType) { 1438 // add default net's dns entries 1439 NetworkStateTracker nt = mNetTrackers[netType]; 1440 if (nt != null && nt.getNetworkInfo().isConnected() && !nt.isTeardownRequested()) { 1441 String[] dnsList = nt.getNameServers(); 1442 if (mNetAttributes[netType].isDefault()) { 1443 int j = 1; 1444 for (String dns : dnsList) { 1445 if (dns != null && !TextUtils.equals(dns, "0.0.0.0")) { 1446 if (DBG) { 1447 Slog.d(TAG, "adding dns " + dns + " for " + 1448 nt.getNetworkInfo().getTypeName()); 1449 } 1450 SystemProperties.set("net.dns" + j++, dns); 1451 } 1452 } 1453 for (int k=j ; k<mNumDnsEntries; k++) { 1454 if (DBG) Slog.d(TAG, "erasing net.dns" + k); 1455 SystemProperties.set("net.dns" + k, ""); 1456 } 1457 mNumDnsEntries = j; 1458 } else { 1459 // set per-pid dns for attached secondary nets 1460 List pids = mNetRequestersPids[netType]; 1461 for (int y=0; y< pids.size(); y++) { 1462 Integer pid = (Integer)pids.get(y); 1463 writePidDns(dnsList, pid.intValue()); 1464 } 1465 } 1466 } 1467 bumpDns(); 1468 } 1469 1470 private int getRestoreDefaultNetworkDelay() { 1471 String restoreDefaultNetworkDelayStr = SystemProperties.get( 1472 NETWORK_RESTORE_DELAY_PROP_NAME); 1473 if(restoreDefaultNetworkDelayStr != null && 1474 restoreDefaultNetworkDelayStr.length() != 0) { 1475 try { 1476 return Integer.valueOf(restoreDefaultNetworkDelayStr); 1477 } catch (NumberFormatException e) { 1478 } 1479 } 1480 return RESTORE_DEFAULT_NETWORK_DELAY; 1481 } 1482 1483 @Override 1484 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1485 if (mContext.checkCallingOrSelfPermission( 1486 android.Manifest.permission.DUMP) 1487 != PackageManager.PERMISSION_GRANTED) { 1488 pw.println("Permission Denial: can't dump ConnectivityService " + 1489 "from from pid=" + Binder.getCallingPid() + ", uid=" + 1490 Binder.getCallingUid()); 1491 return; 1492 } 1493 pw.println(); 1494 for (NetworkStateTracker nst : mNetTrackers) { 1495 if (nst != null) { 1496 if (nst.getNetworkInfo().isConnected()) { 1497 pw.println("Active network: " + nst.getNetworkInfo(). 1498 getTypeName()); 1499 } 1500 pw.println(nst.getNetworkInfo()); 1501 pw.println(nst); 1502 pw.println(); 1503 } 1504 } 1505 1506 pw.println("Network Requester Pids:"); 1507 for (int net : mPriorityList) { 1508 String pidString = net + ": "; 1509 for (Object pid : mNetRequestersPids[net]) { 1510 pidString = pidString + pid.toString() + ", "; 1511 } 1512 pw.println(pidString); 1513 } 1514 pw.println(); 1515 1516 pw.println("FeatureUsers:"); 1517 for (Object requester : mFeatureUsers) { 1518 pw.println(requester.toString()); 1519 } 1520 pw.println(); 1521 1522 mTethering.dump(fd, pw, args); 1523 1524 if (mInetLog != null) { 1525 pw.println(); 1526 pw.println("Inet condition reports:"); 1527 for(int i = 0; i < mInetLog.size(); i++) { 1528 pw.println(mInetLog.get(i)); 1529 } 1530 } 1531 } 1532 1533 // must be stateless - things change under us. 1534 private class MyHandler extends Handler { 1535 @Override 1536 public void handleMessage(Message msg) { 1537 NetworkInfo info; 1538 switch (msg.what) { 1539 case NetworkStateTracker.EVENT_STATE_CHANGED: 1540 info = (NetworkInfo) msg.obj; 1541 int type = info.getType(); 1542 NetworkInfo.State state = info.getState(); 1543 // only do this optimization for wifi. It going into scan mode for location 1544 // services generates alot of noise. Meanwhile the mms apn won't send out 1545 // subsequent notifications when on default cellular because it never 1546 // disconnects.. so only do this to wifi notifications. Fixed better when the 1547 // APN notifications are standardized. 1548 if (mNetAttributes[type].mLastState == state && 1549 mNetAttributes[type].mRadio == ConnectivityManager.TYPE_WIFI) { 1550 if (DBG) { 1551 // TODO - remove this after we validate the dropping doesn't break 1552 // anything 1553 Slog.d(TAG, "Dropping ConnectivityChange for " + 1554 info.getTypeName() + ": " + 1555 state + "/" + info.getDetailedState()); 1556 } 1557 return; 1558 } 1559 mNetAttributes[type].mLastState = state; 1560 1561 if (DBG) Slog.d(TAG, "ConnectivityChange for " + 1562 info.getTypeName() + ": " + 1563 state + "/" + info.getDetailedState()); 1564 1565 // Connectivity state changed: 1566 // [31-13] Reserved for future use 1567 // [12-9] Network subtype (for mobile network, as defined 1568 // by TelephonyManager) 1569 // [8-3] Detailed state ordinal (as defined by 1570 // NetworkInfo.DetailedState) 1571 // [2-0] Network type (as defined by ConnectivityManager) 1572 int eventLogParam = (info.getType() & 0x7) | 1573 ((info.getDetailedState().ordinal() & 0x3f) << 3) | 1574 (info.getSubtype() << 9); 1575 EventLog.writeEvent(EventLogTags.CONNECTIVITY_STATE_CHANGED, 1576 eventLogParam); 1577 1578 if (info.getDetailedState() == 1579 NetworkInfo.DetailedState.FAILED) { 1580 handleConnectionFailure(info); 1581 } else if (state == NetworkInfo.State.DISCONNECTED) { 1582 handleDisconnect(info); 1583 } else if (state == NetworkInfo.State.SUSPENDED) { 1584 // TODO: need to think this over. 1585 // the logic here is, handle SUSPENDED the same as 1586 // DISCONNECTED. The only difference being we are 1587 // broadcasting an intent with NetworkInfo that's 1588 // suspended. This allows the applications an 1589 // opportunity to handle DISCONNECTED and SUSPENDED 1590 // differently, or not. 1591 handleDisconnect(info); 1592 } else if (state == NetworkInfo.State.CONNECTED) { 1593 handleConnect(info); 1594 } 1595 break; 1596 1597 case NetworkStateTracker.EVENT_SCAN_RESULTS_AVAILABLE: 1598 info = (NetworkInfo) msg.obj; 1599 handleScanResultsAvailable(info); 1600 break; 1601 1602 case NetworkStateTracker.EVENT_NOTIFICATION_CHANGED: 1603 handleNotificationChange(msg.arg1 == 1, msg.arg2, 1604 (Notification) msg.obj); 1605 break; 1606 1607 case NetworkStateTracker.EVENT_CONFIGURATION_CHANGED: 1608 info = (NetworkInfo) msg.obj; 1609 type = info.getType(); 1610 handleDnsConfigurationChange(type); 1611 break; 1612 1613 case NetworkStateTracker.EVENT_ROAMING_CHANGED: 1614 // fill me in 1615 break; 1616 1617 case NetworkStateTracker.EVENT_NETWORK_SUBTYPE_CHANGED: 1618 // fill me in 1619 break; 1620 case EVENT_RESTORE_DEFAULT_NETWORK: 1621 FeatureUser u = (FeatureUser)msg.obj; 1622 u.expire(); 1623 break; 1624 case EVENT_INET_CONDITION_CHANGE: 1625 { 1626 int netType = msg.arg1; 1627 int condition = msg.arg2; 1628 handleInetConditionChange(netType, condition); 1629 break; 1630 } 1631 case EVENT_INET_CONDITION_HOLD_END: 1632 { 1633 int netType = msg.arg1; 1634 int sequence = msg.arg2; 1635 handleInetConditionHoldEnd(netType, sequence); 1636 break; 1637 } 1638 case EVENT_SET_NETWORK_PREFERENCE: 1639 { 1640 int preference = msg.arg1; 1641 handleSetNetworkPreference(preference); 1642 break; 1643 } 1644 case EVENT_SET_BACKGROUND_DATA: 1645 { 1646 boolean enabled = (msg.arg1 == ENABLED); 1647 handleSetBackgroundData(enabled); 1648 break; 1649 } 1650 case EVENT_SET_MOBILE_DATA: 1651 { 1652 boolean enabled = (msg.arg1 == ENABLED); 1653 handleSetMobileData(enabled); 1654 break; 1655 } 1656 } 1657 } 1658 } 1659 1660 // javadoc from interface 1661 public int tether(String iface) { 1662 enforceTetherChangePermission(); 1663 1664 if (isTetheringSupported()) { 1665 return mTethering.tether(iface); 1666 } else { 1667 return ConnectivityManager.TETHER_ERROR_UNSUPPORTED; 1668 } 1669 } 1670 1671 // javadoc from interface 1672 public int untether(String iface) { 1673 enforceTetherChangePermission(); 1674 1675 if (isTetheringSupported()) { 1676 return mTethering.untether(iface); 1677 } else { 1678 return ConnectivityManager.TETHER_ERROR_UNSUPPORTED; 1679 } 1680 } 1681 1682 // javadoc from interface 1683 public int getLastTetherError(String iface) { 1684 enforceTetherAccessPermission(); 1685 1686 if (isTetheringSupported()) { 1687 return mTethering.getLastTetherError(iface); 1688 } else { 1689 return ConnectivityManager.TETHER_ERROR_UNSUPPORTED; 1690 } 1691 } 1692 1693 // TODO - proper iface API for selection by property, inspection, etc 1694 public String[] getTetherableUsbRegexs() { 1695 enforceTetherAccessPermission(); 1696 if (isTetheringSupported()) { 1697 return mTethering.getTetherableUsbRegexs(); 1698 } else { 1699 return new String[0]; 1700 } 1701 } 1702 1703 public String[] getTetherableWifiRegexs() { 1704 enforceTetherAccessPermission(); 1705 if (isTetheringSupported()) { 1706 return mTethering.getTetherableWifiRegexs(); 1707 } else { 1708 return new String[0]; 1709 } 1710 } 1711 1712 // TODO - move iface listing, queries, etc to new module 1713 // javadoc from interface 1714 public String[] getTetherableIfaces() { 1715 enforceTetherAccessPermission(); 1716 return mTethering.getTetherableIfaces(); 1717 } 1718 1719 public String[] getTetheredIfaces() { 1720 enforceTetherAccessPermission(); 1721 return mTethering.getTetheredIfaces(); 1722 } 1723 1724 public String[] getTetheringErroredIfaces() { 1725 enforceTetherAccessPermission(); 1726 return mTethering.getErroredIfaces(); 1727 } 1728 1729 // if ro.tether.denied = true we default to no tethering 1730 // gservices could set the secure setting to 1 though to enable it on a build where it 1731 // had previously been turned off. 1732 public boolean isTetheringSupported() { 1733 enforceTetherAccessPermission(); 1734 int defaultVal = (SystemProperties.get("ro.tether.denied").equals("true") ? 0 : 1); 1735 boolean tetherEnabledInSettings = (Settings.Secure.getInt(mContext.getContentResolver(), 1736 Settings.Secure.TETHER_SUPPORTED, defaultVal) != 0); 1737 return tetherEnabledInSettings && mTetheringConfigValid; 1738 } 1739 1740 // 100 percent is full good, 0 is full bad. 1741 public void reportInetCondition(int networkType, int percentage) { 1742 if (DBG) Slog.d(TAG, "reportNetworkCondition(" + networkType + ", " + percentage + ")"); 1743 mContext.enforceCallingOrSelfPermission( 1744 android.Manifest.permission.STATUS_BAR, 1745 "ConnectivityService"); 1746 1747 if (DBG) { 1748 int pid = getCallingPid(); 1749 int uid = getCallingUid(); 1750 String s = pid + "(" + uid + ") reports inet is " + 1751 (percentage > 50 ? "connected" : "disconnected") + " (" + percentage + ") on " + 1752 "network Type " + networkType + " at " + GregorianCalendar.getInstance().getTime(); 1753 mInetLog.add(s); 1754 while(mInetLog.size() > INET_CONDITION_LOG_MAX_SIZE) { 1755 mInetLog.remove(0); 1756 } 1757 } 1758 mHandler.sendMessage(mHandler.obtainMessage( 1759 EVENT_INET_CONDITION_CHANGE, networkType, percentage)); 1760 } 1761 1762 private void handleInetConditionChange(int netType, int condition) { 1763 if (DBG) { 1764 Slog.d(TAG, "Inet connectivity change, net=" + 1765 netType + ", condition=" + condition + 1766 ",mActiveDefaultNetwork=" + mActiveDefaultNetwork); 1767 } 1768 if (mActiveDefaultNetwork == -1) { 1769 if (DBG) Slog.d(TAG, "no active default network - aborting"); 1770 return; 1771 } 1772 if (mActiveDefaultNetwork != netType) { 1773 if (DBG) Slog.d(TAG, "given net not default - aborting"); 1774 return; 1775 } 1776 mDefaultInetCondition = condition; 1777 int delay; 1778 if (mInetConditionChangeInFlight == false) { 1779 if (DBG) Slog.d(TAG, "starting a change hold"); 1780 // setup a new hold to debounce this 1781 if (mDefaultInetCondition > 50) { 1782 delay = Settings.Secure.getInt(mContext.getContentResolver(), 1783 Settings.Secure.INET_CONDITION_DEBOUNCE_UP_DELAY, 500); 1784 } else { 1785 delay = Settings.Secure.getInt(mContext.getContentResolver(), 1786 Settings.Secure.INET_CONDITION_DEBOUNCE_DOWN_DELAY, 3000); 1787 } 1788 mInetConditionChangeInFlight = true; 1789 mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_INET_CONDITION_HOLD_END, 1790 mActiveDefaultNetwork, mDefaultConnectionSequence), delay); 1791 } else { 1792 // we've set the new condition, when this hold ends that will get 1793 // picked up 1794 if (DBG) Slog.d(TAG, "currently in hold - not setting new end evt"); 1795 } 1796 } 1797 1798 private void handleInetConditionHoldEnd(int netType, int sequence) { 1799 if (DBG) { 1800 Slog.d(TAG, "Inet hold end, net=" + netType + 1801 ", condition =" + mDefaultInetCondition + 1802 ", published condition =" + mDefaultInetConditionPublished); 1803 } 1804 mInetConditionChangeInFlight = false; 1805 1806 if (mActiveDefaultNetwork == -1) { 1807 if (DBG) Slog.d(TAG, "no active default network - aborting"); 1808 return; 1809 } 1810 if (mDefaultConnectionSequence != sequence) { 1811 if (DBG) Slog.d(TAG, "event hold for obsolete network - aborting"); 1812 return; 1813 } 1814 if (mDefaultInetConditionPublished == mDefaultInetCondition) { 1815 if (DBG) Slog.d(TAG, "no change in condition - aborting"); 1816 return; 1817 } 1818 NetworkInfo networkInfo = mNetTrackers[mActiveDefaultNetwork].getNetworkInfo(); 1819 if (networkInfo.isConnected() == false) { 1820 if (DBG) Slog.d(TAG, "default network not connected - aborting"); 1821 return; 1822 } 1823 mDefaultInetConditionPublished = mDefaultInetCondition; 1824 sendInetConditionBroadcast(networkInfo); 1825 return; 1826 } 1827} 1828