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

Commit 93365c94 authored by Łukasz Rymanowski's avatar Łukasz Rymanowski
Browse files

gatt: Fix reconnection on Bluetooth On.

When Bluetooth is turning On, Android tries to connect to any of the
known devices using direct connect allocating transport control blocks
(tcb). If there is more than 7 (GATT_MAX_PHY_CHANNEL) LE devices on the list,
only first 7 devices will be doing direct connect. Other devices will not be
connected unless user (usually gatt client application) does background connect.

However, if device from the background connect gets connected (ACL will
be created) during first 30 sec after BT is ON, the device will not be
connected to GATT as all tcbs are still in use for direct connect.

With this patch, TCB block is allocated when ACLs is established.

Bug: 325438660
Bug: 325595120
Test: mmm packages/modules/Bluetooth
Test: reconnect multiple devices on Bluetooth On
Test: multiple configuration tests e.g. having GATT_MAX_PHY_CHANNEL=1

Change-Id: I3cca7301c9e6d42fc6c9095215ecde1aec6d0b33
parent 89d49ce5
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -1051,6 +1051,7 @@ cc_test {
    shared_libs: [
        "libcrypto",
        "libcutils",
        "server_configurable_flags",
    ],
    static_libs: [
        "libbase",
@@ -1354,6 +1355,7 @@ cc_test {
    shared_libs: [
        "libcrypto",
        "libcutils",
        "server_configurable_flags",
    ],
    static_libs: [
        "libbase",
+14 −2
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@

#include "stack/include/gatt_api.h"

#include <android_bluetooth_flags.h>
#include <base/logging.h>
#include <base/strings/string_number_conversions.h>
#include <bluetooth/log.h>
@@ -47,6 +48,7 @@
#include "stack/include/bt_hdr.h"
#include "stack/include/bt_types.h"
#include "stack/include/bt_uuid16.h"
#include "stack/include/l2cap_acl_interface.h"
#include "stack/include/sdp_api.h"
#include "types/bluetooth/uuid.h"
#include "types/bt_transport.h"
@@ -1429,8 +1431,18 @@ bool GATT_Connect(tGATT_IF gatt_if, const RawAddress& bd_addr,
  if (is_direct) {
    log::debug("Starting direct connect gatt_if={} address={}", gatt_if,
               ADDRESS_TO_LOGGABLE_CSTR(bd_addr));
    ret =
        gatt_act_connect(p_reg, bd_addr, addr_type, transport, initiating_phys);
    bool tcb_exist = !!gatt_find_tcb_by_addr(bd_addr, transport);

    if (!IS_FLAG_ENABLED(gatt_reconnect_on_bt_on_fix) || tcb_exist) {
      /* Consider to remove gatt_act_connect at all */
      ret = gatt_act_connect(p_reg, bd_addr, addr_type, transport,
                             initiating_phys);
    } else {
      log::verbose("Connecting without tcb address: {}",
                   ADDRESS_TO_LOGGABLE_CSTR(bd_addr));
      ret = acl_create_le_connection_with_id(gatt_if, bd_addr, addr_type);
    }

  } else {
    log::debug("Starting background connect gatt_if={} address={}", gatt_if,
               ADDRESS_TO_LOGGABLE_CSTR(bd_addr));
+2 −0
Original line number Diff line number Diff line
@@ -422,6 +422,8 @@ void gatt_update_app_use_link_flag(tGATT_IF gatt_if, tGATT_TCB* p_tcb,
bool gatt_act_connect(tGATT_REG* p_reg, const RawAddress& bd_addr,
                      tBLE_ADDR_TYPE addr_type, tBT_TRANSPORT transport,
                      int8_t initiating_phys) {
  log::verbose("address:{}, transport:{}", ADDRESS_TO_LOGGABLE_CSTR(bd_addr),
               bt_transport_text(transport).c_str());
  tGATT_TCB* p_tcb = gatt_find_tcb_by_addr(bd_addr, transport);
  if (p_tcb != NULL) {
    /* before link down, another app try to open a GATT connection */
+29 −8
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@
 ******************************************************************************/
#define LOG_TAG "gatt_utils"

#include <android_bluetooth_flags.h>
#include <base/logging.h>
#include <base/strings/stringprintf.h>
#include <bluetooth/log.h>
@@ -1744,6 +1745,26 @@ void gatt_end_operation(tGATT_CLCB* p_clcb, tGATT_STATUS status, void* p_data) {
              fmt::ptr(p_disc_cmpl_cb), fmt::ptr(p_cmpl_cb));
}

static void gatt_le_disconnect_complete_notify_user(const RawAddress& bda,
                                                    tGATT_DISCONN_REASON reason,
                                                    tBT_TRANSPORT transport) {
  tGATT_TCB* p_tcb = gatt_find_tcb_by_addr(bda, transport);
  uint8_t tcb_idx = 0;

  if (p_tcb) {
    tcb_idx = p_tcb->tcb_idx;
  }

  for (uint8_t i = 0; i < GATT_MAX_APPS; i++) {
    tGATT_REG* p_reg = &gatt_cb.cl_rcb[i];
    if (p_reg->in_use && p_reg->app_cb.p_conn_cb) {
      uint16_t conn_id = GATT_CREATE_CONN_ID(tcb_idx, p_reg->gatt_if);
      (*p_reg->app_cb.p_conn_cb)(p_reg->gatt_if, bda, conn_id,
                                 kGattDisconnected, reason, transport);
    }
  }
}

/** This function cleans up the control blocks when L2CAP channel disconnect */
void gatt_cleanup_upon_disc(const RawAddress& bda, tGATT_DISCONN_REASON reason,
                            tBT_TRANSPORT transport) {
@@ -1755,6 +1776,13 @@ void gatt_cleanup_upon_disc(const RawAddress& bda, tGATT_DISCONN_REASON reason,
        "Disconnect for unknown connection bd_addr:{} reason:{} transport:{}",
        ADDRESS_TO_LOGGABLE_CSTR(bda), gatt_disconnection_reason_text(reason),
        bt_transport_text(transport));

    if (!IS_FLAG_ENABLED(gatt_reconnect_on_bt_on_fix)) {
      return;
    }

    /* Notify about timeout on direct connect */
    gatt_le_disconnect_complete_notify_user(bda, reason, transport);
    return;
  }

@@ -1793,14 +1821,7 @@ void gatt_cleanup_upon_disc(const RawAddress& bda, tGATT_DISCONN_REASON reason,
  fixed_queue_free(p_tcb->sr_cmd.multi_rsp_q, NULL);
  p_tcb->sr_cmd.multi_rsp_q = NULL;

  for (uint8_t i = 0; i < GATT_MAX_APPS; i++) {
    tGATT_REG* p_reg = &gatt_cb.cl_rcb[i];
    if (p_reg->in_use && p_reg->app_cb.p_conn_cb) {
      uint16_t conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, p_reg->gatt_if);
      (*p_reg->app_cb.p_conn_cb)(p_reg->gatt_if, bda, conn_id,
                                 kGattDisconnected, reason, transport);
    }
  }
  gatt_le_disconnect_complete_notify_user(bda, reason, transport);

  *p_tcb = tGATT_TCB();
  log::verbose("exit");