Loading system/btif/Android.bp +1 −0 Original line number Original line Diff line number Diff line Loading @@ -133,6 +133,7 @@ cc_test { "libbtcore", "libbtcore", "libbt-common", "libbt-common", "libbt-stack", "libbt-stack", "libbt-sbc-decoder", "libbt-sbc-encoder", "libbt-sbc-encoder", "libbt-utils", "libbt-utils", "libFraunhoferAAC", "libFraunhoferAAC", Loading system/btif/src/btif_a2dp_sink.cc +116 −97 Original line number Original line Diff line number Diff line Loading @@ -20,8 +20,12 @@ #define LOG_TAG "bt_btif_a2dp_sink" #define LOG_TAG "bt_btif_a2dp_sink" #include <atomic> #include <atomic> #include <cstdio> #include <cstring> #include <cstring> #include <mutex> #include <mutex> #include <string> #include <base/bind.h> #include "bt_common.h" #include "bt_common.h" #include "btif_a2dp.h" #include "btif_a2dp.h" Loading @@ -30,11 +34,12 @@ #include "btif_av_co.h" #include "btif_av_co.h" #include "btif_avrcp_audio_track.h" #include "btif_avrcp_audio_track.h" #include "btif_util.h" #include "btif_util.h" #include "common/message_loop_thread.h" #include "osi/include/fixed_queue.h" #include "osi/include/fixed_queue.h" #include "osi/include/log.h" #include "osi/include/log.h" #include "osi/include/osi.h" #include "osi/include/osi.h" #include "osi/include/thread.h" using bluetooth::common::MessageLoopThread; using LockGuard = std::lock_guard<std::mutex>; using LockGuard = std::lock_guard<std::mutex>; /** /** Loading Loading @@ -73,9 +78,37 @@ typedef struct { } tBTIF_MEDIA_SINK_FOCUS_UPDATE; } tBTIF_MEDIA_SINK_FOCUS_UPDATE; /* BTIF A2DP Sink control block */ /* BTIF A2DP Sink control block */ typedef struct { class BtifA2dpSinkControlBlock { thread_t* worker_thread; public: fixed_queue_t* cmd_msg_queue; explicit BtifA2dpSinkControlBlock(const std::string& thread_name) : worker_thread(thread_name), rx_audio_queue(nullptr), rx_flush(false), decode_alarm(nullptr), sample_rate(0), channel_count(0), rx_focus_state(BTIF_A2DP_SINK_FOCUS_NOT_GRANTED), audio_track(nullptr), decoder_interface(nullptr) {} void Reset() { if (audio_track != nullptr) { BtifAvrcpAudioTrackStop(audio_track); BtifAvrcpAudioTrackDelete(audio_track); } audio_track = nullptr; fixed_queue_free(rx_audio_queue, nullptr); rx_audio_queue = nullptr; alarm_free(decode_alarm); decode_alarm = nullptr; rx_flush = false; rx_focus_state = BTIF_A2DP_SINK_FOCUS_NOT_GRANTED; sample_rate = 0; channel_count = 0; decoder_interface = nullptr; } MessageLoopThread worker_thread; fixed_queue_t* rx_audio_queue; fixed_queue_t* rx_audio_queue; bool rx_flush; /* discards any incoming data when true */ bool rx_flush; /* discards any incoming data when true */ alarm_t* decode_alarm; alarm_t* decode_alarm; Loading @@ -84,36 +117,37 @@ typedef struct { btif_a2dp_sink_focus_state_t rx_focus_state; /* audio focus state */ btif_a2dp_sink_focus_state_t rx_focus_state; /* audio focus state */ void* audio_track; void* audio_track; const tA2DP_DECODER_INTERFACE* decoder_interface; const tA2DP_DECODER_INTERFACE* decoder_interface; } tBTIF_A2DP_SINK_CB; }; // Mutex for below data structures. // Mutex for below data structures. static std::mutex g_mutex; static std::mutex g_mutex; static tBTIF_A2DP_SINK_CB btif_a2dp_sink_cb; static BtifA2dpSinkControlBlock btif_a2dp_sink_cb( "btif_a2dp_sink_worker_thread"); static std::atomic<int> btif_a2dp_sink_state{BTIF_A2DP_SINK_STATE_OFF}; static std::atomic<int> btif_a2dp_sink_state{BTIF_A2DP_SINK_STATE_OFF}; static void btif_a2dp_sink_init_delayed(void* context); static void btif_a2dp_sink_init_delayed(); static void btif_a2dp_sink_startup_delayed(void* context); static void btif_a2dp_sink_startup_delayed(); static void btif_a2dp_sink_start_session_delayed(void* context); static void btif_a2dp_sink_start_session_delayed(); static void btif_a2dp_sink_end_session_delayed(void* context); static void btif_a2dp_sink_end_session_delayed(); static void btif_a2dp_sink_shutdown_delayed(void* context); static void btif_a2dp_sink_shutdown_delayed(); static void btif_a2dp_sink_cleanup_delayed(void* context); static void btif_a2dp_sink_cleanup_delayed(); static void btif_a2dp_sink_command_ready(fixed_queue_t* queue, void* context); static void btif_a2dp_sink_command_ready(BT_HDR* p_msg); static void btif_a2dp_sink_audio_handle_stop_decoding(void); static void btif_a2dp_sink_audio_handle_stop_decoding(); static void btif_decode_alarm_cb(void* context); static void btif_decode_alarm_cb(void* context); static void btif_a2dp_sink_audio_handle_start_decoding(void); static void btif_a2dp_sink_audio_handle_start_decoding(); static void btif_a2dp_sink_avk_handle_timer(UNUSED_ATTR void* context); static void btif_a2dp_sink_avk_handle_timer(); static void btif_a2dp_sink_audio_rx_flush_req(void); static void btif_a2dp_sink_audio_rx_flush_req(); /* Handle incoming media packets A2DP SINK streaming */ /* Handle incoming media packets A2DP SINK streaming */ static void btif_a2dp_sink_handle_inc_media(BT_HDR* p_msg); static void btif_a2dp_sink_handle_inc_media(BT_HDR* p_msg); static void btif_a2dp_sink_decoder_update_event( static void btif_a2dp_sink_decoder_update_event( tBTIF_MEDIA_SINK_DECODER_UPDATE* p_buf); tBTIF_MEDIA_SINK_DECODER_UPDATE* p_buf); static void btif_a2dp_sink_clear_track_event(void); static void btif_a2dp_sink_clear_track_event(); static void btif_a2dp_sink_set_focus_state_event( static void btif_a2dp_sink_set_focus_state_event( btif_a2dp_sink_focus_state_t state); btif_a2dp_sink_focus_state_t state); static void btif_a2dp_sink_audio_rx_flush_event(void); static void btif_a2dp_sink_audio_rx_flush_event(); static void btif_a2dp_sink_clear_track_event_req(void); static void btif_a2dp_sink_clear_track_event_req(); UNUSED_ATTR static const char* dump_media_event(uint16_t event) { UNUSED_ATTR static const char* dump_media_event(uint16_t event) { switch (event) { switch (event) { Loading @@ -127,7 +161,7 @@ UNUSED_ATTR static const char* dump_media_event(uint16_t event) { return "UNKNOWN A2DP SINK EVENT"; return "UNKNOWN A2DP SINK EVENT"; } } bool btif_a2dp_sink_init(void) { bool btif_a2dp_sink_init() { LOG_INFO(LOG_TAG, "%s", __func__); LOG_INFO(LOG_TAG, "%s", __func__); LockGuard lock(g_mutex); LockGuard lock(g_mutex); Loading @@ -136,48 +170,42 @@ bool btif_a2dp_sink_init(void) { return false; return false; } } memset(&btif_a2dp_sink_cb, 0, sizeof(btif_a2dp_sink_cb)); btif_a2dp_sink_cb.Reset(); btif_a2dp_sink_state = BTIF_A2DP_SINK_STATE_STARTING_UP; btif_a2dp_sink_state = BTIF_A2DP_SINK_STATE_STARTING_UP; /* Start A2DP Sink media task */ /* Start A2DP Sink media task */ btif_a2dp_sink_cb.worker_thread = thread_new("btif_a2dp_sink_worker_thread"); btif_a2dp_sink_cb.worker_thread.StartUp(); if (btif_a2dp_sink_cb.worker_thread == NULL) { if (!btif_a2dp_sink_cb.worker_thread.IsRunning()) { LOG_ERROR(LOG_TAG, "%s: unable to start up media thread", __func__); LOG_ERROR(LOG_TAG, "%s: unable to start up media thread", __func__); btif_a2dp_sink_state = BTIF_A2DP_SINK_STATE_OFF; btif_a2dp_sink_state = BTIF_A2DP_SINK_STATE_OFF; return false; return false; } } 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); btif_a2dp_sink_cb.rx_audio_queue = fixed_queue_new(SIZE_MAX); btif_a2dp_sink_cb.cmd_msg_queue = fixed_queue_new(SIZE_MAX); 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); /* Schedule the rest of the operations */ /* Schedule the rest of the operations */ thread_post(btif_a2dp_sink_cb.worker_thread, btif_a2dp_sink_init_delayed, if (!btif_a2dp_sink_cb.worker_thread.EnableRealTimeScheduling()) { NULL); LOG(FATAL) << __func__ << ": Failed to increase A2DP decoder thread priority"; } btif_a2dp_sink_cb.worker_thread.DoInThread( FROM_HERE, base::BindOnce(btif_a2dp_sink_init_delayed)); return true; return true; } } static void btif_a2dp_sink_init_delayed(UNUSED_ATTR void* context) { static void btif_a2dp_sink_init_delayed() { LOG_INFO(LOG_TAG, "%s", __func__); LOG_INFO(LOG_TAG, "%s", __func__); raise_priority_a2dp(TASK_HIGH_MEDIA); btif_a2dp_sink_state = BTIF_A2DP_SINK_STATE_RUNNING; btif_a2dp_sink_state = BTIF_A2DP_SINK_STATE_RUNNING; } } bool btif_a2dp_sink_startup(void) { bool btif_a2dp_sink_startup() { LOG_INFO(LOG_TAG, "%s", __func__); LOG_INFO(LOG_TAG, "%s", __func__); thread_post(btif_a2dp_sink_cb.worker_thread, btif_a2dp_sink_startup_delayed, btif_a2dp_sink_cb.worker_thread.DoInThread( NULL); FROM_HERE, base::BindOnce(btif_a2dp_sink_startup_delayed)); return true; return true; } } static void btif_a2dp_sink_startup_delayed(UNUSED_ATTR void* context) { static void btif_a2dp_sink_startup_delayed() { LOG_INFO(LOG_TAG, "%s", __func__); LOG_INFO(LOG_TAG, "%s", __func__); LockGuard lock(g_mutex); LockGuard lock(g_mutex); // Nothing to do // Nothing to do Loading @@ -186,12 +214,12 @@ static void btif_a2dp_sink_startup_delayed(UNUSED_ATTR void* context) { bool btif_a2dp_sink_start_session(const RawAddress& peer_address) { bool btif_a2dp_sink_start_session(const RawAddress& peer_address) { LOG_INFO(LOG_TAG, "%s: peer_address=%s", __func__, LOG_INFO(LOG_TAG, "%s: peer_address=%s", __func__, peer_address.ToString().c_str()); peer_address.ToString().c_str()); thread_post(btif_a2dp_sink_cb.worker_thread, btif_a2dp_sink_cb.worker_thread.DoInThread( btif_a2dp_sink_start_session_delayed, NULL); FROM_HERE, base::BindOnce(btif_a2dp_sink_start_session_delayed)); return true; return true; } } static void btif_a2dp_sink_start_session_delayed(UNUSED_ATTR void* context) { static void btif_a2dp_sink_start_session_delayed() { LOG_INFO(LOG_TAG, "%s", __func__); LOG_INFO(LOG_TAG, "%s", __func__); LockGuard lock(g_mutex); LockGuard lock(g_mutex); // Nothing to do // Nothing to do Loading Loading @@ -226,35 +254,33 @@ bool btif_a2dp_sink_restart_session(const RawAddress& old_peer_address, bool btif_a2dp_sink_end_session(const RawAddress& peer_address) { bool btif_a2dp_sink_end_session(const RawAddress& peer_address) { LOG_INFO(LOG_TAG, "%s: peer_address=%s", __func__, LOG_INFO(LOG_TAG, "%s: peer_address=%s", __func__, peer_address.ToString().c_str()); peer_address.ToString().c_str()); thread_post(btif_a2dp_sink_cb.worker_thread, btif_a2dp_sink_cb.worker_thread.DoInThread( btif_a2dp_sink_end_session_delayed, NULL); FROM_HERE, base::BindOnce(btif_a2dp_sink_end_session_delayed)); return true; return true; } } static void btif_a2dp_sink_end_session_delayed(UNUSED_ATTR void* context) { static void btif_a2dp_sink_end_session_delayed() { LOG_INFO(LOG_TAG, "%s", __func__); LOG_INFO(LOG_TAG, "%s", __func__); LockGuard lock(g_mutex); LockGuard lock(g_mutex); // Nothing to do // Nothing to do } } void btif_a2dp_sink_shutdown(void) { void btif_a2dp_sink_shutdown() { LOG_INFO(LOG_TAG, "%s", __func__); LOG_INFO(LOG_TAG, "%s", __func__); thread_post(btif_a2dp_sink_cb.worker_thread, btif_a2dp_sink_shutdown_delayed, btif_a2dp_sink_cb.worker_thread.DoInThread( NULL); FROM_HERE, base::BindOnce(btif_a2dp_sink_shutdown_delayed)); } } static void btif_a2dp_sink_shutdown_delayed(UNUSED_ATTR void* context) { static void btif_a2dp_sink_shutdown_delayed() { LOG_INFO(LOG_TAG, "%s", __func__); LOG_INFO(LOG_TAG, "%s", __func__); LockGuard lock(g_mutex); LockGuard lock(g_mutex); // Nothing to do // Nothing to do } } void btif_a2dp_sink_cleanup(void) { void btif_a2dp_sink_cleanup() { LOG_INFO(LOG_TAG, "%s", __func__); LOG_INFO(LOG_TAG, "%s", __func__); alarm_t* decode_alarm; alarm_t* decode_alarm; fixed_queue_t* cmd_msg_queue; thread_t* worker_thread; // Make sure the sink is shutdown // Make sure the sink is shutdown btif_a2dp_sink_shutdown(); btif_a2dp_sink_shutdown(); Loading @@ -269,47 +295,38 @@ void btif_a2dp_sink_cleanup(void) { btif_a2dp_sink_state = BTIF_A2DP_SINK_STATE_SHUTTING_DOWN; btif_a2dp_sink_state = BTIF_A2DP_SINK_STATE_SHUTTING_DOWN; decode_alarm = btif_a2dp_sink_cb.decode_alarm; decode_alarm = btif_a2dp_sink_cb.decode_alarm; btif_a2dp_sink_cb.decode_alarm = NULL; btif_a2dp_sink_cb.decode_alarm = nullptr; cmd_msg_queue = btif_a2dp_sink_cb.cmd_msg_queue; btif_a2dp_sink_cb.cmd_msg_queue = NULL; worker_thread = btif_a2dp_sink_cb.worker_thread; btif_a2dp_sink_cb.worker_thread = NULL; } } // Stop the timer // Stop the timer alarm_free(decode_alarm); alarm_free(decode_alarm); // Exit the thread // Exit the thread fixed_queue_free(cmd_msg_queue, NULL); btif_a2dp_sink_cb.worker_thread.DoInThread( thread_post(worker_thread, btif_a2dp_sink_cleanup_delayed, NULL); FROM_HERE, base::BindOnce(btif_a2dp_sink_cleanup_delayed)); thread_free(worker_thread); btif_a2dp_sink_cb.worker_thread.ShutDown(); } } static void btif_a2dp_sink_cleanup_delayed(UNUSED_ATTR void* context) { static void btif_a2dp_sink_cleanup_delayed() { LOG_INFO(LOG_TAG, "%s", __func__); LOG_INFO(LOG_TAG, "%s", __func__); LockGuard lock(g_mutex); LockGuard lock(g_mutex); fixed_queue_free(btif_a2dp_sink_cb.rx_audio_queue, NULL); fixed_queue_free(btif_a2dp_sink_cb.rx_audio_queue, nullptr); btif_a2dp_sink_cb.rx_audio_queue = NULL; btif_a2dp_sink_cb.rx_audio_queue = nullptr; btif_a2dp_sink_state = BTIF_A2DP_SINK_STATE_OFF; btif_a2dp_sink_state = BTIF_A2DP_SINK_STATE_OFF; } } tA2DP_SAMPLE_RATE btif_a2dp_sink_get_sample_rate(void) { tA2DP_SAMPLE_RATE btif_a2dp_sink_get_sample_rate() { LockGuard lock(g_mutex); LockGuard lock(g_mutex); return btif_a2dp_sink_cb.sample_rate; return btif_a2dp_sink_cb.sample_rate; } } tA2DP_CHANNEL_COUNT btif_a2dp_sink_get_channel_count(void) { tA2DP_CHANNEL_COUNT btif_a2dp_sink_get_channel_count() { LockGuard lock(g_mutex); LockGuard lock(g_mutex); return btif_a2dp_sink_cb.channel_count; return btif_a2dp_sink_cb.channel_count; } } static void btif_a2dp_sink_command_ready(fixed_queue_t* queue, static void btif_a2dp_sink_command_ready(BT_HDR* p_msg) { UNUSED_ATTR void* context) { BT_HDR* p_msg = (BT_HDR*)fixed_queue_dequeue(queue); LOG_VERBOSE(LOG_TAG, "%s: event %d %s", __func__, p_msg->event, LOG_VERBOSE(LOG_TAG, "%s: event %d %s", __func__, p_msg->event, dump_media_event(p_msg->event)); dump_media_event(p_msg->event)); Loading Loading @@ -352,10 +369,11 @@ void btif_a2dp_sink_update_decoder(const uint8_t* p_codec_info) { memcpy(p_buf->codec_info, p_codec_info, AVDT_CODEC_SIZE); memcpy(p_buf->codec_info, p_codec_info, AVDT_CODEC_SIZE); p_buf->hdr.event = BTIF_MEDIA_SINK_DECODER_UPDATE; p_buf->hdr.event = BTIF_MEDIA_SINK_DECODER_UPDATE; fixed_queue_enqueue(btif_a2dp_sink_cb.cmd_msg_queue, p_buf); btif_a2dp_sink_cb.worker_thread.DoInThread( FROM_HERE, base::BindOnce(btif_a2dp_sink_command_ready, (BT_HDR*)p_buf)); } } void btif_a2dp_sink_on_idle(void) { void btif_a2dp_sink_on_idle() { LOG_INFO(LOG_TAG, "%s", __func__); LOG_INFO(LOG_TAG, "%s", __func__); if (btif_a2dp_sink_state == BTIF_A2DP_SINK_STATE_OFF) return; if (btif_a2dp_sink_state == BTIF_A2DP_SINK_STATE_OFF) return; btif_a2dp_sink_audio_handle_stop_decoding(); btif_a2dp_sink_audio_handle_stop_decoding(); Loading @@ -374,7 +392,7 @@ void btif_a2dp_sink_on_suspended(UNUSED_ATTR tBTA_AV_SUSPEND* p_av_suspend) { btif_a2dp_sink_audio_handle_stop_decoding(); btif_a2dp_sink_audio_handle_stop_decoding(); } } static void btif_a2dp_sink_audio_handle_stop_decoding(void) { static void btif_a2dp_sink_audio_handle_stop_decoding() { LOG_INFO(LOG_TAG, "%s", __func__); LOG_INFO(LOG_TAG, "%s", __func__); alarm_t* old_alarm; alarm_t* old_alarm; { { Loading @@ -382,7 +400,7 @@ static void btif_a2dp_sink_audio_handle_stop_decoding(void) { btif_a2dp_sink_cb.rx_flush = true; btif_a2dp_sink_cb.rx_flush = true; btif_a2dp_sink_audio_rx_flush_req(); btif_a2dp_sink_audio_rx_flush_req(); old_alarm = btif_a2dp_sink_cb.decode_alarm; old_alarm = btif_a2dp_sink_cb.decode_alarm; btif_a2dp_sink_cb.decode_alarm = NULL; btif_a2dp_sink_cb.decode_alarm = nullptr; } } // Drop the lock here, btif_decode_alarm_cb may in the process of being called // Drop the lock here, btif_decode_alarm_cb may in the process of being called Loading @@ -401,13 +419,11 @@ static void btif_a2dp_sink_audio_handle_stop_decoding(void) { static void btif_decode_alarm_cb(UNUSED_ATTR void* context) { static void btif_decode_alarm_cb(UNUSED_ATTR void* context) { LockGuard lock(g_mutex); LockGuard lock(g_mutex); if (btif_a2dp_sink_cb.worker_thread != NULL) { btif_a2dp_sink_cb.worker_thread.DoInThread( thread_post(btif_a2dp_sink_cb.worker_thread, FROM_HERE, base::BindOnce(btif_a2dp_sink_avk_handle_timer)); btif_a2dp_sink_avk_handle_timer, NULL); } } } static void btif_a2dp_sink_clear_track_event(void) { static void btif_a2dp_sink_clear_track_event() { LOG_INFO(LOG_TAG, "%s", __func__); LOG_INFO(LOG_TAG, "%s", __func__); LockGuard lock(g_mutex); LockGuard lock(g_mutex); Loading @@ -415,13 +431,13 @@ static void btif_a2dp_sink_clear_track_event(void) { BtifAvrcpAudioTrackStop(btif_a2dp_sink_cb.audio_track); BtifAvrcpAudioTrackStop(btif_a2dp_sink_cb.audio_track); BtifAvrcpAudioTrackDelete(btif_a2dp_sink_cb.audio_track); BtifAvrcpAudioTrackDelete(btif_a2dp_sink_cb.audio_track); #endif #endif btif_a2dp_sink_cb.audio_track = NULL; btif_a2dp_sink_cb.audio_track = nullptr; } } // Must be called while locked. // Must be called while locked. static void btif_a2dp_sink_audio_handle_start_decoding(void) { static void btif_a2dp_sink_audio_handle_start_decoding() { LOG_INFO(LOG_TAG, "%s", __func__); LOG_INFO(LOG_TAG, "%s", __func__); if (btif_a2dp_sink_cb.decode_alarm != NULL) if (btif_a2dp_sink_cb.decode_alarm != nullptr) return; // Already started decoding return; // Already started decoding #ifndef OS_GENERIC #ifndef OS_GENERIC Loading @@ -429,12 +445,12 @@ static void btif_a2dp_sink_audio_handle_start_decoding(void) { #endif #endif btif_a2dp_sink_cb.decode_alarm = alarm_new_periodic("btif.a2dp_sink_decode"); btif_a2dp_sink_cb.decode_alarm = alarm_new_periodic("btif.a2dp_sink_decode"); if (btif_a2dp_sink_cb.decode_alarm == NULL) { if (btif_a2dp_sink_cb.decode_alarm == nullptr) { LOG_ERROR(LOG_TAG, "%s: unable to allocate decode alarm", __func__); LOG_ERROR(LOG_TAG, "%s: unable to allocate decode alarm", __func__); return; return; } } alarm_set(btif_a2dp_sink_cb.decode_alarm, BTIF_SINK_MEDIA_TIME_TICK_MS, alarm_set(btif_a2dp_sink_cb.decode_alarm, BTIF_SINK_MEDIA_TIME_TICK_MS, btif_decode_alarm_cb, NULL); btif_decode_alarm_cb, nullptr); } } static void btif_a2dp_sink_on_decode_complete(uint8_t* data, uint32_t len) { static void btif_a2dp_sink_on_decode_complete(uint8_t* data, uint32_t len) { Loading @@ -452,13 +468,13 @@ static void btif_a2dp_sink_handle_inc_media(BT_HDR* p_msg) { return; return; } } CHECK(btif_a2dp_sink_cb.decoder_interface); CHECK(btif_a2dp_sink_cb.decoder_interface != nullptr); if (!btif_a2dp_sink_cb.decoder_interface->decode_packet(p_msg)) { if (!btif_a2dp_sink_cb.decoder_interface->decode_packet(p_msg)) { LOG_ERROR(LOG_TAG, "%s: decoding failed", __func__); LOG_ERROR(LOG_TAG, "%s: decoding failed", __func__); } } } } static void btif_a2dp_sink_avk_handle_timer(UNUSED_ATTR void* context) { static void btif_a2dp_sink_avk_handle_timer() { LockGuard lock(g_mutex); LockGuard lock(g_mutex); BT_HDR* p_msg; BT_HDR* p_msg; Loading Loading @@ -503,7 +519,7 @@ void btif_a2dp_sink_set_rx_flush(bool enable) { btif_a2dp_sink_cb.rx_flush = enable; btif_a2dp_sink_cb.rx_flush = enable; } } static void btif_a2dp_sink_audio_rx_flush_event(void) { static void btif_a2dp_sink_audio_rx_flush_event() { LOG_INFO(LOG_TAG, "%s", __func__); LOG_INFO(LOG_TAG, "%s", __func__); LockGuard lock(g_mutex); LockGuard lock(g_mutex); // Flush all received encoded audio buffers // Flush all received encoded audio buffers Loading Loading @@ -541,7 +557,7 @@ static void btif_a2dp_sink_decoder_update_event( APPL_TRACE_DEBUG("%s: reset to Sink role", __func__); APPL_TRACE_DEBUG("%s: reset to Sink role", __func__); btif_a2dp_sink_cb.decoder_interface = bta_av_co_get_decoder_interface(); btif_a2dp_sink_cb.decoder_interface = bta_av_co_get_decoder_interface(); if (btif_a2dp_sink_cb.decoder_interface == NULL) { if (btif_a2dp_sink_cb.decoder_interface == nullptr) { LOG_ERROR(LOG_TAG, "%s: cannot stream audio: no source decoder interface", LOG_ERROR(LOG_TAG, "%s: cannot stream audio: no source decoder interface", __func__); __func__); return; return; Loading @@ -560,7 +576,7 @@ static void btif_a2dp_sink_decoder_update_event( #else #else NULL; NULL; #endif #endif if (btif_a2dp_sink_cb.audio_track == NULL) { if (btif_a2dp_sink_cb.audio_track == nullptr) { LOG_ERROR(LOG_TAG, "%s: track creation failed", __func__); LOG_ERROR(LOG_TAG, "%s: track creation failed", __func__); return; return; } } Loading Loading @@ -595,7 +611,7 @@ uint8_t btif_a2dp_sink_enqueue_buf(BT_HDR* p_pkt) { return fixed_queue_length(btif_a2dp_sink_cb.rx_audio_queue); return fixed_queue_length(btif_a2dp_sink_cb.rx_audio_queue); } } void btif_a2dp_sink_audio_rx_flush_req(void) { void btif_a2dp_sink_audio_rx_flush_req() { LOG_INFO(LOG_TAG, "%s", __func__); LOG_INFO(LOG_TAG, "%s", __func__); if (fixed_queue_is_empty(btif_a2dp_sink_cb.rx_audio_queue)) { if (fixed_queue_is_empty(btif_a2dp_sink_cb.rx_audio_queue)) { /* Queue is already empty */ /* Queue is already empty */ Loading @@ -604,7 +620,8 @@ void btif_a2dp_sink_audio_rx_flush_req(void) { BT_HDR* p_buf = reinterpret_cast<BT_HDR*>(osi_malloc(sizeof(BT_HDR))); BT_HDR* p_buf = reinterpret_cast<BT_HDR*>(osi_malloc(sizeof(BT_HDR))); p_buf->event = BTIF_MEDIA_SINK_AUDIO_RX_FLUSH; p_buf->event = BTIF_MEDIA_SINK_AUDIO_RX_FLUSH; fixed_queue_enqueue(btif_a2dp_sink_cb.cmd_msg_queue, p_buf); btif_a2dp_sink_cb.worker_thread.DoInThread( FROM_HERE, base::BindOnce(btif_a2dp_sink_command_ready, p_buf)); } } void btif_a2dp_sink_debug_dump(UNUSED_ATTR int fd) { void btif_a2dp_sink_debug_dump(UNUSED_ATTR int fd) { Loading @@ -618,7 +635,8 @@ void btif_a2dp_sink_set_focus_state_req(btif_a2dp_sink_focus_state_t state) { osi_malloc(sizeof(tBTIF_MEDIA_SINK_FOCUS_UPDATE))); osi_malloc(sizeof(tBTIF_MEDIA_SINK_FOCUS_UPDATE))); p_buf->focus_state = state; p_buf->focus_state = state; p_buf->hdr.event = BTIF_MEDIA_SINK_SET_FOCUS_STATE; p_buf->hdr.event = BTIF_MEDIA_SINK_SET_FOCUS_STATE; fixed_queue_enqueue(btif_a2dp_sink_cb.cmd_msg_queue, p_buf); btif_a2dp_sink_cb.worker_thread.DoInThread( FROM_HERE, base::BindOnce(btif_a2dp_sink_command_ready, (BT_HDR*)p_buf)); } } static void btif_a2dp_sink_set_focus_state_event( static void btif_a2dp_sink_set_focus_state_event( Loading Loading @@ -646,10 +664,11 @@ void btif_a2dp_sink_set_audio_track_gain(float gain) { #endif #endif } } static void btif_a2dp_sink_clear_track_event_req(void) { static void btif_a2dp_sink_clear_track_event_req() { LOG_INFO(LOG_TAG, "%s", __func__); LOG_INFO(LOG_TAG, "%s", __func__); BT_HDR* p_buf = reinterpret_cast<BT_HDR*>(osi_malloc(sizeof(BT_HDR))); BT_HDR* p_buf = reinterpret_cast<BT_HDR*>(osi_malloc(sizeof(BT_HDR))); p_buf->event = BTIF_MEDIA_SINK_CLEAR_TRACK; p_buf->event = BTIF_MEDIA_SINK_CLEAR_TRACK; fixed_queue_enqueue(btif_a2dp_sink_cb.cmd_msg_queue, p_buf); btif_a2dp_sink_cb.worker_thread.DoInThread( FROM_HERE, base::BindOnce(btif_a2dp_sink_command_ready, p_buf)); } } Loading
system/btif/Android.bp +1 −0 Original line number Original line Diff line number Diff line Loading @@ -133,6 +133,7 @@ cc_test { "libbtcore", "libbtcore", "libbt-common", "libbt-common", "libbt-stack", "libbt-stack", "libbt-sbc-decoder", "libbt-sbc-encoder", "libbt-sbc-encoder", "libbt-utils", "libbt-utils", "libFraunhoferAAC", "libFraunhoferAAC", Loading
system/btif/src/btif_a2dp_sink.cc +116 −97 Original line number Original line Diff line number Diff line Loading @@ -20,8 +20,12 @@ #define LOG_TAG "bt_btif_a2dp_sink" #define LOG_TAG "bt_btif_a2dp_sink" #include <atomic> #include <atomic> #include <cstdio> #include <cstring> #include <cstring> #include <mutex> #include <mutex> #include <string> #include <base/bind.h> #include "bt_common.h" #include "bt_common.h" #include "btif_a2dp.h" #include "btif_a2dp.h" Loading @@ -30,11 +34,12 @@ #include "btif_av_co.h" #include "btif_av_co.h" #include "btif_avrcp_audio_track.h" #include "btif_avrcp_audio_track.h" #include "btif_util.h" #include "btif_util.h" #include "common/message_loop_thread.h" #include "osi/include/fixed_queue.h" #include "osi/include/fixed_queue.h" #include "osi/include/log.h" #include "osi/include/log.h" #include "osi/include/osi.h" #include "osi/include/osi.h" #include "osi/include/thread.h" using bluetooth::common::MessageLoopThread; using LockGuard = std::lock_guard<std::mutex>; using LockGuard = std::lock_guard<std::mutex>; /** /** Loading Loading @@ -73,9 +78,37 @@ typedef struct { } tBTIF_MEDIA_SINK_FOCUS_UPDATE; } tBTIF_MEDIA_SINK_FOCUS_UPDATE; /* BTIF A2DP Sink control block */ /* BTIF A2DP Sink control block */ typedef struct { class BtifA2dpSinkControlBlock { thread_t* worker_thread; public: fixed_queue_t* cmd_msg_queue; explicit BtifA2dpSinkControlBlock(const std::string& thread_name) : worker_thread(thread_name), rx_audio_queue(nullptr), rx_flush(false), decode_alarm(nullptr), sample_rate(0), channel_count(0), rx_focus_state(BTIF_A2DP_SINK_FOCUS_NOT_GRANTED), audio_track(nullptr), decoder_interface(nullptr) {} void Reset() { if (audio_track != nullptr) { BtifAvrcpAudioTrackStop(audio_track); BtifAvrcpAudioTrackDelete(audio_track); } audio_track = nullptr; fixed_queue_free(rx_audio_queue, nullptr); rx_audio_queue = nullptr; alarm_free(decode_alarm); decode_alarm = nullptr; rx_flush = false; rx_focus_state = BTIF_A2DP_SINK_FOCUS_NOT_GRANTED; sample_rate = 0; channel_count = 0; decoder_interface = nullptr; } MessageLoopThread worker_thread; fixed_queue_t* rx_audio_queue; fixed_queue_t* rx_audio_queue; bool rx_flush; /* discards any incoming data when true */ bool rx_flush; /* discards any incoming data when true */ alarm_t* decode_alarm; alarm_t* decode_alarm; Loading @@ -84,36 +117,37 @@ typedef struct { btif_a2dp_sink_focus_state_t rx_focus_state; /* audio focus state */ btif_a2dp_sink_focus_state_t rx_focus_state; /* audio focus state */ void* audio_track; void* audio_track; const tA2DP_DECODER_INTERFACE* decoder_interface; const tA2DP_DECODER_INTERFACE* decoder_interface; } tBTIF_A2DP_SINK_CB; }; // Mutex for below data structures. // Mutex for below data structures. static std::mutex g_mutex; static std::mutex g_mutex; static tBTIF_A2DP_SINK_CB btif_a2dp_sink_cb; static BtifA2dpSinkControlBlock btif_a2dp_sink_cb( "btif_a2dp_sink_worker_thread"); static std::atomic<int> btif_a2dp_sink_state{BTIF_A2DP_SINK_STATE_OFF}; static std::atomic<int> btif_a2dp_sink_state{BTIF_A2DP_SINK_STATE_OFF}; static void btif_a2dp_sink_init_delayed(void* context); static void btif_a2dp_sink_init_delayed(); static void btif_a2dp_sink_startup_delayed(void* context); static void btif_a2dp_sink_startup_delayed(); static void btif_a2dp_sink_start_session_delayed(void* context); static void btif_a2dp_sink_start_session_delayed(); static void btif_a2dp_sink_end_session_delayed(void* context); static void btif_a2dp_sink_end_session_delayed(); static void btif_a2dp_sink_shutdown_delayed(void* context); static void btif_a2dp_sink_shutdown_delayed(); static void btif_a2dp_sink_cleanup_delayed(void* context); static void btif_a2dp_sink_cleanup_delayed(); static void btif_a2dp_sink_command_ready(fixed_queue_t* queue, void* context); static void btif_a2dp_sink_command_ready(BT_HDR* p_msg); static void btif_a2dp_sink_audio_handle_stop_decoding(void); static void btif_a2dp_sink_audio_handle_stop_decoding(); static void btif_decode_alarm_cb(void* context); static void btif_decode_alarm_cb(void* context); static void btif_a2dp_sink_audio_handle_start_decoding(void); static void btif_a2dp_sink_audio_handle_start_decoding(); static void btif_a2dp_sink_avk_handle_timer(UNUSED_ATTR void* context); static void btif_a2dp_sink_avk_handle_timer(); static void btif_a2dp_sink_audio_rx_flush_req(void); static void btif_a2dp_sink_audio_rx_flush_req(); /* Handle incoming media packets A2DP SINK streaming */ /* Handle incoming media packets A2DP SINK streaming */ static void btif_a2dp_sink_handle_inc_media(BT_HDR* p_msg); static void btif_a2dp_sink_handle_inc_media(BT_HDR* p_msg); static void btif_a2dp_sink_decoder_update_event( static void btif_a2dp_sink_decoder_update_event( tBTIF_MEDIA_SINK_DECODER_UPDATE* p_buf); tBTIF_MEDIA_SINK_DECODER_UPDATE* p_buf); static void btif_a2dp_sink_clear_track_event(void); static void btif_a2dp_sink_clear_track_event(); static void btif_a2dp_sink_set_focus_state_event( static void btif_a2dp_sink_set_focus_state_event( btif_a2dp_sink_focus_state_t state); btif_a2dp_sink_focus_state_t state); static void btif_a2dp_sink_audio_rx_flush_event(void); static void btif_a2dp_sink_audio_rx_flush_event(); static void btif_a2dp_sink_clear_track_event_req(void); static void btif_a2dp_sink_clear_track_event_req(); UNUSED_ATTR static const char* dump_media_event(uint16_t event) { UNUSED_ATTR static const char* dump_media_event(uint16_t event) { switch (event) { switch (event) { Loading @@ -127,7 +161,7 @@ UNUSED_ATTR static const char* dump_media_event(uint16_t event) { return "UNKNOWN A2DP SINK EVENT"; return "UNKNOWN A2DP SINK EVENT"; } } bool btif_a2dp_sink_init(void) { bool btif_a2dp_sink_init() { LOG_INFO(LOG_TAG, "%s", __func__); LOG_INFO(LOG_TAG, "%s", __func__); LockGuard lock(g_mutex); LockGuard lock(g_mutex); Loading @@ -136,48 +170,42 @@ bool btif_a2dp_sink_init(void) { return false; return false; } } memset(&btif_a2dp_sink_cb, 0, sizeof(btif_a2dp_sink_cb)); btif_a2dp_sink_cb.Reset(); btif_a2dp_sink_state = BTIF_A2DP_SINK_STATE_STARTING_UP; btif_a2dp_sink_state = BTIF_A2DP_SINK_STATE_STARTING_UP; /* Start A2DP Sink media task */ /* Start A2DP Sink media task */ btif_a2dp_sink_cb.worker_thread = thread_new("btif_a2dp_sink_worker_thread"); btif_a2dp_sink_cb.worker_thread.StartUp(); if (btif_a2dp_sink_cb.worker_thread == NULL) { if (!btif_a2dp_sink_cb.worker_thread.IsRunning()) { LOG_ERROR(LOG_TAG, "%s: unable to start up media thread", __func__); LOG_ERROR(LOG_TAG, "%s: unable to start up media thread", __func__); btif_a2dp_sink_state = BTIF_A2DP_SINK_STATE_OFF; btif_a2dp_sink_state = BTIF_A2DP_SINK_STATE_OFF; return false; return false; } } 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); btif_a2dp_sink_cb.rx_audio_queue = fixed_queue_new(SIZE_MAX); btif_a2dp_sink_cb.cmd_msg_queue = fixed_queue_new(SIZE_MAX); 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); /* Schedule the rest of the operations */ /* Schedule the rest of the operations */ thread_post(btif_a2dp_sink_cb.worker_thread, btif_a2dp_sink_init_delayed, if (!btif_a2dp_sink_cb.worker_thread.EnableRealTimeScheduling()) { NULL); LOG(FATAL) << __func__ << ": Failed to increase A2DP decoder thread priority"; } btif_a2dp_sink_cb.worker_thread.DoInThread( FROM_HERE, base::BindOnce(btif_a2dp_sink_init_delayed)); return true; return true; } } static void btif_a2dp_sink_init_delayed(UNUSED_ATTR void* context) { static void btif_a2dp_sink_init_delayed() { LOG_INFO(LOG_TAG, "%s", __func__); LOG_INFO(LOG_TAG, "%s", __func__); raise_priority_a2dp(TASK_HIGH_MEDIA); btif_a2dp_sink_state = BTIF_A2DP_SINK_STATE_RUNNING; btif_a2dp_sink_state = BTIF_A2DP_SINK_STATE_RUNNING; } } bool btif_a2dp_sink_startup(void) { bool btif_a2dp_sink_startup() { LOG_INFO(LOG_TAG, "%s", __func__); LOG_INFO(LOG_TAG, "%s", __func__); thread_post(btif_a2dp_sink_cb.worker_thread, btif_a2dp_sink_startup_delayed, btif_a2dp_sink_cb.worker_thread.DoInThread( NULL); FROM_HERE, base::BindOnce(btif_a2dp_sink_startup_delayed)); return true; return true; } } static void btif_a2dp_sink_startup_delayed(UNUSED_ATTR void* context) { static void btif_a2dp_sink_startup_delayed() { LOG_INFO(LOG_TAG, "%s", __func__); LOG_INFO(LOG_TAG, "%s", __func__); LockGuard lock(g_mutex); LockGuard lock(g_mutex); // Nothing to do // Nothing to do Loading @@ -186,12 +214,12 @@ static void btif_a2dp_sink_startup_delayed(UNUSED_ATTR void* context) { bool btif_a2dp_sink_start_session(const RawAddress& peer_address) { bool btif_a2dp_sink_start_session(const RawAddress& peer_address) { LOG_INFO(LOG_TAG, "%s: peer_address=%s", __func__, LOG_INFO(LOG_TAG, "%s: peer_address=%s", __func__, peer_address.ToString().c_str()); peer_address.ToString().c_str()); thread_post(btif_a2dp_sink_cb.worker_thread, btif_a2dp_sink_cb.worker_thread.DoInThread( btif_a2dp_sink_start_session_delayed, NULL); FROM_HERE, base::BindOnce(btif_a2dp_sink_start_session_delayed)); return true; return true; } } static void btif_a2dp_sink_start_session_delayed(UNUSED_ATTR void* context) { static void btif_a2dp_sink_start_session_delayed() { LOG_INFO(LOG_TAG, "%s", __func__); LOG_INFO(LOG_TAG, "%s", __func__); LockGuard lock(g_mutex); LockGuard lock(g_mutex); // Nothing to do // Nothing to do Loading Loading @@ -226,35 +254,33 @@ bool btif_a2dp_sink_restart_session(const RawAddress& old_peer_address, bool btif_a2dp_sink_end_session(const RawAddress& peer_address) { bool btif_a2dp_sink_end_session(const RawAddress& peer_address) { LOG_INFO(LOG_TAG, "%s: peer_address=%s", __func__, LOG_INFO(LOG_TAG, "%s: peer_address=%s", __func__, peer_address.ToString().c_str()); peer_address.ToString().c_str()); thread_post(btif_a2dp_sink_cb.worker_thread, btif_a2dp_sink_cb.worker_thread.DoInThread( btif_a2dp_sink_end_session_delayed, NULL); FROM_HERE, base::BindOnce(btif_a2dp_sink_end_session_delayed)); return true; return true; } } static void btif_a2dp_sink_end_session_delayed(UNUSED_ATTR void* context) { static void btif_a2dp_sink_end_session_delayed() { LOG_INFO(LOG_TAG, "%s", __func__); LOG_INFO(LOG_TAG, "%s", __func__); LockGuard lock(g_mutex); LockGuard lock(g_mutex); // Nothing to do // Nothing to do } } void btif_a2dp_sink_shutdown(void) { void btif_a2dp_sink_shutdown() { LOG_INFO(LOG_TAG, "%s", __func__); LOG_INFO(LOG_TAG, "%s", __func__); thread_post(btif_a2dp_sink_cb.worker_thread, btif_a2dp_sink_shutdown_delayed, btif_a2dp_sink_cb.worker_thread.DoInThread( NULL); FROM_HERE, base::BindOnce(btif_a2dp_sink_shutdown_delayed)); } } static void btif_a2dp_sink_shutdown_delayed(UNUSED_ATTR void* context) { static void btif_a2dp_sink_shutdown_delayed() { LOG_INFO(LOG_TAG, "%s", __func__); LOG_INFO(LOG_TAG, "%s", __func__); LockGuard lock(g_mutex); LockGuard lock(g_mutex); // Nothing to do // Nothing to do } } void btif_a2dp_sink_cleanup(void) { void btif_a2dp_sink_cleanup() { LOG_INFO(LOG_TAG, "%s", __func__); LOG_INFO(LOG_TAG, "%s", __func__); alarm_t* decode_alarm; alarm_t* decode_alarm; fixed_queue_t* cmd_msg_queue; thread_t* worker_thread; // Make sure the sink is shutdown // Make sure the sink is shutdown btif_a2dp_sink_shutdown(); btif_a2dp_sink_shutdown(); Loading @@ -269,47 +295,38 @@ void btif_a2dp_sink_cleanup(void) { btif_a2dp_sink_state = BTIF_A2DP_SINK_STATE_SHUTTING_DOWN; btif_a2dp_sink_state = BTIF_A2DP_SINK_STATE_SHUTTING_DOWN; decode_alarm = btif_a2dp_sink_cb.decode_alarm; decode_alarm = btif_a2dp_sink_cb.decode_alarm; btif_a2dp_sink_cb.decode_alarm = NULL; btif_a2dp_sink_cb.decode_alarm = nullptr; cmd_msg_queue = btif_a2dp_sink_cb.cmd_msg_queue; btif_a2dp_sink_cb.cmd_msg_queue = NULL; worker_thread = btif_a2dp_sink_cb.worker_thread; btif_a2dp_sink_cb.worker_thread = NULL; } } // Stop the timer // Stop the timer alarm_free(decode_alarm); alarm_free(decode_alarm); // Exit the thread // Exit the thread fixed_queue_free(cmd_msg_queue, NULL); btif_a2dp_sink_cb.worker_thread.DoInThread( thread_post(worker_thread, btif_a2dp_sink_cleanup_delayed, NULL); FROM_HERE, base::BindOnce(btif_a2dp_sink_cleanup_delayed)); thread_free(worker_thread); btif_a2dp_sink_cb.worker_thread.ShutDown(); } } static void btif_a2dp_sink_cleanup_delayed(UNUSED_ATTR void* context) { static void btif_a2dp_sink_cleanup_delayed() { LOG_INFO(LOG_TAG, "%s", __func__); LOG_INFO(LOG_TAG, "%s", __func__); LockGuard lock(g_mutex); LockGuard lock(g_mutex); fixed_queue_free(btif_a2dp_sink_cb.rx_audio_queue, NULL); fixed_queue_free(btif_a2dp_sink_cb.rx_audio_queue, nullptr); btif_a2dp_sink_cb.rx_audio_queue = NULL; btif_a2dp_sink_cb.rx_audio_queue = nullptr; btif_a2dp_sink_state = BTIF_A2DP_SINK_STATE_OFF; btif_a2dp_sink_state = BTIF_A2DP_SINK_STATE_OFF; } } tA2DP_SAMPLE_RATE btif_a2dp_sink_get_sample_rate(void) { tA2DP_SAMPLE_RATE btif_a2dp_sink_get_sample_rate() { LockGuard lock(g_mutex); LockGuard lock(g_mutex); return btif_a2dp_sink_cb.sample_rate; return btif_a2dp_sink_cb.sample_rate; } } tA2DP_CHANNEL_COUNT btif_a2dp_sink_get_channel_count(void) { tA2DP_CHANNEL_COUNT btif_a2dp_sink_get_channel_count() { LockGuard lock(g_mutex); LockGuard lock(g_mutex); return btif_a2dp_sink_cb.channel_count; return btif_a2dp_sink_cb.channel_count; } } static void btif_a2dp_sink_command_ready(fixed_queue_t* queue, static void btif_a2dp_sink_command_ready(BT_HDR* p_msg) { UNUSED_ATTR void* context) { BT_HDR* p_msg = (BT_HDR*)fixed_queue_dequeue(queue); LOG_VERBOSE(LOG_TAG, "%s: event %d %s", __func__, p_msg->event, LOG_VERBOSE(LOG_TAG, "%s: event %d %s", __func__, p_msg->event, dump_media_event(p_msg->event)); dump_media_event(p_msg->event)); Loading Loading @@ -352,10 +369,11 @@ void btif_a2dp_sink_update_decoder(const uint8_t* p_codec_info) { memcpy(p_buf->codec_info, p_codec_info, AVDT_CODEC_SIZE); memcpy(p_buf->codec_info, p_codec_info, AVDT_CODEC_SIZE); p_buf->hdr.event = BTIF_MEDIA_SINK_DECODER_UPDATE; p_buf->hdr.event = BTIF_MEDIA_SINK_DECODER_UPDATE; fixed_queue_enqueue(btif_a2dp_sink_cb.cmd_msg_queue, p_buf); btif_a2dp_sink_cb.worker_thread.DoInThread( FROM_HERE, base::BindOnce(btif_a2dp_sink_command_ready, (BT_HDR*)p_buf)); } } void btif_a2dp_sink_on_idle(void) { void btif_a2dp_sink_on_idle() { LOG_INFO(LOG_TAG, "%s", __func__); LOG_INFO(LOG_TAG, "%s", __func__); if (btif_a2dp_sink_state == BTIF_A2DP_SINK_STATE_OFF) return; if (btif_a2dp_sink_state == BTIF_A2DP_SINK_STATE_OFF) return; btif_a2dp_sink_audio_handle_stop_decoding(); btif_a2dp_sink_audio_handle_stop_decoding(); Loading @@ -374,7 +392,7 @@ void btif_a2dp_sink_on_suspended(UNUSED_ATTR tBTA_AV_SUSPEND* p_av_suspend) { btif_a2dp_sink_audio_handle_stop_decoding(); btif_a2dp_sink_audio_handle_stop_decoding(); } } static void btif_a2dp_sink_audio_handle_stop_decoding(void) { static void btif_a2dp_sink_audio_handle_stop_decoding() { LOG_INFO(LOG_TAG, "%s", __func__); LOG_INFO(LOG_TAG, "%s", __func__); alarm_t* old_alarm; alarm_t* old_alarm; { { Loading @@ -382,7 +400,7 @@ static void btif_a2dp_sink_audio_handle_stop_decoding(void) { btif_a2dp_sink_cb.rx_flush = true; btif_a2dp_sink_cb.rx_flush = true; btif_a2dp_sink_audio_rx_flush_req(); btif_a2dp_sink_audio_rx_flush_req(); old_alarm = btif_a2dp_sink_cb.decode_alarm; old_alarm = btif_a2dp_sink_cb.decode_alarm; btif_a2dp_sink_cb.decode_alarm = NULL; btif_a2dp_sink_cb.decode_alarm = nullptr; } } // Drop the lock here, btif_decode_alarm_cb may in the process of being called // Drop the lock here, btif_decode_alarm_cb may in the process of being called Loading @@ -401,13 +419,11 @@ static void btif_a2dp_sink_audio_handle_stop_decoding(void) { static void btif_decode_alarm_cb(UNUSED_ATTR void* context) { static void btif_decode_alarm_cb(UNUSED_ATTR void* context) { LockGuard lock(g_mutex); LockGuard lock(g_mutex); if (btif_a2dp_sink_cb.worker_thread != NULL) { btif_a2dp_sink_cb.worker_thread.DoInThread( thread_post(btif_a2dp_sink_cb.worker_thread, FROM_HERE, base::BindOnce(btif_a2dp_sink_avk_handle_timer)); btif_a2dp_sink_avk_handle_timer, NULL); } } } static void btif_a2dp_sink_clear_track_event(void) { static void btif_a2dp_sink_clear_track_event() { LOG_INFO(LOG_TAG, "%s", __func__); LOG_INFO(LOG_TAG, "%s", __func__); LockGuard lock(g_mutex); LockGuard lock(g_mutex); Loading @@ -415,13 +431,13 @@ static void btif_a2dp_sink_clear_track_event(void) { BtifAvrcpAudioTrackStop(btif_a2dp_sink_cb.audio_track); BtifAvrcpAudioTrackStop(btif_a2dp_sink_cb.audio_track); BtifAvrcpAudioTrackDelete(btif_a2dp_sink_cb.audio_track); BtifAvrcpAudioTrackDelete(btif_a2dp_sink_cb.audio_track); #endif #endif btif_a2dp_sink_cb.audio_track = NULL; btif_a2dp_sink_cb.audio_track = nullptr; } } // Must be called while locked. // Must be called while locked. static void btif_a2dp_sink_audio_handle_start_decoding(void) { static void btif_a2dp_sink_audio_handle_start_decoding() { LOG_INFO(LOG_TAG, "%s", __func__); LOG_INFO(LOG_TAG, "%s", __func__); if (btif_a2dp_sink_cb.decode_alarm != NULL) if (btif_a2dp_sink_cb.decode_alarm != nullptr) return; // Already started decoding return; // Already started decoding #ifndef OS_GENERIC #ifndef OS_GENERIC Loading @@ -429,12 +445,12 @@ static void btif_a2dp_sink_audio_handle_start_decoding(void) { #endif #endif btif_a2dp_sink_cb.decode_alarm = alarm_new_periodic("btif.a2dp_sink_decode"); btif_a2dp_sink_cb.decode_alarm = alarm_new_periodic("btif.a2dp_sink_decode"); if (btif_a2dp_sink_cb.decode_alarm == NULL) { if (btif_a2dp_sink_cb.decode_alarm == nullptr) { LOG_ERROR(LOG_TAG, "%s: unable to allocate decode alarm", __func__); LOG_ERROR(LOG_TAG, "%s: unable to allocate decode alarm", __func__); return; return; } } alarm_set(btif_a2dp_sink_cb.decode_alarm, BTIF_SINK_MEDIA_TIME_TICK_MS, alarm_set(btif_a2dp_sink_cb.decode_alarm, BTIF_SINK_MEDIA_TIME_TICK_MS, btif_decode_alarm_cb, NULL); btif_decode_alarm_cb, nullptr); } } static void btif_a2dp_sink_on_decode_complete(uint8_t* data, uint32_t len) { static void btif_a2dp_sink_on_decode_complete(uint8_t* data, uint32_t len) { Loading @@ -452,13 +468,13 @@ static void btif_a2dp_sink_handle_inc_media(BT_HDR* p_msg) { return; return; } } CHECK(btif_a2dp_sink_cb.decoder_interface); CHECK(btif_a2dp_sink_cb.decoder_interface != nullptr); if (!btif_a2dp_sink_cb.decoder_interface->decode_packet(p_msg)) { if (!btif_a2dp_sink_cb.decoder_interface->decode_packet(p_msg)) { LOG_ERROR(LOG_TAG, "%s: decoding failed", __func__); LOG_ERROR(LOG_TAG, "%s: decoding failed", __func__); } } } } static void btif_a2dp_sink_avk_handle_timer(UNUSED_ATTR void* context) { static void btif_a2dp_sink_avk_handle_timer() { LockGuard lock(g_mutex); LockGuard lock(g_mutex); BT_HDR* p_msg; BT_HDR* p_msg; Loading Loading @@ -503,7 +519,7 @@ void btif_a2dp_sink_set_rx_flush(bool enable) { btif_a2dp_sink_cb.rx_flush = enable; btif_a2dp_sink_cb.rx_flush = enable; } } static void btif_a2dp_sink_audio_rx_flush_event(void) { static void btif_a2dp_sink_audio_rx_flush_event() { LOG_INFO(LOG_TAG, "%s", __func__); LOG_INFO(LOG_TAG, "%s", __func__); LockGuard lock(g_mutex); LockGuard lock(g_mutex); // Flush all received encoded audio buffers // Flush all received encoded audio buffers Loading Loading @@ -541,7 +557,7 @@ static void btif_a2dp_sink_decoder_update_event( APPL_TRACE_DEBUG("%s: reset to Sink role", __func__); APPL_TRACE_DEBUG("%s: reset to Sink role", __func__); btif_a2dp_sink_cb.decoder_interface = bta_av_co_get_decoder_interface(); btif_a2dp_sink_cb.decoder_interface = bta_av_co_get_decoder_interface(); if (btif_a2dp_sink_cb.decoder_interface == NULL) { if (btif_a2dp_sink_cb.decoder_interface == nullptr) { LOG_ERROR(LOG_TAG, "%s: cannot stream audio: no source decoder interface", LOG_ERROR(LOG_TAG, "%s: cannot stream audio: no source decoder interface", __func__); __func__); return; return; Loading @@ -560,7 +576,7 @@ static void btif_a2dp_sink_decoder_update_event( #else #else NULL; NULL; #endif #endif if (btif_a2dp_sink_cb.audio_track == NULL) { if (btif_a2dp_sink_cb.audio_track == nullptr) { LOG_ERROR(LOG_TAG, "%s: track creation failed", __func__); LOG_ERROR(LOG_TAG, "%s: track creation failed", __func__); return; return; } } Loading Loading @@ -595,7 +611,7 @@ uint8_t btif_a2dp_sink_enqueue_buf(BT_HDR* p_pkt) { return fixed_queue_length(btif_a2dp_sink_cb.rx_audio_queue); return fixed_queue_length(btif_a2dp_sink_cb.rx_audio_queue); } } void btif_a2dp_sink_audio_rx_flush_req(void) { void btif_a2dp_sink_audio_rx_flush_req() { LOG_INFO(LOG_TAG, "%s", __func__); LOG_INFO(LOG_TAG, "%s", __func__); if (fixed_queue_is_empty(btif_a2dp_sink_cb.rx_audio_queue)) { if (fixed_queue_is_empty(btif_a2dp_sink_cb.rx_audio_queue)) { /* Queue is already empty */ /* Queue is already empty */ Loading @@ -604,7 +620,8 @@ void btif_a2dp_sink_audio_rx_flush_req(void) { BT_HDR* p_buf = reinterpret_cast<BT_HDR*>(osi_malloc(sizeof(BT_HDR))); BT_HDR* p_buf = reinterpret_cast<BT_HDR*>(osi_malloc(sizeof(BT_HDR))); p_buf->event = BTIF_MEDIA_SINK_AUDIO_RX_FLUSH; p_buf->event = BTIF_MEDIA_SINK_AUDIO_RX_FLUSH; fixed_queue_enqueue(btif_a2dp_sink_cb.cmd_msg_queue, p_buf); btif_a2dp_sink_cb.worker_thread.DoInThread( FROM_HERE, base::BindOnce(btif_a2dp_sink_command_ready, p_buf)); } } void btif_a2dp_sink_debug_dump(UNUSED_ATTR int fd) { void btif_a2dp_sink_debug_dump(UNUSED_ATTR int fd) { Loading @@ -618,7 +635,8 @@ void btif_a2dp_sink_set_focus_state_req(btif_a2dp_sink_focus_state_t state) { osi_malloc(sizeof(tBTIF_MEDIA_SINK_FOCUS_UPDATE))); osi_malloc(sizeof(tBTIF_MEDIA_SINK_FOCUS_UPDATE))); p_buf->focus_state = state; p_buf->focus_state = state; p_buf->hdr.event = BTIF_MEDIA_SINK_SET_FOCUS_STATE; p_buf->hdr.event = BTIF_MEDIA_SINK_SET_FOCUS_STATE; fixed_queue_enqueue(btif_a2dp_sink_cb.cmd_msg_queue, p_buf); btif_a2dp_sink_cb.worker_thread.DoInThread( FROM_HERE, base::BindOnce(btif_a2dp_sink_command_ready, (BT_HDR*)p_buf)); } } static void btif_a2dp_sink_set_focus_state_event( static void btif_a2dp_sink_set_focus_state_event( Loading Loading @@ -646,10 +664,11 @@ void btif_a2dp_sink_set_audio_track_gain(float gain) { #endif #endif } } static void btif_a2dp_sink_clear_track_event_req(void) { static void btif_a2dp_sink_clear_track_event_req() { LOG_INFO(LOG_TAG, "%s", __func__); LOG_INFO(LOG_TAG, "%s", __func__); BT_HDR* p_buf = reinterpret_cast<BT_HDR*>(osi_malloc(sizeof(BT_HDR))); BT_HDR* p_buf = reinterpret_cast<BT_HDR*>(osi_malloc(sizeof(BT_HDR))); p_buf->event = BTIF_MEDIA_SINK_CLEAR_TRACK; p_buf->event = BTIF_MEDIA_SINK_CLEAR_TRACK; fixed_queue_enqueue(btif_a2dp_sink_cb.cmd_msg_queue, p_buf); btif_a2dp_sink_cb.worker_thread.DoInThread( FROM_HERE, base::BindOnce(btif_a2dp_sink_command_ready, p_buf)); } }