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