Tethering.java revision cd63d247f08eddd506a679ffa244d6ac6c4742b1
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 android.app.Notification; 20import android.app.NotificationManager; 21import android.app.PendingIntent; 22import android.bluetooth.BluetoothAdapter; 23import android.bluetooth.BluetoothPan; 24import android.bluetooth.BluetoothProfile; 25import android.bluetooth.BluetoothProfile.ServiceListener; 26import android.content.BroadcastReceiver; 27import android.content.ComponentName; 28import android.content.Context; 29import android.content.Intent; 30import android.content.IntentFilter; 31import android.content.pm.PackageManager; 32import android.content.res.Resources; 33import android.hardware.usb.UsbManager; 34import android.net.ConnectivityManager; 35import android.net.ConnectivityManager.NetworkCallback; 36import android.net.INetworkStatsService; 37import android.net.InterfaceConfiguration; 38import android.net.LinkAddress; 39import android.net.LinkProperties; 40import android.net.Network; 41import android.net.NetworkCapabilities; 42import android.net.NetworkInfo; 43import android.net.NetworkRequest; 44import android.net.NetworkState; 45import android.net.NetworkUtils; 46import android.net.RouteInfo; 47import android.net.wifi.WifiManager; 48import android.os.Binder; 49import android.os.Bundle; 50import android.os.INetworkManagementService; 51import android.os.Looper; 52import android.os.Message; 53import android.os.Parcel; 54import android.os.ResultReceiver; 55import android.os.SystemProperties; 56import android.os.UserHandle; 57import android.provider.Settings; 58import android.telephony.CarrierConfigManager; 59import android.telephony.TelephonyManager; 60import android.text.TextUtils; 61import android.util.Log; 62import android.util.SparseArray; 63 64import com.android.internal.telephony.IccCardConstants; 65import com.android.internal.telephony.TelephonyIntents; 66import com.android.internal.util.IState; 67import com.android.internal.util.IndentingPrintWriter; 68import com.android.internal.util.MessageUtils; 69import com.android.internal.util.Protocol; 70import com.android.internal.util.State; 71import com.android.internal.util.StateMachine; 72import com.android.server.IoThread; 73import com.android.server.net.BaseNetworkObserver; 74 75import java.io.FileDescriptor; 76import java.io.PrintWriter; 77import java.net.Inet4Address; 78import java.net.InetAddress; 79import java.util.ArrayList; 80import java.util.Arrays; 81import java.util.Collection; 82import java.util.HashMap; 83import java.util.Iterator; 84import java.util.Set; 85import java.util.concurrent.atomic.AtomicInteger; 86 87 88/** 89 * @hide 90 * 91 * Timeout 92 * 93 * TODO - look for parent classes and code sharing 94 */ 95public class Tethering extends BaseNetworkObserver { 96 97 private final Context mContext; 98 private final static String TAG = "Tethering"; 99 private final static boolean DBG = false; 100 private final static boolean VDBG = false; 101 102 private static final Class[] messageClasses = { 103 Tethering.class, TetherMasterSM.class, TetherInterfaceSM.class 104 }; 105 private static final SparseArray<String> sMagicDecoderRing = 106 MessageUtils.findMessageNames(messageClasses); 107 108 // TODO - remove both of these - should be part of interface inspection/selection stuff 109 private String[] mTetherableUsbRegexs; 110 private String[] mTetherableWifiRegexs; 111 private String[] mTetherableBluetoothRegexs; 112 private Collection<Integer> mUpstreamIfaceTypes; 113 114 // used to synchronize public access to members 115 private final Object mPublicSync; 116 117 private static final Integer MOBILE_TYPE = new Integer(ConnectivityManager.TYPE_MOBILE); 118 private static final Integer HIPRI_TYPE = new Integer(ConnectivityManager.TYPE_MOBILE_HIPRI); 119 private static final Integer DUN_TYPE = new Integer(ConnectivityManager.TYPE_MOBILE_DUN); 120 121 // if we have to connect to mobile, what APN type should we use? Calculated by examining the 122 // upstream type list and the DUN_REQUIRED secure-setting 123 private int mPreferredUpstreamMobileApn = ConnectivityManager.TYPE_NONE; 124 125 private final INetworkManagementService mNMService; 126 private final INetworkStatsService mStatsService; 127 private final Looper mLooper; 128 129 private HashMap<String, TetherInterfaceSM> mIfaces; // all tethered/tetherable ifaces 130 131 private BroadcastReceiver mStateReceiver; 132 133 // {@link ComponentName} of the Service used to run tether provisioning. 134 private static final ComponentName TETHER_SERVICE = ComponentName.unflattenFromString(Resources 135 .getSystem().getString(com.android.internal.R.string.config_wifi_tether_enable)); 136 137 private static final String USB_NEAR_IFACE_ADDR = "192.168.42.129"; 138 private static final int USB_PREFIX_LENGTH = 24; 139 140 // USB is 192.168.42.1 and 255.255.255.0 141 // Wifi is 192.168.43.1 and 255.255.255.0 142 // BT is limited to max default of 5 connections. 192.168.44.1 to 192.168.48.1 143 // with 255.255.255.0 144 // P2P is 192.168.49.1 and 255.255.255.0 145 146 private String[] mDhcpRange; 147 private static final String[] DHCP_DEFAULT_RANGE = { 148 "192.168.42.2", "192.168.42.254", "192.168.43.2", "192.168.43.254", 149 "192.168.44.2", "192.168.44.254", "192.168.45.2", "192.168.45.254", 150 "192.168.46.2", "192.168.46.254", "192.168.47.2", "192.168.47.254", 151 "192.168.48.2", "192.168.48.254", "192.168.49.2", "192.168.49.254", 152 }; 153 154 private String[] mDefaultDnsServers; 155 private static final String DNS_DEFAULT_SERVER1 = "8.8.8.8"; 156 private static final String DNS_DEFAULT_SERVER2 = "8.8.4.4"; 157 158 private final StateMachine mTetherMasterSM; 159 private final UpstreamNetworkMonitor mUpstreamNetworkMonitor; 160 private String mCurrentUpstreamIface; 161 162 private Notification.Builder mTetheredNotificationBuilder; 163 private int mLastNotificationId; 164 165 private boolean mRndisEnabled; // track the RNDIS function enabled state 166 private boolean mUsbTetherRequested; // true if USB tethering should be started 167 // when RNDIS is enabled 168 169 public Tethering(Context context, INetworkManagementService nmService, 170 INetworkStatsService statsService) { 171 mContext = context; 172 mNMService = nmService; 173 mStatsService = statsService; 174 175 mPublicSync = new Object(); 176 177 mIfaces = new HashMap<String, TetherInterfaceSM>(); 178 179 // make our own thread so we don't anr the system 180 mLooper = IoThread.get().getLooper(); 181 mTetherMasterSM = new TetherMasterSM("TetherMaster", mLooper); 182 mTetherMasterSM.start(); 183 184 mUpstreamNetworkMonitor = new UpstreamNetworkMonitor(); 185 186 mStateReceiver = new StateReceiver(); 187 IntentFilter filter = new IntentFilter(); 188 filter.addAction(UsbManager.ACTION_USB_STATE); 189 filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); 190 filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED); 191 mContext.registerReceiver(mStateReceiver, filter); 192 193 filter = new IntentFilter(); 194 filter.addAction(Intent.ACTION_MEDIA_SHARED); 195 filter.addAction(Intent.ACTION_MEDIA_UNSHARED); 196 filter.addDataScheme("file"); 197 mContext.registerReceiver(mStateReceiver, filter); 198 199 mDhcpRange = context.getResources().getStringArray( 200 com.android.internal.R.array.config_tether_dhcp_range); 201 if ((mDhcpRange.length == 0) || (mDhcpRange.length % 2 ==1)) { 202 mDhcpRange = DHCP_DEFAULT_RANGE; 203 } 204 205 // load device config info 206 updateConfiguration(); 207 208 // TODO - remove and rely on real notifications of the current iface 209 mDefaultDnsServers = new String[2]; 210 mDefaultDnsServers[0] = DNS_DEFAULT_SERVER1; 211 mDefaultDnsServers[1] = DNS_DEFAULT_SERVER2; 212 } 213 214 // We can't do this once in the Tethering() constructor and cache the value, because the 215 // CONNECTIVITY_SERVICE is registered only after the Tethering() constructor has completed. 216 private ConnectivityManager getConnectivityManager() { 217 return (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE); 218 } 219 220 void updateConfiguration() { 221 String[] tetherableUsbRegexs = mContext.getResources().getStringArray( 222 com.android.internal.R.array.config_tether_usb_regexs); 223 String[] tetherableWifiRegexs = mContext.getResources().getStringArray( 224 com.android.internal.R.array.config_tether_wifi_regexs); 225 String[] tetherableBluetoothRegexs = mContext.getResources().getStringArray( 226 com.android.internal.R.array.config_tether_bluetooth_regexs); 227 228 int ifaceTypes[] = mContext.getResources().getIntArray( 229 com.android.internal.R.array.config_tether_upstream_types); 230 Collection<Integer> upstreamIfaceTypes = new ArrayList(); 231 for (int i : ifaceTypes) { 232 upstreamIfaceTypes.add(new Integer(i)); 233 } 234 235 synchronized (mPublicSync) { 236 mTetherableUsbRegexs = tetherableUsbRegexs; 237 mTetherableWifiRegexs = tetherableWifiRegexs; 238 mTetherableBluetoothRegexs = tetherableBluetoothRegexs; 239 mUpstreamIfaceTypes = upstreamIfaceTypes; 240 } 241 242 // check if the upstream type list needs to be modified due to secure-settings 243 checkDunRequired(); 244 } 245 246 @Override 247 public void interfaceStatusChanged(String iface, boolean up) { 248 // Never called directly: only called from interfaceLinkStateChanged. 249 // See NetlinkHandler.cpp:71. 250 if (VDBG) Log.d(TAG, "interfaceStatusChanged " + iface + ", " + up); 251 boolean found = false; 252 boolean usb = false; 253 synchronized (mPublicSync) { 254 if (isWifi(iface)) { 255 found = true; 256 } else if (isUsb(iface)) { 257 found = true; 258 usb = true; 259 } else if (isBluetooth(iface)) { 260 found = true; 261 } 262 if (found == false) return; 263 264 TetherInterfaceSM sm = mIfaces.get(iface); 265 if (up) { 266 if (sm == null) { 267 sm = new TetherInterfaceSM(iface, mLooper, usb); 268 mIfaces.put(iface, sm); 269 sm.start(); 270 } 271 } else { 272 if (isUsb(iface)) { 273 // ignore usb0 down after enabling RNDIS 274 // we will handle disconnect in interfaceRemoved instead 275 if (VDBG) Log.d(TAG, "ignore interface down for " + iface); 276 } else if (isWifi(iface)) { 277 // handle disconnect in interfaceRemoved 278 if (VDBG) Log.d(TAG, "ignore interface down for " + iface); 279 } else if (sm != null) { 280 sm.sendMessage(TetherInterfaceSM.CMD_INTERFACE_DOWN); 281 mIfaces.remove(iface); 282 } 283 } 284 } 285 } 286 287 @Override 288 public void interfaceLinkStateChanged(String iface, boolean up) { 289 interfaceStatusChanged(iface, up); 290 } 291 292 private boolean isUsb(String iface) { 293 synchronized (mPublicSync) { 294 for (String regex : mTetherableUsbRegexs) { 295 if (iface.matches(regex)) return true; 296 } 297 return false; 298 } 299 } 300 301 public boolean isWifi(String iface) { 302 synchronized (mPublicSync) { 303 for (String regex : mTetherableWifiRegexs) { 304 if (iface.matches(regex)) return true; 305 } 306 return false; 307 } 308 } 309 310 public boolean isBluetooth(String iface) { 311 synchronized (mPublicSync) { 312 for (String regex : mTetherableBluetoothRegexs) { 313 if (iface.matches(regex)) return true; 314 } 315 return false; 316 } 317 } 318 319 @Override 320 public void interfaceAdded(String iface) { 321 if (VDBG) Log.d(TAG, "interfaceAdded " + iface); 322 boolean found = false; 323 boolean usb = false; 324 synchronized (mPublicSync) { 325 if (isWifi(iface)) { 326 found = true; 327 } 328 if (isUsb(iface)) { 329 found = true; 330 usb = true; 331 } 332 if (isBluetooth(iface)) { 333 found = true; 334 } 335 if (found == false) { 336 if (VDBG) Log.d(TAG, iface + " is not a tetherable iface, ignoring"); 337 return; 338 } 339 340 TetherInterfaceSM sm = mIfaces.get(iface); 341 if (sm != null) { 342 if (VDBG) Log.d(TAG, "active iface (" + iface + ") reported as added, ignoring"); 343 return; 344 } 345 sm = new TetherInterfaceSM(iface, mLooper, usb); 346 mIfaces.put(iface, sm); 347 sm.start(); 348 } 349 } 350 351 @Override 352 public void interfaceRemoved(String iface) { 353 if (VDBG) Log.d(TAG, "interfaceRemoved " + iface); 354 synchronized (mPublicSync) { 355 TetherInterfaceSM sm = mIfaces.get(iface); 356 if (sm == null) { 357 if (VDBG) { 358 Log.e(TAG, "attempting to remove unknown iface (" + iface + "), ignoring"); 359 } 360 return; 361 } 362 sm.sendMessage(TetherInterfaceSM.CMD_INTERFACE_DOWN); 363 mIfaces.remove(iface); 364 } 365 } 366 367 public void startTethering(int type, ResultReceiver receiver, 368 boolean showProvisioningUi) { 369 if (!isTetherProvisioningRequired()) { 370 enableTetheringInternal(type, true, receiver); 371 return; 372 } 373 374 if (showProvisioningUi) { 375 runUiTetherProvisioningAndEnable(type, receiver); 376 } else { 377 runSilentTetherProvisioningAndEnable(type, receiver); 378 } 379 } 380 381 public void stopTethering(int type) { 382 enableTetheringInternal(type, false, null); 383 if (isTetherProvisioningRequired()) { 384 cancelTetherProvisioningRechecks(type); 385 } 386 } 387 388 /** 389 * Check if the device requires a provisioning check in order to enable tethering. 390 * 391 * @return a boolean - {@code true} indicating tether provisioning is required by the carrier. 392 */ 393 private boolean isTetherProvisioningRequired() { 394 String[] provisionApp = mContext.getResources().getStringArray( 395 com.android.internal.R.array.config_mobile_hotspot_provision_app); 396 if (SystemProperties.getBoolean("net.tethering.noprovisioning", false) 397 || provisionApp == null) { 398 return false; 399 } 400 401 // Check carrier config for entitlement checks 402 final CarrierConfigManager configManager = (CarrierConfigManager) mContext 403 .getSystemService(Context.CARRIER_CONFIG_SERVICE); 404 boolean isEntitlementCheckRequired = configManager.getConfig().getBoolean( 405 CarrierConfigManager.KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL); 406 407 if (!isEntitlementCheckRequired) { 408 return false; 409 } 410 return (provisionApp.length == 2); 411 } 412 413 /** 414 * Enables or disables tethering for the given type. This should only be called once 415 * provisioning has succeeded or is not necessary. It will also schedule provisioning rechecks 416 * for the specified interface. 417 */ 418 private void enableTetheringInternal(int type, boolean enable, ResultReceiver receiver) { 419 boolean isProvisioningRequired = isTetherProvisioningRequired(); 420 switch (type) { 421 case ConnectivityManager.TETHERING_WIFI: 422 final WifiManager wifiManager = 423 (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE); 424 if (wifiManager.setWifiApEnabled(null, enable)) { 425 sendTetherResult(receiver, ConnectivityManager.TETHER_ERROR_NO_ERROR); 426 if (enable && isProvisioningRequired) { 427 scheduleProvisioningRechecks(type); 428 } 429 } else{ 430 sendTetherResult(receiver, ConnectivityManager.TETHER_ERROR_MASTER_ERROR); 431 } 432 break; 433 case ConnectivityManager.TETHERING_USB: 434 int result = setUsbTethering(enable); 435 if (enable && isProvisioningRequired && 436 result == ConnectivityManager.TETHER_ERROR_NO_ERROR) { 437 scheduleProvisioningRechecks(type); 438 } 439 sendTetherResult(receiver, result); 440 break; 441 case ConnectivityManager.TETHERING_BLUETOOTH: 442 setBluetoothTethering(enable, receiver); 443 break; 444 default: 445 Log.w(TAG, "Invalid tether type."); 446 sendTetherResult(receiver, ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE); 447 } 448 } 449 450 private void sendTetherResult(ResultReceiver receiver, int result) { 451 if (receiver != null) { 452 receiver.send(result, null); 453 } 454 } 455 456 private void setBluetoothTethering(final boolean enable, final ResultReceiver receiver) { 457 final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 458 if (adapter == null || !adapter.isEnabled()) { 459 Log.w(TAG, "Tried to enable bluetooth tethering with null or disabled adapter. null: " + 460 (adapter == null)); 461 sendTetherResult(receiver, ConnectivityManager.TETHER_ERROR_SERVICE_UNAVAIL); 462 return; 463 } 464 465 adapter.getProfileProxy(mContext, new ServiceListener() { 466 @Override 467 public void onServiceDisconnected(int profile) { } 468 469 @Override 470 public void onServiceConnected(int profile, BluetoothProfile proxy) { 471 ((BluetoothPan) proxy).setBluetoothTethering(enable); 472 // TODO: Enabling bluetooth tethering can fail asynchronously here. 473 // We should figure out a way to bubble up that failure instead of sending success. 474 int result = ((BluetoothPan) proxy).isTetheringOn() == enable ? 475 ConnectivityManager.TETHER_ERROR_NO_ERROR : 476 ConnectivityManager.TETHER_ERROR_MASTER_ERROR; 477 sendTetherResult(receiver, result); 478 if (enable && isTetherProvisioningRequired()) { 479 scheduleProvisioningRechecks(ConnectivityManager.TETHERING_BLUETOOTH); 480 } 481 adapter.closeProfileProxy(BluetoothProfile.PAN, proxy); 482 } 483 }, BluetoothProfile.PAN); 484 } 485 486 private void runUiTetherProvisioningAndEnable(int type, ResultReceiver receiver) { 487 ResultReceiver proxyReceiver = getProxyReceiver(type, receiver); 488 sendUiTetherProvisionIntent(type, proxyReceiver); 489 } 490 491 private void sendUiTetherProvisionIntent(int type, ResultReceiver receiver) { 492 Intent intent = new Intent(Settings.ACTION_TETHER_PROVISIONING); 493 intent.putExtra(ConnectivityManager.EXTRA_ADD_TETHER_TYPE, type); 494 intent.putExtra(ConnectivityManager.EXTRA_PROVISION_CALLBACK, receiver); 495 final long ident = Binder.clearCallingIdentity(); 496 try { 497 mContext.startActivityAsUser(intent, UserHandle.CURRENT); 498 } finally { 499 Binder.restoreCallingIdentity(ident); 500 } 501 } 502 503 /** 504 * Creates a proxy {@link ResultReceiver} which enables tethering if the provsioning result is 505 * successful before firing back up to the wrapped receiver. 506 * 507 * @param type The type of tethering being enabled. 508 * @param receiver A ResultReceiver which will be called back with an int resultCode. 509 * @return The proxy receiver. 510 */ 511 private ResultReceiver getProxyReceiver(final int type, final ResultReceiver receiver) { 512 ResultReceiver rr = new ResultReceiver(null) { 513 @Override 514 protected void onReceiveResult(int resultCode, Bundle resultData) { 515 // If provisioning is successful, enable tethering, otherwise just send the error. 516 if (resultCode == ConnectivityManager.TETHER_ERROR_NO_ERROR) { 517 enableTetheringInternal(type, true, receiver); 518 } else { 519 sendTetherResult(receiver, resultCode); 520 } 521 } 522 }; 523 524 // The following is necessary to avoid unmarshalling issues when sending the receiver 525 // across processes. 526 Parcel parcel = Parcel.obtain(); 527 rr.writeToParcel(parcel,0); 528 parcel.setDataPosition(0); 529 ResultReceiver receiverForSending = ResultReceiver.CREATOR.createFromParcel(parcel); 530 parcel.recycle(); 531 return receiverForSending; 532 } 533 534 private void scheduleProvisioningRechecks(int type) { 535 Intent intent = new Intent(); 536 intent.putExtra(ConnectivityManager.EXTRA_ADD_TETHER_TYPE, type); 537 intent.putExtra(ConnectivityManager.EXTRA_SET_ALARM, true); 538 intent.setComponent(TETHER_SERVICE); 539 final long ident = Binder.clearCallingIdentity(); 540 try { 541 mContext.startServiceAsUser(intent, UserHandle.CURRENT); 542 } finally { 543 Binder.restoreCallingIdentity(ident); 544 } 545 } 546 547 private void runSilentTetherProvisioningAndEnable(int type, ResultReceiver receiver) { 548 ResultReceiver proxyReceiver = getProxyReceiver(type, receiver); 549 sendSilentTetherProvisionIntent(type, proxyReceiver); 550 } 551 552 private void sendSilentTetherProvisionIntent(int type, ResultReceiver receiver) { 553 Intent intent = new Intent(); 554 intent.putExtra(ConnectivityManager.EXTRA_ADD_TETHER_TYPE, type); 555 intent.putExtra(ConnectivityManager.EXTRA_RUN_PROVISION, true); 556 intent.putExtra(ConnectivityManager.EXTRA_PROVISION_CALLBACK, receiver); 557 intent.setComponent(TETHER_SERVICE); 558 final long ident = Binder.clearCallingIdentity(); 559 try { 560 mContext.startServiceAsUser(intent, UserHandle.CURRENT); 561 } finally { 562 Binder.restoreCallingIdentity(ident); 563 } 564 } 565 566 private void cancelTetherProvisioningRechecks(int type) { 567 if (getConnectivityManager().isTetheringSupported()) { 568 Intent intent = new Intent(); 569 intent.putExtra(ConnectivityManager.EXTRA_REM_TETHER_TYPE, type); 570 intent.setComponent(TETHER_SERVICE); 571 final long ident = Binder.clearCallingIdentity(); 572 try { 573 mContext.startServiceAsUser(intent, UserHandle.CURRENT); 574 } finally { 575 Binder.restoreCallingIdentity(ident); 576 } 577 } 578 } 579 580 public int tether(String iface) { 581 if (DBG) Log.d(TAG, "Tethering " + iface); 582 TetherInterfaceSM sm = null; 583 synchronized (mPublicSync) { 584 sm = mIfaces.get(iface); 585 } 586 if (sm == null) { 587 Log.e(TAG, "Tried to Tether an unknown iface :" + iface + ", ignoring"); 588 return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE; 589 } 590 if (!sm.isAvailable() && !sm.isErrored()) { 591 Log.e(TAG, "Tried to Tether an unavailable iface :" + iface + ", ignoring"); 592 return ConnectivityManager.TETHER_ERROR_UNAVAIL_IFACE; 593 } 594 sm.sendMessage(TetherInterfaceSM.CMD_TETHER_REQUESTED); 595 return ConnectivityManager.TETHER_ERROR_NO_ERROR; 596 } 597 598 public int untether(String iface) { 599 if (DBG) Log.d(TAG, "Untethering " + iface); 600 TetherInterfaceSM sm = null; 601 synchronized (mPublicSync) { 602 sm = mIfaces.get(iface); 603 } 604 if (sm == null) { 605 Log.e(TAG, "Tried to Untether an unknown iface :" + iface + ", ignoring"); 606 return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE; 607 } 608 if (sm.isErrored()) { 609 Log.e(TAG, "Tried to Untethered an errored iface :" + iface + ", ignoring"); 610 return ConnectivityManager.TETHER_ERROR_UNAVAIL_IFACE; 611 } 612 sm.sendMessage(TetherInterfaceSM.CMD_TETHER_UNREQUESTED); 613 return ConnectivityManager.TETHER_ERROR_NO_ERROR; 614 } 615 616 public int getLastTetherError(String iface) { 617 TetherInterfaceSM sm = null; 618 synchronized (mPublicSync) { 619 sm = mIfaces.get(iface); 620 if (sm == null) { 621 Log.e(TAG, "Tried to getLastTetherError on an unknown iface :" + iface + 622 ", ignoring"); 623 return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE; 624 } 625 return sm.getLastError(); 626 } 627 } 628 629 // TODO - move all private methods used only by the state machine into the state machine 630 // to clarify what needs synchronized protection. 631 private void sendTetherStateChangedBroadcast() { 632 if (!getConnectivityManager().isTetheringSupported()) return; 633 634 ArrayList<String> availableList = new ArrayList<String>(); 635 ArrayList<String> activeList = new ArrayList<String>(); 636 ArrayList<String> erroredList = new ArrayList<String>(); 637 638 boolean wifiTethered = false; 639 boolean usbTethered = false; 640 boolean bluetoothTethered = false; 641 642 synchronized (mPublicSync) { 643 Set ifaces = mIfaces.keySet(); 644 for (Object iface : ifaces) { 645 TetherInterfaceSM sm = mIfaces.get(iface); 646 if (sm != null) { 647 if (sm.isErrored()) { 648 erroredList.add((String)iface); 649 } else if (sm.isAvailable()) { 650 availableList.add((String)iface); 651 } else if (sm.isTethered()) { 652 if (isUsb((String)iface)) { 653 usbTethered = true; 654 } else if (isWifi((String)iface)) { 655 wifiTethered = true; 656 } else if (isBluetooth((String)iface)) { 657 bluetoothTethered = true; 658 } 659 activeList.add((String)iface); 660 } 661 } 662 } 663 } 664 Intent broadcast = new Intent(ConnectivityManager.ACTION_TETHER_STATE_CHANGED); 665 broadcast.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING | 666 Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 667 broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_AVAILABLE_TETHER, 668 availableList); 669 broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_ACTIVE_TETHER, activeList); 670 broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_ERRORED_TETHER, 671 erroredList); 672 mContext.sendStickyBroadcastAsUser(broadcast, UserHandle.ALL); 673 if (DBG) { 674 Log.d(TAG, String.format( 675 "sendTetherStateChangedBroadcast avail=[%s] active=[%s] error=[%s]", 676 TextUtils.join(",", availableList), 677 TextUtils.join(",", activeList), 678 TextUtils.join(",", erroredList))); 679 } 680 681 if (usbTethered) { 682 if (wifiTethered || bluetoothTethered) { 683 showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_general); 684 } else { 685 showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_usb); 686 } 687 } else if (wifiTethered) { 688 if (bluetoothTethered) { 689 showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_general); 690 } else { 691 /* We now have a status bar icon for WifiTethering, so drop the notification */ 692 clearTetheredNotification(); 693 } 694 } else if (bluetoothTethered) { 695 showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_bluetooth); 696 } else { 697 clearTetheredNotification(); 698 } 699 } 700 701 private void showTetheredNotification(int icon) { 702 NotificationManager notificationManager = 703 (NotificationManager)mContext.getSystemService(Context.NOTIFICATION_SERVICE); 704 if (notificationManager == null) { 705 return; 706 } 707 708 if (mLastNotificationId != 0) { 709 if (mLastNotificationId == icon) { 710 return; 711 } 712 notificationManager.cancelAsUser(null, mLastNotificationId, 713 UserHandle.ALL); 714 mLastNotificationId = 0; 715 } 716 717 Intent intent = new Intent(); 718 intent.setClassName("com.android.settings", "com.android.settings.TetherSettings"); 719 intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY); 720 721 PendingIntent pi = PendingIntent.getActivityAsUser(mContext, 0, intent, 0, 722 null, UserHandle.CURRENT); 723 724 Resources r = Resources.getSystem(); 725 CharSequence title = r.getText(com.android.internal.R.string.tethered_notification_title); 726 CharSequence message = r.getText(com.android.internal.R.string. 727 tethered_notification_message); 728 729 if (mTetheredNotificationBuilder == null) { 730 mTetheredNotificationBuilder = new Notification.Builder(mContext); 731 mTetheredNotificationBuilder.setWhen(0) 732 .setOngoing(true) 733 .setColor(mContext.getColor( 734 com.android.internal.R.color.system_notification_accent_color)) 735 .setVisibility(Notification.VISIBILITY_PUBLIC) 736 .setCategory(Notification.CATEGORY_STATUS); 737 } 738 mTetheredNotificationBuilder.setSmallIcon(icon) 739 .setContentTitle(title) 740 .setContentText(message) 741 .setContentIntent(pi); 742 mLastNotificationId = icon; 743 744 notificationManager.notifyAsUser(null, mLastNotificationId, 745 mTetheredNotificationBuilder.build(), UserHandle.ALL); 746 } 747 748 private void clearTetheredNotification() { 749 NotificationManager notificationManager = 750 (NotificationManager)mContext.getSystemService(Context.NOTIFICATION_SERVICE); 751 if (notificationManager != null && mLastNotificationId != 0) { 752 notificationManager.cancelAsUser(null, mLastNotificationId, 753 UserHandle.ALL); 754 mLastNotificationId = 0; 755 } 756 } 757 758 private class StateReceiver extends BroadcastReceiver { 759 @Override 760 public void onReceive(Context content, Intent intent) { 761 String action = intent.getAction(); 762 if (action == null) { return; } 763 if (action.equals(UsbManager.ACTION_USB_STATE)) { 764 synchronized (Tethering.this.mPublicSync) { 765 boolean usbConnected = intent.getBooleanExtra(UsbManager.USB_CONNECTED, false); 766 mRndisEnabled = intent.getBooleanExtra(UsbManager.USB_FUNCTION_RNDIS, false); 767 // start tethering if we have a request pending 768 if (usbConnected && mRndisEnabled && mUsbTetherRequested) { 769 tetherUsb(true); 770 } 771 mUsbTetherRequested = false; 772 } 773 } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) { 774 NetworkInfo networkInfo = (NetworkInfo)intent.getParcelableExtra( 775 ConnectivityManager.EXTRA_NETWORK_INFO); 776 if (networkInfo != null && 777 networkInfo.getDetailedState() != NetworkInfo.DetailedState.FAILED) { 778 if (VDBG) Log.d(TAG, "Tethering got CONNECTIVITY_ACTION"); 779 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_UPSTREAM_CHANGED); 780 } 781 } else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) { 782 updateConfiguration(); 783 } 784 } 785 } 786 787 private void tetherUsb(boolean enable) { 788 if (VDBG) Log.d(TAG, "tetherUsb " + enable); 789 790 String[] ifaces = new String[0]; 791 try { 792 ifaces = mNMService.listInterfaces(); 793 } catch (Exception e) { 794 Log.e(TAG, "Error listing Interfaces", e); 795 return; 796 } 797 for (String iface : ifaces) { 798 if (isUsb(iface)) { 799 int result = (enable ? tether(iface) : untether(iface)); 800 if (result == ConnectivityManager.TETHER_ERROR_NO_ERROR) { 801 return; 802 } 803 } 804 } 805 Log.e(TAG, "unable start or stop USB tethering"); 806 } 807 808 // configured when we start tethering and unconfig'd on error or conclusion 809 private boolean configureUsbIface(boolean enabled) { 810 if (VDBG) Log.d(TAG, "configureUsbIface(" + enabled + ")"); 811 812 // toggle the USB interfaces 813 String[] ifaces = new String[0]; 814 try { 815 ifaces = mNMService.listInterfaces(); 816 } catch (Exception e) { 817 Log.e(TAG, "Error listing Interfaces", e); 818 return false; 819 } 820 for (String iface : ifaces) { 821 if (isUsb(iface)) { 822 InterfaceConfiguration ifcg = null; 823 try { 824 ifcg = mNMService.getInterfaceConfig(iface); 825 if (ifcg != null) { 826 InetAddress addr = NetworkUtils.numericToInetAddress(USB_NEAR_IFACE_ADDR); 827 ifcg.setLinkAddress(new LinkAddress(addr, USB_PREFIX_LENGTH)); 828 if (enabled) { 829 ifcg.setInterfaceUp(); 830 } else { 831 ifcg.setInterfaceDown(); 832 } 833 ifcg.clearFlag("running"); 834 mNMService.setInterfaceConfig(iface, ifcg); 835 } 836 } catch (Exception e) { 837 Log.e(TAG, "Error configuring interface " + iface, e); 838 return false; 839 } 840 } 841 } 842 843 return true; 844 } 845 846 // TODO - return copies so people can't tamper 847 public String[] getTetherableUsbRegexs() { 848 return mTetherableUsbRegexs; 849 } 850 851 public String[] getTetherableWifiRegexs() { 852 return mTetherableWifiRegexs; 853 } 854 855 public String[] getTetherableBluetoothRegexs() { 856 return mTetherableBluetoothRegexs; 857 } 858 859 public int setUsbTethering(boolean enable) { 860 if (VDBG) Log.d(TAG, "setUsbTethering(" + enable + ")"); 861 UsbManager usbManager = (UsbManager)mContext.getSystemService(Context.USB_SERVICE); 862 863 synchronized (mPublicSync) { 864 if (enable) { 865 if (mRndisEnabled) { 866 final long ident = Binder.clearCallingIdentity(); 867 try { 868 tetherUsb(true); 869 } finally { 870 Binder.restoreCallingIdentity(ident); 871 } 872 } else { 873 mUsbTetherRequested = true; 874 usbManager.setCurrentFunction(UsbManager.USB_FUNCTION_RNDIS); 875 } 876 } else { 877 final long ident = Binder.clearCallingIdentity(); 878 try { 879 tetherUsb(false); 880 } finally { 881 Binder.restoreCallingIdentity(ident); 882 } 883 if (mRndisEnabled) { 884 usbManager.setCurrentFunction(null); 885 } 886 mUsbTetherRequested = false; 887 } 888 } 889 return ConnectivityManager.TETHER_ERROR_NO_ERROR; 890 } 891 892 public int[] getUpstreamIfaceTypes() { 893 int values[]; 894 synchronized (mPublicSync) { 895 updateConfiguration(); // TODO - remove? 896 values = new int[mUpstreamIfaceTypes.size()]; 897 Iterator<Integer> iterator = mUpstreamIfaceTypes.iterator(); 898 for (int i=0; i < mUpstreamIfaceTypes.size(); i++) { 899 values[i] = iterator.next(); 900 } 901 } 902 return values; 903 } 904 905 private void checkDunRequired() { 906 int secureSetting = 2; 907 TelephonyManager tm = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE); 908 if (tm != null) { 909 secureSetting = tm.getTetherApnRequired(); 910 } 911 synchronized (mPublicSync) { 912 // 2 = not set, 0 = DUN not required, 1 = DUN required 913 if (secureSetting != 2) { 914 int requiredApn = (secureSetting == 1 ? 915 ConnectivityManager.TYPE_MOBILE_DUN : 916 ConnectivityManager.TYPE_MOBILE_HIPRI); 917 if (requiredApn == ConnectivityManager.TYPE_MOBILE_DUN) { 918 while (mUpstreamIfaceTypes.contains(MOBILE_TYPE)) { 919 mUpstreamIfaceTypes.remove(MOBILE_TYPE); 920 } 921 while (mUpstreamIfaceTypes.contains(HIPRI_TYPE)) { 922 mUpstreamIfaceTypes.remove(HIPRI_TYPE); 923 } 924 if (mUpstreamIfaceTypes.contains(DUN_TYPE) == false) { 925 mUpstreamIfaceTypes.add(DUN_TYPE); 926 } 927 } else { 928 while (mUpstreamIfaceTypes.contains(DUN_TYPE)) { 929 mUpstreamIfaceTypes.remove(DUN_TYPE); 930 } 931 if (mUpstreamIfaceTypes.contains(MOBILE_TYPE) == false) { 932 mUpstreamIfaceTypes.add(MOBILE_TYPE); 933 } 934 if (mUpstreamIfaceTypes.contains(HIPRI_TYPE) == false) { 935 mUpstreamIfaceTypes.add(HIPRI_TYPE); 936 } 937 } 938 } 939 if (mUpstreamIfaceTypes.contains(DUN_TYPE)) { 940 mPreferredUpstreamMobileApn = ConnectivityManager.TYPE_MOBILE_DUN; 941 } else { 942 mPreferredUpstreamMobileApn = ConnectivityManager.TYPE_MOBILE_HIPRI; 943 } 944 } 945 } 946 947 // TODO review API - maybe return ArrayList<String> here and below? 948 public String[] getTetheredIfaces() { 949 ArrayList<String> list = new ArrayList<String>(); 950 synchronized (mPublicSync) { 951 Set keys = mIfaces.keySet(); 952 for (Object key : keys) { 953 TetherInterfaceSM sm = mIfaces.get(key); 954 if (sm.isTethered()) { 955 list.add((String)key); 956 } 957 } 958 } 959 String[] retVal = new String[list.size()]; 960 for (int i=0; i < list.size(); i++) { 961 retVal[i] = list.get(i); 962 } 963 return retVal; 964 } 965 966 public String[] getTetherableIfaces() { 967 ArrayList<String> list = new ArrayList<String>(); 968 synchronized (mPublicSync) { 969 Set keys = mIfaces.keySet(); 970 for (Object key : keys) { 971 TetherInterfaceSM sm = mIfaces.get(key); 972 if (sm.isAvailable()) { 973 list.add((String)key); 974 } 975 } 976 } 977 String[] retVal = new String[list.size()]; 978 for (int i=0; i < list.size(); i++) { 979 retVal[i] = list.get(i); 980 } 981 return retVal; 982 } 983 984 public String[] getTetheredDhcpRanges() { 985 return mDhcpRange; 986 } 987 988 public String[] getErroredIfaces() { 989 ArrayList<String> list = new ArrayList<String>(); 990 synchronized (mPublicSync) { 991 Set keys = mIfaces.keySet(); 992 for (Object key : keys) { 993 TetherInterfaceSM sm = mIfaces.get(key); 994 if (sm.isErrored()) { 995 list.add((String)key); 996 } 997 } 998 } 999 String[] retVal = new String[list.size()]; 1000 for (int i= 0; i< list.size(); i++) { 1001 retVal[i] = list.get(i); 1002 } 1003 return retVal; 1004 } 1005 1006 private void maybeLogMessage(State state, int what) { 1007 if (DBG) { 1008 Log.d(TAG, state.getName() + " got " + 1009 sMagicDecoderRing.get(what, Integer.toString(what))); 1010 } 1011 } 1012 1013 class TetherInterfaceSM extends StateMachine { 1014 private static final int BASE_IFACE = Protocol.BASE_TETHERING + 100; 1015 // notification from the master SM that it's not in tether mode 1016 static final int CMD_TETHER_MODE_DEAD = BASE_IFACE + 1; 1017 // request from the user that it wants to tether 1018 static final int CMD_TETHER_REQUESTED = BASE_IFACE + 2; 1019 // request from the user that it wants to untether 1020 static final int CMD_TETHER_UNREQUESTED = BASE_IFACE + 3; 1021 // notification that this interface is down 1022 static final int CMD_INTERFACE_DOWN = BASE_IFACE + 4; 1023 // notification that this interface is up 1024 static final int CMD_INTERFACE_UP = BASE_IFACE + 5; 1025 // notification from the master SM that it had an error turning on cellular dun 1026 static final int CMD_CELL_DUN_ERROR = BASE_IFACE + 6; 1027 // notification from the master SM that it had trouble enabling IP Forwarding 1028 static final int CMD_IP_FORWARDING_ENABLE_ERROR = BASE_IFACE + 7; 1029 // notification from the master SM that it had trouble disabling IP Forwarding 1030 static final int CMD_IP_FORWARDING_DISABLE_ERROR = BASE_IFACE + 8; 1031 // notification from the master SM that it had trouble starting tethering 1032 static final int CMD_START_TETHERING_ERROR = BASE_IFACE + 9; 1033 // notification from the master SM that it had trouble stopping tethering 1034 static final int CMD_STOP_TETHERING_ERROR = BASE_IFACE + 10; 1035 // notification from the master SM that it had trouble setting the DNS forwarders 1036 static final int CMD_SET_DNS_FORWARDERS_ERROR = BASE_IFACE + 11; 1037 // the upstream connection has changed 1038 static final int CMD_TETHER_CONNECTION_CHANGED = BASE_IFACE + 12; 1039 1040 private State mDefaultState; 1041 1042 private State mInitialState; 1043 private State mStartingState; 1044 private State mTetheredState; 1045 1046 private State mUnavailableState; 1047 1048 private boolean mAvailable; 1049 private boolean mTethered; 1050 int mLastError; 1051 1052 String mIfaceName; 1053 String mMyUpstreamIfaceName; // may change over time 1054 1055 boolean mUsb; 1056 1057 TetherInterfaceSM(String name, Looper looper, boolean usb) { 1058 super(name, looper); 1059 mIfaceName = name; 1060 mUsb = usb; 1061 setLastError(ConnectivityManager.TETHER_ERROR_NO_ERROR); 1062 1063 mInitialState = new InitialState(); 1064 addState(mInitialState); 1065 mStartingState = new StartingState(); 1066 addState(mStartingState); 1067 mTetheredState = new TetheredState(); 1068 addState(mTetheredState); 1069 mUnavailableState = new UnavailableState(); 1070 addState(mUnavailableState); 1071 1072 setInitialState(mInitialState); 1073 } 1074 1075 public String toString() { 1076 String res = new String(); 1077 res += mIfaceName + " - "; 1078 IState current = getCurrentState(); 1079 if (current == mInitialState) res += "InitialState"; 1080 if (current == mStartingState) res += "StartingState"; 1081 if (current == mTetheredState) res += "TetheredState"; 1082 if (current == mUnavailableState) res += "UnavailableState"; 1083 if (mAvailable) res += " - Available"; 1084 if (mTethered) res += " - Tethered"; 1085 res += " - lastError =" + mLastError; 1086 return res; 1087 } 1088 1089 public int getLastError() { 1090 synchronized (Tethering.this.mPublicSync) { 1091 return mLastError; 1092 } 1093 } 1094 1095 private void setLastError(int error) { 1096 synchronized (Tethering.this.mPublicSync) { 1097 mLastError = error; 1098 1099 if (isErrored()) { 1100 if (mUsb) { 1101 // note everything's been unwound by this point so nothing to do on 1102 // further error.. 1103 Tethering.this.configureUsbIface(false); 1104 } 1105 } 1106 } 1107 } 1108 1109 public boolean isAvailable() { 1110 synchronized (Tethering.this.mPublicSync) { 1111 return mAvailable; 1112 } 1113 } 1114 1115 private void setAvailable(boolean available) { 1116 synchronized (Tethering.this.mPublicSync) { 1117 mAvailable = available; 1118 } 1119 } 1120 1121 public boolean isTethered() { 1122 synchronized (Tethering.this.mPublicSync) { 1123 return mTethered; 1124 } 1125 } 1126 1127 private void setTethered(boolean tethered) { 1128 synchronized (Tethering.this.mPublicSync) { 1129 mTethered = tethered; 1130 } 1131 } 1132 1133 public boolean isErrored() { 1134 synchronized (Tethering.this.mPublicSync) { 1135 return (mLastError != ConnectivityManager.TETHER_ERROR_NO_ERROR); 1136 } 1137 } 1138 1139 class InitialState extends State { 1140 @Override 1141 public void enter() { 1142 setAvailable(true); 1143 setTethered(false); 1144 sendTetherStateChangedBroadcast(); 1145 } 1146 1147 @Override 1148 public boolean processMessage(Message message) { 1149 maybeLogMessage(this, message.what); 1150 boolean retValue = true; 1151 switch (message.what) { 1152 case CMD_TETHER_REQUESTED: 1153 setLastError(ConnectivityManager.TETHER_ERROR_NO_ERROR); 1154 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_REQUESTED, 1155 TetherInterfaceSM.this); 1156 transitionTo(mStartingState); 1157 break; 1158 case CMD_INTERFACE_DOWN: 1159 transitionTo(mUnavailableState); 1160 break; 1161 default: 1162 retValue = false; 1163 break; 1164 } 1165 return retValue; 1166 } 1167 } 1168 1169 class StartingState extends State { 1170 @Override 1171 public void enter() { 1172 setAvailable(false); 1173 if (mUsb) { 1174 if (!Tethering.this.configureUsbIface(true)) { 1175 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED, 1176 TetherInterfaceSM.this); 1177 setLastError(ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR); 1178 1179 transitionTo(mInitialState); 1180 return; 1181 } 1182 } 1183 sendTetherStateChangedBroadcast(); 1184 1185 // Skipping StartingState 1186 transitionTo(mTetheredState); 1187 } 1188 @Override 1189 public boolean processMessage(Message message) { 1190 maybeLogMessage(this, message.what); 1191 boolean retValue = true; 1192 switch (message.what) { 1193 // maybe a parent class? 1194 case CMD_TETHER_UNREQUESTED: 1195 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED, 1196 TetherInterfaceSM.this); 1197 if (mUsb) { 1198 if (!Tethering.this.configureUsbIface(false)) { 1199 setLastErrorAndTransitionToInitialState( 1200 ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR); 1201 break; 1202 } 1203 } 1204 transitionTo(mInitialState); 1205 break; 1206 case CMD_CELL_DUN_ERROR: 1207 case CMD_IP_FORWARDING_ENABLE_ERROR: 1208 case CMD_IP_FORWARDING_DISABLE_ERROR: 1209 case CMD_START_TETHERING_ERROR: 1210 case CMD_STOP_TETHERING_ERROR: 1211 case CMD_SET_DNS_FORWARDERS_ERROR: 1212 setLastErrorAndTransitionToInitialState( 1213 ConnectivityManager.TETHER_ERROR_MASTER_ERROR); 1214 break; 1215 case CMD_INTERFACE_DOWN: 1216 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED, 1217 TetherInterfaceSM.this); 1218 transitionTo(mUnavailableState); 1219 break; 1220 default: 1221 retValue = false; 1222 } 1223 return retValue; 1224 } 1225 } 1226 1227 class TetheredState extends State { 1228 @Override 1229 public void enter() { 1230 try { 1231 mNMService.tetherInterface(mIfaceName); 1232 } catch (Exception e) { 1233 Log.e(TAG, "Error Tethering: " + e.toString()); 1234 setLastError(ConnectivityManager.TETHER_ERROR_TETHER_IFACE_ERROR); 1235 1236 try { 1237 mNMService.untetherInterface(mIfaceName); 1238 } catch (Exception ee) { 1239 Log.e(TAG, "Error untethering after failure!" + ee.toString()); 1240 } 1241 transitionTo(mInitialState); 1242 return; 1243 } 1244 if (DBG) Log.d(TAG, "Tethered " + mIfaceName); 1245 setAvailable(false); 1246 setTethered(true); 1247 sendTetherStateChangedBroadcast(); 1248 } 1249 1250 private void cleanupUpstream() { 1251 if (mMyUpstreamIfaceName != null) { 1252 // note that we don't care about errors here. 1253 // sometimes interfaces are gone before we get 1254 // to remove their rules, which generates errors. 1255 // just do the best we can. 1256 try { 1257 // about to tear down NAT; gather remaining statistics 1258 mStatsService.forceUpdate(); 1259 } catch (Exception e) { 1260 if (VDBG) Log.e(TAG, "Exception in forceUpdate: " + e.toString()); 1261 } 1262 try { 1263 mNMService.stopInterfaceForwarding(mIfaceName, mMyUpstreamIfaceName); 1264 } catch (Exception e) { 1265 if (VDBG) Log.e( 1266 TAG, "Exception in removeInterfaceForward: " + e.toString()); 1267 } 1268 try { 1269 mNMService.disableNat(mIfaceName, mMyUpstreamIfaceName); 1270 } catch (Exception e) { 1271 if (VDBG) Log.e(TAG, "Exception in disableNat: " + e.toString()); 1272 } 1273 mMyUpstreamIfaceName = null; 1274 } 1275 return; 1276 } 1277 1278 @Override 1279 public boolean processMessage(Message message) { 1280 maybeLogMessage(this, message.what); 1281 boolean retValue = true; 1282 boolean error = false; 1283 switch (message.what) { 1284 case CMD_TETHER_UNREQUESTED: 1285 case CMD_INTERFACE_DOWN: 1286 cleanupUpstream(); 1287 try { 1288 mNMService.untetherInterface(mIfaceName); 1289 } catch (Exception e) { 1290 setLastErrorAndTransitionToInitialState( 1291 ConnectivityManager.TETHER_ERROR_UNTETHER_IFACE_ERROR); 1292 break; 1293 } 1294 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED, 1295 TetherInterfaceSM.this); 1296 if (message.what == CMD_TETHER_UNREQUESTED) { 1297 if (mUsb) { 1298 if (!Tethering.this.configureUsbIface(false)) { 1299 setLastError( 1300 ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR); 1301 } 1302 } 1303 transitionTo(mInitialState); 1304 } else if (message.what == CMD_INTERFACE_DOWN) { 1305 transitionTo(mUnavailableState); 1306 } 1307 if (DBG) Log.d(TAG, "Untethered " + mIfaceName); 1308 break; 1309 case CMD_TETHER_CONNECTION_CHANGED: 1310 String newUpstreamIfaceName = (String)(message.obj); 1311 if ((mMyUpstreamIfaceName == null && newUpstreamIfaceName == null) || 1312 (mMyUpstreamIfaceName != null && 1313 mMyUpstreamIfaceName.equals(newUpstreamIfaceName))) { 1314 if (VDBG) Log.d(TAG, "Connection changed noop - dropping"); 1315 break; 1316 } 1317 cleanupUpstream(); 1318 if (newUpstreamIfaceName != null) { 1319 try { 1320 mNMService.enableNat(mIfaceName, newUpstreamIfaceName); 1321 mNMService.startInterfaceForwarding(mIfaceName, 1322 newUpstreamIfaceName); 1323 } catch (Exception e) { 1324 Log.e(TAG, "Exception enabling Nat: " + e.toString()); 1325 try { 1326 mNMService.disableNat(mIfaceName, newUpstreamIfaceName); 1327 } catch (Exception ee) {} 1328 try { 1329 mNMService.untetherInterface(mIfaceName); 1330 } catch (Exception ee) {} 1331 1332 setLastError(ConnectivityManager.TETHER_ERROR_ENABLE_NAT_ERROR); 1333 transitionTo(mInitialState); 1334 return true; 1335 } 1336 } 1337 mMyUpstreamIfaceName = newUpstreamIfaceName; 1338 break; 1339 case CMD_CELL_DUN_ERROR: 1340 case CMD_IP_FORWARDING_ENABLE_ERROR: 1341 case CMD_IP_FORWARDING_DISABLE_ERROR: 1342 case CMD_START_TETHERING_ERROR: 1343 case CMD_STOP_TETHERING_ERROR: 1344 case CMD_SET_DNS_FORWARDERS_ERROR: 1345 error = true; 1346 // fall through 1347 case CMD_TETHER_MODE_DEAD: 1348 cleanupUpstream(); 1349 try { 1350 mNMService.untetherInterface(mIfaceName); 1351 } catch (Exception e) { 1352 setLastErrorAndTransitionToInitialState( 1353 ConnectivityManager.TETHER_ERROR_UNTETHER_IFACE_ERROR); 1354 break; 1355 } 1356 if (error) { 1357 setLastErrorAndTransitionToInitialState( 1358 ConnectivityManager.TETHER_ERROR_MASTER_ERROR); 1359 break; 1360 } 1361 if (DBG) Log.d(TAG, "Tether lost upstream connection " + mIfaceName); 1362 sendTetherStateChangedBroadcast(); 1363 if (mUsb) { 1364 if (!Tethering.this.configureUsbIface(false)) { 1365 setLastError(ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR); 1366 } 1367 } 1368 transitionTo(mInitialState); 1369 break; 1370 default: 1371 retValue = false; 1372 break; 1373 } 1374 return retValue; 1375 } 1376 } 1377 1378 class UnavailableState extends State { 1379 @Override 1380 public void enter() { 1381 setAvailable(false); 1382 setLastError(ConnectivityManager.TETHER_ERROR_NO_ERROR); 1383 setTethered(false); 1384 sendTetherStateChangedBroadcast(); 1385 } 1386 @Override 1387 public boolean processMessage(Message message) { 1388 boolean retValue = true; 1389 switch (message.what) { 1390 case CMD_INTERFACE_UP: 1391 transitionTo(mInitialState); 1392 break; 1393 default: 1394 retValue = false; 1395 break; 1396 } 1397 return retValue; 1398 } 1399 } 1400 1401 void setLastErrorAndTransitionToInitialState(int error) { 1402 setLastError(error); 1403 transitionTo(mInitialState); 1404 } 1405 1406 } 1407 1408 /** 1409 * A NetworkCallback class that relays information of interest to the 1410 * tethering master state machine thread for subsequent processing. 1411 */ 1412 class UpstreamNetworkCallback extends NetworkCallback { 1413 @Override 1414 public void onLinkPropertiesChanged(Network network, LinkProperties newLp) { 1415 mTetherMasterSM.sendMessage( 1416 TetherMasterSM.EVENT_UPSTREAM_LINKPROPERTIES_CHANGED, 1417 new NetworkState(null, newLp, null, network, null, null)); 1418 } 1419 1420 @Override 1421 public void onLost(Network network) { 1422 mTetherMasterSM.sendMessage(TetherMasterSM.EVENT_UPSTREAM_LOST, network); 1423 } 1424 } 1425 1426 /** 1427 * A class to centralize all the network and link properties information 1428 * pertaining to the current and any potential upstream network. 1429 * 1430 * Calling #start() registers two callbacks: one to track the system default 1431 * network and a second to specifically observe TYPE_MOBILE_DUN networks. 1432 * 1433 * The methods and data members of this class are only to be accessed and 1434 * modified from the tethering master state machine thread. Any other 1435 * access semantics would necessitate the addition of locking. 1436 * 1437 * TODO: Investigate whether more "upstream-specific" logic/functionality 1438 * could/should be moved here. 1439 */ 1440 class UpstreamNetworkMonitor { 1441 final HashMap<Network, NetworkState> mNetworkMap = new HashMap(); 1442 NetworkCallback mDefaultNetworkCallback; 1443 NetworkCallback mDunTetheringCallback; 1444 1445 void start() { 1446 stop(); 1447 1448 mDefaultNetworkCallback = new UpstreamNetworkCallback(); 1449 getConnectivityManager().registerDefaultNetworkCallback(mDefaultNetworkCallback); 1450 1451 final NetworkRequest dunTetheringRequest = new NetworkRequest.Builder() 1452 .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR) 1453 .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED) 1454 .addCapability(NetworkCapabilities.NET_CAPABILITY_DUN) 1455 .build(); 1456 mDunTetheringCallback = new UpstreamNetworkCallback(); 1457 getConnectivityManager().registerNetworkCallback( 1458 dunTetheringRequest, mDunTetheringCallback); 1459 } 1460 1461 void stop() { 1462 if (mDefaultNetworkCallback != null) { 1463 getConnectivityManager().unregisterNetworkCallback(mDefaultNetworkCallback); 1464 mDefaultNetworkCallback = null; 1465 } 1466 1467 if (mDunTetheringCallback != null) { 1468 getConnectivityManager().unregisterNetworkCallback(mDunTetheringCallback); 1469 mDunTetheringCallback = null; 1470 } 1471 1472 mNetworkMap.clear(); 1473 } 1474 1475 // Returns true if these updated LinkProperties pertain to the current 1476 // upstream network interface, false otherwise (or if there is not 1477 // currently any upstream tethering interface). 1478 boolean processLinkPropertiesChanged(NetworkState networkState) { 1479 if (networkState == null || 1480 networkState.network == null || 1481 networkState.linkProperties == null) { 1482 return false; 1483 } 1484 1485 mNetworkMap.put(networkState.network, networkState); 1486 1487 if (mCurrentUpstreamIface != null) { 1488 for (String ifname : networkState.linkProperties.getAllInterfaceNames()) { 1489 if (mCurrentUpstreamIface.equals(ifname)) { 1490 return true; 1491 } 1492 } 1493 } 1494 return false; 1495 } 1496 1497 void processNetworkLost(Network network) { 1498 if (network != null) { 1499 mNetworkMap.remove(network); 1500 } 1501 } 1502 } 1503 1504 class TetherMasterSM extends StateMachine { 1505 private static final int BASE_MASTER = Protocol.BASE_TETHERING; 1506 // an interface SM has requested Tethering 1507 static final int CMD_TETHER_MODE_REQUESTED = BASE_MASTER + 1; 1508 // an interface SM has unrequested Tethering 1509 static final int CMD_TETHER_MODE_UNREQUESTED = BASE_MASTER + 2; 1510 // upstream connection change - do the right thing 1511 static final int CMD_UPSTREAM_CHANGED = BASE_MASTER + 3; 1512 // we don't have a valid upstream conn, check again after a delay 1513 static final int CMD_RETRY_UPSTREAM = BASE_MASTER + 4; 1514 // Events from NetworkCallbacks that we process on the master state 1515 // machine thread on behalf of the UpstreamNetworkMonitor. 1516 static final int EVENT_UPSTREAM_LINKPROPERTIES_CHANGED = BASE_MASTER + 5; 1517 static final int EVENT_UPSTREAM_LOST = BASE_MASTER + 6; 1518 1519 // This indicates what a timeout event relates to. A state that 1520 // sends itself a delayed timeout event and handles incoming timeout events 1521 // should inc this when it is entered and whenever it sends a new timeout event. 1522 // We do not flush the old ones. 1523 private int mSequenceNumber; 1524 1525 private State mInitialState; 1526 private State mTetherModeAliveState; 1527 1528 private State mSetIpForwardingEnabledErrorState; 1529 private State mSetIpForwardingDisabledErrorState; 1530 private State mStartTetheringErrorState; 1531 private State mStopTetheringErrorState; 1532 private State mSetDnsForwardersErrorState; 1533 1534 private ArrayList<TetherInterfaceSM> mNotifyList; 1535 1536 private int mMobileApnReserved = ConnectivityManager.TYPE_NONE; 1537 private NetworkCallback mMobileUpstreamCallback; 1538 1539 private static final int UPSTREAM_SETTLE_TIME_MS = 10000; 1540 1541 TetherMasterSM(String name, Looper looper) { 1542 super(name, looper); 1543 1544 //Add states 1545 mInitialState = new InitialState(); 1546 addState(mInitialState); 1547 mTetherModeAliveState = new TetherModeAliveState(); 1548 addState(mTetherModeAliveState); 1549 1550 mSetIpForwardingEnabledErrorState = new SetIpForwardingEnabledErrorState(); 1551 addState(mSetIpForwardingEnabledErrorState); 1552 mSetIpForwardingDisabledErrorState = new SetIpForwardingDisabledErrorState(); 1553 addState(mSetIpForwardingDisabledErrorState); 1554 mStartTetheringErrorState = new StartTetheringErrorState(); 1555 addState(mStartTetheringErrorState); 1556 mStopTetheringErrorState = new StopTetheringErrorState(); 1557 addState(mStopTetheringErrorState); 1558 mSetDnsForwardersErrorState = new SetDnsForwardersErrorState(); 1559 addState(mSetDnsForwardersErrorState); 1560 1561 mNotifyList = new ArrayList<TetherInterfaceSM>(); 1562 setInitialState(mInitialState); 1563 } 1564 1565 class TetherMasterUtilState extends State { 1566 @Override 1567 public boolean processMessage(Message m) { 1568 return false; 1569 } 1570 1571 protected boolean turnOnUpstreamMobileConnection(int apnType) { 1572 if (apnType == ConnectivityManager.TYPE_NONE) { return false; } 1573 1574 if (apnType != mMobileApnReserved) { 1575 // Unregister any previous mobile upstream callback because 1576 // this request, if any, will be different. 1577 turnOffUpstreamMobileConnection(); 1578 } 1579 1580 if (mMobileUpstreamCallback != null) { 1581 // Looks like we already filed a request for this apnType. 1582 return true; 1583 } 1584 1585 switch (apnType) { 1586 case ConnectivityManager.TYPE_MOBILE_DUN: 1587 case ConnectivityManager.TYPE_MOBILE: 1588 case ConnectivityManager.TYPE_MOBILE_HIPRI: 1589 mMobileApnReserved = apnType; 1590 break; 1591 default: 1592 return false; 1593 } 1594 1595 final NetworkRequest.Builder builder = new NetworkRequest.Builder() 1596 .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR); 1597 if (apnType == ConnectivityManager.TYPE_MOBILE_DUN) { 1598 builder.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED) 1599 .addCapability(NetworkCapabilities.NET_CAPABILITY_DUN); 1600 } else { 1601 builder.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); 1602 } 1603 final NetworkRequest mobileUpstreamRequest = builder.build(); 1604 1605 // The UpstreamNetworkMonitor's callback will be notified. 1606 // Therefore, to avoid duplicate notifications, we only register a no-op. 1607 mMobileUpstreamCallback = new NetworkCallback(); 1608 1609 // TODO: Change the timeout from 0 (no onUnavailable callback) to use some 1610 // moderate callback time (once timeout callbacks are implemented). This might 1611 // be useful for updating some UI. Additionally, we should definitely log a 1612 // message to aid in any subsequent debugging 1613 if (DBG) Log.d(TAG, "requesting mobile upstream network: " + mobileUpstreamRequest); 1614 getConnectivityManager().requestNetwork( 1615 mobileUpstreamRequest, mMobileUpstreamCallback, 0, apnType); 1616 return true; 1617 } 1618 1619 protected void turnOffUpstreamMobileConnection() { 1620 if (mMobileUpstreamCallback != null) { 1621 getConnectivityManager().unregisterNetworkCallback(mMobileUpstreamCallback); 1622 mMobileUpstreamCallback = null; 1623 } 1624 mMobileApnReserved = ConnectivityManager.TYPE_NONE; 1625 } 1626 1627 protected boolean turnOnMasterTetherSettings() { 1628 try { 1629 mNMService.setIpForwardingEnabled(true); 1630 } catch (Exception e) { 1631 transitionTo(mSetIpForwardingEnabledErrorState); 1632 return false; 1633 } 1634 try { 1635 mNMService.startTethering(mDhcpRange); 1636 } catch (Exception e) { 1637 try { 1638 mNMService.stopTethering(); 1639 mNMService.startTethering(mDhcpRange); 1640 } catch (Exception ee) { 1641 transitionTo(mStartTetheringErrorState); 1642 return false; 1643 } 1644 } 1645 return true; 1646 } 1647 1648 protected boolean turnOffMasterTetherSettings() { 1649 try { 1650 mNMService.stopTethering(); 1651 } catch (Exception e) { 1652 transitionTo(mStopTetheringErrorState); 1653 return false; 1654 } 1655 try { 1656 mNMService.setIpForwardingEnabled(false); 1657 } catch (Exception e) { 1658 transitionTo(mSetIpForwardingDisabledErrorState); 1659 return false; 1660 } 1661 transitionTo(mInitialState); 1662 return true; 1663 } 1664 1665 protected void chooseUpstreamType(boolean tryCell) { 1666 int upType = ConnectivityManager.TYPE_NONE; 1667 String iface = null; 1668 1669 updateConfiguration(); // TODO - remove? 1670 1671 synchronized (mPublicSync) { 1672 if (VDBG) { 1673 Log.d(TAG, "chooseUpstreamType has upstream iface types:"); 1674 for (Integer netType : mUpstreamIfaceTypes) { 1675 Log.d(TAG, " " + netType); 1676 } 1677 } 1678 1679 for (Integer netType : mUpstreamIfaceTypes) { 1680 NetworkInfo info = 1681 getConnectivityManager().getNetworkInfo(netType.intValue()); 1682 if ((info != null) && info.isConnected()) { 1683 upType = netType.intValue(); 1684 break; 1685 } 1686 } 1687 } 1688 1689 if (DBG) { 1690 Log.d(TAG, "chooseUpstreamType(" + tryCell + ")," 1691 + " preferredApn=" 1692 + ConnectivityManager.getNetworkTypeName(mPreferredUpstreamMobileApn) 1693 + ", got type=" 1694 + ConnectivityManager.getNetworkTypeName(upType)); 1695 } 1696 1697 switch (upType) { 1698 case ConnectivityManager.TYPE_MOBILE_DUN: 1699 case ConnectivityManager.TYPE_MOBILE_HIPRI: 1700 // If we're on DUN, put our own grab on it. 1701 turnOnUpstreamMobileConnection(upType); 1702 break; 1703 case ConnectivityManager.TYPE_NONE: 1704 if (tryCell && 1705 turnOnUpstreamMobileConnection(mPreferredUpstreamMobileApn)) { 1706 // We think mobile should be coming up; don't set a retry. 1707 } else { 1708 sendMessageDelayed(CMD_RETRY_UPSTREAM, UPSTREAM_SETTLE_TIME_MS); 1709 } 1710 break; 1711 default: 1712 /* If we've found an active upstream connection that's not DUN/HIPRI 1713 * we should stop any outstanding DUN/HIPRI start requests. 1714 * 1715 * If we found NONE we don't want to do this as we want any previous 1716 * requests to keep trying to bring up something we can use. 1717 */ 1718 turnOffUpstreamMobileConnection(); 1719 break; 1720 } 1721 1722 if (upType != ConnectivityManager.TYPE_NONE) { 1723 LinkProperties linkProperties = 1724 getConnectivityManager().getLinkProperties(upType); 1725 if (linkProperties != null) { 1726 // Find the interface with the default IPv4 route. It may be the 1727 // interface described by linkProperties, or one of the interfaces 1728 // stacked on top of it. 1729 Log.i(TAG, "Finding IPv4 upstream interface on: " + linkProperties); 1730 RouteInfo ipv4Default = RouteInfo.selectBestRoute( 1731 linkProperties.getAllRoutes(), Inet4Address.ANY); 1732 if (ipv4Default != null) { 1733 iface = ipv4Default.getInterface(); 1734 Log.i(TAG, "Found interface " + ipv4Default.getInterface()); 1735 } else { 1736 Log.i(TAG, "No IPv4 upstream interface, giving up."); 1737 } 1738 } 1739 1740 if (iface != null) { 1741 Network network = getConnectivityManager().getNetworkForType(upType); 1742 if (network == null) { 1743 Log.e(TAG, "No Network for upstream type " + upType + "!"); 1744 } 1745 setDnsForwarders(network, linkProperties); 1746 } 1747 } 1748 notifyTetheredOfNewUpstreamIface(iface); 1749 } 1750 1751 protected void setDnsForwarders(final Network network, final LinkProperties lp) { 1752 String[] dnsServers = mDefaultDnsServers; 1753 final Collection<InetAddress> dnses = lp.getDnsServers(); 1754 // TODO: Properly support the absence of DNS servers. 1755 if (dnses != null && !dnses.isEmpty()) { 1756 // TODO: remove this invocation of NetworkUtils.makeStrings(). 1757 dnsServers = NetworkUtils.makeStrings(dnses); 1758 } 1759 if (VDBG) { 1760 Log.d(TAG, "Setting DNS forwarders: Network=" + network + 1761 ", dnsServers=" + Arrays.toString(dnsServers)); 1762 } 1763 try { 1764 mNMService.setDnsForwarders(network, dnsServers); 1765 } catch (Exception e) { 1766 // TODO: Investigate how this can fail and what exactly 1767 // happens if/when such failures occur. 1768 Log.e(TAG, "Setting DNS forwarders failed!"); 1769 transitionTo(mSetDnsForwardersErrorState); 1770 } 1771 } 1772 1773 protected void notifyTetheredOfNewUpstreamIface(String ifaceName) { 1774 if (DBG) Log.d(TAG, "Notifying tethered with upstream=" + ifaceName); 1775 mCurrentUpstreamIface = ifaceName; 1776 for (TetherInterfaceSM sm : mNotifyList) { 1777 sm.sendMessage(TetherInterfaceSM.CMD_TETHER_CONNECTION_CHANGED, 1778 ifaceName); 1779 } 1780 } 1781 } 1782 1783 private final AtomicInteger mSimBcastGenerationNumber = new AtomicInteger(0); 1784 private SimChangeBroadcastReceiver mBroadcastReceiver = null; 1785 1786 private void startListeningForSimChanges() { 1787 if (DBG) Log.d(TAG, "startListeningForSimChanges"); 1788 if (mBroadcastReceiver == null) { 1789 mBroadcastReceiver = new SimChangeBroadcastReceiver( 1790 mSimBcastGenerationNumber.incrementAndGet()); 1791 final IntentFilter filter = new IntentFilter(); 1792 filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED); 1793 1794 mContext.registerReceiver(mBroadcastReceiver, filter); 1795 } 1796 } 1797 1798 private void stopListeningForSimChanges() { 1799 if (DBG) Log.d(TAG, "stopListeningForSimChanges"); 1800 if (mBroadcastReceiver != null) { 1801 mSimBcastGenerationNumber.incrementAndGet(); 1802 mContext.unregisterReceiver(mBroadcastReceiver); 1803 mBroadcastReceiver = null; 1804 } 1805 } 1806 1807 class SimChangeBroadcastReceiver extends BroadcastReceiver { 1808 // used to verify this receiver is still current 1809 final private int mGenerationNumber; 1810 1811 // we're interested in edge-triggered LOADED notifications, so 1812 // ignore LOADED unless we saw an ABSENT state first 1813 private boolean mSimAbsentSeen = false; 1814 1815 public SimChangeBroadcastReceiver(int generationNumber) { 1816 super(); 1817 mGenerationNumber = generationNumber; 1818 } 1819 1820 @Override 1821 public void onReceive(Context context, Intent intent) { 1822 if (DBG) { 1823 Log.d(TAG, "simchange mGenerationNumber=" + mGenerationNumber + 1824 ", current generationNumber=" + mSimBcastGenerationNumber.get()); 1825 } 1826 if (mGenerationNumber != mSimBcastGenerationNumber.get()) return; 1827 1828 final String state = 1829 intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE); 1830 1831 Log.d(TAG, "got Sim changed to state " + state + ", mSimAbsentSeen=" + 1832 mSimAbsentSeen); 1833 if (!mSimAbsentSeen && IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(state)) { 1834 mSimAbsentSeen = true; 1835 } 1836 1837 if (mSimAbsentSeen && IccCardConstants.INTENT_VALUE_ICC_LOADED.equals(state)) { 1838 mSimAbsentSeen = false; 1839 try { 1840 if (mContext.getResources().getString(com.android.internal.R.string. 1841 config_mobile_hotspot_provision_app_no_ui).isEmpty() == false) { 1842 ArrayList<Integer> tethered = new ArrayList<Integer>(); 1843 synchronized (mPublicSync) { 1844 Set ifaces = mIfaces.keySet(); 1845 for (Object iface : ifaces) { 1846 TetherInterfaceSM sm = mIfaces.get(iface); 1847 if (sm != null && sm.isTethered()) { 1848 if (isUsb((String)iface)) { 1849 tethered.add(new Integer( 1850 ConnectivityManager.TETHERING_USB)); 1851 } else if (isWifi((String)iface)) { 1852 tethered.add(new Integer( 1853 ConnectivityManager.TETHERING_WIFI)); 1854 } else if (isBluetooth((String)iface)) { 1855 tethered.add(new Integer( 1856 ConnectivityManager.TETHERING_BLUETOOTH)); 1857 } 1858 } 1859 } 1860 } 1861 for (int tetherType : tethered) { 1862 Intent startProvIntent = new Intent(); 1863 startProvIntent.putExtra( 1864 ConnectivityManager.EXTRA_ADD_TETHER_TYPE, tetherType); 1865 startProvIntent.putExtra( 1866 ConnectivityManager.EXTRA_RUN_PROVISION, true); 1867 startProvIntent.setComponent(TETHER_SERVICE); 1868 mContext.startServiceAsUser(startProvIntent, UserHandle.CURRENT); 1869 } 1870 Log.d(TAG, "re-evaluate provisioning"); 1871 } else { 1872 Log.d(TAG, "no prov-check needed for new SIM"); 1873 } 1874 } catch (Resources.NotFoundException e) { 1875 Log.d(TAG, "no prov-check needed for new SIM"); 1876 // not defined, do nothing 1877 } 1878 } 1879 } 1880 } 1881 1882 class InitialState extends TetherMasterUtilState { 1883 @Override 1884 public void enter() { 1885 } 1886 @Override 1887 public boolean processMessage(Message message) { 1888 maybeLogMessage(this, message.what); 1889 boolean retValue = true; 1890 switch (message.what) { 1891 case CMD_TETHER_MODE_REQUESTED: 1892 TetherInterfaceSM who = (TetherInterfaceSM)message.obj; 1893 if (VDBG) Log.d(TAG, "Tether Mode requested by " + who); 1894 mNotifyList.add(who); 1895 transitionTo(mTetherModeAliveState); 1896 break; 1897 case CMD_TETHER_MODE_UNREQUESTED: 1898 who = (TetherInterfaceSM)message.obj; 1899 if (VDBG) Log.d(TAG, "Tether Mode unrequested by " + who); 1900 int index = mNotifyList.indexOf(who); 1901 if (index != -1) { 1902 mNotifyList.remove(who); 1903 } 1904 break; 1905 default: 1906 retValue = false; 1907 break; 1908 } 1909 return retValue; 1910 } 1911 } 1912 1913 class TetherModeAliveState extends TetherMasterUtilState { 1914 boolean mTryCell = true; 1915 @Override 1916 public void enter() { 1917 // TODO: examine if we should check the return value. 1918 turnOnMasterTetherSettings(); // may transition us out 1919 startListeningForSimChanges(); 1920 mUpstreamNetworkMonitor.start(); 1921 1922 mTryCell = true; // better try something first pass or crazy tests cases will fail 1923 chooseUpstreamType(mTryCell); 1924 mTryCell = !mTryCell; 1925 } 1926 @Override 1927 public void exit() { 1928 // TODO: examine if we should check the return value. 1929 turnOffUpstreamMobileConnection(); 1930 mUpstreamNetworkMonitor.stop(); 1931 stopListeningForSimChanges(); 1932 notifyTetheredOfNewUpstreamIface(null); 1933 } 1934 @Override 1935 public boolean processMessage(Message message) { 1936 maybeLogMessage(this, message.what); 1937 boolean retValue = true; 1938 switch (message.what) { 1939 case CMD_TETHER_MODE_REQUESTED: 1940 TetherInterfaceSM who = (TetherInterfaceSM)message.obj; 1941 if (VDBG) Log.d(TAG, "Tether Mode requested by " + who); 1942 mNotifyList.add(who); 1943 who.sendMessage(TetherInterfaceSM.CMD_TETHER_CONNECTION_CHANGED, 1944 mCurrentUpstreamIface); 1945 break; 1946 case CMD_TETHER_MODE_UNREQUESTED: 1947 who = (TetherInterfaceSM)message.obj; 1948 if (VDBG) Log.d(TAG, "Tether Mode unrequested by " + who); 1949 int index = mNotifyList.indexOf(who); 1950 if (index != -1) { 1951 if (DBG) Log.d(TAG, "TetherModeAlive removing notifyee " + who); 1952 mNotifyList.remove(index); 1953 if (mNotifyList.isEmpty()) { 1954 turnOffMasterTetherSettings(); // transitions appropriately 1955 } else { 1956 if (DBG) { 1957 Log.d(TAG, "TetherModeAlive still has " + mNotifyList.size() + 1958 " live requests:"); 1959 for (Object o : mNotifyList) Log.d(TAG, " " + o); 1960 } 1961 } 1962 } else { 1963 Log.e(TAG, "TetherModeAliveState UNREQUESTED has unknown who: " + who); 1964 } 1965 break; 1966 case CMD_UPSTREAM_CHANGED: 1967 // need to try DUN immediately if Wifi goes down 1968 mTryCell = true; 1969 chooseUpstreamType(mTryCell); 1970 mTryCell = !mTryCell; 1971 break; 1972 case CMD_RETRY_UPSTREAM: 1973 chooseUpstreamType(mTryCell); 1974 mTryCell = !mTryCell; 1975 break; 1976 case EVENT_UPSTREAM_LINKPROPERTIES_CHANGED: 1977 NetworkState state = (NetworkState) message.obj; 1978 if (mUpstreamNetworkMonitor.processLinkPropertiesChanged(state)) { 1979 setDnsForwarders(state.network, state.linkProperties); 1980 } else if (mCurrentUpstreamIface == null) { 1981 // If we have no upstream interface, try to run through upstream 1982 // selection again. If, for example, IPv4 connectivity has shown up 1983 // after IPv6 (e.g., 464xlat became available) we want the chance to 1984 // notice and act accordingly. 1985 chooseUpstreamType(false); 1986 } 1987 break; 1988 case EVENT_UPSTREAM_LOST: 1989 // TODO: Re-evaluate possible upstreams. Currently upstream reevaluation 1990 // is triggered via received CONNECTIVITY_ACTION broadcasts that result 1991 // in being passed a TetherMasterSM.CMD_UPSTREAM_CHANGED. 1992 mUpstreamNetworkMonitor.processNetworkLost((Network) message.obj); 1993 break; 1994 default: 1995 retValue = false; 1996 break; 1997 } 1998 return retValue; 1999 } 2000 } 2001 2002 class ErrorState extends State { 2003 int mErrorNotification; 2004 @Override 2005 public boolean processMessage(Message message) { 2006 boolean retValue = true; 2007 switch (message.what) { 2008 case CMD_TETHER_MODE_REQUESTED: 2009 TetherInterfaceSM who = (TetherInterfaceSM)message.obj; 2010 who.sendMessage(mErrorNotification); 2011 break; 2012 default: 2013 retValue = false; 2014 } 2015 return retValue; 2016 } 2017 void notify(int msgType) { 2018 mErrorNotification = msgType; 2019 for (Object o : mNotifyList) { 2020 TetherInterfaceSM sm = (TetherInterfaceSM)o; 2021 sm.sendMessage(msgType); 2022 } 2023 } 2024 2025 } 2026 class SetIpForwardingEnabledErrorState extends ErrorState { 2027 @Override 2028 public void enter() { 2029 Log.e(TAG, "Error in setIpForwardingEnabled"); 2030 notify(TetherInterfaceSM.CMD_IP_FORWARDING_ENABLE_ERROR); 2031 } 2032 } 2033 2034 class SetIpForwardingDisabledErrorState extends ErrorState { 2035 @Override 2036 public void enter() { 2037 Log.e(TAG, "Error in setIpForwardingDisabled"); 2038 notify(TetherInterfaceSM.CMD_IP_FORWARDING_DISABLE_ERROR); 2039 } 2040 } 2041 2042 class StartTetheringErrorState extends ErrorState { 2043 @Override 2044 public void enter() { 2045 Log.e(TAG, "Error in startTethering"); 2046 notify(TetherInterfaceSM.CMD_START_TETHERING_ERROR); 2047 try { 2048 mNMService.setIpForwardingEnabled(false); 2049 } catch (Exception e) {} 2050 } 2051 } 2052 2053 class StopTetheringErrorState extends ErrorState { 2054 @Override 2055 public void enter() { 2056 Log.e(TAG, "Error in stopTethering"); 2057 notify(TetherInterfaceSM.CMD_STOP_TETHERING_ERROR); 2058 try { 2059 mNMService.setIpForwardingEnabled(false); 2060 } catch (Exception e) {} 2061 } 2062 } 2063 2064 class SetDnsForwardersErrorState extends ErrorState { 2065 @Override 2066 public void enter() { 2067 Log.e(TAG, "Error in setDnsForwarders"); 2068 notify(TetherInterfaceSM.CMD_SET_DNS_FORWARDERS_ERROR); 2069 try { 2070 mNMService.stopTethering(); 2071 } catch (Exception e) {} 2072 try { 2073 mNMService.setIpForwardingEnabled(false); 2074 } catch (Exception e) {} 2075 } 2076 } 2077 } 2078 2079 public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { 2080 final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " "); 2081 2082 if (mContext.checkCallingOrSelfPermission( 2083 android.Manifest.permission.DUMP) != PackageManager.PERMISSION_GRANTED) { 2084 pw.println("Permission Denial: can't dump ConnectivityService.Tether " + 2085 "from from pid=" + Binder.getCallingPid() + ", uid=" + 2086 Binder.getCallingUid()); 2087 return; 2088 } 2089 2090 pw.println("Tethering:"); 2091 pw.increaseIndent(); 2092 pw.print("mUpstreamIfaceTypes:"); 2093 synchronized (mPublicSync) { 2094 for (Integer netType : mUpstreamIfaceTypes) { 2095 pw.print(" " + ConnectivityManager.getNetworkTypeName(netType)); 2096 } 2097 pw.println(); 2098 2099 pw.println("Tether state:"); 2100 pw.increaseIndent(); 2101 for (Object o : mIfaces.values()) { 2102 pw.println(o); 2103 } 2104 pw.decreaseIndent(); 2105 } 2106 pw.decreaseIndent(); 2107 return; 2108 } 2109} 2110