对部分代码一眼无法知道运行结果的地方备注。
可以理解为闭包吧!将参数和方法打包在一起传入队列中等待执行。最终执行的就是 connect_init(),参数就是bd_addr, connect_init。
static bt_status_t connect(RawAddress* bd_addr) {
return btif_queue_connect(UUID_SERVCLASS_HF_HANDSFREE, bd_addr, connect_int);
}
这里的用到BlueDroid中最常用的消息传递方式,malloc出结构体后。赋值event和layer_specific。
然后通过bta_sys_sendmsg发送event到bta_sys_main.cc bta_sys_event中进行处理。
void BTA_HfClientOpen(const RawAddress& bd_addr, tBTA_SEC sec_mask,
uint16_t* p_handle) {
APPL_TRACE_DEBUG("%s", __func__);
tBTA_HF_CLIENT_API_OPEN* p_buf =
(tBTA_HF_CLIENT_API_OPEN*)osi_malloc(sizeof(tBTA_HF_CLIENT_API_OPEN));
if (!bta_hf_client_allocate_handle(bd_addr, p_handle)) {
APPL_TRACE_ERROR("%s: could not allocate handle", __func__);
return;
}
p_buf->hdr.event = BTA_HF_CLIENT_API_OPEN_EVT; //BTA_HF_CLIENT_API_OPEN_EVT = 27 << 8:
p_buf->hdr.layer_specific = *p_handle;
p_buf->bd_addr = bd_addr;
p_buf->sec_mask = sec_mask;
bta_sys_sendmsg(p_buf);
}
enum {
/* these events are handled by the state machine */
BTA_HF_CLIENT_API_OPEN_EVT = BTA_SYS_EVT_START(BTA_ID_HS), // BTA_ID_HS 27
BTA_HF_CLIENT_API_CLOSE_EVT,
BTA_HF_CLIENT_API_AUDIO_OPEN_EVT,
BTA_HF_CLIENT_API_AUDIO_CLOSE_EVT,
BTA_HF_CLIENT_RFC_OPEN_EVT,
BTA_HF_CLIENT_RFC_CLOSE_EVT,
BTA_HF_CLIENT_RFC_SRV_CLOSE_EVT,
BTA_HF_CLIENT_RFC_DATA_EVT,
BTA_HF_CLIENT_DISC_ACP_RES_EVT,
BTA_HF_CLIENT_DISC_INT_RES_EVT,
BTA_HF_CLIENT_DISC_OK_EVT,
BTA_HF_CLIENT_DISC_FAIL_EVT,
BTA_HF_CLIENT_SCO_OPEN_EVT,
BTA_HF_CLIENT_SCO_CLOSE_EVT,
BTA_HF_CLIENT_SEND_AT_CMD_EVT,
BTA_HF_CLIENT_MAX_EVT,
/* these events are handled outside of the state machine */
BTA_HF_CLIENT_API_ENABLE_EVT,
BTA_HF_CLIENT_API_DISABLE_EVT
};
//记住这三个结构体,都包含有一个BT_HDR 的结构提。这结构体中包含一些共同的信息
/* data type for BTA_HF_CLIENT_API_OPEN_EVT */
typedef struct {
BT_HDR hdr;
RawAddress bd_addr;
uint16_t* handle;
tBTA_SEC sec_mask;
} tBTA_HF_CLIENT_API_OPEN;
/* data type for BTA_HF_CLIENT_DISC_RESULT_EVT */
typedef struct {
BT_HDR hdr;
uint16_t status;
} tBTA_HF_CLIENT_DISC_RESULT;
/* data type for RFCOMM events */
typedef struct {
BT_HDR hdr;
uint16_t port_handle;
} tBTA_HF_CLIENT_RFC;
/* generic purpose data type for other events */
typedef struct {
BT_HDR hdr;
bool bool_val;
uint8_t uint8_val;
uint32_t uint32_val1;
uint32_t uint32_val2;
char str[BTA_HF_CLIENT_NUMBER_LEN + 1];
} tBTA_HF_CLIENT_DATA_VAL;
//注意这是一个联合体!!! 后面会知道这个联合体的用处。
/* union of all event datatypes */
typedef union {
BT_HDR hdr;
tBTA_HF_CLIENT_API_OPEN api_open;
tBTA_HF_CLIENT_DISC_RESULT disc_result;
tBTA_HF_CLIENT_RFC rfc;
tBTA_HF_CLIENT_DATA_VAL val;
} tBTA_HF_CLIENT_DATA;
这个方法就是处理event。传进来的参数已经是BT_HDR *,因为这个方法是通用的处理。不止HFP会发送消息到这里进行处理。其他的profile也会发送消息过来,所以需要一个共同的结构体。
id = (uint8_t)(p_msg->event >> 8);
获取的id是右移8位,为什么要这样了。是因为BTA_HF_CLIENT_API_OPEN_EVT就是在 BTA_ID_HS的基础上左移8位,同时这个值又被enum包括,这样后续的值再右移8位后得到的值仍然是BTA_ID_HS。既保证了Event的不同,同时保证这些Event指向同一个ID。
(*bta_sys_cb.reg[id]->evt_hdlr)(p_msg)
从上面我们知道id等于BTA_ID_HS,那就从数组中去除对应register进行处理,使用BTA_ID_HS进行注册的是在bta_hf_client_main.cc bta_hf_client_api_enable()方法中。最终调用 bta_hf_client_hdl_event()。
这个过程还是比较绕的。
//bta_sys_main.cc
void bta_sys_event(BT_HDR* 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 {
APPL_TRACE_WARNING("%s: Received unregistered event id %d", __func__, id);
}
if (freebuf) {
osi_free(p_msg);
}
}
// 2 BTA_HF_CLIENT_API_OPEN_EVT = BTA_ID_HS << 8; 这样后续的值通过右移恢复都会得到同样的值BTA_ID_HS
enum {
/* these events are handled by the state machine */
BTA_HF_CLIENT_API_OPEN_EVT = BTA_SYS_EVT_START(BTA_ID_HS), // BTA_ID_HS 27
BTA_HF_CLIENT_API_CLOSE_EVT,
BTA_HF_CLIENT_API_AUDIO_OPEN_EVT,
BTA_HF_CLIENT_API_AUDIO_CLOSE_EVT,
BTA_HF_CLIENT_RFC_OPEN_EVT,
BTA_HF_CLIENT_RFC_CLOSE_EVT,
BTA_HF_CLIENT_RFC_SRV_CLOSE_EVT,
BTA_HF_CLIENT_RFC_DATA_EVT,
BTA_HF_CLIENT_DISC_ACP_RES_EVT,
BTA_HF_CLIENT_DISC_INT_RES_EVT,
BTA_HF_CLIENT_DISC_OK_EVT,
BTA_HF_CLIENT_DISC_FAIL_EVT,
BTA_HF_CLIENT_SCO_OPEN_EVT,
BTA_HF_CLIENT_SCO_CLOSE_EVT,
BTA_HF_CLIENT_SEND_AT_CMD_EVT,
BTA_HF_CLIENT_MAX_EVT,
/* these events are handled outside of the state machine */
BTA_HF_CLIENT_API_ENABLE_EVT,
BTA_HF_CLIENT_API_DISABLE_EVT
};
//这个方法是在通过 init方法调用的,里面初始化的bta_hf_client_cb_arr 这个重要的结构体。
tBTA_STATUS bta_hf_client_api_enable(tBTA_HF_CLIENT_CBACK* p_cback,
tBTA_SEC sec_mask,
tBTA_HF_CLIENT_FEAT features,
const char* p_service_name) {
...
/* register with BTA system manager */
bta_sys_register(BTA_ID_HS, &bta_hf_client_reg);
...
return BTA_SUCCESS;
}
下面的代码会比较绕,一眼看过还是需要回头在细细品味一下的。我直接在代码中添加注释了。
//注意此处传进来的参数是tBTA_HF_CLIENT_DATA * 联合体,这是因为 tBTA_HF_CLIENT_API_OPEN
//tBTA_HF_CLIENT_DISC_RESULT tBTA_HF_CLIENT_RFC tBTA_HF_CLIENT_DATA_VAL 都会在这里进行处理
void bta_hf_client_sm_execute(uint16_t event, tBTA_HF_CLIENT_DATA* p_data) {
//p_data->hdr.layer_specific 是 handle = 1,此处的结构体是tBTA_HF_CLIENT_CB
//(ps:CB control bolck 千万不要联想是callback)
tBTA_HF_CLIENT_CB* client_cb =
bta_hf_client_find_cb_by_handle(p_data->hdr.layer_specific);
if (client_cb == NULL) {
APPL_TRACE_ERROR("%s: cb not found for handle %d", __func__,
p_data->hdr.layer_specific);
return;
}
tBTA_HF_CLIENT_ST_TBL state_table;
uint8_t action;
int i;
//BTA_HF_CLIENT_API_OPEN_EVT = BTA_SYS_EVT_START(BTA_ID_HS) ===>
uint16_t in_event = event;
//client_cb-> 初始状态是 0
uint8_t in_state = client_cb->state;
/* Ignore displaying of AT results when not connected (Ignored in state
* machine) */
if (client_cb->state == BTA_HF_CLIENT_OPEN_ST) {
APPL_TRACE_EVENT("HF Client evt : State %d (%s), Event 0x%04x (%s)",
client_cb->state,
bta_hf_client_state_str(client_cb->state), event,
bta_hf_client_evt_str(event));
}
//!!! 经过与操作后 event就是值是从0开始,后续的值就是从0的基础上加1。
event &= 0x00FF;
if (event >= (BTA_HF_CLIENT_MAX_EVT & 0x00FF)) {
APPL_TRACE_ERROR("HF Client evt out of range, ignoring...");
return;
}
//bta_hf_client_st_tbl是一组状态表。 (ps:st_tbl state_table)
//client_cb->state 当前是0, 对应状态表:bta_hf_client_st_init
/* look up the state table for the current state */
state_table = bta_hf_client_st_tbl[client_cb->state];
/* set next state */
//通过bta_hf_client_st_init 对应下一个状态。 event = 0, BTA_HF_CLIENT_NEXT_STATE = 2
//就是第一行的最后一个参数就是下一个状态。
// Event Action 1 Action 2 Next State
// API_OPEN_EVT | {BTA_HF_CLIENT_START_OPEN, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_OPENING_ST},
//client_cb->state = BTA_HF_CLIENT_OPENING_ST; (1)
client_cb->state = state_table[event][BTA_HF_CLIENT_NEXT_STATE];
/* execute action functions */
// bta_hf_client_action 是一个action 函数指针 数组
// action = state_table[event][i]; 就是通过查表找对对应action 执行,
// 此处的action BTA_HF_CLIENT_START_OPEN 2
// 执行bta_hf_client_act.cc bta_hf_client_start_open 方法
for (i = 0; i < BTA_HF_CLIENT_ACTIONS; i++) {
action = state_table[event][i];
if (action != BTA_HF_CLIENT_IGNORE) {
(*bta_hf_client_action[action])(p_data);
} else {
break;
}
}
//当前的client_cb->state 为BTA_HF_CLIENT_OPENING_ST,虽然与前一个状态不同。但是不会执行下面的方法。
/* If the state has changed then notify the app of the corresponding change */
if (in_state != client_cb->state) {
VLOG(1) << __func__ << ": notifying state change to " << in_state << " -> "
<< client_cb->state << " device " << client_cb->peer_addr;
tBTA_HF_CLIENT evt;
memset(&evt, 0, sizeof(evt));
evt.bd_addr = client_cb->peer_addr;
if (client_cb->state == BTA_HF_CLIENT_INIT_ST) {
bta_hf_client_app_callback(BTA_HF_CLIENT_CLOSE_EVT, &evt);
} else if (client_cb->state == BTA_HF_CLIENT_OPEN_ST) {
evt.open.handle = client_cb->handle;
bta_hf_client_app_callback(BTA_HF_CLIENT_OPEN_EVT, &evt);
}
}
/* if the next state is INIT then release the cb for future use */
/* If the collision timer is scheduled, don't release the cb */
if ((client_cb->state == BTA_HF_CLIENT_INIT_ST) &&
(!alarm_is_scheduled(client_cb->collision_timer))) {
APPL_TRACE_DEBUG("%s: marking CB handle %d to false", __func__,
client_cb->handle);
client_cb->is_allocated = false;
}
...
}
/* state table */
const tBTA_HF_CLIENT_ST_TBL bta_hf_client_st_tbl[] = {
bta_hf_client_st_init,
bta_hf_client_st_opening,
bta_hf_client_st_open,
bta_hf_client_st_closing};
/* action functions table, indexed with action enum */
const tBTA_HF_CLIENT_ACTION bta_hf_client_action[] = {
/* BTA_HF_CLIENT_RFC_DO_CLOSE */ bta_hf_client_rfc_do_close,
/* BTA_HF_CLIENT_START_CLOSE */ bta_hf_client_start_close,
/* BTA_HF_CLIENT_START_OPEN */ bta_hf_client_start_open,
/* BTA_HF_CLIENT_RFC_ACP_OPEN */ bta_hf_client_rfc_acp_open,
/* BTA_HF_CLIENT_SCO_LISTEN */ NULL,
/* BTA_HF_CLIENT_SCO_CONN_OPEN */ bta_hf_client_sco_conn_open,
/* BTA_HF_CLIENT_SCO_CONN_CLOSE*/ bta_hf_client_sco_conn_close,
/* BTA_HF_CLIENT_SCO_OPEN */ bta_hf_client_sco_open,
/* BTA_HF_CLIENT_SCO_CLOSE */ bta_hf_client_sco_close,
/* BTA_HF_CLIENT_FREE_DB */ bta_hf_client_free_db,
/* BTA_HF_CLIENT_OPEN_FAIL */ bta_hf_client_open_fail,
/* BTA_HF_CLIENT_RFC_OPEN */ bta_hf_client_rfc_open,
/* BTA_HF_CLIENT_RFC_FAIL */ bta_hf_client_rfc_fail,
/* BTA_HF_CLIENT_DISC_INT_RES */ bta_hf_client_disc_int_res,
/* BTA_HF_CLIENT_RFC_DO_OPEN */ bta_hf_client_rfc_do_open,
/* BTA_HF_CLIENT_DISC_FAIL */ bta_hf_client_disc_fail,
/* BTA_HF_CLIENT_RFC_CLOSE */ bta_hf_client_rfc_close,
/* BTA_HF_CLIENT_RFC_DATA */ bta_hf_client_rfc_data,
/* BTA_HF_CLIENT_DISC_ACP_RES */ bta_hf_client_disc_acp_res,
/* BTA_HF_CLIENT_SVC_CONN_OPEN */ bta_hf_client_svc_conn_open,
/* BTA_HF_CLIENT_SEND_AT_CMD */ bta_hf_client_send_at_cmd,
};
在连接之前需要通过SDP发现对端的服务。SDP_ServiceSearchAttributeRequest2()最后的结果会回调给bta_hf_client_sdp_cback。然后又是发送Event到bta_sys_main.cc 的bta_sys_event中进行处理。
最后还是回到bta_hf_client_main.cc 的 bta_hf_client_sm_execute()方法中。
void bta_hf_client_do_disc(tBTA_HF_CLIENT_CB* client_cb) {
Uuid uuid_list[1];
uint16_t num_uuid = 1;
uint16_t attr_list[4];
uint8_t num_attr;
bool db_inited = false;
/* initiator; get proto list and features */
if (client_cb->role == BTA_HF_CLIENT_INT) {
attr_list[0] = ATTR_ID_SERVICE_CLASS_ID_LIST;
attr_list[1] = ATTR_ID_PROTOCOL_DESC_LIST;
attr_list[2] = ATTR_ID_BT_PROFILE_DESC_LIST;
attr_list[3] = ATTR_ID_SUPPORTED_FEATURES;
num_attr = 4;
uuid_list[0] = Uuid::From16Bit(UUID_SERVCLASS_AG_HANDSFREE);
}
/* acceptor; get features */
else {
attr_list[0] = ATTR_ID_SERVICE_CLASS_ID_LIST;
attr_list[1] = ATTR_ID_BT_PROFILE_DESC_LIST;
attr_list[2] = ATTR_ID_SUPPORTED_FEATURES;
num_attr = 3;
uuid_list[0] = Uuid::From16Bit(UUID_SERVCLASS_AG_HANDSFREE);
}
/* allocate buffer for sdp database */
client_cb->p_disc_db = (tSDP_DISCOVERY_DB*)osi_malloc(BT_DEFAULT_BUFFER_SIZE);
/* set up service discovery database; attr happens to be attr_list len */
db_inited = SDP_InitDiscoveryDb(client_cb->p_disc_db, BT_DEFAULT_BUFFER_SIZE,
num_uuid, uuid_list, num_attr, attr_list);
if (db_inited) {
/*Service discovery not initiated */
//会走到此方法中
db_inited = SDP_ServiceSearchAttributeRequest2(
client_cb->peer_addr, client_cb->p_disc_db, bta_hf_client_sdp_cback,
(void*)client_cb);
}
if (!db_inited) {
/*free discover db */
osi_free_and_reset((void**)&client_cb->p_disc_db);
/* sent failed event */
tBTA_HF_CLIENT_DATA msg;
msg.hdr.layer_specific = client_cb->handle;
bta_hf_client_sm_execute(BTA_HF_CLIENT_DISC_FAIL_EVT, &msg);
}
}
static void bta_hf_client_sdp_cback(uint16_t status, void* data) {
uint16_t event;
//注意这里是tBTA_HF_CLIENT_DISC_RESULT 结构体 之前是tBTA_HF_CLIENT_API_OPEN
tBTA_HF_CLIENT_DISC_RESULT* p_buf = (tBTA_HF_CLIENT_DISC_RESULT*)osi_malloc(
sizeof(tBTA_HF_CLIENT_DISC_RESULT));
APPL_TRACE_DEBUG("bta_hf_client_sdp_cback status:0x%x", status);
tBTA_HF_CLIENT_CB* client_cb = (tBTA_HF_CLIENT_CB*)data;
/* set event according to int/acp */
//role 是init
if (client_cb->role == BTA_HF_CLIENT_ACP)
event = BTA_HF_CLIENT_DISC_ACP_RES_EVT;
else
event = BTA_HF_CLIENT_DISC_INT_RES_EVT;
p_buf->hdr.event = event;
p_buf->hdr.layer_specific = client_cb->handle;
p_buf->status = status;
bta_sys_sendmsg(p_buf);
}
最后绕到bta_hf_client_main.cc方法中,我们来分析一波。
首先从API_OPEN 状态 BTA_HF_CLIENT_INIT_ST, 之后将状态迁移到 BTA_HF_CLIENT_OPENING_ST。对应的state_stable是 bta_hf_client_st_opening。
BTA_HF_CLIENT_DISC_INT_RES_EVT 再枚举中排第9。在bta_hf_client_st_opening找到下标为9那一列:
/* DISC_INT_RES_EVT */ {BTA_HF_CLIENT_DISC_INT_RES, BTA_HF_CLIENT_IGNORE,
BTA_HF_CLIENT_OPENING_ST},
找相应的action 值,以及下一个状态。 BTA_HF_CLIENT_DISC_INT_RES 为 13,下一个迁移状态仍然是 BTA_HF_CLIENT_OPENING_ST
根据上面的action值,在bta_hf_client_action 函数指针数组中找到对应下标的函数。
最后找到
/* BTA_HF_CLIENT_DISC_INT_RES */ bta_hf_client_disc_int_res,
接下就是Refcom connect, 两端建立连接。最关键的在于这个状态表迁移的逻辑。如果能够理解整个流程还是比较好理解的。