博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
A2dp sink 初始化流程源码分析
阅读量:6268 次
发布时间:2019-06-22

本文共 35052 字,大约阅读时间需要 116 分钟。

A2dp sink的初始化流程和A2dp 的初始化流程,基本一样,这里做简单分析.这里分析的android的版本是Android O.

我们先从service的启动说起吧.

下面 是启动的时候的log:

D/BluetoothAdapterService( 2029): setProfileServiceState() - Starting service com.android.bluetooth.a2dpsink.A2dpSinkService
01-01 08:00:22.042 D/A2dpSinkService( 2029): Received start request. Starting profile...01-01 08:00:22.045 D/A2dpSinkService( 2029): start()01-01 08:00:22.054 I/BluetoothA2dpSinkServiceJni( 2029): classInitNative: succeeds

我们看看 A2dpSinkService.java的start函数的实现:

protected boolean start() {        if (DBG) {            Log.d(TAG, "start()");        }        // Start the media browser service.        Intent startIntent = new Intent(this, A2dpMediaBrowserService.class);        startService(startIntent);//启动service        mStateMachine = A2dpSinkStateMachine.make(this, this);//启动状态机        setA2dpSinkService(this);//设置sA2dpSinkService = this        return true;    }

 

这里比较重要的地方就是 sink 状态机的启动,我们进一步看看:

static A2dpSinkStateMachine make(A2dpSinkService svc, Context context) {        Log.d("A2dpSinkStateMachine", "make");        A2dpSinkStateMachine a2dpSm = new A2dpSinkStateMachine(svc, context);//新建状态机        a2dpSm.start();        return a2dpSm;    }

 我们看看这个类的构造函数实现:

static {        classInitNative();    }
private A2dpSinkStateMachine(A2dpSinkService svc, Context context) {        super("A2dpSinkStateMachine");        mService = svc;        mContext = context;        mAdapter = BluetoothAdapter.getDefaultAdapter();        initNative();//初始化        mDisconnected = new Disconnected();        mPending = new Pending();        mConnected = new Connected();        addState(mDisconnected);        addState(mPending);        addState(mConnected);        setInitialState(mDisconnected);        PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);        mIntentBroadcastHandler = new IntentBroadcastHandler();    }

 

上面  主要做了初始化,然后 新建三个状态,然后设置初始状态.这里主要分析一下初始化相关的流程: classInitNative()和initNative()

我们先看前者:

private native static void classInitNative();

 

这是本地实现的函数,在com_android_bluetooth_a2dp_sink.cpp中:

static void classInitNative(JNIEnv* env, jclass clazz) {  method_onConnectionStateChanged =      env->GetMethodID(clazz, "onConnectionStateChanged", "(I[B)V");  method_onAudioStateChanged =      env->GetMethodID(clazz, "onAudioStateChanged", "(I[B)V");  method_onAudioConfigChanged =      env->GetMethodID(clazz, "onAudioConfigChanged", "([BII)V");  ALOGI("%s: succeeds", __func__);}

 

主要就是 从上层 索取了一些函数调用的"句柄",我们继续看initNative:

static void initNative(JNIEnv* env, jobject object) {  const bt_interface_t* btInf = getBluetoothInterface();  if (btInf == 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;  }  sBluetoothA2dpInterface =      (btav_sink_interface_t*)btInf->get_profile_interface(          BT_PROFILE_ADVANCED_AUDIO_SINK_ID);  if (sBluetoothA2dpInterface == NULL) {    ALOGE("Failed to get Bluetooth A2DP Sink Interface");    return;  }  bt_status_t status = sBluetoothA2dpInterface->init(&sBluetoothA2dpCallbacks);  if (status != BT_STATUS_SUCCESS) {    ALOGE("Failed to initialize Bluetooth A2DP Sink, status: %d", status);    sBluetoothA2dpInterface = NULL;    return;  }  mCallbacksObj = env->NewGlobalRef(object);}

 

上面的逻辑 就是先获取蓝牙的接口,再获取sink 的接口,然后对sink 接口进行初始化.我们主要看初始化的过程:

实现是在btif_av.cc中:

 

static const btav_sink_interface_t bt_av_sink_interface = {    sizeof(btav_sink_interface_t),    init_sink,    sink_connect_src,    disconnect,    cleanup_sink,    update_audio_focus_state,    update_audio_track_gain,}

 

这里的init 对应的接口就是init_sink,我们继续看:

/******************************************************************************* * * Function         init_sink * * Description      Initializes the AV interface for sink mode * * Returns          bt_status_t * ******************************************************************************/static bt_status_t init_sink(btav_sink_callbacks_t* callbacks) {  BTIF_TRACE_EVENT("%s()", __func__);  bt_status_t status = btif_av_init(BTA_A2DP_SINK_SERVICE_ID);  if (status == BT_STATUS_SUCCESS) bt_av_sink_callbacks = callbacks;  return status;}

 

这里的核心是btif_av_init,这里和之前src的初始化很相似,由于Android版本的演化,这里的btif_av_init 接口已经有了参数,:

/******************************************************************************* * * Function         btif_av_init * * Description      Initializes btif AV if not already done * * Returns          bt_status_t * ******************************************************************************/bt_status_t btif_av_init(int service_id) {  if (btif_av_cb.sm_handle == NULL) {    alarm_free(av_open_on_rc_timer);    av_open_on_rc_timer = alarm_new("btif_av.av_open_on_rc_timer");    switch (service_id) {      case BTA_A2DP_SOURCE_SERVICE_ID:        if (!btif_a2dp_source_startup())          return BT_STATUS_FAIL;  // Already running        break;      case BTA_A2DP_SINK_SERVICE_ID:        if (!btif_a2dp_sink_startup())          return BT_STATUS_FAIL;  // Already running        break;    }    /* 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);//初始化 av 状态机    btif_enable_service(service_id);//enable 某个service  }  return BT_STATUS_SUCCESS;}

 

从上面的代码结构可以看出,此接口是sink 和src 共享的.

上面的代码的执行任务分为3个部分:

  1. btif—a2dp-sink的线程启动btif_sm_init
  2. btif_sm_init
  3. btif_enable_service(sink)

我们发现根据传入的参数不同,如果是src,那么执行btif_a2dp_source_startup,如果是sink 执行:btif_a2dp_sink_startup,看了下两者的实现也是大致相同,都是先设置相应的状态,然后新建线程,然后绑定线程队列,然后调用thread_post 去执行 剩下的流程:

bool btif_a2dp_sink_startup(void) {  if (btif_a2dp_sink_state != BTIF_A2DP_SINK_STATE_OFF) {    APPL_TRACE_ERROR("%s: A2DP Sink media task already running", __func__);//先判断状态机的状态    return false;  }  memset(&btif_a2dp_sink_cb, 0, sizeof(btif_a2dp_sink_cb));  btif_a2dp_sink_state = BTIF_A2DP_SINK_STATE_STARTING_UP;//设置状态机  APPL_TRACE_EVENT("## A2DP SINK START MEDIA THREAD ##");  /* Start A2DP Sink media task */  btif_a2dp_sink_cb.worker_thread = thread_new("btif_a2dp_sink_worker_thread");...  btif_a2dp_sink_cb.rx_focus_state = BTIF_A2DP_SINK_FOCUS_NOT_GRANTED;  btif_a2dp_sink_cb.audio_track = NULL;  btif_a2dp_sink_cb.rx_audio_queue = fixed_queue_new(SIZE_MAX);//新建audio 队列  btif_a2dp_sink_cb.cmd_msg_queue = fixed_queue_new(SIZE_MAX);//新建cmd msg队列  fixed_queue_register_dequeue(      btif_a2dp_sink_cb.cmd_msg_queue,      thread_get_reactor(btif_a2dp_sink_cb.worker_thread),      btif_a2dp_sink_command_ready, NULL);绑定命令队列以及命令处理函数  APPL_TRACE_EVENT("## A2DP SINK MEDIA THREAD STARTED ##");  /* Schedule the rest of the startup operations */  thread_post(btif_a2dp_sink_cb.worker_thread, btif_a2dp_sink_startup_delayed,              NULL);//接下来的流程放置到btif_a2dp_sink_worker_thread的work_queue里面去  return true;}

 

我们看看 btif_a2dp_sink_startup_delayed  的实现:

static void btif_a2dp_sink_startup_delayed(UNUSED_ATTR void* context) {  raise_priority_a2dp(TASK_HIGH_MEDIA);  btif_a2dp_sink_state = BTIF_A2DP_SINK_STATE_RUNNING;//更新sink的状态}

 

下面我们看看btif_sm_init的实现:

这里是新建了一个状态机,为后续的状态转换作准备:该函数将会传入以下的参数,我们发现是一个个的处理handler

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};

 

 

/***************************************************************************** * * Function     btif_sm_init * * Description  Initializes the state machine with the state handlers *              The caller should ensure that the table and the corresponding *              states match. The location that 'p_handlers' points to shall *              be available until the btif_sm_shutdown API is invoked. * * Returns      Returns a pointer to the initialized state machine handle. * *****************************************************************************/btif_sm_handle_t btif_sm_init(const btif_sm_handler_t* p_handlers,                              btif_sm_state_t initial_state) {  btif_sm_cb_t* p_cb = (btif_sm_cb_t*)osi_malloc(sizeof(btif_sm_cb_t));  p_cb->state = initial_state;//设置初始状态  p_cb->p_handlers = (btif_sm_handler_t*)p_handlers;//将这个handler赋值到pcb里面  /* Send BTIF_SM_ENTER_EVT to the initial state */  p_cb->p_handlers[initial_state](BTIF_SM_ENTER_EVT, NULL);  return (btif_sm_handle_t)p_cb;}

 

最后会执行 进如idle 的状态机的流程:这里不作具体分析了

static bool btif_av_state_idle_handler(btif_sm_event_t event, void* p_data) {  BTIF_TRACE_DEBUG("%s event:%s flags %x", __func__,                   dump_av_sm_event_name((btif_av_sm_event_t)event),                   btif_av_cb.flags);  switch (event) {    case BTIF_SM_ENTER_EVT:      /* clear the peer_bda */      memset(&btif_av_cb.peer_bda, 0, sizeof(bt_bdaddr_t));      btif_av_cb.flags = 0;      btif_av_cb.edr = 0;      bta_av_co_init(btif_av_cb.codec_priorities);      btif_a2dp_on_idle();      break;

 

 下面我们在看看btif_enable_service 的流程:

/******************************************************************************* * * Function         btif_enable_service * * Description      Enables the service 'service_ID' to the service_mask. *                  Upon BT enable, BTIF core shall invoke the BTA APIs to *                  enable the profiles * * Returns          bt_status_t * ******************************************************************************/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);//设置标志位  BTIF_TRACE_DEBUG("%s: current services:0x%x", __func__,                   btif_enabled_services);  if (btif_is_enabled()) {    btif_transfer_context(btif_dm_execute_service_request,                          BTIF_DM_ENABLE_SERVICE, (char*)p_id,                          sizeof(tBTA_SERVICE_ID), NULL);//开启该profile  }  return BT_STATUS_SUCCESS;}

 

我们需要开始的profile 隐藏在p_id 参数中,那我们也可以看出,这里其他的profile 也应该是走的这个流程.

void btif_dm_execute_service_request(uint16_t event, char* p_param) {  bool b_enable = false;  bt_status_t status;  if (event == BTIF_DM_ENABLE_SERVICE) {    b_enable = true;  }  status =      btif_in_execute_service_request(*((tBTA_SERVICE_ID*)p_param), b_enable);  if (status == BT_STATUS_SUCCESS) {    bt_property_t property;    bt_uuid_t local_uuids[BT_MAX_NUM_UUIDS];//新建内存存放uuid    /* Now send the UUID_PROPERTY_CHANGED event to the upper layer */    BTIF_STORAGE_FILL_PROPERTY(&property, BT_PROPERTY_UUIDS,                               sizeof(local_uuids), local_uuids);//    btif_storage_get_adapter_property(&property);//fill property value    HAL_CBACK(bt_hal_cbacks, adapter_properties_cb, BT_STATUS_SUCCESS, 1,              &property);//上报相关的property  }  return;}

 

我们知道当 profile启动完成之后,那么 将通过HAL_CBACK 将已经启动的property 上报到JNI 以及以上.

那么我们现在看看btif_in_execute_service_request的实现:

bt_status_t btif_in_execute_service_request(tBTA_SERVICE_ID service_id,                                            bool b_enable) {  BTIF_TRACE_DEBUG("%s service_id: %d", __func__, service_id);  /* Check the service_ID and invoke the profile's BT state changed API */  switch (service_id) {    case BTA_HFP_SERVICE_ID:    case BTA_HSP_SERVICE_ID: {      btif_hf_execute_service(b_enable);    } break;    case BTA_A2DP_SOURCE_SERVICE_ID: {      btif_av_execute_service(b_enable);    } break;    case BTA_A2DP_SINK_SERVICE_ID: {      btif_av_sink_execute_service(b_enable);    } break;...

 

/******************************************************************************* * * Function         btif_av_sink_execute_service * * Description      Initializes/Shuts down the service * * Returns          BT_STATUS_SUCCESS on success, BT_STATUS_FAIL otherwise * ******************************************************************************/bt_status_t btif_av_sink_execute_service(bool b_enable) {  if (b_enable) {    /* Added BTA_AV_FEAT_NO_SCO_SSPD - this ensures that the BTA does not     * auto-suspend av streaming on AG events(SCO or Call). The suspend shall     * be initiated by the app/audioflinger layers */    BTA_AvEnable(BTA_SEC_AUTHENTICATE,                 BTA_AV_FEAT_NO_SCO_SSPD | BTA_AV_FEAT_RCCT |                     BTA_AV_FEAT_METADATA | BTA_AV_FEAT_VENDOR |                     BTA_AV_FEAT_ADV_CTRL | BTA_AV_FEAT_RCTG |                     BTA_AV_FEAT_BROWSE,                 bte_av_callback);    BTA_AvRegister(BTA_AV_CHNL_AUDIO, BTIF_AVK_SERVICE_NAME, 0,                   bte_av_sink_media_callback, UUID_SERVCLASS_AUDIO_SINK);  } else {    BTA_AvDeregister(btif_av_cb.bta_handle);    BTA_AvDisable();  }  return BT_STATUS_SUCCESS;}

 

这里和src的初始化的流程非常的相似,也是分为两个步骤:

  1. BTA_AvEnable(BTA_SEC_AUTHENTICATE,BTA_AV_FEAT_NO_SCO_SSPD | BTA_AV_FEAT_RCCT |BTA_AV_FEAT_METADATA | BTA_AV_FEAT_VENDOR |BTA_AV_FEAT_ADV_CTRL | BTA_AV_FEAT_RCTG |

    BTA_AV_FEAT_BROWSE,bte_av_callback);

  2. BTA_AvRegister(BTA_AV_CHNL_AUDIO, BTIF_AVK_SERVICE_NAME, 0,bte_av_sink_media_callback, UUID_SERVCLASS_AUDIO_SINK);

我们先看BTA_AvEnable :

#define BTA_SEC_AUTHENTICATE   (BTM_SEC_IN_AUTHENTICATE | BTM_SEC_OUT_AUTHENTICATE) /* Authentication required. */0x12
#define BTM_SEC_IN_AUTHENTICATE 0x0002#define BTM_SEC_OUT_AUTHENTICATE 0x0010

 

BTA_AV_FEAT_NO_SCO_SSPD | BTA_AV_FEAT_RCCT | BTA_AV_FEAT_METADATA | BTA_AV_FEAT_VENDOR | BTA_AV_FEAT_ADV_CTRL | BTA_AV_FEAT_RCTG | BTA_AV_FEAT_BROWSE,//0x825B

 

 看看其回调函数:

static void bte_av_callback(tBTA_AV_EVT event, tBTA_AV* p_data) {  btif_transfer_context(btif_av_handle_event, event, (char*)p_data,                        sizeof(tBTA_AV), btif_av_event_deep_copy);//基本上是把event 传给状态机}

 

现在看看BTA_AvEnable的实现

/******************************************************************************* * * Function         BTA_AvEnable * * Description      Enable the advanced audio/video service. When the enable *                  operation is complete the callback function will be *                  called with a BTA_AV_ENABLE_EVT. This function must *                  be called before other function in the AV API are *                  called. * * Returns          void * ******************************************************************************/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;//bte_av_callback  p_buf->features = features;//0x825B  p_buf->sec_mask = sec_mask;//0x0012  bta_sys_sendmsg(p_buf);}

 

发送了BTA_AV_API_ENABLE_EVT  这个事件;

#define BTA_ID_AV 18            /* Advanced audio/video */

 

这个 event的 主ID 还是BTA_ID_AV,而并不是BTA_ID_AVK

/* register with BTA system manager */  bta_sys_register(BTA_ID_AV, &bta_av_reg);

 

我们看看

static const tBTA_SYS_REG bta_av_reg = {bta_av_hdl_event, BTA_AvDisable};

 

也就是0x18开头的event 都是由bta_av_hdl_event  来统一处理:

/******************************************************************************* * * Function         bta_av_hdl_event * * Description      Advanced audio/video main event handling function. * * * Returns          bool * ******************************************************************************/bool bta_av_hdl_event(BT_HDR* p_msg) {  if (p_msg->event > BTA_AV_LAST_EVT) {    return true; /* to free p_msg */  }  if (p_msg->event >= BTA_AV_FIRST_NSM_EVT) {    APPL_TRACE_VERBOSE("%s: AV nsm event=0x%x(%s)", __func__, p_msg->event,                       bta_av_evt_code(p_msg->event));    /* non state machine events */    (*bta_av_nsm_act[p_msg->event - BTA_AV_FIRST_NSM_EVT])(        (tBTA_AV_DATA*)p_msg);  } else if (p_msg->event >= BTA_AV_FIRST_SM_EVT &&             p_msg->event <= BTA_AV_LAST_SM_EVT) {    APPL_TRACE_VERBOSE("%s: AV sm event=0x%x(%s)", __func__, p_msg->event,                       bta_av_evt_code(p_msg->event));    /* state machine events */    bta_av_sm_execute(&bta_av_cb, p_msg->event, (tBTA_AV_DATA*)p_msg);  } else {    APPL_TRACE_VERBOSE("handle=0x%x", p_msg->layer_specific);    /* 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;}

 

从上面的代码实现,我们发现 其讲event 分为了3类,一类是不在状态机中处理的,一类是在状态机中处理,还有一类是在stream 的状态机中处理的,现在我们将这些event 分类一下:

一以下是所有的event:

enum {  /* these events are handled by the AV main state machine */  BTA_AV_API_DISABLE_EVT = BTA_SYS_EVT_START(BTA_ID_AV),  BTA_AV_API_REMOTE_CMD_EVT,  BTA_AV_API_VENDOR_CMD_EVT,  BTA_AV_API_VENDOR_RSP_EVT,  BTA_AV_API_META_RSP_EVT,  BTA_AV_API_RC_CLOSE_EVT,  BTA_AV_AVRC_OPEN_EVT,  BTA_AV_AVRC_MSG_EVT,  BTA_AV_AVRC_NONE_EVT,  /* these events are handled by the AV stream state machine */  BTA_AV_API_OPEN_EVT,  BTA_AV_API_CLOSE_EVT,  BTA_AV_AP_START_EVT, /* the following 2 events must be in the same order as                          the *API_*EVT */  BTA_AV_AP_STOP_EVT,  BTA_AV_API_RECONFIG_EVT,  BTA_AV_API_PROTECT_REQ_EVT,  BTA_AV_API_PROTECT_RSP_EVT,  BTA_AV_API_RC_OPEN_EVT,  BTA_AV_SRC_DATA_READY_EVT,  BTA_AV_CI_SETCONFIG_OK_EVT,  BTA_AV_CI_SETCONFIG_FAIL_EVT,  BTA_AV_SDP_DISC_OK_EVT,  BTA_AV_SDP_DISC_FAIL_EVT,  BTA_AV_STR_DISC_OK_EVT,  BTA_AV_STR_DISC_FAIL_EVT,  BTA_AV_STR_GETCAP_OK_EVT,  BTA_AV_STR_GETCAP_FAIL_EVT,  BTA_AV_STR_OPEN_OK_EVT,  BTA_AV_STR_OPEN_FAIL_EVT,  BTA_AV_STR_START_OK_EVT,  BTA_AV_STR_START_FAIL_EVT,  BTA_AV_STR_CLOSE_EVT,  BTA_AV_STR_CONFIG_IND_EVT,  BTA_AV_STR_SECURITY_IND_EVT,  BTA_AV_STR_SECURITY_CFM_EVT,  BTA_AV_STR_WRITE_CFM_EVT,  BTA_AV_STR_SUSPEND_CFM_EVT,  BTA_AV_STR_RECONFIG_CFM_EVT,  BTA_AV_AVRC_TIMER_EVT,  BTA_AV_AVDT_CONNECT_EVT,  BTA_AV_AVDT_DISCONNECT_EVT,  BTA_AV_ROLE_CHANGE_EVT,  BTA_AV_AVDT_DELAY_RPT_EVT,  BTA_AV_ACP_CONNECT_EVT,  BTA_AV_API_OFFLOAD_START_EVT,  BTA_AV_API_OFFLOAD_START_RSP_EVT,  /* these events are handled outside of the state machine */  BTA_AV_API_ENABLE_EVT,  BTA_AV_API_REGISTER_EVT,  BTA_AV_API_DEREGISTER_EVT,  BTA_AV_API_DISCONNECT_EVT,  BTA_AV_CI_SRC_DATA_READY_EVT,  BTA_AV_SIG_CHG_EVT,  BTA_AV_SIGNALLING_TIMER_EVT,  BTA_AV_SDP_AVRC_DISC_EVT,  BTA_AV_AVRC_CLOSE_EVT,  BTA_AV_AVRC_BROWSE_OPEN_EVT,  BTA_AV_AVRC_BROWSE_CLOSE_EVT,  BTA_AV_CONN_CHG_EVT,  BTA_AV_DEREG_COMP_EVT,#if (AVDT_REPORTING == TRUE)  BTA_AV_AVDT_RPT_CONN_EVT,#endif  BTA_AV_API_START_EVT, /* the following 2 events must be in the same order as                           the *AP_*EVT */  BTA_AV_API_STOP_EVT}

 

我们发现,不在状态机中处理的event是:

/* these events are handled outside of the state machine */  BTA_AV_API_ENABLE_EVT,  BTA_AV_API_REGISTER_EVT,  BTA_AV_API_DEREGISTER_EVT,  BTA_AV_API_DISCONNECT_EVT,  BTA_AV_CI_SRC_DATA_READY_EVT,  BTA_AV_SIG_CHG_EVT,  BTA_AV_SIGNALLING_TIMER_EVT,  BTA_AV_SDP_AVRC_DISC_EVT,  BTA_AV_AVRC_CLOSE_EVT,  BTA_AV_AVRC_BROWSE_OPEN_EVT,  BTA_AV_AVRC_BROWSE_CLOSE_EVT,  BTA_AV_CONN_CHG_EVT,  BTA_AV_DEREG_COMP_EVT,#if (AVDT_REPORTING == TRUE)  BTA_AV_AVDT_RPT_CONN_EVT,#endif  BTA_AV_API_START_EVT, /* the following 2 events must be in the same order as                           the *AP_*EVT */  BTA_AV_API_STOP_EVT

 

处理他的函数是:bta_av_nsm_act:

/* action functions */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 */    bta_av_api_deregister,   /* BTA_AV_API_DEREGISTER_EVT */    bta_av_api_disconnect,   /* BTA_AV_API_DISCONNECT_EVT */    bta_av_ci_data,          /* BTA_AV_CI_SRC_DATA_READY_EVT */    bta_av_sig_chg,          /* BTA_AV_SIG_CHG_EVT */    bta_av_signalling_timer, /* BTA_AV_SIGNALLING_TIMER_EVT */    bta_av_rc_disc_done,     /* BTA_AV_SDP_AVRC_DISC_EVT */    bta_av_rc_closed,        /* BTA_AV_AVRC_CLOSE_EVT */    bta_av_rc_browse_opened, /* BTA_AV_AVRC_BROWSE_OPEN_EVT */    bta_av_rc_browse_closed, /* BTA_AV_AVRC_BROWSE_CLOSE_EVT */    bta_av_conn_chg,         /* BTA_AV_CONN_CHG_EVT */    bta_av_dereg_comp,       /* BTA_AV_DEREG_COMP_EVT */#if (AVDT_REPORTING == TRUE)    bta_av_rpc_conn, /* BTA_AV_AVDT_RPT_CONN_EVT */#endif    bta_av_api_to_ssm, /* BTA_AV_API_START_EVT */    bta_av_api_to_ssm, /* BTA_AV_API_STOP_EVT */}

 

还有一类事件 是在AV的main 的状态机中处理的:

/* these events are handled by the AV main state machine */  BTA_AV_API_DISABLE_EVT = BTA_SYS_EVT_START(BTA_ID_AV),  BTA_AV_API_REMOTE_CMD_EVT,  BTA_AV_API_VENDOR_CMD_EVT,  BTA_AV_API_VENDOR_RSP_EVT,  BTA_AV_API_META_RSP_EVT,  BTA_AV_API_RC_CLOSE_EVT,  BTA_AV_AVRC_OPEN_EVT,  BTA_AV_AVRC_MSG_EVT,  BTA_AV_AVRC_NONE_EVT,

 

处理的函数组是:bta_av_sm_execute --->bta_av_action:

/* action functions */const tBTA_AV_ACTION bta_av_action[] = {    bta_av_disable,    bta_av_rc_opened,    bta_av_rc_remote_cmd,    bta_av_rc_vendor_cmd,    bta_av_rc_vendor_rsp,    bta_av_rc_free_rsp,    bta_av_rc_free_browse_msg,    bta_av_rc_meta_rsp,    bta_av_rc_msg,    bta_av_rc_close,};

 

最后一类是  建立 stream之后的event:

/* these events are handled by the AV stream state machine */  BTA_AV_API_OPEN_EVT,  BTA_AV_API_CLOSE_EVT,  BTA_AV_AP_START_EVT, /* the following 2 events must be in the same order as                          the *API_*EVT */  BTA_AV_AP_STOP_EVT,  BTA_AV_API_RECONFIG_EVT,  BTA_AV_API_PROTECT_REQ_EVT,  BTA_AV_API_PROTECT_RSP_EVT,  BTA_AV_API_RC_OPEN_EVT,  BTA_AV_SRC_DATA_READY_EVT,  BTA_AV_CI_SETCONFIG_OK_EVT,  BTA_AV_CI_SETCONFIG_FAIL_EVT,  BTA_AV_SDP_DISC_OK_EVT,  BTA_AV_SDP_DISC_FAIL_EVT,  BTA_AV_STR_DISC_OK_EVT,  BTA_AV_STR_DISC_FAIL_EVT,  BTA_AV_STR_GETCAP_OK_EVT,  BTA_AV_STR_GETCAP_FAIL_EVT,  BTA_AV_STR_OPEN_OK_EVT,  BTA_AV_STR_OPEN_FAIL_EVT,  BTA_AV_STR_START_OK_EVT,  BTA_AV_STR_START_FAIL_EVT,  BTA_AV_STR_CLOSE_EVT,  BTA_AV_STR_CONFIG_IND_EVT,  BTA_AV_STR_SECURITY_IND_EVT,  BTA_AV_STR_SECURITY_CFM_EVT,  BTA_AV_STR_WRITE_CFM_EVT,  BTA_AV_STR_SUSPEND_CFM_EVT,  BTA_AV_STR_RECONFIG_CFM_EVT,  BTA_AV_AVRC_TIMER_EVT,  BTA_AV_AVDT_CONNECT_EVT,  BTA_AV_AVDT_DISCONNECT_EVT,  BTA_AV_ROLE_CHANGE_EVT,  BTA_AV_AVDT_DELAY_RPT_EVT,  BTA_AV_ACP_CONNECT_EVT,  BTA_AV_API_OFFLOAD_START_EVT,  BTA_AV_API_OFFLOAD_START_RSP_EVT,

 

处理的函数是bta_av_ssm_execute ,处理的action 是p_scb->p_act_tbl

我们继续看BTA_AV_API_ENABLE_EVT 的处理,根据上面的分类,处理的函数是bta_av_api_enable:

/******************************************************************************* * * Function         bta_av_api_enable * * Description      Handle an API enable event. * * * Returns          void * ******************************************************************************/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");//这里只是新建了一个timer ,还没有启动  bta_av_cb.accept_signalling_timer =      alarm_new("bta_av.accept_signalling_timer");  /* store parameters */  bta_av_cb.p_cback = p_data->api_enable.p_cback;//bte_av_callback  bta_av_cb.features = p_data->api_enable.features;//0x825B  bta_av_cb.sec_mask = p_data->api_enable.sec_mask;//0x0012  tBTA_AV_ENABLE enable;  enable.features = bta_av_cb.features;//0x825B  /* Register for SCO change event */  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);//callback:bte_av_callback}

 这里需要注意的是 上面只是新建了定时器,还么有 启动定时器,我们看看回调函数的实现:

static void bte_av_callback(tBTA_AV_EVT event, tBTA_AV* p_data) {  btif_transfer_context(btif_av_handle_event, event, (char*)p_data,                        sizeof(tBTA_AV), btif_av_event_deep_copy);}
static void btif_av_handle_event(uint16_t event, char* p_param) {  BTIF_TRACE_EVENT("%s event:%s", __func__,                   dump_av_sm_event_name((btif_av_sm_event_t)event));  switch (event) {    case BTIF_AV_CLEANUP_REQ_EVT:      btif_a2dp_source_shutdown();      btif_a2dp_sink_shutdown();      break;    case BTA_AV_REGISTER_EVT:      if (btif_av_cb.sm_handle == NULL) {        btif_av_cb.bta_handle = ((tBTA_AV*)p_param)->registr.hndl;        BTIF_TRACE_DEBUG("%s: BTA AV Handle updated", __func__);      }    /* FALLTHROUGH */    default:      btif_sm_dispatch(btif_av_cb.sm_handle, event, (void*)p_param);      btif_av_event_free_data(event, p_param);  }}

 

上面走到到了 btif_sm_dispatch 里面了:

/***************************************************************************** * * Function     btif_sm_dispatch * * Description  Dispatches the 'event' along with 'data' to the current state *              handler * * Returns      BT_STATUS_SUCCESS on success *              BT_STATUS_UNHANDLED if event was not processed *              BT_STATUS_FAIL otherwise * *****************************************************************************/bt_status_t btif_sm_dispatch(btif_sm_handle_t handle, btif_sm_event_t event,                             void* data) {  bt_status_t status = BT_STATUS_SUCCESS;  btif_sm_cb_t* p_cb = (btif_sm_cb_t*)handle;  if (p_cb == NULL) {    BTIF_TRACE_ERROR("%s : Invalid handle", __func__);    return BT_STATUS_FAIL;  }  if (p_cb->p_handlers[p_cb->state](event, data) == false)    return BT_STATUS_UNHANDLED;  return status;}

 

这里的state  还是idle 状态, 这里发现 对于这个BTA_AV_ENABLE_EVT 并么有处理,这里就不分析。(和src的分析的流程基本一致)

下面继续看看BTA_AvRegister(BTA_AV_CHNL_AUDIO, BTIF_AVK_SERVICE_NAME, 0,bte_av_sink_media_callback, UUID_SERVCLASS_AUDIO_SINK);的实现:

这里和之前的src的分析不同点在于(Android版本不同)这里的参数个数多了一个,这里会传入了一个参数,标志是src还是sink 进行的注册。

/******************************************************************************* * * Function         BTA_AvRegister * * Description      Register the audio or video service to stack. When the *                  operation is complete the callback function will be *                  called with a BTA_AV_REGISTER_EVT. This function must *                  be called before AVDT stream is open. * * * Returns          void * ******************************************************************************/void BTA_AvRegister(tBTA_AV_CHNL chnl, const char* p_service_name,                    uint8_t app_id, tBTA_AV_SINK_DATA_CBACK* p_sink_data_cback,                    uint16_t 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;//BTA_AV_CHNL_AUDIO = 0x40  p_buf->hdr.event = BTA_AV_API_REGISTER_EVT;  if (p_service_name)    strlcpy(p_buf->p_service_name, p_service_name, BTA_SERVICE_NAME_LEN);  else    p_buf->p_service_name[0] = 0;  p_buf->app_id = app_id;//0  p_buf->p_app_sink_data_cback = p_sink_data_cback;//bte_av_sink_media_callback  p_buf->service_uuid = service_uuid;//UUID_SERVCLASS_AUDIO_SINK = 0x110B  bta_sys_sendmsg(p_buf);}

 

我们继续看这个event 的处理,我们发现bta_av_api_register 这个函数也是 sink 和src 共用的,这也是和Android6.0的实现不同的地方。

其实可以仿照AndroidO的代码去修改AndroidM的代码,以此将sink 和src 分开。

/******************************************************************************* * * Function         bta_av_api_register * * Description      allocate stream control block, *                  register the service to stack *                  create SDP record * * Returns          void * ******************************************************************************/static void bta_av_api_register(tBTA_AV_DATA* p_data) {  tBTA_AV_REGISTER registr;  tBTA_AV_SCB* p_scb; /* stream control block */  tAVDT_REG reg;  tAVDT_CS cs;  char* p_service_name;  tBTA_UTL_COD cod;  memset(&cs, 0, sizeof(tAVDT_CS));//初始化cs,该项最终拷贝到p_scb->cfg,并且AVDT_CreateStream 会使用到  registr.status = BTA_AV_FAIL_RESOURCES;//register 记录注册的信息,回调的时候会上报  registr.app_id = p_data->api_reg.app_id;//0  registr.chnl = (tBTA_AV_CHNL)p_data->hdr.layer_specific;//layer_specific = 0x40  uint16_t profile_initialized = p_data->api_reg.service_uuid;//sink  if (profile_initialized == UUID_SERVCLASS_AUDIO_SINK) {    p_bta_av_cfg = (tBTA_AV_CFG*)&bta_avk_cfg;  } else if (profile_initialized == UUID_SERVCLASS_AUDIO_SOURCE) {    p_bta_av_cfg = (tBTA_AV_CFG*)&bta_av_cfg;  }  do {    p_scb = bta_av_alloc_scb(registr.chnl);//分配了一个 stream control block  :bta_av_cb.p_scb[xx] = p_scb    registr.hndl = p_scb->hndl;//0x41 or 0x42  --- hndl = (tBTA_AV_HNDL)((xx + 1) | chnl);    p_scb->app_id = registr.app_id;    /* initialize the stream control block */    registr.status = BTA_AV_SUCCESS;    if ((bta_av_cb.reg_audio + bta_av_cb.reg_video) == 0) {      /* the first channel registered. register to AVDTP */      reg.ctrl_mtu = p_bta_av_cfg->sig_mtu;      reg.ret_tout = BTA_AV_RET_TOUT;      reg.sig_tout = BTA_AV_SIG_TOUT;      reg.idle_tout = BTA_AV_IDLE_TOUT;      reg.sec_mask = bta_av_cb.sec_mask;      bta_ar_reg_avdt(®, bta_av_conn_cback, BTA_ID_AV);//注册到AVDT      bta_sys_role_chg_register(&bta_av_sys_rs_cback);      /* create remote control TG service if required */      if (bta_av_cb.features & (BTA_AV_FEAT_RCTG)) {/* register with no authorization; let AVDTP use authorization instead */        bta_ar_reg_avct(p_bta_av_cfg->avrc_mtu, p_bta_av_cfg->avrc_br_mtu,                        (uint8_t)(bta_av_cb.sec_mask & (~BTA_SEC_AUTHORIZE)),                        BTA_ID_AV);        /* For the Audio Sink role we support additional TG 1.3 to support         * absolute volume.         */        uint16_t profile_version = AVRC_REV_1_0;        if (profile_initialized == UUID_SERVCLASS_AUDIO_SOURCE) {...        } else if (profile_initialized == UUID_SERVCLASS_AUDIO_SINK) {          // Initialize AVRCP1.4 to provide Absolute Volume control.          profile_version = AVRC_REV_1_4;        }        bta_ar_reg_avrc(            UUID_SERVCLASS_AV_REM_CTRL_TARGET, "AV Remote Control Target", NULL,            p_bta_av_cfg->avrc_tg_cat, BTA_ID_AV,            (bta_av_cb.features & BTA_AV_FEAT_BROWSE), profile_version);#endif      }      /* Set the Capturing service class bit */      if (profile_initialized == UUID_SERVCLASS_AUDIO_SOURCE)        cod.service = BTM_COD_SERVICE_CAPTURING;      else if (profile_initialized == UUID_SERVCLASS_AUDIO_SINK)        cod.service = BTM_COD_SERVICE_RENDERING;      utl_set_device_class(&cod, BTA_UTL_SET_COD_SERVICE_CLASS);    } /* if 1st channel */    /* get stream configuration and create stream */    cs.cfg.num_codec = 1;    cs.nsc_mask =        AVDT_NSC_RECONFIG |        ((bta_av_cb.features & BTA_AV_FEAT_PROTECT) ? 0 : AVDT_NSC_SECURITY);    APPL_TRACE_DEBUG("nsc_mask: 0x%x", cs.nsc_mask);    if (p_data->api_reg.p_service_name[0] == 0) {      p_service_name = NULL;    } else {      p_service_name = p_data->api_reg.p_service_name;//用于后面创建SDP record    }    p_scb->suspend_sup = true;    p_scb->recfg_sup = true;    p_scb->skip_sdp = false;    cs.p_ctrl_cback = bta_av_dt_cback[p_scb->hdi];    if (registr.chnl == BTA_AV_CHNL_AUDIO) {
//填充p_scb /* set up the audio stream control block */ p_scb->p_act_tbl = (const tBTA_AV_ACT*)bta_av_a2dp_action; p_scb->p_cos = &bta_av_a2dp_cos; p_scb->media_type = AVDT_MEDIA_TYPE_AUDIO; cs.cfg.psc_mask = AVDT_PSC_TRANS; cs.media_type = AVDT_MEDIA_TYPE_AUDIO; cs.mtu = p_bta_av_cfg->audio_mtu; cs.flush_to = L2CAP_DEFAULT_FLUSH_TO; btav_a2dp_codec_index_t codec_index_min = BTAV_A2DP_CODEC_INDEX_SOURCE_MIN; btav_a2dp_codec_index_t codec_index_max = BTAV_A2DP_CODEC_INDEX_SOURCE_MAX; if (profile_initialized == UUID_SERVCLASS_AUDIO_SOURCE) {... } else if (profile_initialized == UUID_SERVCLASS_AUDIO_SINK) { cs.tsep = AVDT_TSEP_SNK; cs.p_sink_data_cback = bta_av_sink_data_cback; codec_index_min = BTAV_A2DP_CODEC_INDEX_SINK_MIN; codec_index_max = BTAV_A2DP_CODEC_INDEX_SINK_MAX; } /* Initialize handles to zero */ for (int xx = 0; xx < BTAV_A2DP_CODEC_INDEX_MAX; xx++) { p_scb->seps[xx].av_handle = 0; } /* keep the configuration in the stream control block */ memcpy(&p_scb->cfg, &cs.cfg, sizeof(tAVDT_CFG)); for (int i = codec_index_min; i < codec_index_max; i++) { btav_a2dp_codec_index_t codec_index = static_cast
(i); if (!(*bta_av_a2dp_cos.init)(codec_index, &cs.cfg)) { continue; } if (AVDT_CreateStream(&p_scb->seps[codec_index].av_handle, &cs) != AVDT_SUCCESS) { continue; } /* Save a copy of the codec */ memcpy(p_scb->seps[codec_index].codec_info, cs.cfg.codec_info, AVDT_CODEC_SIZE); p_scb->seps[codec_index].tsep = cs.tsep; if (cs.tsep == AVDT_TSEP_SNK) { p_scb->seps[codec_index].p_app_sink_data_cback = p_data->api_reg.p_app_sink_data_cback; } else { /* In case of A2DP SOURCE we don't need a callback to * handle media packets. */ p_scb->seps[codec_index].p_app_sink_data_cback = NULL; } } if (!bta_av_cb.reg_audio) { bta_av_cb.sdp_a2dp_handle = 0; bta_av_cb.sdp_a2dp_snk_handle = 0; if (profile_initialized == UUID_SERVCLASS_AUDIO_SOURCE) {... } else if (profile_initialized == UUID_SERVCLASS_AUDIO_SINK) {#if (BTA_AV_SINK_INCLUDED == TRUE) bta_av_cb.sdp_a2dp_snk_handle = SDP_CreateRecord(); A2DP_AddRecord(UUID_SERVCLASS_AUDIO_SINK, p_service_name, NULL, A2DP_SUPF_PLAYER, bta_av_cb.sdp_a2dp_snk_handle); bta_sys_add_uuid(UUID_SERVCLASS_AUDIO_SINK);#endif } /* 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); /* if the AV and AVK are both supported, it cannot support the CT role */ if (bta_av_cb.features & (BTA_AV_FEAT_RCCT)) { /* create an SDP record as AVRC CT. We create 1.3 for SOURCE * because we rely on feature bits being scanned by external * devices more than the profile version itself. * * We create 1.4 for SINK since we support browsing. */ if (profile_initialized == UUID_SERVCLASS_AUDIO_SOURCE) {... } else if (profile_initialized == UUID_SERVCLASS_AUDIO_SINK) { bta_ar_reg_avrc(UUID_SERVCLASS_AV_REMOTE_CONTROL, NULL, NULL, p_bta_av_cfg->avrc_ct_cat, BTA_ID_AV, (bta_av_cb.features & BTA_AV_FEAT_BROWSE), AVRC_REV_1_6); } } } bta_av_cb.reg_audio |= BTA_AV_HNDL_TO_MSK(p_scb->hdi); APPL_TRACE_DEBUG("reg_audio: 0x%x", bta_av_cb.reg_audio); } } while (0); /* call callback with register event */ (*bta_av_cb.p_cback)(BTA_AV_REGISTER_EVT, (tBTA_AV*)&registr);}

 

上面注册的内容和 a2dp 初始化的流程基本相同,不作具体分析。

关于a2dp sink的初始化的流程,就分析到这里了。 

转载于:https://www.cnblogs.com/libs-liu/p/9541160.html

你可能感兴趣的文章
SQL经典面试题集锦
查看>>
View学习(一)-DecorView,measureSpec与LayoutParams
查看>>
色彩力量!21款你应该知道的优秀品牌设计
查看>>
SDUT 3503 有两个正整数,求N!的K进制的位数
查看>>
【.Net】C# 根据绝对路径获取 带后缀文件名、后缀名、文件名、不带文件名的文件路径...
查看>>
Redis常用命令速查 <第二篇>
查看>>
CSS规范
查看>>
使用FastDateFormat来代替JDK自带的DateFormat
查看>>
Python爬虫从入门到放弃(十六)之 Scrapy框架中Item Pipeline用法
查看>>
Android源代码解析之(三)--&gt;异步任务AsyncTask
查看>>
(zhuan) 自然语言处理中的Attention Model:是什么及为什么
查看>>
C#中使用RabbitMQ收发队列消息
查看>>
Hadoop1.2.1 全然分布式集群搭建实操笔记
查看>>
第三百二十七节,web爬虫讲解2—urllib库爬虫—基础使用—超时设置—自动模拟http请求...
查看>>
MVC总结--MVC简单介绍以及和WebForm差别
查看>>
tiny4412 裸机程序 五、控制icache【转】
查看>>
VB.NET多线程入门
查看>>
国外物联网平台初探(二) ——微软Azure IoT
查看>>
findlibrary returned null产生的联想,Android ndk开发打包时我们应该怎样注意平台的兼容(x86,arm,arm-v7a)...
查看>>
Android事件分发机制源代码分析
查看>>