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.content.BroadcastReceiver; 23 import android.content.ComponentName; 24 import android.content.Context; 25 import android.content.Intent; 26 import android.content.IntentFilter; 27 import android.content.pm.PackageManager; 28 import android.content.res.Resources; 29 import android.hardware.usb.UsbManager; 30 import android.net.ConnectivityManager; 31 import android.net.INetworkStatsService; 32 import android.net.InterfaceConfiguration; 33 import android.net.LinkAddress; 34 import android.net.LinkProperties; 35 import android.net.Network; 36 import android.net.NetworkInfo; 37 import android.net.NetworkUtils; 38 import android.net.RouteInfo; 39 import android.os.Binder; 40 import android.os.INetworkManagementService; 41 import android.os.Looper; 42 import android.os.Message; 43 import android.os.UserHandle; 44 import android.telephony.TelephonyManager; 45 import android.util.Log; 46 47 import com.android.internal.telephony.IccCardConstants; 48 import com.android.internal.telephony.Phone; 49 import com.android.internal.telephony.PhoneConstants; 50 import com.android.internal.telephony.TelephonyIntents; 51 import com.android.internal.util.IndentingPrintWriter; 52 import com.android.internal.util.IState; 53 import com.android.internal.util.State; 54 import com.android.internal.util.StateMachine; 55 import com.android.server.IoThread; 56 import com.android.server.net.BaseNetworkObserver; 57 58 import java.io.FileDescriptor; 59 import java.io.PrintWriter; 60 import java.net.InetAddress; 61 import java.net.Inet4Address; 62 import java.util.ArrayList; 63 import java.util.Arrays; 64 import java.util.Collection; 65 import java.util.HashMap; 66 import java.util.Iterator; 67 import java.util.Set; 68 import java.util.concurrent.atomic.AtomicInteger; 69 70 71 /** 72 * @hide 73 * 74 * Timeout 75 * 76 * TODO - look for parent classes and code sharing 77 */ 78 public class Tethering extends BaseNetworkObserver { 79 80 private Context mContext; 81 private final static String TAG = "Tethering"; 82 private final static boolean DBG = true; 83 private final static boolean VDBG = false; 84 85 // TODO - remove both of these - should be part of interface inspection/selection stuff 86 private String[] mTetherableUsbRegexs; 87 private String[] mTetherableWifiRegexs; 88 private String[] mTetherableBluetoothRegexs; 89 private Collection<Integer> mUpstreamIfaceTypes; 90 91 // used to synchronize public access to members 92 private Object mPublicSync; 93 94 private static final Integer MOBILE_TYPE = new Integer(ConnectivityManager.TYPE_MOBILE); 95 private static final Integer HIPRI_TYPE = new Integer(ConnectivityManager.TYPE_MOBILE_HIPRI); 96 private static final Integer DUN_TYPE = new Integer(ConnectivityManager.TYPE_MOBILE_DUN); 97 98 // if we have to connect to mobile, what APN type should we use? Calculated by examining the 99 // upstream type list and the DUN_REQUIRED secure-setting 100 private int mPreferredUpstreamMobileApn = ConnectivityManager.TYPE_NONE; 101 102 private final INetworkManagementService mNMService; 103 private final INetworkStatsService mStatsService; 104 private Looper mLooper; 105 106 private HashMap<String, TetherInterfaceSM> mIfaces; // all tethered/tetherable ifaces 107 108 private BroadcastReceiver mStateReceiver; 109 110 private static final String USB_NEAR_IFACE_ADDR = "192.168.42.129"; 111 private static final int USB_PREFIX_LENGTH = 24; 112 113 // USB is 192.168.42.1 and 255.255.255.0 114 // Wifi is 192.168.43.1 and 255.255.255.0 115 // BT is limited to max default of 5 connections. 192.168.44.1 to 192.168.48.1 116 // with 255.255.255.0 117 // P2P is 192.168.49.1 and 255.255.255.0 118 119 private String[] mDhcpRange; 120 private static final String[] DHCP_DEFAULT_RANGE = { 121 "192.168.42.2", "192.168.42.254", "192.168.43.2", "192.168.43.254", 122 "192.168.44.2", "192.168.44.254", "192.168.45.2", "192.168.45.254", 123 "192.168.46.2", "192.168.46.254", "192.168.47.2", "192.168.47.254", 124 "192.168.48.2", "192.168.48.254", "192.168.49.2", "192.168.49.254", 125 }; 126 127 private String[] mDefaultDnsServers; 128 private static final String DNS_DEFAULT_SERVER1 = "8.8.8.8"; 129 private static final String DNS_DEFAULT_SERVER2 = "8.8.4.4"; 130 131 private StateMachine mTetherMasterSM; 132 133 private Notification.Builder mTetheredNotificationBuilder; 134 private int mLastNotificationId; 135 136 private boolean mRndisEnabled; // track the RNDIS function enabled state 137 private boolean mUsbTetherRequested; // true if USB tethering should be started 138 // when RNDIS is enabled 139 Tethering(Context context, INetworkManagementService nmService, INetworkStatsService statsService, Looper looper)140 public Tethering(Context context, INetworkManagementService nmService, 141 INetworkStatsService statsService, Looper looper) { 142 mContext = context; 143 mNMService = nmService; 144 mStatsService = statsService; 145 mLooper = looper; 146 147 mPublicSync = new Object(); 148 149 mIfaces = new HashMap<String, TetherInterfaceSM>(); 150 151 // make our own thread so we don't anr the system 152 mLooper = IoThread.get().getLooper(); 153 mTetherMasterSM = new TetherMasterSM("TetherMaster", mLooper); 154 mTetherMasterSM.start(); 155 156 mStateReceiver = new StateReceiver(); 157 IntentFilter filter = new IntentFilter(); 158 filter.addAction(UsbManager.ACTION_USB_STATE); 159 filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); 160 filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED); 161 mContext.registerReceiver(mStateReceiver, filter); 162 163 filter = new IntentFilter(); 164 filter.addAction(Intent.ACTION_MEDIA_SHARED); 165 filter.addAction(Intent.ACTION_MEDIA_UNSHARED); 166 filter.addDataScheme("file"); 167 mContext.registerReceiver(mStateReceiver, filter); 168 169 mDhcpRange = context.getResources().getStringArray( 170 com.android.internal.R.array.config_tether_dhcp_range); 171 if ((mDhcpRange.length == 0) || (mDhcpRange.length % 2 ==1)) { 172 mDhcpRange = DHCP_DEFAULT_RANGE; 173 } 174 175 // load device config info 176 updateConfiguration(); 177 178 // TODO - remove and rely on real notifications of the current iface 179 mDefaultDnsServers = new String[2]; 180 mDefaultDnsServers[0] = DNS_DEFAULT_SERVER1; 181 mDefaultDnsServers[1] = DNS_DEFAULT_SERVER2; 182 } 183 184 // We can't do this once in the Tethering() constructor and cache the value, because the 185 // CONNECTIVITY_SERVICE is registered only after the Tethering() constructor has completed. getConnectivityManager()186 private ConnectivityManager getConnectivityManager() { 187 return (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE); 188 } 189 updateConfiguration()190 void updateConfiguration() { 191 String[] tetherableUsbRegexs = mContext.getResources().getStringArray( 192 com.android.internal.R.array.config_tether_usb_regexs); 193 String[] tetherableWifiRegexs = mContext.getResources().getStringArray( 194 com.android.internal.R.array.config_tether_wifi_regexs); 195 String[] tetherableBluetoothRegexs = mContext.getResources().getStringArray( 196 com.android.internal.R.array.config_tether_bluetooth_regexs); 197 198 int ifaceTypes[] = mContext.getResources().getIntArray( 199 com.android.internal.R.array.config_tether_upstream_types); 200 Collection<Integer> upstreamIfaceTypes = new ArrayList(); 201 for (int i : ifaceTypes) { 202 upstreamIfaceTypes.add(new Integer(i)); 203 } 204 205 synchronized (mPublicSync) { 206 mTetherableUsbRegexs = tetherableUsbRegexs; 207 mTetherableWifiRegexs = tetherableWifiRegexs; 208 mTetherableBluetoothRegexs = tetherableBluetoothRegexs; 209 mUpstreamIfaceTypes = upstreamIfaceTypes; 210 } 211 212 // check if the upstream type list needs to be modified due to secure-settings 213 checkDunRequired(); 214 } 215 interfaceStatusChanged(String iface, boolean up)216 public void interfaceStatusChanged(String iface, boolean up) { 217 if (VDBG) Log.d(TAG, "interfaceStatusChanged " + iface + ", " + up); 218 boolean found = false; 219 boolean usb = false; 220 synchronized (mPublicSync) { 221 if (isWifi(iface)) { 222 found = true; 223 } else if (isUsb(iface)) { 224 found = true; 225 usb = true; 226 } else if (isBluetooth(iface)) { 227 found = true; 228 } 229 if (found == false) return; 230 231 TetherInterfaceSM sm = mIfaces.get(iface); 232 if (up) { 233 if (sm == null) { 234 sm = new TetherInterfaceSM(iface, mLooper, usb); 235 mIfaces.put(iface, sm); 236 sm.start(); 237 } 238 } else { 239 if (isUsb(iface)) { 240 // ignore usb0 down after enabling RNDIS 241 // we will handle disconnect in interfaceRemoved instead 242 if (VDBG) Log.d(TAG, "ignore interface down for " + iface); 243 } else if (sm != null) { 244 sm.sendMessage(TetherInterfaceSM.CMD_INTERFACE_DOWN); 245 mIfaces.remove(iface); 246 } 247 } 248 } 249 } 250 interfaceLinkStateChanged(String iface, boolean up)251 public void interfaceLinkStateChanged(String iface, boolean up) { 252 if (VDBG) Log.d(TAG, "interfaceLinkStateChanged " + iface + ", " + up); 253 interfaceStatusChanged(iface, up); 254 } 255 isUsb(String iface)256 private boolean isUsb(String iface) { 257 synchronized (mPublicSync) { 258 for (String regex : mTetherableUsbRegexs) { 259 if (iface.matches(regex)) return true; 260 } 261 return false; 262 } 263 } 264 isWifi(String iface)265 public boolean isWifi(String iface) { 266 synchronized (mPublicSync) { 267 for (String regex : mTetherableWifiRegexs) { 268 if (iface.matches(regex)) return true; 269 } 270 return false; 271 } 272 } 273 isBluetooth(String iface)274 public boolean isBluetooth(String iface) { 275 synchronized (mPublicSync) { 276 for (String regex : mTetherableBluetoothRegexs) { 277 if (iface.matches(regex)) return true; 278 } 279 return false; 280 } 281 } 282 interfaceAdded(String iface)283 public void interfaceAdded(String iface) { 284 if (VDBG) Log.d(TAG, "interfaceAdded " + iface); 285 boolean found = false; 286 boolean usb = false; 287 synchronized (mPublicSync) { 288 if (isWifi(iface)) { 289 found = true; 290 } 291 if (isUsb(iface)) { 292 found = true; 293 usb = true; 294 } 295 if (isBluetooth(iface)) { 296 found = true; 297 } 298 if (found == false) { 299 if (VDBG) Log.d(TAG, iface + " is not a tetherable iface, ignoring"); 300 return; 301 } 302 303 TetherInterfaceSM sm = mIfaces.get(iface); 304 if (sm != null) { 305 if (VDBG) Log.d(TAG, "active iface (" + iface + ") reported as added, ignoring"); 306 return; 307 } 308 sm = new TetherInterfaceSM(iface, mLooper, usb); 309 mIfaces.put(iface, sm); 310 sm.start(); 311 } 312 } 313 interfaceRemoved(String iface)314 public void interfaceRemoved(String iface) { 315 if (VDBG) Log.d(TAG, "interfaceRemoved " + iface); 316 synchronized (mPublicSync) { 317 TetherInterfaceSM sm = mIfaces.get(iface); 318 if (sm == null) { 319 if (VDBG) { 320 Log.e(TAG, "attempting to remove unknown iface (" + iface + "), ignoring"); 321 } 322 return; 323 } 324 sm.sendMessage(TetherInterfaceSM.CMD_INTERFACE_DOWN); 325 mIfaces.remove(iface); 326 } 327 } 328 tether(String iface)329 public int tether(String iface) { 330 if (DBG) Log.d(TAG, "Tethering " + iface); 331 TetherInterfaceSM sm = null; 332 synchronized (mPublicSync) { 333 sm = mIfaces.get(iface); 334 } 335 if (sm == null) { 336 Log.e(TAG, "Tried to Tether an unknown iface :" + iface + ", ignoring"); 337 return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE; 338 } 339 if (!sm.isAvailable() && !sm.isErrored()) { 340 Log.e(TAG, "Tried to Tether an unavailable iface :" + iface + ", ignoring"); 341 return ConnectivityManager.TETHER_ERROR_UNAVAIL_IFACE; 342 } 343 sm.sendMessage(TetherInterfaceSM.CMD_TETHER_REQUESTED); 344 return ConnectivityManager.TETHER_ERROR_NO_ERROR; 345 } 346 untether(String iface)347 public int untether(String iface) { 348 if (DBG) Log.d(TAG, "Untethering " + iface); 349 TetherInterfaceSM sm = null; 350 synchronized (mPublicSync) { 351 sm = mIfaces.get(iface); 352 } 353 if (sm == null) { 354 Log.e(TAG, "Tried to Untether an unknown iface :" + iface + ", ignoring"); 355 return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE; 356 } 357 if (sm.isErrored()) { 358 Log.e(TAG, "Tried to Untethered an errored iface :" + iface + ", ignoring"); 359 return ConnectivityManager.TETHER_ERROR_UNAVAIL_IFACE; 360 } 361 sm.sendMessage(TetherInterfaceSM.CMD_TETHER_UNREQUESTED); 362 return ConnectivityManager.TETHER_ERROR_NO_ERROR; 363 } 364 getLastTetherError(String iface)365 public int getLastTetherError(String iface) { 366 TetherInterfaceSM sm = null; 367 synchronized (mPublicSync) { 368 sm = mIfaces.get(iface); 369 if (sm == null) { 370 Log.e(TAG, "Tried to getLastTetherError on an unknown iface :" + iface + 371 ", ignoring"); 372 return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE; 373 } 374 return sm.getLastError(); 375 } 376 } 377 378 // TODO - move all private methods used only by the state machine into the state machine 379 // to clarify what needs synchronized protection. sendTetherStateChangedBroadcast()380 private void sendTetherStateChangedBroadcast() { 381 if (!getConnectivityManager().isTetheringSupported()) return; 382 383 ArrayList<String> availableList = new ArrayList<String>(); 384 ArrayList<String> activeList = new ArrayList<String>(); 385 ArrayList<String> erroredList = new ArrayList<String>(); 386 387 boolean wifiTethered = false; 388 boolean usbTethered = false; 389 boolean bluetoothTethered = false; 390 391 synchronized (mPublicSync) { 392 Set ifaces = mIfaces.keySet(); 393 for (Object iface : ifaces) { 394 TetherInterfaceSM sm = mIfaces.get(iface); 395 if (sm != null) { 396 if (sm.isErrored()) { 397 erroredList.add((String)iface); 398 } else if (sm.isAvailable()) { 399 availableList.add((String)iface); 400 } else if (sm.isTethered()) { 401 if (isUsb((String)iface)) { 402 usbTethered = true; 403 } else if (isWifi((String)iface)) { 404 wifiTethered = true; 405 } else if (isBluetooth((String)iface)) { 406 bluetoothTethered = true; 407 } 408 activeList.add((String)iface); 409 } 410 } 411 } 412 } 413 Intent broadcast = new Intent(ConnectivityManager.ACTION_TETHER_STATE_CHANGED); 414 broadcast.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING | 415 Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 416 broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_AVAILABLE_TETHER, 417 availableList); 418 broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_ACTIVE_TETHER, activeList); 419 broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_ERRORED_TETHER, 420 erroredList); 421 mContext.sendStickyBroadcastAsUser(broadcast, UserHandle.ALL); 422 if (DBG) { 423 Log.d(TAG, "sendTetherStateChangedBroadcast " + availableList.size() + ", " + 424 activeList.size() + ", " + erroredList.size()); 425 } 426 427 if (usbTethered) { 428 if (wifiTethered || bluetoothTethered) { 429 showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_general); 430 } else { 431 showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_usb); 432 } 433 } else if (wifiTethered) { 434 if (bluetoothTethered) { 435 showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_general); 436 } else { 437 /* We now have a status bar icon for WifiTethering, so drop the notification */ 438 clearTetheredNotification(); 439 } 440 } else if (bluetoothTethered) { 441 showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_bluetooth); 442 } else { 443 clearTetheredNotification(); 444 } 445 } 446 showTetheredNotification(int icon)447 private void showTetheredNotification(int icon) { 448 NotificationManager notificationManager = 449 (NotificationManager)mContext.getSystemService(Context.NOTIFICATION_SERVICE); 450 if (notificationManager == null) { 451 return; 452 } 453 454 if (mLastNotificationId != 0) { 455 if (mLastNotificationId == icon) { 456 return; 457 } 458 notificationManager.cancelAsUser(null, mLastNotificationId, 459 UserHandle.ALL); 460 mLastNotificationId = 0; 461 } 462 463 Intent intent = new Intent(); 464 intent.setClassName("com.android.settings", "com.android.settings.TetherSettings"); 465 intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY); 466 467 PendingIntent pi = PendingIntent.getActivityAsUser(mContext, 0, intent, 0, 468 null, UserHandle.CURRENT); 469 470 Resources r = Resources.getSystem(); 471 CharSequence title = r.getText(com.android.internal.R.string.tethered_notification_title); 472 CharSequence message = r.getText(com.android.internal.R.string. 473 tethered_notification_message); 474 475 if (mTetheredNotificationBuilder == null) { 476 mTetheredNotificationBuilder = new Notification.Builder(mContext); 477 mTetheredNotificationBuilder.setWhen(0) 478 .setOngoing(true) 479 .setColor(mContext.getColor( 480 com.android.internal.R.color.system_notification_accent_color)) 481 .setVisibility(Notification.VISIBILITY_PUBLIC) 482 .setCategory(Notification.CATEGORY_STATUS); 483 } 484 mTetheredNotificationBuilder.setSmallIcon(icon) 485 .setContentTitle(title) 486 .setContentText(message) 487 .setContentIntent(pi); 488 mLastNotificationId = icon; 489 490 notificationManager.notifyAsUser(null, mLastNotificationId, 491 mTetheredNotificationBuilder.build(), UserHandle.ALL); 492 } 493 clearTetheredNotification()494 private void clearTetheredNotification() { 495 NotificationManager notificationManager = 496 (NotificationManager)mContext.getSystemService(Context.NOTIFICATION_SERVICE); 497 if (notificationManager != null && mLastNotificationId != 0) { 498 notificationManager.cancelAsUser(null, mLastNotificationId, 499 UserHandle.ALL); 500 mLastNotificationId = 0; 501 } 502 } 503 504 private class StateReceiver extends BroadcastReceiver { 505 @Override onReceive(Context content, Intent intent)506 public void onReceive(Context content, Intent intent) { 507 String action = intent.getAction(); 508 if (action == null) { return; } 509 if (action.equals(UsbManager.ACTION_USB_STATE)) { 510 synchronized (Tethering.this.mPublicSync) { 511 boolean usbConnected = intent.getBooleanExtra(UsbManager.USB_CONNECTED, false); 512 mRndisEnabled = intent.getBooleanExtra(UsbManager.USB_FUNCTION_RNDIS, false); 513 // start tethering if we have a request pending 514 if (usbConnected && mRndisEnabled && mUsbTetherRequested) { 515 tetherUsb(true); 516 } 517 mUsbTetherRequested = false; 518 } 519 } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) { 520 NetworkInfo networkInfo = (NetworkInfo)intent.getParcelableExtra( 521 ConnectivityManager.EXTRA_NETWORK_INFO); 522 if (networkInfo != null && 523 networkInfo.getDetailedState() != NetworkInfo.DetailedState.FAILED) { 524 if (VDBG) Log.d(TAG, "Tethering got CONNECTIVITY_ACTION"); 525 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_UPSTREAM_CHANGED); 526 } 527 } else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) { 528 updateConfiguration(); 529 } 530 } 531 } 532 tetherUsb(boolean enable)533 private void tetherUsb(boolean enable) { 534 if (VDBG) Log.d(TAG, "tetherUsb " + enable); 535 536 String[] ifaces = new String[0]; 537 try { 538 ifaces = mNMService.listInterfaces(); 539 } catch (Exception e) { 540 Log.e(TAG, "Error listing Interfaces", e); 541 return; 542 } 543 for (String iface : ifaces) { 544 if (isUsb(iface)) { 545 int result = (enable ? tether(iface) : untether(iface)); 546 if (result == ConnectivityManager.TETHER_ERROR_NO_ERROR) { 547 return; 548 } 549 } 550 } 551 Log.e(TAG, "unable start or stop USB tethering"); 552 } 553 554 // configured when we start tethering and unconfig'd on error or conclusion configureUsbIface(boolean enabled)555 private boolean configureUsbIface(boolean enabled) { 556 if (VDBG) Log.d(TAG, "configureUsbIface(" + enabled + ")"); 557 558 // toggle the USB interfaces 559 String[] ifaces = new String[0]; 560 try { 561 ifaces = mNMService.listInterfaces(); 562 } catch (Exception e) { 563 Log.e(TAG, "Error listing Interfaces", e); 564 return false; 565 } 566 for (String iface : ifaces) { 567 if (isUsb(iface)) { 568 InterfaceConfiguration ifcg = null; 569 try { 570 ifcg = mNMService.getInterfaceConfig(iface); 571 if (ifcg != null) { 572 InetAddress addr = NetworkUtils.numericToInetAddress(USB_NEAR_IFACE_ADDR); 573 ifcg.setLinkAddress(new LinkAddress(addr, USB_PREFIX_LENGTH)); 574 if (enabled) { 575 ifcg.setInterfaceUp(); 576 } else { 577 ifcg.setInterfaceDown(); 578 } 579 ifcg.clearFlag("running"); 580 mNMService.setInterfaceConfig(iface, ifcg); 581 } 582 } catch (Exception e) { 583 Log.e(TAG, "Error configuring interface " + iface, e); 584 return false; 585 } 586 } 587 } 588 589 return true; 590 } 591 592 // TODO - return copies so people can't tamper getTetherableUsbRegexs()593 public String[] getTetherableUsbRegexs() { 594 return mTetherableUsbRegexs; 595 } 596 getTetherableWifiRegexs()597 public String[] getTetherableWifiRegexs() { 598 return mTetherableWifiRegexs; 599 } 600 getTetherableBluetoothRegexs()601 public String[] getTetherableBluetoothRegexs() { 602 return mTetherableBluetoothRegexs; 603 } 604 setUsbTethering(boolean enable)605 public int setUsbTethering(boolean enable) { 606 if (VDBG) Log.d(TAG, "setUsbTethering(" + enable + ")"); 607 UsbManager usbManager = (UsbManager)mContext.getSystemService(Context.USB_SERVICE); 608 609 synchronized (mPublicSync) { 610 if (enable) { 611 if (mRndisEnabled) { 612 tetherUsb(true); 613 } else { 614 mUsbTetherRequested = true; 615 usbManager.setCurrentFunction(UsbManager.USB_FUNCTION_RNDIS); 616 } 617 } else { 618 tetherUsb(false); 619 if (mRndisEnabled) { 620 usbManager.setCurrentFunction(null); 621 } 622 mUsbTetherRequested = false; 623 } 624 } 625 return ConnectivityManager.TETHER_ERROR_NO_ERROR; 626 } 627 getUpstreamIfaceTypes()628 public int[] getUpstreamIfaceTypes() { 629 int values[]; 630 synchronized (mPublicSync) { 631 updateConfiguration(); // TODO - remove? 632 values = new int[mUpstreamIfaceTypes.size()]; 633 Iterator<Integer> iterator = mUpstreamIfaceTypes.iterator(); 634 for (int i=0; i < mUpstreamIfaceTypes.size(); i++) { 635 values[i] = iterator.next(); 636 } 637 } 638 return values; 639 } 640 checkDunRequired()641 public void checkDunRequired() { 642 int secureSetting = 2; 643 TelephonyManager tm = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE); 644 if (tm != null) { 645 secureSetting = tm.getTetherApnRequired(); 646 } 647 synchronized (mPublicSync) { 648 // 2 = not set, 0 = DUN not required, 1 = DUN required 649 if (secureSetting != 2) { 650 int requiredApn = (secureSetting == 1 ? 651 ConnectivityManager.TYPE_MOBILE_DUN : 652 ConnectivityManager.TYPE_MOBILE_HIPRI); 653 if (requiredApn == ConnectivityManager.TYPE_MOBILE_DUN) { 654 while (mUpstreamIfaceTypes.contains(MOBILE_TYPE)) { 655 mUpstreamIfaceTypes.remove(MOBILE_TYPE); 656 } 657 while (mUpstreamIfaceTypes.contains(HIPRI_TYPE)) { 658 mUpstreamIfaceTypes.remove(HIPRI_TYPE); 659 } 660 if (mUpstreamIfaceTypes.contains(DUN_TYPE) == false) { 661 mUpstreamIfaceTypes.add(DUN_TYPE); 662 } 663 } else { 664 while (mUpstreamIfaceTypes.contains(DUN_TYPE)) { 665 mUpstreamIfaceTypes.remove(DUN_TYPE); 666 } 667 if (mUpstreamIfaceTypes.contains(MOBILE_TYPE) == false) { 668 mUpstreamIfaceTypes.add(MOBILE_TYPE); 669 } 670 if (mUpstreamIfaceTypes.contains(HIPRI_TYPE) == false) { 671 mUpstreamIfaceTypes.add(HIPRI_TYPE); 672 } 673 } 674 } 675 if (mUpstreamIfaceTypes.contains(DUN_TYPE)) { 676 mPreferredUpstreamMobileApn = ConnectivityManager.TYPE_MOBILE_DUN; 677 } else { 678 mPreferredUpstreamMobileApn = ConnectivityManager.TYPE_MOBILE_HIPRI; 679 } 680 } 681 } 682 683 // TODO review API - maybe return ArrayList<String> here and below? getTetheredIfaces()684 public String[] getTetheredIfaces() { 685 ArrayList<String> list = new ArrayList<String>(); 686 synchronized (mPublicSync) { 687 Set keys = mIfaces.keySet(); 688 for (Object key : keys) { 689 TetherInterfaceSM sm = mIfaces.get(key); 690 if (sm.isTethered()) { 691 list.add((String)key); 692 } 693 } 694 } 695 String[] retVal = new String[list.size()]; 696 for (int i=0; i < list.size(); i++) { 697 retVal[i] = list.get(i); 698 } 699 return retVal; 700 } 701 getTetherableIfaces()702 public String[] getTetherableIfaces() { 703 ArrayList<String> list = new ArrayList<String>(); 704 synchronized (mPublicSync) { 705 Set keys = mIfaces.keySet(); 706 for (Object key : keys) { 707 TetherInterfaceSM sm = mIfaces.get(key); 708 if (sm.isAvailable()) { 709 list.add((String)key); 710 } 711 } 712 } 713 String[] retVal = new String[list.size()]; 714 for (int i=0; i < list.size(); i++) { 715 retVal[i] = list.get(i); 716 } 717 return retVal; 718 } 719 getTetheredDhcpRanges()720 public String[] getTetheredDhcpRanges() { 721 return mDhcpRange; 722 } 723 getErroredIfaces()724 public String[] getErroredIfaces() { 725 ArrayList<String> list = new ArrayList<String>(); 726 synchronized (mPublicSync) { 727 Set keys = mIfaces.keySet(); 728 for (Object key : keys) { 729 TetherInterfaceSM sm = mIfaces.get(key); 730 if (sm.isErrored()) { 731 list.add((String)key); 732 } 733 } 734 } 735 String[] retVal = new String[list.size()]; 736 for (int i= 0; i< list.size(); i++) { 737 retVal[i] = list.get(i); 738 } 739 return retVal; 740 } 741 742 class TetherInterfaceSM extends StateMachine { 743 // notification from the master SM that it's not in tether mode 744 static final int CMD_TETHER_MODE_DEAD = 1; 745 // request from the user that it wants to tether 746 static final int CMD_TETHER_REQUESTED = 2; 747 // request from the user that it wants to untether 748 static final int CMD_TETHER_UNREQUESTED = 3; 749 // notification that this interface is down 750 static final int CMD_INTERFACE_DOWN = 4; 751 // notification that this interface is up 752 static final int CMD_INTERFACE_UP = 5; 753 // notification from the master SM that it had an error turning on cellular dun 754 static final int CMD_CELL_DUN_ERROR = 6; 755 // notification from the master SM that it had trouble enabling IP Forwarding 756 static final int CMD_IP_FORWARDING_ENABLE_ERROR = 7; 757 // notification from the master SM that it had trouble disabling IP Forwarding 758 static final int CMD_IP_FORWARDING_DISABLE_ERROR = 8; 759 // notification from the master SM that it had trouble starting tethering 760 static final int CMD_START_TETHERING_ERROR = 9; 761 // notification from the master SM that it had trouble stopping tethering 762 static final int CMD_STOP_TETHERING_ERROR = 10; 763 // notification from the master SM that it had trouble setting the DNS forwarders 764 static final int CMD_SET_DNS_FORWARDERS_ERROR = 11; 765 // the upstream connection has changed 766 static final int CMD_TETHER_CONNECTION_CHANGED = 12; 767 768 private State mDefaultState; 769 770 private State mInitialState; 771 private State mStartingState; 772 private State mTetheredState; 773 774 private State mUnavailableState; 775 776 private boolean mAvailable; 777 private boolean mTethered; 778 int mLastError; 779 780 String mIfaceName; 781 String mMyUpstreamIfaceName; // may change over time 782 783 boolean mUsb; 784 TetherInterfaceSM(String name, Looper looper, boolean usb)785 TetherInterfaceSM(String name, Looper looper, boolean usb) { 786 super(name, looper); 787 mIfaceName = name; 788 mUsb = usb; 789 setLastError(ConnectivityManager.TETHER_ERROR_NO_ERROR); 790 791 mInitialState = new InitialState(); 792 addState(mInitialState); 793 mStartingState = new StartingState(); 794 addState(mStartingState); 795 mTetheredState = new TetheredState(); 796 addState(mTetheredState); 797 mUnavailableState = new UnavailableState(); 798 addState(mUnavailableState); 799 800 setInitialState(mInitialState); 801 } 802 toString()803 public String toString() { 804 String res = new String(); 805 res += mIfaceName + " - "; 806 IState current = getCurrentState(); 807 if (current == mInitialState) res += "InitialState"; 808 if (current == mStartingState) res += "StartingState"; 809 if (current == mTetheredState) res += "TetheredState"; 810 if (current == mUnavailableState) res += "UnavailableState"; 811 if (mAvailable) res += " - Available"; 812 if (mTethered) res += " - Tethered"; 813 res += " - lastError =" + mLastError; 814 return res; 815 } 816 getLastError()817 public int getLastError() { 818 synchronized (Tethering.this.mPublicSync) { 819 return mLastError; 820 } 821 } 822 setLastError(int error)823 private void setLastError(int error) { 824 synchronized (Tethering.this.mPublicSync) { 825 mLastError = error; 826 827 if (isErrored()) { 828 if (mUsb) { 829 // note everything's been unwound by this point so nothing to do on 830 // further error.. 831 Tethering.this.configureUsbIface(false); 832 } 833 } 834 } 835 } 836 isAvailable()837 public boolean isAvailable() { 838 synchronized (Tethering.this.mPublicSync) { 839 return mAvailable; 840 } 841 } 842 setAvailable(boolean available)843 private void setAvailable(boolean available) { 844 synchronized (Tethering.this.mPublicSync) { 845 mAvailable = available; 846 } 847 } 848 isTethered()849 public boolean isTethered() { 850 synchronized (Tethering.this.mPublicSync) { 851 return mTethered; 852 } 853 } 854 setTethered(boolean tethered)855 private void setTethered(boolean tethered) { 856 synchronized (Tethering.this.mPublicSync) { 857 mTethered = tethered; 858 } 859 } 860 isErrored()861 public boolean isErrored() { 862 synchronized (Tethering.this.mPublicSync) { 863 return (mLastError != ConnectivityManager.TETHER_ERROR_NO_ERROR); 864 } 865 } 866 867 class InitialState extends State { 868 @Override enter()869 public void enter() { 870 setAvailable(true); 871 setTethered(false); 872 sendTetherStateChangedBroadcast(); 873 } 874 875 @Override processMessage(Message message)876 public boolean processMessage(Message message) { 877 if (DBG) Log.d(TAG, "InitialState.processMessage what=" + message.what); 878 boolean retValue = true; 879 switch (message.what) { 880 case CMD_TETHER_REQUESTED: 881 setLastError(ConnectivityManager.TETHER_ERROR_NO_ERROR); 882 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_REQUESTED, 883 TetherInterfaceSM.this); 884 transitionTo(mStartingState); 885 break; 886 case CMD_INTERFACE_DOWN: 887 transitionTo(mUnavailableState); 888 break; 889 default: 890 retValue = false; 891 break; 892 } 893 return retValue; 894 } 895 } 896 897 class StartingState extends State { 898 @Override enter()899 public void enter() { 900 setAvailable(false); 901 if (mUsb) { 902 if (!Tethering.this.configureUsbIface(true)) { 903 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED, 904 TetherInterfaceSM.this); 905 setLastError(ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR); 906 907 transitionTo(mInitialState); 908 return; 909 } 910 } 911 sendTetherStateChangedBroadcast(); 912 913 // Skipping StartingState 914 transitionTo(mTetheredState); 915 } 916 @Override processMessage(Message message)917 public boolean processMessage(Message message) { 918 if (DBG) Log.d(TAG, "StartingState.processMessage what=" + message.what); 919 boolean retValue = true; 920 switch (message.what) { 921 // maybe a parent class? 922 case CMD_TETHER_UNREQUESTED: 923 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED, 924 TetherInterfaceSM.this); 925 if (mUsb) { 926 if (!Tethering.this.configureUsbIface(false)) { 927 setLastErrorAndTransitionToInitialState( 928 ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR); 929 break; 930 } 931 } 932 transitionTo(mInitialState); 933 break; 934 case CMD_CELL_DUN_ERROR: 935 case CMD_IP_FORWARDING_ENABLE_ERROR: 936 case CMD_IP_FORWARDING_DISABLE_ERROR: 937 case CMD_START_TETHERING_ERROR: 938 case CMD_STOP_TETHERING_ERROR: 939 case CMD_SET_DNS_FORWARDERS_ERROR: 940 setLastErrorAndTransitionToInitialState( 941 ConnectivityManager.TETHER_ERROR_MASTER_ERROR); 942 break; 943 case CMD_INTERFACE_DOWN: 944 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED, 945 TetherInterfaceSM.this); 946 transitionTo(mUnavailableState); 947 break; 948 default: 949 retValue = false; 950 } 951 return retValue; 952 } 953 } 954 955 class TetheredState extends State { 956 @Override enter()957 public void enter() { 958 try { 959 mNMService.tetherInterface(mIfaceName); 960 } catch (Exception e) { 961 Log.e(TAG, "Error Tethering: " + e.toString()); 962 setLastError(ConnectivityManager.TETHER_ERROR_TETHER_IFACE_ERROR); 963 964 transitionTo(mInitialState); 965 return; 966 } 967 if (DBG) Log.d(TAG, "Tethered " + mIfaceName); 968 setAvailable(false); 969 setTethered(true); 970 sendTetherStateChangedBroadcast(); 971 } 972 cleanupUpstream()973 private void cleanupUpstream() { 974 if (mMyUpstreamIfaceName != null) { 975 // note that we don't care about errors here. 976 // sometimes interfaces are gone before we get 977 // to remove their rules, which generates errors. 978 // just do the best we can. 979 try { 980 // about to tear down NAT; gather remaining statistics 981 mStatsService.forceUpdate(); 982 } catch (Exception e) { 983 if (VDBG) Log.e(TAG, "Exception in forceUpdate: " + e.toString()); 984 } 985 try { 986 mNMService.stopInterfaceForwarding(mIfaceName, mMyUpstreamIfaceName); 987 } catch (Exception e) { 988 if (VDBG) Log.e( 989 TAG, "Exception in removeInterfaceForward: " + e.toString()); 990 } 991 try { 992 mNMService.disableNat(mIfaceName, mMyUpstreamIfaceName); 993 } catch (Exception e) { 994 if (VDBG) Log.e(TAG, "Exception in disableNat: " + e.toString()); 995 } 996 mMyUpstreamIfaceName = null; 997 } 998 return; 999 } 1000 1001 @Override processMessage(Message message)1002 public boolean processMessage(Message message) { 1003 if (DBG) Log.d(TAG, "TetheredState.processMessage what=" + message.what); 1004 boolean retValue = true; 1005 boolean error = false; 1006 switch (message.what) { 1007 case CMD_TETHER_UNREQUESTED: 1008 case CMD_INTERFACE_DOWN: 1009 cleanupUpstream(); 1010 try { 1011 mNMService.untetherInterface(mIfaceName); 1012 } catch (Exception e) { 1013 setLastErrorAndTransitionToInitialState( 1014 ConnectivityManager.TETHER_ERROR_UNTETHER_IFACE_ERROR); 1015 break; 1016 } 1017 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED, 1018 TetherInterfaceSM.this); 1019 if (message.what == CMD_TETHER_UNREQUESTED) { 1020 if (mUsb) { 1021 if (!Tethering.this.configureUsbIface(false)) { 1022 setLastError( 1023 ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR); 1024 } 1025 } 1026 transitionTo(mInitialState); 1027 } else if (message.what == CMD_INTERFACE_DOWN) { 1028 transitionTo(mUnavailableState); 1029 } 1030 if (DBG) Log.d(TAG, "Untethered " + mIfaceName); 1031 break; 1032 case CMD_TETHER_CONNECTION_CHANGED: 1033 String newUpstreamIfaceName = (String)(message.obj); 1034 if ((mMyUpstreamIfaceName == null && newUpstreamIfaceName == null) || 1035 (mMyUpstreamIfaceName != null && 1036 mMyUpstreamIfaceName.equals(newUpstreamIfaceName))) { 1037 if (VDBG) Log.d(TAG, "Connection changed noop - dropping"); 1038 break; 1039 } 1040 cleanupUpstream(); 1041 if (newUpstreamIfaceName != null) { 1042 try { 1043 mNMService.enableNat(mIfaceName, newUpstreamIfaceName); 1044 mNMService.startInterfaceForwarding(mIfaceName, 1045 newUpstreamIfaceName); 1046 } catch (Exception e) { 1047 Log.e(TAG, "Exception enabling Nat: " + e.toString()); 1048 try { 1049 mNMService.disableNat(mIfaceName, newUpstreamIfaceName); 1050 } catch (Exception ee) {} 1051 try { 1052 mNMService.untetherInterface(mIfaceName); 1053 } catch (Exception ee) {} 1054 1055 setLastError(ConnectivityManager.TETHER_ERROR_ENABLE_NAT_ERROR); 1056 transitionTo(mInitialState); 1057 return true; 1058 } 1059 } 1060 mMyUpstreamIfaceName = newUpstreamIfaceName; 1061 break; 1062 case CMD_CELL_DUN_ERROR: 1063 case CMD_IP_FORWARDING_ENABLE_ERROR: 1064 case CMD_IP_FORWARDING_DISABLE_ERROR: 1065 case CMD_START_TETHERING_ERROR: 1066 case CMD_STOP_TETHERING_ERROR: 1067 case CMD_SET_DNS_FORWARDERS_ERROR: 1068 error = true; 1069 // fall through 1070 case CMD_TETHER_MODE_DEAD: 1071 cleanupUpstream(); 1072 try { 1073 mNMService.untetherInterface(mIfaceName); 1074 } catch (Exception e) { 1075 setLastErrorAndTransitionToInitialState( 1076 ConnectivityManager.TETHER_ERROR_UNTETHER_IFACE_ERROR); 1077 break; 1078 } 1079 if (error) { 1080 setLastErrorAndTransitionToInitialState( 1081 ConnectivityManager.TETHER_ERROR_MASTER_ERROR); 1082 break; 1083 } 1084 if (DBG) Log.d(TAG, "Tether lost upstream connection " + mIfaceName); 1085 sendTetherStateChangedBroadcast(); 1086 if (mUsb) { 1087 if (!Tethering.this.configureUsbIface(false)) { 1088 setLastError(ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR); 1089 } 1090 } 1091 transitionTo(mInitialState); 1092 break; 1093 default: 1094 retValue = false; 1095 break; 1096 } 1097 return retValue; 1098 } 1099 } 1100 1101 class UnavailableState extends State { 1102 @Override enter()1103 public void enter() { 1104 setAvailable(false); 1105 setLastError(ConnectivityManager.TETHER_ERROR_NO_ERROR); 1106 setTethered(false); 1107 sendTetherStateChangedBroadcast(); 1108 } 1109 @Override processMessage(Message message)1110 public boolean processMessage(Message message) { 1111 boolean retValue = true; 1112 switch (message.what) { 1113 case CMD_INTERFACE_UP: 1114 transitionTo(mInitialState); 1115 break; 1116 default: 1117 retValue = false; 1118 break; 1119 } 1120 return retValue; 1121 } 1122 } 1123 setLastErrorAndTransitionToInitialState(int error)1124 void setLastErrorAndTransitionToInitialState(int error) { 1125 setLastError(error); 1126 transitionTo(mInitialState); 1127 } 1128 1129 } 1130 1131 class TetherMasterSM extends StateMachine { 1132 // an interface SM has requested Tethering 1133 static final int CMD_TETHER_MODE_REQUESTED = 1; 1134 // an interface SM has unrequested Tethering 1135 static final int CMD_TETHER_MODE_UNREQUESTED = 2; 1136 // upstream connection change - do the right thing 1137 static final int CMD_UPSTREAM_CHANGED = 3; 1138 // we received notice that the cellular DUN connection is up 1139 static final int CMD_CELL_CONNECTION_RENEW = 4; 1140 // we don't have a valid upstream conn, check again after a delay 1141 static final int CMD_RETRY_UPSTREAM = 5; 1142 1143 // This indicates what a timeout event relates to. A state that 1144 // sends itself a delayed timeout event and handles incoming timeout events 1145 // should inc this when it is entered and whenever it sends a new timeout event. 1146 // We do not flush the old ones. 1147 private int mSequenceNumber; 1148 1149 private State mInitialState; 1150 private State mTetherModeAliveState; 1151 1152 private State mSetIpForwardingEnabledErrorState; 1153 private State mSetIpForwardingDisabledErrorState; 1154 private State mStartTetheringErrorState; 1155 private State mStopTetheringErrorState; 1156 private State mSetDnsForwardersErrorState; 1157 1158 private ArrayList<TetherInterfaceSM> mNotifyList; 1159 1160 private int mCurrentConnectionSequence; 1161 private int mMobileApnReserved = ConnectivityManager.TYPE_NONE; 1162 1163 private String mUpstreamIfaceName = null; 1164 1165 private static final int UPSTREAM_SETTLE_TIME_MS = 10000; 1166 private static final int CELL_CONNECTION_RENEW_MS = 40000; 1167 TetherMasterSM(String name, Looper looper)1168 TetherMasterSM(String name, Looper looper) { 1169 super(name, looper); 1170 1171 //Add states 1172 mInitialState = new InitialState(); 1173 addState(mInitialState); 1174 mTetherModeAliveState = new TetherModeAliveState(); 1175 addState(mTetherModeAliveState); 1176 1177 mSetIpForwardingEnabledErrorState = new SetIpForwardingEnabledErrorState(); 1178 addState(mSetIpForwardingEnabledErrorState); 1179 mSetIpForwardingDisabledErrorState = new SetIpForwardingDisabledErrorState(); 1180 addState(mSetIpForwardingDisabledErrorState); 1181 mStartTetheringErrorState = new StartTetheringErrorState(); 1182 addState(mStartTetheringErrorState); 1183 mStopTetheringErrorState = new StopTetheringErrorState(); 1184 addState(mStopTetheringErrorState); 1185 mSetDnsForwardersErrorState = new SetDnsForwardersErrorState(); 1186 addState(mSetDnsForwardersErrorState); 1187 1188 mNotifyList = new ArrayList<TetherInterfaceSM>(); 1189 setInitialState(mInitialState); 1190 } 1191 1192 class TetherMasterUtilState extends State { 1193 protected final static boolean TRY_TO_SETUP_MOBILE_CONNECTION = true; 1194 protected final static boolean WAIT_FOR_NETWORK_TO_SETTLE = false; 1195 1196 @Override processMessage(Message m)1197 public boolean processMessage(Message m) { 1198 return false; 1199 } enableString(int apnType)1200 protected String enableString(int apnType) { 1201 switch (apnType) { 1202 case ConnectivityManager.TYPE_MOBILE_DUN: 1203 return Phone.FEATURE_ENABLE_DUN_ALWAYS; 1204 case ConnectivityManager.TYPE_MOBILE: 1205 case ConnectivityManager.TYPE_MOBILE_HIPRI: 1206 return Phone.FEATURE_ENABLE_HIPRI; 1207 } 1208 return null; 1209 } turnOnUpstreamMobileConnection(int apnType)1210 protected boolean turnOnUpstreamMobileConnection(int apnType) { 1211 boolean retValue = true; 1212 if (apnType == ConnectivityManager.TYPE_NONE) return false; 1213 if (apnType != mMobileApnReserved) turnOffUpstreamMobileConnection(); 1214 int result = PhoneConstants.APN_REQUEST_FAILED; 1215 String enableString = enableString(apnType); 1216 if (enableString == null) return false; 1217 result = getConnectivityManager().startUsingNetworkFeature( 1218 ConnectivityManager.TYPE_MOBILE, enableString); 1219 switch (result) { 1220 case PhoneConstants.APN_ALREADY_ACTIVE: 1221 case PhoneConstants.APN_REQUEST_STARTED: 1222 mMobileApnReserved = apnType; 1223 Message m = obtainMessage(CMD_CELL_CONNECTION_RENEW); 1224 m.arg1 = ++mCurrentConnectionSequence; 1225 sendMessageDelayed(m, CELL_CONNECTION_RENEW_MS); 1226 break; 1227 case PhoneConstants.APN_REQUEST_FAILED: 1228 default: 1229 retValue = false; 1230 break; 1231 } 1232 1233 return retValue; 1234 } turnOffUpstreamMobileConnection()1235 protected boolean turnOffUpstreamMobileConnection() { 1236 // ignore pending renewal requests 1237 ++mCurrentConnectionSequence; 1238 if (mMobileApnReserved != ConnectivityManager.TYPE_NONE) { 1239 getConnectivityManager().stopUsingNetworkFeature( 1240 ConnectivityManager.TYPE_MOBILE, enableString(mMobileApnReserved)); 1241 mMobileApnReserved = ConnectivityManager.TYPE_NONE; 1242 } 1243 return true; 1244 } turnOnMasterTetherSettings()1245 protected boolean turnOnMasterTetherSettings() { 1246 try { 1247 mNMService.setIpForwardingEnabled(true); 1248 } catch (Exception e) { 1249 transitionTo(mSetIpForwardingEnabledErrorState); 1250 return false; 1251 } 1252 try { 1253 mNMService.startTethering(mDhcpRange); 1254 } catch (Exception e) { 1255 try { 1256 mNMService.stopTethering(); 1257 mNMService.startTethering(mDhcpRange); 1258 } catch (Exception ee) { 1259 transitionTo(mStartTetheringErrorState); 1260 return false; 1261 } 1262 } 1263 return true; 1264 } turnOffMasterTetherSettings()1265 protected boolean turnOffMasterTetherSettings() { 1266 try { 1267 mNMService.stopTethering(); 1268 } catch (Exception e) { 1269 transitionTo(mStopTetheringErrorState); 1270 return false; 1271 } 1272 try { 1273 mNMService.setIpForwardingEnabled(false); 1274 } catch (Exception e) { 1275 transitionTo(mSetIpForwardingDisabledErrorState); 1276 return false; 1277 } 1278 transitionTo(mInitialState); 1279 return true; 1280 } 1281 chooseUpstreamType(boolean tryCell)1282 protected void chooseUpstreamType(boolean tryCell) { 1283 int upType = ConnectivityManager.TYPE_NONE; 1284 String iface = null; 1285 1286 updateConfiguration(); // TODO - remove? 1287 1288 synchronized (mPublicSync) { 1289 if (VDBG) { 1290 Log.d(TAG, "chooseUpstreamType has upstream iface types:"); 1291 for (Integer netType : mUpstreamIfaceTypes) { 1292 Log.d(TAG, " " + netType); 1293 } 1294 } 1295 1296 for (Integer netType : mUpstreamIfaceTypes) { 1297 NetworkInfo info = 1298 getConnectivityManager().getNetworkInfo(netType.intValue()); 1299 if ((info != null) && info.isConnected()) { 1300 upType = netType.intValue(); 1301 break; 1302 } 1303 } 1304 } 1305 1306 if (DBG) { 1307 Log.d(TAG, "chooseUpstreamType(" + tryCell + "), preferredApn =" 1308 + mPreferredUpstreamMobileApn + ", got type=" + upType); 1309 } 1310 1311 // if we're on DUN, put our own grab on it 1312 if (upType == ConnectivityManager.TYPE_MOBILE_DUN || 1313 upType == ConnectivityManager.TYPE_MOBILE_HIPRI) { 1314 turnOnUpstreamMobileConnection(upType); 1315 } else if (upType != ConnectivityManager.TYPE_NONE) { 1316 /* If we've found an active upstream connection that's not DUN/HIPRI 1317 * we should stop any outstanding DUN/HIPRI start requests. 1318 * 1319 * If we found NONE we don't want to do this as we want any previous 1320 * requests to keep trying to bring up something we can use. 1321 */ 1322 turnOffUpstreamMobileConnection(); 1323 } 1324 1325 if (upType == ConnectivityManager.TYPE_NONE) { 1326 boolean tryAgainLater = true; 1327 if ((tryCell == TRY_TO_SETUP_MOBILE_CONNECTION) && 1328 (turnOnUpstreamMobileConnection(mPreferredUpstreamMobileApn) == true)) { 1329 // we think mobile should be coming up - don't set a retry 1330 tryAgainLater = false; 1331 } 1332 if (tryAgainLater) { 1333 sendMessageDelayed(CMD_RETRY_UPSTREAM, UPSTREAM_SETTLE_TIME_MS); 1334 } 1335 } else { 1336 LinkProperties linkProperties = 1337 getConnectivityManager().getLinkProperties(upType); 1338 if (linkProperties != null) { 1339 // Find the interface with the default IPv4 route. It may be the 1340 // interface described by linkProperties, or one of the interfaces 1341 // stacked on top of it. 1342 Log.i(TAG, "Finding IPv4 upstream interface on: " + linkProperties); 1343 RouteInfo ipv4Default = RouteInfo.selectBestRoute( 1344 linkProperties.getAllRoutes(), Inet4Address.ANY); 1345 if (ipv4Default != null) { 1346 iface = ipv4Default.getInterface(); 1347 Log.i(TAG, "Found interface " + ipv4Default.getInterface()); 1348 } else { 1349 Log.i(TAG, "No IPv4 upstream interface, giving up."); 1350 } 1351 } 1352 1353 if (iface != null) { 1354 String[] dnsServers = mDefaultDnsServers; 1355 Collection<InetAddress> dnses = linkProperties.getDnsServers(); 1356 if (dnses != null) { 1357 // we currently only handle IPv4 1358 ArrayList<InetAddress> v4Dnses = 1359 new ArrayList<InetAddress>(dnses.size()); 1360 for (InetAddress dnsAddress : dnses) { 1361 if (dnsAddress instanceof Inet4Address) { 1362 v4Dnses.add(dnsAddress); 1363 } 1364 } 1365 if (v4Dnses.size() > 0) { 1366 dnsServers = NetworkUtils.makeStrings(v4Dnses); 1367 } 1368 } 1369 try { 1370 Network network = getConnectivityManager().getNetworkForType(upType); 1371 if (network == null) { 1372 Log.e(TAG, "No Network for upstream type " + upType + "!"); 1373 } 1374 if (VDBG) { 1375 Log.d(TAG, "Setting DNS forwarders: Network=" + network + 1376 ", dnsServers=" + Arrays.toString(dnsServers)); 1377 } 1378 mNMService.setDnsForwarders(network, dnsServers); 1379 } catch (Exception e) { 1380 Log.e(TAG, "Setting DNS forwarders failed!"); 1381 transitionTo(mSetDnsForwardersErrorState); 1382 } 1383 } 1384 } 1385 notifyTetheredOfNewUpstreamIface(iface); 1386 } 1387 notifyTetheredOfNewUpstreamIface(String ifaceName)1388 protected void notifyTetheredOfNewUpstreamIface(String ifaceName) { 1389 if (DBG) Log.d(TAG, "notifying tethered with iface =" + ifaceName); 1390 mUpstreamIfaceName = ifaceName; 1391 for (TetherInterfaceSM sm : mNotifyList) { 1392 sm.sendMessage(TetherInterfaceSM.CMD_TETHER_CONNECTION_CHANGED, 1393 ifaceName); 1394 } 1395 } 1396 } 1397 1398 private final AtomicInteger mSimBcastGenerationNumber = new AtomicInteger(0); 1399 private SimChangeBroadcastReceiver mBroadcastReceiver = null; 1400 1401 // keep consts in sync with packages/apps/Settings TetherSettings.java 1402 private static final int WIFI_TETHERING = 0; 1403 private static final int USB_TETHERING = 1; 1404 private static final int BLUETOOTH_TETHERING = 2; 1405 1406 // keep consts in sync with packages/apps/Settings TetherService.java 1407 private static final String EXTRA_ADD_TETHER_TYPE = "extraAddTetherType"; 1408 private static final String EXTRA_RUN_PROVISION = "extraRunProvision"; 1409 startListeningForSimChanges()1410 private void startListeningForSimChanges() { 1411 if (DBG) Log.d(TAG, "startListeningForSimChanges"); 1412 if (mBroadcastReceiver == null) { 1413 mBroadcastReceiver = new SimChangeBroadcastReceiver( 1414 mSimBcastGenerationNumber.incrementAndGet()); 1415 final IntentFilter filter = new IntentFilter(); 1416 filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED); 1417 1418 mContext.registerReceiver(mBroadcastReceiver, filter); 1419 } 1420 } 1421 stopListeningForSimChanges()1422 private void stopListeningForSimChanges() { 1423 if (DBG) Log.d(TAG, "stopListeningForSimChanges"); 1424 if (mBroadcastReceiver != null) { 1425 mSimBcastGenerationNumber.incrementAndGet(); 1426 mContext.unregisterReceiver(mBroadcastReceiver); 1427 mBroadcastReceiver = null; 1428 } 1429 } 1430 1431 class SimChangeBroadcastReceiver extends BroadcastReceiver { 1432 // used to verify this receiver is still current 1433 final private int mGenerationNumber; 1434 1435 // we're interested in edge-triggered LOADED notifications, so 1436 // ignore LOADED unless we saw an ABSENT state first 1437 private boolean mSimAbsentSeen = false; 1438 SimChangeBroadcastReceiver(int generationNumber)1439 public SimChangeBroadcastReceiver(int generationNumber) { 1440 super(); 1441 mGenerationNumber = generationNumber; 1442 } 1443 1444 @Override onReceive(Context context, Intent intent)1445 public void onReceive(Context context, Intent intent) { 1446 if (DBG) { 1447 Log.d(TAG, "simchange mGenerationNumber=" + mGenerationNumber + 1448 ", current generationNumber=" + mSimBcastGenerationNumber.get()); 1449 } 1450 if (mGenerationNumber != mSimBcastGenerationNumber.get()) return; 1451 1452 final String state = 1453 intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE); 1454 1455 Log.d(TAG, "got Sim changed to state " + state + ", mSimAbsentSeen=" + 1456 mSimAbsentSeen); 1457 if (!mSimAbsentSeen && IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(state)) { 1458 mSimAbsentSeen = true; 1459 } 1460 1461 if (mSimAbsentSeen && IccCardConstants.INTENT_VALUE_ICC_LOADED.equals(state)) { 1462 mSimAbsentSeen = false; 1463 try { 1464 if (mContext.getResources().getString(com.android.internal.R.string. 1465 config_mobile_hotspot_provision_app_no_ui).isEmpty() == false) { 1466 final String tetherService = mContext.getResources().getString( 1467 com.android.internal.R.string.config_wifi_tether_enable); 1468 ArrayList<Integer> tethered = new ArrayList<Integer>(); 1469 synchronized (mPublicSync) { 1470 Set ifaces = mIfaces.keySet(); 1471 for (Object iface : ifaces) { 1472 TetherInterfaceSM sm = mIfaces.get(iface); 1473 if (sm != null && sm.isTethered()) { 1474 if (isUsb((String)iface)) { 1475 tethered.add(new Integer(USB_TETHERING)); 1476 } else if (isWifi((String)iface)) { 1477 tethered.add(new Integer(WIFI_TETHERING)); 1478 } else if (isBluetooth((String)iface)) { 1479 tethered.add(new Integer(BLUETOOTH_TETHERING)); 1480 } 1481 } 1482 } 1483 } 1484 for (int tetherType : tethered) { 1485 Intent startProvIntent = new Intent(); 1486 startProvIntent.putExtra(EXTRA_ADD_TETHER_TYPE, tetherType); 1487 startProvIntent.putExtra(EXTRA_RUN_PROVISION, true); 1488 startProvIntent.setComponent( 1489 ComponentName.unflattenFromString(tetherService)); 1490 mContext.startServiceAsUser(startProvIntent, UserHandle.CURRENT); 1491 } 1492 Log.d(TAG, "re-evaluate provisioning"); 1493 } else { 1494 Log.d(TAG, "no prov-check needed for new SIM"); 1495 } 1496 } catch (Resources.NotFoundException e) { 1497 Log.d(TAG, "no prov-check needed for new SIM"); 1498 // not defined, do nothing 1499 } 1500 } 1501 } 1502 } 1503 1504 class InitialState extends TetherMasterUtilState { 1505 @Override enter()1506 public void enter() { 1507 } 1508 @Override processMessage(Message message)1509 public boolean processMessage(Message message) { 1510 if (DBG) Log.d(TAG, "MasterInitialState.processMessage what=" + message.what); 1511 boolean retValue = true; 1512 switch (message.what) { 1513 case CMD_TETHER_MODE_REQUESTED: 1514 TetherInterfaceSM who = (TetherInterfaceSM)message.obj; 1515 if (VDBG) Log.d(TAG, "Tether Mode requested by " + who); 1516 mNotifyList.add(who); 1517 transitionTo(mTetherModeAliveState); 1518 break; 1519 case CMD_TETHER_MODE_UNREQUESTED: 1520 who = (TetherInterfaceSM)message.obj; 1521 if (VDBG) Log.d(TAG, "Tether Mode unrequested by " + who); 1522 int index = mNotifyList.indexOf(who); 1523 if (index != -1) { 1524 mNotifyList.remove(who); 1525 } 1526 break; 1527 default: 1528 retValue = false; 1529 break; 1530 } 1531 return retValue; 1532 } 1533 } 1534 1535 class TetherModeAliveState extends TetherMasterUtilState { 1536 boolean mTryCell = !WAIT_FOR_NETWORK_TO_SETTLE; 1537 @Override enter()1538 public void enter() { 1539 turnOnMasterTetherSettings(); // may transition us out 1540 startListeningForSimChanges(); 1541 1542 mTryCell = !WAIT_FOR_NETWORK_TO_SETTLE; // better try something first pass 1543 // or crazy tests cases will fail 1544 chooseUpstreamType(mTryCell); 1545 mTryCell = !mTryCell; 1546 } 1547 @Override exit()1548 public void exit() { 1549 turnOffUpstreamMobileConnection(); 1550 stopListeningForSimChanges(); 1551 notifyTetheredOfNewUpstreamIface(null); 1552 } 1553 @Override processMessage(Message message)1554 public boolean processMessage(Message message) { 1555 if (DBG) Log.d(TAG, "TetherModeAliveState.processMessage what=" + message.what); 1556 boolean retValue = true; 1557 switch (message.what) { 1558 case CMD_TETHER_MODE_REQUESTED: 1559 TetherInterfaceSM who = (TetherInterfaceSM)message.obj; 1560 if (VDBG) Log.d(TAG, "Tether Mode requested by " + who); 1561 mNotifyList.add(who); 1562 who.sendMessage(TetherInterfaceSM.CMD_TETHER_CONNECTION_CHANGED, 1563 mUpstreamIfaceName); 1564 break; 1565 case CMD_TETHER_MODE_UNREQUESTED: 1566 who = (TetherInterfaceSM)message.obj; 1567 if (VDBG) Log.d(TAG, "Tether Mode unrequested by " + who); 1568 int index = mNotifyList.indexOf(who); 1569 if (index != -1) { 1570 if (DBG) Log.d(TAG, "TetherModeAlive removing notifyee " + who); 1571 mNotifyList.remove(index); 1572 if (mNotifyList.isEmpty()) { 1573 turnOffMasterTetherSettings(); // transitions appropriately 1574 } else { 1575 if (DBG) { 1576 Log.d(TAG, "TetherModeAlive still has " + mNotifyList.size() + 1577 " live requests:"); 1578 for (Object o : mNotifyList) Log.d(TAG, " " + o); 1579 } 1580 } 1581 } else { 1582 Log.e(TAG, "TetherModeAliveState UNREQUESTED has unknown who: " + who); 1583 } 1584 break; 1585 case CMD_UPSTREAM_CHANGED: 1586 // need to try DUN immediately if Wifi goes down 1587 mTryCell = !WAIT_FOR_NETWORK_TO_SETTLE; 1588 chooseUpstreamType(mTryCell); 1589 mTryCell = !mTryCell; 1590 break; 1591 case CMD_CELL_CONNECTION_RENEW: 1592 // make sure we're still using a requested connection - may have found 1593 // wifi or something since then. 1594 if (mCurrentConnectionSequence == message.arg1) { 1595 if (VDBG) { 1596 Log.d(TAG, "renewing mobile connection - requeuing for another " + 1597 CELL_CONNECTION_RENEW_MS + "ms"); 1598 } 1599 turnOnUpstreamMobileConnection(mMobileApnReserved); 1600 } 1601 break; 1602 case CMD_RETRY_UPSTREAM: 1603 chooseUpstreamType(mTryCell); 1604 mTryCell = !mTryCell; 1605 break; 1606 default: 1607 retValue = false; 1608 break; 1609 } 1610 return retValue; 1611 } 1612 } 1613 1614 class ErrorState extends State { 1615 int mErrorNotification; 1616 @Override processMessage(Message message)1617 public boolean processMessage(Message message) { 1618 boolean retValue = true; 1619 switch (message.what) { 1620 case CMD_TETHER_MODE_REQUESTED: 1621 TetherInterfaceSM who = (TetherInterfaceSM)message.obj; 1622 who.sendMessage(mErrorNotification); 1623 break; 1624 default: 1625 retValue = false; 1626 } 1627 return retValue; 1628 } notify(int msgType)1629 void notify(int msgType) { 1630 mErrorNotification = msgType; 1631 for (Object o : mNotifyList) { 1632 TetherInterfaceSM sm = (TetherInterfaceSM)o; 1633 sm.sendMessage(msgType); 1634 } 1635 } 1636 1637 } 1638 class SetIpForwardingEnabledErrorState extends ErrorState { 1639 @Override enter()1640 public void enter() { 1641 Log.e(TAG, "Error in setIpForwardingEnabled"); 1642 notify(TetherInterfaceSM.CMD_IP_FORWARDING_ENABLE_ERROR); 1643 } 1644 } 1645 1646 class SetIpForwardingDisabledErrorState extends ErrorState { 1647 @Override enter()1648 public void enter() { 1649 Log.e(TAG, "Error in setIpForwardingDisabled"); 1650 notify(TetherInterfaceSM.CMD_IP_FORWARDING_DISABLE_ERROR); 1651 } 1652 } 1653 1654 class StartTetheringErrorState extends ErrorState { 1655 @Override enter()1656 public void enter() { 1657 Log.e(TAG, "Error in startTethering"); 1658 notify(TetherInterfaceSM.CMD_START_TETHERING_ERROR); 1659 try { 1660 mNMService.setIpForwardingEnabled(false); 1661 } catch (Exception e) {} 1662 } 1663 } 1664 1665 class StopTetheringErrorState extends ErrorState { 1666 @Override enter()1667 public void enter() { 1668 Log.e(TAG, "Error in stopTethering"); 1669 notify(TetherInterfaceSM.CMD_STOP_TETHERING_ERROR); 1670 try { 1671 mNMService.setIpForwardingEnabled(false); 1672 } catch (Exception e) {} 1673 } 1674 } 1675 1676 class SetDnsForwardersErrorState extends ErrorState { 1677 @Override enter()1678 public void enter() { 1679 Log.e(TAG, "Error in setDnsForwarders"); 1680 notify(TetherInterfaceSM.CMD_SET_DNS_FORWARDERS_ERROR); 1681 try { 1682 mNMService.stopTethering(); 1683 } catch (Exception e) {} 1684 try { 1685 mNMService.setIpForwardingEnabled(false); 1686 } catch (Exception e) {} 1687 } 1688 } 1689 } 1690 dump(FileDescriptor fd, PrintWriter writer, String[] args)1691 public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { 1692 final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " "); 1693 1694 if (mContext.checkCallingOrSelfPermission( 1695 android.Manifest.permission.DUMP) != PackageManager.PERMISSION_GRANTED) { 1696 pw.println("Permission Denial: can't dump ConnectivityService.Tether " + 1697 "from from pid=" + Binder.getCallingPid() + ", uid=" + 1698 Binder.getCallingUid()); 1699 return; 1700 } 1701 1702 pw.println("Tethering:"); 1703 pw.increaseIndent(); 1704 pw.print("mUpstreamIfaceTypes:"); 1705 synchronized (mPublicSync) { 1706 for (Integer netType : mUpstreamIfaceTypes) { 1707 pw.print(" " + ConnectivityManager.getNetworkTypeName(netType)); 1708 } 1709 pw.println(); 1710 1711 pw.println("Tether state:"); 1712 pw.increaseIndent(); 1713 for (Object o : mIfaces.values()) { 1714 pw.println(o); 1715 } 1716 pw.decreaseIndent(); 1717 } 1718 pw.decreaseIndent(); 1719 return; 1720 } 1721 } 1722