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