Tethering.java revision bfe61f696de3ceecda51612d3b26f20af33bc16c
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 113 private String[] mDhcpRange; 114 private static final String[] DHCP_DEFAULT_RANGE = { 115 "192.168.42.2", "192.168.42.254", "192.168.43.2", "192.168.43.254", 116 "192.168.44.2", "192.168.44.254", "192.168.45.2", "192.168.45.254", 117 "192.168.46.2", "192.168.46.254", "192.168.47.2", "192.168.47.254", 118 "192.168.48.2", "192.168.48.254", 119 }; 120 121 private String[] mDefaultDnsServers; 122 private static final String DNS_DEFAULT_SERVER1 = "8.8.8.8"; 123 private static final String DNS_DEFAULT_SERVER2 = "8.8.4.4"; 124 125 private StateMachine mTetherMasterSM; 126 127 private Notification mTetheredNotification; 128 129 private boolean mRndisEnabled; // track the RNDIS function enabled state 130 private boolean mUsbTetherRequested; // true if USB tethering should be started 131 // when RNDIS is enabled 132 133 public Tethering(Context context, INetworkManagementService nmService, 134 INetworkStatsService statsService, IConnectivityManager connService, Looper looper) { 135 mContext = context; 136 mNMService = nmService; 137 mStatsService = statsService; 138 mConnService = connService; 139 mLooper = looper; 140 141 mPublicSync = new Object(); 142 143 mIfaces = new HashMap<String, TetherInterfaceSM>(); 144 145 // make our own thread so we don't anr the system 146 mLooper = IoThread.get().getLooper(); 147 mTetherMasterSM = new TetherMasterSM("TetherMaster", mLooper); 148 mTetherMasterSM.start(); 149 150 mStateReceiver = new StateReceiver(); 151 IntentFilter filter = new IntentFilter(); 152 filter.addAction(UsbManager.ACTION_USB_STATE); 153 filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); 154 filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED); 155 mContext.registerReceiver(mStateReceiver, filter); 156 157 filter = new IntentFilter(); 158 filter.addAction(Intent.ACTION_MEDIA_SHARED); 159 filter.addAction(Intent.ACTION_MEDIA_UNSHARED); 160 filter.addDataScheme("file"); 161 mContext.registerReceiver(mStateReceiver, filter); 162 163 mDhcpRange = context.getResources().getStringArray( 164 com.android.internal.R.array.config_tether_dhcp_range); 165 if ((mDhcpRange.length == 0) || (mDhcpRange.length % 2 ==1)) { 166 mDhcpRange = DHCP_DEFAULT_RANGE; 167 } 168 169 // load device config info 170 updateConfiguration(); 171 172 // TODO - remove and rely on real notifications of the current iface 173 mDefaultDnsServers = new String[2]; 174 mDefaultDnsServers[0] = DNS_DEFAULT_SERVER1; 175 mDefaultDnsServers[1] = DNS_DEFAULT_SERVER2; 176 } 177 178 void updateConfiguration() { 179 String[] tetherableUsbRegexs = mContext.getResources().getStringArray( 180 com.android.internal.R.array.config_tether_usb_regexs); 181 String[] tetherableWifiRegexs = mContext.getResources().getStringArray( 182 com.android.internal.R.array.config_tether_wifi_regexs); 183 String[] tetherableBluetoothRegexs = mContext.getResources().getStringArray( 184 com.android.internal.R.array.config_tether_bluetooth_regexs); 185 186 int ifaceTypes[] = mContext.getResources().getIntArray( 187 com.android.internal.R.array.config_tether_upstream_types); 188 Collection<Integer> upstreamIfaceTypes = new ArrayList(); 189 for (int i : ifaceTypes) { 190 upstreamIfaceTypes.add(new Integer(i)); 191 } 192 193 synchronized (mPublicSync) { 194 mTetherableUsbRegexs = tetherableUsbRegexs; 195 mTetherableWifiRegexs = tetherableWifiRegexs; 196 mTetherableBluetoothRegexs = tetherableBluetoothRegexs; 197 mUpstreamIfaceTypes = upstreamIfaceTypes; 198 } 199 200 // check if the upstream type list needs to be modified due to secure-settings 201 checkDunRequired(); 202 } 203 204 public void interfaceStatusChanged(String iface, boolean up) { 205 if (VDBG) Log.d(TAG, "interfaceStatusChanged " + iface + ", " + up); 206 boolean found = false; 207 boolean usb = false; 208 synchronized (mPublicSync) { 209 if (isWifi(iface)) { 210 found = true; 211 } else if (isUsb(iface)) { 212 found = true; 213 usb = true; 214 } else if (isBluetooth(iface)) { 215 found = true; 216 } 217 if (found == false) return; 218 219 TetherInterfaceSM sm = mIfaces.get(iface); 220 if (up) { 221 if (sm == null) { 222 sm = new TetherInterfaceSM(iface, mLooper, usb); 223 mIfaces.put(iface, sm); 224 sm.start(); 225 } 226 } else { 227 if (isUsb(iface)) { 228 // ignore usb0 down after enabling RNDIS 229 // we will handle disconnect in interfaceRemoved instead 230 if (VDBG) Log.d(TAG, "ignore interface down for " + iface); 231 } else if (sm != null) { 232 sm.sendMessage(TetherInterfaceSM.CMD_INTERFACE_DOWN); 233 mIfaces.remove(iface); 234 } 235 } 236 } 237 } 238 239 public void interfaceLinkStateChanged(String iface, boolean up) { 240 if (VDBG) Log.d(TAG, "interfaceLinkStateChanged " + iface + ", " + up); 241 interfaceStatusChanged(iface, up); 242 } 243 244 private boolean isUsb(String iface) { 245 synchronized (mPublicSync) { 246 for (String regex : mTetherableUsbRegexs) { 247 if (iface.matches(regex)) return true; 248 } 249 return false; 250 } 251 } 252 253 public boolean isWifi(String iface) { 254 synchronized (mPublicSync) { 255 for (String regex : mTetherableWifiRegexs) { 256 if (iface.matches(regex)) return true; 257 } 258 return false; 259 } 260 } 261 262 public boolean isBluetooth(String iface) { 263 synchronized (mPublicSync) { 264 for (String regex : mTetherableBluetoothRegexs) { 265 if (iface.matches(regex)) return true; 266 } 267 return false; 268 } 269 } 270 271 public void interfaceAdded(String iface) { 272 if (VDBG) Log.d(TAG, "interfaceAdded " + iface); 273 boolean found = false; 274 boolean usb = false; 275 synchronized (mPublicSync) { 276 if (isWifi(iface)) { 277 found = true; 278 } 279 if (isUsb(iface)) { 280 found = true; 281 usb = true; 282 } 283 if (isBluetooth(iface)) { 284 found = true; 285 } 286 if (found == false) { 287 if (VDBG) Log.d(TAG, iface + " is not a tetherable iface, ignoring"); 288 return; 289 } 290 291 TetherInterfaceSM sm = mIfaces.get(iface); 292 if (sm != null) { 293 if (VDBG) Log.d(TAG, "active iface (" + iface + ") reported as added, ignoring"); 294 return; 295 } 296 sm = new TetherInterfaceSM(iface, mLooper, usb); 297 mIfaces.put(iface, sm); 298 sm.start(); 299 } 300 } 301 302 public void interfaceRemoved(String iface) { 303 if (VDBG) Log.d(TAG, "interfaceRemoved " + iface); 304 synchronized (mPublicSync) { 305 TetherInterfaceSM sm = mIfaces.get(iface); 306 if (sm == null) { 307 if (VDBG) { 308 Log.e(TAG, "attempting to remove unknown iface (" + iface + "), ignoring"); 309 } 310 return; 311 } 312 sm.sendMessage(TetherInterfaceSM.CMD_INTERFACE_DOWN); 313 mIfaces.remove(iface); 314 } 315 } 316 317 public int tether(String iface) { 318 if (DBG) Log.d(TAG, "Tethering " + iface); 319 TetherInterfaceSM sm = null; 320 synchronized (mPublicSync) { 321 sm = mIfaces.get(iface); 322 } 323 if (sm == null) { 324 Log.e(TAG, "Tried to Tether an unknown iface :" + iface + ", ignoring"); 325 return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE; 326 } 327 if (!sm.isAvailable() && !sm.isErrored()) { 328 Log.e(TAG, "Tried to Tether an unavailable iface :" + iface + ", ignoring"); 329 return ConnectivityManager.TETHER_ERROR_UNAVAIL_IFACE; 330 } 331 sm.sendMessage(TetherInterfaceSM.CMD_TETHER_REQUESTED); 332 return ConnectivityManager.TETHER_ERROR_NO_ERROR; 333 } 334 335 public int untether(String iface) { 336 if (DBG) Log.d(TAG, "Untethering " + iface); 337 TetherInterfaceSM sm = null; 338 synchronized (mPublicSync) { 339 sm = mIfaces.get(iface); 340 } 341 if (sm == null) { 342 Log.e(TAG, "Tried to Untether an unknown iface :" + iface + ", ignoring"); 343 return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE; 344 } 345 if (sm.isErrored()) { 346 Log.e(TAG, "Tried to Untethered an errored iface :" + iface + ", ignoring"); 347 return ConnectivityManager.TETHER_ERROR_UNAVAIL_IFACE; 348 } 349 sm.sendMessage(TetherInterfaceSM.CMD_TETHER_UNREQUESTED); 350 return ConnectivityManager.TETHER_ERROR_NO_ERROR; 351 } 352 353 public int getLastTetherError(String iface) { 354 TetherInterfaceSM sm = null; 355 synchronized (mPublicSync) { 356 sm = mIfaces.get(iface); 357 if (sm == null) { 358 Log.e(TAG, "Tried to getLastTetherError on an unknown iface :" + iface + 359 ", ignoring"); 360 return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE; 361 } 362 return sm.getLastError(); 363 } 364 } 365 366 // TODO - move all private methods used only by the state machine into the state machine 367 // to clarify what needs synchronized protection. 368 private void sendTetherStateChangedBroadcast() { 369 try { 370 if (!mConnService.isTetheringSupported()) return; 371 } catch (RemoteException e) { 372 return; 373 } 374 375 ArrayList<String> availableList = new ArrayList<String>(); 376 ArrayList<String> activeList = new ArrayList<String>(); 377 ArrayList<String> erroredList = new ArrayList<String>(); 378 379 boolean wifiTethered = false; 380 boolean usbTethered = false; 381 boolean bluetoothTethered = false; 382 383 synchronized (mPublicSync) { 384 Set ifaces = mIfaces.keySet(); 385 for (Object iface : ifaces) { 386 TetherInterfaceSM sm = mIfaces.get(iface); 387 if (sm != null) { 388 if (sm.isErrored()) { 389 erroredList.add((String)iface); 390 } else if (sm.isAvailable()) { 391 availableList.add((String)iface); 392 } else if (sm.isTethered()) { 393 if (isUsb((String)iface)) { 394 usbTethered = true; 395 } else if (isWifi((String)iface)) { 396 wifiTethered = true; 397 } else if (isBluetooth((String)iface)) { 398 bluetoothTethered = true; 399 } 400 activeList.add((String)iface); 401 } 402 } 403 } 404 } 405 Intent broadcast = new Intent(ConnectivityManager.ACTION_TETHER_STATE_CHANGED); 406 broadcast.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING | 407 Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 408 broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_AVAILABLE_TETHER, 409 availableList); 410 broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_ACTIVE_TETHER, activeList); 411 broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_ERRORED_TETHER, 412 erroredList); 413 mContext.sendStickyBroadcastAsUser(broadcast, UserHandle.ALL); 414 if (DBG) { 415 Log.d(TAG, "sendTetherStateChangedBroadcast " + availableList.size() + ", " + 416 activeList.size() + ", " + erroredList.size()); 417 } 418 419 if (usbTethered) { 420 if (wifiTethered || bluetoothTethered) { 421 showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_general); 422 } else { 423 showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_usb); 424 } 425 } else if (wifiTethered) { 426 if (bluetoothTethered) { 427 showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_general); 428 } else { 429 showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_wifi); 430 } 431 } else if (bluetoothTethered) { 432 showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_bluetooth); 433 } else { 434 clearTetheredNotification(); 435 } 436 } 437 438 private void showTetheredNotification(int icon) { 439 NotificationManager notificationManager = 440 (NotificationManager)mContext.getSystemService(Context.NOTIFICATION_SERVICE); 441 if (notificationManager == null) { 442 return; 443 } 444 445 if (mTetheredNotification != null) { 446 if (mTetheredNotification.icon == icon) { 447 return; 448 } 449 notificationManager.cancelAsUser(null, mTetheredNotification.icon, 450 UserHandle.ALL); 451 } 452 453 Intent intent = new Intent(); 454 intent.setClassName("com.android.settings", "com.android.settings.TetherSettings"); 455 intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY); 456 457 PendingIntent pi = PendingIntent.getActivityAsUser(mContext, 0, intent, 0, 458 null, UserHandle.CURRENT); 459 460 Resources r = Resources.getSystem(); 461 CharSequence title = r.getText(com.android.internal.R.string.tethered_notification_title); 462 CharSequence message = r.getText(com.android.internal.R.string. 463 tethered_notification_message); 464 465 if (mTetheredNotification == null) { 466 mTetheredNotification = new Notification(); 467 mTetheredNotification.when = 0; 468 } 469 mTetheredNotification.icon = icon; 470 mTetheredNotification.defaults &= ~Notification.DEFAULT_SOUND; 471 mTetheredNotification.flags = Notification.FLAG_ONGOING_EVENT; 472 mTetheredNotification.tickerText = title; 473 mTetheredNotification.visibility = Notification.VISIBILITY_PUBLIC; 474 mTetheredNotification.setLatestEventInfo(mContext, title, message, pi); 475 476 notificationManager.notifyAsUser(null, mTetheredNotification.icon, 477 mTetheredNotification, UserHandle.ALL); 478 } 479 480 private void clearTetheredNotification() { 481 NotificationManager notificationManager = 482 (NotificationManager)mContext.getSystemService(Context.NOTIFICATION_SERVICE); 483 if (notificationManager != null && mTetheredNotification != null) { 484 notificationManager.cancelAsUser(null, mTetheredNotification.icon, 485 UserHandle.ALL); 486 mTetheredNotification = null; 487 } 488 } 489 490 private class StateReceiver extends BroadcastReceiver { 491 public void onReceive(Context content, Intent intent) { 492 String action = intent.getAction(); 493 if (action.equals(UsbManager.ACTION_USB_STATE)) { 494 synchronized (Tethering.this.mPublicSync) { 495 boolean usbConnected = intent.getBooleanExtra(UsbManager.USB_CONNECTED, false); 496 mRndisEnabled = intent.getBooleanExtra(UsbManager.USB_FUNCTION_RNDIS, false); 497 // start tethering if we have a request pending 498 if (usbConnected && mRndisEnabled && mUsbTetherRequested) { 499 tetherUsb(true); 500 } 501 mUsbTetherRequested = false; 502 } 503 } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) { 504 NetworkInfo networkInfo = (NetworkInfo)intent.getParcelableExtra( 505 ConnectivityManager.EXTRA_NETWORK_INFO); 506 if (networkInfo != null && 507 networkInfo.getDetailedState() != NetworkInfo.DetailedState.FAILED) { 508 if (VDBG) Log.d(TAG, "Tethering got CONNECTIVITY_ACTION"); 509 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_UPSTREAM_CHANGED); 510 } 511 } else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) { 512 updateConfiguration(); 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(); // TODO - remove? 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.Global.getInt(mContext.getContentResolver(), 627 Settings.Global.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[] getTetherableIfaces() { 684 ArrayList<String> list = new ArrayList<String>(); 685 synchronized (mPublicSync) { 686 Set keys = mIfaces.keySet(); 687 for (Object key : keys) { 688 TetherInterfaceSM sm = mIfaces.get(key); 689 if (sm.isAvailable()) { 690 list.add((String)key); 691 } 692 } 693 } 694 String[] retVal = new String[list.size()]; 695 for (int i=0; i < list.size(); i++) { 696 retVal[i] = list.get(i); 697 } 698 return retVal; 699 } 700 701 public String[] getErroredIfaces() { 702 ArrayList<String> list = new ArrayList<String>(); 703 synchronized (mPublicSync) { 704 Set keys = mIfaces.keySet(); 705 for (Object key : keys) { 706 TetherInterfaceSM sm = mIfaces.get(key); 707 if (sm.isErrored()) { 708 list.add((String)key); 709 } 710 } 711 } 712 String[] retVal = new String[list.size()]; 713 for (int i= 0; i< list.size(); i++) { 714 retVal[i] = list.get(i); 715 } 716 return retVal; 717 } 718 719 //TODO: Temporary handling upstream change triggered without 720 // CONNECTIVITY_ACTION. Only to accomodate interface 721 // switch during HO. 722 // @see bug/4455071 723 public void handleTetherIfaceChange() { 724 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_UPSTREAM_CHANGED); 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.getLinkProperties(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.getDnses(); 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