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