From fe85d07eca1b97ea667caa5cdd6b3fab59670188 Mon Sep 17 00:00:00 2001 From: Nitin Shivpure Date: Thu, 16 Jun 2016 20:45:29 +0530 Subject: [PATCH] PAN: Avoid reconfiguration of bt-pan interface in NAP role Issue: Browsing is not working with multiple remote PANU Device(s). Root Cause: When the 1st remote PANU is connected, the bt-pan interface gets configured. As soon as 2nd PANU is connected, the bt-pan interface goes into a bad state. The second device is able to write Ethernet packets on the bt-pan interface (TUN driver) after reconfiguration, but it is unable to read Ethernet packets from the interface. Fix: If the bt-pan interface is already configured in the NAP role, then do not reconfigure bt-pan when the 2nd PANU is connected. Bug: 29992925 Change-Id: Ib6e0cb91d573649af45ffe25c7095a4bd74a5022 --- src/com/android/bluetooth/pan/PanService.java | 118 +++++++++++++------------- 1 file changed, 58 insertions(+), 60 deletions(-) diff --git a/src/com/android/bluetooth/pan/PanService.java b/src/com/android/bluetooth/pan/PanService.java index ea9b97ed..6456b7dd 100755 --- a/src/com/android/bluetooth/pan/PanService.java +++ b/src/com/android/bluetooth/pan/PanService.java @@ -67,6 +67,7 @@ public class PanService extends ProfileService { private ArrayList 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 @@ -412,20 +415,30 @@ public class PanService extends ProfileService { if (prevState == state) return; 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"); + if ((!mTetherOn) || (local_role == BluetoothPan.LOCAL_PANU_ROLE)) { + 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,15 +515,29 @@ 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); + + if (enable) { + int tetherStatus = cm.tether(iface); + if (tetherStatus != ConnectivityManager.TETHER_ERROR_NO_ERROR) { + Log.e(TAG, "Error tethering "+ iface + " tetherStatus: " + tetherStatus); + return null; + } + } else { + int untetherStatus = cm.untether(iface); + Log.i(TAG, "Untethered: "+ iface + " untetherStatus: " + untetherStatus); } } } catch (Exception e) { @@ -524,25 +547,6 @@ public class PanService extends ProfileService { return address; } - private String createNewTetheringAddressLocked() { - if (getConnectedPanDevices().size() == mMaxPanDevices) { - if (DBG) Log.d(TAG, "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; - } - private List getConnectedPanDevices() { List devices = new ArrayList(); @@ -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; } -- 2.11.0