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