对于Audio Flinger而言,他能够获取到a2dp的hw module,然后怎才能将数据送至蓝牙协议栈。蓝牙方面已经起了一个线程,专用于发送和接收media的数据,线程名称:btif_media_task.蓝牙与Audio的通信则采用了socket的方式,管理socket的中间文件为:UIPC。
因此UIPC主要的作用就是,接收Audio的控制命令转发给bt,接收Audio的音频数据发送给bt。因此UIPC建立了两条socket,分别为:
#define A2DP_CTRL_PATH "/data/misc/bluedroid/.a2dp_ctrl"
#define A2DP_DATA_PATH "/data/misc/bluedroid/.a2dp_data"
其中第一条control socket在btif media task启动的时候随之创建。
bool btif_a2dp_start_media_task(void)
{
...
thread_post(worker_thread, btif_media_thread_init, NULL);
APPL_TRACE_EVENT("## A2DP MEDIA THREAD STARTED ##");
return true;
...
}
static void btif_media_thread_init(UNUSED_ATTR void *context) {
memset(&btif_media_cb, 0, sizeof(btif_media_cb));
UIPC_Init(NULL);
UIPC_Open(UIPC_CH_ID_AV_CTRL , btif_a2dp_ctrl_cb);
raise_priority_a2dp(TASK_HIGH_MEDIA);
media_task_running = MEDIA_TASK_STATE_ON;
}
第二条data socket在收到audio cmd start时候创建。任何命令的处理,btif task都需要恢复ack,表明命令是否执行完成。
case A2DP_CTRL_CMD_START:
if (!btif_hf_is_call_idle())
{
a2dp_cmd_acknowledge(A2DP_CTRL_ACK_INCALL_FAILURE);
break;
}
if (btif_av_stream_ready() == TRUE)
{
UIPC_Open(UIPC_CH_ID_AV_AUDIO, btif_a2dp_data_cb);
btif_dispatch_sm_event(BTIF_AV_START_STREAM_REQ_EVT, NULL, 0);
#if (BTA_AV_SINK_INCLUDED == TRUE)
if (btif_media_cb.peer_sep == AVDT_TSEP_SRC)
a2dp_cmd_acknowledge(A2DP_CTRL_ACK_SUCCESS);
#endif
}
else if (btif_av_stream_started_ready())
{
UIPC_Open(UIPC_CH_ID_AV_AUDIO, btif_a2dp_data_cb);
a2dp_cmd_acknowledge(A2DP_CTRL_ACK_SUCCESS);
}
else
{
a2dp_cmd_acknowledge(A2DP_CTRL_ACK_FAILURE);
break;
}
break;
static int a2dp_command(struct a2dp_stream_common *common, char cmd)
{
char ack;
DEBUG("A2DP COMMAND %s", dump_a2dp_ctrl_event(cmd));
if (send(common->ctrl_fd, &cmd, 1, MSG_NOSIGNAL) == -1)
{
ERROR("cmd failed (%s)", strerror(errno));
skt_disconnect(common->ctrl_fd);
common->ctrl_fd = AUDIO_SKT_DISCONNECTED;
return -1;
}
if (a2dp_ctrl_receive(common, &ack, 1) < 0)
return -1;
...
UIPC接收command机制:
1. 启动时,创建一个thread,接收command。
void UIPC_Init(void *p_data)
{
UNUSED(p_data);
BTIF_TRACE_DEBUG("UIPC_Init");
memset(&uipc_main, 0, sizeof(tUIPC_MAIN));
uipc_main_init();
uipc_start_main_server_thread();
}
int uipc_start_main_server_thread(void)
{
uipc_main.running = 1;
if (pthread_create(&uipc_main.tid, (const pthread_attr_t *) NULL, (void*)uipc_read_task, NULL) < 0)
{
BTIF_TRACE_ERROR("uipc_thread_create pthread_create failed:%d", errno);
return -1;
}
return 0;
}
2. 监听每一个socket,发现数据后,有限判断是不是音频,再判断是不是命令。
static void uipc_read_task(void *arg)
{
while (uipc_main.running)
{
result = select(uipc_main.max_fd+1, &uipc_main.read_set, NULL, NULL, NULL);
uipc_check_fd_locked(UIPC_CH_ID_AV_AUDIO);
for (ch_id = 0; ch_id < UIPC_CH_NUM; ch_id++) {
if (ch_id != UIPC_CH_ID_AV_AUDIO)
uipc_check_fd_locked(ch_id);
}
}
static int uipc_check_fd_locked(tUIPC_CH_ID ch_id)
{
if (uipc_main.ch[ch_id].cback)
uipc_main.ch[ch_id].cback(ch_id, UIPC_RX_DATA_READY_EVT);
}
3. 通知btif去读取command并处理
static void btif_a2dp_ctrl_cb(tUIPC_CH_ID ch_id, tUIPC_EVENT event)
{
switch(event)
{
case UIPC_RX_DATA_READY_EVT:
btif_recv_ctrl_data();
break;
}
}
static void btif_recv_ctrl_data(void)
{
UINT8 cmd = 0;
int n;
n = UIPC_Read(UIPC_CH_ID_AV_CTRL, NULL, &cmd, 1);
}
经过上面复杂的操作,btif总算得到了audio发来的command,主要的命令就是suspend和start。