Tethering.java revision 94260caf2fb3f5dbf6e17b29a269b46ea05f8680
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.ContentResolver; 24import android.content.Context; 25import android.content.Intent; 26import android.content.IntentFilter; 27import android.content.pm.PackageManager; 28import android.content.res.Resources; 29import android.hardware.usb.UsbManager; 30import android.net.ConnectivityManager; 31import android.net.InterfaceConfiguration; 32import android.net.IConnectivityManager; 33import android.net.INetworkManagementEventObserver; 34import android.net.NetworkInfo; 35import android.net.NetworkUtils; 36import android.os.Binder; 37import android.os.Environment; 38import android.os.Handler; 39import android.os.HandlerThread; 40import android.os.IBinder; 41import android.os.INetworkManagementService; 42import android.os.Looper; 43import android.os.Message; 44import android.os.RemoteException; 45import android.os.ServiceManager; 46import android.provider.Settings; 47import android.util.Log; 48 49import com.android.internal.telephony.Phone; 50import com.android.internal.util.HierarchicalState; 51import com.android.internal.util.HierarchicalStateMachine; 52 53import java.io.FileDescriptor; 54import java.io.PrintWriter; 55import java.util.ArrayList; 56import java.util.HashMap; 57import java.util.Set; 58/** 59 * @hide 60 * 61 * Timeout 62 * 63 * TODO - look for parent classes and code sharing 64 */ 65 66public class Tethering extends INetworkManagementEventObserver.Stub { 67 68 private Context mContext; 69 private final String TAG = "Tethering"; 70 71 private boolean mBooted = false; 72 //used to remember if we got connected before boot finished 73 private boolean mDeferedUsbConnection = false; 74 75 // TODO - remove both of these - should be part of interface inspection/selection stuff 76 private String[] mTetherableUsbRegexs; 77 private String[] mTetherableWifiRegexs; 78 private String[] mUpstreamIfaceRegexs; 79 80 private Looper mLooper; 81 private HandlerThread mThread; 82 83 private HashMap<String, TetherInterfaceSM> mIfaces; // all tethered/tetherable ifaces 84 85 private BroadcastReceiver mStateReceiver; 86 87 private static final String USB_NEAR_IFACE_ADDR = "192.168.42.129"; 88 private static final String USB_NETMASK = "255.255.255.0"; 89 90 // FYI - the default wifi is 192.168.43.1 and 255.255.255.0 91 92 private String[] mDhcpRange; 93 private static final String DHCP_DEFAULT_RANGE1_START = "192.168.42.2"; 94 private static final String DHCP_DEFAULT_RANGE1_STOP = "192.168.42.254"; 95 private static final String DHCP_DEFAULT_RANGE2_START = "192.168.43.2"; 96 private static final String DHCP_DEFAULT_RANGE2_STOP = "192.168.43.254"; 97 98 private String[] mDnsServers; 99 private static final String DNS_DEFAULT_SERVER1 = "8.8.8.8"; 100 private static final String DNS_DEFAULT_SERVER2 = "4.2.2.2"; 101 102 // resampled each time we turn on tethering - used as cache for settings/config-val 103 private boolean mDunRequired; // configuration info - must use DUN apn on 3g 104 105 private HierarchicalStateMachine mTetherMasterSM; 106 107 private Notification mTetheredNotification; 108 109 // whether we can tether is the && of these two - they come in as separate 110 // broadcasts so track them so we can decide what to do when either changes 111 private boolean mUsbMassStorageOff; // track the status of USB Mass Storage 112 private boolean mUsbConnected; // track the status of USB connection 113 114 public Tethering(Context context, Looper looper) { 115 mContext = context; 116 mLooper = looper; 117 118 // register for notifications from NetworkManagement Service 119 IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE); 120 INetworkManagementService service = INetworkManagementService.Stub.asInterface(b); 121 try { 122 service.registerObserver(this); 123 } catch (RemoteException e) { 124 Log.e(TAG, "Error registering observer :" + e); 125 } 126 127 mIfaces = new HashMap<String, TetherInterfaceSM>(); 128 129 // make our own thread so we don't anr the system 130 mThread = new HandlerThread("Tethering"); 131 mThread.start(); 132 mLooper = mThread.getLooper(); 133 mTetherMasterSM = new TetherMasterSM("TetherMaster", mLooper); 134 mTetherMasterSM.start(); 135 136 mStateReceiver = new StateReceiver(); 137 IntentFilter filter = new IntentFilter(); 138 filter.addAction(UsbManager.ACTION_USB_STATE); 139 filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); 140 filter.addAction(Intent.ACTION_BOOT_COMPLETED); 141 mContext.registerReceiver(mStateReceiver, filter); 142 143 filter = new IntentFilter(); 144 filter.addAction(Intent.ACTION_MEDIA_SHARED); 145 filter.addAction(Intent.ACTION_MEDIA_UNSHARED); 146 filter.addDataScheme("file"); 147 mContext.registerReceiver(mStateReceiver, filter); 148 149 mUsbMassStorageOff = !Environment.MEDIA_SHARED.equals( 150 Environment.getExternalStorageState()); 151 152 mDhcpRange = context.getResources().getStringArray( 153 com.android.internal.R.array.config_tether_dhcp_range); 154 if ((mDhcpRange.length == 0) || (mDhcpRange.length % 2 ==1)) { 155 mDhcpRange = new String[4]; 156 mDhcpRange[0] = DHCP_DEFAULT_RANGE1_START; 157 mDhcpRange[1] = DHCP_DEFAULT_RANGE1_STOP; 158 mDhcpRange[2] = DHCP_DEFAULT_RANGE2_START; 159 mDhcpRange[3] = DHCP_DEFAULT_RANGE2_STOP; 160 } 161 mDunRequired = false; // resample when we turn on 162 163 mTetherableUsbRegexs = context.getResources().getStringArray( 164 com.android.internal.R.array.config_tether_usb_regexs); 165 mTetherableWifiRegexs = context.getResources().getStringArray( 166 com.android.internal.R.array.config_tether_wifi_regexs); 167 mUpstreamIfaceRegexs = context.getResources().getStringArray( 168 com.android.internal.R.array.config_tether_upstream_regexs); 169 170 // TODO - remove and rely on real notifications of the current iface 171 mDnsServers = new String[2]; 172 mDnsServers[0] = DNS_DEFAULT_SERVER1; 173 mDnsServers[1] = DNS_DEFAULT_SERVER2; 174 } 175 176 public void interfaceLinkStatusChanged(String iface, boolean link) { 177 Log.d(TAG, "interfaceLinkStatusChanged " + iface + ", " + link); 178 boolean found = false; 179 boolean usb = false; 180 if (isWifi(iface)) { 181 found = true; 182 } else if (isUsb(iface)) { 183 found = true; 184 usb = true; 185 } 186 if (found == false) return; 187 188 synchronized (mIfaces) { 189 TetherInterfaceSM sm = mIfaces.get(iface); 190 if (link) { 191 if (sm == null) { 192 sm = new TetherInterfaceSM(iface, mLooper, usb); 193 mIfaces.put(iface, sm); 194 sm.start(); 195 } 196 } else { 197 if (sm != null) { 198 sm.sendMessage(TetherInterfaceSM.CMD_INTERFACE_DOWN); 199 mIfaces.remove(iface); 200 } 201 } 202 } 203 } 204 205 private boolean isUsb(String iface) { 206 for (String regex : mTetherableUsbRegexs) { 207 if (iface.matches(regex)) return true; 208 } 209 return false; 210 } 211 212 public boolean isWifi(String iface) { 213 for (String regex : mTetherableWifiRegexs) { 214 if (iface.matches(regex)) return true; 215 } 216 return false; 217 } 218 219 public void interfaceAdded(String iface) { 220 IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE); 221 INetworkManagementService service = INetworkManagementService.Stub.asInterface(b); 222 boolean found = false; 223 boolean usb = false; 224 if (isWifi(iface)) { 225 found = true; 226 } 227 if (isUsb(iface)) { 228 found = true; 229 usb = true; 230 } 231 if (found == false) { 232 Log.d(TAG, iface + " is not a tetherable iface, ignoring"); 233 return; 234 } 235 236 synchronized (mIfaces) { 237 TetherInterfaceSM sm = mIfaces.get(iface); 238 if (sm != null) { 239 Log.e(TAG, "active iface (" + iface + ") reported as added, ignoring"); 240 return; 241 } 242 sm = new TetherInterfaceSM(iface, mLooper, usb); 243 mIfaces.put(iface, sm); 244 sm.start(); 245 } 246 Log.d(TAG, "interfaceAdded :" + iface); 247 } 248 249 public void interfaceRemoved(String iface) { 250 synchronized (mIfaces) { 251 TetherInterfaceSM sm = mIfaces.get(iface); 252 if (sm == null) { 253 Log.e(TAG, "attempting to remove unknown iface (" + iface + "), ignoring"); 254 return; 255 } 256 sm.sendMessage(TetherInterfaceSM.CMD_INTERFACE_DOWN); 257 mIfaces.remove(iface); 258 } 259 } 260 261 public int tether(String iface) { 262 Log.d(TAG, "Tethering " + iface); 263 TetherInterfaceSM sm = null; 264 synchronized (mIfaces) { 265 sm = mIfaces.get(iface); 266 } 267 if (sm == null) { 268 Log.e(TAG, "Tried to Tether an unknown iface :" + iface + ", ignoring"); 269 return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE; 270 } 271 if (!sm.isAvailable() && !sm.isErrored()) { 272 Log.e(TAG, "Tried to Tether an unavailable iface :" + iface + ", ignoring"); 273 return ConnectivityManager.TETHER_ERROR_UNAVAIL_IFACE; 274 } 275 sm.sendMessage(TetherInterfaceSM.CMD_TETHER_REQUESTED); 276 return ConnectivityManager.TETHER_ERROR_NO_ERROR; 277 } 278 279 public int untether(String iface) { 280 Log.d(TAG, "Untethering " + iface); 281 TetherInterfaceSM sm = null; 282 synchronized (mIfaces) { 283 sm = mIfaces.get(iface); 284 } 285 if (sm == null) { 286 Log.e(TAG, "Tried to Untether an unknown iface :" + iface + ", ignoring"); 287 return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE; 288 } 289 if (sm.isErrored()) { 290 Log.e(TAG, "Tried to Untethered an errored iface :" + iface + ", ignoring"); 291 return ConnectivityManager.TETHER_ERROR_UNAVAIL_IFACE; 292 } 293 sm.sendMessage(TetherInterfaceSM.CMD_TETHER_UNREQUESTED); 294 return ConnectivityManager.TETHER_ERROR_NO_ERROR; 295 } 296 297 public int getLastTetherError(String iface) { 298 TetherInterfaceSM sm = null; 299 synchronized (mIfaces) { 300 sm = mIfaces.get(iface); 301 } 302 if (sm == null) { 303 Log.e(TAG, "Tried to getLastTetherError on an unknown iface :" + iface + ", ignoring"); 304 return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE; 305 } 306 return sm.getLastError(); 307 } 308 309 private void sendTetherStateChangedBroadcast() { 310 IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE); 311 IConnectivityManager service = IConnectivityManager.Stub.asInterface(b); 312 try { 313 if (!service.isTetheringSupported()) return; 314 } catch (RemoteException e) { 315 return; 316 } 317 318 ArrayList<String> availableList = new ArrayList<String>(); 319 ArrayList<String> activeList = new ArrayList<String>(); 320 ArrayList<String> erroredList = new ArrayList<String>(); 321 322 boolean wifiTethered = false; 323 boolean usbTethered = false; 324 325 synchronized (mIfaces) { 326 Set ifaces = mIfaces.keySet(); 327 for (Object iface : ifaces) { 328 TetherInterfaceSM sm = mIfaces.get(iface); 329 if (sm != null) { 330 if(sm.isErrored()) { 331 erroredList.add((String)iface); 332 } else if (sm.isAvailable()) { 333 availableList.add((String)iface); 334 } else if (sm.isTethered()) { 335 if (isUsb((String)iface)) { 336 usbTethered = true; 337 } else if (isWifi((String)iface)) { 338 wifiTethered = true; 339 } 340 activeList.add((String)iface); 341 } 342 } 343 } 344 } 345 Intent broadcast = new Intent(ConnectivityManager.ACTION_TETHER_STATE_CHANGED); 346 broadcast.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); 347 broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_AVAILABLE_TETHER, 348 availableList); 349 broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_ACTIVE_TETHER, activeList); 350 broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_ERRORED_TETHER, 351 erroredList); 352 mContext.sendStickyBroadcast(broadcast); 353 Log.d(TAG, "sendTetherStateChangedBroadcast " + availableList.size() + ", " + 354 activeList.size() + ", " + erroredList.size()); 355 356 if (usbTethered) { 357 if (wifiTethered) { 358 showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_general); 359 } else { 360 showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_usb); 361 } 362 } else if (wifiTethered) { 363 showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_wifi); 364 } else { 365 clearTetheredNotification(); 366 } 367 } 368 369 private void showTetheredNotification(int icon) { 370 NotificationManager notificationManager = 371 (NotificationManager)mContext.getSystemService(Context.NOTIFICATION_SERVICE); 372 if (notificationManager == null) { 373 return; 374 } 375 376 if (mTetheredNotification != null) { 377 if (mTetheredNotification.icon == icon) { 378 return; 379 } 380 notificationManager.cancel(mTetheredNotification.icon); 381 } 382 383 Intent intent = new Intent(); 384 intent.setClassName("com.android.settings", "com.android.settings.TetherSettings"); 385 intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY); 386 387 PendingIntent pi = PendingIntent.getActivity(mContext, 0, intent, 0); 388 389 Resources r = Resources.getSystem(); 390 CharSequence title = r.getText(com.android.internal.R.string.tethered_notification_title); 391 CharSequence message = r.getText(com.android.internal.R.string. 392 tethered_notification_message); 393 394 if(mTetheredNotification == null) { 395 mTetheredNotification = new Notification(); 396 mTetheredNotification.when = 0; 397 } 398 mTetheredNotification.icon = icon; 399 mTetheredNotification.defaults &= ~Notification.DEFAULT_SOUND; 400 mTetheredNotification.flags = Notification.FLAG_ONGOING_EVENT; 401 mTetheredNotification.tickerText = title; 402 mTetheredNotification.setLatestEventInfo(mContext, title, message, pi); 403 404 notificationManager.notify(mTetheredNotification.icon, mTetheredNotification); 405 } 406 407 private void clearTetheredNotification() { 408 NotificationManager notificationManager = 409 (NotificationManager)mContext.getSystemService(Context.NOTIFICATION_SERVICE); 410 if (notificationManager != null && mTetheredNotification != null) { 411 notificationManager.cancel(mTetheredNotification.icon); 412 mTetheredNotification = null; 413 } 414 } 415 416 private void updateUsbStatus() { 417 boolean enable = mUsbConnected && mUsbMassStorageOff; 418 419 if (mBooted) { 420 enableUsbIfaces(enable); 421 } 422 } 423 424 private class StateReceiver extends BroadcastReceiver { 425 public void onReceive(Context content, Intent intent) { 426 String action = intent.getAction(); 427 if (action.equals(UsbManager.ACTION_USB_STATE)) { 428 mUsbConnected = intent.getExtras().getBoolean(UsbManager.USB_CONNECTED); 429 updateUsbStatus(); 430 } else if (action.equals(Intent.ACTION_MEDIA_SHARED)) { 431 mUsbMassStorageOff = false; 432 updateUsbStatus(); 433 } 434 else if (action.equals(Intent.ACTION_MEDIA_UNSHARED)) { 435 mUsbMassStorageOff = true; 436 updateUsbStatus(); 437 } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) { 438 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_UPSTREAM_CHANGED); 439 } else if (action.equals(Intent.ACTION_BOOT_COMPLETED)) { 440 mBooted = true; 441 updateUsbStatus(); 442 } 443 } 444 } 445 446 // used on cable insert/remove 447 private void enableUsbIfaces(boolean enable) { 448 IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE); 449 INetworkManagementService service = INetworkManagementService.Stub.asInterface(b); 450 String[] ifaces = new String[0]; 451 try { 452 ifaces = service.listInterfaces(); 453 } catch (Exception e) { 454 Log.e(TAG, "Error listing Interfaces :" + e); 455 return; 456 } 457 for (String iface : ifaces) { 458 if (isUsb(iface)) { 459 if (enable) { 460 interfaceAdded(iface); 461 } else { 462 interfaceRemoved(iface); 463 } 464 } 465 } 466 } 467 468 // toggled when we enter/leave the fully teathered state 469 private boolean enableUsbRndis(boolean enabled) { 470 Log.d(TAG, "enableUsbRndis(" + enabled + ")"); 471 IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE); 472 INetworkManagementService service = INetworkManagementService.Stub.asInterface(b); 473 474 try { 475 if (enabled) { 476 synchronized (this) { 477 if (!service.isUsbRNDISStarted()) { 478 service.startUsbRNDIS(); 479 } 480 } 481 } else { 482 if (service.isUsbRNDISStarted()) { 483 service.stopUsbRNDIS(); 484 } 485 } 486 } catch (Exception e) { 487 Log.e(TAG, "Error toggling usb RNDIS :" + e); 488 return false; 489 } 490 return true; 491 } 492 493 // configured when we start tethering and unconfig'd on error or conclusion 494 private boolean configureUsbIface(boolean enabled) { 495 Log.d(TAG, "configureUsbIface(" + enabled + ")"); 496 497 IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE); 498 INetworkManagementService service = INetworkManagementService.Stub.asInterface(b); 499 500 // bring toggle the interfaces 501 String[] ifaces = new String[0]; 502 try { 503 ifaces = service.listInterfaces(); 504 } catch (Exception e) { 505 Log.e(TAG, "Error listing Interfaces :" + e); 506 return false; 507 } 508 for (String iface : ifaces) { 509 if (isUsb(iface)) { 510 InterfaceConfiguration ifcg = null; 511 try { 512 ifcg = service.getInterfaceConfig(iface); 513 if (ifcg != null) { 514 String[] addr = USB_NEAR_IFACE_ADDR.split("\\."); 515 ifcg.ipAddr = (Integer.parseInt(addr[0]) << 24) + 516 (Integer.parseInt(addr[1]) << 16) + 517 (Integer.parseInt(addr[2]) << 8) + 518 (Integer.parseInt(addr[3])); 519 addr = USB_NETMASK.split("\\."); 520 ifcg.netmask = (Integer.parseInt(addr[0]) << 24) + 521 (Integer.parseInt(addr[1]) << 16) + 522 (Integer.parseInt(addr[2]) << 8) + 523 (Integer.parseInt(addr[3])); 524 if (enabled) { 525 ifcg.interfaceFlags = ifcg.interfaceFlags.replace("down", "up"); 526 } else { 527 ifcg.interfaceFlags = ifcg.interfaceFlags.replace("up", "down"); 528 } 529 ifcg.interfaceFlags = ifcg.interfaceFlags.replace("running", ""); 530 ifcg.interfaceFlags = ifcg.interfaceFlags.replace(" "," "); 531 service.setInterfaceConfig(iface, ifcg); 532 } 533 } catch (Exception e) { 534 Log.e(TAG, "Error configuring interface " + iface + ", :" + e); 535 return false; 536 } 537 } 538 } 539 540 return true; 541 } 542 543 public String[] getTetherableUsbRegexs() { 544 return mTetherableUsbRegexs; 545 } 546 547 public String[] getTetherableWifiRegexs() { 548 return mTetherableWifiRegexs; 549 } 550 551 public String[] getUpstreamIfaceRegexs() { 552 return mUpstreamIfaceRegexs; 553 } 554 555 public boolean isDunRequired() { 556 boolean defaultVal = mContext.getResources().getBoolean( 557 com.android.internal.R.bool.config_tether_dun_required); 558 boolean result = (Settings.Secure.getInt(mContext.getContentResolver(), 559 Settings.Secure.TETHER_DUN_REQUIRED, (defaultVal ? 1 : 0)) == 1); 560 return result; 561 } 562 563 public String[] getTetheredIfaces() { 564 ArrayList<String> list = new ArrayList<String>(); 565 synchronized (mIfaces) { 566 Set keys = mIfaces.keySet(); 567 for (Object key : keys) { 568 TetherInterfaceSM sm = mIfaces.get(key); 569 if (sm.isTethered()) { 570 list.add((String)key); 571 } 572 } 573 } 574 String[] retVal = new String[list.size()]; 575 for (int i=0; i < list.size(); i++) { 576 retVal[i] = list.get(i); 577 } 578 return retVal; 579 } 580 581 public String[] getTetherableIfaces() { 582 ArrayList<String> list = new ArrayList<String>(); 583 synchronized (mIfaces) { 584 Set keys = mIfaces.keySet(); 585 for (Object key : keys) { 586 TetherInterfaceSM sm = mIfaces.get(key); 587 if (sm.isAvailable()) { 588 list.add((String)key); 589 } 590 } 591 } 592 String[] retVal = new String[list.size()]; 593 for (int i=0; i < list.size(); i++) { 594 retVal[i] = list.get(i); 595 } 596 return retVal; 597 } 598 599 public String[] getErroredIfaces() { 600 ArrayList<String> list = new ArrayList<String>(); 601 synchronized (mIfaces) { 602 Set keys = mIfaces.keySet(); 603 for (Object key : keys) { 604 TetherInterfaceSM sm = mIfaces.get(key); 605 if (sm.isErrored()) { 606 list.add((String)key); 607 } 608 } 609 } 610 String[] retVal = new String[list.size()]; 611 for (int i= 0; i< list.size(); i++) { 612 retVal[i] = list.get(i); 613 } 614 return retVal; 615 } 616 617 618 class TetherInterfaceSM extends HierarchicalStateMachine { 619 // notification from the master SM that it's not in tether mode 620 static final int CMD_TETHER_MODE_DEAD = 1; 621 // request from the user that it wants to tether 622 static final int CMD_TETHER_REQUESTED = 2; 623 // request from the user that it wants to untether 624 static final int CMD_TETHER_UNREQUESTED = 3; 625 // notification that this interface is down 626 static final int CMD_INTERFACE_DOWN = 4; 627 // notification that this interface is up 628 static final int CMD_INTERFACE_UP = 5; 629 // notification from the master SM that it had an error turning on cellular dun 630 static final int CMD_CELL_DUN_ERROR = 6; 631 // notification from the master SM that it had trouble enabling IP Forwarding 632 static final int CMD_IP_FORWARDING_ENABLE_ERROR = 7; 633 // notification from the master SM that it had trouble disabling IP Forwarding 634 static final int CMD_IP_FORWARDING_DISABLE_ERROR = 8; 635 // notification from the master SM that it had trouble staring tethering 636 static final int CMD_START_TETHERING_ERROR = 9; 637 // notification from the master SM that it had trouble stopping tethering 638 static final int CMD_STOP_TETHERING_ERROR = 10; 639 // notification from the master SM that it had trouble setting the DNS forwarders 640 static final int CMD_SET_DNS_FORWARDERS_ERROR = 11; 641 // the upstream connection has changed 642 static final int CMD_TETHER_CONNECTION_CHANGED = 12; 643 644 private HierarchicalState mDefaultState; 645 646 private HierarchicalState mInitialState; 647 private HierarchicalState mStartingState; 648 private HierarchicalState mTetheredState; 649 650 private HierarchicalState mUnavailableState; 651 652 private boolean mAvailable; 653 private boolean mTethered; 654 int mLastError; 655 656 String mIfaceName; 657 String mMyUpstreamIfaceName; // may change over time 658 659 boolean mUsb; 660 661 TetherInterfaceSM(String name, Looper looper, boolean usb) { 662 super(name, looper); 663 mIfaceName = name; 664 mUsb = usb; 665 setLastError(ConnectivityManager.TETHER_ERROR_NO_ERROR); 666 667 mInitialState = new InitialState(); 668 addState(mInitialState); 669 mStartingState = new StartingState(); 670 addState(mStartingState); 671 mTetheredState = new TetheredState(); 672 addState(mTetheredState); 673 mUnavailableState = new UnavailableState(); 674 addState(mUnavailableState); 675 676 setInitialState(mInitialState); 677 } 678 679 public String toString() { 680 String res = new String(); 681 res += mIfaceName + " - "; 682 HierarchicalState current = getCurrentState(); 683 if (current == mInitialState) res += "InitialState"; 684 if (current == mStartingState) res += "StartingState"; 685 if (current == mTetheredState) res += "TetheredState"; 686 if (current == mUnavailableState) res += "UnavailableState"; 687 if (mAvailable) res += " - Available"; 688 if (mTethered) res += " - Tethered"; 689 res += " - lastError =" + mLastError; 690 return res; 691 } 692 693 public synchronized int getLastError() { 694 return mLastError; 695 } 696 697 private synchronized void setLastError(int error) { 698 mLastError = error; 699 700 if (isErrored()) { 701 if (mUsb) { 702 // note everything's been unwound by this point so nothing to do on 703 // further error.. 704 Tethering.this.configureUsbIface(false); 705 } 706 } 707 } 708 709 // synchronized between this getter and the following setter 710 public synchronized boolean isAvailable() { 711 return mAvailable; 712 } 713 714 private synchronized void setAvailable(boolean available) { 715 mAvailable = available; 716 } 717 718 // synchronized between this getter and the following setter 719 public synchronized boolean isTethered() { 720 return mTethered; 721 } 722 723 private synchronized void setTethered(boolean tethered) { 724 mTethered = tethered; 725 } 726 727 // synchronized between this getter and the following setter 728 public synchronized boolean isErrored() { 729 return (mLastError != ConnectivityManager.TETHER_ERROR_NO_ERROR); 730 } 731 732 class InitialState extends HierarchicalState { 733 @Override 734 public void enter() { 735 setAvailable(true); 736 setTethered(false); 737 sendTetherStateChangedBroadcast(); 738 } 739 740 @Override 741 public boolean processMessage(Message message) { 742 Log.d(TAG, "InitialState.processMessage what=" + message.what); 743 boolean retValue = true; 744 switch (message.what) { 745 case CMD_TETHER_REQUESTED: 746 setLastError(ConnectivityManager.TETHER_ERROR_NO_ERROR); 747 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_REQUESTED, 748 TetherInterfaceSM.this); 749 transitionTo(mStartingState); 750 break; 751 case CMD_INTERFACE_DOWN: 752 transitionTo(mUnavailableState); 753 break; 754 default: 755 retValue = false; 756 break; 757 } 758 return retValue; 759 } 760 } 761 762 class StartingState extends HierarchicalState { 763 @Override 764 public void enter() { 765 setAvailable(false); 766 if (mUsb) { 767 if (!Tethering.this.configureUsbIface(true)) { 768 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED, 769 TetherInterfaceSM.this); 770 setLastError(ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR); 771 772 transitionTo(mInitialState); 773 return; 774 } 775 } 776 sendTetherStateChangedBroadcast(); 777 778 // Skipping StartingState 779 transitionTo(mTetheredState); 780 } 781 @Override 782 public boolean processMessage(Message message) { 783 Log.d(TAG, "StartingState.processMessage what=" + message.what); 784 boolean retValue = true; 785 switch (message.what) { 786 // maybe a parent class? 787 case CMD_TETHER_UNREQUESTED: 788 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED, 789 TetherInterfaceSM.this); 790 if (mUsb) { 791 if (!Tethering.this.configureUsbIface(false)) { 792 setLastErrorAndTransitionToInitialState( 793 ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR); 794 break; 795 } 796 } 797 transitionTo(mInitialState); 798 break; 799 case CMD_CELL_DUN_ERROR: 800 case CMD_IP_FORWARDING_ENABLE_ERROR: 801 case CMD_IP_FORWARDING_DISABLE_ERROR: 802 case CMD_START_TETHERING_ERROR: 803 case CMD_STOP_TETHERING_ERROR: 804 case CMD_SET_DNS_FORWARDERS_ERROR: 805 setLastErrorAndTransitionToInitialState( 806 ConnectivityManager.TETHER_ERROR_MASTER_ERROR); 807 break; 808 case CMD_INTERFACE_DOWN: 809 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED, 810 TetherInterfaceSM.this); 811 transitionTo(mUnavailableState); 812 break; 813 default: 814 retValue = false; 815 } 816 return retValue; 817 } 818 } 819 820 class TetheredState extends HierarchicalState { 821 @Override 822 public void enter() { 823 IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE); 824 INetworkManagementService service = 825 INetworkManagementService.Stub.asInterface(b); 826 try { 827 service.tetherInterface(mIfaceName); 828 } catch (Exception e) { 829 setLastError(ConnectivityManager.TETHER_ERROR_TETHER_IFACE_ERROR); 830 831 transitionTo(mInitialState); 832 return; 833 } 834 if (mUsb) Tethering.this.enableUsbRndis(true); 835 Log.d(TAG, "Tethered " + mIfaceName); 836 setAvailable(false); 837 setTethered(true); 838 sendTetherStateChangedBroadcast(); 839 } 840 @Override 841 public void exit() { 842 if (mUsb) Tethering.this.enableUsbRndis(false); 843 } 844 @Override 845 public boolean processMessage(Message message) { 846 Log.d(TAG, "TetheredState.processMessage what=" + message.what); 847 boolean retValue = true; 848 boolean error = false; 849 switch (message.what) { 850 case CMD_TETHER_UNREQUESTED: 851 case CMD_INTERFACE_DOWN: 852 IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE); 853 INetworkManagementService service = 854 INetworkManagementService.Stub.asInterface(b); 855 if (mMyUpstreamIfaceName != null) { 856 try { 857 service.disableNat(mIfaceName, mMyUpstreamIfaceName); 858 mMyUpstreamIfaceName = null; 859 } catch (Exception e) { 860 try { 861 service.untetherInterface(mIfaceName); 862 } catch (Exception ee) {} 863 864 setLastErrorAndTransitionToInitialState( 865 ConnectivityManager.TETHER_ERROR_DISABLE_NAT_ERROR); 866 break; 867 } 868 } 869 try { 870 service.untetherInterface(mIfaceName); 871 } catch (Exception e) { 872 setLastErrorAndTransitionToInitialState( 873 ConnectivityManager.TETHER_ERROR_UNTETHER_IFACE_ERROR); 874 break; 875 } 876 mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED, 877 TetherInterfaceSM.this); 878 if (message.what == CMD_TETHER_UNREQUESTED) { 879 if (mUsb) { 880 if (!Tethering.this.configureUsbIface(false)) { 881 setLastError( 882 ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR); 883 } 884 } 885 transitionTo(mInitialState); 886 } else if (message.what == CMD_INTERFACE_DOWN) { 887 transitionTo(mUnavailableState); 888 } 889 Log.d(TAG, "Untethered " + mIfaceName); 890 break; 891 case CMD_TETHER_CONNECTION_CHANGED: 892 String newUpstreamIfaceName = (String)(message.obj); 893 b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE); 894 service = INetworkManagementService.Stub.asInterface(b); 895 896 if (mMyUpstreamIfaceName != null) { 897 try { 898 service.disableNat(mIfaceName, mMyUpstreamIfaceName); 899 mMyUpstreamIfaceName = null; 900 } catch (Exception e) { 901 try { 902 service.untetherInterface(mIfaceName); 903 } catch (Exception ee) {} 904 905 setLastErrorAndTransitionToInitialState( 906 ConnectivityManager.TETHER_ERROR_DISABLE_NAT_ERROR); 907 break; 908 } 909 } 910 if (newUpstreamIfaceName != null) { 911 try { 912 service.enableNat(mIfaceName, newUpstreamIfaceName); 913 } catch (Exception e) { 914 try { 915 service.untetherInterface(mIfaceName); 916 } catch (Exception ee) {} 917 918 setLastError(ConnectivityManager.TETHER_ERROR_ENABLE_NAT_ERROR); 919 transitionTo(mInitialState); 920 return true; 921 } 922 } 923 mMyUpstreamIfaceName = newUpstreamIfaceName; 924 break; 925 case CMD_CELL_DUN_ERROR: 926 case CMD_IP_FORWARDING_ENABLE_ERROR: 927 case CMD_IP_FORWARDING_DISABLE_ERROR: 928 case CMD_START_TETHERING_ERROR: 929 case CMD_STOP_TETHERING_ERROR: 930 case CMD_SET_DNS_FORWARDERS_ERROR: 931 error = true; 932 // fall through 933 case CMD_TETHER_MODE_DEAD: 934 b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE); 935 service = INetworkManagementService.Stub.asInterface(b); 936 if (mMyUpstreamIfaceName != null) { 937 try { 938 service.disableNat(mIfaceName, mMyUpstreamIfaceName); 939 mMyUpstreamIfaceName = null; 940 } catch (Exception e) { 941 try { 942 service.untetherInterface(mIfaceName); 943 } catch (Exception ee) {} 944 945 setLastErrorAndTransitionToInitialState( 946 ConnectivityManager.TETHER_ERROR_DISABLE_NAT_ERROR); 947 break; 948 } 949 } 950 try { 951 service.untetherInterface(mIfaceName); 952 } catch (Exception e) { 953 setLastErrorAndTransitionToInitialState( 954 ConnectivityManager.TETHER_ERROR_UNTETHER_IFACE_ERROR); 955 break; 956 } 957 if (error) { 958 setLastErrorAndTransitionToInitialState( 959 ConnectivityManager.TETHER_ERROR_MASTER_ERROR); 960 break; 961 } 962 Log.d(TAG, "Tether lost upstream connection " + mIfaceName); 963 sendTetherStateChangedBroadcast(); 964 if (mUsb) { 965 if (!Tethering.this.configureUsbIface(false)) { 966 setLastError(ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR); 967 } 968 } 969 transitionTo(mInitialState); 970 break; 971 default: 972 retValue = false; 973 break; 974 } 975 return retValue; 976 } 977 } 978 979 class UnavailableState extends HierarchicalState { 980 @Override 981 public void enter() { 982 setAvailable(false); 983 setLastError(ConnectivityManager.TETHER_ERROR_NO_ERROR); 984 setTethered(false); 985 sendTetherStateChangedBroadcast(); 986 } 987 @Override 988 public boolean processMessage(Message message) { 989 boolean retValue = true; 990 switch (message.what) { 991 case CMD_INTERFACE_UP: 992 transitionTo(mInitialState); 993 break; 994 default: 995 retValue = false; 996 break; 997 } 998 return retValue; 999 } 1000 } 1001 1002 void setLastErrorAndTransitionToInitialState(int error) { 1003 setLastError(error); 1004 transitionTo(mInitialState); 1005 } 1006 1007 } 1008 1009 class TetherMasterSM extends HierarchicalStateMachine { 1010 // an interface SM has requested Tethering 1011 static final int CMD_TETHER_MODE_REQUESTED = 1; 1012 // an interface SM has unrequested Tethering 1013 static final int CMD_TETHER_MODE_UNREQUESTED = 2; 1014 // upstream connection change - do the right thing 1015 static final int CMD_UPSTREAM_CHANGED = 3; 1016 // we received notice that the cellular DUN connection is up 1017 static final int CMD_CELL_CONNECTION_RENEW = 4; 1018 // we don't have a valid upstream conn, check again after a delay 1019 static final int CMD_RETRY_UPSTREAM = 5; 1020 1021 // This indicates what a timeout event relates to. A state that 1022 // sends itself a delayed timeout event and handles incoming timeout events 1023 // should inc this when it is entered and whenever it sends a new timeout event. 1024 // We do not flush the old ones. 1025 private int mSequenceNumber; 1026 1027 private HierarchicalState mInitialState; 1028 private HierarchicalState mTetherModeAliveState; 1029 1030 private HierarchicalState mSetIpForwardingEnabledErrorState; 1031 private HierarchicalState mSetIpForwardingDisabledErrorState; 1032 private HierarchicalState mStartTetheringErrorState; 1033 private HierarchicalState mStopTetheringErrorState; 1034 private HierarchicalState mSetDnsForwardersErrorState; 1035 1036 private ArrayList mNotifyList; 1037 1038 private boolean mConnectionRequested = false; 1039 1040 private String mUpstreamIfaceName = null; 1041 1042 private static final int UPSTREAM_SETTLE_TIME_MS = 10000; 1043 private static final int CELL_CONNECTION_RENEW_MS = 40000; 1044 1045 TetherMasterSM(String name, Looper looper) { 1046 super(name, looper); 1047 1048 //Add states 1049 mInitialState = new InitialState(); 1050 addState(mInitialState); 1051 mTetherModeAliveState = new TetherModeAliveState(); 1052 addState(mTetherModeAliveState); 1053 1054 mSetIpForwardingEnabledErrorState = new SetIpForwardingEnabledErrorState(); 1055 addState(mSetIpForwardingEnabledErrorState); 1056 mSetIpForwardingDisabledErrorState = new SetIpForwardingDisabledErrorState(); 1057 addState(mSetIpForwardingDisabledErrorState); 1058 mStartTetheringErrorState = new StartTetheringErrorState(); 1059 addState(mStartTetheringErrorState); 1060 mStopTetheringErrorState = new StopTetheringErrorState(); 1061 addState(mStopTetheringErrorState); 1062 mSetDnsForwardersErrorState = new SetDnsForwardersErrorState(); 1063 addState(mSetDnsForwardersErrorState); 1064 1065 mNotifyList = new ArrayList(); 1066 setInitialState(mInitialState); 1067 } 1068 1069 class TetherMasterUtilState extends HierarchicalState { 1070 protected final static boolean TRY_TO_SETUP_MOBILE_CONNECTION = true; 1071 protected final static boolean WAIT_FOR_NETWORK_TO_SETTLE = false; 1072 1073 @Override 1074 public boolean processMessage(Message m) { 1075 return false; 1076 } 1077 protected int turnOnMobileConnection() { 1078 IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE); 1079 IConnectivityManager service = IConnectivityManager.Stub.asInterface(b); 1080 int retValue = Phone.APN_REQUEST_FAILED; 1081 try { 1082 retValue = service.startUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE, 1083 (mDunRequired ? Phone.FEATURE_ENABLE_DUN : Phone.FEATURE_ENABLE_HIPRI), 1084 new Binder()); 1085 } catch (Exception e) { 1086 } 1087 switch (retValue) { 1088 case Phone.APN_ALREADY_ACTIVE: 1089 case Phone.APN_REQUEST_STARTED: 1090 sendMessageDelayed(CMD_CELL_CONNECTION_RENEW, CELL_CONNECTION_RENEW_MS); 1091 mConnectionRequested = true; 1092 break; 1093 case Phone.APN_REQUEST_FAILED: 1094 default: 1095 mConnectionRequested = false; 1096 break; 1097 } 1098 1099 return retValue; 1100 } 1101 protected boolean turnOffMobileConnection() { 1102 if (mConnectionRequested) { 1103 IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE); 1104 IConnectivityManager service = 1105 IConnectivityManager.Stub.asInterface(b); 1106 try { 1107 service.stopUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE, 1108 (mDunRequired? Phone.FEATURE_ENABLE_DUN : 1109 Phone.FEATURE_ENABLE_HIPRI)); 1110 } catch (Exception e) { 1111 return false; 1112 } 1113 mConnectionRequested = false; 1114 } 1115 return true; 1116 } 1117 protected boolean turnOnMasterTetherSettings() { 1118 IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE); 1119 INetworkManagementService service = 1120 INetworkManagementService.Stub.asInterface(b); 1121 try { 1122 service.setIpForwardingEnabled(true); 1123 } catch (Exception e) { 1124 transitionTo(mSetIpForwardingEnabledErrorState); 1125 return false; 1126 } 1127 try { 1128 service.startTethering(mDhcpRange); 1129 } catch (Exception e) { 1130 transitionTo(mStartTetheringErrorState); 1131 return false; 1132 } 1133 try { 1134 service.setDnsForwarders(mDnsServers); 1135 } catch (Exception e) { 1136 transitionTo(mSetDnsForwardersErrorState); 1137 return false; 1138 } 1139 return true; 1140 } 1141 protected boolean turnOffMasterTetherSettings() { 1142 IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE); 1143 INetworkManagementService service = 1144 INetworkManagementService.Stub.asInterface(b); 1145 try { 1146 service.stopTethering(); 1147 } catch (Exception e) { 1148 transitionTo(mStopTetheringErrorState); 1149 return false; 1150 } 1151 try { 1152 service.setIpForwardingEnabled(false); 1153 } catch (Exception e) { 1154 transitionTo(mSetIpForwardingDisabledErrorState); 1155 return false; 1156 } 1157 transitionTo(mInitialState); 1158 return true; 1159 } 1160 protected String findActiveUpstreamIface() { 1161 // check for what iface we can use - if none found switch to error. 1162 IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE); 1163 INetworkManagementService service = INetworkManagementService.Stub.asInterface(b); 1164 1165 String[] ifaces = new String[0]; 1166 try { 1167 ifaces = service.listInterfaces(); 1168 } catch (Exception e) { 1169 Log.e(TAG, "Error listing Interfaces :" + e); 1170 return null; 1171 } 1172 1173 for (String regex : mUpstreamIfaceRegexs) { 1174 for (String iface : ifaces) { 1175 if (iface.matches(regex)) { 1176 // verify it is active 1177 InterfaceConfiguration ifcg = null; 1178 try { 1179 ifcg = service.getInterfaceConfig(iface); 1180 if (ifcg.isActive()) { 1181 return iface; 1182 } 1183 } catch (Exception e) { 1184 Log.e(TAG, "Error getting iface config :" + e); 1185 // ignore - try next 1186 continue; 1187 } 1188 } 1189 } 1190 } 1191 return null; 1192 } 1193 protected void chooseUpstreamType(boolean tryCell) { 1194 // decide if the current upstream is good or not and if not 1195 // do something about it (start up DUN if required or HiPri if not) 1196 String iface = findActiveUpstreamIface(); 1197 IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE); 1198 IConnectivityManager cm = IConnectivityManager.Stub.asInterface(b); 1199 mConnectionRequested = false; 1200 Log.d(TAG, "chooseUpstreamType(" + tryCell + "), dunRequired =" 1201 + mDunRequired + ", iface=" + iface); 1202 if (iface != null) { 1203 try { 1204 if (mDunRequired) { 1205 // check if Dun is on - we can use that 1206 NetworkInfo info = cm.getNetworkInfo( 1207 ConnectivityManager.TYPE_MOBILE_DUN); 1208 if (info.isConnected()) { 1209 Log.d(TAG, "setting dun ifacename =" + iface); 1210 // even if we're already connected - it may be somebody else's 1211 // refcount, so add our own 1212 turnOnMobileConnection(); 1213 } else { 1214 // verify the iface is not the default mobile - can't use that! 1215 info = cm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE); 1216 if (info.isConnected()) { 1217 iface = null; // can't accept this one 1218 } 1219 } 1220 } else { 1221 Log.d(TAG, "checking if hipri brought us this connection"); 1222 NetworkInfo info = cm.getNetworkInfo( 1223 ConnectivityManager.TYPE_MOBILE_HIPRI); 1224 if (info.isConnected()) { 1225 Log.d(TAG, "yes - hipri in use"); 1226 // even if we're already connected - it may be sombody else's 1227 // refcount, so add our own 1228 turnOnMobileConnection(); 1229 } 1230 } 1231 } catch (RemoteException e) { 1232 Log.e(TAG, "RemoteException calling ConnectivityManager " + e); 1233 iface = null; 1234 } 1235 } 1236 // may have been set to null in the if above 1237 if (iface == null ) { 1238 if (tryCell == TRY_TO_SETUP_MOBILE_CONNECTION) { 1239 turnOnMobileConnection(); 1240 } 1241 // wait for things to settle and retry 1242 sendMessageDelayed(CMD_RETRY_UPSTREAM, UPSTREAM_SETTLE_TIME_MS); 1243 } 1244 notifyTetheredOfNewUpstreamIface(iface); 1245 } 1246 protected void notifyTetheredOfNewUpstreamIface(String ifaceName) { 1247 Log.d(TAG, "notifying tethered with iface =" + ifaceName); 1248 mUpstreamIfaceName = ifaceName; 1249 for (Object o : mNotifyList) { 1250 TetherInterfaceSM sm = (TetherInterfaceSM)o; 1251 sm.sendMessage(TetherInterfaceSM.CMD_TETHER_CONNECTION_CHANGED, 1252 ifaceName); 1253 } 1254 } 1255 } 1256 1257 class InitialState extends TetherMasterUtilState { 1258 @Override 1259 public void enter() { 1260 mConnectionRequested = false; 1261 } 1262 @Override 1263 public boolean processMessage(Message message) { 1264 Log.d(TAG, "MasterInitialState.processMessage what=" + message.what); 1265 boolean retValue = true; 1266 switch (message.what) { 1267 case CMD_TETHER_MODE_REQUESTED: 1268 mDunRequired = isDunRequired(); 1269 TetherInterfaceSM who = (TetherInterfaceSM)message.obj; 1270 Log.d(TAG, "Tether Mode requested by " + who.toString()); 1271 mNotifyList.add(who); 1272 transitionTo(mTetherModeAliveState); 1273 break; 1274 case CMD_TETHER_MODE_UNREQUESTED: 1275 who = (TetherInterfaceSM)message.obj; 1276 Log.d(TAG, "Tether Mode unrequested by " + who.toString()); 1277 int index = mNotifyList.indexOf(who); 1278 if (index != -1) { 1279 mNotifyList.remove(who); 1280 } 1281 break; 1282 default: 1283 retValue = false; 1284 break; 1285 } 1286 return retValue; 1287 } 1288 } 1289 1290 class TetherModeAliveState extends TetherMasterUtilState { 1291 boolean mTryCell = WAIT_FOR_NETWORK_TO_SETTLE; 1292 @Override 1293 public void enter() { 1294 mTryCell = WAIT_FOR_NETWORK_TO_SETTLE; // first pass lets just see what we have. 1295 chooseUpstreamType(mTryCell); 1296 mTryCell = !mTryCell; 1297 turnOnMasterTetherSettings(); // may transition us out 1298 } 1299 @Override 1300 public void exit() { 1301 turnOffMobileConnection(); 1302 notifyTetheredOfNewUpstreamIface(null); 1303 } 1304 @Override 1305 public boolean processMessage(Message message) { 1306 Log.d(TAG, "TetherModeAliveState.processMessage what=" + message.what); 1307 boolean retValue = true; 1308 switch (message.what) { 1309 case CMD_TETHER_MODE_REQUESTED: 1310 TetherInterfaceSM who = (TetherInterfaceSM)message.obj; 1311 mNotifyList.add(who); 1312 who.sendMessage(TetherInterfaceSM.CMD_TETHER_CONNECTION_CHANGED, 1313 mUpstreamIfaceName); 1314 break; 1315 case CMD_TETHER_MODE_UNREQUESTED: 1316 who = (TetherInterfaceSM)message.obj; 1317 int index = mNotifyList.indexOf(who); 1318 if (index != -1) { 1319 mNotifyList.remove(index); 1320 if (mNotifyList.isEmpty()) { 1321 turnOffMasterTetherSettings(); // transitions appropriately 1322 } 1323 } 1324 break; 1325 case CMD_UPSTREAM_CHANGED: 1326 mTryCell = WAIT_FOR_NETWORK_TO_SETTLE; 1327 chooseUpstreamType(mTryCell); 1328 mTryCell = !mTryCell; 1329 break; 1330 case CMD_CELL_CONNECTION_RENEW: 1331 // make sure we're still using a requested connection - may have found 1332 // wifi or something since then. 1333 if (mConnectionRequested) { 1334 Log.d(TAG, "renewing mobile connection - requeuing for another " + 1335 CELL_CONNECTION_RENEW_MS + "ms"); 1336 turnOnMobileConnection(); 1337 } 1338 break; 1339 case CMD_RETRY_UPSTREAM: 1340 chooseUpstreamType(mTryCell); 1341 mTryCell = !mTryCell; 1342 break; 1343 default: 1344 retValue = false; 1345 break; 1346 } 1347 return retValue; 1348 } 1349 } 1350 1351 class ErrorState extends HierarchicalState { 1352 int mErrorNotification; 1353 @Override 1354 public boolean processMessage(Message message) { 1355 boolean retValue = true; 1356 switch (message.what) { 1357 case CMD_TETHER_MODE_REQUESTED: 1358 TetherInterfaceSM who = (TetherInterfaceSM)message.obj; 1359 who.sendMessage(mErrorNotification); 1360 break; 1361 default: 1362 retValue = false; 1363 } 1364 return retValue; 1365 } 1366 void notify(int msgType) { 1367 mErrorNotification = msgType; 1368 for (Object o : mNotifyList) { 1369 TetherInterfaceSM sm = (TetherInterfaceSM)o; 1370 sm.sendMessage(msgType); 1371 } 1372 } 1373 1374 } 1375 class SetIpForwardingEnabledErrorState extends ErrorState { 1376 @Override 1377 public void enter() { 1378 Log.e(TAG, "Error in setIpForwardingEnabled"); 1379 notify(TetherInterfaceSM.CMD_IP_FORWARDING_ENABLE_ERROR); 1380 } 1381 } 1382 1383 class SetIpForwardingDisabledErrorState extends ErrorState { 1384 @Override 1385 public void enter() { 1386 Log.e(TAG, "Error in setIpForwardingDisabled"); 1387 notify(TetherInterfaceSM.CMD_IP_FORWARDING_DISABLE_ERROR); 1388 } 1389 } 1390 1391 class StartTetheringErrorState extends ErrorState { 1392 @Override 1393 public void enter() { 1394 Log.e(TAG, "Error in startTethering"); 1395 notify(TetherInterfaceSM.CMD_START_TETHERING_ERROR); 1396 IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE); 1397 INetworkManagementService service = 1398 INetworkManagementService.Stub.asInterface(b); 1399 try { 1400 service.setIpForwardingEnabled(false); 1401 } catch (Exception e) {} 1402 } 1403 } 1404 1405 class StopTetheringErrorState extends ErrorState { 1406 @Override 1407 public void enter() { 1408 Log.e(TAG, "Error in stopTethering"); 1409 notify(TetherInterfaceSM.CMD_STOP_TETHERING_ERROR); 1410 IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE); 1411 INetworkManagementService service = 1412 INetworkManagementService.Stub.asInterface(b); 1413 try { 1414 service.setIpForwardingEnabled(false); 1415 } catch (Exception e) {} 1416 } 1417 } 1418 1419 class SetDnsForwardersErrorState extends ErrorState { 1420 @Override 1421 public void enter() { 1422 Log.e(TAG, "Error in setDnsForwarders"); 1423 notify(TetherInterfaceSM.CMD_SET_DNS_FORWARDERS_ERROR); 1424 IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE); 1425 INetworkManagementService service = 1426 INetworkManagementService.Stub.asInterface(b); 1427 try { 1428 service.stopTethering(); 1429 } catch (Exception e) {} 1430 try { 1431 service.setIpForwardingEnabled(false); 1432 } catch (Exception e) {} 1433 } 1434 } 1435 } 1436 1437 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1438 if (mContext.checkCallingOrSelfPermission( 1439 android.Manifest.permission.DUMP) != PackageManager.PERMISSION_GRANTED) { 1440 pw.println("Permission Denial: can't dump ConnectivityService.Tether " + 1441 "from from pid=" + Binder.getCallingPid() + ", uid=" + 1442 Binder.getCallingUid()); 1443 return; 1444 } 1445 1446 pw.println(); 1447 pw.println("Tether state:"); 1448 synchronized (mIfaces) { 1449 for (Object o : mIfaces.values()) { 1450 pw.println(" "+o.toString()); 1451 } 1452 } 1453 pw.println(); 1454 return; 1455 } 1456} 1457