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