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