summaryrefslogtreecommitdiffstats
path: root/services/java/com/android/server/connectivity
diff options
context:
space:
mode:
authorMike Lockwood <lockwood@android.com>2011-07-19 13:04:47 -0700
committerMike Lockwood <lockwood@android.com>2011-07-23 21:57:55 -0400
commit6c2260b3af3a9243aa7f04cf03106f31817cb4c1 (patch)
treee4798968f479173d874e3f4211585f12b0f0ff97 /services/java/com/android/server/connectivity
parent40c4321df41eec6eba7e5001c7e13e9b7680b1fb (diff)
downloadframeworks_base-6c2260b3af3a9243aa7f04cf03106f31817cb4c1.zip
frameworks_base-6c2260b3af3a9243aa7f04cf03106f31817cb4c1.tar.gz
frameworks_base-6c2260b3af3a9243aa7f04cf03106f31817cb4c1.tar.bz2
Fix USB tethering
The previous approach no longer works with the new USB drivers, since the usb0 interface is no longer enabled by default. This introduced a chicken & egg problem - usb0 will not be enabled until the user tries to start tethering, but Settings will not enable the checkbox unless usb0 is enabled. To fix this we add an explicit call to start USB tethering in the connectivity manager. This will enable RNDIS if necessary and then bring up tethering once usb0 is enabled. Change-Id: Iae1f733366aa6b0dafa66d4c97207794173ef54b Signed-off-by: Mike Lockwood <lockwood@android.com>
Diffstat (limited to 'services/java/com/android/server/connectivity')
-rw-r--r--services/java/com/android/server/connectivity/Tethering.java173
1 files changed, 67 insertions, 106 deletions
diff --git a/services/java/com/android/server/connectivity/Tethering.java b/services/java/com/android/server/connectivity/Tethering.java
index 82bc505..7a5a641 100644
--- a/services/java/com/android/server/connectivity/Tethering.java
+++ b/services/java/com/android/server/connectivity/Tethering.java
@@ -36,7 +36,6 @@ import android.net.LinkProperties;
import android.net.NetworkInfo;
import android.net.NetworkUtils;
import android.os.Binder;
-import android.os.Environment;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
@@ -76,10 +75,6 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
private final static String TAG = "Tethering";
private final static boolean DEBUG = true;
- private boolean mBooted = false;
- //used to remember if we got connected before boot finished
- private boolean mDeferedUsbConnection = false;
-
// TODO - remove both of these - should be part of interface inspection/selection stuff
private String[] mTetherableUsbRegexs;
private String[] mTetherableWifiRegexs;
@@ -126,10 +121,9 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
private Notification mTetheredNotification;
- // whether we can tether is the && of these two - they come in as separate
- // broadcasts so track them so we can decide what to do when either changes
- private boolean mUsbMassStorageOff; // track the status of USB Mass Storage
- private boolean mUsbConnected; // track the status of USB connection
+ private boolean mRndisEnabled; // track the RNDIS function enabled state
+ private boolean mUsbTetherRequested; // true if USB tethering should be started
+ // when RNDIS is enabled
public Tethering(Context context, INetworkManagementService nmService, Looper looper) {
mContext = context;
@@ -149,7 +143,6 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
IntentFilter filter = new IntentFilter();
filter.addAction(UsbManager.ACTION_USB_STATE);
filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
- filter.addAction(Intent.ACTION_BOOT_COMPLETED);
mContext.registerReceiver(mStateReceiver, filter);
filter = new IntentFilter();
@@ -158,9 +151,6 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
filter.addDataScheme("file");
mContext.registerReceiver(mStateReceiver, filter);
- mUsbMassStorageOff = !Environment.MEDIA_SHARED.equals(
- Environment.getExternalStorageState());
-
mDhcpRange = context.getResources().getStringArray(
com.android.internal.R.array.config_tether_dhcp_range);
if ((mDhcpRange.length == 0) || (mDhcpRange.length % 2 ==1)) {
@@ -243,6 +233,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
}
return false;
}
+
public void interfaceAdded(String iface) {
boolean found = false;
boolean usb = false;
@@ -456,47 +447,28 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
}
}
- private void updateUsbStatus() {
- boolean enable = mUsbConnected && mUsbMassStorageOff;
-
- if (mBooted) {
- enableUsbIfaces(enable);
- }
- }
-
private class StateReceiver extends BroadcastReceiver {
public void onReceive(Context content, Intent intent) {
String action = intent.getAction();
if (action.equals(UsbManager.ACTION_USB_STATE)) {
- mUsbConnected = intent.getExtras().getBoolean(UsbManager.USB_CONNECTED);
- updateUsbStatus();
- } else if (action.equals(Intent.ACTION_MEDIA_SHARED)) {
- mUsbMassStorageOff = false;
- updateUsbStatus();
- }
- else if (action.equals(Intent.ACTION_MEDIA_UNSHARED)) {
- mUsbMassStorageOff = true;
- updateUsbStatus();
+ synchronized (Tethering.this) {
+ boolean usbConnected = intent.getBooleanExtra(UsbManager.USB_CONNECTED, false);
+ mRndisEnabled = intent.getBooleanExtra(UsbManager.USB_FUNCTION_RNDIS, false);
+ // start tethering if we have a request pending
+ if (usbConnected && mRndisEnabled && mUsbTetherRequested) {
+ tetherUsb(true);
+ }
+ mUsbTetherRequested = false;
+ }
} else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
if (DEBUG) Log.d(TAG, "Tethering got CONNECTIVITY_ACTION");
mTetherMasterSM.sendMessage(TetherMasterSM.CMD_UPSTREAM_CHANGED);
- } else if (action.equals(Intent.ACTION_BOOT_COMPLETED)) {
- mBooted = true;
- updateUsbStatus();
}
}
}
- // used on cable insert/remove
- private void enableUsbIfaces(boolean enable) {
- // add/remove USB interfaces when USB is connected/disconnected
- for (String intf : mTetherableUsbRegexs) {
- if (enable) {
- interfaceAdded(intf);
- } else {
- interfaceRemoved(intf);
- }
- }
+ private void tetherUsb(boolean enable) {
+ if (DEBUG) Log.d(TAG, "tetherUsb " + enable);
String[] ifaces = new String[0];
try {
@@ -507,83 +479,50 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
}
for (String iface : ifaces) {
if (isUsb(iface)) {
- if (enable) {
- interfaceAdded(iface);
- } else {
- interfaceRemoved(iface);
+ int result = (enable ? tether(iface) : untether(iface));
+ if (result == ConnectivityManager.TETHER_ERROR_NO_ERROR) {
+ return;
}
}
}
- }
-
- // toggled when we enter/leave the fully tethered state
- private boolean enableUsbRndis(boolean enabled) {
- if (DEBUG) Log.d(TAG, "enableUsbRndis(" + enabled + ")");
-
- UsbManager usbManager = (UsbManager)mContext.getSystemService(Context.USB_SERVICE);
- if (usbManager == null) {
- Log.d(TAG, "could not get UsbManager");
- return false;
- }
- try {
- if (enabled) {
- usbManager.setCurrentFunction(UsbManager.USB_FUNCTION_RNDIS, false);
- } else {
- usbManager.setCurrentFunction(null, false);
- }
- } catch (Exception e) {
- Log.e(TAG, "Error toggling usb RNDIS", e);
- return false;
- }
- return true;
+ Log.e(TAG, "unable start or stop USB tethering");
}
// configured when we start tethering and unconfig'd on error or conclusion
private boolean configureUsbIface(boolean enabled) {
if (DEBUG) Log.d(TAG, "configureUsbIface(" + enabled + ")");
- if (enabled) {
- // must enable RNDIS first to create the interface
- enableUsbRndis(enabled);
- }
-
+ // toggle the USB interfaces
+ String[] ifaces = new String[0];
try {
- // bring toggle the interfaces
- String[] ifaces = new String[0];
- try {
- ifaces = mNMService.listInterfaces();
- } catch (Exception e) {
- Log.e(TAG, "Error listing Interfaces", e);
- return false;
- }
- for (String iface : ifaces) {
- if (isUsb(iface)) {
- InterfaceConfiguration ifcg = null;
- try {
- ifcg = mNMService.getInterfaceConfig(iface);
- if (ifcg != null) {
- InetAddress addr = NetworkUtils.numericToInetAddress(USB_NEAR_IFACE_ADDR);
- ifcg.addr = new LinkAddress(addr, USB_PREFIX_LENGTH);
- if (enabled) {
- ifcg.interfaceFlags = ifcg.interfaceFlags.replace("down", "up");
- } else {
- ifcg.interfaceFlags = ifcg.interfaceFlags.replace("up", "down");
- }
- ifcg.interfaceFlags = ifcg.interfaceFlags.replace("running", "");
- ifcg.interfaceFlags = ifcg.interfaceFlags.replace(" "," ");
- mNMService.setInterfaceConfig(iface, ifcg);
+ ifaces = mNMService.listInterfaces();
+ } catch (Exception e) {
+ Log.e(TAG, "Error listing Interfaces", e);
+ return false;
+ }
+ for (String iface : ifaces) {
+ if (isUsb(iface)) {
+ InterfaceConfiguration ifcg = null;
+ try {
+ ifcg = mNMService.getInterfaceConfig(iface);
+ if (ifcg != null) {
+ InetAddress addr = NetworkUtils.numericToInetAddress(USB_NEAR_IFACE_ADDR);
+ ifcg.addr = new LinkAddress(addr, USB_PREFIX_LENGTH);
+ if (enabled) {
+ ifcg.interfaceFlags = ifcg.interfaceFlags.replace("down", "up");
+ } else {
+ ifcg.interfaceFlags = ifcg.interfaceFlags.replace("up", "down");
}
- } catch (Exception e) {
- Log.e(TAG, "Error configuring interface " + iface, e);
- return false;
+ ifcg.interfaceFlags = ifcg.interfaceFlags.replace("running", "");
+ ifcg.interfaceFlags = ifcg.interfaceFlags.replace(" "," ");
+ mNMService.setInterfaceConfig(iface, ifcg);
}
+ } catch (Exception e) {
+ Log.e(TAG, "Error configuring interface " + iface, e);
+ return false;
}
- }
- } finally {
- if (!enabled) {
- enableUsbRndis(false);
}
- }
+ }
return true;
}
@@ -600,6 +539,28 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
return mTetherableBluetoothRegexs;
}
+ public int setUsbTethering(boolean enable) {
+ UsbManager usbManager = (UsbManager)mContext.getSystemService(Context.USB_SERVICE);
+
+ synchronized (this) {
+ if (enable) {
+ if (mRndisEnabled) {
+ tetherUsb(true);
+ } else {
+ mUsbTetherRequested = true;
+ usbManager.setCurrentFunction(UsbManager.USB_FUNCTION_RNDIS, false);
+ }
+ } else {
+ tetherUsb(false);
+ if (mRndisEnabled) {
+ usbManager.setCurrentFunction(null, false);
+ }
+ mUsbTetherRequested = false;
+ }
+ }
+ return ConnectivityManager.TETHER_ERROR_NO_ERROR;
+ }
+
public int[] getUpstreamIfaceTypes() {
int values[] = new int[mUpstreamIfaceTypes.size()];
Iterator<Integer> iterator = mUpstreamIfaceTypes.iterator();