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