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