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

Commit 6205defc authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "PAN: Avoid reconfiguration of bt-pan interface in NAP role" into nyc-mr1-dev

parents 3904a93f 7f8bb949
Loading
Loading
Loading
Loading
+58 −60
Original line number Diff line number Diff line
@@ -67,6 +67,7 @@ public class PanService extends ProfileService {
    private ArrayList<String> mBluetoothIfaceAddresses;
    private int mMaxPanDevices;
    private String mPanIfName;
    private String mNapIfaceAddr;
    private boolean mNativeAvailable;

    private static final int MESSAGE_CONNECT = 1;
@@ -125,9 +126,6 @@ public class PanService extends ProfileService {
            }
            mPanDevices.clear();
        }
        if(mBluetoothIfaceAddresses != null) {
            mBluetoothIfaceAddresses.clear();
        }
        return true;
    }

@@ -389,13 +387,18 @@ public class PanService extends ProfileService {
                    remote_role);
        }
        int prevState;
        String ifaceAddr = null;

        BluetoothPanDevice panDevice = mPanDevices.get(device);
        if (panDevice == null) {
            Log.i(TAG, "state " + state + " Num of connected pan devices: " + mPanDevices.size());
            prevState = BluetoothProfile.STATE_DISCONNECTED;
            panDevice = new BluetoothPanDevice(state, iface, local_role);
            mPanDevices.put(device, panDevice);
        } else {
            prevState = panDevice.mState;
            ifaceAddr = panDevice.mIfaceAddr;
            panDevice.mState = state;
            panDevice.mLocalRole = local_role;
            panDevice.mIface = iface;
        }

        // Avoid race condition that gets this class stuck in STATE_DISCONNECTING. While we
@@ -413,19 +416,29 @@ public class PanService extends ProfileService {
        if (remote_role == BluetoothPan.LOCAL_PANU_ROLE) {
            if (state == BluetoothProfile.STATE_CONNECTED) {
                if ((!mTetherOn) || (local_role == BluetoothPan.LOCAL_PANU_ROLE)) {
                    Log.d(TAG,"handlePanDeviceStateChange BT tethering is off/Local role is PANU "+
                              "drop the connection");
                    Log.d(TAG, "handlePanDeviceStateChange BT tethering is off/Local role"
                            + " is PANU drop the connection");
                    mPanDevices.remove(device);
                    disconnectPanNative(Utils.getByteAddress(device));
                    return;
                }
                Log.d(TAG, "handlePanDeviceStateChange LOCAL_NAP_ROLE:REMOTE_PANU_ROLE");
                ifaceAddr = enableTethering(iface);
                if (ifaceAddr == null) Log.e(TAG, "Error seting up tether interface");

                if (mNapIfaceAddr == null) {
                    mNapIfaceAddr = startTethering(iface);
                    if (mNapIfaceAddr == null) {
                        Log.e(TAG, "Error seting up tether interface");
                        mPanDevices.remove(device);
                        disconnectPanNative(Utils.getByteAddress(device));
                        return;
                    }
                }
            } else if (state == BluetoothProfile.STATE_DISCONNECTED) {
                if (ifaceAddr != null) {
                    mBluetoothIfaceAddresses.remove(ifaceAddr);
                    ifaceAddr = null;
                mPanDevices.remove(device);
                Log.i(TAG, "remote(PANU) is disconnected, Remaining connected PANU devices: "
                        + mPanDevices.size());
                if (mNapIfaceAddr != null && mPanDevices.size() == 0) {
                    stopTethering(iface);
                    mNapIfaceAddr = null;
                }
            }
        } else if (mNetworkFactory != null) {
@@ -438,19 +451,10 @@ public class PanService extends ProfileService {
                   (prevState == BluetoothProfile.STATE_CONNECTED ||
                   prevState == BluetoothProfile.STATE_DISCONNECTING)) {
                mNetworkFactory.stopReverseTether();
                mPanDevices.remove(device);
            }
        }

        if (panDevice == null) {
            panDevice = new BluetoothPanDevice(state, ifaceAddr, iface, local_role);
            mPanDevices.put(device, panDevice);
        } else {
            panDevice.mState = state;
            panDevice.mIfaceAddr = ifaceAddr;
            panDevice.mLocalRole = local_role;
            panDevice.mIface = iface;
        }

        /* Notifying the connection state change of the profile before sending the intent for
           connection state change, as it was causing a race condition, with the UI not being
           updated with the correct connection state. */
@@ -465,9 +469,16 @@ public class PanService extends ProfileService {
        sendBroadcast(intent, BLUETOOTH_PERM);
    }

    // configured when we start tethering
    private String enableTethering(String iface) {
        if (DBG) Log.d(TAG, "updateTetherState:" + iface);
    private String startTethering(String iface) {
        return configureBtIface(true, iface);
    }

    private String stopTethering(String iface) {
        return configureBtIface(false, iface);
    }

    private String configureBtIface(boolean enable, String iface) {
        Log.i(TAG, "configureBtIface: " + iface + " enable: " + enable);

        IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
        INetworkManagementService service = INetworkManagementService.Stub.asInterface(b);
@@ -494,10 +505,8 @@ public class PanService extends ProfileService {

        if (!found) return null;

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

        InterfaceConfiguration ifcg = null;
        String address = null;
        try {
            ifcg = service.getInterfaceConfig(iface);
            if (ifcg != null) {
@@ -506,40 +515,35 @@ public class PanService extends ProfileService {
                if (linkAddr == null || (addr = linkAddr.getAddress()) == null ||
                        addr.equals(NetworkUtils.numericToInetAddress("0.0.0.0")) ||
                        addr.equals(NetworkUtils.numericToInetAddress("::0"))) {
                    address = BLUETOOTH_IFACE_ADDR_START;
                    addr = NetworkUtils.numericToInetAddress(address);
                }
                ifcg.setInterfaceUp();

                ifcg.setLinkAddress(new LinkAddress(addr, BLUETOOTH_PREFIX_LENGTH));
                if (enable) {
                    ifcg.setInterfaceUp();
                } else {
                    ifcg.setInterfaceDown();
                }

                ifcg.clearFlag("running");
                // TODO(BT) ifcg.interfaceFlags = ifcg.interfaceFlags.replace("  "," ");
                service.setInterfaceConfig(iface, ifcg);
                if (cm.tether(iface) != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
                    Log.e(TAG, "Error tethering "+iface);
                }
            }
        } catch (Exception e) {
            Log.e(TAG, "Error configuring interface " + iface + ", :" + e);
            return null;
        }
        return address;
    }

    private String createNewTetheringAddressLocked() {
        if (getConnectedPanDevices().size() == mMaxPanDevices) {
            if (DBG) Log.d(TAG, "Max PAN device connections reached");
                if (enable) {
                    int tetherStatus = cm.tether(iface);
                    if (tetherStatus != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
                        Log.e(TAG, "Error tethering "+ iface + " tetherStatus: " + tetherStatus);
                        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;
                    int untetherStatus = cm.untether(iface);
                    Log.i(TAG, "Untethered: "+ iface + " untetherStatus: " + untetherStatus);
                }
            }
        mBluetoothIfaceAddresses.add(address);
        } catch (Exception e) {
            Log.e(TAG, "Error configuring interface " + iface + ", :" + e);
            return null;
        }
        return address;
    }

@@ -572,21 +576,15 @@ public class PanService extends ProfileService {
        for (BluetoothDevice device : mPanDevices.keySet()) {
            println(sb, "  " + device + " : " + mPanDevices.get(device));
        }
        println(sb, "mBluetoothIfaceAddresses:");
        for (String address : mBluetoothIfaceAddresses) {
            println(sb, "  " + address);
        }
    }

    private class BluetoothPanDevice {
        private int mState;
        private String mIfaceAddr;
        private String mIface;
        private int mLocalRole; // Which local role is this PAN device bound to

        BluetoothPanDevice(int state, String ifaceAddr, String iface, int localRole) {
        BluetoothPanDevice(int state, String iface, int localRole) {
            mState = state;
            mIfaceAddr = ifaceAddr;
            mIface = iface;
            mLocalRole = localRole;
        }