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