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

Commit 4c9a5be4 authored by Jaikumar Ganesh's avatar Jaikumar Ganesh Committed by Android (Google) Code Review
Browse files

Merge "Rework Bluetooth tethering networking configuration."

parents 22c0a58e 707952ec
Loading
Loading
Loading
Loading
+11 −6
Original line number Diff line number Diff line
@@ -463,9 +463,14 @@ class BluetoothEventLoop {
        }
        BluetoothDevice device = mAdapter.getRemoteDevice(address);
        if (name.equals("Connected")) {
            int state = propValues[1].equals("true") ? BluetoothInputDevice.STATE_CONNECTED :
                BluetoothInputDevice.STATE_DISCONNECTED;
            mBluetoothService.handlePanDeviceStateChange(device, state);
            if (propValues[1].equals("false")) {
                mBluetoothService.handlePanDeviceStateChange(device,
                                          BluetoothInputDevice.STATE_DISCONNECTED);
            }
        } else if (name.equals("Interface")) {
            String iface = propValues[1];
            mBluetoothService.handlePanDeviceStateChange(device, iface,
                                            BluetoothInputDevice.STATE_CONNECTED);
        }
    }

@@ -662,7 +667,7 @@ class BluetoothEventLoop {
                 Log.i(TAG, "Rejecting incoming HID connection from " + address);
             }
        } else if (BluetoothUuid.isBnep(uuid) || BluetoothUuid.isNap(uuid) &&
                mBluetoothService.isTetheringOn()){
                mBluetoothService.allowIncomingTethering()){
            authorized = true;
        } else {
            Log.i(TAG, "Rejecting incoming " + deviceUuid + " connection from " + address);
@@ -796,9 +801,9 @@ class BluetoothEventLoop {
        mBluetoothService.handlePanDeviceStateChange(device, BluetoothPan.STATE_DISCONNECTED);
    }

    private void onNetworkDeviceConnected(String address, int destUuid) {
    private void onNetworkDeviceConnected(String address, String iface, int destUuid) {
        BluetoothDevice device = mAdapter.getRemoteDevice(address);
        mBluetoothService.handlePanDeviceStateChange(device, BluetoothPan.STATE_CONNECTED);
        mBluetoothService.handlePanDeviceStateChange(device, iface, BluetoothPan.STATE_CONNECTED);
    }

    private void onRestartRequired() {
+112 −69
Original line number Diff line number Diff line
@@ -42,6 +42,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.res.Resources.NotFoundException;
import android.net.ConnectivityManager;
import android.net.InterfaceConfiguration;
import android.os.Binder;
@@ -114,7 +115,10 @@ public class BluetoothService extends IBluetooth.Stub {
    private static final int MESSAGE_DISCOVERABLE_TIMEOUT = 4;

    private ArrayList<String> mBluetoothIfaceAddresses;
    private static final String BLUETOOTH_NEAR_IFACE_ADDR_PREFIX= "192.168.44.";
    private int mMaxPanDevices;

    private static final String BLUETOOTH_IFACE_ADDR_START= "192.168.44.1";
    private static final int BLUETOOTH_MAX_PAN_CONNECTIONS = 5;
    private static final String BLUETOOTH_NETMASK        = "255.255.255.0";

    // The timeout used to sent the UUIDs Intent
@@ -144,9 +148,10 @@ public class BluetoothService extends IBluetooth.Stub {

    private BluetoothA2dpService mA2dpService;
    private final HashMap<BluetoothDevice, Integer> mInputDevices;
    private final HashMap<BluetoothDevice, Integer> mPanDevices;
    private final HashMap<BluetoothDevice, Pair<Integer, String>> mPanDevices;
    private final HashMap<String, Pair<byte[], byte[]>> mDeviceOobData;


    private static String mDockAddress;
    private String mDockPin;

@@ -211,10 +216,12 @@ public class BluetoothService extends IBluetooth.Stub {
        mHfpProfileState = new BluetoothProfileState(mContext, BluetoothProfileState.HFP);
        mHidProfileState = new BluetoothProfileState(mContext, BluetoothProfileState.HID);

        // Can tether to up to 7 devices
        mBluetoothIfaceAddresses = new ArrayList<String>(BluetoothPan.MAX_CONNECTIONS);
        for (int i=1; i <= BluetoothPan.MAX_CONNECTIONS; i++) {
            mBluetoothIfaceAddresses.add(BLUETOOTH_NEAR_IFACE_ADDR_PREFIX + i);
        mBluetoothIfaceAddresses = new ArrayList<String>();
        try {
            mMaxPanDevices = context.getResources().getInteger(
                            com.android.internal.R.integer.config_max_pan_devices);
        } catch (NotFoundException e) {
            mMaxPanDevices = BLUETOOTH_MAX_PAN_CONNECTIONS;
        }

        mHfpProfileState.start();
@@ -227,7 +234,7 @@ public class BluetoothService extends IBluetooth.Stub {
        filter.addAction(Intent.ACTION_DOCK_EVENT);
        mContext.registerReceiver(mReceiver, filter);
        mInputDevices = new HashMap<BluetoothDevice, Integer>();
        mPanDevices = new HashMap<BluetoothDevice, Integer>();
        mPanDevices = new HashMap<BluetoothDevice, Pair<Integer, String>>();
    }

    public static synchronized String readDockBluetoothAddress() {
@@ -1313,6 +1320,12 @@ public class BluetoothService extends IBluetooth.Stub {
        return mTetheringOn;
    }

    /*package*/ synchronized boolean allowIncomingTethering() {
        if (isTetheringOn() && getConnectedPanDevices().length < mMaxPanDevices)
            return true;
        return false;
    }

    private BroadcastReceiver mTetheringReceiver = null;

    public synchronized void setBluetoothTethering(boolean value) {
@@ -1342,10 +1355,11 @@ public class BluetoothService extends IBluetooth.Stub {
    public synchronized int getPanDeviceState(BluetoothDevice device) {
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");

        if (mPanDevices.get(device) == null) {
        Pair<Integer, String> panDevice = mPanDevices.get(device);
        if (panDevice == null) {
            return BluetoothPan.STATE_DISCONNECTED;
        }
        return mPanDevices.get(device);
        return panDevice.first;
    }

    public synchronized boolean connectPanDevice(BluetoothDevice device) {
@@ -1359,8 +1373,8 @@ public class BluetoothService extends IBluetooth.Stub {
        }

        int connectedCount = 0;
        for (BluetoothDevice BTdevice: mPanDevices.keySet()) {
            if (getPanDeviceState(BTdevice) == BluetoothPan.STATE_CONNECTED) {
        for (BluetoothDevice panDevice: mPanDevices.keySet()) {
            if (getPanDeviceState(panDevice) == BluetoothPan.STATE_CONNECTED) {
                connectedCount ++;
            }
        }
@@ -1419,21 +1433,33 @@ public class BluetoothService extends IBluetooth.Stub {
        return disconnectPanDeviceNative(objectPath);
    }

    /*package*/ void handlePanDeviceStateChange(BluetoothDevice device, int state) {
    /*package*/ synchronized void handlePanDeviceStateChange(BluetoothDevice device,
                                                             String iface,
                                                             int state) {
        int prevState;
        String ifaceAddr = null;

        if (mPanDevices.get(device) == null) {
            prevState = BluetoothPan.STATE_DISCONNECTED;
        } else {
            prevState = mPanDevices.get(device);
            prevState = mPanDevices.get(device).first;
            ifaceAddr = mPanDevices.get(device).second;
        }
        if (prevState == state) return;

        mPanDevices.put(device, state);

        if (state == BluetoothPan.STATE_CONNECTED) {
            updateTetherState(true);
            ifaceAddr = enableTethering(iface);
            if (ifaceAddr == null) Log.e(TAG, "Error seting up tether interface");
        } else if (state == BluetoothPan.STATE_DISCONNECTED) {
            if (ifaceAddr != null) {
                mBluetoothIfaceAddresses.remove(ifaceAddr);
                ifaceAddr = null;
            }
        }

        Pair<Integer, String> value = new Pair<Integer, String>(state, ifaceAddr);
        mPanDevices.put(device, value);

        Intent intent = new Intent(BluetoothPan.ACTION_PAN_STATE_CHANGED);
        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
        intent.putExtra(BluetoothPan.EXTRA_PREVIOUS_PAN_STATE, prevState);
@@ -1441,12 +1467,35 @@ public class BluetoothService extends IBluetooth.Stub {
        mContext.sendBroadcast(intent, BLUETOOTH_PERM);

        if (DBG) log("Pan Device state : device: " + device + " State:" + prevState + "->" + state);
    }

    /*package*/ synchronized void handlePanDeviceStateChange(BluetoothDevice device,
                                                             int state) {
        handlePanDeviceStateChange(device, null, state);
    }

    private String createNewTetheringAddressLocked() {
        if (getConnectedPanDevices().length == mMaxPanDevices) {
            log("Max PAN device connections reached");
            return null;
        }
        String address = BLUETOOTH_IFACE_ADDR_START;
        while (true) {
            if (mBluetoothIfaceAddresses.contains(address)) {
                String[] addr = address.split("\\.");
                Integer newIp = Integer.parseInt(addr[2]) + 1;
                address = address.replace(addr[2], newIp.toString());
            } else {
                break;
            }
        }
        mBluetoothIfaceAddresses.add(address);
        return address;
    }

    // configured when we start tethering and unconfig'd on error or conclusion
    private boolean updateTetherState(boolean enabled) {
        Log.d(TAG, "configureBluetoothIface(" + enabled + ")");
    // configured when we start tethering
    private synchronized String enableTethering(String iface) {
        log("updateTetherState:" + iface);

        IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
        INetworkManagementService service = INetworkManagementService.Stub.asInterface(b);
@@ -1455,64 +1504,58 @@ public class BluetoothService extends IBluetooth.Stub {
        String[] bluetoothRegexs = cm.getTetherableBluetoothRegexs();

        // bring toggle the interfaces
        String[] ifaces = new String[0];
        String[] currentIfaces = new String[0];
        try {
            ifaces = service.listInterfaces();
            currentIfaces = service.listInterfaces();
        } catch (Exception e) {
            Log.e(TAG, "Error listing Interfaces :" + e);
            return false;
            return null;
        }

        boolean found = false;
        for (String currIface: currentIfaces) {
            if (currIface.equals(iface)) {
                found = true;
                break;
            }
        }

        ArrayList<String> ifaceAddresses = (ArrayList<String>) mBluetoothIfaceAddresses.clone();
        for (String iface : ifaces) {
            for (String regex : bluetoothRegexs) {
                if (iface.matches(regex)) {
        if (!found) return null;

        String address = createNewTetheringAddressLocked();
        if (address == null) return null;

        InterfaceConfiguration ifcg = null;
        try {
            ifcg = service.getInterfaceConfig(iface);
            if (ifcg != null) {
                            if (enabled) {
                String[] addr = BLUETOOTH_NETMASK.split("\\.");
                ifcg.netmask = (Integer.parseInt(addr[0]) << 24) +
                        (Integer.parseInt(addr[1]) << 16) +
                        (Integer.parseInt(addr[2]) << 8) +
                        (Integer.parseInt(addr[3]));
                                if (ifcg.ipAddr == 0 && !ifaceAddresses.isEmpty()) {
                                    addr = ifaceAddresses.remove(0).split("\\.");
                if (ifcg.ipAddr == 0) {
                    addr = address.split("\\.");

                    ifcg.ipAddr = (Integer.parseInt(addr[0]) << 24) +
                            (Integer.parseInt(addr[1]) << 16) +
                            (Integer.parseInt(addr[2]) << 8) +
                            (Integer.parseInt(addr[3]));
                                } else {
                                    String IfaceAddress =
                                            String.valueOf(ifcg.ipAddr >>> 24) + "." +
                                            String.valueOf((ifcg.ipAddr & 0x00FF0000) >>> 16) + "." +
                                            String.valueOf((ifcg.ipAddr & 0x0000FF00) >>> 8) + "." +
                                            String.valueOf(ifcg.ipAddr & 0x000000FF);
                                    ifaceAddresses.remove(IfaceAddress);
                                }
                                ifcg.interfaceFlags = ifcg.interfaceFlags.replace("down", "up");
                            } else {
                                ifcg.interfaceFlags = ifcg.interfaceFlags.replace("up", "down");
                    ifcg.interfaceFlags =
                        ifcg.interfaceFlags.replace("down", "up");
                }
                ifcg.interfaceFlags = ifcg.interfaceFlags.replace("running", "");
                ifcg.interfaceFlags = ifcg.interfaceFlags.replace("  "," ");
                service.setInterfaceConfig(iface, ifcg);
                            if (enabled) {
                if (cm.tether(iface) != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
                                    Log.e(TAG, "Error tethering "+ifaces);
                                }
                    Log.e(TAG, "Error tethering "+iface);
                }
            }
        } catch (Exception e) {
            Log.e(TAG, "Error configuring interface " + iface + ", :" + e);
                        return false;
                    }
                }
            }
            return null;
        }

        return true;
        return address;
    }

    public synchronized boolean connectInputDevice(BluetoothDevice device) {
+4 −1
Original line number Diff line number Diff line
@@ -105,7 +105,7 @@ static void classInitNative(JNIEnv* env, jclass clazz) {
    method_onDeviceDisconnectRequested = env->GetMethodID(clazz, "onDeviceDisconnectRequested",
                                                        "(Ljava/lang/String;)V");
    method_onNetworkDeviceConnected = env->GetMethodID(clazz, "onNetworkDeviceConnected",
                                                              "(Ljava/lang/String;I)V");
                                                     "(Ljava/lang/String;Ljava/lang/String;I)V");
    method_onNetworkDeviceDisconnected = env->GetMethodID(clazz, "onNetworkDeviceDisconnected",
                                                              "(Ljava/lang/String;)V");

@@ -969,15 +969,18 @@ static DBusHandlerResult event_filter(DBusConnection *conn, DBusMessage *msg,
                                     "org.bluez.NetworkServer",
                                     "DeviceConnected")) {
       char *c_address;
       char *c_iface;
       uint16_t uuid;

       if (dbus_message_get_args(msg, &err,
                                  DBUS_TYPE_STRING, &c_address,
                                  DBUS_TYPE_STRING, &c_iface,
                                  DBUS_TYPE_UINT16, &uuid,
                                  DBUS_TYPE_INVALID)) {
           env->CallVoidMethod(nat->me,
                               method_onNetworkDeviceConnected,
                               env->NewStringUTF(c_address),
                               env->NewStringUTF(c_iface),
                               uuid);
       } else {
           LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg);
+4 −0
Original line number Diff line number Diff line
@@ -131,6 +131,10 @@
    <string-array translatable="false" name="config_tether_bluetooth_regexs">
    </string-array>

    <!-- Max number of Bluetooth tethering connections allowed. If this is
         updated config_tether_dhcp_range has to be updated appropriately. -->
    <integer translateable="false" name="config_max_pan_devices">5</integer>

    <!-- Dhcp range (min, max) to use for tethering purposes -->
    <string-array translatable="false" name="config_tether_dhcp_range">
    </string-array>
+23 −3
Original line number Diff line number Diff line
@@ -89,15 +89,27 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
    private static final String USB_NEAR_IFACE_ADDR      = "192.168.42.129";
    private static final String USB_NETMASK              = "255.255.255.0";

    // FYI - the default wifi is 192.168.43.1 and 255.255.255.0
    // USB is  192.168.42.1 and 255.255.255.0
    // Wifi is 192.168.43.1 and 255.255.255.0
    // BT is limited to max default of 5 connections. 192.168.44.1 to 192.168.48.1
    // with 255.255.255.0

    private String[] mDhcpRange;
    private static final String DHCP_DEFAULT_RANGE1_START = "192.168.42.2";
    private static final String DHCP_DEFAULT_RANGE1_STOP  = "192.168.42.254";
    private static final String DHCP_DEFAULT_RANGE2_START = "192.168.43.2";
    private static final String DHCP_DEFAULT_RANGE2_STOP  = "192.168.43.254";
    private static final String DHCP_DEFAULT_RANGE3_START = "192.168.44.9";
    private static final String DHCP_DEFAULT_RANGE3_START = "192.168.44.2";
    private static final String DHCP_DEFAULT_RANGE3_STOP  = "192.168.44.254";
    private static final String DHCP_DEFAULT_RANGE4_START = "192.168.45.2";
    private static final String DHCP_DEFAULT_RANGE4_STOP  = "192.168.45.254";
    private static final String DHCP_DEFAULT_RANGE5_START = "192.168.46.2";
    private static final String DHCP_DEFAULT_RANGE5_STOP  = "192.168.46.254";
    private static final String DHCP_DEFAULT_RANGE6_START = "192.168.47.2";
    private static final String DHCP_DEFAULT_RANGE6_STOP  = "192.168.47.254";
    private static final String DHCP_DEFAULT_RANGE7_START = "192.168.48.2";
    private static final String DHCP_DEFAULT_RANGE7_STOP  = "192.168.48.254";


    private String[] mDnsServers;
    private static final String DNS_DEFAULT_SERVER1 = "8.8.8.8";
@@ -165,13 +177,21 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
        mDhcpRange = context.getResources().getStringArray(
                com.android.internal.R.array.config_tether_dhcp_range);
        if ((mDhcpRange.length == 0) || (mDhcpRange.length % 2 ==1)) {
            mDhcpRange = new String[6];
            mDhcpRange = new String[14];
            mDhcpRange[0] = DHCP_DEFAULT_RANGE1_START;
            mDhcpRange[1] = DHCP_DEFAULT_RANGE1_STOP;
            mDhcpRange[2] = DHCP_DEFAULT_RANGE2_START;
            mDhcpRange[3] = DHCP_DEFAULT_RANGE2_STOP;
            mDhcpRange[4] = DHCP_DEFAULT_RANGE3_START;
            mDhcpRange[5] = DHCP_DEFAULT_RANGE3_STOP;
            mDhcpRange[6] = DHCP_DEFAULT_RANGE4_START;
            mDhcpRange[7] = DHCP_DEFAULT_RANGE4_STOP;
            mDhcpRange[8] = DHCP_DEFAULT_RANGE5_START;
            mDhcpRange[9] = DHCP_DEFAULT_RANGE5_STOP;
            mDhcpRange[10] = DHCP_DEFAULT_RANGE6_START;
            mDhcpRange[11] = DHCP_DEFAULT_RANGE6_STOP;
            mDhcpRange[12] = DHCP_DEFAULT_RANGE7_START;
            mDhcpRange[13] = DHCP_DEFAULT_RANGE7_STOP;
        }
        mDunRequired = false; // resample when we turn on