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