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

Commit 707952ec authored by Jaikumar Ganesh's avatar Jaikumar Ganesh
Browse files

Rework Bluetooth tethering networking configuration.

Limit it to 5 for now, and store the iface.

Change-Id: Ia6044b8e8f886dcd587ab0bb57273e0c11b6cd74
parent 15107701
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