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