Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5db7af96 authored by Mike Lockwood's avatar Mike Lockwood Committed by Android (Google) Code Review
Browse files

Merge "Fix USB tethering"

parents ab45c768 6c2260b3
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -653,6 +653,17 @@ public class ConnectivityManager {
        }
    }

    /**
     * {@hide}
     */
    public int setUsbTethering(boolean enable) {
        try {
            return mService.setUsbTethering(enable);
        } catch (RemoteException e) {
            return TETHER_ERROR_SERVICE_UNAVAIL;
        }
    }

    /** {@hide} */
    public static final int TETHER_ERROR_NO_ERROR           = 0;
    /** {@hide} */
+2 −0
Original line number Diff line number Diff line
@@ -88,6 +88,8 @@ interface IConnectivityManager

    String[] getTetherableBluetoothRegexs();

    int setUsbTethering(boolean enable);

    void requestNetworkTransitionWakelock(in String forWhom);

    void reportInetCondition(int networkType, int percentage);
+9 −0
Original line number Diff line number Diff line
@@ -2262,6 +2262,15 @@ public class ConnectivityService extends IConnectivityManager.Stub {
        }
    }

    public int setUsbTethering(boolean enable) {
        enforceTetherAccessPermission();
        if (isTetheringSupported()) {
            return mTethering.setUsbTethering(enable);
        } else {
            return ConnectivityManager.TETHER_ERROR_UNSUPPORTED;
        }
    }

    // TODO - move iface listing, queries, etc to new module
    // javadoc from interface
    public String[] getTetherableIfaces() {
+67 −106
Original line number Diff line number Diff line
@@ -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,48 +479,20 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
        }
        for (String iface : ifaces) {
            if (isUsb(iface)) {
                if (enable) {
                    interfaceAdded(iface);
                } else {
                    interfaceRemoved(iface);
                }
            }
        }
    }

    // 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;
                int result = (enable ? tether(iface) : untether(iface));
                if (result == ConnectivityManager.TETHER_ERROR_NO_ERROR) {
                    return;
                }
        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);
        }

        try {
            // bring toggle the interfaces
        // toggle the USB interfaces
        String[] ifaces = new String[0];
        try {
            ifaces = mNMService.listInterfaces();
@@ -579,11 +523,6 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
                }
            }
         }
        } 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();