当我们要使用A2dp这个profile的时候,首先A2DPService的start()函数会被触发:
protected boolean start() {
mStateMachine = A2dpStateMachine.make(this, this);
mAvrcp = Avrcp.make(this);
setA2dpService(this);
return true;
}
此处主要创建了一个管理a2dp的状态机以及avrcp协议的创建。
那我们先来看A2dpStateMachine的初始化,它里面调用了一个native的init以及加入了三个状态。在initNative中,注册了a2dp的profile。
static void initNative(JNIEnv *env, jobject object) {
const bt_interface_t* btInf;
bt_status_t status;
if ( (btInf = getBluetoothInterface()) == NULL) {
ALOGE("Bluetooth module is not loaded");
return;
}
if (sBluetoothA2dpInterface !=NULL) {
ALOGW("Cleaning up A2DP Interface before initializing...");
sBluetoothA2dpInterface->cleanup();
sBluetoothA2dpInterface = NULL;
}
if (mCallbacksObj != NULL) {
ALOGW("Cleaning up A2DP callback object");
env->DeleteGlobalRef(mCallbacksObj);
mCallbacksObj = NULL;
}
if ( (sBluetoothA2dpInterface = (btav_interface_t *)
btInf->get_profile_interface(BT_PROFILE_ADVANCED_AUDIO_ID)) == NULL) {
ALOGE("Failed to get Bluetooth A2DP Interface");
return;
}//还是见btif/src/bluetooth.c中BT_PROFILE_ADVANCED_AUDIO_ID对应得到的是sBluetoothA2dpInterface,具体见./btif/src/btif_av.c
if ( (status = sBluetoothA2dpInterface->init(&sBluetoothA2dpCallbacks)) != BT_STATUS_SUCCESS) {
ALOGE("Failed to initialize Bluetooth A2DP, status: %d", status);
sBluetoothA2dpInterface = NULL;
return;
}//此处init函数见下面分解
mCallbacksObj = env->NewGlobalRef(object);
}
在btif_av.c文件中,我们可以看到具体的init动作
bt_status_t btif_av_init(void)
{
if (btif_av_cb.sm_handle == NULL)
{
if (btif_a2dp_start_media_task() != GKI_SUCCESS)
return BT_STATUS_FAIL;
btif_enable_service(BTA_A2DP_SERVICE_ID);//此处具体进行addservice操作
/* Also initialize the AV state machine */
btif_av_cb.sm_handle = btif_sm_init((const btif_sm_handler_t*)btif_av_state_handlers, BTIF_AV_STATE_IDLE);
btif_a2dp_on_init();
return BT_STATUS_SUCCESS;
}
return BT_STATUS_DONE;
}
首先建立一个线程来监听socket链接(btif_a2dp_start_media_task),这个线程主要是建立用来将准备好的pcm数据sbc压缩。
nt btif_media_task(void *p)
{
UINT16 event;
BT_HDR *p_msg;
VERBOSE("================ MEDIA TASK STARTING ================");
btif_media_task_init();
media_task_running = MEDIA_TASK_STATE_ON;
raise_priority_a2dp(TASK_HIGH_MEDIA);
while (1)
{
event = GKI_wait(0xffff, 0);
VERBOSE("================= MEDIA TASK EVENT %d ===============", event);
if (event & BTIF_MEDIA_TASK_CMD)
{
/* Process all messages in the queue */
while ((p_msg = (BT_HDR *) GKI_read_mbox(BTIF_MEDIA_TASK_CMD_MBOX)) != NULL)
{
btif_media_task_handle_cmd(p_msg);
}
}
if (event & BTIF_MEDIA_TASK_DATA)
{
/* Process all messages in the queue */
while ((p_msg = (BT_HDR *) GKI_read_mbox(BTIF_MEDIA_TASK_DATA_MBOX)) != NULL)
{
btif_media_task_handle_media(p_msg);
}
}
if (event & BTIF_MEDIA_AA_TASK_TIMER)
{
/* advance audio timer expiration */
btif_media_task_aa_handle_timer();
}
VERBOSE("=============== MEDIA TASK EVENT %d DONE ============", event);
/* When we get this event we exit the task - should only happen on GKI_shutdown */
if (event & BTIF_MEDIA_TASK_KILL)
{
/* make sure no channels are restarted while shutting down */
media_task_running = MEDIA_TASK_STATE_SHUTTING_DOWN;
/* this calls blocks until uipc is fully closed */
UIPC_Close(UIPC_CH_ID_ALL);
break;
}
}
/* Clear media task flag */
media_task_running = MEDIA_TASK_STATE_OFF;
APPL_TRACE_DEBUG0("MEDIA TASK EXITING");
return 0;
}
第二步,进行注册service,btif_enable_service(BTA_A2DP_SERVICE_ID);调用的还是和hsp注册过程一样的bt_status_t btif_av_execute_service(BOOLEAN b_enable)函数。
该函数中有如下两个调用,具体的干事情的地方在bta_av_main.c这个文件里。
BTA_AvEnable(BTA_SEC_AUTHENTICATE, (BTA_AV_FEAT_RCTG | BTA_AV_FEAT_NO_SCO_SSPD),
bte_av_callback);
BTA_AvRegister(BTA_AV_CHNL_AUDIO, BTIF_AV_SERVICE_NAME, 0);
先来看BTA_AvEnable()
void BTA_AvEnable(tBTA_SEC sec_mask, tBTA_AV_FEAT features, tBTA_AV_CBACK *p_cback)
{
tBTA_AV_API_ENABLE *p_buf;
/* register with BTA system manager */
GKI_sched_lock();
bta_sys_register(BTA_ID_AV, &bta_av_reg);//注册了bta_sys_cb的处理函数
GKI_sched_unlock();
if ((p_buf = (tBTA_AV_API_ENABLE *) GKI_getbuf(sizeof(tBTA_AV_API_ENABLE))) != NULL)
{
p_buf->hdr.event = BTA_AV_API_ENABLE_EVT;//传入的event,下面有用到
p_buf->p_cback = p_cback;
p_buf->features = features;
p_buf->sec_mask = sec_mask;
bta_sys_sendmsg(p_buf);//在bta_ava_hdl_event中处理
}
}
static const tBTA_SYS_REG bta_av_reg =
{
bta_av_hdl_event,
BTA_AvDisable
};
此处来看下具体这个消息的处理的地方:
BOOLEAN bta_av_hdl_event(BT_HDR *p_msg)
{
UINT16 event = p_msg->event;
UINT16 first_event = BTA_AV_FIRST_NSM_EVT;
if (event > BTA_AV_LAST_EVT)
{
return TRUE; /* to free p_msg */
}
if(event >= first_event)//此处满足条件,BTA_AV_FIRST_NSM_EVT为firstevent,与传入进来的BTA_AV_API_ENABLE_EVT是一致的。
{
#if (defined(BTA_AV_DEBUG) && BTA_AV_DEBUG == TRUE)
APPL_TRACE_VERBOSE2("AV nsm event=0x%x(%s)", event, bta_av_evt_code(event));
#else
APPL_TRACE_VERBOSE1("AV nsm event=0x%x", event);
#endif
/* non state machine events */
(*bta_av_nsm_act[event - BTA_AV_FIRST_NSM_EVT]) ((tBTA_AV_DATA *) p_msg);//主要调用这里这个函数
}
****省略****
return TRUE;
}
这里的(*bta_av_nsm_act[event - BTA_AV_FIRST_NSM_EVT])指向bta_av_api_enable(),后面的先不用管了。
再来看BTA_AvRegister
遵循一样的流程,可以在bta_av_main.c中看到
static void bta_av_api_register(tBTA_AV_DATA *p_data)函数
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 */
if (bta_av_cb.features & BTA_AV_FEAT_RCTG)
bta_av_rc_create(&bta_av_cb, AVCT_ACP, 0, BTA_AV_NUM_LINKS + 1);
这里就见到熟悉的sdp了,注册流程以及一些其他工作在这里完成了,未能细查。
完成了服务的注册之后,还要设置一些状态:
第三步,注册一些关于av状态的回调函数btif_av_cb.sm_handle = btif_sm_init((const btif_sm_handler_t*)btif_av_state_handlers, BTIF_AV_STATE_IDLE);
这里的btif_av_cb变量需要注意下,他是btif_av_cb_t*的一个指针,
typedef struct
{
tBTA_AV_HNDL bta_handle;
bt_bdaddr_t peer_bda;
btif_sm_handle_t sm_handle;//状态切换的处理函数
UINT8 flags;
tBTA_AV_EDR edr;
} btif_av_cb_t;
具体可以见每个状态的处理函数结构体btif_av_state_handlers:
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
};
并且进入btif_av_state_idle_handler状态。
到这里为止,a2dp的初始化工作算是完成了。
接下来我们看下设备去连接一个sink端的过程。
当蓝牙耳机之类的设备被扫描到后,通过调用A2dpStateMachine的
if (!connectA2dpNative(getByteAddress(device)) ) {
broadcastConnectionState(device, BluetoothProfile.STATE_DISCONNECTED,
BluetoothProfile.STATE_CONNECTING);
break;
}
然后惯例,会调用到btif_av.c中的connect函数
static bt_status_t connect(bt_bdaddr_t *bd_addr)
{
BTIF_TRACE_EVENT1("%s", __FUNCTION__);
CHECK_BTAV_INIT();
return btif_queue_connect(UUID_SERVCLASS_AUDIO_SOURCE, bd_addr, connect_int);//加入处理队列,等待调用connect_int函数
}
connect_int函数中:
static bt_status_t connect_int(bt_bdaddr_t *bd_addr)
{
BTIF_TRACE_EVENT1("%s", __FUNCTION__);
btif_sm_dispatch(btif_av_cb.sm_handle, BTIF_AV_CONNECT_REQ_EVT, (char*)bd_addr);
return BT_STATUS_SUCCESS;
}
由于当前是idle状态,所以任然会进入btif_av_state_idle_handler函数中执行
case BTIF_AV_CONNECT_REQ_EVT:
{
if (event == BTIF_AV_CONNECT_REQ_EVT)
{
memcpy(&btif_av_cb.peer_bda, (bt_bdaddr_t*)p_data, sizeof(bt_bdaddr_t));
}
else if (event == BTA_AV_PENDING_EVT)
{
bdcpy(btif_av_cb.peer_bda.address, ((tBTA_AV*)p_data)->pend.bd_addr);
}
BTA_AvOpen(btif_av_cb.peer_bda.address,btif_av_cb.bta_handle,
TRUE, BTA_SEC_NONE);
btif_sm_change_state(btif_av_cb.sm_handle, BTIF_AV_STATE_OPENING);//设置为opening状态
} break;