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