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