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