蓝牙Remove Bond的流程分析

Posted libs-liu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了蓝牙Remove Bond的流程分析相关的知识,希望对你有一定的参考价值。

此篇文章简单分析一下蓝牙解除配对在协议栈中的工作流程。分析的协议栈版本是android8.0

协议栈的接口都定义在bluetooth.cc这个文件中:

static int remove_bond(const bt_bdaddr_t* bd_addr) {
  if (is_restricted_mode() && !btif_storage_is_restricted_device(bd_addr))
    return BT_STATUS_SUCCESS;
  /* sanity check */
  if (interface_ready() == false) return BT_STATUS_NOT_READY;
  return btif_dm_remove_bond(bd_addr);
}

这里需要注意一下bt_bdaddr_t 是一个结构体,内部一个元素是数组。

 /** Bluetooth Address */
 typedef struct {
    uint8_t address[6];
 } __attribute__((packed))bt_bdaddr_t;

进入btif_dm_remove_bond:

bt_status_t btif_dm_remove_bond(const bt_bdaddr_t* bd_addr) {
  bdstr_t bdstr;
  btif_transfer_context(btif_dm_generic_evt, BTIF_DM_CB_REMOVE_BOND,
                        (char*)bd_addr, sizeof(bt_bdaddr_t), NULL);
  return BT_STATUS_SUCCESS;
}

这个函数btif_transfer_context 是将remove bond这件事情交给bt_jni_workqueue_thread来处理。在该线程中执行的函数就是btif_dm_generic_evt

static void btif_dm_generic_evt(uint16_t event, char* p_param) {
  BTIF_TRACE_EVENT("%s: event=%d", __func__, event);
  switch (event) {
    case BTIF_DM_CB_REMOVE_BOND: {
      btif_dm_cb_remove_bond((bt_bdaddr_t*)p_param);
    } break;
  }
}

执行的函数:btif_dm_cb_remove_bond 

void btif_dm_cb_remove_bond(bt_bdaddr_t* bd_addr) {
    BTA_DmRemoveDevice((uint8_t*)bd_addr->address);
}

函数执行到了BTA层面。

tBTA_STATUS BTA_DmRemoveDevice(BD_ADDR bd_addr) {
  tBTA_DM_API_REMOVE_DEVICE* p_msg =
   (tBTA_DM_API_REMOVE_DEVICE*)osi_calloc(sizeof(tBTA_DM_API_REMOVE_DEVICE));
  p_msg->hdr.event = BTA_DM_API_REMOVE_DEVICE_EVT;
  bdcpy(p_msg->bd_addr, bd_addr);
  bta_sys_sendmsg(p_msg);
  return BTA_SUCCESS;
}

这边是发送了一个BTA_DM_API_REMOVE_DEVICE_EVT到另一个线程:bt_workqueue_thread,这个线程是专门处理bt里面的队列的,当队列里面有数据都会在这个线程里面处理。

通过bta_sys_sendmsg发送的信号都会经过bta_sys_event来处理,bta_sys_event会根据相应的事件路由到相应的处理函数。这里处理这个事件的函数是:

/*******************************************************************************
 *
 * Function         bta_dm_remove_device
 *
 * Description      Removes device, disconnects ACL link if required.
 ***
 ******************************************************************************/
void bta_dm_remove_device(tBTA_DM_MSG* p_data) {
  tBTA_DM_API_REMOVE_DEVICE* p_dev = &p_data->remove_dev;//获取消息
  bool continue_delete_other_dev = false;/* If ACL exists for the device in the remove_bond message*/
  bool continue_delete_dev = false;
  uint8_t other_transport = BT_TRANSPORT_INVALID;
/*首先判断该address 是否存有link*/
  if (BTM_IsAclConnectionUp(p_dev->bd_addr, BT_TRANSPORT_LE) ||
      BTM_IsAclConnectionUp(p_dev->bd_addr, BT_TRANSPORT_BR_EDR)) {
    APPL_TRACE_DEBUG("%s: ACL Up count  %d", __func__,
                     bta_dm_cb.device_list.count);
    continue_delete_dev = false;
    /* Take the link down first, and mark the device for removal when
     * disconnected */
    for (int i = 0; i < bta_dm_cb.device_list.count; i++) {
      if (!bdcmp(bta_dm_cb.device_list.peer_device[i].peer_bdaddr,
                 p_dev->bd_addr)) {
        uint8_t transport = BT_TRANSPORT_BR_EDR;
        transport = bta_dm_cb.device_list.peer_device[i].transport;
        bta_dm_cb.device_list.peer_device[i].conn_state = BTA_DM_UNPAIRING;//设置标志位,在acl link状态改变的函数中会去删除link key
        btm_remove_acl(p_dev->bd_addr, transport);//已经存在link,那么要先删除这条linkbreak;
      }
    }
  } else {
    continue_delete_dev = true;
  }
...
  /* Delete the device mentioned in the msg */
  if (continue_delete_dev) bta_dm_process_remove_device(p_dev->bd_addr);//解配的设备没有处于连接状态则执行
}

从上面的代码可以看出,核心的地方就两处:

  1. bta_dm_cb.device_list.peer_device[i].conn_state = BTA_DM_UNPAIRING; 标记该设备是要解除配对的,后续会删除其link key
  2. btm_remove_acl 做实际的断开连接的操作。

 

以上是关于蓝牙Remove Bond的流程分析的主要内容,如果未能解决你的问题,请参考以下文章

车机蓝牙通话流程分析的流程分析

车机蓝牙通话流程分析的流程分析

蓝牙speaker配对流程源码分析

Android 逆向整体加固脱壳 ( DEX 优化流程分析 | DexPrepare.cpp 中 dvmOptimizeDexFile() 方法分析 | /bin/dexopt 源码分析 )(代码片段

Android博通BCM libbt-vendor.so 分析蓝牙初始化流程

Android博通BCM libbt-vendor.so 分析蓝牙初始化流程