Tethering.java revision df2b878ff4e7b4a258588d3a93574c399db78a07
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 mTetheredNotification.category = Notification.CATEGORY_STATUS; 476 477 notificationManager.notifyAsUser(null, mTetheredNotification.icon, 478 mTetheredNotification, UserHandle.ALL); 479 } 480 481 private void clearTetheredNotification() { 482 NotificationManager notificationManager = 483 (NotificationManager)mContext.getSystemService(Context.NOTIFICATION_SERVICE); 484 if (notificationManager != null && mTetheredNotification != null) { 485 notificationManager.cancelAsUser(null, mTetheredNotification.icon, 486 UserHandle.ALL); 487 mTetheredNotification = null; 488 } 489 } 490 491 private class StateReceiver extends BroadcastReceiver { 492 @Override 493 public void onReceive(Context content, Intent intent) { 494 String action = intent.getAction(); 495 if (action == null) { return; } 496 if (action.equals(UsbManager.ACTION_USB_STATE)) { 497 synchronized (Tethering.this.mPublicSync) { 498 boolean usbConnected = intent.getBooleanExtra(UsbManager.USB_CONNECTED, false); 499 mRndisEnabled = intent.getBooleanExtra(UsbManager.USB_FUNCTION_RNDIS, false); 500 // start tethering if we have a request pending 501 if (usbConnected && mRndisEnabled && mUsbTetherRequested) { 502 tetherUsb(true); 503 } 504 mUsbTetherRequested = false; 505 } 506 } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) { 507 NetworkInfo networkInfo = (NetworkInfo)intent.getParcelableExtra( 508 ConnectivityManager.EXTRA_NETWORK_INFO); 509 if (networkInfo != null && 510 networkInfo.getDetailedState() != NetworkInfo.DetailedState.FAILED) { 511 if (VDBG) Log.d(TAG, "Tethering got CONNECTIVITY_ACTION"); 512 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_UPSTREAM_CHANGED); 513 } 514 } else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) { 515 updateConfiguration(); 516 } 517 } 518 } 519 520 private void tetherUsb(boolean enable) { 521 if (VDBG) Log.d(TAG, "tetherUsb " + enable); 522 523 String[] ifaces = new String[0]; 524 try { 525 ifaces = mNMService.listInterfaces(); 526 } catch (Exception e) { 527 Log.e(TAG, "Error listing Interfaces", e); 528 return; 529 } 530 for (String iface : ifaces) { 531 if (isUsb(iface)) { 532 int result = (enable ? tether(iface) : untether(iface)); 533 if (result == ConnectivityManager.TETHER_ERROR_NO_ERROR) { 534 return; 535 } 536 } 537 } 538 Log.e(TAG, "unable start or stop USB tethering"); 539 } 540 541 // configured when we start tethering and unconfig'd on error or conclusion 542 private boolean configureUsbIface(boolean enabled) { 543 if (VDBG) Log.d(TAG, "configureUsbIface(" + enabled + ")"); 544 545 // toggle the USB interfaces 546 String[] ifaces = new String[0]; 547 try { 548 ifaces = mNMService.listInterfaces(); 549 } catch (Exception e) { 550 Log.e(TAG, "Error listing Interfaces", e); 551 return false; 552 } 553 for (String iface : ifaces) { 554 if (isUsb(iface)) { 555 InterfaceConfiguration ifcg = null; 556 try { 557 ifcg = mNMService.getInterfaceConfig(iface); 558 if (ifcg != null) { 559 InetAddress addr = NetworkUtils.numericToInetAddress(USB_NEAR_IFACE_ADDR); 560 ifcg.setLinkAddress(new LinkAddress(addr, USB_PREFIX_LENGTH)); 561 if (enabled) { 562 ifcg.setInterfaceUp(); 563 } else { 564 ifcg.setInterfaceDown(); 565 } 566 ifcg.clearFlag("running"); 567 mNMService.setInterfaceConfig(iface, ifcg); 568 } 569 } catch (Exception e) { 570 Log.e(TAG, "Error configuring interface " + iface, e); 571 return false; 572 } 573 } 574 } 575 576 return true; 577 } 578 579 // TODO - return copies so people can't tamper 580 public String[] getTetherableUsbRegexs() { 581 return mTetherableUsbRegexs; 582 } 583 584 public String[] getTetherableWifiRegexs() { 585 return mTetherableWifiRegexs; 586 } 587 588 public String[] getTetherableBluetoothRegexs() { 589 return mTetherableBluetoothRegexs; 590 } 591 592 public int setUsbTethering(boolean enable) { 593 if (VDBG) Log.d(TAG, "setUsbTethering(" + enable + ")"); 594 UsbManager usbManager = (UsbManager)mContext.getSystemService(Context.USB_SERVICE); 595 596 synchronized (mPublicSync) { 597 if (enable) { 598 if (mRndisEnabled) { 599 tetherUsb(true); 600 } else { 601 mUsbTetherRequested = true; 602 usbManager.setCurrentFunction(UsbManager.USB_FUNCTION_RNDIS, false); 603 } 604 } else { 605 tetherUsb(false); 606 if (mRndisEnabled) { 607 usbManager.setCurrentFunction(null, false); 608 } 609 mUsbTetherRequested = false; 610 } 611 } 612 return ConnectivityManager.TETHER_ERROR_NO_ERROR; 613 } 614 615 public int[] getUpstreamIfaceTypes() { 616 int values[]; 617 synchronized (mPublicSync) { 618 updateConfiguration(); // TODO - remove? 619 values = new int[mUpstreamIfaceTypes.size()]; 620 Iterator<Integer> iterator = mUpstreamIfaceTypes.iterator(); 621 for (int i=0; i < mUpstreamIfaceTypes.size(); i++) { 622 values[i] = iterator.next(); 623 } 624 } 625 return values; 626 } 627 628 public void checkDunRequired() { 629 int secureSetting = Settings.Global.getInt(mContext.getContentResolver(), 630 Settings.Global.TETHER_DUN_REQUIRED, 2); 631 synchronized (mPublicSync) { 632 // 2 = not set, 0 = DUN not required, 1 = DUN required 633 if (secureSetting != 2) { 634 int requiredApn = (secureSetting == 1 ? 635 ConnectivityManager.TYPE_MOBILE_DUN : 636 ConnectivityManager.TYPE_MOBILE_HIPRI); 637 if (requiredApn == ConnectivityManager.TYPE_MOBILE_DUN) { 638 while (mUpstreamIfaceTypes.contains(MOBILE_TYPE)) { 639 mUpstreamIfaceTypes.remove(MOBILE_TYPE); 640 } 641 while (mUpstreamIfaceTypes.contains(HIPRI_TYPE)) { 642 mUpstreamIfaceTypes.remove(HIPRI_TYPE); 643 } 644 if (mUpstreamIfaceTypes.contains(DUN_TYPE) == false) { 645 mUpstreamIfaceTypes.add(DUN_TYPE); 646 } 647 } else { 648 while (mUpstreamIfaceTypes.contains(DUN_TYPE)) { 649 mUpstreamIfaceTypes.remove(DUN_TYPE); 650 } 651 if (mUpstreamIfaceTypes.contains(MOBILE_TYPE) == false) { 652 mUpstreamIfaceTypes.add(MOBILE_TYPE); 653 } 654 if (mUpstreamIfaceTypes.contains(HIPRI_TYPE) == false) { 655 mUpstreamIfaceTypes.add(HIPRI_TYPE); 656 } 657 } 658 } 659 if (mUpstreamIfaceTypes.contains(DUN_TYPE)) { 660 mPreferredUpstreamMobileApn = ConnectivityManager.TYPE_MOBILE_DUN; 661 } else { 662 mPreferredUpstreamMobileApn = ConnectivityManager.TYPE_MOBILE_HIPRI; 663 } 664 } 665 } 666 667 // TODO review API - maybe return ArrayList<String> here and below? 668 public String[] getTetheredIfaces() { 669 ArrayList<String> list = new ArrayList<String>(); 670 synchronized (mPublicSync) { 671 Set keys = mIfaces.keySet(); 672 for (Object key : keys) { 673 TetherInterfaceSM sm = mIfaces.get(key); 674 if (sm.isTethered()) { 675 list.add((String)key); 676 } 677 } 678 } 679 String[] retVal = new String[list.size()]; 680 for (int i=0; i < list.size(); i++) { 681 retVal[i] = list.get(i); 682 } 683 return retVal; 684 } 685 686 public String[] getTetherableIfaces() { 687 ArrayList<String> list = new ArrayList<String>(); 688 synchronized (mPublicSync) { 689 Set keys = mIfaces.keySet(); 690 for (Object key : keys) { 691 TetherInterfaceSM sm = mIfaces.get(key); 692 if (sm.isAvailable()) { 693 list.add((String)key); 694 } 695 } 696 } 697 String[] retVal = new String[list.size()]; 698 for (int i=0; i < list.size(); i++) { 699 retVal[i] = list.get(i); 700 } 701 return retVal; 702 } 703 704 public String[] getErroredIfaces() { 705 ArrayList<String> list = new ArrayList<String>(); 706 synchronized (mPublicSync) { 707 Set keys = mIfaces.keySet(); 708 for (Object key : keys) { 709 TetherInterfaceSM sm = mIfaces.get(key); 710 if (sm.isErrored()) { 711 list.add((String)key); 712 } 713 } 714 } 715 String[] retVal = new String[list.size()]; 716 for (int i= 0; i< list.size(); i++) { 717 retVal[i] = list.get(i); 718 } 719 return retVal; 720 } 721 722 //TODO: Temporary handling upstream change triggered without 723 // CONNECTIVITY_ACTION. Only to accomodate interface 724 // switch during HO. 725 // @see bug/4455071 726 public void handleTetherIfaceChange() { 727 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_UPSTREAM_CHANGED); 728 } 729 730 class TetherInterfaceSM extends StateMachine { 731 // notification from the master SM that it's not in tether mode 732 static final int CMD_TETHER_MODE_DEAD = 1; 733 // request from the user that it wants to tether 734 static final int CMD_TETHER_REQUESTED = 2; 735 // request from the user that it wants to untether 736 static final int CMD_TETHER_UNREQUESTED = 3; 737 // notification that this interface is down 738 static final int CMD_INTERFACE_DOWN = 4; 739 // notification that this interface is up 740 static final int CMD_INTERFACE_UP = 5; 741 // notification from the master SM that it had an error turning on cellular dun 742 static final int CMD_CELL_DUN_ERROR = 6; 743 // notification from the master SM that it had trouble enabling IP Forwarding 744 static final int CMD_IP_FORWARDING_ENABLE_ERROR = 7; 745 // notification from the master SM that it had trouble disabling IP Forwarding 746 static final int CMD_IP_FORWARDING_DISABLE_ERROR = 8; 747 // notification from the master SM that it had trouble staring tethering 748 static final int CMD_START_TETHERING_ERROR = 9; 749 // notification from the master SM that it had trouble stopping tethering 750 static final int CMD_STOP_TETHERING_ERROR = 10; 751 // notification from the master SM that it had trouble setting the DNS forwarders 752 static final int CMD_SET_DNS_FORWARDERS_ERROR = 11; 753 // the upstream connection has changed 754 static final int CMD_TETHER_CONNECTION_CHANGED = 12; 755 756 private State mDefaultState; 757 758 private State mInitialState; 759 private State mStartingState; 760 private State mTetheredState; 761 762 private State mUnavailableState; 763 764 private boolean mAvailable; 765 private boolean mTethered; 766 int mLastError; 767 768 String mIfaceName; 769 String mMyUpstreamIfaceName; // may change over time 770 771 boolean mUsb; 772 773 TetherInterfaceSM(String name, Looper looper, boolean usb) { 774 super(name, looper); 775 mIfaceName = name; 776 mUsb = usb; 777 setLastError(ConnectivityManager.TETHER_ERROR_NO_ERROR); 778 779 mInitialState = new InitialState(); 780 addState(mInitialState); 781 mStartingState = new StartingState(); 782 addState(mStartingState); 783 mTetheredState = new TetheredState(); 784 addState(mTetheredState); 785 mUnavailableState = new UnavailableState(); 786 addState(mUnavailableState); 787 788 setInitialState(mInitialState); 789 } 790 791 public String toString() { 792 String res = new String(); 793 res += mIfaceName + " - "; 794 IState current = getCurrentState(); 795 if (current == mInitialState) res += "InitialState"; 796 if (current == mStartingState) res += "StartingState"; 797 if (current == mTetheredState) res += "TetheredState"; 798 if (current == mUnavailableState) res += "UnavailableState"; 799 if (mAvailable) res += " - Available"; 800 if (mTethered) res += " - Tethered"; 801 res += " - lastError =" + mLastError; 802 return res; 803 } 804 805 public int getLastError() { 806 synchronized (Tethering.this.mPublicSync) { 807 return mLastError; 808 } 809 } 810 811 private void setLastError(int error) { 812 synchronized (Tethering.this.mPublicSync) { 813 mLastError = error; 814 815 if (isErrored()) { 816 if (mUsb) { 817 // note everything's been unwound by this point so nothing to do on 818 // further error.. 819 Tethering.this.configureUsbIface(false); 820 } 821 } 822 } 823 } 824 825 public boolean isAvailable() { 826 synchronized (Tethering.this.mPublicSync) { 827 return mAvailable; 828 } 829 } 830 831 private void setAvailable(boolean available) { 832 synchronized (Tethering.this.mPublicSync) { 833 mAvailable = available; 834 } 835 } 836 837 public boolean isTethered() { 838 synchronized (Tethering.this.mPublicSync) { 839 return mTethered; 840 } 841 } 842 843 private void setTethered(boolean tethered) { 844 synchronized (Tethering.this.mPublicSync) { 845 mTethered = tethered; 846 } 847 } 848 849 public boolean isErrored() { 850 synchronized (Tethering.this.mPublicSync) { 851 return (mLastError != ConnectivityManager.TETHER_ERROR_NO_ERROR); 852 } 853 } 854 855 class InitialState extends State { 856 @Override 857 public void enter() { 858 setAvailable(true); 859 setTethered(false); 860 sendTetherStateChangedBroadcast(); 861 } 862 863 @Override 864 public boolean processMessage(Message message) { 865 if (DBG) Log.d(TAG, "InitialState.processMessage what=" + message.what); 866 boolean retValue = true; 867 switch (message.what) { 868 case CMD_TETHER_REQUESTED: 869 setLastError(ConnectivityManager.TETHER_ERROR_NO_ERROR); 870 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_REQUESTED, 871 TetherInterfaceSM.this); 872 transitionTo(mStartingState); 873 break; 874 case CMD_INTERFACE_DOWN: 875 transitionTo(mUnavailableState); 876 break; 877 default: 878 retValue = false; 879 break; 880 } 881 return retValue; 882 } 883 } 884 885 class StartingState extends State { 886 @Override 887 public void enter() { 888 setAvailable(false); 889 if (mUsb) { 890 if (!Tethering.this.configureUsbIface(true)) { 891 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED, 892 TetherInterfaceSM.this); 893 setLastError(ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR); 894 895 transitionTo(mInitialState); 896 return; 897 } 898 } 899 sendTetherStateChangedBroadcast(); 900 901 // Skipping StartingState 902 transitionTo(mTetheredState); 903 } 904 @Override 905 public boolean processMessage(Message message) { 906 if (DBG) Log.d(TAG, "StartingState.processMessage what=" + message.what); 907 boolean retValue = true; 908 switch (message.what) { 909 // maybe a parent class? 910 case CMD_TETHER_UNREQUESTED: 911 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED, 912 TetherInterfaceSM.this); 913 if (mUsb) { 914 if (!Tethering.this.configureUsbIface(false)) { 915 setLastErrorAndTransitionToInitialState( 916 ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR); 917 break; 918 } 919 } 920 transitionTo(mInitialState); 921 break; 922 case CMD_CELL_DUN_ERROR: 923 case CMD_IP_FORWARDING_ENABLE_ERROR: 924 case CMD_IP_FORWARDING_DISABLE_ERROR: 925 case CMD_START_TETHERING_ERROR: 926 case CMD_STOP_TETHERING_ERROR: 927 case CMD_SET_DNS_FORWARDERS_ERROR: 928 setLastErrorAndTransitionToInitialState( 929 ConnectivityManager.TETHER_ERROR_MASTER_ERROR); 930 break; 931 case CMD_INTERFACE_DOWN: 932 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED, 933 TetherInterfaceSM.this); 934 transitionTo(mUnavailableState); 935 break; 936 default: 937 retValue = false; 938 } 939 return retValue; 940 } 941 } 942 943 class TetheredState extends State { 944 @Override 945 public void enter() { 946 try { 947 mNMService.tetherInterface(mIfaceName); 948 } catch (Exception e) { 949 Log.e(TAG, "Error Tethering: " + e.toString()); 950 setLastError(ConnectivityManager.TETHER_ERROR_TETHER_IFACE_ERROR); 951 952 transitionTo(mInitialState); 953 return; 954 } 955 if (DBG) Log.d(TAG, "Tethered " + mIfaceName); 956 setAvailable(false); 957 setTethered(true); 958 sendTetherStateChangedBroadcast(); 959 } 960 961 private void cleanupUpstream() { 962 if (mMyUpstreamIfaceName != null) { 963 // note that we don't care about errors here. 964 // sometimes interfaces are gone before we get 965 // to remove their rules, which generates errors. 966 // just do the best we can. 967 try { 968 // about to tear down NAT; gather remaining statistics 969 mStatsService.forceUpdate(); 970 } catch (Exception e) { 971 if (VDBG) Log.e(TAG, "Exception in forceUpdate: " + e.toString()); 972 } 973 try { 974 mNMService.disableNat(mIfaceName, mMyUpstreamIfaceName); 975 } catch (Exception e) { 976 if (VDBG) Log.e(TAG, "Exception in disableNat: " + e.toString()); 977 } 978 mMyUpstreamIfaceName = null; 979 } 980 return; 981 } 982 983 @Override 984 public boolean processMessage(Message message) { 985 if (DBG) Log.d(TAG, "TetheredState.processMessage what=" + message.what); 986 boolean retValue = true; 987 boolean error = false; 988 switch (message.what) { 989 case CMD_TETHER_UNREQUESTED: 990 case CMD_INTERFACE_DOWN: 991 cleanupUpstream(); 992 try { 993 mNMService.untetherInterface(mIfaceName); 994 } catch (Exception e) { 995 setLastErrorAndTransitionToInitialState( 996 ConnectivityManager.TETHER_ERROR_UNTETHER_IFACE_ERROR); 997 break; 998 } 999 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED, 1000 TetherInterfaceSM.this); 1001 if (message.what == CMD_TETHER_UNREQUESTED) { 1002 if (mUsb) { 1003 if (!Tethering.this.configureUsbIface(false)) { 1004 setLastError( 1005 ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR); 1006 } 1007 } 1008 transitionTo(mInitialState); 1009 } else if (message.what == CMD_INTERFACE_DOWN) { 1010 transitionTo(mUnavailableState); 1011 } 1012 if (DBG) Log.d(TAG, "Untethered " + mIfaceName); 1013 break; 1014 case CMD_TETHER_CONNECTION_CHANGED: 1015 String newUpstreamIfaceName = (String)(message.obj); 1016 if ((mMyUpstreamIfaceName == null && newUpstreamIfaceName == null) || 1017 (mMyUpstreamIfaceName != null && 1018 mMyUpstreamIfaceName.equals(newUpstreamIfaceName))) { 1019 if (VDBG) Log.d(TAG, "Connection changed noop - dropping"); 1020 break; 1021 } 1022 cleanupUpstream(); 1023 if (newUpstreamIfaceName != null) { 1024 try { 1025 mNMService.enableNat(mIfaceName, newUpstreamIfaceName); 1026 } catch (Exception e) { 1027 Log.e(TAG, "Exception enabling Nat: " + e.toString()); 1028 try { 1029 mNMService.untetherInterface(mIfaceName); 1030 } catch (Exception ee) {} 1031 1032 setLastError(ConnectivityManager.TETHER_ERROR_ENABLE_NAT_ERROR); 1033 transitionTo(mInitialState); 1034 return true; 1035 } 1036 } 1037 mMyUpstreamIfaceName = newUpstreamIfaceName; 1038 break; 1039 case CMD_CELL_DUN_ERROR: 1040 case CMD_IP_FORWARDING_ENABLE_ERROR: 1041 case CMD_IP_FORWARDING_DISABLE_ERROR: 1042 case CMD_START_TETHERING_ERROR: 1043 case CMD_STOP_TETHERING_ERROR: 1044 case CMD_SET_DNS_FORWARDERS_ERROR: 1045 error = true; 1046 // fall through 1047 case CMD_TETHER_MODE_DEAD: 1048 cleanupUpstream(); 1049 try { 1050 mNMService.untetherInterface(mIfaceName); 1051 } catch (Exception e) { 1052 setLastErrorAndTransitionToInitialState( 1053 ConnectivityManager.TETHER_ERROR_UNTETHER_IFACE_ERROR); 1054 break; 1055 } 1056 if (error) { 1057 setLastErrorAndTransitionToInitialState( 1058 ConnectivityManager.TETHER_ERROR_MASTER_ERROR); 1059 break; 1060 } 1061 if (DBG) Log.d(TAG, "Tether lost upstream connection " + mIfaceName); 1062 sendTetherStateChangedBroadcast(); 1063 if (mUsb) { 1064 if (!Tethering.this.configureUsbIface(false)) { 1065 setLastError(ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR); 1066 } 1067 } 1068 transitionTo(mInitialState); 1069 break; 1070 default: 1071 retValue = false; 1072 break; 1073 } 1074 return retValue; 1075 } 1076 } 1077 1078 class UnavailableState extends State { 1079 @Override 1080 public void enter() { 1081 setAvailable(false); 1082 setLastError(ConnectivityManager.TETHER_ERROR_NO_ERROR); 1083 setTethered(false); 1084 sendTetherStateChangedBroadcast(); 1085 } 1086 @Override 1087 public boolean processMessage(Message message) { 1088 boolean retValue = true; 1089 switch (message.what) { 1090 case CMD_INTERFACE_UP: 1091 transitionTo(mInitialState); 1092 break; 1093 default: 1094 retValue = false; 1095 break; 1096 } 1097 return retValue; 1098 } 1099 } 1100 1101 void setLastErrorAndTransitionToInitialState(int error) { 1102 setLastError(error); 1103 transitionTo(mInitialState); 1104 } 1105 1106 } 1107 1108 class TetherMasterSM extends StateMachine { 1109 // an interface SM has requested Tethering 1110 static final int CMD_TETHER_MODE_REQUESTED = 1; 1111 // an interface SM has unrequested Tethering 1112 static final int CMD_TETHER_MODE_UNREQUESTED = 2; 1113 // upstream connection change - do the right thing 1114 static final int CMD_UPSTREAM_CHANGED = 3; 1115 // we received notice that the cellular DUN connection is up 1116 static final int CMD_CELL_CONNECTION_RENEW = 4; 1117 // we don't have a valid upstream conn, check again after a delay 1118 static final int CMD_RETRY_UPSTREAM = 5; 1119 1120 // This indicates what a timeout event relates to. A state that 1121 // sends itself a delayed timeout event and handles incoming timeout events 1122 // should inc this when it is entered and whenever it sends a new timeout event. 1123 // We do not flush the old ones. 1124 private int mSequenceNumber; 1125 1126 private State mInitialState; 1127 private State mTetherModeAliveState; 1128 1129 private State mSetIpForwardingEnabledErrorState; 1130 private State mSetIpForwardingDisabledErrorState; 1131 private State mStartTetheringErrorState; 1132 private State mStopTetheringErrorState; 1133 private State mSetDnsForwardersErrorState; 1134 1135 private ArrayList<TetherInterfaceSM> mNotifyList; 1136 1137 private int mCurrentConnectionSequence; 1138 private int mMobileApnReserved = ConnectivityManager.TYPE_NONE; 1139 1140 private String mUpstreamIfaceName = null; 1141 1142 private static final int UPSTREAM_SETTLE_TIME_MS = 10000; 1143 private static final int CELL_CONNECTION_RENEW_MS = 40000; 1144 1145 TetherMasterSM(String name, Looper looper) { 1146 super(name, looper); 1147 1148 //Add states 1149 mInitialState = new InitialState(); 1150 addState(mInitialState); 1151 mTetherModeAliveState = new TetherModeAliveState(); 1152 addState(mTetherModeAliveState); 1153 1154 mSetIpForwardingEnabledErrorState = new SetIpForwardingEnabledErrorState(); 1155 addState(mSetIpForwardingEnabledErrorState); 1156 mSetIpForwardingDisabledErrorState = new SetIpForwardingDisabledErrorState(); 1157 addState(mSetIpForwardingDisabledErrorState); 1158 mStartTetheringErrorState = new StartTetheringErrorState(); 1159 addState(mStartTetheringErrorState); 1160 mStopTetheringErrorState = new StopTetheringErrorState(); 1161 addState(mStopTetheringErrorState); 1162 mSetDnsForwardersErrorState = new SetDnsForwardersErrorState(); 1163 addState(mSetDnsForwardersErrorState); 1164 1165 mNotifyList = new ArrayList<TetherInterfaceSM>(); 1166 setInitialState(mInitialState); 1167 } 1168 1169 class TetherMasterUtilState extends State { 1170 protected final static boolean TRY_TO_SETUP_MOBILE_CONNECTION = true; 1171 protected final static boolean WAIT_FOR_NETWORK_TO_SETTLE = false; 1172 1173 @Override 1174 public boolean processMessage(Message m) { 1175 return false; 1176 } 1177 protected String enableString(int apnType) { 1178 switch (apnType) { 1179 case ConnectivityManager.TYPE_MOBILE_DUN: 1180 return Phone.FEATURE_ENABLE_DUN_ALWAYS; 1181 case ConnectivityManager.TYPE_MOBILE: 1182 case ConnectivityManager.TYPE_MOBILE_HIPRI: 1183 return Phone.FEATURE_ENABLE_HIPRI; 1184 } 1185 return null; 1186 } 1187 protected boolean turnOnUpstreamMobileConnection(int apnType) { 1188 boolean retValue = true; 1189 if (apnType == ConnectivityManager.TYPE_NONE) return false; 1190 if (apnType != mMobileApnReserved) turnOffUpstreamMobileConnection(); 1191 int result = PhoneConstants.APN_REQUEST_FAILED; 1192 String enableString = enableString(apnType); 1193 if (enableString == null) return false; 1194 try { 1195 result = mConnService.startUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE, 1196 enableString, new Binder()); 1197 } catch (Exception e) { 1198 } 1199 switch (result) { 1200 case PhoneConstants.APN_ALREADY_ACTIVE: 1201 case PhoneConstants.APN_REQUEST_STARTED: 1202 mMobileApnReserved = apnType; 1203 Message m = obtainMessage(CMD_CELL_CONNECTION_RENEW); 1204 m.arg1 = ++mCurrentConnectionSequence; 1205 sendMessageDelayed(m, CELL_CONNECTION_RENEW_MS); 1206 break; 1207 case PhoneConstants.APN_REQUEST_FAILED: 1208 default: 1209 retValue = false; 1210 break; 1211 } 1212 1213 return retValue; 1214 } 1215 protected boolean turnOffUpstreamMobileConnection() { 1216 // ignore pending renewal requests 1217 ++mCurrentConnectionSequence; 1218 if (mMobileApnReserved != ConnectivityManager.TYPE_NONE) { 1219 try { 1220 mConnService.stopUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE, 1221 enableString(mMobileApnReserved)); 1222 } catch (Exception e) { 1223 return false; 1224 } 1225 mMobileApnReserved = ConnectivityManager.TYPE_NONE; 1226 } 1227 return true; 1228 } 1229 protected boolean turnOnMasterTetherSettings() { 1230 try { 1231 mNMService.setIpForwardingEnabled(true); 1232 } catch (Exception e) { 1233 transitionTo(mSetIpForwardingEnabledErrorState); 1234 return false; 1235 } 1236 try { 1237 mNMService.startTethering(mDhcpRange); 1238 } catch (Exception e) { 1239 try { 1240 mNMService.stopTethering(); 1241 mNMService.startTethering(mDhcpRange); 1242 } catch (Exception ee) { 1243 transitionTo(mStartTetheringErrorState); 1244 return false; 1245 } 1246 } 1247 try { 1248 mNMService.setDnsForwarders(mDefaultDnsServers); 1249 } catch (Exception e) { 1250 transitionTo(mSetDnsForwardersErrorState); 1251 return false; 1252 } 1253 return true; 1254 } 1255 protected boolean turnOffMasterTetherSettings() { 1256 try { 1257 mNMService.stopTethering(); 1258 } catch (Exception e) { 1259 transitionTo(mStopTetheringErrorState); 1260 return false; 1261 } 1262 try { 1263 mNMService.setIpForwardingEnabled(false); 1264 } catch (Exception e) { 1265 transitionTo(mSetIpForwardingDisabledErrorState); 1266 return false; 1267 } 1268 transitionTo(mInitialState); 1269 return true; 1270 } 1271 1272 protected void chooseUpstreamType(boolean tryCell) { 1273 int upType = ConnectivityManager.TYPE_NONE; 1274 String iface = null; 1275 1276 updateConfiguration(); // TODO - remove? 1277 1278 synchronized (mPublicSync) { 1279 if (VDBG) { 1280 Log.d(TAG, "chooseUpstreamType has upstream iface types:"); 1281 for (Integer netType : mUpstreamIfaceTypes) { 1282 Log.d(TAG, " " + netType); 1283 } 1284 } 1285 1286 for (Integer netType : mUpstreamIfaceTypes) { 1287 NetworkInfo info = null; 1288 try { 1289 info = mConnService.getNetworkInfo(netType.intValue()); 1290 } catch (RemoteException e) { } 1291 if ((info != null) && info.isConnected()) { 1292 upType = netType.intValue(); 1293 break; 1294 } 1295 } 1296 } 1297 1298 if (DBG) { 1299 Log.d(TAG, "chooseUpstreamType(" + tryCell + "), preferredApn =" 1300 + mPreferredUpstreamMobileApn + ", got type=" + upType); 1301 } 1302 1303 // if we're on DUN, put our own grab on it 1304 if (upType == ConnectivityManager.TYPE_MOBILE_DUN || 1305 upType == ConnectivityManager.TYPE_MOBILE_HIPRI) { 1306 turnOnUpstreamMobileConnection(upType); 1307 } else if (upType != ConnectivityManager.TYPE_NONE) { 1308 /* If we've found an active upstream connection that's not DUN/HIPRI 1309 * we should stop any outstanding DUN/HIPRI start requests. 1310 * 1311 * If we found NONE we don't want to do this as we want any previous 1312 * requests to keep trying to bring up something we can use. 1313 */ 1314 turnOffUpstreamMobileConnection(); 1315 } 1316 1317 if (upType == ConnectivityManager.TYPE_NONE) { 1318 boolean tryAgainLater = true; 1319 if ((tryCell == TRY_TO_SETUP_MOBILE_CONNECTION) && 1320 (turnOnUpstreamMobileConnection(mPreferredUpstreamMobileApn) == true)) { 1321 // we think mobile should be coming up - don't set a retry 1322 tryAgainLater = false; 1323 } 1324 if (tryAgainLater) { 1325 sendMessageDelayed(CMD_RETRY_UPSTREAM, UPSTREAM_SETTLE_TIME_MS); 1326 } 1327 } else { 1328 LinkProperties linkProperties = null; 1329 try { 1330 linkProperties = mConnService.getLinkPropertiesForType(upType); 1331 } catch (RemoteException e) { } 1332 if (linkProperties != null) { 1333 // Find the interface with the default IPv4 route. It may be the 1334 // interface described by linkProperties, or one of the interfaces 1335 // stacked on top of it. 1336 Log.i(TAG, "Finding IPv4 upstream interface on: " + linkProperties); 1337 RouteInfo ipv4Default = RouteInfo.selectBestRoute( 1338 linkProperties.getAllRoutes(), Inet4Address.ANY); 1339 if (ipv4Default != null) { 1340 iface = ipv4Default.getInterface(); 1341 Log.i(TAG, "Found interface " + ipv4Default.getInterface()); 1342 } else { 1343 Log.i(TAG, "No IPv4 upstream interface, giving up."); 1344 } 1345 } 1346 1347 if (iface != null) { 1348 String[] dnsServers = mDefaultDnsServers; 1349 Collection<InetAddress> dnses = linkProperties.getDnsServers(); 1350 if (dnses != null) { 1351 // we currently only handle IPv4 1352 ArrayList<InetAddress> v4Dnses = 1353 new ArrayList<InetAddress>(dnses.size()); 1354 for (InetAddress dnsAddress : dnses) { 1355 if (dnsAddress instanceof Inet4Address) { 1356 v4Dnses.add(dnsAddress); 1357 } 1358 } 1359 if (v4Dnses.size() > 0) { 1360 dnsServers = NetworkUtils.makeStrings(v4Dnses); 1361 } 1362 } 1363 try { 1364 mNMService.setDnsForwarders(dnsServers); 1365 } catch (Exception e) { 1366 transitionTo(mSetDnsForwardersErrorState); 1367 } 1368 } 1369 } 1370 notifyTetheredOfNewUpstreamIface(iface); 1371 } 1372 1373 protected void notifyTetheredOfNewUpstreamIface(String ifaceName) { 1374 if (DBG) Log.d(TAG, "notifying tethered with iface =" + ifaceName); 1375 mUpstreamIfaceName = ifaceName; 1376 for (TetherInterfaceSM sm : mNotifyList) { 1377 sm.sendMessage(TetherInterfaceSM.CMD_TETHER_CONNECTION_CHANGED, 1378 ifaceName); 1379 } 1380 } 1381 } 1382 1383 class InitialState extends TetherMasterUtilState { 1384 @Override 1385 public void enter() { 1386 } 1387 @Override 1388 public boolean processMessage(Message message) { 1389 if (DBG) Log.d(TAG, "MasterInitialState.processMessage what=" + message.what); 1390 boolean retValue = true; 1391 switch (message.what) { 1392 case CMD_TETHER_MODE_REQUESTED: 1393 TetherInterfaceSM who = (TetherInterfaceSM)message.obj; 1394 if (VDBG) Log.d(TAG, "Tether Mode requested by " + who); 1395 mNotifyList.add(who); 1396 transitionTo(mTetherModeAliveState); 1397 break; 1398 case CMD_TETHER_MODE_UNREQUESTED: 1399 who = (TetherInterfaceSM)message.obj; 1400 if (VDBG) Log.d(TAG, "Tether Mode unrequested by " + who); 1401 int index = mNotifyList.indexOf(who); 1402 if (index != -1) { 1403 mNotifyList.remove(who); 1404 } 1405 break; 1406 default: 1407 retValue = false; 1408 break; 1409 } 1410 return retValue; 1411 } 1412 } 1413 1414 class TetherModeAliveState extends TetherMasterUtilState { 1415 boolean mTryCell = !WAIT_FOR_NETWORK_TO_SETTLE; 1416 @Override 1417 public void enter() { 1418 turnOnMasterTetherSettings(); // may transition us out 1419 1420 mTryCell = !WAIT_FOR_NETWORK_TO_SETTLE; // better try something first pass 1421 // or crazy tests cases will fail 1422 chooseUpstreamType(mTryCell); 1423 mTryCell = !mTryCell; 1424 } 1425 @Override 1426 public void exit() { 1427 turnOffUpstreamMobileConnection(); 1428 notifyTetheredOfNewUpstreamIface(null); 1429 } 1430 @Override 1431 public boolean processMessage(Message message) { 1432 if (DBG) Log.d(TAG, "TetherModeAliveState.processMessage what=" + message.what); 1433 boolean retValue = true; 1434 switch (message.what) { 1435 case CMD_TETHER_MODE_REQUESTED: 1436 TetherInterfaceSM who = (TetherInterfaceSM)message.obj; 1437 if (VDBG) Log.d(TAG, "Tether Mode requested by " + who); 1438 mNotifyList.add(who); 1439 who.sendMessage(TetherInterfaceSM.CMD_TETHER_CONNECTION_CHANGED, 1440 mUpstreamIfaceName); 1441 break; 1442 case CMD_TETHER_MODE_UNREQUESTED: 1443 who = (TetherInterfaceSM)message.obj; 1444 if (VDBG) Log.d(TAG, "Tether Mode unrequested by " + who); 1445 int index = mNotifyList.indexOf(who); 1446 if (index != -1) { 1447 if (DBG) Log.d(TAG, "TetherModeAlive removing notifyee " + who); 1448 mNotifyList.remove(index); 1449 if (mNotifyList.isEmpty()) { 1450 turnOffMasterTetherSettings(); // transitions appropriately 1451 } else { 1452 if (DBG) { 1453 Log.d(TAG, "TetherModeAlive still has " + mNotifyList.size() + 1454 " live requests:"); 1455 for (Object o : mNotifyList) Log.d(TAG, " " + o); 1456 } 1457 } 1458 } else { 1459 Log.e(TAG, "TetherModeAliveState UNREQUESTED has unknown who: " + who); 1460 } 1461 break; 1462 case CMD_UPSTREAM_CHANGED: 1463 // need to try DUN immediately if Wifi goes down 1464 mTryCell = !WAIT_FOR_NETWORK_TO_SETTLE; 1465 chooseUpstreamType(mTryCell); 1466 mTryCell = !mTryCell; 1467 break; 1468 case CMD_CELL_CONNECTION_RENEW: 1469 // make sure we're still using a requested connection - may have found 1470 // wifi or something since then. 1471 if (mCurrentConnectionSequence == message.arg1) { 1472 if (VDBG) { 1473 Log.d(TAG, "renewing mobile connection - requeuing for another " + 1474 CELL_CONNECTION_RENEW_MS + "ms"); 1475 } 1476 turnOnUpstreamMobileConnection(mMobileApnReserved); 1477 } 1478 break; 1479 case CMD_RETRY_UPSTREAM: 1480 chooseUpstreamType(mTryCell); 1481 mTryCell = !mTryCell; 1482 break; 1483 default: 1484 retValue = false; 1485 break; 1486 } 1487 return retValue; 1488 } 1489 } 1490 1491 class ErrorState extends State { 1492 int mErrorNotification; 1493 @Override 1494 public boolean processMessage(Message message) { 1495 boolean retValue = true; 1496 switch (message.what) { 1497 case CMD_TETHER_MODE_REQUESTED: 1498 TetherInterfaceSM who = (TetherInterfaceSM)message.obj; 1499 who.sendMessage(mErrorNotification); 1500 break; 1501 default: 1502 retValue = false; 1503 } 1504 return retValue; 1505 } 1506 void notify(int msgType) { 1507 mErrorNotification = msgType; 1508 for (Object o : mNotifyList) { 1509 TetherInterfaceSM sm = (TetherInterfaceSM)o; 1510 sm.sendMessage(msgType); 1511 } 1512 } 1513 1514 } 1515 class SetIpForwardingEnabledErrorState extends ErrorState { 1516 @Override 1517 public void enter() { 1518 Log.e(TAG, "Error in setIpForwardingEnabled"); 1519 notify(TetherInterfaceSM.CMD_IP_FORWARDING_ENABLE_ERROR); 1520 } 1521 } 1522 1523 class SetIpForwardingDisabledErrorState extends ErrorState { 1524 @Override 1525 public void enter() { 1526 Log.e(TAG, "Error in setIpForwardingDisabled"); 1527 notify(TetherInterfaceSM.CMD_IP_FORWARDING_DISABLE_ERROR); 1528 } 1529 } 1530 1531 class StartTetheringErrorState extends ErrorState { 1532 @Override 1533 public void enter() { 1534 Log.e(TAG, "Error in startTethering"); 1535 notify(TetherInterfaceSM.CMD_START_TETHERING_ERROR); 1536 try { 1537 mNMService.setIpForwardingEnabled(false); 1538 } catch (Exception e) {} 1539 } 1540 } 1541 1542 class StopTetheringErrorState extends ErrorState { 1543 @Override 1544 public void enter() { 1545 Log.e(TAG, "Error in stopTethering"); 1546 notify(TetherInterfaceSM.CMD_STOP_TETHERING_ERROR); 1547 try { 1548 mNMService.setIpForwardingEnabled(false); 1549 } catch (Exception e) {} 1550 } 1551 } 1552 1553 class SetDnsForwardersErrorState extends ErrorState { 1554 @Override 1555 public void enter() { 1556 Log.e(TAG, "Error in setDnsForwarders"); 1557 notify(TetherInterfaceSM.CMD_SET_DNS_FORWARDERS_ERROR); 1558 try { 1559 mNMService.stopTethering(); 1560 } catch (Exception e) {} 1561 try { 1562 mNMService.setIpForwardingEnabled(false); 1563 } catch (Exception e) {} 1564 } 1565 } 1566 } 1567 1568 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1569 if (mContext.checkCallingOrSelfPermission( 1570 android.Manifest.permission.DUMP) != PackageManager.PERMISSION_GRANTED) { 1571 pw.println("Permission Denial: can't dump ConnectivityService.Tether " + 1572 "from from pid=" + Binder.getCallingPid() + ", uid=" + 1573 Binder.getCallingUid()); 1574 return; 1575 } 1576 1577 synchronized (mPublicSync) { 1578 pw.println("mUpstreamIfaceTypes: "); 1579 for (Integer netType : mUpstreamIfaceTypes) { 1580 pw.println(" " + netType); 1581 } 1582 1583 pw.println(); 1584 pw.println("Tether state:"); 1585 for (Object o : mIfaces.values()) { 1586 pw.println(" " + o); 1587 } 1588 } 1589 pw.println(); 1590 return; 1591 } 1592} 1593