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