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

Commit 4ffd870f authored by Łukasz Rymanowski's avatar Łukasz Rymanowski
Browse files

GattService: Fix server requests

When dual mode devices, which is using Identity address on both
transports, connects GATT on both directions then GATT response from the
GATT servers implemented in JAVA might not be multiplexed correctly
which  will lead to blocking ATT channel and eventually to ACL
disconnect due to GATT timeout.

Root cause for this is that mServerMap in GattService might contain two
entries for the same address but different connId, and when sendResponse
is received by the GattService, code does no guarante that correct
connId will be restored before sending response down to the native
stack.

This patch fixes it.

Bug: 356319811
Bug: 361331170
Test: atest GattServiceTest
Test: manual tests, connecting GATT over two transports and checking
GATT operations.
Flag: com.android.bluetooth.flags.gatt_server_requests_fix

Change-Id: I77a0b2a31413ee90c0c168567705ec4a38508d43
parent 63c95dd5
Loading
Loading
Loading
Loading
+21 −10
Original line number Diff line number Diff line
@@ -2913,7 +2913,7 @@ public class GattService extends ProfileService {
            return;
        }

        mHandleMap.addRequest(transId, handle);
        mHandleMap.addRequest(connId, transId, handle);

        ContextMap<IBluetoothGattServerCallback>.App app = mServerMap.getById(entry.serverIf);
        if (app == null) {
@@ -2944,7 +2944,7 @@ public class GattService extends ProfileService {
            return;
        }

        mHandleMap.addRequest(transId, handle);
        mHandleMap.addRequest(connId, transId, handle);

        ContextMap<IBluetoothGattServerCallback>.App app = mServerMap.getById(entry.serverIf);
        if (app == null) {
@@ -2985,7 +2985,7 @@ public class GattService extends ProfileService {
            return;
        }

        mHandleMap.addRequest(transId, handle);
        mHandleMap.addRequest(connId, transId, handle);

        ContextMap<IBluetoothGattServerCallback>.App app = mServerMap.getById(entry.serverIf);
        if (app == null) {
@@ -3027,7 +3027,7 @@ public class GattService extends ProfileService {
            return;
        }

        mHandleMap.addRequest(transId, handle);
        mHandleMap.addRequest(connId, transId, handle);

        ContextMap<IBluetoothGattServerCallback>.App app = mServerMap.getById(entry.serverIf);
        if (app == null) {
@@ -3311,15 +3311,26 @@ public class GattService extends ProfileService {
            return;
        }

        Log.v(TAG, "sendResponse() - address=" + address);
        Log.v(TAG, "sendResponse() - address=" + address + ", requestId=" + requestId);

        int handle = 0;
        Integer connId = 0;

        if (!Flags.gattServerRequestsFix()) {
            HandleMap.Entry entry = mHandleMap.getByRequestId(requestId);
            if (entry != null) {
                handle = entry.handle;
            }

        Integer connId = mServerMap.connIdByAddress(serverIf, address);
            connId = mServerMap.connIdByAddress(serverIf, address);
        } else {
            HandleMap.RequestData requestData = mHandleMap.getRequestDataByRequestId(requestId);
            if (requestData != null) {
                handle = requestData.mHandle;
                connId = requestData.mConnId;
            } else {
                connId = mServerMap.connIdByAddress(serverIf, address);
            }
        }
        mNativeInterface.gattServerSendResponse(
                serverIf,
                connId != null ? connId : 0,
+34 −5
Original line number Diff line number Diff line
@@ -86,13 +86,23 @@ class HandleMap {
        }
    }

    static class RequestData {
        int mConnId;
        int mHandle;

        RequestData(int connId, int handle) {
            mConnId = connId;
            mHandle = handle;
        }
    }

    List<Entry> mEntries = null;
    Map<Integer, Integer> mRequestMap = null;
    Map<Integer, RequestData> mRequestMap = null;
    int mLastCharacteristic = 0;

    HandleMap() {
        mEntries = new CopyOnWriteArrayList<Entry>();
        mRequestMap = new ConcurrentHashMap<Integer, Integer>();
        mRequestMap = new ConcurrentHashMap<Integer, RequestData>();
    }

    void clear() {
@@ -170,8 +180,8 @@ class HandleMap {
        return mEntries;
    }

    void addRequest(int requestId, int handle) {
        mRequestMap.put(requestId, handle);
    void addRequest(int connId, int requestId, int handle) {
        mRequestMap.put(requestId, new RequestData(connId, handle));
    }

    void deleteRequest(int requestId) {
@@ -179,7 +189,12 @@ class HandleMap {
    }

    Entry getByRequestId(int requestId) {
        Integer handle = mRequestMap.get(requestId);
        Integer handle = null;
        RequestData data = mRequestMap.get(requestId);
        if (data != null) {
            handle = data.mHandle;
        }

        if (handle == null) {
            Log.e(TAG, "getByRequestId() - Request ID " + requestId + " not found!");
            return null;
@@ -187,6 +202,20 @@ class HandleMap {
        return getByHandle(handle);
    }

    RequestData getRequestDataByRequestId(int requestId) {
        RequestData data = mRequestMap.get(requestId);
        if (data == null) {
            Log.e(TAG, "getRequestDataByRequestId() - Request ID " + requestId + " not found!");
        } else {
            Log.d(
                    TAG,
                    ("getRequestDataByRequestId(), requestId=" + requestId)
                            + (", connId=" + data.mConnId + ",handle=" + data.mHandle));
        }

        return data;
    }

    /** Logs debug information. */
    void dump(StringBuilder sb) {
        sb.append("  Entries: ").append(mEntries.size()).append("\n");