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