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