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