蓝牙A2DP的初始化过程

当我们要使用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;

你可能感兴趣的:(蓝牙学习)