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