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