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