A2dp sink 初始化流程源碼分析

A2dp sink的初始化流程和A2dp 的初始化流程,基本同樣,這裏作簡單分析.這裏分析的android的版本是Android O.java

咱們先從service的啓動提及吧.react

下面 是啓動的時候的log:android

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函數的實現:api

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

 咱們看看這個類的構造函數實現:app

    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()ide

咱們先看前者:函數

 private native static void classInitNative();

 

這是本地實現的函數,在com_android_bluetooth_a2dp_sink.cpp中:post

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:ui

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(&reg, 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<btav_a2dp_codec_index_t>(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的初始化的流程,就分析到這裏了。 

相關文章
相關標籤/搜索