接着上一篇【Bluedroid】AVRCP 连接源码分析(一)-CSDN博客,继续AVRCP连接的源码分析。
AVRC_OpenBrowse
/packages/modules/Bluetooth/system/stack/avrc/avrc_api.cc
/******************************************************************************** Function AVRC_OpenBrowse** Description This function is called to open a browsing connection to* AVCTP. The connection can be either an initiator or* acceptor, as determined by the p_conn_role.* The handle is returned by a previous call to AVRC_Open.** Returns AVRC_SUCCESS if successful.* AVRC_NO_RESOURCES if there are not enough resources to open* the connection.******************************************************************************/
uint16_t AVRC_OpenBrowse(uint8_t handle, uint8_t conn_role) {return AVCT_CreateBrowse(handle, conn_role);
}
AVRC_OpenBrowse 函数主要功能是发起一个到 AVCTP的浏览连接。这个连接可以是发起方(initiator)连接,也可以是接收方(acceptor)连接,具体由传入的 conn_role 参数决定。
AVCT_CreateBrowse
packages/modules/Bluetooth/system/stack/avct/avct_api.cc
/********************************************************************************* Function AVCT_CreateBrowse** Description Create an AVCTP Browse channel. There are two types of* connections, initiator and acceptor, as determined by* the role parameter. When this function is called to* create an initiator connection, the Browse channel to* the peer device is initiated if one does not already exist.* If an acceptor connection is created, the connection waits* passively for an incoming AVCTP connection from a peer* device.*** Returns AVCT_SUCCESS if successful, otherwise error.*******************************************************************************/
uint16_t AVCT_CreateBrowse(uint8_t handle, uint8_t role) {uint16_t result = AVCT_SUCCESS;tAVCT_CCB* p_ccb;tAVCT_BCB* p_bcb;int index;log::verbose("AVCT_CreateBrowse: {}", role);/* map handle to ccb */// 1. 映射句柄到连接控制块p_ccb = avct_ccb_by_idx(handle);if (p_ccb == NULL) {return AVCT_BAD_HANDLE;} else {/* mark this CCB as supporting browsing channel */if ((p_ccb->allocated & AVCT_ALOC_BCB) == 0) {p_ccb->allocated |= AVCT_ALOC_BCB;}}/* if initiator connection */// 2. 发起方连接处理if (role == AVCT_INT) {/* the link control block must exist before this function is called as INT.*/if ((p_ccb->p_lcb == NULL) || (p_ccb->p_lcb->allocated == 0)) {result = AVCT_NOT_OPEN;} else {/* find link; if none allocate a new one */index = p_ccb->p_lcb->allocated;if (index > AVCT_NUM_LINKS) {result = AVCT_BAD_HANDLE;} else {p_bcb = &avct_cb.bcb[index - 1];p_bcb->allocated = index;}}if (result == AVCT_SUCCESS) {/* bind bcb to ccb */p_ccb->p_bcb = p_bcb;p_bcb->peer_addr = p_ccb->p_lcb->peer_addr;log::verbose("ch_state: {}", p_bcb->ch_state);tAVCT_LCB_EVT avct_lcb_evt;avct_lcb_evt.p_ccb = p_ccb;avct_bcb_event(p_bcb, AVCT_LCB_UL_BIND_EVT, &avct_lcb_evt);}}return result;
}
创建一个 AVCTP的浏览通道。根据传入的 role 参数,连接可以是发起方(initiator)连接或者接收方(acceptor)连接。如果是发起方连接,会尝试发起与对端设备的浏览通道连接;如果是接收方连接,会被动等待来自对端设备的 AVCTP 连接。
avct_bcb_event(AVCT_LCB_UL_BIND_EVT)
packages/modules/Bluetooth/system/stack/avct/avct_lcb.cc
/********************************************************************************* Function avct_bcb_event** Description State machine event handling function for lcb*** Returns Nothing.*******************************************************************************/
void avct_bcb_event(tAVCT_BCB* p_bcb, uint8_t event, tAVCT_LCB_EVT* p_data) {tAVCT_LCB_ST_TBL state_table; // 存储当前状态对应的状态转移表uint8_t action;int i;log::verbose("BCB lcb={} event={} state={}", p_bcb->allocated,avct_lcb_evt_str[event], avct_lcb_st_str[p_bcb->state]);/* look up the state table for the current state */// 1. 查找当前状态的状态转移表state_table = avct_lcb_st_tbl[p_bcb->state];/* set next state */// 2. 设置下一个状态p_bcb->state = state_table[event][AVCT_LCB_NEXT_STATE];/* execute action functions */// 3. 执行动作函数for (i = 0; i < AVCT_LCB_ACTIONS; i++) {action = state_table[event][i];if (action != AVCT_LCB_IGNORE) {(*avct_bcb_action[action])(p_bcb, p_data);} else {break;}}
}
处理 tAVCT_BCB( AVCTP 浏览通道控制块)状态机事件的函数。根据传入的事件和当前状态,查找对应的状态转移表,更新控制块的状态,并执行相应的动作函数。
avct_bcb_chnl_open
packages/modules/Bluetooth/system/stack/avct/avct_bcb_act.cc
/********************************************************************************* Function avct_bcb_chnl_open** Description Open L2CAP channel to peer*** Returns Nothing.*******************************************************************************/
void avct_bcb_chnl_open(tAVCT_BCB* p_bcb, UNUSED_ATTR tAVCT_LCB_EVT* p_data) {uint16_t result = AVCT_RESULT_FAIL;tAVCT_LCB* p_lcb = avct_lcb_by_bcb(p_bcb);tL2CAP_ERTM_INFO ertm_info;/* Set the FCR options: Browsing channel mandates ERTM */ertm_info.preferred_mode = L2CAP_FCR_ERTM_MODE;/* call l2cap connect req */p_bcb->ch_state = AVCT_CH_CONN;p_bcb->ch_lcid =L2CA_ConnectReq2(AVCT_BR_PSM, p_lcb->peer_addr, BTA_SEC_AUTHENTICATE);if (p_bcb->ch_lcid == 0) {/* if connect req failed, send ourselves close event */tAVCT_LCB_EVT avct_lcb_evt;avct_lcb_evt.result = result;avct_bcb_event(p_bcb, AVCT_LCB_LL_CLOSE_EVT, &avct_lcb_evt);}
}
L2CA_ConnectReq2
L2CA_ConnectReq2源码这里不再分析。
对端设备收到 L2CAP 连接请求后,会根据自身的状态和能力进行处理,并发送 L2CAP 连接响应。响应消息用于告知发起方连接请求的结果(成功或失败),以及协商连接的一些参数。
发起方收到连接响应后,会根据结果码进行相应的处理。如果连接成功,会使用分配的 LCID 进行后续的数据传输;如果连接失败,可能会进行错误处理或重试。
bta_av_rc_ctrl_cback
bta_av_rc_ctrl_cback前文有分析,不再赘述。
bta_av_non_state_machine_event(BTA_AV_AVRC_BROWSE_OPEN_EVT)
bta_av_rc_browse_opened
packages/modules/Bluetooth/system/bta/av/bta_av_act.cc
/********************************************************************************* Function bta_av_rc_browse_opened** Description AVRC browsing channel is opened** Returns void*******************************************************************************/
void bta_av_rc_browse_opened(tBTA_AV_DATA* p_data) {tBTA_AV_CB* p_cb = &bta_av_cb;tBTA_AV_RC_CONN_CHG* p_msg = (tBTA_AV_RC_CONN_CHG*)p_data;tBTA_AV_RC_BROWSE_OPEN rc_browse_open;log::info("peer_addr: {} rc_handle:{}",ADDRESS_TO_LOGGABLE_CSTR(p_msg->peer_addr), p_msg->handle);// 填充 rc_browse_open 结构体rc_browse_open.status = BTA_AV_SUCCESS;rc_browse_open.rc_handle = p_msg->handle;rc_browse_open.peer_addr = p_msg->peer_addr;// 准备回调数据并调用回调函数tBTA_AV bta_av_data;bta_av_data.rc_browse_open = rc_browse_open;(*p_cb->p_cback)(BTA_AV_RC_BROWSE_OPEN_EVT, &bta_av_data);
}
处理 AVRCP浏览通道已打开的事件。当 AVRCP 浏览通道成功打开时,会收集相关信息,如状态、句柄和对端设备地址等,然后调用回调函数通知上层模块浏览通道已成功打开。
bta_av_source_callback(BTA_AV_RC_BROWSE_OPEN_EVT)
btif_av_handle_bta_av_event
btif_av_handle_event
同前文分析。
BtifAvStateMachine::StateOpened::ProcessEvent
btif_rc_handler(BTA_AV_RC_BROWSE_OPEN_EVT)
handle_rc_browse_connect
packages/modules/Bluetooth/system/btif/src/btif_rc.cc
/**************************************************************************** Function handle_rc_browse_connect** - Argument: tBTA_AV_RC_OPEN browse RC open data structure** - Description: browse RC connection event handler****************************************************************************/
void handle_rc_browse_connect(tBTA_AV_RC_BROWSE_OPEN* p_rc_br_open) {log::verbose("rc_handle {} status {}", p_rc_br_open->rc_handle,p_rc_br_open->status);// 1. 设备查找btif_rc_device_cb_t* p_dev =btif_rc_get_device_by_handle(p_rc_br_open->rc_handle);if (!p_dev) {log::error("p_dev is null");return;}/* check that we are already connected to this address since being connected* to a browse when not connected to the control channel over AVRCP is* probably not preferred anyways. */// 2. 连接成功处理if (p_rc_br_open->status == BTA_AV_SUCCESS) {p_dev->br_connected = true;if (btif_av_src_sink_coexist_enabled()) {if (btif_av_peer_is_connected_source(p_dev->rc_addr)) { // 支持共存且对端是已连接源设备if (bt_rc_ctrl_callbacks != NULL) {// 通知上层应用 AVRCP 浏览连接已建立do_in_jni_thread(FROM_HERE,base::BindOnce(bt_rc_ctrl_callbacks->connection_state_cb, true,true, p_dev->rc_addr));}} else { // 支持共存但对端不是已连接源设备p_dev->launch_cmd_pending |= RC_PENDING_ACT_REPORT_CONN; // 有浏览连接事件待处理log::verbose("pending rc browse connection event");}} else { // 不支持共存if (bt_rc_ctrl_callbacks != NULL) {// 通知上层应用连接已建立do_in_jni_thread(FROM_HERE,base::BindOnce(bt_rc_ctrl_callbacks->connection_state_cb, true,true, p_dev->rc_addr));} else {log::warn("bt_rc_ctrl_callbacks is null.");}}}
}
处理 AVRCP浏览连接事件。当接收到 AVRCP 浏览通道打开的事件时,会根据事件的状态和系统的配置情况,更新设备的连接状态,并通过回调函数通知上层应用。
关键字
AVCT_CreateBrowse|avct_bcb_event|bta_av_rc_ctrl_cback|bta_av_rc_browse_opened|handle_rc_browse_connect