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