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