bta_sys_sendmsg、bta_gattc_cback、HAL_CBACK

一、bta_sys_sendmsg

void bta_sys_sendmsg(void* p_msg)

功能:在bt_main_thread线程执行bta_sys_cb.reg[id]->evt_hdlr(p_msg),其中id是p_msg->event归属的消息类别。

如何快速判断bta_sys_cb.reg[id]->evt_hdlr指向哪个函数,这分三步。

  1. 找到p_msg->event消息码的类别。这从对它的定义能看到。针对消息码BTA_GATTC_API_OPEN_EVT,它的消息类别是BTA_ID_GATTC,
  2. bta_sys_register(id, p_reg)用于把消息码处理函数赋值给bta_sys_cb.reg,找到以第一个参数是该消息码类别的调用bta_sys_register代码。这时第二个参数记为p_reg。针对BTA_GATTC_API_OPEN_EVT,赋值bta_sys_cb.reg[id]时的调用代码是bta_sys_register(BTA_ID_GATTC, &bta_gattc_reg),第二个参数是bta_gattc_reg。
  3. p_reg->evt_hdlr就是我们要找到的消息处理函数。针对BTA_GATTC_API_OPEN_EVT,bta_gattc_reg.evt_hdlr是bta_gattc_hdl_event,它就要找的消息处理函数

接下让进入代码。

<aosp>/system/bt/bta/sys/bta_sys_main.cc
------
void bta_sys_sendmsg(void* p_msg) {
  if (do_in_main_thread(
          FROM_HERE,
          base::Bind(&bta_sys_event, static_cast<BT_HDR_RIGID*>(p_msg))) !=
      BT_STATUS_SUCCESS) {
    LOG(ERROR) << __func__ << ": do_in_main_thread failed";
  }
}

<aosp>/system/bt/bta/sys/bta_sys_main.cc
------
static void bta_sys_event(BT_HDR_RIGID* p_msg) {
  uint8_t id;
  bool freebuf = true;

  APPL_TRACE_EVENT("%s: Event 0x%x", __func__, p_msg->event);

  /* get subsystem id from event */
  id = (uint8_t)(p_msg->event >> 8);

  /* verify id and call subsystem event handler */
  if ((id < BTA_ID_MAX) && (bta_sys_cb.reg[id] != NULL)) {
    freebuf = (*bta_sys_cb.reg[id]->evt_hdlr)(p_msg);
  } else {
    LOG_INFO("Ignoring receipt of unregistered event id:%s",
             BtaIdSysText(id).c_str());
  }

  if (freebuf) {
    osi_free(p_msg);
  }
}

bta_sys_sendmsg做的是让在bt_main_thread线程执行bta_sys_event,内中着重调用以下这条语句。

freebuf = (*bta_sys_cb.reg[id]->evt_hdlr)(p_msg);

要理解这个,首先说下bt协议栈定义消息码的机制,当然,这些消息码不是蓝牙标准,只是bt协议栈内部使用。

#define BTA_ID_GATTC 31         /* GATT Client */
#define BTA_SYS_EVT_START(id) ((id) << 8)

enum {
  BTA_GATTC_API_OPEN_EVT = BTA_SYS_EVT_START(BTA_ID_GATTC),
  BTA_GATTC_INT_OPEN_FAIL_EVT,
  BTA_GATTC_API_CANCEL_OPEN_EVT,
  BTA_GATTC_INT_CANCEL_OPEN_OK_EVT,

  BTA_GATTC_API_READ_EVT,
  BTA_GATTC_API_WRITE_EVT,
  BTA_GATTC_API_EXEC_EVT,
  BTA_GATTC_API_CFG_MTU_EVT,

  BTA_GATTC_API_CLOSE_EVT,

  BTA_GATTC_API_SEARCH_EVT,
  ...
};

<apsp>/system/bt/bta/sys/bta_sys_int.h
------
/* system manager control block */
typedef struct {
  tBTA_SYS_REG* reg[BTA_ID_MAX]; /* registration structures */
  bool is_reg[BTA_ID_MAX];       /* registration structures */
  bool forward_hw_failures;
  uint16_t sys_features;         /* Bitmask of sys features */

  ......

} tBTA_SYS_CB;

<aosp>/system/bt/bta/sys/bta_sys.h
------
/* registration structure */
typedef struct {
  tBTA_SYS_EVT_HDLR* evt_hdlr;
  tBTA_SYS_DISABLE* disable;
} tBTA_SYS_REG;

<aosp>/system/bt/bta/sys/bta_sys_main.cc
------
void bta_sys_register(uint8_t id, const tBTA_SYS_REG* p_reg) {
  bta_sys_cb.reg[id] = (tBTA_SYS_REG*)p_reg;
  bta_sys_cb.is_reg[id] = true;
}

<aosp>/system/bt/bta/gatt/bta_gattc_api.cc
------
void BTA_GATTC_AppRegister(tBTA_GATTC_CBACK* p_client_cb,
                           BtaAppRegisterCallback cb, bool eatt_support) {
  if (!bta_sys_is_register(BTA_ID_GATTC))
    bta_sys_register(BTA_ID_GATTC, &bta_gattc_reg);

  do_in_main_thread(
      FROM_HERE, base::Bind(&bta_gattc_register, Uuid::GetRandom(), p_client_cb,
                            std::move(cb), eatt_support));
}

<aosp>/system/bt/bta/gatt\bta_gattc_api.cc
------
static const tBTA_SYS_REG bta_gattc_reg = {bta_gattc_hdl_event,
                                           BTA_GATTC_Disable};
  1. 将消息码进行分类,消息码16位,高8位是类别,低8位是该类别下的二级值。以BTA_GATTC_API_OPEN_EVT为例,它属于BTA_ID_GATTC这个类别,在该类别下,它的二级码是0。同样的,BTA_GATTC_API_SEARCH_EVT也属于BTA_ID_GATTC类别,二级值则是9。
  2. 既然定义了消息码,那就需要实现处理这些消息的函数,这些函数被集中放在一个全局变量:tBTA_SYS_CB bta_sys_cb,具体是当中的reg[BTA_ID_MAX]。
  3. reg[BTA_ID_MAX]中的一单元对应处理某一类别的消息码。举个例子,reg[BTA_ID_GATTC]对应处理BTA_ID_GATTC类别的消息码,像BTA_GATTC_API_OPEN_EVT、BTA_GATTC_API_SEARCH_EVT。
  4. bta_sys_register(uint8_t id, const tBTA_SYS_REG* p_reg)执行着将具体消息处理函数赋值到bta_sys_cb。对不同消息类型,这赋值时机自然是不同的,具体到BTA_ID_GATTC,那就是btif_gattc_register_app时的BTA_GATTC_AppRegister。
freebuf = (*bta_sys_cb.reg[id]->evt_hdlr)(p_msg);

结合以上规则,再看上面这条语句,对消息码BTA_GATTC_API_OPEN_EVT,那就是:freebuf = bta_gattc_hdl_event(p_msg)。

 

二、bta_gattc_cback、btif_gattc_upstreams_evt

void bta_gattc_cback(tBTA_GATTC_EVT event, tBTA_GATTC* p_data);

常以类似下面语句被调用,p_clreg->p_cback就是bta_gattc_cback
(*p_clreg->p_cback)(BTA_GATTC_OPEN_EVT, &cb_data);

bta_gattc_cback功能:在bt_jni_thread线程执行btif_gattc_upstreams_evt(event, p_data),参数event、p_data分别是传给bta_gattc_cback的第一、第二个参数。

又因为btif_gattc_upstreams_evt主要工作是调用HAL_CBACK,这是一个宏,它的功能是用于回调bt-JNI注册到bt协议栈函数,换句话说,bta_gattc_cback用于bt协议栈把此次操作的处理结果反馈到bt-JNI。

以上是结论,接下进入分析过程。bt协议栈:connectGatt之btif_gattc_open中有写,btif_gattc_open通过调用bta_gattc_send_open_cback,把此次处理结果反馈到bt-JNI。

<aosp>/system/bt/bta/gatt/bta_gattc_utils.cc
------
void bta_gattc_send_open_cback(tBTA_GATTC_RCB* p_clreg, tGATT_STATUS status,
                               const RawAddress& remote_bda, uint16_t conn_id,
                               tBT_TRANSPORT transport, uint16_t mtu) {
  tBTA_GATTC cb_data;

  if (p_clreg->p_cback) {
    memset(&cb_data, 0, sizeof(tBTA_GATTC));

    cb_data.open.status = status;
    cb_data.open.client_if = p_clreg->client_if;
    cb_data.open.conn_id = conn_id;
    cb_data.open.mtu = mtu;
    cb_data.open.transport = transport;
    cb_data.open.remote_bda = remote_bda;

    (*p_clreg->p_cback)(BTA_GATTC_OPEN_EVT, &cb_data);
  }
}

在bta_gattc_send_open_cback,生成cb_data结构后,以它为参数调用p_clreg->p_cback,那这个p_clcb来自哪里?

回看“图1 bta_gattc_cb”,p_clreg就是cl_rcb[BTA_GATTC_CL_MAX]数组中的某个cl_rcb。cl_rcb是全局数组的一个单元,内存分配不用管了,那它何时填充有效数据?——我们知道连接peripheral时第一个操作是btif_gattc_register_app,也就是在那时填充了cl_rcb。

<aosp>/system/bt/bta/gatt/bta_gattc_act.cc
------
/** Register a GATT client application with BTA */
void bta_gattc_register(const Uuid& app_uuid, tBTA_GATTC_CBACK* p_cback,
                        BtaAppRegisterCallback cb, bool eatt_suppport) {
  ...

  for (uint8_t i = 0; i < BTA_GATTC_CL_MAX; i++) {
    if (!bta_gattc_cb.cl_rcb[i].in_use) {
      if ((bta_gattc_cb.cl_rcb[i].client_if = GATT_Register(
               app_uuid, "GattClient", &bta_gattc_cl_cback, eatt_suppport)) ==
          0) {
        ...
      } else {
        bta_gattc_cb.cl_rcb[i].in_use = true;

        // p_cback是传给BTA_GATTC_AppRegister的第一个参数,即bta_gattc_cback
        bta_gattc_cb.cl_rcb[i].p_cback = p_cback;
        ...
        break;
      }
    }
  }
  ...
}

bt协议栈:connectGatt之btif_gattc_register_app有细说bta_gattc_registe,它有4个操作,其中第二个是给bta_gattc_cb.cl_rcb[i]各字段赋值,当中有包括p_cback。右侧的参数p_cback来自哪里?——是传给BTA_GATTC_AppRegister的第一个参数,即全局变量bta_gattc_cback。深入bta_gattc_cback,看它执行了什么。

<aosp>/system/bt/btif/src/btif_gatt_client.cc
------
static void bta_gattc_cback(tBTA_GATTC_EVT event, tBTA_GATTC* p_data) {
  bt_status_t status =
      btif_transfer_context(btif_gattc_upstreams_evt, (uint16_t)event,
                            (char*)p_data, sizeof(tBTA_GATTC), NULL);
  ASSERTC(status == BT_STATUS_SUCCESS, "Context transfer failed!", status);
}

<aosp>/system/bt/btif/src/btif_core.cc
------
bt_status_t btif_transfer_context(tBTIF_CBACK* p_cback, uint16_t event,
                                  char* p_params, int param_len,
                                  tBTIF_COPY_CBACK* p_copy_cback) {
  tBTIF_CONTEXT_SWITCH_CBACK* p_msg = (tBTIF_CONTEXT_SWITCH_CBACK*)osi_malloc(
      sizeof(tBTIF_CONTEXT_SWITCH_CBACK) + param_len);

  BTIF_TRACE_VERBOSE("btif_transfer_context event %d, len %d", event,
                     param_len);

  /* allocate and send message that will be executed in btif context */
  p_msg->hdr.event = BT_EVT_CONTEXT_SWITCH_EVT; /* internal event */
  // p_cback指向btif_gattc_upstreams_evt,它赋值给p_msg->p_cb
  p_msg->p_cb = p_cback;
  // event来自传给bta_gattc_cback的第一个参数,示例是BTA_GATTC_OPEN_EVT
  p_msg->event = event; /* callback event */

  /* check if caller has provided a copy callback to do the deep copy */
  if (p_copy_cback) {
    p_copy_cback(event, p_msg->p_param, p_params);
  } else if (p_params) {
    // 源p_params来自传给bta_gattc_cback的第二个参数p_data,示例是“&cb_data”。
    memcpy(p_msg->p_param, p_params, param_len); /* callback parameter data */
  }

  do_in_jni_thread(base::Bind(&bt_jni_msg_ready, p_msg));
  return BT_STATUS_SUCCESS;
}

static void bt_jni_msg_ready(void* context) {
  tBTIF_CONTEXT_SWITCH_CBACK* p = (tBTIF_CONTEXT_SWITCH_CBACK*)context;
  if (p->p_cb) p->p_cb(p->event, p->p_param);
  osi_free(p);
}

bta_gattc_cback以p_copy_cback==nullptr调用btif_transfer_context,结合btif_transfer_context、bt_jni_msg_ready代码,可小结bta_gattc_cback功能:在bt_jni_thread线程执行btif_gattc_upstreams_evt(event, p_data),参数event、p_data分别是传给bta_gattc_cback的第一、第二个参数。

<aosp>/system/bt/btif/src/btif_gatt_client.cc
------
static void btif_gattc_upstreams_evt(uint16_t event, char* p_param) {
  tBTA_GATTC* p_data = (tBTA_GATTC*)p_param;
  switch (event) {
    ...
    case BTA_GATTC_OPEN_EVT: {
      DVLOG(1) << "BTA_GATTC_OPEN_EVT " << p_data->open.remote_bda;
      HAL_CBACK(bt_gatt_callbacks, client->open_cb, p_data->open.conn_id,
                p_data->open.status, p_data->open.client_if,
                p_data->open.remote_bda);

      if (GATT_DEF_BLE_MTU_SIZE != p_data->open.mtu && p_data->open.mtu) {
        HAL_CBACK(bt_gatt_callbacks, client->configure_mtu_cb,
                  p_data->open.conn_id, p_data->open.status, p_data->open.mtu);
      }

      if (p_data->open.status == GATT_SUCCESS)
        btif_gatt_check_encrypted_link(p_data->open.remote_bda,
                                       p_data->open.transport);
      break;
    }

    case BTA_GATTC_CLOSE_EVT: {
      HAL_CBACK(bt_gatt_callbacks, client->close_cb, p_data->close.conn_id,
                p_data->close.status, p_data->close.client_if,
                p_data->close.remote_bda);
      break;
    }
    ...

    default:
      LOG_ERROR("Unhandled event (%d)!", event);
      break;
  }
}

在btif_gattc_upstreams_evt,它的主要工作就是调用HAL_CBACK,这是一个宏,它的功能是用于回调bt-JNI注册到bt协议栈函数,换句话说,bt协议栈把此次处理结果反馈到bt-JNI。

 

三、HAL_CBACK

#define HAL_CBACK(P_CB, P_CBACK, ...)   

HAL_CBACK是一个宏,调用时一般采用下面形式

HAL_CBACK(bt_gatt_callbacks, client->register_client_cb, status, client_id, uuid);
HAL_CBACK(bt_gatt_callbacks, client->open_cb, p_data->open.conn_id,
                p_data->open.status, p_data->open.client_if,
                p_data->open.remote_bda);

第一个参数是一个结构s,第二个参数是结构s中的一个字段,是函数f,后面则是要传给函数f的参数。如果第一个参数是bt_gatt_callbacks,第二个参数又是“client->”为前缀,那HAL_CBACK功能是执行位在bt-JNI内的、变量sGattClientCallbacks中的某个函数。在用途上,一般用于bt协议栈把此次操作结果返馈给bt-JNI。

struct btgatt_client_callbacks_t(bt-JNI)sGattClientCallbacks中函数 bt协议栈操作/调用时机
register_client_cbbtgattc_register_app_cbbtif_gattc_register_app
open_cb btgattc_open_cbbtif_gattc_open
close_cbbtgattc_close_cb 
search_complete_cbbtgattc_search_complete_cbbtif_gattc_search_service
.........

以“HAL_CBACK(bt_gatt_callbacks, client->register_client_cb, status, client_id, uuid)”为例,分析HAL_CBACK。

<aosp>/system/bt/btif/include/btif_common.h
------
#define HAL_CBACK(P_CB, P_CBACK, ...)                              \
  do {                                                             \
    if ((P_CB) && (P_CB)->P_CBACK) {                               \
      BTIF_TRACE_API("%s: HAL %s->%s", __func__, #P_CB, #P_CBACK); \
      (P_CB)->P_CBACK(__VA_ARGS__);                                \
    } else {                                                       \
      ASSERTC(0, "Callback is NULL", 0);                           \
    }                                                              \
  } while (0)

这里展开一下,并替换其中实际的变量:

bt_gatt_callbacks->client->register_client_cb(status, client_if, uuid);

可以看到这里就是执行一个回调函数。

现在问题是bt_gatt_callbacks是谁?我们可以看到它是在btif_gatt_init初始化的:

const btgatt_callbacks_t* bt_gatt_callbacks;
<aosp>/system/bt/btif/src/btif_gatt.c
------
static bt_status_t btif_gatt_init(const btgatt_callbacks_t* callbacks) {
  bt_gatt_callbacks = callbacks;
  return BT_STATUS_SUCCESS;
}

<aosp>/system/bt/btif/src/btif_gatt.cc
------
static btgatt_interface_t btgattInterface = {
    .size = sizeof(btgattInterface),

    .init = btif_gatt_init,
    .cleanup = btif_gatt_cleanup,

    .client = &btgattClientInterface,
    .server = &btgattServerInterface,
    .scanner = nullptr,    // filled in btif_gatt_get_interface
    .advertiser = nullptr  // filled in btif_gatt_get_interface
};

也就是btif_gatt_init时候,通过参数传递进来。在分析api如何从frameworks到bt-JNI时,已经看到了初始化btgattInterface,这里的btif_gatt_init函数就赋值给了它的init成员。

通过前面的分析,bt-JNI层的sGattIf实际指向的就是这个btgattInterface对象。我们回到bt-JNI层的代码:

<aosp>/packages/apps/Bluetooth/jni/com_android_bluetooth_gatt.cpp
------
static void initializeNative(JNIEnv* env, jobject object) {
  ...
  // 这里我们前面分析过,bt-JNI中的sGattIf指向bt协议栈中的btif_gatt_init。
  sGattIf =
      (btgatt_interface_t*)btIf->get_profile_interface(BT_PROFILE_GATT_ID);
  if (sGattIf == NULL) {
    error("Failed to get Bluetooth GATT Interface");
    return;
  }
  // 调用了这时说的初始化方法init(...)
  bt_status_t status = sGattIf->init(&sGattCallbacks);
  if (status != BT_STATUS_SUCCESS) {
    error("Failed to initialize Bluetooth GATT, status: %d", status);
    sGattIf = NULL;
    return;
  }

  sGattIf->advertiser->RegisterCallbacks(
      JniAdvertisingCallbacks::GetInstance());
  sGattIf->scanner->RegisterCallbacks(JniScanningCallbacks::GetInstance());

  mCallbacksObj = env->NewGlobalRef(object);
}

这里调用了sGattIf->init(...)方法,实际上就是前面的btif_gatt_init(...)函数。于是我们可以到这个结论,bt协议栈中的bt_gatt_callbacks,它指向的是bt-JNI中的sGattCallbacks对象。

<aosp>/packages/apps/Bluetooth/jni/com_android_bluetooth_gatt.cpp
------
static const btgatt_callbacks_t sGattCallbacks = {
    sizeof(btgatt_callbacks_t), // => size
    &sGattClientCallbacks,      // => client
    &sGattServerCallbacks,      // => server
    &sGattScannerCallbacks,     // => scanner
};

<aosp>/packages/apps/Bluetooth/jni/com_android_bluetooth_gatt.cpp
------
static const btgatt_client_callbacks_t sGattClientCallbacks = {
    btgattc_register_app_cb,               // => register_client_cb
    btgattc_open_cb,                       // => open_cb
    btgattc_close_cb,                      // => close_cb
    btgattc_search_complete_cb,            // => search_complete_cb
    ...
    btgattc_get_gatt_db_cb,                // => get_gatt_db_cb
    NULL, /* services_removed_cb */        
    NULL, /* services_added_cb */
    btgattc_phy_updated_cb,                // => phy_updated_cb
    btgattc_conn_updated_cb,               // => conn_updated_cb
    btgattc_service_changed_cb,            // => service_changed_cb
};

回到上面这个例子,

bt_gatt_callbacks->client->register_client_cb(status, client_if, uuid);

等于执行bt-JNI中的btgattc_register_app_cb(status, client_if, uuid)。

全部评论: 0

    写评论: