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