Tethering.java revision ea9cc488eb0f096c9fd402eff49e3d30f5b6de2e
1/* 2 * Copyright (C) 2010 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.connectivity; 18 19import static android.hardware.usb.UsbManager.USB_CONNECTED; 20import static android.hardware.usb.UsbManager.USB_FUNCTION_RNDIS; 21import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_STATE; 22import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLED; 23 24import android.app.Notification; 25import android.app.NotificationManager; 26import android.app.PendingIntent; 27import android.bluetooth.BluetoothAdapter; 28import android.bluetooth.BluetoothPan; 29import android.bluetooth.BluetoothProfile; 30import android.bluetooth.BluetoothProfile.ServiceListener; 31import android.content.BroadcastReceiver; 32import android.content.ComponentName; 33import android.content.Context; 34import android.content.Intent; 35import android.content.IntentFilter; 36import android.content.pm.PackageManager; 37import android.content.res.Resources; 38import android.hardware.usb.UsbManager; 39import android.net.ConnectivityManager; 40import android.net.INetworkPolicyManager; 41import android.net.INetworkStatsService; 42import android.net.LinkProperties; 43import android.net.Network; 44import android.net.NetworkCapabilities; 45import android.net.NetworkInfo; 46import android.net.NetworkRequest; 47import android.net.NetworkState; 48import android.net.NetworkUtils; 49import android.net.RouteInfo; 50import android.net.wifi.WifiManager; 51import android.os.Binder; 52import android.os.Bundle; 53import android.os.INetworkManagementService; 54import android.os.Looper; 55import android.os.Message; 56import android.os.Parcel; 57import android.os.RemoteException; 58import android.os.ResultReceiver; 59import android.os.UserHandle; 60import android.provider.Settings; 61import android.telephony.CarrierConfigManager; 62import android.telephony.TelephonyManager; 63import android.text.TextUtils; 64import android.util.ArrayMap; 65import android.util.Log; 66import android.util.SparseArray; 67 68import com.android.internal.annotations.VisibleForTesting; 69import com.android.internal.telephony.IccCardConstants; 70import com.android.internal.telephony.TelephonyIntents; 71import com.android.internal.util.IndentingPrintWriter; 72import com.android.internal.util.MessageUtils; 73import com.android.internal.util.Protocol; 74import com.android.internal.util.State; 75import com.android.internal.util.StateMachine; 76import com.android.server.connectivity.tethering.IControlsTethering; 77import com.android.server.connectivity.tethering.IPv6TetheringCoordinator; 78import com.android.server.connectivity.tethering.IPv6TetheringInterfaceServices; 79import com.android.server.connectivity.tethering.OffloadController; 80import com.android.server.connectivity.tethering.TetherInterfaceStateMachine; 81import com.android.server.connectivity.tethering.TetheringConfiguration; 82import com.android.server.connectivity.tethering.UpstreamNetworkMonitor; 83import com.android.server.net.BaseNetworkObserver; 84 85import java.io.FileDescriptor; 86import java.io.PrintWriter; 87import java.net.Inet4Address; 88import java.net.InetAddress; 89import java.util.ArrayList; 90import java.util.Arrays; 91import java.util.Collection; 92import java.util.HashMap; 93import java.util.HashSet; 94import java.util.Iterator; 95import java.util.Map; 96import java.util.concurrent.atomic.AtomicInteger; 97 98 99/** 100 * @hide 101 * 102 * This class holds much of the business logic to allow Android devices 103 * to act as IP gateways via USB, BT, and WiFi interfaces. 104 */ 105public class Tethering extends BaseNetworkObserver implements IControlsTethering { 106 107 private final static String TAG = Tethering.class.getSimpleName(); 108 private final static boolean DBG = false; 109 private final static boolean VDBG = false; 110 111 protected static final String DISABLE_PROVISIONING_SYSPROP_KEY = "net.tethering.noprovisioning"; 112 113 private static final Class[] messageClasses = { 114 Tethering.class, TetherMasterSM.class, TetherInterfaceStateMachine.class 115 }; 116 private static final SparseArray<String> sMagicDecoderRing = 117 MessageUtils.findMessageNames(messageClasses); 118 119 // {@link ComponentName} of the Service used to run tether provisioning. 120 private static final ComponentName TETHER_SERVICE = ComponentName.unflattenFromString(Resources 121 .getSystem().getString(com.android.internal.R.string.config_wifi_tether_enable)); 122 123 private static class TetherState { 124 public final TetherInterfaceStateMachine stateMachine; 125 public int lastState; 126 public int lastError; 127 128 public TetherState(TetherInterfaceStateMachine sm) { 129 stateMachine = sm; 130 // Assume all state machines start out available and with no errors. 131 lastState = IControlsTethering.STATE_AVAILABLE; 132 lastError = ConnectivityManager.TETHER_ERROR_NO_ERROR; 133 } 134 135 public boolean isCurrentlyServing() { 136 switch (lastState) { 137 case IControlsTethering.STATE_TETHERED: 138 case IControlsTethering.STATE_LOCAL_HOTSPOT: 139 return true; 140 default: 141 return false; 142 } 143 } 144 } 145 146 // used to synchronize public access to members 147 private final Object mPublicSync; 148 private final Context mContext; 149 private final ArrayMap<String, TetherState> mTetherStates; 150 private final BroadcastReceiver mStateReceiver; 151 private final INetworkManagementService mNMService; 152 private final INetworkStatsService mStatsService; 153 private final INetworkPolicyManager mPolicyManager; 154 private final Looper mLooper; 155 private final MockableSystemProperties mSystemProperties; 156 private final StateMachine mTetherMasterSM; 157 private final OffloadController mOffloadController; 158 private final UpstreamNetworkMonitor mUpstreamNetworkMonitor; 159 private final HashSet<TetherInterfaceStateMachine> mForwardedDownstreams; 160 161 private volatile TetheringConfiguration mConfig; 162 private String mCurrentUpstreamIface; 163 private Notification.Builder mTetheredNotificationBuilder; 164 private int mLastNotificationId; 165 166 private boolean mRndisEnabled; // track the RNDIS function enabled state 167 private boolean mUsbTetherRequested; // true if USB tethering should be started 168 // when RNDIS is enabled 169 // True iff WiFi tethering should be started when soft AP is ready. 170 private boolean mWifiTetherRequested; 171 172 public Tethering(Context context, INetworkManagementService nmService, 173 INetworkStatsService statsService, INetworkPolicyManager policyManager, 174 Looper looper, MockableSystemProperties systemProperties) { 175 mContext = context; 176 mNMService = nmService; 177 mStatsService = statsService; 178 mPolicyManager = policyManager; 179 mLooper = looper; 180 mSystemProperties = systemProperties; 181 182 mPublicSync = new Object(); 183 184 mTetherStates = new ArrayMap<>(); 185 186 mTetherMasterSM = new TetherMasterSM("TetherMaster", mLooper); 187 mTetherMasterSM.start(); 188 189 mOffloadController = new OffloadController(mTetherMasterSM.getHandler()); 190 mUpstreamNetworkMonitor = new UpstreamNetworkMonitor( 191 mContext, mTetherMasterSM, TetherMasterSM.EVENT_UPSTREAM_CALLBACK); 192 mForwardedDownstreams = new HashSet<>(); 193 194 mStateReceiver = new StateReceiver(); 195 IntentFilter filter = new IntentFilter(); 196 filter.addAction(UsbManager.ACTION_USB_STATE); 197 filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); 198 filter.addAction(WifiManager.WIFI_AP_STATE_CHANGED_ACTION); 199 filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED); 200 mContext.registerReceiver(mStateReceiver, filter, null, mTetherMasterSM.getHandler()); 201 202 filter = new IntentFilter(); 203 filter.addAction(Intent.ACTION_MEDIA_SHARED); 204 filter.addAction(Intent.ACTION_MEDIA_UNSHARED); 205 filter.addDataScheme("file"); 206 mContext.registerReceiver(mStateReceiver, filter, null, mTetherMasterSM.getHandler()); 207 208 // load device config info 209 updateConfiguration(); 210 } 211 212 // We can't do this once in the Tethering() constructor and cache the value, because the 213 // CONNECTIVITY_SERVICE is registered only after the Tethering() constructor has completed. 214 private ConnectivityManager getConnectivityManager() { 215 return (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE); 216 } 217 218 private void updateConfiguration() { 219 mConfig = new TetheringConfiguration(mContext); 220 } 221 222 @Override 223 public void interfaceStatusChanged(String iface, boolean up) { 224 // Never called directly: only called from interfaceLinkStateChanged. 225 // See NetlinkHandler.cpp:71. 226 if (VDBG) Log.d(TAG, "interfaceStatusChanged " + iface + ", " + up); 227 synchronized (mPublicSync) { 228 int interfaceType = ifaceNameToType(iface); 229 if (interfaceType == ConnectivityManager.TETHERING_INVALID) { 230 return; 231 } 232 233 TetherState tetherState = mTetherStates.get(iface); 234 if (up) { 235 if (tetherState == null) { 236 trackNewTetherableInterface(iface, interfaceType); 237 } 238 } else { 239 if (interfaceType == ConnectivityManager.TETHERING_BLUETOOTH) { 240 tetherState.stateMachine.sendMessage( 241 TetherInterfaceStateMachine.CMD_INTERFACE_DOWN); 242 mTetherStates.remove(iface); 243 } else { 244 // Ignore usb0 down after enabling RNDIS. 245 // We will handle disconnect in interfaceRemoved. 246 // Similarly, ignore interface down for WiFi. We monitor WiFi AP status 247 // through the WifiManager.WIFI_AP_STATE_CHANGED_ACTION intent. 248 if (VDBG) Log.d(TAG, "ignore interface down for " + iface); 249 } 250 } 251 } 252 } 253 254 @Override 255 public void interfaceLinkStateChanged(String iface, boolean up) { 256 interfaceStatusChanged(iface, up); 257 } 258 259 private int ifaceNameToType(String iface) { 260 final TetheringConfiguration cfg = mConfig; 261 262 if (cfg.isWifi(iface)) { 263 return ConnectivityManager.TETHERING_WIFI; 264 } else if (cfg.isUsb(iface)) { 265 return ConnectivityManager.TETHERING_USB; 266 } else if (cfg.isBluetooth(iface)) { 267 return ConnectivityManager.TETHERING_BLUETOOTH; 268 } 269 return ConnectivityManager.TETHERING_INVALID; 270 } 271 272 @Override 273 public void interfaceAdded(String iface) { 274 if (VDBG) Log.d(TAG, "interfaceAdded " + iface); 275 synchronized (mPublicSync) { 276 int interfaceType = ifaceNameToType(iface); 277 if (interfaceType == ConnectivityManager.TETHERING_INVALID) { 278 if (VDBG) Log.d(TAG, iface + " is not a tetherable iface, ignoring"); 279 return; 280 } 281 282 TetherState tetherState = mTetherStates.get(iface); 283 if (tetherState == null) { 284 trackNewTetherableInterface(iface, interfaceType); 285 } else { 286 if (VDBG) Log.d(TAG, "active iface (" + iface + ") reported as added, ignoring"); 287 } 288 } 289 } 290 291 @Override 292 public void interfaceRemoved(String iface) { 293 if (VDBG) Log.d(TAG, "interfaceRemoved " + iface); 294 synchronized (mPublicSync) { 295 TetherState tetherState = mTetherStates.get(iface); 296 if (tetherState == null) { 297 if (VDBG) { 298 Log.e(TAG, "attempting to remove unknown iface (" + iface + "), ignoring"); 299 } 300 return; 301 } 302 tetherState.stateMachine.sendMessage(TetherInterfaceStateMachine.CMD_INTERFACE_DOWN); 303 mTetherStates.remove(iface); 304 } 305 } 306 307 public void startTethering(int type, ResultReceiver receiver, boolean showProvisioningUi) { 308 if (!isTetherProvisioningRequired()) { 309 enableTetheringInternal(type, true, receiver); 310 return; 311 } 312 313 if (showProvisioningUi) { 314 runUiTetherProvisioningAndEnable(type, receiver); 315 } else { 316 runSilentTetherProvisioningAndEnable(type, receiver); 317 } 318 } 319 320 public void stopTethering(int type) { 321 enableTetheringInternal(type, false, null); 322 if (isTetherProvisioningRequired()) { 323 cancelTetherProvisioningRechecks(type); 324 } 325 } 326 327 /** 328 * Check if the device requires a provisioning check in order to enable tethering. 329 * 330 * @return a boolean - {@code true} indicating tether provisioning is required by the carrier. 331 */ 332 @VisibleForTesting 333 protected boolean isTetherProvisioningRequired() { 334 String[] provisionApp = mContext.getResources().getStringArray( 335 com.android.internal.R.array.config_mobile_hotspot_provision_app); 336 if (mSystemProperties.getBoolean(DISABLE_PROVISIONING_SYSPROP_KEY, false) 337 || provisionApp == null) { 338 return false; 339 } 340 341 // Check carrier config for entitlement checks 342 final CarrierConfigManager configManager = (CarrierConfigManager) mContext 343 .getSystemService(Context.CARRIER_CONFIG_SERVICE); 344 if (configManager != null && configManager.getConfig() != null) { 345 // we do have a CarrierConfigManager and it has a config. 346 boolean isEntitlementCheckRequired = configManager.getConfig().getBoolean( 347 CarrierConfigManager.KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL); 348 if (!isEntitlementCheckRequired) { 349 return false; 350 } 351 } 352 return (provisionApp.length == 2); 353 } 354 355 /** 356 * Enables or disables tethering for the given type. This should only be called once 357 * provisioning has succeeded or is not necessary. It will also schedule provisioning rechecks 358 * for the specified interface. 359 */ 360 private void enableTetheringInternal(int type, boolean enable, ResultReceiver receiver) { 361 boolean isProvisioningRequired = enable && isTetherProvisioningRequired(); 362 int result; 363 switch (type) { 364 case ConnectivityManager.TETHERING_WIFI: 365 result = setWifiTethering(enable); 366 if (isProvisioningRequired && result == ConnectivityManager.TETHER_ERROR_NO_ERROR) { 367 scheduleProvisioningRechecks(type); 368 } 369 sendTetherResult(receiver, result); 370 break; 371 case ConnectivityManager.TETHERING_USB: 372 result = setUsbTethering(enable); 373 if (isProvisioningRequired && result == ConnectivityManager.TETHER_ERROR_NO_ERROR) { 374 scheduleProvisioningRechecks(type); 375 } 376 sendTetherResult(receiver, result); 377 break; 378 case ConnectivityManager.TETHERING_BLUETOOTH: 379 setBluetoothTethering(enable, receiver); 380 break; 381 default: 382 Log.w(TAG, "Invalid tether type."); 383 sendTetherResult(receiver, ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE); 384 } 385 } 386 387 private void sendTetherResult(ResultReceiver receiver, int result) { 388 if (receiver != null) { 389 receiver.send(result, null); 390 } 391 } 392 393 private int setWifiTethering(final boolean enable) { 394 synchronized (mPublicSync) { 395 mWifiTetherRequested = enable; 396 final WifiManager wifiManager = 397 (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE); 398 if (wifiManager.setWifiApEnabled(null /* use existing wifi config */, enable)) { 399 return ConnectivityManager.TETHER_ERROR_NO_ERROR; 400 } 401 return ConnectivityManager.TETHER_ERROR_MASTER_ERROR; 402 } 403 } 404 405 private void setBluetoothTethering(final boolean enable, final ResultReceiver receiver) { 406 final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 407 if (adapter == null || !adapter.isEnabled()) { 408 Log.w(TAG, "Tried to enable bluetooth tethering with null or disabled adapter. null: " + 409 (adapter == null)); 410 sendTetherResult(receiver, ConnectivityManager.TETHER_ERROR_SERVICE_UNAVAIL); 411 return; 412 } 413 414 adapter.getProfileProxy(mContext, new ServiceListener() { 415 @Override 416 public void onServiceDisconnected(int profile) { } 417 418 @Override 419 public void onServiceConnected(int profile, BluetoothProfile proxy) { 420 ((BluetoothPan) proxy).setBluetoothTethering(enable); 421 // TODO: Enabling bluetooth tethering can fail asynchronously here. 422 // We should figure out a way to bubble up that failure instead of sending success. 423 int result = ((BluetoothPan) proxy).isTetheringOn() == enable ? 424 ConnectivityManager.TETHER_ERROR_NO_ERROR : 425 ConnectivityManager.TETHER_ERROR_MASTER_ERROR; 426 sendTetherResult(receiver, result); 427 if (enable && isTetherProvisioningRequired()) { 428 scheduleProvisioningRechecks(ConnectivityManager.TETHERING_BLUETOOTH); 429 } 430 adapter.closeProfileProxy(BluetoothProfile.PAN, proxy); 431 } 432 }, BluetoothProfile.PAN); 433 } 434 435 private void runUiTetherProvisioningAndEnable(int type, ResultReceiver receiver) { 436 ResultReceiver proxyReceiver = getProxyReceiver(type, receiver); 437 sendUiTetherProvisionIntent(type, proxyReceiver); 438 } 439 440 private void sendUiTetherProvisionIntent(int type, ResultReceiver receiver) { 441 Intent intent = new Intent(Settings.ACTION_TETHER_PROVISIONING); 442 intent.putExtra(ConnectivityManager.EXTRA_ADD_TETHER_TYPE, type); 443 intent.putExtra(ConnectivityManager.EXTRA_PROVISION_CALLBACK, receiver); 444 final long ident = Binder.clearCallingIdentity(); 445 try { 446 mContext.startActivityAsUser(intent, UserHandle.CURRENT); 447 } finally { 448 Binder.restoreCallingIdentity(ident); 449 } 450 } 451 452 /** 453 * Creates a proxy {@link ResultReceiver} which enables tethering if the provisioning result 454 * is successful before firing back up to the wrapped receiver. 455 * 456 * @param type The type of tethering being enabled. 457 * @param receiver A ResultReceiver which will be called back with an int resultCode. 458 * @return The proxy receiver. 459 */ 460 private ResultReceiver getProxyReceiver(final int type, final ResultReceiver receiver) { 461 ResultReceiver rr = new ResultReceiver(null) { 462 @Override 463 protected void onReceiveResult(int resultCode, Bundle resultData) { 464 // If provisioning is successful, enable tethering, otherwise just send the error. 465 if (resultCode == ConnectivityManager.TETHER_ERROR_NO_ERROR) { 466 enableTetheringInternal(type, true, receiver); 467 } else { 468 sendTetherResult(receiver, resultCode); 469 } 470 } 471 }; 472 473 // The following is necessary to avoid unmarshalling issues when sending the receiver 474 // across processes. 475 Parcel parcel = Parcel.obtain(); 476 rr.writeToParcel(parcel,0); 477 parcel.setDataPosition(0); 478 ResultReceiver receiverForSending = ResultReceiver.CREATOR.createFromParcel(parcel); 479 parcel.recycle(); 480 return receiverForSending; 481 } 482 483 private void scheduleProvisioningRechecks(int type) { 484 Intent intent = new Intent(); 485 intent.putExtra(ConnectivityManager.EXTRA_ADD_TETHER_TYPE, type); 486 intent.putExtra(ConnectivityManager.EXTRA_SET_ALARM, true); 487 intent.setComponent(TETHER_SERVICE); 488 final long ident = Binder.clearCallingIdentity(); 489 try { 490 mContext.startServiceAsUser(intent, UserHandle.CURRENT); 491 } finally { 492 Binder.restoreCallingIdentity(ident); 493 } 494 } 495 496 private void runSilentTetherProvisioningAndEnable(int type, ResultReceiver receiver) { 497 ResultReceiver proxyReceiver = getProxyReceiver(type, receiver); 498 sendSilentTetherProvisionIntent(type, proxyReceiver); 499 } 500 501 private void sendSilentTetherProvisionIntent(int type, ResultReceiver receiver) { 502 Intent intent = new Intent(); 503 intent.putExtra(ConnectivityManager.EXTRA_ADD_TETHER_TYPE, type); 504 intent.putExtra(ConnectivityManager.EXTRA_RUN_PROVISION, true); 505 intent.putExtra(ConnectivityManager.EXTRA_PROVISION_CALLBACK, receiver); 506 intent.setComponent(TETHER_SERVICE); 507 final long ident = Binder.clearCallingIdentity(); 508 try { 509 mContext.startServiceAsUser(intent, UserHandle.CURRENT); 510 } finally { 511 Binder.restoreCallingIdentity(ident); 512 } 513 } 514 515 private void cancelTetherProvisioningRechecks(int type) { 516 if (getConnectivityManager().isTetheringSupported()) { 517 Intent intent = new Intent(); 518 intent.putExtra(ConnectivityManager.EXTRA_REM_TETHER_TYPE, type); 519 intent.setComponent(TETHER_SERVICE); 520 final long ident = Binder.clearCallingIdentity(); 521 try { 522 mContext.startServiceAsUser(intent, UserHandle.CURRENT); 523 } finally { 524 Binder.restoreCallingIdentity(ident); 525 } 526 } 527 } 528 529 public int tether(String iface) { 530 return tether(iface, IControlsTethering.STATE_TETHERED); 531 } 532 533 private int tether(String iface, int requestedState) { 534 if (DBG) Log.d(TAG, "Tethering " + iface); 535 synchronized (mPublicSync) { 536 TetherState tetherState = mTetherStates.get(iface); 537 if (tetherState == null) { 538 Log.e(TAG, "Tried to Tether an unknown iface: " + iface + ", ignoring"); 539 return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE; 540 } 541 // Ignore the error status of the interface. If the interface is available, 542 // the errors are referring to past tethering attempts anyway. 543 if (tetherState.lastState != IControlsTethering.STATE_AVAILABLE) { 544 Log.e(TAG, "Tried to Tether an unavailable iface: " + iface + ", ignoring"); 545 return ConnectivityManager.TETHER_ERROR_UNAVAIL_IFACE; 546 } 547 // NOTE: If a CMD_TETHER_REQUESTED message is already in the TISM's 548 // queue but not yet processed, this will be a no-op and it will not 549 // return an error. 550 // 551 // TODO: reexamine the threading and messaging model. 552 tetherState.stateMachine.sendMessage( 553 TetherInterfaceStateMachine.CMD_TETHER_REQUESTED, requestedState); 554 return ConnectivityManager.TETHER_ERROR_NO_ERROR; 555 } 556 } 557 558 public int untether(String iface) { 559 if (DBG) Log.d(TAG, "Untethering " + iface); 560 synchronized (mPublicSync) { 561 TetherState tetherState = mTetherStates.get(iface); 562 if (tetherState == null) { 563 Log.e(TAG, "Tried to Untether an unknown iface :" + iface + ", ignoring"); 564 return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE; 565 } 566 if (!tetherState.isCurrentlyServing()) { 567 Log.e(TAG, "Tried to untether an inactive iface :" + iface + ", ignoring"); 568 return ConnectivityManager.TETHER_ERROR_UNAVAIL_IFACE; 569 } 570 tetherState.stateMachine.sendMessage( 571 TetherInterfaceStateMachine.CMD_TETHER_UNREQUESTED); 572 return ConnectivityManager.TETHER_ERROR_NO_ERROR; 573 } 574 } 575 576 public void untetherAll() { 577 stopTethering(ConnectivityManager.TETHERING_WIFI); 578 stopTethering(ConnectivityManager.TETHERING_USB); 579 stopTethering(ConnectivityManager.TETHERING_BLUETOOTH); 580 } 581 582 public int getLastTetherError(String iface) { 583 synchronized (mPublicSync) { 584 TetherState tetherState = mTetherStates.get(iface); 585 if (tetherState == null) { 586 Log.e(TAG, "Tried to getLastTetherError on an unknown iface :" + iface + 587 ", ignoring"); 588 return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE; 589 } 590 return tetherState.lastError; 591 } 592 } 593 594 // TODO: Figure out how to update for local hotspot mode interfaces. 595 private void sendTetherStateChangedBroadcast() { 596 if (!getConnectivityManager().isTetheringSupported()) return; 597 598 ArrayList<String> availableList = new ArrayList<String>(); 599 ArrayList<String> activeList = new ArrayList<String>(); 600 ArrayList<String> erroredList = new ArrayList<String>(); 601 602 boolean wifiTethered = false; 603 boolean usbTethered = false; 604 boolean bluetoothTethered = false; 605 606 final TetheringConfiguration cfg = mConfig; 607 608 synchronized (mPublicSync) { 609 for (int i = 0; i < mTetherStates.size(); i++) { 610 TetherState tetherState = mTetherStates.valueAt(i); 611 String iface = mTetherStates.keyAt(i); 612 if (tetherState.lastError != ConnectivityManager.TETHER_ERROR_NO_ERROR) { 613 erroredList.add(iface); 614 } else if (tetherState.lastState == IControlsTethering.STATE_AVAILABLE) { 615 availableList.add(iface); 616 } else if (tetherState.lastState == IControlsTethering.STATE_TETHERED) { 617 if (cfg.isUsb(iface)) { 618 usbTethered = true; 619 } else if (cfg.isWifi(iface)) { 620 wifiTethered = true; 621 } else if (cfg.isBluetooth(iface)) { 622 bluetoothTethered = true; 623 } 624 activeList.add(iface); 625 } 626 } 627 } 628 Intent broadcast = new Intent(ConnectivityManager.ACTION_TETHER_STATE_CHANGED); 629 broadcast.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING | 630 Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 631 broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_AVAILABLE_TETHER, 632 availableList); 633 broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_ACTIVE_TETHER, activeList); 634 broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_ERRORED_TETHER, 635 erroredList); 636 mContext.sendStickyBroadcastAsUser(broadcast, UserHandle.ALL); 637 if (DBG) { 638 Log.d(TAG, String.format( 639 "sendTetherStateChangedBroadcast avail=[%s] active=[%s] error=[%s]", 640 TextUtils.join(",", availableList), 641 TextUtils.join(",", activeList), 642 TextUtils.join(",", erroredList))); 643 } 644 645 if (usbTethered) { 646 if (wifiTethered || bluetoothTethered) { 647 showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_general); 648 } else { 649 showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_usb); 650 } 651 } else if (wifiTethered) { 652 if (bluetoothTethered) { 653 showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_general); 654 } else { 655 /* We now have a status bar icon for WifiTethering, so drop the notification */ 656 clearTetheredNotification(); 657 } 658 } else if (bluetoothTethered) { 659 showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_bluetooth); 660 } else { 661 clearTetheredNotification(); 662 } 663 } 664 665 private void showTetheredNotification(int icon) { 666 NotificationManager notificationManager = 667 (NotificationManager)mContext.getSystemService(Context.NOTIFICATION_SERVICE); 668 if (notificationManager == null) { 669 return; 670 } 671 672 if (mLastNotificationId != 0) { 673 if (mLastNotificationId == icon) { 674 return; 675 } 676 notificationManager.cancelAsUser(null, mLastNotificationId, 677 UserHandle.ALL); 678 mLastNotificationId = 0; 679 } 680 681 Intent intent = new Intent(); 682 intent.setClassName("com.android.settings", "com.android.settings.TetherSettings"); 683 intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY); 684 685 PendingIntent pi = PendingIntent.getActivityAsUser(mContext, 0, intent, 0, 686 null, UserHandle.CURRENT); 687 688 Resources r = Resources.getSystem(); 689 CharSequence title = r.getText(com.android.internal.R.string.tethered_notification_title); 690 CharSequence message = r.getText(com.android.internal.R.string. 691 tethered_notification_message); 692 693 if (mTetheredNotificationBuilder == null) { 694 mTetheredNotificationBuilder = new Notification.Builder(mContext); 695 mTetheredNotificationBuilder.setWhen(0) 696 .setOngoing(true) 697 .setColor(mContext.getColor( 698 com.android.internal.R.color.system_notification_accent_color)) 699 .setVisibility(Notification.VISIBILITY_PUBLIC) 700 .setCategory(Notification.CATEGORY_STATUS); 701 } 702 mTetheredNotificationBuilder.setSmallIcon(icon) 703 .setContentTitle(title) 704 .setContentText(message) 705 .setContentIntent(pi); 706 mLastNotificationId = icon; 707 708 notificationManager.notifyAsUser(null, mLastNotificationId, 709 mTetheredNotificationBuilder.build(), UserHandle.ALL); 710 } 711 712 private void clearTetheredNotification() { 713 NotificationManager notificationManager = 714 (NotificationManager)mContext.getSystemService(Context.NOTIFICATION_SERVICE); 715 if (notificationManager != null && mLastNotificationId != 0) { 716 notificationManager.cancelAsUser(null, mLastNotificationId, 717 UserHandle.ALL); 718 mLastNotificationId = 0; 719 } 720 } 721 722 private class StateReceiver extends BroadcastReceiver { 723 @Override 724 public void onReceive(Context content, Intent intent) { 725 final String action = intent.getAction(); 726 if (action == null) return; 727 728 if (action.equals(UsbManager.ACTION_USB_STATE)) { 729 handleUsbAction(intent); 730 } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) { 731 handleConnectivityAction(intent); 732 } else if (action.equals(WifiManager.WIFI_AP_STATE_CHANGED_ACTION)) { 733 handleWifiApAction(intent); 734 } else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) { 735 updateConfiguration(); 736 } 737 } 738 739 private void handleConnectivityAction(Intent intent) { 740 final NetworkInfo networkInfo = (NetworkInfo)intent.getParcelableExtra( 741 ConnectivityManager.EXTRA_NETWORK_INFO); 742 if (networkInfo == null || 743 networkInfo.getDetailedState() == NetworkInfo.DetailedState.FAILED) { 744 return; 745 } 746 747 if (VDBG) Log.d(TAG, "Tethering got CONNECTIVITY_ACTION: " + networkInfo.toString()); 748 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_UPSTREAM_CHANGED); 749 } 750 751 private void handleUsbAction(Intent intent) { 752 final boolean usbConnected = intent.getBooleanExtra(USB_CONNECTED, false); 753 final boolean rndisEnabled = intent.getBooleanExtra(USB_FUNCTION_RNDIS, false); 754 synchronized (Tethering.this.mPublicSync) { 755 mRndisEnabled = rndisEnabled; 756 // start tethering if we have a request pending 757 if (usbConnected && mRndisEnabled && mUsbTetherRequested) { 758 tetherMatchingInterfaces( 759 IControlsTethering.STATE_TETHERED, 760 ConnectivityManager.TETHERING_USB); 761 } 762 mUsbTetherRequested = false; 763 } 764 } 765 766 private void handleWifiApAction(Intent intent) { 767 final int curState = intent.getIntExtra(EXTRA_WIFI_AP_STATE, WIFI_AP_STATE_DISABLED); 768 synchronized (Tethering.this.mPublicSync) { 769 switch (curState) { 770 case WifiManager.WIFI_AP_STATE_ENABLING: 771 // We can see this state on the way to both enabled and failure states. 772 break; 773 case WifiManager.WIFI_AP_STATE_ENABLED: 774 // When the AP comes up and we've been requested to tether it, do so. 775 // Otherwise, assume it's a local-only hotspot request. 776 final int state = mWifiTetherRequested 777 ? IControlsTethering.STATE_TETHERED 778 : IControlsTethering.STATE_LOCAL_HOTSPOT; 779 tetherMatchingInterfaces(state, ConnectivityManager.TETHERING_WIFI); 780 break; 781 case WifiManager.WIFI_AP_STATE_DISABLED: 782 case WifiManager.WIFI_AP_STATE_DISABLING: 783 case WifiManager.WIFI_AP_STATE_FAILED: 784 default: 785 if (DBG) { 786 Log.d(TAG, "Canceling WiFi tethering request - AP_STATE=" + 787 curState); 788 } 789 // Tell appropriate interface state machines that they should tear 790 // themselves down. 791 for (int i = 0; i < mTetherStates.size(); i++) { 792 TetherInterfaceStateMachine tism = 793 mTetherStates.valueAt(i).stateMachine; 794 if (tism.interfaceType() == ConnectivityManager.TETHERING_WIFI) { 795 tism.sendMessage( 796 TetherInterfaceStateMachine.CMD_TETHER_UNREQUESTED); 797 break; // There should be at most one of these. 798 } 799 } 800 // Regardless of whether we requested this transition, the AP has gone 801 // down. Don't try to tether again unless we're requested to do so. 802 mWifiTetherRequested = false; 803 break; 804 } 805 } 806 } 807 } 808 809 // TODO: Consider renaming to something more accurate in its description. 810 // This method: 811 // - allows requesting either tethering or local hotspot serving states 812 // - handles both enabling and disabling serving states 813 // - only tethers the first matching interface in listInterfaces() 814 // order of a given type 815 private void tetherMatchingInterfaces(int requestedState, int interfaceType) { 816 if (VDBG) { 817 Log.d(TAG, "tetherMatchingInterfaces(" + requestedState + ", " + interfaceType + ")"); 818 } 819 820 String[] ifaces = null; 821 try { 822 ifaces = mNMService.listInterfaces(); 823 } catch (Exception e) { 824 Log.e(TAG, "Error listing Interfaces", e); 825 return; 826 } 827 String chosenIface = null; 828 if (ifaces != null) { 829 for (String iface : ifaces) { 830 if (ifaceNameToType(iface) == interfaceType) { 831 chosenIface = iface; 832 break; 833 } 834 } 835 } 836 if (chosenIface == null) { 837 Log.e(TAG, "could not find iface of type " + interfaceType); 838 return; 839 } 840 841 final int result; 842 switch (requestedState) { 843 case IControlsTethering.STATE_UNAVAILABLE: 844 case IControlsTethering.STATE_AVAILABLE: 845 result = untether(chosenIface); 846 break; 847 case IControlsTethering.STATE_TETHERED: 848 case IControlsTethering.STATE_LOCAL_HOTSPOT: 849 result = tether(chosenIface, requestedState); 850 break; 851 default: 852 Log.wtf(TAG, "Unknown interface state: " + requestedState); 853 return; 854 } 855 if (result != ConnectivityManager.TETHER_ERROR_NO_ERROR) { 856 Log.e(TAG, "unable start or stop tethering on iface " + chosenIface); 857 return; 858 } 859 } 860 861 public TetheringConfiguration getTetheringConfiguration() { 862 return mConfig; 863 } 864 865 public boolean hasTetherableConfiguration() { 866 final TetheringConfiguration cfg = mConfig; 867 final boolean hasDownstreamConfiguration = 868 (cfg.tetherableUsbRegexs.length != 0) || 869 (cfg.tetherableWifiRegexs.length != 0) || 870 (cfg.tetherableBluetoothRegexs.length != 0); 871 final boolean hasUpstreamConfiguration = !cfg.preferredUpstreamIfaceTypes.isEmpty(); 872 873 return hasDownstreamConfiguration && hasUpstreamConfiguration; 874 } 875 876 // TODO - update callers to use getTetheringConfiguration(), 877 // which has only final members. 878 public String[] getTetherableUsbRegexs() { 879 return copy(mConfig.tetherableUsbRegexs); 880 } 881 882 public String[] getTetherableWifiRegexs() { 883 return copy(mConfig.tetherableWifiRegexs); 884 } 885 886 public String[] getTetherableBluetoothRegexs() { 887 return copy(mConfig.tetherableBluetoothRegexs); 888 } 889 890 public int setUsbTethering(boolean enable) { 891 if (VDBG) Log.d(TAG, "setUsbTethering(" + enable + ")"); 892 UsbManager usbManager = mContext.getSystemService(UsbManager.class); 893 894 synchronized (mPublicSync) { 895 if (enable) { 896 if (mRndisEnabled) { 897 final long ident = Binder.clearCallingIdentity(); 898 try { 899 tetherMatchingInterfaces(IControlsTethering.STATE_TETHERED, 900 ConnectivityManager.TETHERING_USB); 901 } finally { 902 Binder.restoreCallingIdentity(ident); 903 } 904 } else { 905 mUsbTetherRequested = true; 906 usbManager.setCurrentFunction(UsbManager.USB_FUNCTION_RNDIS, false); 907 } 908 } else { 909 final long ident = Binder.clearCallingIdentity(); 910 try { 911 tetherMatchingInterfaces(IControlsTethering.STATE_AVAILABLE, 912 ConnectivityManager.TETHERING_USB); 913 } finally { 914 Binder.restoreCallingIdentity(ident); 915 } 916 if (mRndisEnabled) { 917 usbManager.setCurrentFunction(null, false); 918 } 919 mUsbTetherRequested = false; 920 } 921 } 922 return ConnectivityManager.TETHER_ERROR_NO_ERROR; 923 } 924 925 // TODO review API - maybe return ArrayList<String> here and below? 926 public String[] getTetheredIfaces() { 927 ArrayList<String> list = new ArrayList<String>(); 928 synchronized (mPublicSync) { 929 for (int i = 0; i < mTetherStates.size(); i++) { 930 TetherState tetherState = mTetherStates.valueAt(i); 931 if (tetherState.lastState == IControlsTethering.STATE_TETHERED) { 932 list.add(mTetherStates.keyAt(i)); 933 } 934 } 935 } 936 return list.toArray(new String[list.size()]); 937 } 938 939 public String[] getTetherableIfaces() { 940 ArrayList<String> list = new ArrayList<String>(); 941 synchronized (mPublicSync) { 942 for (int i = 0; i < mTetherStates.size(); i++) { 943 TetherState tetherState = mTetherStates.valueAt(i); 944 if (tetherState.lastState == IControlsTethering.STATE_AVAILABLE) { 945 list.add(mTetherStates.keyAt(i)); 946 } 947 } 948 } 949 return list.toArray(new String[list.size()]); 950 } 951 952 public String[] getTetheredDhcpRanges() { 953 return mConfig.dhcpRanges; 954 } 955 956 public String[] getErroredIfaces() { 957 ArrayList<String> list = new ArrayList<String>(); 958 synchronized (mPublicSync) { 959 for (int i = 0; i < mTetherStates.size(); i++) { 960 TetherState tetherState = mTetherStates.valueAt(i); 961 if (tetherState.lastError != ConnectivityManager.TETHER_ERROR_NO_ERROR) { 962 list.add(mTetherStates.keyAt(i)); 963 } 964 } 965 } 966 return list.toArray(new String[list.size()]); 967 } 968 969 private void maybeLogMessage(State state, int what) { 970 if (DBG) { 971 Log.d(TAG, state.getName() + " got " + 972 sMagicDecoderRing.get(what, Integer.toString(what))); 973 } 974 } 975 976 private boolean upstreamWanted() { 977 if (!mForwardedDownstreams.isEmpty()) return true; 978 979 synchronized (mPublicSync) { 980 return mUsbTetherRequested || mWifiTetherRequested; 981 } 982 } 983 984 // Needed because the canonical source of upstream truth is just the 985 // upstream interface name, |mCurrentUpstreamIface|. This is ripe for 986 // future simplification, once the upstream Network is canonical. 987 boolean pertainsToCurrentUpstream(NetworkState ns) { 988 if (ns != null && ns.linkProperties != null && mCurrentUpstreamIface != null) { 989 for (String ifname : ns.linkProperties.getAllInterfaceNames()) { 990 if (mCurrentUpstreamIface.equals(ifname)) { 991 return true; 992 } 993 } 994 } 995 return false; 996 } 997 998 class TetherMasterSM extends StateMachine { 999 private static final int BASE_MASTER = Protocol.BASE_TETHERING; 1000 // an interface SM has requested Tethering/Local Hotspot 1001 static final int EVENT_IFACE_SERVING_STATE_ACTIVE = BASE_MASTER + 1; 1002 // an interface SM has unrequested Tethering/Local Hotspot 1003 static final int EVENT_IFACE_SERVING_STATE_INACTIVE = BASE_MASTER + 2; 1004 // upstream connection change - do the right thing 1005 static final int CMD_UPSTREAM_CHANGED = BASE_MASTER + 3; 1006 // we don't have a valid upstream conn, check again after a delay 1007 static final int CMD_RETRY_UPSTREAM = BASE_MASTER + 4; 1008 // Events from NetworkCallbacks that we process on the master state 1009 // machine thread on behalf of the UpstreamNetworkMonitor. 1010 static final int EVENT_UPSTREAM_CALLBACK = BASE_MASTER + 5; 1011 // we treated the error and want now to clear it 1012 static final int CMD_CLEAR_ERROR = BASE_MASTER + 6; 1013 1014 private State mInitialState; 1015 private State mTetherModeAliveState; 1016 1017 private State mSetIpForwardingEnabledErrorState; 1018 private State mSetIpForwardingDisabledErrorState; 1019 private State mStartTetheringErrorState; 1020 private State mStopTetheringErrorState; 1021 private State mSetDnsForwardersErrorState; 1022 1023 // This list is a little subtle. It contains all the interfaces that currently are 1024 // requesting tethering, regardless of whether these interfaces are still members of 1025 // mTetherStates. This allows us to maintain the following predicates: 1026 // 1027 // 1) mTetherStates contains the set of all currently existing, tetherable, link state up 1028 // interfaces. 1029 // 2) mNotifyList contains all state machines that may have outstanding tethering state 1030 // that needs to be torn down. 1031 // 1032 // Because we excise interfaces immediately from mTetherStates, we must maintain mNotifyList 1033 // so that the garbage collector does not clean up the state machine before it has a chance 1034 // to tear itself down. 1035 private final ArrayList<TetherInterfaceStateMachine> mNotifyList; 1036 private final IPv6TetheringCoordinator mIPv6TetheringCoordinator; 1037 1038 private static final int UPSTREAM_SETTLE_TIME_MS = 10000; 1039 1040 TetherMasterSM(String name, Looper looper) { 1041 super(name, looper); 1042 1043 //Add states 1044 mInitialState = new InitialState(); 1045 addState(mInitialState); 1046 mTetherModeAliveState = new TetherModeAliveState(); 1047 addState(mTetherModeAliveState); 1048 1049 mSetIpForwardingEnabledErrorState = new SetIpForwardingEnabledErrorState(); 1050 addState(mSetIpForwardingEnabledErrorState); 1051 mSetIpForwardingDisabledErrorState = new SetIpForwardingDisabledErrorState(); 1052 addState(mSetIpForwardingDisabledErrorState); 1053 mStartTetheringErrorState = new StartTetheringErrorState(); 1054 addState(mStartTetheringErrorState); 1055 mStopTetheringErrorState = new StopTetheringErrorState(); 1056 addState(mStopTetheringErrorState); 1057 mSetDnsForwardersErrorState = new SetDnsForwardersErrorState(); 1058 addState(mSetDnsForwardersErrorState); 1059 1060 mNotifyList = new ArrayList<>(); 1061 mIPv6TetheringCoordinator = new IPv6TetheringCoordinator(mNotifyList); 1062 setInitialState(mInitialState); 1063 } 1064 1065 class TetherMasterUtilState extends State { 1066 @Override 1067 public boolean processMessage(Message m) { 1068 return false; 1069 } 1070 1071 protected void requestUpstreamMobileConnection() { 1072 mUpstreamNetworkMonitor.updateMobileRequiresDun(mConfig.isDunRequired); 1073 mUpstreamNetworkMonitor.registerMobileNetworkRequest(); 1074 } 1075 1076 protected void unrequestUpstreamMobileConnection() { 1077 mUpstreamNetworkMonitor.releaseMobileNetworkRequest(); 1078 } 1079 1080 protected boolean turnOnMasterTetherSettings() { 1081 final TetheringConfiguration cfg = mConfig; 1082 try { 1083 mNMService.setIpForwardingEnabled(true); 1084 } catch (Exception e) { 1085 transitionTo(mSetIpForwardingEnabledErrorState); 1086 return false; 1087 } 1088 // TODO: Randomize DHCPv4 ranges, especially in hotspot mode. 1089 try { 1090 // TODO: Find a more accurate method name (startDHCPv4()?). 1091 mNMService.startTethering(cfg.dhcpRanges); 1092 } catch (Exception e) { 1093 try { 1094 mNMService.stopTethering(); 1095 mNMService.startTethering(cfg.dhcpRanges); 1096 } catch (Exception ee) { 1097 transitionTo(mStartTetheringErrorState); 1098 return false; 1099 } 1100 } 1101 return true; 1102 } 1103 1104 protected boolean turnOffMasterTetherSettings() { 1105 try { 1106 mNMService.stopTethering(); 1107 } catch (Exception e) { 1108 transitionTo(mStopTetheringErrorState); 1109 return false; 1110 } 1111 try { 1112 mNMService.setIpForwardingEnabled(false); 1113 } catch (Exception e) { 1114 transitionTo(mSetIpForwardingDisabledErrorState); 1115 return false; 1116 } 1117 transitionTo(mInitialState); 1118 return true; 1119 } 1120 1121 protected void chooseUpstreamType(boolean tryCell) { 1122 final int upstreamType = findPreferredUpstreamType(tryCell); 1123 setUpstreamByType(upstreamType); 1124 } 1125 1126 protected int findPreferredUpstreamType(boolean tryCell) { 1127 final ConnectivityManager cm = getConnectivityManager(); 1128 int upType = ConnectivityManager.TYPE_NONE; 1129 1130 updateConfiguration(); // TODO - remove? 1131 1132 final TetheringConfiguration cfg = mConfig; 1133 if (VDBG) { 1134 Log.d(TAG, "chooseUpstreamType has upstream iface types:"); 1135 for (Integer netType : cfg.preferredUpstreamIfaceTypes) { 1136 Log.d(TAG, " " + netType); 1137 } 1138 } 1139 1140 for (Integer netType : cfg.preferredUpstreamIfaceTypes) { 1141 NetworkInfo info = cm.getNetworkInfo(netType.intValue()); 1142 // TODO: if the network is suspended we should consider 1143 // that to be the same as connected here. 1144 if ((info != null) && info.isConnected()) { 1145 upType = netType.intValue(); 1146 break; 1147 } 1148 } 1149 1150 final int preferredUpstreamMobileApn = cfg.isDunRequired 1151 ? ConnectivityManager.TYPE_MOBILE_DUN 1152 : ConnectivityManager.TYPE_MOBILE_HIPRI; 1153 if (DBG) { 1154 Log.d(TAG, "chooseUpstreamType(" + tryCell + ")," 1155 + " preferredApn=" 1156 + ConnectivityManager.getNetworkTypeName(preferredUpstreamMobileApn) 1157 + ", got type=" 1158 + ConnectivityManager.getNetworkTypeName(upType)); 1159 } 1160 1161 switch (upType) { 1162 case ConnectivityManager.TYPE_MOBILE_DUN: 1163 case ConnectivityManager.TYPE_MOBILE_HIPRI: 1164 // If we're on DUN, put our own grab on it. 1165 requestUpstreamMobileConnection(); 1166 break; 1167 case ConnectivityManager.TYPE_NONE: 1168 if (tryCell) { 1169 requestUpstreamMobileConnection(); 1170 // We think mobile should be coming up; don't set a retry. 1171 } else { 1172 sendMessageDelayed(CMD_RETRY_UPSTREAM, UPSTREAM_SETTLE_TIME_MS); 1173 } 1174 break; 1175 default: 1176 /* If we've found an active upstream connection that's not DUN/HIPRI 1177 * we should stop any outstanding DUN/HIPRI start requests. 1178 * 1179 * If we found NONE we don't want to do this as we want any previous 1180 * requests to keep trying to bring up something we can use. 1181 */ 1182 unrequestUpstreamMobileConnection(); 1183 break; 1184 } 1185 1186 return upType; 1187 } 1188 1189 protected void setUpstreamByType(int upType) { 1190 final ConnectivityManager cm = getConnectivityManager(); 1191 Network network = null; 1192 String iface = null; 1193 if (upType != ConnectivityManager.TYPE_NONE) { 1194 LinkProperties linkProperties = cm.getLinkProperties(upType); 1195 if (linkProperties != null) { 1196 // Find the interface with the default IPv4 route. It may be the 1197 // interface described by linkProperties, or one of the interfaces 1198 // stacked on top of it. 1199 Log.i(TAG, "Finding IPv4 upstream interface on: " + linkProperties); 1200 RouteInfo ipv4Default = RouteInfo.selectBestRoute( 1201 linkProperties.getAllRoutes(), Inet4Address.ANY); 1202 if (ipv4Default != null) { 1203 iface = ipv4Default.getInterface(); 1204 Log.i(TAG, "Found interface " + ipv4Default.getInterface()); 1205 } else { 1206 Log.i(TAG, "No IPv4 upstream interface, giving up."); 1207 } 1208 } 1209 1210 if (iface != null) { 1211 network = cm.getNetworkForType(upType); 1212 if (network == null) { 1213 Log.e(TAG, "No Network for upstream type " + upType + "!"); 1214 } 1215 setDnsForwarders(network, linkProperties); 1216 } 1217 } 1218 notifyTetheredOfNewUpstreamIface(iface); 1219 NetworkState ns = mUpstreamNetworkMonitor.lookup(network); 1220 if (ns != null && pertainsToCurrentUpstream(ns)) { 1221 // If we already have NetworkState for this network examine 1222 // it immediately, because there likely will be no second 1223 // EVENT_ON_AVAILABLE (it was already received). 1224 handleNewUpstreamNetworkState(ns); 1225 } else if (mCurrentUpstreamIface == null) { 1226 // There are no available upstream networks, or none that 1227 // have an IPv4 default route (current metric for success). 1228 handleNewUpstreamNetworkState(null); 1229 } 1230 } 1231 1232 protected void setDnsForwarders(final Network network, final LinkProperties lp) { 1233 // TODO: Set v4 and/or v6 DNS per available connectivity. 1234 String[] dnsServers = mConfig.defaultIPv4DNS; 1235 final Collection<InetAddress> dnses = lp.getDnsServers(); 1236 // TODO: Properly support the absence of DNS servers. 1237 if (dnses != null && !dnses.isEmpty()) { 1238 // TODO: remove this invocation of NetworkUtils.makeStrings(). 1239 dnsServers = NetworkUtils.makeStrings(dnses); 1240 } 1241 if (VDBG) { 1242 Log.d(TAG, "Setting DNS forwarders: Network=" + network + 1243 ", dnsServers=" + Arrays.toString(dnsServers)); 1244 } 1245 try { 1246 mNMService.setDnsForwarders(network, dnsServers); 1247 } catch (Exception e) { 1248 // TODO: Investigate how this can fail and what exactly 1249 // happens if/when such failures occur. 1250 Log.e(TAG, "Setting DNS forwarders failed!"); 1251 transitionTo(mSetDnsForwardersErrorState); 1252 } 1253 } 1254 1255 protected void notifyTetheredOfNewUpstreamIface(String ifaceName) { 1256 if (DBG) Log.d(TAG, "Notifying tethered with upstream=" + ifaceName); 1257 mCurrentUpstreamIface = ifaceName; 1258 for (TetherInterfaceStateMachine sm : mNotifyList) { 1259 sm.sendMessage(TetherInterfaceStateMachine.CMD_TETHER_CONNECTION_CHANGED, 1260 ifaceName); 1261 } 1262 } 1263 1264 protected void handleNewUpstreamNetworkState(NetworkState ns) { 1265 mIPv6TetheringCoordinator.updateUpstreamNetworkState(ns); 1266 mOffloadController.setUpstreamLinkProperties( 1267 (ns != null) ? ns.linkProperties : null); 1268 } 1269 } 1270 1271 private class SimChangeListener { 1272 private final Context mContext; 1273 private final AtomicInteger mSimBcastGenerationNumber; 1274 private BroadcastReceiver mBroadcastReceiver; 1275 1276 SimChangeListener(Context ctx) { 1277 mContext = ctx; 1278 mSimBcastGenerationNumber = new AtomicInteger(0); 1279 } 1280 1281 public int generationNumber() { 1282 return mSimBcastGenerationNumber.get(); 1283 } 1284 1285 public void startListening() { 1286 if (DBG) Log.d(TAG, "startListening for SIM changes"); 1287 1288 if (mBroadcastReceiver != null) return; 1289 1290 mBroadcastReceiver = new SimChangeBroadcastReceiver( 1291 mSimBcastGenerationNumber.incrementAndGet()); 1292 final IntentFilter filter = new IntentFilter(); 1293 filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED); 1294 1295 mContext.registerReceiver(mBroadcastReceiver, filter, null, 1296 mTetherMasterSM.getHandler()); 1297 } 1298 1299 public void stopListening() { 1300 if (DBG) Log.d(TAG, "stopListening for SIM changes"); 1301 1302 if (mBroadcastReceiver == null) return; 1303 1304 mSimBcastGenerationNumber.incrementAndGet(); 1305 mContext.unregisterReceiver(mBroadcastReceiver); 1306 mBroadcastReceiver = null; 1307 } 1308 1309 public boolean hasMobileHotspotProvisionApp() { 1310 try { 1311 if (!mContext.getResources().getString(com.android.internal.R.string. 1312 config_mobile_hotspot_provision_app_no_ui).isEmpty()) { 1313 Log.d(TAG, "re-evaluate provisioning"); 1314 return true; 1315 } 1316 } catch (Resources.NotFoundException e) {} 1317 Log.d(TAG, "no prov-check needed for new SIM"); 1318 return false; 1319 } 1320 1321 private boolean isSimCardLoaded(String state) { 1322 return IccCardConstants.INTENT_VALUE_ICC_LOADED.equals(state); 1323 } 1324 1325 private void startProvisionIntent(int tetherType) { 1326 final Intent startProvIntent = new Intent(); 1327 startProvIntent.putExtra(ConnectivityManager.EXTRA_ADD_TETHER_TYPE, tetherType); 1328 startProvIntent.putExtra(ConnectivityManager.EXTRA_RUN_PROVISION, true); 1329 startProvIntent.setComponent(TETHER_SERVICE); 1330 mContext.startServiceAsUser(startProvIntent, UserHandle.CURRENT); 1331 } 1332 1333 private class SimChangeBroadcastReceiver extends BroadcastReceiver { 1334 // used to verify this receiver is still current 1335 final private int mGenerationNumber; 1336 1337 // used to check the sim state transition from non-loaded to loaded 1338 private boolean mSimNotLoadedSeen = false; 1339 1340 public SimChangeBroadcastReceiver(int generationNumber) { 1341 mGenerationNumber = generationNumber; 1342 } 1343 1344 @Override 1345 public void onReceive(Context context, Intent intent) { 1346 final int currentGenerationNumber = mSimBcastGenerationNumber.get(); 1347 1348 if (DBG) { 1349 Log.d(TAG, "simchange mGenerationNumber=" + mGenerationNumber + 1350 ", current generationNumber=" + currentGenerationNumber); 1351 } 1352 if (mGenerationNumber != currentGenerationNumber) return; 1353 1354 final String state = intent.getStringExtra( 1355 IccCardConstants.INTENT_KEY_ICC_STATE); 1356 Log.d(TAG, "got Sim changed to state " + state + ", mSimNotLoadedSeen=" + 1357 mSimNotLoadedSeen); 1358 1359 if (!isSimCardLoaded(state)) { 1360 if (!mSimNotLoadedSeen) mSimNotLoadedSeen = true; 1361 return; 1362 } 1363 1364 if (isSimCardLoaded(state) && mSimNotLoadedSeen) { 1365 mSimNotLoadedSeen = false; 1366 1367 if (!hasMobileHotspotProvisionApp()) return; 1368 1369 ArrayList<Integer> tethered = new ArrayList<Integer>(); 1370 synchronized (mPublicSync) { 1371 for (int i = 0; i < mTetherStates.size(); i++) { 1372 TetherState tetherState = mTetherStates.valueAt(i); 1373 if (tetherState.lastState != IControlsTethering.STATE_TETHERED) { 1374 continue; // Skip interfaces that aren't tethered. 1375 } 1376 String iface = mTetherStates.keyAt(i); 1377 int interfaceType = ifaceNameToType(iface); 1378 if (interfaceType != ConnectivityManager.TETHERING_INVALID) { 1379 tethered.add(new Integer(interfaceType)); 1380 } 1381 } 1382 } 1383 1384 for (int tetherType : tethered) { 1385 startProvisionIntent(tetherType); 1386 } 1387 } 1388 } 1389 } 1390 } 1391 1392 private void handleInterfaceServingStateActive(int mode, TetherInterfaceStateMachine who) { 1393 if (mNotifyList.indexOf(who) < 0) { 1394 mNotifyList.add(who); 1395 mIPv6TetheringCoordinator.addActiveDownstream(who, mode); 1396 } 1397 1398 if (mode == IControlsTethering.STATE_TETHERED) { 1399 mForwardedDownstreams.add(who); 1400 } else { 1401 mForwardedDownstreams.remove(who); 1402 } 1403 } 1404 1405 private void handleInterfaceServingStateInactive(TetherInterfaceStateMachine who) { 1406 mNotifyList.remove(who); 1407 mIPv6TetheringCoordinator.removeActiveDownstream(who); 1408 mForwardedDownstreams.remove(who); 1409 } 1410 1411 class InitialState extends TetherMasterUtilState { 1412 @Override 1413 public boolean processMessage(Message message) { 1414 maybeLogMessage(this, message.what); 1415 boolean retValue = true; 1416 switch (message.what) { 1417 case EVENT_IFACE_SERVING_STATE_ACTIVE: 1418 TetherInterfaceStateMachine who = (TetherInterfaceStateMachine)message.obj; 1419 if (VDBG) Log.d(TAG, "Tether Mode requested by " + who); 1420 handleInterfaceServingStateActive(message.arg1, who); 1421 transitionTo(mTetherModeAliveState); 1422 break; 1423 case EVENT_IFACE_SERVING_STATE_INACTIVE: 1424 who = (TetherInterfaceStateMachine)message.obj; 1425 if (VDBG) Log.d(TAG, "Tether Mode unrequested by " + who); 1426 handleInterfaceServingStateInactive(who); 1427 break; 1428 default: 1429 retValue = false; 1430 break; 1431 } 1432 return retValue; 1433 } 1434 } 1435 1436 class TetherModeAliveState extends TetherMasterUtilState { 1437 final SimChangeListener simChange = new SimChangeListener(mContext); 1438 boolean mUpstreamWanted = false; 1439 boolean mTryCell = true; 1440 1441 @Override 1442 public void enter() { 1443 // TODO: examine if we should check the return value. 1444 turnOnMasterTetherSettings(); // may transition us out 1445 simChange.startListening(); 1446 mUpstreamNetworkMonitor.start(); 1447 mOffloadController.start(); 1448 1449 if (upstreamWanted()) { 1450 mUpstreamWanted = true; 1451 chooseUpstreamType(true); 1452 mTryCell = false; 1453 } 1454 } 1455 1456 @Override 1457 public void exit() { 1458 mOffloadController.stop(); 1459 unrequestUpstreamMobileConnection(); 1460 mUpstreamNetworkMonitor.stop(); 1461 simChange.stopListening(); 1462 notifyTetheredOfNewUpstreamIface(null); 1463 handleNewUpstreamNetworkState(null); 1464 } 1465 1466 private boolean updateUpstreamWanted() { 1467 final boolean previousUpstreamWanted = mUpstreamWanted; 1468 mUpstreamWanted = upstreamWanted(); 1469 return previousUpstreamWanted; 1470 } 1471 1472 @Override 1473 public boolean processMessage(Message message) { 1474 maybeLogMessage(this, message.what); 1475 boolean retValue = true; 1476 switch (message.what) { 1477 case EVENT_IFACE_SERVING_STATE_ACTIVE: { 1478 TetherInterfaceStateMachine who = (TetherInterfaceStateMachine)message.obj; 1479 if (VDBG) Log.d(TAG, "Tether Mode requested by " + who); 1480 handleInterfaceServingStateActive(message.arg1, who); 1481 who.sendMessage(TetherInterfaceStateMachine.CMD_TETHER_CONNECTION_CHANGED, 1482 mCurrentUpstreamIface); 1483 // If there has been a change and an upstream is now 1484 // desired, kick off the selection process. 1485 final boolean previousUpstreamWanted = updateUpstreamWanted(); 1486 if (!previousUpstreamWanted && mUpstreamWanted) { 1487 chooseUpstreamType(true); 1488 } 1489 break; 1490 } 1491 case EVENT_IFACE_SERVING_STATE_INACTIVE: { 1492 TetherInterfaceStateMachine who = (TetherInterfaceStateMachine)message.obj; 1493 if (VDBG) Log.d(TAG, "Tether Mode unrequested by " + who); 1494 handleInterfaceServingStateInactive(who); 1495 1496 if (mNotifyList.isEmpty()) { 1497 turnOffMasterTetherSettings(); // transitions appropriately 1498 } else { 1499 if (DBG) { 1500 Log.d(TAG, "TetherModeAlive still has " + mNotifyList.size() + 1501 " live requests:"); 1502 for (TetherInterfaceStateMachine o : mNotifyList) { 1503 Log.d(TAG, " " + o); 1504 } 1505 } 1506 } 1507 // If there has been a change and an upstream is no 1508 // longer desired, release any mobile requests. 1509 final boolean previousUpstreamWanted = updateUpstreamWanted(); 1510 if (previousUpstreamWanted && !mUpstreamWanted) { 1511 mUpstreamNetworkMonitor.releaseMobileNetworkRequest(); 1512 } 1513 break; 1514 } 1515 case CMD_UPSTREAM_CHANGED: 1516 updateUpstreamWanted(); 1517 if (!mUpstreamWanted) break; 1518 1519 // Need to try DUN immediately if Wi-Fi goes down. 1520 chooseUpstreamType(true); 1521 mTryCell = false; 1522 break; 1523 case CMD_RETRY_UPSTREAM: 1524 updateUpstreamWanted(); 1525 if (!mUpstreamWanted) break; 1526 1527 chooseUpstreamType(mTryCell); 1528 mTryCell = !mTryCell; 1529 break; 1530 case EVENT_UPSTREAM_CALLBACK: { 1531 updateUpstreamWanted(); 1532 if (!mUpstreamWanted) break; 1533 1534 final NetworkState ns = (NetworkState) message.obj; 1535 1536 if (ns == null || !pertainsToCurrentUpstream(ns)) { 1537 // TODO: In future, this is where upstream evaluation and selection 1538 // could be handled for notifications which include sufficient data. 1539 // For example, after CONNECTIVITY_ACTION listening is removed, here 1540 // is where we could observe a Wi-Fi network becoming available and 1541 // passing validation. 1542 if (mCurrentUpstreamIface == null) { 1543 // If we have no upstream interface, try to run through upstream 1544 // selection again. If, for example, IPv4 connectivity has shown up 1545 // after IPv6 (e.g., 464xlat became available) we want the chance to 1546 // notice and act accordingly. 1547 chooseUpstreamType(false); 1548 } 1549 break; 1550 } 1551 1552 switch (message.arg1) { 1553 case UpstreamNetworkMonitor.EVENT_ON_AVAILABLE: 1554 // The default network changed, or DUN connected 1555 // before this callback was processed. Updates 1556 // for the current NetworkCapabilities and 1557 // LinkProperties have been requested (default 1558 // request) or are being sent shortly (DUN). Do 1559 // nothing until they arrive; if no updates 1560 // arrive there's nothing to do. 1561 break; 1562 case UpstreamNetworkMonitor.EVENT_ON_CAPABILITIES: 1563 handleNewUpstreamNetworkState(ns); 1564 break; 1565 case UpstreamNetworkMonitor.EVENT_ON_LINKPROPERTIES: 1566 setDnsForwarders(ns.network, ns.linkProperties); 1567 handleNewUpstreamNetworkState(ns); 1568 break; 1569 case UpstreamNetworkMonitor.EVENT_ON_LOST: 1570 // TODO: Re-evaluate possible upstreams. Currently upstream 1571 // reevaluation is triggered via received CONNECTIVITY_ACTION 1572 // broadcasts that result in being passed a 1573 // TetherMasterSM.CMD_UPSTREAM_CHANGED. 1574 handleNewUpstreamNetworkState(null); 1575 break; 1576 default: 1577 break; 1578 } 1579 break; 1580 } 1581 default: 1582 retValue = false; 1583 break; 1584 } 1585 return retValue; 1586 } 1587 } 1588 1589 class ErrorState extends State { 1590 int mErrorNotification; 1591 @Override 1592 public boolean processMessage(Message message) { 1593 boolean retValue = true; 1594 switch (message.what) { 1595 case EVENT_IFACE_SERVING_STATE_ACTIVE: 1596 TetherInterfaceStateMachine who = (TetherInterfaceStateMachine)message.obj; 1597 who.sendMessage(mErrorNotification); 1598 break; 1599 case CMD_CLEAR_ERROR: 1600 mErrorNotification = ConnectivityManager.TETHER_ERROR_NO_ERROR; 1601 transitionTo(mInitialState); 1602 break; 1603 default: 1604 retValue = false; 1605 } 1606 return retValue; 1607 } 1608 void notify(int msgType) { 1609 mErrorNotification = msgType; 1610 for (TetherInterfaceStateMachine sm : mNotifyList) { 1611 sm.sendMessage(msgType); 1612 } 1613 } 1614 1615 } 1616 class SetIpForwardingEnabledErrorState extends ErrorState { 1617 @Override 1618 public void enter() { 1619 Log.e(TAG, "Error in setIpForwardingEnabled"); 1620 notify(TetherInterfaceStateMachine.CMD_IP_FORWARDING_ENABLE_ERROR); 1621 } 1622 } 1623 1624 class SetIpForwardingDisabledErrorState extends ErrorState { 1625 @Override 1626 public void enter() { 1627 Log.e(TAG, "Error in setIpForwardingDisabled"); 1628 notify(TetherInterfaceStateMachine.CMD_IP_FORWARDING_DISABLE_ERROR); 1629 } 1630 } 1631 1632 class StartTetheringErrorState extends ErrorState { 1633 @Override 1634 public void enter() { 1635 Log.e(TAG, "Error in startTethering"); 1636 notify(TetherInterfaceStateMachine.CMD_START_TETHERING_ERROR); 1637 try { 1638 mNMService.setIpForwardingEnabled(false); 1639 } catch (Exception e) {} 1640 } 1641 } 1642 1643 class StopTetheringErrorState extends ErrorState { 1644 @Override 1645 public void enter() { 1646 Log.e(TAG, "Error in stopTethering"); 1647 notify(TetherInterfaceStateMachine.CMD_STOP_TETHERING_ERROR); 1648 try { 1649 mNMService.setIpForwardingEnabled(false); 1650 } catch (Exception e) {} 1651 } 1652 } 1653 1654 class SetDnsForwardersErrorState extends ErrorState { 1655 @Override 1656 public void enter() { 1657 Log.e(TAG, "Error in setDnsForwarders"); 1658 notify(TetherInterfaceStateMachine.CMD_SET_DNS_FORWARDERS_ERROR); 1659 try { 1660 mNMService.stopTethering(); 1661 } catch (Exception e) {} 1662 try { 1663 mNMService.setIpForwardingEnabled(false); 1664 } catch (Exception e) {} 1665 } 1666 } 1667 } 1668 1669 @Override 1670 public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { 1671 // Binder.java closes the resource for us. 1672 @SuppressWarnings("resource") 1673 final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " "); 1674 if (mContext.checkCallingOrSelfPermission( 1675 android.Manifest.permission.DUMP) != PackageManager.PERMISSION_GRANTED) { 1676 pw.println("Permission Denial: can't dump ConnectivityService.Tether " + 1677 "from from pid=" + Binder.getCallingPid() + ", uid=" + 1678 Binder.getCallingUid()); 1679 return; 1680 } 1681 1682 pw.println("Tethering:"); 1683 pw.increaseIndent(); 1684 1685 pw.println("Configuration:"); 1686 pw.increaseIndent(); 1687 final TetheringConfiguration cfg = mConfig; 1688 cfg.dump(pw); 1689 pw.decreaseIndent(); 1690 1691 synchronized (mPublicSync) { 1692 pw.println("Tether state:"); 1693 pw.increaseIndent(); 1694 for (int i = 0; i < mTetherStates.size(); i++) { 1695 final String iface = mTetherStates.keyAt(i); 1696 final TetherState tetherState = mTetherStates.valueAt(i); 1697 pw.print(iface + " - "); 1698 1699 switch (tetherState.lastState) { 1700 case IControlsTethering.STATE_UNAVAILABLE: 1701 pw.print("UnavailableState"); 1702 break; 1703 case IControlsTethering.STATE_AVAILABLE: 1704 pw.print("AvailableState"); 1705 break; 1706 case IControlsTethering.STATE_TETHERED: 1707 pw.print("TetheredState"); 1708 break; 1709 case IControlsTethering.STATE_LOCAL_HOTSPOT: 1710 pw.print("LocalHotspotState"); 1711 break; 1712 default: 1713 pw.print("UnknownState"); 1714 break; 1715 } 1716 pw.println(" - lastError = " + tetherState.lastError); 1717 } 1718 pw.println("Upstream wanted: " + upstreamWanted()); 1719 pw.decreaseIndent(); 1720 } 1721 pw.decreaseIndent(); 1722 } 1723 1724 @Override 1725 public void notifyInterfaceStateChange(String iface, TetherInterfaceStateMachine who, 1726 int state, int error) { 1727 synchronized (mPublicSync) { 1728 TetherState tetherState = mTetherStates.get(iface); 1729 if (tetherState != null && tetherState.stateMachine.equals(who)) { 1730 tetherState.lastState = state; 1731 tetherState.lastError = error; 1732 } else { 1733 if (DBG) Log.d(TAG, "got notification from stale iface " + iface); 1734 } 1735 } 1736 1737 if (DBG) { 1738 Log.d(TAG, "iface " + iface + " notified that it was in state " + state + 1739 " with error " + error); 1740 } 1741 1742 try { 1743 // Notify that we're tethering (or not) this interface. 1744 // This is how data saver for instance knows if the user explicitly 1745 // turned on tethering (thus keeping us from being in data saver mode). 1746 mPolicyManager.onTetheringChanged(iface, state == IControlsTethering.STATE_TETHERED); 1747 } catch (RemoteException e) { 1748 // Not really very much we can do here. 1749 } 1750 1751 // If TetherMasterSM is in ErrorState, TetherMasterSM stays there. 1752 // Thus we give a chance for TetherMasterSM to recover to InitialState 1753 // by sending CMD_CLEAR_ERROR 1754 if (error == ConnectivityManager.TETHER_ERROR_MASTER_ERROR) { 1755 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_CLEAR_ERROR, who); 1756 } 1757 int which; 1758 switch (state) { 1759 case IControlsTethering.STATE_UNAVAILABLE: 1760 case IControlsTethering.STATE_AVAILABLE: 1761 which = TetherMasterSM.EVENT_IFACE_SERVING_STATE_INACTIVE; 1762 break; 1763 case IControlsTethering.STATE_TETHERED: 1764 case IControlsTethering.STATE_LOCAL_HOTSPOT: 1765 which = TetherMasterSM.EVENT_IFACE_SERVING_STATE_ACTIVE; 1766 break; 1767 default: 1768 Log.wtf(TAG, "Unknown interface state: " + state); 1769 return; 1770 } 1771 mTetherMasterSM.sendMessage(which, state, 0, who); 1772 sendTetherStateChangedBroadcast(); 1773 } 1774 1775 private void trackNewTetherableInterface(String iface, int interfaceType) { 1776 TetherState tetherState; 1777 tetherState = new TetherState(new TetherInterfaceStateMachine(iface, mLooper, 1778 interfaceType, mNMService, mStatsService, this, 1779 new IPv6TetheringInterfaceServices(iface, mNMService))); 1780 mTetherStates.put(iface, tetherState); 1781 tetherState.stateMachine.start(); 1782 } 1783 1784 private static String[] copy(String[] strarray) { 1785 return Arrays.copyOf(strarray, strarray.length); 1786 } 1787} 1788