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