ConnectivityService.java revision 33034b13cae1429d526722374bd39be3f9605ae4
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 static android.Manifest.permission.MANAGE_NETWORK_POLICY; 20import static android.net.ConnectivityManager.CONNECTIVITY_ACTION; 21import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE; 22import static android.net.ConnectivityManager.isNetworkTypeValid; 23import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL; 24import static android.net.NetworkPolicyManager.RULE_REJECT_METERED; 25 26import android.bluetooth.BluetoothTetheringDataTracker; 27import android.content.ContentResolver; 28import android.content.Context; 29import android.content.ContextWrapper; 30import android.content.Intent; 31import android.content.pm.PackageManager; 32import android.content.res.Resources; 33import android.database.ContentObserver; 34import android.net.ConnectivityManager; 35import android.net.DummyDataStateTracker; 36import android.net.EthernetDataTracker; 37import android.net.IConnectivityManager; 38import android.net.INetworkPolicyListener; 39import android.net.INetworkPolicyManager; 40import android.net.INetworkStatsService; 41import android.net.LinkAddress; 42import android.net.LinkProperties; 43import android.net.LinkProperties.CompareResult; 44import android.net.MobileDataStateTracker; 45import android.net.NetworkConfig; 46import android.net.NetworkInfo; 47import android.net.NetworkInfo.DetailedState; 48import android.net.NetworkQuotaInfo; 49import android.net.NetworkState; 50import android.net.NetworkStateTracker; 51import android.net.NetworkUtils; 52import android.net.Proxy; 53import android.net.ProxyProperties; 54import android.net.RouteInfo; 55import android.net.wifi.WifiStateTracker; 56import android.net.wimax.WimaxManagerConstants; 57import android.os.Binder; 58import android.os.FileUtils; 59import android.os.Handler; 60import android.os.HandlerThread; 61import android.os.IBinder; 62import android.os.INetworkManagementService; 63import android.os.Looper; 64import android.os.Message; 65import android.os.ParcelFileDescriptor; 66import android.os.PowerManager; 67import android.os.RemoteException; 68import android.os.ServiceManager; 69import android.os.SystemClock; 70import android.os.SystemProperties; 71import android.provider.Settings; 72import android.text.TextUtils; 73import android.util.EventLog; 74import android.util.Slog; 75import android.util.SparseIntArray; 76 77import com.android.internal.net.LegacyVpnInfo; 78import com.android.internal.net.VpnConfig; 79import com.android.internal.telephony.Phone; 80import com.android.internal.telephony.PhoneConstants; 81import com.android.server.am.BatteryStatsService; 82import com.android.server.connectivity.Tethering; 83import com.android.server.connectivity.Vpn; 84import com.google.android.collect.Lists; 85import com.google.android.collect.Sets; 86import dalvik.system.DexClassLoader; 87import java.io.FileDescriptor; 88import java.io.IOException; 89import java.io.PrintWriter; 90import java.lang.reflect.Constructor; 91import java.lang.reflect.Method; 92import java.lang.reflect.Modifier; 93import java.lang.reflect.InvocationTargetException; 94import java.net.Inet4Address; 95import java.net.Inet6Address; 96import java.net.InetAddress; 97import java.net.UnknownHostException; 98import java.util.ArrayList; 99import java.util.Arrays; 100import java.util.Collection; 101import java.util.GregorianCalendar; 102import java.util.HashSet; 103import java.util.List; 104 105/** 106 * @hide 107 */ 108public class ConnectivityService extends IConnectivityManager.Stub { 109 110 private static final boolean DBG = true; 111 private static final boolean VDBG = false; 112 private static final String TAG = "ConnectivityService"; 113 114 private static final boolean LOGD_RULES = false; 115 116 // how long to wait before switching back to a radio's default network 117 private static final int RESTORE_DEFAULT_NETWORK_DELAY = 1 * 60 * 1000; 118 // system property that can override the above value 119 private static final String NETWORK_RESTORE_DELAY_PROP_NAME = 120 "android.telephony.apn-restore"; 121 122 // used in recursive route setting to add gateways for the host for which 123 // a host route was requested. 124 private static final int MAX_HOSTROUTE_CYCLE_COUNT = 10; 125 126 private Tethering mTethering; 127 private boolean mTetheringConfigValid = false; 128 129 private Vpn mVpn; 130 131 /** Lock around {@link #mUidRules} and {@link #mMeteredIfaces}. */ 132 private Object mRulesLock = new Object(); 133 /** Currently active network rules by UID. */ 134 private SparseIntArray mUidRules = new SparseIntArray(); 135 /** Set of ifaces that are costly. */ 136 private HashSet<String> mMeteredIfaces = Sets.newHashSet(); 137 138 /** 139 * Sometimes we want to refer to the individual network state 140 * trackers separately, and sometimes we just want to treat them 141 * abstractly. 142 */ 143 private NetworkStateTracker mNetTrackers[]; 144 145 /** 146 * The link properties that define the current links 147 */ 148 private LinkProperties mCurrentLinkProperties[]; 149 150 /** 151 * A per Net list of the PID's that requested access to the net 152 * used both as a refcount and for per-PID DNS selection 153 */ 154 private List mNetRequestersPids[]; 155 156 // priority order of the nettrackers 157 // (excluding dynamically set mNetworkPreference) 158 // TODO - move mNetworkTypePreference into this 159 private int[] mPriorityList; 160 161 private Context mContext; 162 private int mNetworkPreference; 163 private int mActiveDefaultNetwork = -1; 164 // 0 is full bad, 100 is full good 165 private int mDefaultInetCondition = 0; 166 private int mDefaultInetConditionPublished = 0; 167 private boolean mInetConditionChangeInFlight = false; 168 private int mDefaultConnectionSequence = 0; 169 170 private Object mDnsLock = new Object(); 171 private int mNumDnsEntries; 172 private boolean mDnsOverridden = false; 173 174 private boolean mTestMode; 175 private static ConnectivityService sServiceInstance; 176 177 private INetworkManagementService mNetd; 178 private INetworkPolicyManager mPolicyManager; 179 180 private static final int ENABLED = 1; 181 private static final int DISABLED = 0; 182 183 private static final boolean ADD = true; 184 private static final boolean REMOVE = false; 185 186 private static final boolean TO_DEFAULT_TABLE = true; 187 private static final boolean TO_SECONDARY_TABLE = false; 188 189 // Share the event space with NetworkStateTracker (which can't see this 190 // internal class but sends us events). If you change these, change 191 // NetworkStateTracker.java too. 192 private static final int MIN_NETWORK_STATE_TRACKER_EVENT = 1; 193 private static final int MAX_NETWORK_STATE_TRACKER_EVENT = 100; 194 195 /** 196 * used internally as a delayed event to make us switch back to the 197 * default network 198 */ 199 private static final int EVENT_RESTORE_DEFAULT_NETWORK = 200 MAX_NETWORK_STATE_TRACKER_EVENT + 1; 201 202 /** 203 * used internally to change our mobile data enabled flag 204 */ 205 private static final int EVENT_CHANGE_MOBILE_DATA_ENABLED = 206 MAX_NETWORK_STATE_TRACKER_EVENT + 2; 207 208 /** 209 * used internally to change our network preference setting 210 * arg1 = networkType to prefer 211 */ 212 private static final int EVENT_SET_NETWORK_PREFERENCE = 213 MAX_NETWORK_STATE_TRACKER_EVENT + 3; 214 215 /** 216 * used internally to synchronize inet condition reports 217 * arg1 = networkType 218 * arg2 = condition (0 bad, 100 good) 219 */ 220 private static final int EVENT_INET_CONDITION_CHANGE = 221 MAX_NETWORK_STATE_TRACKER_EVENT + 4; 222 223 /** 224 * used internally to mark the end of inet condition hold periods 225 * arg1 = networkType 226 */ 227 private static final int EVENT_INET_CONDITION_HOLD_END = 228 MAX_NETWORK_STATE_TRACKER_EVENT + 5; 229 230 /** 231 * used internally to set enable/disable cellular data 232 * arg1 = ENBALED or DISABLED 233 */ 234 private static final int EVENT_SET_MOBILE_DATA = 235 MAX_NETWORK_STATE_TRACKER_EVENT + 7; 236 237 /** 238 * used internally to clear a wakelock when transitioning 239 * from one net to another 240 */ 241 private static final int EVENT_CLEAR_NET_TRANSITION_WAKELOCK = 242 MAX_NETWORK_STATE_TRACKER_EVENT + 8; 243 244 /** 245 * used internally to reload global proxy settings 246 */ 247 private static final int EVENT_APPLY_GLOBAL_HTTP_PROXY = 248 MAX_NETWORK_STATE_TRACKER_EVENT + 9; 249 250 /** 251 * used internally to set external dependency met/unmet 252 * arg1 = ENABLED (met) or DISABLED (unmet) 253 * arg2 = NetworkType 254 */ 255 private static final int EVENT_SET_DEPENDENCY_MET = 256 MAX_NETWORK_STATE_TRACKER_EVENT + 10; 257 258 /** 259 * used internally to restore DNS properties back to the 260 * default network 261 */ 262 private static final int EVENT_RESTORE_DNS = 263 MAX_NETWORK_STATE_TRACKER_EVENT + 11; 264 265 /** 266 * used internally to send a sticky broadcast delayed. 267 */ 268 private static final int EVENT_SEND_STICKY_BROADCAST_INTENT = 269 MAX_NETWORK_STATE_TRACKER_EVENT + 12; 270 271 /** 272 * Used internally to 273 * {@link NetworkStateTracker#setPolicyDataEnable(boolean)}. 274 */ 275 private static final int EVENT_SET_POLICY_DATA_ENABLE = MAX_NETWORK_STATE_TRACKER_EVENT + 13; 276 277 private Handler mHandler; 278 279 // list of DeathRecipients used to make sure features are turned off when 280 // a process dies 281 private List<FeatureUser> mFeatureUsers; 282 283 private boolean mSystemReady; 284 private Intent mInitialBroadcast; 285 286 private PowerManager.WakeLock mNetTransitionWakeLock; 287 private String mNetTransitionWakeLockCausedBy = ""; 288 private int mNetTransitionWakeLockSerialNumber; 289 private int mNetTransitionWakeLockTimeout; 290 291 private InetAddress mDefaultDns; 292 293 // this collection is used to refcount the added routes - if there are none left 294 // it's time to remove the route from the route table 295 private Collection<RouteInfo> mAddedRoutes = new ArrayList<RouteInfo>(); 296 297 // used in DBG mode to track inet condition reports 298 private static final int INET_CONDITION_LOG_MAX_SIZE = 15; 299 private ArrayList mInetLog; 300 301 // track the current default http proxy - tell the world if we get a new one (real change) 302 private ProxyProperties mDefaultProxy = null; 303 private Object mDefaultProxyLock = new Object(); 304 private boolean mDefaultProxyDisabled = false; 305 306 // track the global proxy. 307 private ProxyProperties mGlobalProxy = null; 308 private final Object mGlobalProxyLock = new Object(); 309 310 private SettingsObserver mSettingsObserver; 311 312 NetworkConfig[] mNetConfigs; 313 int mNetworksDefined; 314 315 private static class RadioAttributes { 316 public int mSimultaneity; 317 public int mType; 318 public RadioAttributes(String init) { 319 String fragments[] = init.split(","); 320 mType = Integer.parseInt(fragments[0]); 321 mSimultaneity = Integer.parseInt(fragments[1]); 322 } 323 } 324 RadioAttributes[] mRadioAttributes; 325 326 // the set of network types that can only be enabled by system/sig apps 327 List mProtectedNetworks; 328 329 public ConnectivityService(Context context, INetworkManagementService netd, 330 INetworkStatsService statsService, INetworkPolicyManager policyManager) { 331 if (DBG) log("ConnectivityService starting up"); 332 333 HandlerThread handlerThread = new HandlerThread("ConnectivityServiceThread"); 334 handlerThread.start(); 335 mHandler = new MyHandler(handlerThread.getLooper()); 336 337 // setup our unique device name 338 if (TextUtils.isEmpty(SystemProperties.get("net.hostname"))) { 339 String id = Settings.Secure.getString(context.getContentResolver(), 340 Settings.Secure.ANDROID_ID); 341 if (id != null && id.length() > 0) { 342 String name = new String("android-").concat(id); 343 SystemProperties.set("net.hostname", name); 344 } 345 } 346 347 // read our default dns server ip 348 String dns = Settings.Secure.getString(context.getContentResolver(), 349 Settings.Secure.DEFAULT_DNS_SERVER); 350 if (dns == null || dns.length() == 0) { 351 dns = context.getResources().getString( 352 com.android.internal.R.string.config_default_dns_server); 353 } 354 try { 355 mDefaultDns = NetworkUtils.numericToInetAddress(dns); 356 } catch (IllegalArgumentException e) { 357 loge("Error setting defaultDns using " + dns); 358 } 359 360 mContext = checkNotNull(context, "missing Context"); 361 mNetd = checkNotNull(netd, "missing INetworkManagementService"); 362 mPolicyManager = checkNotNull(policyManager, "missing INetworkPolicyManager"); 363 364 try { 365 mPolicyManager.registerListener(mPolicyListener); 366 } catch (RemoteException e) { 367 // ouch, no rules updates means some processes may never get network 368 loge("unable to register INetworkPolicyListener" + e.toString()); 369 } 370 371 final PowerManager powerManager = (PowerManager) context.getSystemService( 372 Context.POWER_SERVICE); 373 mNetTransitionWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG); 374 mNetTransitionWakeLockTimeout = mContext.getResources().getInteger( 375 com.android.internal.R.integer.config_networkTransitionTimeout); 376 377 mNetTrackers = new NetworkStateTracker[ 378 ConnectivityManager.MAX_NETWORK_TYPE+1]; 379 mCurrentLinkProperties = new LinkProperties[ConnectivityManager.MAX_NETWORK_TYPE+1]; 380 381 mNetworkPreference = getPersistedNetworkPreference(); 382 383 mRadioAttributes = new RadioAttributes[ConnectivityManager.MAX_RADIO_TYPE+1]; 384 mNetConfigs = new NetworkConfig[ConnectivityManager.MAX_NETWORK_TYPE+1]; 385 386 // Load device network attributes from resources 387 String[] raStrings = context.getResources().getStringArray( 388 com.android.internal.R.array.radioAttributes); 389 for (String raString : raStrings) { 390 RadioAttributes r = new RadioAttributes(raString); 391 if (r.mType > ConnectivityManager.MAX_RADIO_TYPE) { 392 loge("Error in radioAttributes - ignoring attempt to define type " + r.mType); 393 continue; 394 } 395 if (mRadioAttributes[r.mType] != null) { 396 loge("Error in radioAttributes - ignoring attempt to redefine type " + 397 r.mType); 398 continue; 399 } 400 mRadioAttributes[r.mType] = r; 401 } 402 403 String[] naStrings = context.getResources().getStringArray( 404 com.android.internal.R.array.networkAttributes); 405 for (String naString : naStrings) { 406 try { 407 NetworkConfig n = new NetworkConfig(naString); 408 if (n.type > ConnectivityManager.MAX_NETWORK_TYPE) { 409 loge("Error in networkAttributes - ignoring attempt to define type " + 410 n.type); 411 continue; 412 } 413 if (mNetConfigs[n.type] != null) { 414 loge("Error in networkAttributes - ignoring attempt to redefine type " + 415 n.type); 416 continue; 417 } 418 if (mRadioAttributes[n.radio] == null) { 419 loge("Error in networkAttributes - ignoring attempt to use undefined " + 420 "radio " + n.radio + " in network type " + n.type); 421 continue; 422 } 423 mNetConfigs[n.type] = n; 424 mNetworksDefined++; 425 } catch(Exception e) { 426 // ignore it - leave the entry null 427 } 428 } 429 430 mProtectedNetworks = new ArrayList<Integer>(); 431 int[] protectedNetworks = context.getResources().getIntArray( 432 com.android.internal.R.array.config_protectedNetworks); 433 for (int p : protectedNetworks) { 434 if ((mNetConfigs[p] != null) && (mProtectedNetworks.contains(p) == false)) { 435 mProtectedNetworks.add(p); 436 } else { 437 if (DBG) loge("Ignoring protectedNetwork " + p); 438 } 439 } 440 441 // high priority first 442 mPriorityList = new int[mNetworksDefined]; 443 { 444 int insertionPoint = mNetworksDefined-1; 445 int currentLowest = 0; 446 int nextLowest = 0; 447 while (insertionPoint > -1) { 448 for (NetworkConfig na : mNetConfigs) { 449 if (na == null) continue; 450 if (na.priority < currentLowest) continue; 451 if (na.priority > currentLowest) { 452 if (na.priority < nextLowest || nextLowest == 0) { 453 nextLowest = na.priority; 454 } 455 continue; 456 } 457 mPriorityList[insertionPoint--] = na.type; 458 } 459 currentLowest = nextLowest; 460 nextLowest = 0; 461 } 462 } 463 464 mNetRequestersPids = new ArrayList[ConnectivityManager.MAX_NETWORK_TYPE+1]; 465 for (int i : mPriorityList) { 466 mNetRequestersPids[i] = new ArrayList(); 467 } 468 469 mFeatureUsers = new ArrayList<FeatureUser>(); 470 471 mNumDnsEntries = 0; 472 473 mTestMode = SystemProperties.get("cm.test.mode").equals("true") 474 && SystemProperties.get("ro.build.type").equals("eng"); 475 /* 476 * Create the network state trackers for Wi-Fi and mobile 477 * data. Maybe this could be done with a factory class, 478 * but it's not clear that it's worth it, given that 479 * the number of different network types is not going 480 * to change very often. 481 */ 482 for (int netType : mPriorityList) { 483 switch (mNetConfigs[netType].radio) { 484 case ConnectivityManager.TYPE_WIFI: 485 mNetTrackers[netType] = new WifiStateTracker(netType, 486 mNetConfigs[netType].name); 487 mNetTrackers[netType].startMonitoring(context, mHandler); 488 break; 489 case ConnectivityManager.TYPE_MOBILE: 490 mNetTrackers[netType] = new MobileDataStateTracker(netType, 491 mNetConfigs[netType].name); 492 mNetTrackers[netType].startMonitoring(context, mHandler); 493 break; 494 case ConnectivityManager.TYPE_DUMMY: 495 mNetTrackers[netType] = new DummyDataStateTracker(netType, 496 mNetConfigs[netType].name); 497 mNetTrackers[netType].startMonitoring(context, mHandler); 498 break; 499 case ConnectivityManager.TYPE_BLUETOOTH: 500 mNetTrackers[netType] = BluetoothTetheringDataTracker.getInstance(); 501 mNetTrackers[netType].startMonitoring(context, mHandler); 502 break; 503 case ConnectivityManager.TYPE_WIMAX: 504 mNetTrackers[netType] = makeWimaxStateTracker(); 505 if (mNetTrackers[netType]!= null) { 506 mNetTrackers[netType].startMonitoring(context, mHandler); 507 } 508 break; 509 case ConnectivityManager.TYPE_ETHERNET: 510 mNetTrackers[netType] = EthernetDataTracker.getInstance(); 511 mNetTrackers[netType].startMonitoring(context, mHandler); 512 break; 513 default: 514 loge("Trying to create a DataStateTracker for an unknown radio type " + 515 mNetConfigs[netType].radio); 516 continue; 517 } 518 mCurrentLinkProperties[netType] = null; 519 if (mNetTrackers[netType] != null && mNetConfigs[netType].isDefault()) { 520 mNetTrackers[netType].reconnect(); 521 } 522 } 523 524 IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE); 525 INetworkManagementService nmService = INetworkManagementService.Stub.asInterface(b); 526 527 mTethering = new Tethering(mContext, nmService, statsService, this, mHandler.getLooper()); 528 mTetheringConfigValid = ((mTethering.getTetherableUsbRegexs().length != 0 || 529 mTethering.getTetherableWifiRegexs().length != 0 || 530 mTethering.getTetherableBluetoothRegexs().length != 0) && 531 mTethering.getUpstreamIfaceTypes().length != 0); 532 533 mVpn = new Vpn(mContext, new VpnCallback()); 534 535 try { 536 nmService.registerObserver(mTethering); 537 nmService.registerObserver(mVpn); 538 } catch (RemoteException e) { 539 loge("Error registering observer :" + e); 540 } 541 542 if (DBG) { 543 mInetLog = new ArrayList(); 544 } 545 546 mSettingsObserver = new SettingsObserver(mHandler, EVENT_APPLY_GLOBAL_HTTP_PROXY); 547 mSettingsObserver.observe(mContext); 548 549 loadGlobalProxy(); 550 } 551private NetworkStateTracker makeWimaxStateTracker() { 552 //Initialize Wimax 553 DexClassLoader wimaxClassLoader; 554 Class wimaxStateTrackerClass = null; 555 Class wimaxServiceClass = null; 556 Class wimaxManagerClass; 557 String wimaxJarLocation; 558 String wimaxLibLocation; 559 String wimaxManagerClassName; 560 String wimaxServiceClassName; 561 String wimaxStateTrackerClassName; 562 563 NetworkStateTracker wimaxStateTracker = null; 564 565 boolean isWimaxEnabled = mContext.getResources().getBoolean( 566 com.android.internal.R.bool.config_wimaxEnabled); 567 568 if (isWimaxEnabled) { 569 try { 570 wimaxJarLocation = mContext.getResources().getString( 571 com.android.internal.R.string.config_wimaxServiceJarLocation); 572 wimaxLibLocation = mContext.getResources().getString( 573 com.android.internal.R.string.config_wimaxNativeLibLocation); 574 wimaxManagerClassName = mContext.getResources().getString( 575 com.android.internal.R.string.config_wimaxManagerClassname); 576 wimaxServiceClassName = mContext.getResources().getString( 577 com.android.internal.R.string.config_wimaxServiceClassname); 578 wimaxStateTrackerClassName = mContext.getResources().getString( 579 com.android.internal.R.string.config_wimaxStateTrackerClassname); 580 581 log("wimaxJarLocation: " + wimaxJarLocation); 582 wimaxClassLoader = new DexClassLoader(wimaxJarLocation, 583 new ContextWrapper(mContext).getCacheDir().getAbsolutePath(), 584 wimaxLibLocation, ClassLoader.getSystemClassLoader()); 585 586 try { 587 wimaxManagerClass = wimaxClassLoader.loadClass(wimaxManagerClassName); 588 wimaxStateTrackerClass = wimaxClassLoader.loadClass(wimaxStateTrackerClassName); 589 wimaxServiceClass = wimaxClassLoader.loadClass(wimaxServiceClassName); 590 } catch (ClassNotFoundException ex) { 591 loge("Exception finding Wimax classes: " + ex.toString()); 592 return null; 593 } 594 } catch(Resources.NotFoundException ex) { 595 loge("Wimax Resources does not exist!!! "); 596 return null; 597 } 598 599 try { 600 log("Starting Wimax Service... "); 601 602 Constructor wmxStTrkrConst = wimaxStateTrackerClass.getConstructor 603 (new Class[] {Context.class, Handler.class}); 604 wimaxStateTracker = (NetworkStateTracker)wmxStTrkrConst.newInstance(mContext, 605 mHandler); 606 607 Constructor wmxSrvConst = wimaxServiceClass.getDeclaredConstructor 608 (new Class[] {Context.class, wimaxStateTrackerClass}); 609 wmxSrvConst.setAccessible(true); 610 IBinder svcInvoker = (IBinder)wmxSrvConst.newInstance(mContext, wimaxStateTracker); 611 wmxSrvConst.setAccessible(false); 612 613 ServiceManager.addService(WimaxManagerConstants.WIMAX_SERVICE, svcInvoker); 614 615 } catch(Exception ex) { 616 loge("Exception creating Wimax classes: " + ex.toString()); 617 return null; 618 } 619 } else { 620 loge("Wimax is not enabled or not added to the network attributes!!! "); 621 return null; 622 } 623 624 return wimaxStateTracker; 625 } 626 /** 627 * Sets the preferred network. 628 * @param preference the new preference 629 */ 630 public void setNetworkPreference(int preference) { 631 enforceChangePermission(); 632 633 mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_NETWORK_PREFERENCE, preference, 0)); 634 } 635 636 public int getNetworkPreference() { 637 enforceAccessPermission(); 638 int preference; 639 synchronized(this) { 640 preference = mNetworkPreference; 641 } 642 return preference; 643 } 644 645 private void handleSetNetworkPreference(int preference) { 646 if (ConnectivityManager.isNetworkTypeValid(preference) && 647 mNetConfigs[preference] != null && 648 mNetConfigs[preference].isDefault()) { 649 if (mNetworkPreference != preference) { 650 final ContentResolver cr = mContext.getContentResolver(); 651 Settings.Secure.putInt(cr, Settings.Secure.NETWORK_PREFERENCE, preference); 652 synchronized(this) { 653 mNetworkPreference = preference; 654 } 655 enforcePreference(); 656 } 657 } 658 } 659 660 private int getConnectivityChangeDelay() { 661 final ContentResolver cr = mContext.getContentResolver(); 662 663 /** Check system properties for the default value then use secure settings value, if any. */ 664 int defaultDelay = SystemProperties.getInt( 665 "conn." + Settings.Secure.CONNECTIVITY_CHANGE_DELAY, 666 Settings.Secure.CONNECTIVITY_CHANGE_DELAY_DEFAULT); 667 return Settings.Secure.getInt(cr, Settings.Secure.CONNECTIVITY_CHANGE_DELAY, 668 defaultDelay); 669 } 670 671 private int getPersistedNetworkPreference() { 672 final ContentResolver cr = mContext.getContentResolver(); 673 674 final int networkPrefSetting = Settings.Secure 675 .getInt(cr, Settings.Secure.NETWORK_PREFERENCE, -1); 676 if (networkPrefSetting != -1) { 677 return networkPrefSetting; 678 } 679 680 return ConnectivityManager.DEFAULT_NETWORK_PREFERENCE; 681 } 682 683 /** 684 * Make the state of network connectivity conform to the preference settings 685 * In this method, we only tear down a non-preferred network. Establishing 686 * a connection to the preferred network is taken care of when we handle 687 * the disconnect event from the non-preferred network 688 * (see {@link #handleDisconnect(NetworkInfo)}). 689 */ 690 private void enforcePreference() { 691 if (mNetTrackers[mNetworkPreference].getNetworkInfo().isConnected()) 692 return; 693 694 if (!mNetTrackers[mNetworkPreference].isAvailable()) 695 return; 696 697 for (int t=0; t <= ConnectivityManager.MAX_RADIO_TYPE; t++) { 698 if (t != mNetworkPreference && mNetTrackers[t] != null && 699 mNetTrackers[t].getNetworkInfo().isConnected()) { 700 if (DBG) { 701 log("tearing down " + mNetTrackers[t].getNetworkInfo() + 702 " in enforcePreference"); 703 } 704 teardown(mNetTrackers[t]); 705 } 706 } 707 } 708 709 private boolean teardown(NetworkStateTracker netTracker) { 710 if (netTracker.teardown()) { 711 netTracker.setTeardownRequested(true); 712 return true; 713 } else { 714 return false; 715 } 716 } 717 718 /** 719 * Check if UID should be blocked from using the network represented by the 720 * given {@link NetworkStateTracker}. 721 */ 722 private boolean isNetworkBlocked(NetworkStateTracker tracker, int uid) { 723 final String iface = tracker.getLinkProperties().getInterfaceName(); 724 725 final boolean networkCostly; 726 final int uidRules; 727 synchronized (mRulesLock) { 728 networkCostly = mMeteredIfaces.contains(iface); 729 uidRules = mUidRules.get(uid, RULE_ALLOW_ALL); 730 } 731 732 if (networkCostly && (uidRules & RULE_REJECT_METERED) != 0) { 733 return true; 734 } 735 736 // no restrictive rules; network is visible 737 return false; 738 } 739 740 /** 741 * Return a filtered {@link NetworkInfo}, potentially marked 742 * {@link DetailedState#BLOCKED} based on 743 * {@link #isNetworkBlocked(NetworkStateTracker, int)}. 744 */ 745 private NetworkInfo getFilteredNetworkInfo(NetworkStateTracker tracker, int uid) { 746 NetworkInfo info = tracker.getNetworkInfo(); 747 if (isNetworkBlocked(tracker, uid)) { 748 // network is blocked; clone and override state 749 info = new NetworkInfo(info); 750 info.setDetailedState(DetailedState.BLOCKED, null, null); 751 } 752 return info; 753 } 754 755 /** 756 * Return NetworkInfo for the active (i.e., connected) network interface. 757 * It is assumed that at most one network is active at a time. If more 758 * than one is active, it is indeterminate which will be returned. 759 * @return the info for the active network, or {@code null} if none is 760 * active 761 */ 762 @Override 763 public NetworkInfo getActiveNetworkInfo() { 764 enforceAccessPermission(); 765 final int uid = Binder.getCallingUid(); 766 return getNetworkInfo(mActiveDefaultNetwork, uid); 767 } 768 769 @Override 770 public NetworkInfo getActiveNetworkInfoForUid(int uid) { 771 enforceConnectivityInternalPermission(); 772 return getNetworkInfo(mActiveDefaultNetwork, uid); 773 } 774 775 @Override 776 public NetworkInfo getNetworkInfo(int networkType) { 777 enforceAccessPermission(); 778 final int uid = Binder.getCallingUid(); 779 return getNetworkInfo(networkType, uid); 780 } 781 782 private NetworkInfo getNetworkInfo(int networkType, int uid) { 783 NetworkInfo info = null; 784 if (isNetworkTypeValid(networkType)) { 785 final NetworkStateTracker tracker = mNetTrackers[networkType]; 786 if (tracker != null) { 787 info = getFilteredNetworkInfo(tracker, uid); 788 } 789 } 790 return info; 791 } 792 793 @Override 794 public NetworkInfo[] getAllNetworkInfo() { 795 enforceAccessPermission(); 796 final int uid = Binder.getCallingUid(); 797 final ArrayList<NetworkInfo> result = Lists.newArrayList(); 798 synchronized (mRulesLock) { 799 for (NetworkStateTracker tracker : mNetTrackers) { 800 if (tracker != null) { 801 result.add(getFilteredNetworkInfo(tracker, uid)); 802 } 803 } 804 } 805 return result.toArray(new NetworkInfo[result.size()]); 806 } 807 808 @Override 809 public boolean isNetworkSupported(int networkType) { 810 enforceAccessPermission(); 811 return (isNetworkTypeValid(networkType) && (mNetTrackers[networkType] != null)); 812 } 813 814 /** 815 * Return LinkProperties for the active (i.e., connected) default 816 * network interface. It is assumed that at most one default network 817 * is active at a time. If more than one is active, it is indeterminate 818 * which will be returned. 819 * @return the ip properties for the active network, or {@code null} if 820 * none is active 821 */ 822 @Override 823 public LinkProperties getActiveLinkProperties() { 824 return getLinkProperties(mActiveDefaultNetwork); 825 } 826 827 @Override 828 public LinkProperties getLinkProperties(int networkType) { 829 enforceAccessPermission(); 830 if (isNetworkTypeValid(networkType)) { 831 final NetworkStateTracker tracker = mNetTrackers[networkType]; 832 if (tracker != null) { 833 return tracker.getLinkProperties(); 834 } 835 } 836 return null; 837 } 838 839 @Override 840 public NetworkState[] getAllNetworkState() { 841 enforceAccessPermission(); 842 final int uid = Binder.getCallingUid(); 843 final ArrayList<NetworkState> result = Lists.newArrayList(); 844 synchronized (mRulesLock) { 845 for (NetworkStateTracker tracker : mNetTrackers) { 846 if (tracker != null) { 847 final NetworkInfo info = getFilteredNetworkInfo(tracker, uid); 848 result.add(new NetworkState( 849 info, tracker.getLinkProperties(), tracker.getLinkCapabilities())); 850 } 851 } 852 } 853 return result.toArray(new NetworkState[result.size()]); 854 } 855 856 private NetworkState getNetworkStateUnchecked(int networkType) { 857 if (isNetworkTypeValid(networkType)) { 858 final NetworkStateTracker tracker = mNetTrackers[networkType]; 859 if (tracker != null) { 860 return new NetworkState(tracker.getNetworkInfo(), tracker.getLinkProperties(), 861 tracker.getLinkCapabilities()); 862 } 863 } 864 return null; 865 } 866 867 @Override 868 public NetworkQuotaInfo getActiveNetworkQuotaInfo() { 869 enforceAccessPermission(); 870 871 final long token = Binder.clearCallingIdentity(); 872 try { 873 final NetworkState state = getNetworkStateUnchecked(mActiveDefaultNetwork); 874 if (state != null) { 875 try { 876 return mPolicyManager.getNetworkQuotaInfo(state); 877 } catch (RemoteException e) { 878 } 879 } 880 return null; 881 } finally { 882 Binder.restoreCallingIdentity(token); 883 } 884 } 885 886 @Override 887 public boolean isActiveNetworkMetered() { 888 enforceAccessPermission(); 889 final long token = Binder.clearCallingIdentity(); 890 try { 891 return isNetworkMeteredUnchecked(mActiveDefaultNetwork); 892 } finally { 893 Binder.restoreCallingIdentity(token); 894 } 895 } 896 897 private boolean isNetworkMeteredUnchecked(int networkType) { 898 final NetworkState state = getNetworkStateUnchecked(networkType); 899 if (state != null) { 900 try { 901 return mPolicyManager.isNetworkMetered(state); 902 } catch (RemoteException e) { 903 } 904 } 905 return false; 906 } 907 908 public boolean setRadios(boolean turnOn) { 909 boolean result = true; 910 enforceChangePermission(); 911 for (NetworkStateTracker t : mNetTrackers) { 912 if (t != null) result = t.setRadio(turnOn) && result; 913 } 914 return result; 915 } 916 917 public boolean setRadio(int netType, boolean turnOn) { 918 enforceChangePermission(); 919 if (!ConnectivityManager.isNetworkTypeValid(netType)) { 920 return false; 921 } 922 NetworkStateTracker tracker = mNetTrackers[netType]; 923 return tracker != null && tracker.setRadio(turnOn); 924 } 925 926 /** 927 * Used to notice when the calling process dies so we can self-expire 928 * 929 * Also used to know if the process has cleaned up after itself when 930 * our auto-expire timer goes off. The timer has a link to an object. 931 * 932 */ 933 private class FeatureUser implements IBinder.DeathRecipient { 934 int mNetworkType; 935 String mFeature; 936 IBinder mBinder; 937 int mPid; 938 int mUid; 939 long mCreateTime; 940 941 FeatureUser(int type, String feature, IBinder binder) { 942 super(); 943 mNetworkType = type; 944 mFeature = feature; 945 mBinder = binder; 946 mPid = getCallingPid(); 947 mUid = getCallingUid(); 948 mCreateTime = System.currentTimeMillis(); 949 950 try { 951 mBinder.linkToDeath(this, 0); 952 } catch (RemoteException e) { 953 binderDied(); 954 } 955 } 956 957 void unlinkDeathRecipient() { 958 mBinder.unlinkToDeath(this, 0); 959 } 960 961 public void binderDied() { 962 log("ConnectivityService FeatureUser binderDied(" + 963 mNetworkType + ", " + mFeature + ", " + mBinder + "), created " + 964 (System.currentTimeMillis() - mCreateTime) + " mSec ago"); 965 stopUsingNetworkFeature(this, false); 966 } 967 968 public void expire() { 969 if (VDBG) { 970 log("ConnectivityService FeatureUser expire(" + 971 mNetworkType + ", " + mFeature + ", " + mBinder +"), created " + 972 (System.currentTimeMillis() - mCreateTime) + " mSec ago"); 973 } 974 stopUsingNetworkFeature(this, false); 975 } 976 977 public boolean isSameUser(FeatureUser u) { 978 if (u == null) return false; 979 980 return isSameUser(u.mPid, u.mUid, u.mNetworkType, u.mFeature); 981 } 982 983 public boolean isSameUser(int pid, int uid, int networkType, String feature) { 984 if ((mPid == pid) && (mUid == uid) && (mNetworkType == networkType) && 985 TextUtils.equals(mFeature, feature)) { 986 return true; 987 } 988 return false; 989 } 990 991 public String toString() { 992 return "FeatureUser("+mNetworkType+","+mFeature+","+mPid+","+mUid+"), created " + 993 (System.currentTimeMillis() - mCreateTime) + " mSec ago"; 994 } 995 } 996 997 // javadoc from interface 998 public int startUsingNetworkFeature(int networkType, String feature, 999 IBinder binder) { 1000 long startTime = 0; 1001 if (DBG) { 1002 startTime = SystemClock.elapsedRealtime(); 1003 } 1004 if (VDBG) { 1005 log("startUsingNetworkFeature for net " + networkType + ": " + feature + ", uid=" 1006 + Binder.getCallingUid()); 1007 } 1008 enforceChangePermission(); 1009 try { 1010 if (!ConnectivityManager.isNetworkTypeValid(networkType) || 1011 mNetConfigs[networkType] == null) { 1012 return PhoneConstants.APN_REQUEST_FAILED; 1013 } 1014 1015 FeatureUser f = new FeatureUser(networkType, feature, binder); 1016 1017 // TODO - move this into individual networktrackers 1018 int usedNetworkType = convertFeatureToNetworkType(networkType, feature); 1019 1020 if (mProtectedNetworks.contains(usedNetworkType)) { 1021 enforceConnectivityInternalPermission(); 1022 } 1023 1024 // if UID is restricted, don't allow them to bring up metered APNs 1025 final boolean networkMetered = isNetworkMeteredUnchecked(usedNetworkType); 1026 final int uidRules; 1027 synchronized (mRulesLock) { 1028 uidRules = mUidRules.get(Binder.getCallingUid(), RULE_ALLOW_ALL); 1029 } 1030 if (networkMetered && (uidRules & RULE_REJECT_METERED) != 0) { 1031 return PhoneConstants.APN_REQUEST_FAILED; 1032 } 1033 1034 NetworkStateTracker network = mNetTrackers[usedNetworkType]; 1035 if (network != null) { 1036 Integer currentPid = new Integer(getCallingPid()); 1037 if (usedNetworkType != networkType) { 1038 NetworkInfo ni = network.getNetworkInfo(); 1039 1040 if (ni.isAvailable() == false) { 1041 if (!TextUtils.equals(feature,Phone.FEATURE_ENABLE_DUN_ALWAYS)) { 1042 if (DBG) log("special network not available ni=" + ni.getTypeName()); 1043 return PhoneConstants.APN_TYPE_NOT_AVAILABLE; 1044 } else { 1045 // else make the attempt anyway - probably giving REQUEST_STARTED below 1046 if (DBG) { 1047 log("special network not available, but try anyway ni=" + 1048 ni.getTypeName()); 1049 } 1050 } 1051 } 1052 1053 int restoreTimer = getRestoreDefaultNetworkDelay(usedNetworkType); 1054 1055 synchronized(this) { 1056 boolean addToList = true; 1057 if (restoreTimer < 0) { 1058 // In case there is no timer is specified for the feature, 1059 // make sure we don't add duplicate entry with the same request. 1060 for (FeatureUser u : mFeatureUsers) { 1061 if (u.isSameUser(f)) { 1062 // Duplicate user is found. Do not add. 1063 addToList = false; 1064 break; 1065 } 1066 } 1067 } 1068 1069 if (addToList) mFeatureUsers.add(f); 1070 if (!mNetRequestersPids[usedNetworkType].contains(currentPid)) { 1071 // this gets used for per-pid dns when connected 1072 mNetRequestersPids[usedNetworkType].add(currentPid); 1073 } 1074 } 1075 1076 if (restoreTimer >= 0) { 1077 mHandler.sendMessageDelayed(mHandler.obtainMessage( 1078 EVENT_RESTORE_DEFAULT_NETWORK, f), restoreTimer); 1079 } 1080 1081 if ((ni.isConnectedOrConnecting() == true) && 1082 !network.isTeardownRequested()) { 1083 if (ni.isConnected() == true) { 1084 final long token = Binder.clearCallingIdentity(); 1085 try { 1086 // add the pid-specific dns 1087 handleDnsConfigurationChange(usedNetworkType); 1088 if (VDBG) log("special network already active"); 1089 } finally { 1090 Binder.restoreCallingIdentity(token); 1091 } 1092 return PhoneConstants.APN_ALREADY_ACTIVE; 1093 } 1094 if (VDBG) log("special network already connecting"); 1095 return PhoneConstants.APN_REQUEST_STARTED; 1096 } 1097 1098 // check if the radio in play can make another contact 1099 // assume if cannot for now 1100 1101 if (DBG) { 1102 log("startUsingNetworkFeature reconnecting to " + networkType + ": " + 1103 feature); 1104 } 1105 network.reconnect(); 1106 return PhoneConstants.APN_REQUEST_STARTED; 1107 } else { 1108 // need to remember this unsupported request so we respond appropriately on stop 1109 synchronized(this) { 1110 mFeatureUsers.add(f); 1111 if (!mNetRequestersPids[usedNetworkType].contains(currentPid)) { 1112 // this gets used for per-pid dns when connected 1113 mNetRequestersPids[usedNetworkType].add(currentPid); 1114 } 1115 } 1116 return -1; 1117 } 1118 } 1119 return PhoneConstants.APN_TYPE_NOT_AVAILABLE; 1120 } finally { 1121 if (DBG) { 1122 final long execTime = SystemClock.elapsedRealtime() - startTime; 1123 if (execTime > 250) { 1124 loge("startUsingNetworkFeature took too long: " + execTime + "ms"); 1125 } else { 1126 if (VDBG) log("startUsingNetworkFeature took " + execTime + "ms"); 1127 } 1128 } 1129 } 1130 } 1131 1132 // javadoc from interface 1133 public int stopUsingNetworkFeature(int networkType, String feature) { 1134 enforceChangePermission(); 1135 1136 int pid = getCallingPid(); 1137 int uid = getCallingUid(); 1138 1139 FeatureUser u = null; 1140 boolean found = false; 1141 1142 synchronized(this) { 1143 for (FeatureUser x : mFeatureUsers) { 1144 if (x.isSameUser(pid, uid, networkType, feature)) { 1145 u = x; 1146 found = true; 1147 break; 1148 } 1149 } 1150 } 1151 if (found && u != null) { 1152 // stop regardless of how many other time this proc had called start 1153 return stopUsingNetworkFeature(u, true); 1154 } else { 1155 // none found! 1156 if (VDBG) log("stopUsingNetworkFeature - not a live request, ignoring"); 1157 return 1; 1158 } 1159 } 1160 1161 private int stopUsingNetworkFeature(FeatureUser u, boolean ignoreDups) { 1162 int networkType = u.mNetworkType; 1163 String feature = u.mFeature; 1164 int pid = u.mPid; 1165 int uid = u.mUid; 1166 1167 NetworkStateTracker tracker = null; 1168 boolean callTeardown = false; // used to carry our decision outside of sync block 1169 1170 if (VDBG) { 1171 log("stopUsingNetworkFeature: net " + networkType + ": " + feature); 1172 } 1173 1174 if (!ConnectivityManager.isNetworkTypeValid(networkType)) { 1175 if (DBG) { 1176 log("stopUsingNetworkFeature: net " + networkType + ": " + feature + 1177 ", net is invalid"); 1178 } 1179 return -1; 1180 } 1181 1182 // need to link the mFeatureUsers list with the mNetRequestersPids state in this 1183 // sync block 1184 synchronized(this) { 1185 // check if this process still has an outstanding start request 1186 if (!mFeatureUsers.contains(u)) { 1187 if (VDBG) { 1188 log("stopUsingNetworkFeature: this process has no outstanding requests" + 1189 ", ignoring"); 1190 } 1191 return 1; 1192 } 1193 u.unlinkDeathRecipient(); 1194 mFeatureUsers.remove(mFeatureUsers.indexOf(u)); 1195 // If we care about duplicate requests, check for that here. 1196 // 1197 // This is done to support the extension of a request - the app 1198 // can request we start the network feature again and renew the 1199 // auto-shutoff delay. Normal "stop" calls from the app though 1200 // do not pay attention to duplicate requests - in effect the 1201 // API does not refcount and a single stop will counter multiple starts. 1202 if (ignoreDups == false) { 1203 for (FeatureUser x : mFeatureUsers) { 1204 if (x.isSameUser(u)) { 1205 if (VDBG) log("stopUsingNetworkFeature: dup is found, ignoring"); 1206 return 1; 1207 } 1208 } 1209 } 1210 1211 // TODO - move to individual network trackers 1212 int usedNetworkType = convertFeatureToNetworkType(networkType, feature); 1213 1214 tracker = mNetTrackers[usedNetworkType]; 1215 if (tracker == null) { 1216 if (DBG) { 1217 log("stopUsingNetworkFeature: net " + networkType + ": " + feature + 1218 " no known tracker for used net type " + usedNetworkType); 1219 } 1220 return -1; 1221 } 1222 if (usedNetworkType != networkType) { 1223 Integer currentPid = new Integer(pid); 1224 mNetRequestersPids[usedNetworkType].remove(currentPid); 1225 reassessPidDns(pid, true); 1226 if (mNetRequestersPids[usedNetworkType].size() != 0) { 1227 if (VDBG) { 1228 log("stopUsingNetworkFeature: net " + networkType + ": " + feature + 1229 " others still using it"); 1230 } 1231 return 1; 1232 } 1233 callTeardown = true; 1234 } else { 1235 if (DBG) { 1236 log("stopUsingNetworkFeature: net " + networkType + ": " + feature + 1237 " not a known feature - dropping"); 1238 } 1239 } 1240 } 1241 1242 if (callTeardown) { 1243 if (DBG) { 1244 log("stopUsingNetworkFeature: teardown net " + networkType + ": " + feature); 1245 } 1246 tracker.teardown(); 1247 return 1; 1248 } else { 1249 return -1; 1250 } 1251 } 1252 1253 /** 1254 * @deprecated use requestRouteToHostAddress instead 1255 * 1256 * Ensure that a network route exists to deliver traffic to the specified 1257 * host via the specified network interface. 1258 * @param networkType the type of the network over which traffic to the 1259 * specified host is to be routed 1260 * @param hostAddress the IP address of the host to which the route is 1261 * desired 1262 * @return {@code true} on success, {@code false} on failure 1263 */ 1264 public boolean requestRouteToHost(int networkType, int hostAddress) { 1265 InetAddress inetAddress = NetworkUtils.intToInetAddress(hostAddress); 1266 1267 if (inetAddress == null) { 1268 return false; 1269 } 1270 1271 return requestRouteToHostAddress(networkType, inetAddress.getAddress()); 1272 } 1273 1274 /** 1275 * Ensure that a network route exists to deliver traffic to the specified 1276 * host via the specified network interface. 1277 * @param networkType the type of the network over which traffic to the 1278 * specified host is to be routed 1279 * @param hostAddress the IP address of the host to which the route is 1280 * desired 1281 * @return {@code true} on success, {@code false} on failure 1282 */ 1283 public boolean requestRouteToHostAddress(int networkType, byte[] hostAddress) { 1284 enforceChangePermission(); 1285 if (mProtectedNetworks.contains(networkType)) { 1286 enforceConnectivityInternalPermission(); 1287 } 1288 1289 if (!ConnectivityManager.isNetworkTypeValid(networkType)) { 1290 if (DBG) log("requestRouteToHostAddress on invalid network: " + networkType); 1291 return false; 1292 } 1293 NetworkStateTracker tracker = mNetTrackers[networkType]; 1294 1295 if (tracker == null || !tracker.getNetworkInfo().isConnected() || 1296 tracker.isTeardownRequested()) { 1297 if (VDBG) { 1298 log("requestRouteToHostAddress on down network " + 1299 "(" + networkType + ") - dropped"); 1300 } 1301 return false; 1302 } 1303 final long token = Binder.clearCallingIdentity(); 1304 try { 1305 InetAddress addr = InetAddress.getByAddress(hostAddress); 1306 LinkProperties lp = tracker.getLinkProperties(); 1307 return addRouteToAddress(lp, addr); 1308 } catch (UnknownHostException e) { 1309 if (DBG) log("requestRouteToHostAddress got " + e.toString()); 1310 } finally { 1311 Binder.restoreCallingIdentity(token); 1312 } 1313 return false; 1314 } 1315 1316 private boolean addRoute(LinkProperties p, RouteInfo r, boolean toDefaultTable) { 1317 return modifyRoute(p.getInterfaceName(), p, r, 0, ADD, toDefaultTable); 1318 } 1319 1320 private boolean removeRoute(LinkProperties p, RouteInfo r, boolean toDefaultTable) { 1321 return modifyRoute(p.getInterfaceName(), p, r, 0, REMOVE, toDefaultTable); 1322 } 1323 1324 private boolean addRouteToAddress(LinkProperties lp, InetAddress addr) { 1325 return modifyRouteToAddress(lp, addr, ADD, TO_DEFAULT_TABLE); 1326 } 1327 1328 private boolean removeRouteToAddress(LinkProperties lp, InetAddress addr) { 1329 return modifyRouteToAddress(lp, addr, REMOVE, TO_DEFAULT_TABLE); 1330 } 1331 1332 private boolean modifyRouteToAddress(LinkProperties lp, InetAddress addr, boolean doAdd, 1333 boolean toDefaultTable) { 1334 RouteInfo bestRoute = RouteInfo.selectBestRoute(lp.getRoutes(), addr); 1335 if (bestRoute == null) { 1336 bestRoute = RouteInfo.makeHostRoute(addr); 1337 } else { 1338 if (bestRoute.getGateway().equals(addr)) { 1339 // if there is no better route, add the implied hostroute for our gateway 1340 bestRoute = RouteInfo.makeHostRoute(addr); 1341 } else { 1342 // if we will connect to this through another route, add a direct route 1343 // to it's gateway 1344 bestRoute = RouteInfo.makeHostRoute(addr, bestRoute.getGateway()); 1345 } 1346 } 1347 return modifyRoute(lp.getInterfaceName(), lp, bestRoute, 0, doAdd, toDefaultTable); 1348 } 1349 1350 private boolean modifyRoute(String ifaceName, LinkProperties lp, RouteInfo r, int cycleCount, 1351 boolean doAdd, boolean toDefaultTable) { 1352 if ((ifaceName == null) || (lp == null) || (r == null)) { 1353 if (DBG) log("modifyRoute got unexpected null: " + ifaceName + ", " + lp + ", " + r); 1354 return false; 1355 } 1356 1357 if (cycleCount > MAX_HOSTROUTE_CYCLE_COUNT) { 1358 loge("Error modifying route - too much recursion"); 1359 return false; 1360 } 1361 1362 if (r.isHostRoute() == false) { 1363 RouteInfo bestRoute = RouteInfo.selectBestRoute(lp.getRoutes(), r.getGateway()); 1364 if (bestRoute != null) { 1365 if (bestRoute.getGateway().equals(r.getGateway())) { 1366 // if there is no better route, add the implied hostroute for our gateway 1367 bestRoute = RouteInfo.makeHostRoute(r.getGateway()); 1368 } else { 1369 // if we will connect to our gateway through another route, add a direct 1370 // route to it's gateway 1371 bestRoute = RouteInfo.makeHostRoute(r.getGateway(), bestRoute.getGateway()); 1372 } 1373 modifyRoute(ifaceName, lp, bestRoute, cycleCount+1, doAdd, toDefaultTable); 1374 } 1375 } 1376 if (doAdd) { 1377 if (VDBG) log("Adding " + r + " for interface " + ifaceName); 1378 try { 1379 if (toDefaultTable) { 1380 mAddedRoutes.add(r); // only track default table - only one apps can effect 1381 mNetd.addRoute(ifaceName, r); 1382 } else { 1383 mNetd.addSecondaryRoute(ifaceName, r); 1384 } 1385 } catch (Exception e) { 1386 // never crash - catch them all 1387 if (DBG) loge("Exception trying to add a route: " + e); 1388 return false; 1389 } 1390 } else { 1391 // if we remove this one and there are no more like it, then refcount==0 and 1392 // we can remove it from the table 1393 if (toDefaultTable) { 1394 mAddedRoutes.remove(r); 1395 if (mAddedRoutes.contains(r) == false) { 1396 if (VDBG) log("Removing " + r + " for interface " + ifaceName); 1397 try { 1398 mNetd.removeRoute(ifaceName, r); 1399 } catch (Exception e) { 1400 // never crash - catch them all 1401 if (VDBG) loge("Exception trying to remove a route: " + e); 1402 return false; 1403 } 1404 } else { 1405 if (VDBG) log("not removing " + r + " as it's still in use"); 1406 } 1407 } else { 1408 if (VDBG) log("Removing " + r + " for interface " + ifaceName); 1409 try { 1410 mNetd.removeSecondaryRoute(ifaceName, r); 1411 } catch (Exception e) { 1412 // never crash - catch them all 1413 if (VDBG) loge("Exception trying to remove a route: " + e); 1414 return false; 1415 } 1416 } 1417 } 1418 return true; 1419 } 1420 1421 /** 1422 * @see ConnectivityManager#getMobileDataEnabled() 1423 */ 1424 public boolean getMobileDataEnabled() { 1425 // TODO: This detail should probably be in DataConnectionTracker's 1426 // which is where we store the value and maybe make this 1427 // asynchronous. 1428 enforceAccessPermission(); 1429 boolean retVal = Settings.Secure.getInt(mContext.getContentResolver(), 1430 Settings.Secure.MOBILE_DATA, 1) == 1; 1431 if (VDBG) log("getMobileDataEnabled returning " + retVal); 1432 return retVal; 1433 } 1434 1435 public void setDataDependency(int networkType, boolean met) { 1436 enforceConnectivityInternalPermission(); 1437 1438 mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_DEPENDENCY_MET, 1439 (met ? ENABLED : DISABLED), networkType)); 1440 } 1441 1442 private void handleSetDependencyMet(int networkType, boolean met) { 1443 if (mNetTrackers[networkType] != null) { 1444 if (DBG) { 1445 log("handleSetDependencyMet(" + networkType + ", " + met + ")"); 1446 } 1447 mNetTrackers[networkType].setDependencyMet(met); 1448 } 1449 } 1450 1451 private INetworkPolicyListener mPolicyListener = new INetworkPolicyListener.Stub() { 1452 @Override 1453 public void onUidRulesChanged(int uid, int uidRules) { 1454 // caller is NPMS, since we only register with them 1455 if (LOGD_RULES) { 1456 log("onUidRulesChanged(uid=" + uid + ", uidRules=" + uidRules + ")"); 1457 } 1458 1459 synchronized (mRulesLock) { 1460 // skip update when we've already applied rules 1461 final int oldRules = mUidRules.get(uid, RULE_ALLOW_ALL); 1462 if (oldRules == uidRules) return; 1463 1464 mUidRules.put(uid, uidRules); 1465 } 1466 1467 // TODO: notify UID when it has requested targeted updates 1468 } 1469 1470 @Override 1471 public void onMeteredIfacesChanged(String[] meteredIfaces) { 1472 // caller is NPMS, since we only register with them 1473 if (LOGD_RULES) { 1474 log("onMeteredIfacesChanged(ifaces=" + Arrays.toString(meteredIfaces) + ")"); 1475 } 1476 1477 synchronized (mRulesLock) { 1478 mMeteredIfaces.clear(); 1479 for (String iface : meteredIfaces) { 1480 mMeteredIfaces.add(iface); 1481 } 1482 } 1483 } 1484 1485 @Override 1486 public void onRestrictBackgroundChanged(boolean restrictBackground) { 1487 // caller is NPMS, since we only register with them 1488 if (LOGD_RULES) { 1489 log("onRestrictBackgroundChanged(restrictBackground=" + restrictBackground + ")"); 1490 } 1491 1492 // kick off connectivity change broadcast for active network, since 1493 // global background policy change is radical. 1494 final int networkType = mActiveDefaultNetwork; 1495 if (isNetworkTypeValid(networkType)) { 1496 final NetworkStateTracker tracker = mNetTrackers[networkType]; 1497 if (tracker != null) { 1498 final NetworkInfo info = tracker.getNetworkInfo(); 1499 if (info != null && info.isConnected()) { 1500 sendConnectedBroadcast(info); 1501 } 1502 } 1503 } 1504 } 1505 }; 1506 1507 /** 1508 * @see ConnectivityManager#setMobileDataEnabled(boolean) 1509 */ 1510 public void setMobileDataEnabled(boolean enabled) { 1511 enforceChangePermission(); 1512 if (DBG) log("setMobileDataEnabled(" + enabled + ")"); 1513 1514 mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_MOBILE_DATA, 1515 (enabled ? ENABLED : DISABLED), 0)); 1516 } 1517 1518 private void handleSetMobileData(boolean enabled) { 1519 if (mNetTrackers[ConnectivityManager.TYPE_MOBILE] != null) { 1520 if (VDBG) { 1521 log(mNetTrackers[ConnectivityManager.TYPE_MOBILE].toString() + enabled); 1522 } 1523 mNetTrackers[ConnectivityManager.TYPE_MOBILE].setUserDataEnable(enabled); 1524 } 1525 if (mNetTrackers[ConnectivityManager.TYPE_WIMAX] != null) { 1526 if (VDBG) { 1527 log(mNetTrackers[ConnectivityManager.TYPE_WIMAX].toString() + enabled); 1528 } 1529 mNetTrackers[ConnectivityManager.TYPE_WIMAX].setUserDataEnable(enabled); 1530 } 1531 } 1532 1533 @Override 1534 public void setPolicyDataEnable(int networkType, boolean enabled) { 1535 // only someone like NPMS should only be calling us 1536 mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); 1537 1538 mHandler.sendMessage(mHandler.obtainMessage( 1539 EVENT_SET_POLICY_DATA_ENABLE, networkType, (enabled ? ENABLED : DISABLED))); 1540 } 1541 1542 private void handleSetPolicyDataEnable(int networkType, boolean enabled) { 1543 if (isNetworkTypeValid(networkType)) { 1544 final NetworkStateTracker tracker = mNetTrackers[networkType]; 1545 if (tracker != null) { 1546 tracker.setPolicyDataEnable(enabled); 1547 } 1548 } 1549 } 1550 1551 private void enforceAccessPermission() { 1552 mContext.enforceCallingOrSelfPermission( 1553 android.Manifest.permission.ACCESS_NETWORK_STATE, 1554 "ConnectivityService"); 1555 } 1556 1557 private void enforceChangePermission() { 1558 mContext.enforceCallingOrSelfPermission( 1559 android.Manifest.permission.CHANGE_NETWORK_STATE, 1560 "ConnectivityService"); 1561 } 1562 1563 // TODO Make this a special check when it goes public 1564 private void enforceTetherChangePermission() { 1565 mContext.enforceCallingOrSelfPermission( 1566 android.Manifest.permission.CHANGE_NETWORK_STATE, 1567 "ConnectivityService"); 1568 } 1569 1570 private void enforceTetherAccessPermission() { 1571 mContext.enforceCallingOrSelfPermission( 1572 android.Manifest.permission.ACCESS_NETWORK_STATE, 1573 "ConnectivityService"); 1574 } 1575 1576 private void enforceConnectivityInternalPermission() { 1577 mContext.enforceCallingOrSelfPermission( 1578 android.Manifest.permission.CONNECTIVITY_INTERNAL, 1579 "ConnectivityService"); 1580 } 1581 1582 /** 1583 * Handle a {@code DISCONNECTED} event. If this pertains to the non-active 1584 * network, we ignore it. If it is for the active network, we send out a 1585 * broadcast. But first, we check whether it might be possible to connect 1586 * to a different network. 1587 * @param info the {@code NetworkInfo} for the network 1588 */ 1589 private void handleDisconnect(NetworkInfo info) { 1590 1591 int prevNetType = info.getType(); 1592 1593 mNetTrackers[prevNetType].setTeardownRequested(false); 1594 /* 1595 * If the disconnected network is not the active one, then don't report 1596 * this as a loss of connectivity. What probably happened is that we're 1597 * getting the disconnect for a network that we explicitly disabled 1598 * in accordance with network preference policies. 1599 */ 1600 if (!mNetConfigs[prevNetType].isDefault()) { 1601 List pids = mNetRequestersPids[prevNetType]; 1602 for (int i = 0; i<pids.size(); i++) { 1603 Integer pid = (Integer)pids.get(i); 1604 // will remove them because the net's no longer connected 1605 // need to do this now as only now do we know the pids and 1606 // can properly null things that are no longer referenced. 1607 reassessPidDns(pid.intValue(), false); 1608 } 1609 } 1610 1611 Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION); 1612 intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info); 1613 if (info.isFailover()) { 1614 intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true); 1615 info.setFailover(false); 1616 } 1617 if (info.getReason() != null) { 1618 intent.putExtra(ConnectivityManager.EXTRA_REASON, info.getReason()); 1619 } 1620 if (info.getExtraInfo() != null) { 1621 intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO, 1622 info.getExtraInfo()); 1623 } 1624 1625 if (mNetConfigs[prevNetType].isDefault()) { 1626 tryFailover(prevNetType); 1627 if (mActiveDefaultNetwork != -1) { 1628 NetworkInfo switchTo = mNetTrackers[mActiveDefaultNetwork].getNetworkInfo(); 1629 intent.putExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO, switchTo); 1630 } else { 1631 mDefaultInetConditionPublished = 0; // we're not connected anymore 1632 intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true); 1633 } 1634 } 1635 intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION, mDefaultInetConditionPublished); 1636 1637 // Reset interface if no other connections are using the same interface 1638 boolean doReset = true; 1639 LinkProperties linkProperties = mNetTrackers[prevNetType].getLinkProperties(); 1640 if (linkProperties != null) { 1641 String oldIface = linkProperties.getInterfaceName(); 1642 if (TextUtils.isEmpty(oldIface) == false) { 1643 for (NetworkStateTracker networkStateTracker : mNetTrackers) { 1644 if (networkStateTracker == null) continue; 1645 NetworkInfo networkInfo = networkStateTracker.getNetworkInfo(); 1646 if (networkInfo.isConnected() && networkInfo.getType() != prevNetType) { 1647 LinkProperties l = networkStateTracker.getLinkProperties(); 1648 if (l == null) continue; 1649 if (oldIface.equals(l.getInterfaceName())) { 1650 doReset = false; 1651 break; 1652 } 1653 } 1654 } 1655 } 1656 } 1657 1658 // do this before we broadcast the change 1659 handleConnectivityChange(prevNetType, doReset); 1660 1661 final Intent immediateIntent = new Intent(intent); 1662 immediateIntent.setAction(CONNECTIVITY_ACTION_IMMEDIATE); 1663 sendStickyBroadcast(immediateIntent); 1664 sendStickyBroadcastDelayed(intent, getConnectivityChangeDelay()); 1665 /* 1666 * If the failover network is already connected, then immediately send 1667 * out a followup broadcast indicating successful failover 1668 */ 1669 if (mActiveDefaultNetwork != -1) { 1670 sendConnectedBroadcastDelayed(mNetTrackers[mActiveDefaultNetwork].getNetworkInfo(), 1671 getConnectivityChangeDelay()); 1672 } 1673 } 1674 1675 private void tryFailover(int prevNetType) { 1676 /* 1677 * If this is a default network, check if other defaults are available. 1678 * Try to reconnect on all available and let them hash it out when 1679 * more than one connects. 1680 */ 1681 if (mNetConfigs[prevNetType].isDefault()) { 1682 if (mActiveDefaultNetwork == prevNetType) { 1683 mActiveDefaultNetwork = -1; 1684 } 1685 1686 // don't signal a reconnect for anything lower or equal priority than our 1687 // current connected default 1688 // TODO - don't filter by priority now - nice optimization but risky 1689// int currentPriority = -1; 1690// if (mActiveDefaultNetwork != -1) { 1691// currentPriority = mNetConfigs[mActiveDefaultNetwork].mPriority; 1692// } 1693 for (int checkType=0; checkType <= ConnectivityManager.MAX_NETWORK_TYPE; checkType++) { 1694 if (checkType == prevNetType) continue; 1695 if (mNetConfigs[checkType] == null) continue; 1696 if (!mNetConfigs[checkType].isDefault()) continue; 1697 if (mNetTrackers[checkType] == null) continue; 1698 1699// Enabling the isAvailable() optimization caused mobile to not get 1700// selected if it was in the middle of error handling. Specifically 1701// a moble connection that took 30 seconds to complete the DEACTIVATE_DATA_CALL 1702// would not be available and we wouldn't get connected to anything. 1703// So removing the isAvailable() optimization below for now. TODO: This 1704// optimization should work and we need to investigate why it doesn't work. 1705// This could be related to how DEACTIVATE_DATA_CALL is reporting its 1706// complete before it is really complete. 1707// if (!mNetTrackers[checkType].isAvailable()) continue; 1708 1709// if (currentPriority >= mNetConfigs[checkType].mPriority) continue; 1710 1711 NetworkStateTracker checkTracker = mNetTrackers[checkType]; 1712 NetworkInfo checkInfo = checkTracker.getNetworkInfo(); 1713 if (!checkInfo.isConnectedOrConnecting() || checkTracker.isTeardownRequested()) { 1714 checkInfo.setFailover(true); 1715 checkTracker.reconnect(); 1716 } 1717 if (DBG) log("Attempting to switch to " + checkInfo.getTypeName()); 1718 } 1719 } 1720 } 1721 1722 private void sendConnectedBroadcast(NetworkInfo info) { 1723 sendGeneralBroadcast(info, CONNECTIVITY_ACTION_IMMEDIATE); 1724 sendGeneralBroadcast(info, CONNECTIVITY_ACTION); 1725 } 1726 1727 private void sendConnectedBroadcastDelayed(NetworkInfo info, int delayMs) { 1728 sendGeneralBroadcast(info, CONNECTIVITY_ACTION_IMMEDIATE); 1729 sendGeneralBroadcastDelayed(info, CONNECTIVITY_ACTION, delayMs); 1730 } 1731 1732 private void sendInetConditionBroadcast(NetworkInfo info) { 1733 sendGeneralBroadcast(info, ConnectivityManager.INET_CONDITION_ACTION); 1734 } 1735 1736 private Intent makeGeneralIntent(NetworkInfo info, String bcastType) { 1737 Intent intent = new Intent(bcastType); 1738 intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info); 1739 if (info.isFailover()) { 1740 intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true); 1741 info.setFailover(false); 1742 } 1743 if (info.getReason() != null) { 1744 intent.putExtra(ConnectivityManager.EXTRA_REASON, info.getReason()); 1745 } 1746 if (info.getExtraInfo() != null) { 1747 intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO, 1748 info.getExtraInfo()); 1749 } 1750 intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION, mDefaultInetConditionPublished); 1751 return intent; 1752 } 1753 1754 private void sendGeneralBroadcast(NetworkInfo info, String bcastType) { 1755 sendStickyBroadcast(makeGeneralIntent(info, bcastType)); 1756 } 1757 1758 private void sendGeneralBroadcastDelayed(NetworkInfo info, String bcastType, int delayMs) { 1759 sendStickyBroadcastDelayed(makeGeneralIntent(info, bcastType), delayMs); 1760 } 1761 1762 /** 1763 * Called when an attempt to fail over to another network has failed. 1764 * @param info the {@link NetworkInfo} for the failed network 1765 */ 1766 private void handleConnectionFailure(NetworkInfo info) { 1767 mNetTrackers[info.getType()].setTeardownRequested(false); 1768 1769 String reason = info.getReason(); 1770 String extraInfo = info.getExtraInfo(); 1771 1772 String reasonText; 1773 if (reason == null) { 1774 reasonText = "."; 1775 } else { 1776 reasonText = " (" + reason + ")."; 1777 } 1778 loge("Attempt to connect to " + info.getTypeName() + " failed" + reasonText); 1779 1780 Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION); 1781 intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info); 1782 if (getActiveNetworkInfo() == null) { 1783 intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true); 1784 } 1785 if (reason != null) { 1786 intent.putExtra(ConnectivityManager.EXTRA_REASON, reason); 1787 } 1788 if (extraInfo != null) { 1789 intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO, extraInfo); 1790 } 1791 if (info.isFailover()) { 1792 intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true); 1793 info.setFailover(false); 1794 } 1795 1796 if (mNetConfigs[info.getType()].isDefault()) { 1797 tryFailover(info.getType()); 1798 if (mActiveDefaultNetwork != -1) { 1799 NetworkInfo switchTo = mNetTrackers[mActiveDefaultNetwork].getNetworkInfo(); 1800 intent.putExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO, switchTo); 1801 } else { 1802 mDefaultInetConditionPublished = 0; 1803 intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true); 1804 } 1805 } 1806 1807 intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION, mDefaultInetConditionPublished); 1808 1809 final Intent immediateIntent = new Intent(intent); 1810 immediateIntent.setAction(CONNECTIVITY_ACTION_IMMEDIATE); 1811 sendStickyBroadcast(immediateIntent); 1812 sendStickyBroadcast(intent); 1813 /* 1814 * If the failover network is already connected, then immediately send 1815 * out a followup broadcast indicating successful failover 1816 */ 1817 if (mActiveDefaultNetwork != -1) { 1818 sendConnectedBroadcast(mNetTrackers[mActiveDefaultNetwork].getNetworkInfo()); 1819 } 1820 } 1821 1822 private void sendStickyBroadcast(Intent intent) { 1823 synchronized(this) { 1824 if (!mSystemReady) { 1825 mInitialBroadcast = new Intent(intent); 1826 } 1827 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 1828 if (VDBG) { 1829 log("sendStickyBroadcast: action=" + intent.getAction()); 1830 } 1831 1832 mContext.sendStickyBroadcast(intent); 1833 } 1834 } 1835 1836 private void sendStickyBroadcastDelayed(Intent intent, int delayMs) { 1837 if (delayMs <= 0) { 1838 sendStickyBroadcast(intent); 1839 } else { 1840 if (VDBG) { 1841 log("sendStickyBroadcastDelayed: delayMs=" + delayMs + ", action=" 1842 + intent.getAction()); 1843 } 1844 mHandler.sendMessageDelayed(mHandler.obtainMessage( 1845 EVENT_SEND_STICKY_BROADCAST_INTENT, intent), delayMs); 1846 } 1847 } 1848 1849 void systemReady() { 1850 synchronized(this) { 1851 mSystemReady = true; 1852 if (mInitialBroadcast != null) { 1853 mContext.sendStickyBroadcast(mInitialBroadcast); 1854 mInitialBroadcast = null; 1855 } 1856 } 1857 // load the global proxy at startup 1858 mHandler.sendMessage(mHandler.obtainMessage(EVENT_APPLY_GLOBAL_HTTP_PROXY)); 1859 } 1860 1861 private void handleConnect(NetworkInfo info) { 1862 final int type = info.getType(); 1863 1864 // snapshot isFailover, because sendConnectedBroadcast() resets it 1865 boolean isFailover = info.isFailover(); 1866 final NetworkStateTracker thisNet = mNetTrackers[type]; 1867 1868 // if this is a default net and other default is running 1869 // kill the one not preferred 1870 if (mNetConfigs[type].isDefault()) { 1871 if (mActiveDefaultNetwork != -1 && mActiveDefaultNetwork != type) { 1872 if ((type != mNetworkPreference && 1873 mNetConfigs[mActiveDefaultNetwork].priority > 1874 mNetConfigs[type].priority) || 1875 mNetworkPreference == mActiveDefaultNetwork) { 1876 // don't accept this one 1877 if (VDBG) { 1878 log("Not broadcasting CONNECT_ACTION " + 1879 "to torn down network " + info.getTypeName()); 1880 } 1881 teardown(thisNet); 1882 return; 1883 } else { 1884 // tear down the other 1885 NetworkStateTracker otherNet = 1886 mNetTrackers[mActiveDefaultNetwork]; 1887 if (DBG) { 1888 log("Policy requires " + otherNet.getNetworkInfo().getTypeName() + 1889 " teardown"); 1890 } 1891 if (!teardown(otherNet)) { 1892 loge("Network declined teardown request"); 1893 teardown(thisNet); 1894 return; 1895 } 1896 } 1897 } 1898 synchronized (ConnectivityService.this) { 1899 // have a new default network, release the transition wakelock in a second 1900 // if it's held. The second pause is to allow apps to reconnect over the 1901 // new network 1902 if (mNetTransitionWakeLock.isHeld()) { 1903 mHandler.sendMessageDelayed(mHandler.obtainMessage( 1904 EVENT_CLEAR_NET_TRANSITION_WAKELOCK, 1905 mNetTransitionWakeLockSerialNumber, 0), 1906 1000); 1907 } 1908 } 1909 mActiveDefaultNetwork = type; 1910 // this will cause us to come up initially as unconnected and switching 1911 // to connected after our normal pause unless somebody reports us as reall 1912 // disconnected 1913 mDefaultInetConditionPublished = 0; 1914 mDefaultConnectionSequence++; 1915 mInetConditionChangeInFlight = false; 1916 // Don't do this - if we never sign in stay, grey 1917 //reportNetworkCondition(mActiveDefaultNetwork, 100); 1918 } 1919 thisNet.setTeardownRequested(false); 1920 updateNetworkSettings(thisNet); 1921 handleConnectivityChange(type, false); 1922 sendConnectedBroadcastDelayed(info, getConnectivityChangeDelay()); 1923 1924 // notify battery stats service about this network 1925 final String iface = thisNet.getLinkProperties().getInterfaceName(); 1926 if (iface != null) { 1927 try { 1928 BatteryStatsService.getService().noteNetworkInterfaceType(iface, type); 1929 } catch (RemoteException e) { 1930 // ignored; service lives in system_server 1931 } 1932 } 1933 } 1934 1935 /** 1936 * After a change in the connectivity state of a network. We're mainly 1937 * concerned with making sure that the list of DNS servers is set up 1938 * according to which networks are connected, and ensuring that the 1939 * right routing table entries exist. 1940 */ 1941 private void handleConnectivityChange(int netType, boolean doReset) { 1942 int resetMask = doReset ? NetworkUtils.RESET_ALL_ADDRESSES : 0; 1943 1944 /* 1945 * If a non-default network is enabled, add the host routes that 1946 * will allow it's DNS servers to be accessed. 1947 */ 1948 handleDnsConfigurationChange(netType); 1949 1950 LinkProperties curLp = mCurrentLinkProperties[netType]; 1951 LinkProperties newLp = null; 1952 1953 if (mNetTrackers[netType].getNetworkInfo().isConnected()) { 1954 newLp = mNetTrackers[netType].getLinkProperties(); 1955 if (VDBG) { 1956 log("handleConnectivityChange: changed linkProperty[" + netType + "]:" + 1957 " doReset=" + doReset + " resetMask=" + resetMask + 1958 "\n curLp=" + curLp + 1959 "\n newLp=" + newLp); 1960 } 1961 1962 if (curLp != null) { 1963 if (curLp.isIdenticalInterfaceName(newLp)) { 1964 CompareResult<LinkAddress> car = curLp.compareAddresses(newLp); 1965 if ((car.removed.size() != 0) || (car.added.size() != 0)) { 1966 for (LinkAddress linkAddr : car.removed) { 1967 if (linkAddr.getAddress() instanceof Inet4Address) { 1968 resetMask |= NetworkUtils.RESET_IPV4_ADDRESSES; 1969 } 1970 if (linkAddr.getAddress() instanceof Inet6Address) { 1971 resetMask |= NetworkUtils.RESET_IPV6_ADDRESSES; 1972 } 1973 } 1974 if (DBG) { 1975 log("handleConnectivityChange: addresses changed" + 1976 " linkProperty[" + netType + "]:" + " resetMask=" + resetMask + 1977 "\n car=" + car); 1978 } 1979 } else { 1980 if (DBG) { 1981 log("handleConnectivityChange: address are the same reset per doReset" + 1982 " linkProperty[" + netType + "]:" + 1983 " resetMask=" + resetMask); 1984 } 1985 } 1986 } else { 1987 resetMask = NetworkUtils.RESET_ALL_ADDRESSES; 1988 if (DBG) { 1989 log("handleConnectivityChange: interface not not equivalent reset both" + 1990 " linkProperty[" + netType + "]:" + 1991 " resetMask=" + resetMask); 1992 } 1993 } 1994 } 1995 if (mNetConfigs[netType].isDefault()) { 1996 handleApplyDefaultProxy(newLp.getHttpProxy()); 1997 } 1998 } else { 1999 if (VDBG) { 2000 log("handleConnectivityChange: changed linkProperty[" + netType + "]:" + 2001 " doReset=" + doReset + " resetMask=" + resetMask + 2002 "\n curLp=" + curLp + 2003 "\n newLp= null"); 2004 } 2005 } 2006 mCurrentLinkProperties[netType] = newLp; 2007 boolean resetDns = updateRoutes(newLp, curLp, mNetConfigs[netType].isDefault()); 2008 2009 if (resetMask != 0 || resetDns) { 2010 LinkProperties linkProperties = mNetTrackers[netType].getLinkProperties(); 2011 if (linkProperties != null) { 2012 String iface = linkProperties.getInterfaceName(); 2013 if (TextUtils.isEmpty(iface) == false) { 2014 if (resetMask != 0) { 2015 if (DBG) log("resetConnections(" + iface + ", " + resetMask + ")"); 2016 NetworkUtils.resetConnections(iface, resetMask); 2017 2018 // Tell VPN the interface is down. It is a temporary 2019 // but effective fix to make VPN aware of the change. 2020 if ((resetMask & NetworkUtils.RESET_IPV4_ADDRESSES) != 0) { 2021 mVpn.interfaceStatusChanged(iface, false); 2022 } 2023 } 2024 if (resetDns) { 2025 if (VDBG) log("resetting DNS cache for " + iface); 2026 try { 2027 mNetd.flushInterfaceDnsCache(iface); 2028 } catch (Exception e) { 2029 // never crash - catch them all 2030 if (DBG) loge("Exception resetting dns cache: " + e); 2031 } 2032 } 2033 } 2034 } 2035 } 2036 2037 // TODO: Temporary notifying upstread change to Tethering. 2038 // @see bug/4455071 2039 /** Notify TetheringService if interface name has been changed. */ 2040 if (TextUtils.equals(mNetTrackers[netType].getNetworkInfo().getReason(), 2041 PhoneConstants.REASON_LINK_PROPERTIES_CHANGED)) { 2042 if (isTetheringSupported()) { 2043 mTethering.handleTetherIfaceChange(); 2044 } 2045 } 2046 } 2047 2048 /** 2049 * Add and remove routes using the old properties (null if not previously connected), 2050 * new properties (null if becoming disconnected). May even be double null, which 2051 * is a noop. 2052 * Uses isLinkDefault to determine if default routes should be set or conversely if 2053 * host routes should be set to the dns servers 2054 * returns a boolean indicating the routes changed 2055 */ 2056 private boolean updateRoutes(LinkProperties newLp, LinkProperties curLp, 2057 boolean isLinkDefault) { 2058 Collection<RouteInfo> routesToAdd = null; 2059 CompareResult<InetAddress> dnsDiff = new CompareResult<InetAddress>(); 2060 CompareResult<RouteInfo> routeDiff = new CompareResult<RouteInfo>(); 2061 if (curLp != null) { 2062 // check for the delta between the current set and the new 2063 routeDiff = curLp.compareRoutes(newLp); 2064 dnsDiff = curLp.compareDnses(newLp); 2065 } else if (newLp != null) { 2066 routeDiff.added = newLp.getRoutes(); 2067 dnsDiff.added = newLp.getDnses(); 2068 } 2069 2070 boolean routesChanged = (routeDiff.removed.size() != 0 || routeDiff.added.size() != 0); 2071 2072 for (RouteInfo r : routeDiff.removed) { 2073 if (isLinkDefault || ! r.isDefaultRoute()) { 2074 removeRoute(curLp, r, TO_DEFAULT_TABLE); 2075 } 2076 if (isLinkDefault == false) { 2077 // remove from a secondary route table 2078 removeRoute(curLp, r, TO_SECONDARY_TABLE); 2079 } 2080 } 2081 2082 for (RouteInfo r : routeDiff.added) { 2083 if (isLinkDefault || ! r.isDefaultRoute()) { 2084 addRoute(newLp, r, TO_DEFAULT_TABLE); 2085 } else { 2086 // add to a secondary route table 2087 addRoute(newLp, r, TO_SECONDARY_TABLE); 2088 2089 // many radios add a default route even when we don't want one. 2090 // remove the default route unless somebody else has asked for it 2091 String ifaceName = newLp.getInterfaceName(); 2092 if (TextUtils.isEmpty(ifaceName) == false && mAddedRoutes.contains(r) == false) { 2093 if (VDBG) log("Removing " + r + " for interface " + ifaceName); 2094 try { 2095 mNetd.removeRoute(ifaceName, r); 2096 } catch (Exception e) { 2097 // never crash - catch them all 2098 if (DBG) loge("Exception trying to remove a route: " + e); 2099 } 2100 } 2101 } 2102 } 2103 2104 if (!isLinkDefault) { 2105 // handle DNS routes 2106 if (routesChanged) { 2107 // routes changed - remove all old dns entries and add new 2108 if (curLp != null) { 2109 for (InetAddress oldDns : curLp.getDnses()) { 2110 removeRouteToAddress(curLp, oldDns); 2111 } 2112 } 2113 if (newLp != null) { 2114 for (InetAddress newDns : newLp.getDnses()) { 2115 addRouteToAddress(newLp, newDns); 2116 } 2117 } 2118 } else { 2119 // no change in routes, check for change in dns themselves 2120 for (InetAddress oldDns : dnsDiff.removed) { 2121 removeRouteToAddress(curLp, oldDns); 2122 } 2123 for (InetAddress newDns : dnsDiff.added) { 2124 addRouteToAddress(newLp, newDns); 2125 } 2126 } 2127 } 2128 return routesChanged; 2129 } 2130 2131 2132 /** 2133 * Reads the network specific TCP buffer sizes from SystemProperties 2134 * net.tcp.buffersize.[default|wifi|umts|edge|gprs] and set them for system 2135 * wide use 2136 */ 2137 public void updateNetworkSettings(NetworkStateTracker nt) { 2138 String key = nt.getTcpBufferSizesPropName(); 2139 String bufferSizes = SystemProperties.get(key); 2140 2141 if (bufferSizes.length() == 0) { 2142 if (VDBG) log(key + " not found in system properties. Using defaults"); 2143 2144 // Setting to default values so we won't be stuck to previous values 2145 key = "net.tcp.buffersize.default"; 2146 bufferSizes = SystemProperties.get(key); 2147 } 2148 2149 // Set values in kernel 2150 if (bufferSizes.length() != 0) { 2151 if (VDBG) { 2152 log("Setting TCP values: [" + bufferSizes 2153 + "] which comes from [" + key + "]"); 2154 } 2155 setBufferSize(bufferSizes); 2156 } 2157 } 2158 2159 /** 2160 * Writes TCP buffer sizes to /sys/kernel/ipv4/tcp_[r/w]mem_[min/def/max] 2161 * which maps to /proc/sys/net/ipv4/tcp_rmem and tcpwmem 2162 * 2163 * @param bufferSizes in the format of "readMin, readInitial, readMax, 2164 * writeMin, writeInitial, writeMax" 2165 */ 2166 private void setBufferSize(String bufferSizes) { 2167 try { 2168 String[] values = bufferSizes.split(","); 2169 2170 if (values.length == 6) { 2171 final String prefix = "/sys/kernel/ipv4/tcp_"; 2172 FileUtils.stringToFile(prefix + "rmem_min", values[0]); 2173 FileUtils.stringToFile(prefix + "rmem_def", values[1]); 2174 FileUtils.stringToFile(prefix + "rmem_max", values[2]); 2175 FileUtils.stringToFile(prefix + "wmem_min", values[3]); 2176 FileUtils.stringToFile(prefix + "wmem_def", values[4]); 2177 FileUtils.stringToFile(prefix + "wmem_max", values[5]); 2178 } else { 2179 loge("Invalid buffersize string: " + bufferSizes); 2180 } 2181 } catch (IOException e) { 2182 loge("Can't set tcp buffer sizes:" + e); 2183 } 2184 } 2185 2186 /** 2187 * Adjust the per-process dns entries (net.dns<x>.<pid>) based 2188 * on the highest priority active net which this process requested. 2189 * If there aren't any, clear it out 2190 */ 2191 private void reassessPidDns(int myPid, boolean doBump) 2192 { 2193 if (VDBG) log("reassessPidDns for pid " + myPid); 2194 for(int i : mPriorityList) { 2195 if (mNetConfigs[i].isDefault()) { 2196 continue; 2197 } 2198 NetworkStateTracker nt = mNetTrackers[i]; 2199 if (nt.getNetworkInfo().isConnected() && 2200 !nt.isTeardownRequested()) { 2201 LinkProperties p = nt.getLinkProperties(); 2202 if (p == null) continue; 2203 List pids = mNetRequestersPids[i]; 2204 for (int j=0; j<pids.size(); j++) { 2205 Integer pid = (Integer)pids.get(j); 2206 if (pid.intValue() == myPid) { 2207 Collection<InetAddress> dnses = p.getDnses(); 2208 writePidDns(dnses, myPid); 2209 if (doBump) { 2210 bumpDns(); 2211 } 2212 return; 2213 } 2214 } 2215 } 2216 } 2217 // nothing found - delete 2218 for (int i = 1; ; i++) { 2219 String prop = "net.dns" + i + "." + myPid; 2220 if (SystemProperties.get(prop).length() == 0) { 2221 if (doBump) { 2222 bumpDns(); 2223 } 2224 return; 2225 } 2226 SystemProperties.set(prop, ""); 2227 } 2228 } 2229 2230 // return true if results in a change 2231 private boolean writePidDns(Collection <InetAddress> dnses, int pid) { 2232 int j = 1; 2233 boolean changed = false; 2234 for (InetAddress dns : dnses) { 2235 String dnsString = dns.getHostAddress(); 2236 if (changed || !dnsString.equals(SystemProperties.get("net.dns" + j + "." + pid))) { 2237 changed = true; 2238 SystemProperties.set("net.dns" + j + "." + pid, dns.getHostAddress()); 2239 } 2240 j++; 2241 } 2242 return changed; 2243 } 2244 2245 private void bumpDns() { 2246 /* 2247 * Bump the property that tells the name resolver library to reread 2248 * the DNS server list from the properties. 2249 */ 2250 String propVal = SystemProperties.get("net.dnschange"); 2251 int n = 0; 2252 if (propVal.length() != 0) { 2253 try { 2254 n = Integer.parseInt(propVal); 2255 } catch (NumberFormatException e) {} 2256 } 2257 SystemProperties.set("net.dnschange", "" + (n+1)); 2258 /* 2259 * Tell the VMs to toss their DNS caches 2260 */ 2261 Intent intent = new Intent(Intent.ACTION_CLEAR_DNS_CACHE); 2262 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); 2263 /* 2264 * Connectivity events can happen before boot has completed ... 2265 */ 2266 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 2267 mContext.sendBroadcast(intent); 2268 } 2269 2270 // Caller must grab mDnsLock. 2271 private boolean updateDns(String network, String iface, 2272 Collection<InetAddress> dnses, String domains) { 2273 boolean changed = false; 2274 int last = 0; 2275 if (dnses.size() == 0 && mDefaultDns != null) { 2276 ++last; 2277 String value = mDefaultDns.getHostAddress(); 2278 if (!value.equals(SystemProperties.get("net.dns1"))) { 2279 if (DBG) { 2280 loge("no dns provided for " + network + " - using " + value); 2281 } 2282 changed = true; 2283 SystemProperties.set("net.dns1", value); 2284 } 2285 } else { 2286 for (InetAddress dns : dnses) { 2287 ++last; 2288 String key = "net.dns" + last; 2289 String value = dns.getHostAddress(); 2290 if (!changed && value.equals(SystemProperties.get(key))) { 2291 continue; 2292 } 2293 if (VDBG) { 2294 log("adding dns " + value + " for " + network); 2295 } 2296 changed = true; 2297 SystemProperties.set(key, value); 2298 } 2299 } 2300 for (int i = last + 1; i <= mNumDnsEntries; ++i) { 2301 String key = "net.dns" + i; 2302 if (VDBG) log("erasing " + key); 2303 changed = true; 2304 SystemProperties.set(key, ""); 2305 } 2306 mNumDnsEntries = last; 2307 2308 if (changed) { 2309 try { 2310 mNetd.setDnsServersForInterface(iface, NetworkUtils.makeStrings(dnses)); 2311 mNetd.setDefaultInterfaceForDns(iface); 2312 } catch (Exception e) { 2313 if (DBG) loge("exception setting default dns interface: " + e); 2314 } 2315 } 2316 if (!domains.equals(SystemProperties.get("net.dns.search"))) { 2317 SystemProperties.set("net.dns.search", domains); 2318 changed = true; 2319 } 2320 return changed; 2321 } 2322 2323 private void handleDnsConfigurationChange(int netType) { 2324 // add default net's dns entries 2325 NetworkStateTracker nt = mNetTrackers[netType]; 2326 if (nt != null && nt.getNetworkInfo().isConnected() && !nt.isTeardownRequested()) { 2327 LinkProperties p = nt.getLinkProperties(); 2328 if (p == null) return; 2329 Collection<InetAddress> dnses = p.getDnses(); 2330 boolean changed = false; 2331 if (mNetConfigs[netType].isDefault()) { 2332 String network = nt.getNetworkInfo().getTypeName(); 2333 synchronized (mDnsLock) { 2334 if (!mDnsOverridden) { 2335 changed = updateDns(network, p.getInterfaceName(), dnses, ""); 2336 } 2337 } 2338 } else { 2339 try { 2340 mNetd.setDnsServersForInterface(p.getInterfaceName(), 2341 NetworkUtils.makeStrings(dnses)); 2342 } catch (Exception e) { 2343 if (DBG) loge("exception setting dns servers: " + e); 2344 } 2345 // set per-pid dns for attached secondary nets 2346 List pids = mNetRequestersPids[netType]; 2347 for (int y=0; y< pids.size(); y++) { 2348 Integer pid = (Integer)pids.get(y); 2349 changed = writePidDns(dnses, pid.intValue()); 2350 } 2351 } 2352 if (changed) bumpDns(); 2353 } 2354 } 2355 2356 private int getRestoreDefaultNetworkDelay(int networkType) { 2357 String restoreDefaultNetworkDelayStr = SystemProperties.get( 2358 NETWORK_RESTORE_DELAY_PROP_NAME); 2359 if(restoreDefaultNetworkDelayStr != null && 2360 restoreDefaultNetworkDelayStr.length() != 0) { 2361 try { 2362 return Integer.valueOf(restoreDefaultNetworkDelayStr); 2363 } catch (NumberFormatException e) { 2364 } 2365 } 2366 // if the system property isn't set, use the value for the apn type 2367 int ret = RESTORE_DEFAULT_NETWORK_DELAY; 2368 2369 if ((networkType <= ConnectivityManager.MAX_NETWORK_TYPE) && 2370 (mNetConfigs[networkType] != null)) { 2371 ret = mNetConfigs[networkType].restoreTime; 2372 } 2373 return ret; 2374 } 2375 2376 @Override 2377 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 2378 if (mContext.checkCallingOrSelfPermission( 2379 android.Manifest.permission.DUMP) 2380 != PackageManager.PERMISSION_GRANTED) { 2381 pw.println("Permission Denial: can't dump ConnectivityService " + 2382 "from from pid=" + Binder.getCallingPid() + ", uid=" + 2383 Binder.getCallingUid()); 2384 return; 2385 } 2386 pw.println(); 2387 for (NetworkStateTracker nst : mNetTrackers) { 2388 if (nst != null) { 2389 if (nst.getNetworkInfo().isConnected()) { 2390 pw.println("Active network: " + nst.getNetworkInfo(). 2391 getTypeName()); 2392 } 2393 pw.println(nst.getNetworkInfo()); 2394 pw.println(nst); 2395 pw.println(); 2396 } 2397 } 2398 2399 pw.println("Network Requester Pids:"); 2400 for (int net : mPriorityList) { 2401 String pidString = net + ": "; 2402 for (Object pid : mNetRequestersPids[net]) { 2403 pidString = pidString + pid.toString() + ", "; 2404 } 2405 pw.println(pidString); 2406 } 2407 pw.println(); 2408 2409 pw.println("FeatureUsers:"); 2410 for (Object requester : mFeatureUsers) { 2411 pw.println(requester.toString()); 2412 } 2413 pw.println(); 2414 2415 synchronized (this) { 2416 pw.println("NetworkTranstionWakeLock is currently " + 2417 (mNetTransitionWakeLock.isHeld() ? "" : "not ") + "held."); 2418 pw.println("It was last requested for "+mNetTransitionWakeLockCausedBy); 2419 } 2420 pw.println(); 2421 2422 mTethering.dump(fd, pw, args); 2423 2424 if (mInetLog != null) { 2425 pw.println(); 2426 pw.println("Inet condition reports:"); 2427 for(int i = 0; i < mInetLog.size(); i++) { 2428 pw.println(mInetLog.get(i)); 2429 } 2430 } 2431 } 2432 2433 // must be stateless - things change under us. 2434 private class MyHandler extends Handler { 2435 public MyHandler(Looper looper) { 2436 super(looper); 2437 } 2438 2439 @Override 2440 public void handleMessage(Message msg) { 2441 NetworkInfo info; 2442 switch (msg.what) { 2443 case NetworkStateTracker.EVENT_STATE_CHANGED: 2444 info = (NetworkInfo) msg.obj; 2445 int type = info.getType(); 2446 NetworkInfo.State state = info.getState(); 2447 2448 if (VDBG || (state == NetworkInfo.State.CONNECTED) || 2449 (state == NetworkInfo.State.DISCONNECTED)) { 2450 log("ConnectivityChange for " + 2451 info.getTypeName() + ": " + 2452 state + "/" + info.getDetailedState()); 2453 } 2454 2455 // Connectivity state changed: 2456 // [31-14] Reserved for future use 2457 // [13-10] Network subtype (for mobile network, as defined 2458 // by TelephonyManager) 2459 // [9-4] Detailed state ordinal (as defined by 2460 // NetworkInfo.DetailedState) 2461 // [3-0] Network type (as defined by ConnectivityManager) 2462 int eventLogParam = (info.getType() & 0xf) | 2463 ((info.getDetailedState().ordinal() & 0x3f) << 4) | 2464 (info.getSubtype() << 10); 2465 EventLog.writeEvent(EventLogTags.CONNECTIVITY_STATE_CHANGED, 2466 eventLogParam); 2467 2468 if (info.getDetailedState() == 2469 NetworkInfo.DetailedState.FAILED) { 2470 handleConnectionFailure(info); 2471 } else if (state == NetworkInfo.State.DISCONNECTED) { 2472 handleDisconnect(info); 2473 } else if (state == NetworkInfo.State.SUSPENDED) { 2474 // TODO: need to think this over. 2475 // the logic here is, handle SUSPENDED the same as 2476 // DISCONNECTED. The only difference being we are 2477 // broadcasting an intent with NetworkInfo that's 2478 // suspended. This allows the applications an 2479 // opportunity to handle DISCONNECTED and SUSPENDED 2480 // differently, or not. 2481 handleDisconnect(info); 2482 } else if (state == NetworkInfo.State.CONNECTED) { 2483 handleConnect(info); 2484 } 2485 break; 2486 case NetworkStateTracker.EVENT_CONFIGURATION_CHANGED: 2487 info = (NetworkInfo) msg.obj; 2488 // TODO: Temporary allowing network configuration 2489 // change not resetting sockets. 2490 // @see bug/4455071 2491 handleConnectivityChange(info.getType(), false); 2492 break; 2493 case EVENT_CLEAR_NET_TRANSITION_WAKELOCK: 2494 String causedBy = null; 2495 synchronized (ConnectivityService.this) { 2496 if (msg.arg1 == mNetTransitionWakeLockSerialNumber && 2497 mNetTransitionWakeLock.isHeld()) { 2498 mNetTransitionWakeLock.release(); 2499 causedBy = mNetTransitionWakeLockCausedBy; 2500 } 2501 } 2502 if (causedBy != null) { 2503 log("NetTransition Wakelock for " + causedBy + " released by timeout"); 2504 } 2505 break; 2506 case EVENT_RESTORE_DEFAULT_NETWORK: 2507 FeatureUser u = (FeatureUser)msg.obj; 2508 u.expire(); 2509 break; 2510 case EVENT_INET_CONDITION_CHANGE: 2511 { 2512 int netType = msg.arg1; 2513 int condition = msg.arg2; 2514 handleInetConditionChange(netType, condition); 2515 break; 2516 } 2517 case EVENT_INET_CONDITION_HOLD_END: 2518 { 2519 int netType = msg.arg1; 2520 int sequence = msg.arg2; 2521 handleInetConditionHoldEnd(netType, sequence); 2522 break; 2523 } 2524 case EVENT_SET_NETWORK_PREFERENCE: 2525 { 2526 int preference = msg.arg1; 2527 handleSetNetworkPreference(preference); 2528 break; 2529 } 2530 case EVENT_SET_MOBILE_DATA: 2531 { 2532 boolean enabled = (msg.arg1 == ENABLED); 2533 handleSetMobileData(enabled); 2534 break; 2535 } 2536 case EVENT_APPLY_GLOBAL_HTTP_PROXY: 2537 { 2538 handleDeprecatedGlobalHttpProxy(); 2539 break; 2540 } 2541 case EVENT_SET_DEPENDENCY_MET: 2542 { 2543 boolean met = (msg.arg1 == ENABLED); 2544 handleSetDependencyMet(msg.arg2, met); 2545 break; 2546 } 2547 case EVENT_RESTORE_DNS: 2548 { 2549 if (mActiveDefaultNetwork != -1) { 2550 handleDnsConfigurationChange(mActiveDefaultNetwork); 2551 } 2552 break; 2553 } 2554 case EVENT_SEND_STICKY_BROADCAST_INTENT: 2555 { 2556 Intent intent = (Intent)msg.obj; 2557 sendStickyBroadcast(intent); 2558 break; 2559 } 2560 case EVENT_SET_POLICY_DATA_ENABLE: { 2561 final int networkType = msg.arg1; 2562 final boolean enabled = msg.arg2 == ENABLED; 2563 handleSetPolicyDataEnable(networkType, enabled); 2564 } 2565 } 2566 } 2567 } 2568 2569 // javadoc from interface 2570 public int tether(String iface) { 2571 enforceTetherChangePermission(); 2572 2573 if (isTetheringSupported()) { 2574 return mTethering.tether(iface); 2575 } else { 2576 return ConnectivityManager.TETHER_ERROR_UNSUPPORTED; 2577 } 2578 } 2579 2580 // javadoc from interface 2581 public int untether(String iface) { 2582 enforceTetherChangePermission(); 2583 2584 if (isTetheringSupported()) { 2585 return mTethering.untether(iface); 2586 } else { 2587 return ConnectivityManager.TETHER_ERROR_UNSUPPORTED; 2588 } 2589 } 2590 2591 // javadoc from interface 2592 public int getLastTetherError(String iface) { 2593 enforceTetherAccessPermission(); 2594 2595 if (isTetheringSupported()) { 2596 return mTethering.getLastTetherError(iface); 2597 } else { 2598 return ConnectivityManager.TETHER_ERROR_UNSUPPORTED; 2599 } 2600 } 2601 2602 // TODO - proper iface API for selection by property, inspection, etc 2603 public String[] getTetherableUsbRegexs() { 2604 enforceTetherAccessPermission(); 2605 if (isTetheringSupported()) { 2606 return mTethering.getTetherableUsbRegexs(); 2607 } else { 2608 return new String[0]; 2609 } 2610 } 2611 2612 public String[] getTetherableWifiRegexs() { 2613 enforceTetherAccessPermission(); 2614 if (isTetheringSupported()) { 2615 return mTethering.getTetherableWifiRegexs(); 2616 } else { 2617 return new String[0]; 2618 } 2619 } 2620 2621 public String[] getTetherableBluetoothRegexs() { 2622 enforceTetherAccessPermission(); 2623 if (isTetheringSupported()) { 2624 return mTethering.getTetherableBluetoothRegexs(); 2625 } else { 2626 return new String[0]; 2627 } 2628 } 2629 2630 public int setUsbTethering(boolean enable) { 2631 enforceTetherAccessPermission(); 2632 if (isTetheringSupported()) { 2633 return mTethering.setUsbTethering(enable); 2634 } else { 2635 return ConnectivityManager.TETHER_ERROR_UNSUPPORTED; 2636 } 2637 } 2638 2639 // TODO - move iface listing, queries, etc to new module 2640 // javadoc from interface 2641 public String[] getTetherableIfaces() { 2642 enforceTetherAccessPermission(); 2643 return mTethering.getTetherableIfaces(); 2644 } 2645 2646 public String[] getTetheredIfaces() { 2647 enforceTetherAccessPermission(); 2648 return mTethering.getTetheredIfaces(); 2649 } 2650 2651 @Override 2652 public String[] getTetheredIfacePairs() { 2653 enforceTetherAccessPermission(); 2654 return mTethering.getTetheredIfacePairs(); 2655 } 2656 2657 public String[] getTetheringErroredIfaces() { 2658 enforceTetherAccessPermission(); 2659 return mTethering.getErroredIfaces(); 2660 } 2661 2662 // if ro.tether.denied = true we default to no tethering 2663 // gservices could set the secure setting to 1 though to enable it on a build where it 2664 // had previously been turned off. 2665 public boolean isTetheringSupported() { 2666 enforceTetherAccessPermission(); 2667 int defaultVal = (SystemProperties.get("ro.tether.denied").equals("true") ? 0 : 1); 2668 boolean tetherEnabledInSettings = (Settings.Secure.getInt(mContext.getContentResolver(), 2669 Settings.Secure.TETHER_SUPPORTED, defaultVal) != 0); 2670 return tetherEnabledInSettings && mTetheringConfigValid; 2671 } 2672 2673 // An API NetworkStateTrackers can call when they lose their network. 2674 // This will automatically be cleared after X seconds or a network becomes CONNECTED, 2675 // whichever happens first. The timer is started by the first caller and not 2676 // restarted by subsequent callers. 2677 public void requestNetworkTransitionWakelock(String forWhom) { 2678 enforceConnectivityInternalPermission(); 2679 synchronized (this) { 2680 if (mNetTransitionWakeLock.isHeld()) return; 2681 mNetTransitionWakeLockSerialNumber++; 2682 mNetTransitionWakeLock.acquire(); 2683 mNetTransitionWakeLockCausedBy = forWhom; 2684 } 2685 mHandler.sendMessageDelayed(mHandler.obtainMessage( 2686 EVENT_CLEAR_NET_TRANSITION_WAKELOCK, 2687 mNetTransitionWakeLockSerialNumber, 0), 2688 mNetTransitionWakeLockTimeout); 2689 return; 2690 } 2691 2692 // 100 percent is full good, 0 is full bad. 2693 public void reportInetCondition(int networkType, int percentage) { 2694 if (VDBG) log("reportNetworkCondition(" + networkType + ", " + percentage + ")"); 2695 mContext.enforceCallingOrSelfPermission( 2696 android.Manifest.permission.STATUS_BAR, 2697 "ConnectivityService"); 2698 2699 if (DBG) { 2700 int pid = getCallingPid(); 2701 int uid = getCallingUid(); 2702 String s = pid + "(" + uid + ") reports inet is " + 2703 (percentage > 50 ? "connected" : "disconnected") + " (" + percentage + ") on " + 2704 "network Type " + networkType + " at " + GregorianCalendar.getInstance().getTime(); 2705 mInetLog.add(s); 2706 while(mInetLog.size() > INET_CONDITION_LOG_MAX_SIZE) { 2707 mInetLog.remove(0); 2708 } 2709 } 2710 mHandler.sendMessage(mHandler.obtainMessage( 2711 EVENT_INET_CONDITION_CHANGE, networkType, percentage)); 2712 } 2713 2714 private void handleInetConditionChange(int netType, int condition) { 2715 if (mActiveDefaultNetwork == -1) { 2716 if (DBG) log("handleInetConditionChange: no active default network - ignore"); 2717 return; 2718 } 2719 if (mActiveDefaultNetwork != netType) { 2720 if (DBG) log("handleInetConditionChange: net=" + netType + 2721 " != default=" + mActiveDefaultNetwork + " - ignore"); 2722 return; 2723 } 2724 if (VDBG) { 2725 log("handleInetConditionChange: net=" + 2726 netType + ", condition=" + condition + 2727 ",mActiveDefaultNetwork=" + mActiveDefaultNetwork); 2728 } 2729 mDefaultInetCondition = condition; 2730 int delay; 2731 if (mInetConditionChangeInFlight == false) { 2732 if (VDBG) log("handleInetConditionChange: starting a change hold"); 2733 // setup a new hold to debounce this 2734 if (mDefaultInetCondition > 50) { 2735 delay = Settings.Secure.getInt(mContext.getContentResolver(), 2736 Settings.Secure.INET_CONDITION_DEBOUNCE_UP_DELAY, 500); 2737 } else { 2738 delay = Settings.Secure.getInt(mContext.getContentResolver(), 2739 Settings.Secure.INET_CONDITION_DEBOUNCE_DOWN_DELAY, 3000); 2740 } 2741 mInetConditionChangeInFlight = true; 2742 mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_INET_CONDITION_HOLD_END, 2743 mActiveDefaultNetwork, mDefaultConnectionSequence), delay); 2744 } else { 2745 // we've set the new condition, when this hold ends that will get picked up 2746 if (VDBG) log("handleInetConditionChange: currently in hold - not setting new end evt"); 2747 } 2748 } 2749 2750 private void handleInetConditionHoldEnd(int netType, int sequence) { 2751 if (DBG) { 2752 log("handleInetConditionHoldEnd: net=" + netType + 2753 ", condition=" + mDefaultInetCondition + 2754 ", published condition=" + mDefaultInetConditionPublished); 2755 } 2756 mInetConditionChangeInFlight = false; 2757 2758 if (mActiveDefaultNetwork == -1) { 2759 if (DBG) log("handleInetConditionHoldEnd: no active default network - ignoring"); 2760 return; 2761 } 2762 if (mDefaultConnectionSequence != sequence) { 2763 if (DBG) log("handleInetConditionHoldEnd: event hold for obsolete network - ignoring"); 2764 return; 2765 } 2766 // TODO: Figure out why this optimization sometimes causes a 2767 // change in mDefaultInetCondition to be missed and the 2768 // UI to not be updated. 2769 //if (mDefaultInetConditionPublished == mDefaultInetCondition) { 2770 // if (DBG) log("no change in condition - aborting"); 2771 // return; 2772 //} 2773 NetworkInfo networkInfo = mNetTrackers[mActiveDefaultNetwork].getNetworkInfo(); 2774 if (networkInfo.isConnected() == false) { 2775 if (DBG) log("handleInetConditionHoldEnd: default network not connected - ignoring"); 2776 return; 2777 } 2778 mDefaultInetConditionPublished = mDefaultInetCondition; 2779 sendInetConditionBroadcast(networkInfo); 2780 return; 2781 } 2782 2783 public ProxyProperties getProxy() { 2784 synchronized (mDefaultProxyLock) { 2785 return mDefaultProxyDisabled ? null : mDefaultProxy; 2786 } 2787 } 2788 2789 public void setGlobalProxy(ProxyProperties proxyProperties) { 2790 enforceChangePermission(); 2791 synchronized (mGlobalProxyLock) { 2792 if (proxyProperties == mGlobalProxy) return; 2793 if (proxyProperties != null && proxyProperties.equals(mGlobalProxy)) return; 2794 if (mGlobalProxy != null && mGlobalProxy.equals(proxyProperties)) return; 2795 2796 String host = ""; 2797 int port = 0; 2798 String exclList = ""; 2799 if (proxyProperties != null && !TextUtils.isEmpty(proxyProperties.getHost())) { 2800 mGlobalProxy = new ProxyProperties(proxyProperties); 2801 host = mGlobalProxy.getHost(); 2802 port = mGlobalProxy.getPort(); 2803 exclList = mGlobalProxy.getExclusionList(); 2804 } else { 2805 mGlobalProxy = null; 2806 } 2807 ContentResolver res = mContext.getContentResolver(); 2808 Settings.Secure.putString(res, Settings.Secure.GLOBAL_HTTP_PROXY_HOST, host); 2809 Settings.Secure.putInt(res, Settings.Secure.GLOBAL_HTTP_PROXY_PORT, port); 2810 Settings.Secure.putString(res, Settings.Secure.GLOBAL_HTTP_PROXY_EXCLUSION_LIST, 2811 exclList); 2812 } 2813 2814 if (mGlobalProxy == null) { 2815 proxyProperties = mDefaultProxy; 2816 } 2817 //sendProxyBroadcast(proxyProperties); 2818 } 2819 2820 private void loadGlobalProxy() { 2821 ContentResolver res = mContext.getContentResolver(); 2822 String host = Settings.Secure.getString(res, Settings.Secure.GLOBAL_HTTP_PROXY_HOST); 2823 int port = Settings.Secure.getInt(res, Settings.Secure.GLOBAL_HTTP_PROXY_PORT, 0); 2824 String exclList = Settings.Secure.getString(res, 2825 Settings.Secure.GLOBAL_HTTP_PROXY_EXCLUSION_LIST); 2826 if (!TextUtils.isEmpty(host)) { 2827 ProxyProperties proxyProperties = new ProxyProperties(host, port, exclList); 2828 synchronized (mGlobalProxyLock) { 2829 mGlobalProxy = proxyProperties; 2830 } 2831 } 2832 } 2833 2834 public ProxyProperties getGlobalProxy() { 2835 synchronized (mGlobalProxyLock) { 2836 return mGlobalProxy; 2837 } 2838 } 2839 2840 private void handleApplyDefaultProxy(ProxyProperties proxy) { 2841 if (proxy != null && TextUtils.isEmpty(proxy.getHost())) { 2842 proxy = null; 2843 } 2844 synchronized (mDefaultProxyLock) { 2845 if (mDefaultProxy != null && mDefaultProxy.equals(proxy)) return; 2846 if (mDefaultProxy == proxy) return; 2847 mDefaultProxy = proxy; 2848 2849 if (!mDefaultProxyDisabled) { 2850 sendProxyBroadcast(proxy); 2851 } 2852 } 2853 } 2854 2855 private void handleDeprecatedGlobalHttpProxy() { 2856 String proxy = Settings.Secure.getString(mContext.getContentResolver(), 2857 Settings.Secure.HTTP_PROXY); 2858 if (!TextUtils.isEmpty(proxy)) { 2859 String data[] = proxy.split(":"); 2860 String proxyHost = data[0]; 2861 int proxyPort = 8080; 2862 if (data.length > 1) { 2863 try { 2864 proxyPort = Integer.parseInt(data[1]); 2865 } catch (NumberFormatException e) { 2866 return; 2867 } 2868 } 2869 ProxyProperties p = new ProxyProperties(data[0], proxyPort, ""); 2870 setGlobalProxy(p); 2871 } 2872 } 2873 2874 private void sendProxyBroadcast(ProxyProperties proxy) { 2875 if (proxy == null) proxy = new ProxyProperties("", 0, ""); 2876 if (DBG) log("sending Proxy Broadcast for " + proxy); 2877 Intent intent = new Intent(Proxy.PROXY_CHANGE_ACTION); 2878 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING | 2879 Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 2880 intent.putExtra(Proxy.EXTRA_PROXY_INFO, proxy); 2881 mContext.sendStickyBroadcast(intent); 2882 } 2883 2884 private static class SettingsObserver extends ContentObserver { 2885 private int mWhat; 2886 private Handler mHandler; 2887 SettingsObserver(Handler handler, int what) { 2888 super(handler); 2889 mHandler = handler; 2890 mWhat = what; 2891 } 2892 2893 void observe(Context context) { 2894 ContentResolver resolver = context.getContentResolver(); 2895 resolver.registerContentObserver(Settings.Secure.getUriFor( 2896 Settings.Secure.HTTP_PROXY), false, this); 2897 } 2898 2899 @Override 2900 public void onChange(boolean selfChange) { 2901 mHandler.obtainMessage(mWhat).sendToTarget(); 2902 } 2903 } 2904 2905 private void log(String s) { 2906 Slog.d(TAG, s); 2907 } 2908 2909 private void loge(String s) { 2910 Slog.e(TAG, s); 2911 } 2912 2913 int convertFeatureToNetworkType(int networkType, String feature) { 2914 int usedNetworkType = networkType; 2915 2916 if(networkType == ConnectivityManager.TYPE_MOBILE) { 2917 if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_MMS)) { 2918 usedNetworkType = ConnectivityManager.TYPE_MOBILE_MMS; 2919 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_SUPL)) { 2920 usedNetworkType = ConnectivityManager.TYPE_MOBILE_SUPL; 2921 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_DUN) || 2922 TextUtils.equals(feature, Phone.FEATURE_ENABLE_DUN_ALWAYS)) { 2923 usedNetworkType = ConnectivityManager.TYPE_MOBILE_DUN; 2924 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_HIPRI)) { 2925 usedNetworkType = ConnectivityManager.TYPE_MOBILE_HIPRI; 2926 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_FOTA)) { 2927 usedNetworkType = ConnectivityManager.TYPE_MOBILE_FOTA; 2928 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_IMS)) { 2929 usedNetworkType = ConnectivityManager.TYPE_MOBILE_IMS; 2930 } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_CBS)) { 2931 usedNetworkType = ConnectivityManager.TYPE_MOBILE_CBS; 2932 } else { 2933 Slog.e(TAG, "Can't match any mobile netTracker!"); 2934 } 2935 } else if (networkType == ConnectivityManager.TYPE_WIFI) { 2936 if (TextUtils.equals(feature, "p2p")) { 2937 usedNetworkType = ConnectivityManager.TYPE_WIFI_P2P; 2938 } else { 2939 Slog.e(TAG, "Can't match any wifi netTracker!"); 2940 } 2941 } else { 2942 Slog.e(TAG, "Unexpected network type"); 2943 } 2944 return usedNetworkType; 2945 } 2946 2947 private static <T> T checkNotNull(T value, String message) { 2948 if (value == null) { 2949 throw new NullPointerException(message); 2950 } 2951 return value; 2952 } 2953 2954 /** 2955 * Protect a socket from VPN routing rules. This method is used by 2956 * VpnBuilder and not available in ConnectivityManager. Permissions 2957 * are checked in Vpn class. 2958 * @hide 2959 */ 2960 @Override 2961 public boolean protectVpn(ParcelFileDescriptor socket) { 2962 try { 2963 int type = mActiveDefaultNetwork; 2964 if (ConnectivityManager.isNetworkTypeValid(type)) { 2965 mVpn.protect(socket, mNetTrackers[type].getLinkProperties().getInterfaceName()); 2966 return true; 2967 } 2968 } catch (Exception e) { 2969 // ignore 2970 } finally { 2971 try { 2972 socket.close(); 2973 } catch (Exception e) { 2974 // ignore 2975 } 2976 } 2977 return false; 2978 } 2979 2980 /** 2981 * Prepare for a VPN application. This method is used by VpnDialogs 2982 * and not available in ConnectivityManager. Permissions are checked 2983 * in Vpn class. 2984 * @hide 2985 */ 2986 @Override 2987 public boolean prepareVpn(String oldPackage, String newPackage) { 2988 return mVpn.prepare(oldPackage, newPackage); 2989 } 2990 2991 /** 2992 * Configure a TUN interface and return its file descriptor. Parameters 2993 * are encoded and opaque to this class. This method is used by VpnBuilder 2994 * and not available in ConnectivityManager. Permissions are checked in 2995 * Vpn class. 2996 * @hide 2997 */ 2998 @Override 2999 public ParcelFileDescriptor establishVpn(VpnConfig config) { 3000 return mVpn.establish(config); 3001 } 3002 3003 /** 3004 * Start legacy VPN and return an intent to VpnDialogs. This method is 3005 * used by VpnSettings and not available in ConnectivityManager. 3006 * Permissions are checked in Vpn class. 3007 * @hide 3008 */ 3009 @Override 3010 public void startLegacyVpn(VpnConfig config, String[] racoon, String[] mtpd) { 3011 mVpn.startLegacyVpn(config, racoon, mtpd); 3012 } 3013 3014 /** 3015 * Return the information of the ongoing legacy VPN. This method is used 3016 * by VpnSettings and not available in ConnectivityManager. Permissions 3017 * are checked in Vpn class. 3018 * @hide 3019 */ 3020 @Override 3021 public LegacyVpnInfo getLegacyVpnInfo() { 3022 return mVpn.getLegacyVpnInfo(); 3023 } 3024 3025 /** 3026 * Callback for VPN subsystem. Currently VPN is not adapted to the service 3027 * through NetworkStateTracker since it works differently. For example, it 3028 * needs to override DNS servers but never takes the default routes. It 3029 * relies on another data network, and it could keep existing connections 3030 * alive after reconnecting, switching between networks, or even resuming 3031 * from deep sleep. Calls from applications should be done synchronously 3032 * to avoid race conditions. As these are all hidden APIs, refactoring can 3033 * be done whenever a better abstraction is developed. 3034 */ 3035 public class VpnCallback { 3036 3037 private VpnCallback() { 3038 } 3039 3040 public void override(List<String> dnsServers, List<String> searchDomains) { 3041 if (dnsServers == null) { 3042 restore(); 3043 return; 3044 } 3045 3046 // Convert DNS servers into addresses. 3047 List<InetAddress> addresses = new ArrayList<InetAddress>(); 3048 for (String address : dnsServers) { 3049 // Double check the addresses and remove invalid ones. 3050 try { 3051 addresses.add(InetAddress.parseNumericAddress(address)); 3052 } catch (Exception e) { 3053 // ignore 3054 } 3055 } 3056 if (addresses.isEmpty()) { 3057 restore(); 3058 return; 3059 } 3060 3061 // Concatenate search domains into a string. 3062 StringBuilder buffer = new StringBuilder(); 3063 if (searchDomains != null) { 3064 for (String domain : searchDomains) { 3065 buffer.append(domain).append(' '); 3066 } 3067 } 3068 String domains = buffer.toString().trim(); 3069 3070 // Apply DNS changes. 3071 boolean changed = false; 3072 synchronized (mDnsLock) { 3073 changed = updateDns("VPN", "VPN", addresses, domains); 3074 mDnsOverridden = true; 3075 } 3076 if (changed) { 3077 bumpDns(); 3078 } 3079 3080 // Temporarily disable the default proxy. 3081 synchronized (mDefaultProxyLock) { 3082 mDefaultProxyDisabled = true; 3083 if (mDefaultProxy != null) { 3084 sendProxyBroadcast(null); 3085 } 3086 } 3087 3088 // TODO: support proxy per network. 3089 } 3090 3091 public void restore() { 3092 synchronized (mDnsLock) { 3093 if (mDnsOverridden) { 3094 mDnsOverridden = false; 3095 mHandler.sendEmptyMessage(EVENT_RESTORE_DNS); 3096 } 3097 } 3098 synchronized (mDefaultProxyLock) { 3099 mDefaultProxyDisabled = false; 3100 if (mDefaultProxy != null) { 3101 sendProxyBroadcast(mDefaultProxy); 3102 } 3103 } 3104 } 3105 } 3106} 3107