1. init
@ btif_av.c
static bt_status_t init_src(btav_callbacks_t* callbacks, int max_a2dp_connections,
int a2dp_multicast_state, const char* offload_cap)
{
.....
//目前上层传下来的 offload_cap 为null
if (offload_cap)
{
bt_split_a2dp_enabled = TRUE;
//设定支援的 codec
get_offload_codec_capabilities(offload_cap);
is_multicast_supported = FALSE; //Disable multicast in Split A2dp mode
}
status = btif_av_init(BTA_A2DP_SOURCE_SERVICE_ID);
if (status == BT_STATUS_SUCCESS) {
// 保存 callback
bt_av_src_callbacks = callbacks;
}
return status;
}
bt_status_t btif_av_init(int service_id)
{
int i;
// 为了支持多设备这里 btif_av_cb 变为数组
if (btif_av_cb[0].sm_handle == NULL)
{
......
btif_av_cb[0].service = service_id;
/* 初始化a2dp 的状态机 */
for (i = 0; i < btif_max_av_clients; i++)
{
// 关键函数 ①
btif_av_cb[i].sm_handle = btif_sm_init((const btif_sm_handler_t*)btif_av_state_handlers,
BTIF_AV_STATE_IDLE, i);
}
// 关键函数 ②
btif_transfer_context(btif_av_handle_event, BTIF_AV_INIT_REQ_EVT,
(char*)&service_id, sizeof(int), NULL);
// 关键函数 ③
btif_enable_service(service_id);
}
return BT_STATUS_SUCCESS;
}
分别来看以上3个关键函数
1.1 btif_sm_init
用来初始化 a2dp 的状态机, 将 btif_av_cb[i].sm_handle 指向一个 btif_sm_cb_t 结构体
typedef struct {
btif_sm_state_t state; //初始状态为 BTIF_AV_STATE_IDLE
int index; //a2dp 设备号
//状态处理函数数组, 指向 btif_av_state_handlers
btif_sm_handler_t *p_handlers;
} btif_sm_cb_t;
typedef enum {
BTIF_AV_STATE_IDLE = 0x0,
BTIF_AV_STATE_OPENING,
BTIF_AV_STATE_OPENED,
BTIF_AV_STATE_STARTED,
BTIF_AV_STATE_CLOSING
} btif_av_state_t;
static const btif_sm_handler_t btif_av_state_handlers[] =
{
btif_av_state_idle_handler,
btif_av_state_opening_handler,
btif_av_state_opened_handler,
btif_av_state_started_handler,
btif_av_state_closing_handler
};
a2dp 的连接状态切换都会由 btif_av_cb[i].sm_handle 来记录和处理。 在初始化状态机之后 btif_sm_init 最后会向初始状态发送 BTIF_SM_ENTER_EVT :
/* Send BTIF_SM_ENTER_EVT to the initial state */
p_cb->p_handlers[initial_state](BTIF_SM_ENTER_EVT, NULL, index);
由 btif_av_state_idle_handler 来处理 , 其中做一些 cleanup 以及参数的初始化
1.2 btif_a2dp_start_media_task
btif_av_init 函数中还会调用到
btif_transfer_context(btif_av_handle_event, BTIF_AV_INIT_REQ_EVT,
(char*)&service_id, sizeof(int), NULL);
前面的笔记有分析 bluedroid 中线程及消息的处理, 这里不再详细分析其过程。 最终的处理是在
static void btif_av_handle_event(UINT16 event, char* p_param)
{
......
switch (event)
{
case BTIF_AV_INIT_REQ_EVT:
if(btif_a2dp_start_media_task())
btif_a2dp_on_init();
break;
}
btif_a2dp_start_media_task 中又会涉及很多的跨线程通信, 先不看这些内容, 直接看最后的调用 :
static void btif_media_thread_init(UNUSED_ATTR void *context) {
// 仅支持 8 bits/byte
assert(CHAR_BIT == 8);
APPL_TRACE_IMP(" btif_media_thread_init");
memset(&btif_media_cb, 0, sizeof(btif_media_cb));
UIPC_Init(NULL);
btif_media_cb.TxAaQ = fixed_queue_new(SIZE_MAX);
btif_media_cb.RxSbcQ = fixed_queue_new(SIZE_MAX);
UIPC_Open(UIPC_CH_ID_AV_CTRL , btif_a2dp_ctrl_cb);
raise_priority_a2dp(TASK_HIGH_MEDIA);
media_task_running = MEDIA_TASK_STATE_ON;
APPL_TRACE_DEBUG(" btif_media_thread_init complete");
}
这里主要函数为 UIPC_Init 和 UIPC_Open , 他们的作用是什么呢?
Audio Flinger 加载 audio_a2dp_hw 来向 bluedroid 传输数据, 而他们通信的方式就是通过两个socket :
#define A2DP_CTRL_PATH "/data/misc/bluedroid/.a2dp_ctrl"
#define A2DP_DATA_PATH "/data/misc/bluedroid/.a2dp_data"
从名字可以看出一个是用来控制,另一个是用来传输。 UIPC_Init 中初始化 uipc_main , 这里的 UIPC_Open 中创建 a2dp_ctrl socket , 其事件处理函数为 btif_a2dp_ctrl_cb 。 来看一下这里的结构 :
static tUIPC_MAIN uipc_main;
typedef struct {
pthread_t tid; // event 处理线程 uipc_read_task
int running; // uipc_read_task 状态
pthread_mutex_t mutex;
fd_set active_set; // uipc_read_task 中监听的fd集合
fd_set read_set; // 等于active_set
int max_fd;
int signal_fds[2]; // interrupt socket pair
tUIPC_CHAN ch[UIPC_CH_NUM]; //包含 a2dp_ctrl , a2dp_data 的socket fd 的结构体
} tUIPC_MAIN;
其中两个 tUIPC_CHAN 变量, 分别对应 a2dp_ctrl , a2dp_data
typedef struct {
int srvfd; // server socket fd
int fd; // 连接的socket fd
int read_poll_tmo_ms;
int task_evt_flags; /* event flags pending to be processed in read task */
tUIPC_EVENT cond_flags;
pthread_mutex_t cond_mutex;
pthread_cond_t cond;
tUIPC_RCV_CBACK *cback; //event 处理函数
} tUIPC_CHAN;
1.3 btif_enable_service
bt_status_t btif_enable_service(tBTA_SERVICE_ID service_id)
{
tBTA_SERVICE_ID *p_id = &service_id;
/* If BT is enabled, we need to switch to BTIF context and trigger the
* enable for that profile
*
* Otherwise, we just set the flag. On BT_Enable, the DM will trigger
* enable for the profiles that have been enabled */
btif_enabled_services |= (1 << service_id);
if (btif_is_enabled())
{
btif_transfer_context(btif_dm_execute_service_request,
BTIF_DM_ENABLE_SERVICE,
(char*)p_id, sizeof(tBTA_SERVICE_ID), NULL);
}
return BT_STATUS_SUCCESS;
}
看注释的意思: 如果此时 BT 还没有enable , 则仅设置 flag , 在后面 BT enable 之后 DM 将会把这些设置了 flag 的 profile enable 起来; 如果此时 BT 已经enable 则主动去 enable 该profile 。 实际抓到的 log 来看一般这里 BT 还没有enable 。
2. enable a2dp profile
在来看一下 BT enable 之后是如何 enable a2dp profile 的 , 当 enable 到一定阶段会发送 bluedroid 中会发送 BTA_DM_ENABLE_EVT
static void btif_dm_upstreams_evt(UINT16 event, char* p_param)
{
switch (event)
{
case BTA_DM_ENABLE_EVT:
{
/* 获取到所有需要enable profile 的mask , 然后enable profiles */
service_mask = btif_get_enabled_services_mask();
for (i=0; i <= BTA_MAX_SERVICE_ID; i++)
{
if (service_mask &
(tBTA_SERVICE_MASK)(BTA_SERVICE_ID_TO_SERVICE_MASK(i)))
{
btif_in_execute_service_request(i, TRUE);
}
}
}
}
bt_status_t btif_in_execute_service_request(tBTA_SERVICE_ID service_id,
BOOLEAN b_enable)
{
case BTA_A2DP_SOURCE_SERVICE_ID:
{
btif_av_execute_service(b_enable);
......
}
a2dp profile enable 开始
bt_status_t btif_av_execute_service(BOOLEAN b_enable)
{
if (b_enable)
{
BTA_AvEnable(BTA_SEC_AUTHENTICATE, BTA_AV_FEAT_RCTG|...|BTA_AV_FEAT_ADV_CTRL
,bte_av_callback);
BTA_AvRegister(BTA_AV_CHNL_AUDIO, BTIF_AV_SERVICE_NAME, 0, bte_av_media_callback,
UUID_SERVCLASS_AUDIO_SOURCE);
}
else {
BTA_AvDeregister(btif_av_cb.bta_handle);
BTA_AvDisable();
}
return BT_STATUS_SUCCESS;
}
2.1 BTA_AvEnable
void BTA_AvEnable(tBTA_SEC sec_mask, tBTA_AV_FEAT features, tBTA_AV_CBACK *p_cback)
{
tBTA_AV_API_ENABLE *p_buf =
(tBTA_AV_API_ENABLE *)osi_malloc(sizeof(tBTA_AV_API_ENABLE));
/* register with BTA system manager */
bta_sys_register(BTA_ID_AV, &bta_av_reg);
p_buf->hdr.event = BTA_AV_API_ENABLE_EVT;
p_buf->p_cback = p_cback;
p_buf->features = features;
p_buf->sec_mask = sec_mask;
bta_sys_sendmsg(p_buf);
}
bta_sys_register
在 bta 这一层每一个 profile 都会设置其event 处理函数 :
void bta_sys_register(UINT8 id, const tBTA_SYS_REG *p_reg)
{
bta_sys_cb.reg[id] = (tBTA_SYS_REG *) p_reg;
bta_sys_cb.is_reg[id] = TRUE;
}
static const tBTA_SYS_REG bta_av_reg =
{
bta_av_hdl_event,
BTA_AvDisable
};
BTA_AV_API_ENABLE_EVT
回头看 BTA_AvEnable 还会发送一个 BTA_AV_API_ENABLE_EVT 消息, 此外消息中的 p_cback 为 bte_av_callback
bta_sys_sendmsg 发送的消息最后都会由 bta_sys_event 来处理, 其中会根据 event 中的前8位service id 来交给 bta_sys_cb.reg[id]->evt_hdlr (每个profile 的 event handler)处理
void bta_sys_event(BT_HDR *p_msg)
{
/* get subsystem id from event */
id = (UINT8) (p_msg->event >> 8);
if ((id < BTA_ID_MAX) && (bta_sys_cb.reg[id] != NULL))
{
freebuf = (*bta_sys_cb.reg[id]->evt_hdlr)(p_msg);
}
}
前面可以看到这里 a2dp 对应的 bta_sys_cb.reg[id]->evt_hdlr 就是 bta_av_reg.bta_av_hdl_event
再来看 bta_av_hdl_event 其中将 BTA AV event 分为3类来调用不同的处理函数 :
BOOLEAN bta_av_hdl_event(BT_HDR *p_msg)
{
UINT16 event = p_msg->event;
UINT16 first_event = BTA_AV_FIRST_NSM_EVT;
if(event >= first_event)
{
/* non state machine events */
(*bta_av_nsm_act[event - BTA_AV_FIRST_NSM_EVT]) ((tBTA_AV_DATA *) p_msg);
}
else if (event >= BTA_AV_FIRST_SM_EVT && event <= BTA_AV_LAST_SM_EVT)
{
/* state machine events */
bta_av_sm_execute(&bta_av_cb, p_msg->event, (tBTA_AV_DATA *) p_msg);
}
else
{
/* stream state machine events */
bta_av_ssm_execute( bta_av_hndl_to_scb(p_msg->layer_specific),
p_msg->event, (tBTA_AV_DATA *) p_msg);
}
return TRUE;
}
这里 BTA_AV_API_ENABLE_EVT 属于 “non state machine events” , (*bta_av_nsm_act[event - BTA_AV_FIRST_NSM_EVT]) 对应到 :
const tBTA_AV_NSM_ACT bta_av_nsm_act[] =
{
bta_av_api_enable, /* BTA_AV_API_ENABLE_EVT */
bta_av_api_register, /* BTA_AV_API_REGISTER_EVT */
......
static void bta_av_api_enable(tBTA_AV_DATA *p_data)
{
/* initialize control block */
memset(&bta_av_cb, 0, sizeof(tBTA_AV_CB));
for (int i = 0; i < BTA_AV_NUM_RCB; i++)
bta_av_cb.rcb[i].handle = BTA_AV_RC_HANDLE_NONE;
bta_av_cb.rc_acp_handle = BTA_AV_RC_HANDLE_NONE;
/*
* TODO: The "disable" event handling is missing - there we need
* to alarm_free() the alarms below.
*/
bta_av_cb.link_signalling_timer = alarm_new("bta_av.link_signalling_timer");
bta_av_cb.accept_signalling_timer =
alarm_new("bta_av.accept_signalling_timer");
/* 将之前传的数据取出赋值到 bta_av_cb*/
bta_av_cb.p_cback = p_data->api_enable.p_cback; //bte_av_callback
bta_av_cb.features = p_data->api_enable.features;
bta_av_cb.sec_mask = p_data->api_enable.sec_mask;
tBTA_AV_ENABLE enable;
enable.features = bta_av_cb.features;
/* 注册 bta_sys_cb 中的 SCO 连接状态callback p_sco_cb */
if (!(bta_av_cb.features & BTA_AV_FEAT_NO_SCO_SSPD))
{
bta_sys_sco_register(bta_av_sco_chg_cback);
}
/* call callback with enable event */
(*bta_av_cb.p_cback)(BTA_AV_ENABLE_EVT, (tBTA_AV *)&enable);
}
这里主要是初始化 bta 中的 a2dp control block : bta_av_cb .
最后将 BTA_AV_ENABLE_EVT 交给 btif_av_cb[index].sm_handle 当前states 的 handler 来处理, 当前为 IDLE 状态由 btif_av_state_idle_handler 来处理, 这里的处理仅仅是打印了一行log :
static BOOLEAN btif_av_state_idle_handler(btif_sm_event_t event, void *p_data, int index)
{
case BTA_AV_ENABLE_EVT:
BTIF_TRACE_EVENT("AV is enabled now for index: %d", index);
break;
2.2 BTA_AvRegister
继续 btif_av_execute_service 的第二个函数 BTA_AvRegister
BTA_AvRegister(BTA_AV_CHNL_AUDIO, BTIF_AV_SERVICE_NAME, 0, bte_av_media_callback,
UUID_SERVCLASS_AUDIO_SOURCE);
void BTA_AvRegister(tBTA_AV_CHNL chnl, const char *p_service_name, UINT8 app_id,
tBTA_AV_DATA_CBACK *p_data_cback, UINT16 service_uuid)
{
tBTA_AV_API_REG *p_buf =
(tBTA_AV_API_REG *)osi_malloc(sizeof(tBTA_AV_API_REG));
p_buf->hdr.layer_specific = chnl;
p_buf->hdr.event = BTA_AV_API_REGISTER_EVT;
......
bta_sys_sendmsg(p_buf);
}
发送 BTA_AV_API_REGISTER_EVT 到 bta 层 , 和前面一样最后根据event 中的 service id 交给对应的 handler 处理, a2dp 的处理函数为 bta_av_hdl_event , BTA_AV_API_REGISTER_EVT 对应的处理函数为 bta_av_api_register .
/*******************************************************************************
** Description allocate stream control block,
** register the service to stack
** create SDP record
*******************************************************************************/
static void bta_av_api_register(tBTA_AV_DATA *p_data)
{
if(registr.chnl == BTA_AV_CHNL_AUDIO)
{
/* set up the audio stream control block */
APPL_TRACE_EVENT("AV: set up the audio stream control block ");
// 后面的a2dp 相关的处理都会用到 bta_av_a2d_action
p_scb->p_act_tbl = (const tBTA_AV_ACT *)bta_av_a2d_action;
p_scb->p_cos = &bta_av_a2d_cos;
p_scb->media_type= AVDT_MEDIA_AUDIO;
cs.cfg.psc_mask = AVDT_PSC_TRANS;
cs.media_type = AVDT_MEDIA_AUDIO;
cs.mtu = p_bta_av_cfg->audio_mtu;
cs.flush_to = L2CAP_DEFAULT_FLUSH_TO;
......
if(!bta_av_cb.reg_audio)
{
bta_av_cb.sdp_a2d_handle = 0;
if (profile_initialized == UUID_SERVCLASS_AUDIO_SOURCE)
{
/* create the SDP records on the 1st audio channel */
bta_av_cb.sdp_a2d_handle = SDP_CreateRecord();
A2D_AddRecord(UUID_SERVCLASS_AUDIO_SOURCE, p_service_name, NULL,
A2D_SUPF_PLAYER, bta_av_cb.sdp_a2d_handle);
bta_sys_add_uuid(UUID_SERVCLASS_AUDIO_SOURCE);
}
/* start listening when A2DP is registered */
......
}
这里主要用来初始化 stream control block 即 bta_av_cb.p_scb , 其中包含 AVDTP END POINT 的信息, 此外在创建 “Advanced Audio” SDP record .
3.总结
自己总结一下开起 BT 时主要做的事情 :
- 初始化 btif av 状态机 btif_av_cb[i].sm_handle = btif_av_state_handlers (此处 i 为支持的支持连接的 a2dp client 数目),初始状态为 idle , 其状态包含 :
BTIF_AV_STATE_IDLE = 0x0, BTIF_AV_STATE_OPENING, BTIF_AV_STATE_OPENED, BTIF_AV_STATE_STARTED, BTIF_AV_STATE_CLOSING
- 创建 a2dp_ctrl socket (/data/misc/bluedroid/.a2dp_ctrl)
- 设定 bta av 的 event 处理函数 bta_av_hdl_event ,bta 层向上层提供的 AV 接口就是向其发送event , 其中将 event 分为3类来处理 ,
- non state machine events
- state machine events
- stream state machine events
- 注册 “Advanced Audio” SDP record , 并填充包含 AVDTP END POINT 的信息