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