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