蓝牙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 做实际的断开连接的操作。

 现在简单看看btm_remove_acl 的实现:

tBTM_STATUS btm_remove_acl(BD_ADDR bd_addr, tBT_TRANSPORT transport) {
  uint16_t hci_handle = BTM_GetHCIConnHandle(bd_addr, transport);
  tBTM_STATUS status = BTM_SUCCESS;
...
  {
    if (hci_handle != 0xFFFF && p_dev_rec &&
        p_dev_rec->sec_state != BTM_SEC_STATE_DISCONNECTING) {
      btsnd_hcic_disconnect(hci_handle, HCI_ERR_PEER_USER);
    } else
      status = BTM_UNKNOWN_ADDR;
  }
  return status;
}

先搜索btm_cb.acl_db 找到该地址对应的ACL link 的控制体,获取该link 的handle,该handle用于标志是哪一条link,然后调用btsnd_hcic_disconnect(hci_handle, HCI_ERR_PEER_USER); 向controller发送断开的命令。

到这里,在bt_workqueue_thread 线程中发送断开link 的消息是结束了,controller收到信息处理之后,会有断开完成事件上来,这个时候处理该事件的线程依然是bt_workqueue_thread,我们看看具体的处理过程:处理底层的事件的接口实现在btu_hcif.cc中:

/*******************************************************************************
 *
 * Function         btu_hcif_disconnection_comp_evt
 *
 * Description      Process event HCI_DISCONNECTION_COMP_EVT
 *
 * Returns          void
 *
 ******************************************************************************/
static void btu_hcif_disconnection_comp_evt(uint8_t* p) {
  uint16_t handle;
  uint8_t reason;
  ++p;
  STREAM_TO_UINT16(handle, p);
  STREAM_TO_UINT8(reason, p);
  handle = HCID_GET_HANDLE(handle);
  l2c_link_hci_disc_comp(handle, reason);
  /* Notify security manager */
  btm_sec_disconnected(handle, reason);
}

从函数的注释我们也能看出其是处理HCI_DISCONNECTION_COMP_EVT 这个事件的。从代码流程中,我们能看到代码主要做了两件事:

  1. l2c_link_hci_disc_comp
  2. btm_sec_disconnected,这个函数是用来通知security manager的。

下面依次看看这两个函数的实现:

bool l2c_link_hci_disc_comp(uint16_t handle, uint8_t reason) {
  L2CAP_TRACE_EVENT("entry l2c_link_hci_disc_comp libs_liu");
  tL2C_LCB* p_lcb;
  tL2C_CCB* p_ccb;
  bool status = true;
  bool lcb_is_free = true;
  tBT_TRANSPORT transport = BT_TRANSPORT_BR_EDR;
  /* See if we have a link control block for the connection */
  p_lcb = l2cu_find_lcb_by_handle(handle);
...
 {
    /* Just in case app decides to try again in the callback context */
    p_lcb->link_state = LST_DISCONNECTING;

    /* Check for BLE and handle that differently */
    if (p_lcb->transport == BT_TRANSPORT_LE)
      btm_ble_update_link_topology_mask(p_lcb->link_role, false);
    /* Link is disconnected. For all channels, send the event through */
    /* their FSMs. The CCBs should remove themselves from the LCB     */
    for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb;) {
      tL2C_CCB* pn = p_ccb->p_next_ccb;
      /* Keep connect pending control block (if exists)
       * Possible Race condition when a reconnect occurs
       * on the channel during a disconnect of link. This
       * ccb will be automatically retried after link disconnect
       * arrives
       */
      if (p_ccb != p_lcb->p_pending_ccb) {
        l2c_csm_execute(p_ccb, L2CEVT_LP_DISCONNECT_IND, &reason);
      }
      p_ccb = pn;
    }
    p_lcb->p_pending_ccb = NULL;

    /* Release the LCB */
    if (lcb_is_free){ 
    l2cu_release_lcb(p_lcb);}
  }
...
  return status;
}

上面函数核心的地方 是释放link 相关的结构体l2cu_release_lcb,这个函数主要就是释放一些定时器,内存以及channel结构释放,另外还做一些通知的事情:

      /* If anyone cares, tell him database changed */
      if (btm_cb.p_bl_changed_cb) {
        evt_data.event = BTM_BL_DISCN_EVT;
        evt_data.discn.p_bda = bda;
        evt_data.discn.handle = p->hci_handle;
        evt_data.discn.transport = p->transport;
        (*btm_cb.p_bl_changed_cb)(&evt_data);
      }

这里需要思考一下,这个btm_cb.p_bl_changed_cb 回调函数是哪里注册。这个函数其实在bta_dm_sys_hw_cback 函数中注册的:

BTM_RegBusyLevelNotif(bta_dm_bl_change_cback, NULL,
                          BTM_BL_UPDATE_MASK | BTM_BL_ROLE_CHG_MASK);
//那其实是
btm_cb.p_bl_changed_cb  = bta_dm_bl_change_cback

那我们现在看看这个busy level change的实现:从上面也可以看出是把BTM_BL_DISCN_EVT 传入到 bta_dm_bl_change_cback 来执行:

static void bta_dm_bl_change_cback(tBTM_BL_EVENT_DATA* p_data) {
  tBTA_DM_ACL_CHANGE* p_msg =
      (tBTA_DM_ACL_CHANGE*)osi_malloc(sizeof(tBTA_DM_ACL_CHANGE));

  p_msg->event = p_data->event;
  p_msg->is_new = false;

  switch (p_msg->event) {
    case BTM_BL_CONN_EVT:
      p_msg->is_new = true;
      bdcpy(p_msg->bd_addr, p_data->conn.p_bda);
      p_msg->transport = p_data->conn.transport;
      p_msg->handle = p_data->conn.handle;
      break;
    case BTM_BL_DISCN_EVT:
      bdcpy(p_msg->bd_addr, p_data->discn.p_bda);
      p_msg->transport = p_data->discn.transport;
      p_msg->handle = p_data->discn.handle;
      break;
    case BTM_BL_UPDATE_EVT:
      p_msg->busy_level = p_data->update.busy_level;
      p_msg->busy_level_flags = p_data->update.busy_level_flags;
      break;
    case BTM_BL_ROLE_CHG_EVT:
      p_msg->new_role = p_data->role_chg.new_role;
      p_msg->hci_status = p_data->role_chg.hci_status;
      bdcpy(p_msg->bd_addr, p_data->role_chg.p_bda);
      break;
    case BTM_BL_COLLISION_EVT:
      bdcpy(p_msg->bd_addr, p_data->conn.p_bda);
      break;
  }

  p_msg->hdr.event = BTA_DM_ACL_CHANGE_EVT;
  bta_sys_sendmsg(p_msg);
}

从这个函数的实现来看,他是可以处理很多的event的。然后统一发送给bt_workqueue_thread中的另外一个队列中,看看具体的处理流程:

其实现的函数是在bta_dm_act.cc中,

void bta_dm_acl_change(tBTA_DM_MSG* p_data) {
  uint8_t i;
  uint8_t* p;
  tBTA_DM_SEC conn;
  bool is_new = p_data->acl_change.is_new;
  BD_ADDR_PTR p_bda = p_data->acl_change.bd_addr;
  bool need_policy_change = false;
  bool issue_unpair_cb = false;

  tBTA_DM_PEER_DEVICE* p_dev;
  memset(&conn, 0, sizeof(tBTA_DM_SEC));
...
    for (i = 0; i < bta_dm_cb.device_list.count; i++) {
      if (bdcmp(bta_dm_cb.device_list.peer_device[i].peer_bdaddr, p_bda) ||
          bta_dm_cb.device_list.peer_device[i].transport !=
              p_data->acl_change.transport)
        continue;
    /*找到之后*/
      if (bta_dm_cb.device_list.peer_device[i].conn_state == BTA_DM_UNPAIRING) {//之前已经标记过
        if (BTM_SecDeleteDevice(bta_dm_cb.device_list.peer_device[i].peer_bdaddr))
      BTA_GATTC_Refresh(p_bda);//remove all gatt information issue_unpair_cb
= true; } conn.link_down.is_removed = bta_dm_cb.device_list.peer_device[i].remove_dev_pending; break; } ... conn.link_down.link_type = p_data->acl_change.transport; ... bdcpy(conn.link_down.bd_addr, p_bda); conn.link_down.status = (uint8_t)btm_get_acl_disc_reason_code(); if (bta_dm_cb.p_sec_cback) { //执行这里的函数 bta_dm_cb.p_sec_cback(BTA_DM_LINK_DOWN_EVT, &conn); if (issue_unpair_cb) bta_dm_cb.p_sec_cback(BTA_DM_DEV_UNPAIRED_EVT, &conn); } bta_dm_adjust_roles(true); }

上面的回调函数主要执行如下:

  1. 从bta_dm_cb 查找到该地址的结构。
  2. 找到之后判断bta_dm_cb.device_list.peer_device[i].conn_state的状态,如果是BTA_DM_UNPAIRING,则开始删除link key:BTM_SecDeleteDevice
  3. 回调bta_dm_cb.p_sec_cback :BTA_DM_LINK_DOWN_EVT以及BTA_DM_DEV_UNPAIRED_EVT

前两个容易理解,看看第三点:

第三点的回调函数在enable 的时候就已经注册好了:bta_dm_cb.p_sec_cback = bte_dm_evt ,我们进一步看看:

void bte_dm_evt(tBTA_DM_SEC_EVT event, tBTA_DM_SEC* p_data) {
  bt_status_t status = btif_transfer_context(
      btif_dm_upstreams_evt, (uint16_t)event, (char*)p_data,
      sizeof(tBTA_DM_SEC), btif_dm_data_copy);
}

发现其实 他实质执行的函数是btif_dm_upstreams_evt ,这个函数处理的event非常的多,这里就列出相关的代码:

static void btif_dm_upstreams_evt(uint16_t event, char* p_param) {
  tBTA_DM_SEC* p_data = (tBTA_DM_SEC*)p_param;
  tBTA_SERVICE_MASK service_mask;
  uint32_t i;
  bt_bdaddr_t bd_addr;

  switch (event) {
...
    case BTA_DM_DEV_UNPAIRED_EVT:
      bdcpy(bd_addr.address, p_data->link_down.bd_addr);
      btm_set_bond_type_dev(p_data->link_down.bd_addr, BOND_TYPE_UNKNOWN);

/*special handling for HID devices */
#if (defined(BTA_HH_INCLUDED) && (BTA_HH_INCLUDED == true))
      btif_hh_remove_device(bd_addr);
#endif
#if (defined(BTA_HD_INCLUDED) && (BTA_HD_INCLUDED == TRUE))
      btif_hd_remove_device(bd_addr);
#endif
      btif_storage_remove_bonded_device(&bd_addr);
      bond_state_changed(BT_STATUS_SUCCESS, &bd_addr, BT_BOND_STATE_NONE);
      break;

    case BTA_DM_LINK_DOWN_EVT:
      bdcpy(bd_addr.address, p_data->link_down.bd_addr);
      btm_set_bond_type_dev(p_data->link_down.bd_addr, BOND_TYPE_UNKNOWN);
      btif_av_move_idle(bd_addr);
      BTIF_TRACE_DEBUG(
          "BTA_DM_LINK_DOWN_EVT. Sending BT_ACL_STATE_DISCONNECTED");
      HAL_CBACK(bt_hal_cbacks, acl_state_changed_cb, BT_STATUS_SUCCESS,
                &bd_addr, BT_ACL_STATE_DISCONNECTED);
      break;
  }

  btif_dm_data_free(event, p_data);
}

处理的两个事件是BTA_DM_LINK_DOWN_EVT和BTA_DM_DEV_UNPAIRED_EVT 

其中BTA_DM_LINK_DOWN_EVT 主要是执行acl_state_changed_cb,向上层传导BT_ACL_STATE_DISCONNECTED

这里主要看一下BTA_DM_DEV_UNPAIRED_EVT  的处理:

  1. btif_hh_remove_device   
  2. btif_storage_remove_bonded_device  删除config中的key 的信息。

下面看看btif_hh_remove_device

 

void btif_hh_remove_device(bt_bdaddr_t bd_addr) {
  int i;
  btif_hh_device_t* p_dev;
  btif_hh_added_device_t* p_added_dev;for (i = 0; i < BTIF_HH_MAX_ADDED_DEV; i++) {
    p_added_dev = &btif_hh_cb.added_devices[i];
    if (memcmp(&(p_added_dev->bd_addr), &bd_addr, 6) == 0) {
      BTA_HhRemoveDev(p_added_dev->dev_handle);//remove dev
      btif_storage_remove_hid_info(&(p_added_dev->bd_addr));//删除config中的hid信息
      memset(&(p_added_dev->bd_addr), 0, 6);
      p_added_dev->dev_handle = BTA_HH_INVALID_HANDLE;
      break;
    }
  }
... p_dev
= btif_hh_find_dev_by_bda(&bd_addr);/* need to notify up-layer device is disconnected to avoid state out of sync * with up-layer */ HAL_CBACK(bt_hh_callbacks, connection_state_cb, &(p_dev->bd_addr),//向上层汇报状态 BTHH_CONN_STATE_DISCONNECTED); p_dev->dev_status = BTHH_CONN_STATE_UNKNOWN; p_dev->dev_handle = BTA_HH_INVALID_HANDLE; p_dev->ready_for_data = false; ...if (p_dev->fd >= 0) { bta_hh_co_destroy(p_dev->fd);//销毁相关的结构 p_dev->fd = -1; } }

上面代码很简单,主要做清理工作:下面具体看看BTA_HhRemoveDev

void BTA_HhRemoveDev(uint8_t dev_handle) {
  tBTA_HH_MAINT_DEV* p_buf =
      (tBTA_HH_MAINT_DEV*)osi_calloc(sizeof(tBTA_HH_MAINT_DEV));
  p_buf->hdr.event = BTA_HH_API_MAINT_DEV_EVT;
  p_buf->sub_event = BTA_HH_RMV_DEV_EVT;
  p_buf->hdr.layer_specific = (uint16_t)dev_handle;
  bta_sys_sendmsg(p_buf);
}

发送了一个BTA_HH_API_MAINT_DEV_EVT的事件到达BTU task,

void bta_hh_maint_dev_act(tBTA_HH_DEV_CB* p_cb, tBTA_HH_DATA* p_data) {
  tBTA_HH_MAINT_DEV* p_dev_info = &p_data->api_maintdev;
  tBTA_HH_DEV_INFO dev_info;
  uint8_t dev_handle;

  dev_info.status = BTA_HH_ERR;
  dev_info.handle = BTA_HH_INVALID_HANDLE;

  switch (p_dev_info->sub_event) {
...
    case BTA_HH_RMV_DEV_EVT: /* remove device */
      dev_info.handle = (uint8_t)p_dev_info->hdr.layer_specific;
      bdcpy(dev_info.bda, p_cb->addr);

      if (p_cb->is_le_device) {//le 设备
        bta_hh_le_remove_dev_bg_conn(p_cb);//移除background 里面的list,让其不要回连
        bta_hh_sm_execute(p_cb, BTA_HH_API_CLOSE_EVT, NULL);
        bta_hh_clean_up_kdev(p_cb);
      } else//bredr 设备
      {
        if (HID_HostRemoveDev(dev_info.handle) == HID_SUCCESS) {
          dev_info.status = BTA_HH_OK;
          /* remove from known device list in BTA */
          bta_hh_clean_up_kdev(p_cb);
        }
      }
      break;
  }
  (*bta_hh_cb.p_cback)(p_dev_info->sub_event, (tBTA_HH*)&dev_info);
}

这里先讲一下bta_hh_cb.p_cback,也是在 BTA_HhEnable(BTUI_HH_SECURITY, bte_hh_evt); 时候注册的,那么也就是说bta_hh_cb.p_cback = bte_hh_evt

void bte_hh_evt(tBTA_HH_EVT event, tBTA_HH* p_data) {
  bt_status_t status;
  int param_len = 0;

  if (BTA_HH_ENABLE_EVT == event)
    param_len = sizeof(tBTA_HH_STATUS);
  else if (BTA_HH_OPEN_EVT == event)
    param_len = sizeof(tBTA_HH_CONN);
  else if (BTA_HH_DISABLE_EVT == event)
    param_len = sizeof(tBTA_HH_STATUS);
  else if (BTA_HH_CLOSE_EVT == event)
    param_len = sizeof(tBTA_HH_CBDATA);
  else if (BTA_HH_GET_DSCP_EVT == event)
    param_len = sizeof(tBTA_HH_DEV_DSCP_INFO);
  else if ((BTA_HH_GET_PROTO_EVT == event) || (BTA_HH_GET_RPT_EVT == event) ||
           (BTA_HH_GET_IDLE_EVT == event))
    param_len = sizeof(tBTA_HH_HSDATA);
  else if ((BTA_HH_SET_PROTO_EVT == event) || (BTA_HH_SET_RPT_EVT == event) ||
           (BTA_HH_VC_UNPLUG_EVT == event) || (BTA_HH_SET_IDLE_EVT == event))
    param_len = sizeof(tBTA_HH_CBDATA);
  else if ((BTA_HH_ADD_DEV_EVT == event) || (BTA_HH_RMV_DEV_EVT == event))
    param_len = sizeof(tBTA_HH_DEV_INFO);
  else if (BTA_HH_API_ERR_EVT == event)
    param_len = 0;
  /* switch context to btif task context (copy full union size for convenience)
   */
  status = btif_transfer_context(btif_hh_upstreams_evt, (uint16_t)event,
                                 (char*)p_data, param_len, NULL);

  /* catch any failed context transfers */
  ASSERTC(status == BT_STATUS_SUCCESS, "context transfer failed", status);
}

其本质还是transfer 到btif 线程,执行btif_hh_upstreams_evt 函数,这边追踪了一下该事件的处理,只是打印了一些log:

    case BTA_HH_RMV_DEV_EVT:
      BTIF_TRACE_DEBUG("BTA_HH_RMV_DEV_EVT: status = %d, handle = %d",
                       p_data->dev_info.status, p_data->dev_info.handle);
      BTIF_TRACE_DEBUG("BTA_HH_RMV_DEV_EVT:bda = %02x:%02x:%02x:%02x:%02x:%02x",
                       p_data->dev_info.bda[0], p_data->dev_info.bda[1],
                       p_data->dev_info.bda[2], p_data->dev_info.bda[3],
                       p_data->dev_info.bda[4], p_data->dev_info.bda[5]);
      break;

现在着重看一下bta_hh_le_remove_dev_bg_conn(p_cb) 的处理

void bta_hh_le_remove_dev_bg_conn(tBTA_HH_DEV_CB* p_dev_cb) {
  if (p_dev_cb->in_bg_conn) {
    p_dev_cb->in_bg_conn = false;
    BTA_GATTC_CancelOpen(bta_hh_cb.gatt_if, p_dev_cb->addr, false);
  }

  /* deregister all notifications */
  bta_hh_le_deregister_input_notif(p_dev_cb);
}
void BTA_GATTC_CancelOpen(tBTA_GATTC_IF client_if, BD_ADDR remote_bda,
                          bool is_direct) {
  tBTA_GATTC_API_CANCEL_OPEN* p_buf = (tBTA_GATTC_API_CANCEL_OPEN*)osi_malloc(
      sizeof(tBTA_GATTC_API_CANCEL_OPEN));

  p_buf->hdr.event = BTA_GATTC_API_CANCEL_OPEN_EVT;
  p_buf->client_if = client_if;
  p_buf->is_direct = is_direct;
  memcpy(p_buf->remote_bda, remote_bda, BD_ADDR_LEN);

  bta_sys_sendmsg(p_buf);
}
void bta_gattc_process_api_open_cancel(tBTA_GATTC_DATA* p_msg) {
  uint16_t event = ((BT_HDR*)p_msg)->event;
  tBTA_GATTC_CLCB* p_clcb = NULL;
  tBTA_GATTC_RCB* p_clreg;
  tBTA_GATTC cb_data;

  if (p_msg->api_cancel_conn.is_direct) {
...
  } else {
    bta_gattc_cancel_bk_conn(&p_msg->api_cancel_conn);
  }
}
void bta_gattc_cancel_bk_conn(tBTA_GATTC_API_CANCEL_OPEN* p_data) {
  tBTA_GATTC_RCB* p_clreg;
  tBTA_GATTC cb_data;
  cb_data.status = BTA_GATT_ERROR;

  /* remove the device from the bg connection mask */
  if (bta_gattc_mark_bg_conn(p_data->client_if, p_data->remote_bda, false)) {
    if (GATT_CancelConnect(p_data->client_if, p_data->remote_bda, false)) {
      cb_data.status = BTA_GATT_OK;
    } else {
      APPL_TRACE_ERROR("bta_gattc_cancel_bk_conn failed");
    }
  }
  p_clreg = bta_gattc_cl_get_regcb(p_data->client_if);

  if (p_clreg && p_clreg->p_cback) {
    (*p_clreg->p_cback)(BTA_GATTC_CANCEL_OPEN_EVT, &cb_data);
  }
}
bool GATT_CancelConnect(tGATT_IF gatt_if, BD_ADDR bd_addr, bool is_direct) {
  tGATT_REG* p_reg;
  tGATT_TCB* p_tcb;
  bool status = true;
  tGATT_IF temp_gatt_if;
  uint8_t start_idx, found_idx;

    if (!gatt_if) 
        ...
        else {
      status = gatt_remove_bg_dev_for_app(gatt_if, bd_addr);
    }
  return status;
}
bool gatt_remove_bg_dev_for_app(tGATT_IF gatt_if, BD_ADDR bd_addr) {
  tGATT_TCB* p_tcb = gatt_find_tcb_by_addr(bd_addr, BT_TRANSPORT_LE);
  bool status;

  if (p_tcb) gatt_update_app_use_link_flag(gatt_if, p_tcb, false, false);
  status = gatt_update_auto_connect_dev(gatt_if, false, bd_addr);
  return status;
}
bool gatt_update_auto_connect_dev(tGATT_IF gatt_if, bool add, BD_ADDR bd_addr) {
...
  if (add) {
    ret = gatt_add_bg_dev_list(p_reg, bd_addr);
    if (ret && p_tcb != NULL) {
      /* if a connected device, update the link holding number */
      gatt_update_app_use_link_flag(gatt_if, p_tcb, true, true);
    }
  } else {
    ret = gatt_remove_bg_dev_from_list(p_reg, bd_addr);
  }
  return ret;
}
bool gatt_remove_bg_dev_from_list(tGATT_REG* p_reg, BD_ADDR bd_addr) {
  tGATT_IF gatt_if = p_reg->gatt_if;
  tGATT_BG_CONN_DEV* p_dev = NULL;
  uint8_t i, j;
  bool ret = false;

  p_dev = gatt_find_bg_dev(bd_addr);
  if (p_dev == NULL) {
    return ret;
  }

  for (i = 0; i < GATT_MAX_APPS && (p_dev->gatt_if[i] > 0); i++) {
    if (p_dev->gatt_if[i] == gatt_if) {
      p_dev->gatt_if[i] = 0;
      /* move all element behind one forward */
      for (j = i + 1; j < GATT_MAX_APPS; j++)
        p_dev->gatt_if[j - 1] = p_dev->gatt_if[j];

      if (p_dev->gatt_if[0] == 0){//只有设备全部都断开了才会去做BTM_BleUpdateBgConnDev
        ret = BTM_BleUpdateBgConnDev(false, p_dev->remote_bda);
          }
      else
        ret = true;

      break;
    }
  }

  if (i != GATT_MAX_APPS && p_dev->gatt_if[0] == 0) {
    memset(p_dev, 0, sizeof(tGATT_BG_CONN_DEV));
  }

  return ret;
}
bool BTM_BleUpdateBgConnDev(bool add_remove, BD_ADDR remote_bda) {
  return btm_update_dev_to_white_list(add_remove, remote_bda);
}
bool btm_update_dev_to_white_list(bool to_add, BD_ADDR bd_addr) {
  tBTM_BLE_CB* p_cb = &btm_cb.ble_ctr_cb;

  if (to_add && p_cb->white_list_avail_size == 0) {
    BTM_TRACE_ERROR("%s Whitelist full, unable to add device", __func__);
    return false;
  }
  if (to_add)
    background_connection_add((bt_bdaddr_t*)bd_addr);
  else{
    background_connection_remove((bt_bdaddr_t*)bd_addr);
  }
  btm_suspend_wl_activity(p_cb->wl_state);
  btm_enq_wl_dev_operation(to_add, bd_addr);
  btm_resume_wl_activity(p_cb->wl_state);
  return true;
}

删除 里面的值: background_connection_remove

static void btm_resume_wl_activity(tBTM_BLE_WL_STATE wl_state) {
  btm_ble_resume_bg_conn();
  if (wl_state & BTM_BLE_WL_ADV) {
    btm_ble_start_adv();
  }
}
bool btm_ble_resume_bg_conn(void) {
  tBTM_BLE_CB* p_cb = &btm_cb.ble_ctr_cb;
  if (p_cb->bg_conn_type == BTM_BLE_CONN_AUTO) {
    return btm_ble_start_auto_conn(true);//如果background 里面还存在设备,那么就会回连
  }
  return false;
}

这个解除绑定的流程 暂时是分析到这里。

 

 

posted @ 2018-06-17 22:14  雪山飞燕  阅读(3636)  评论(0编辑  收藏  举报