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