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