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