From ed424de5bfff3ba318af64828f291e6e9ff74b3a Mon Sep 17 00:00:00 2001 From: Pavlin Radoslavov Date: Mon, 30 Apr 2018 13:39:20 -0700 Subject: [PATCH] Fix A2DP Suspend related multi-component deadlock Apparently, the processing of A2DP Suspend from the Audio HAL could result in a deadlock across multiple components: A2dpService -> AudioService -> Audio-BT HAL -> BT Native Stack -> BT JNI upcall -> A2dpService 1) A2dpService -> AudioService: - Waiting inside setActiveDevice() -> synchronized (mStateMachines) -> mAudioManager.setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent() - The mAudioManager call can be blocking: a followup call would wait for the previous call to complete. 2) AudioService -> Audio-BT HAL The AudioService is wating on the Audio-BT HAL to complete its request. In this case the request is SUSPEND 3) Audio-BT HAL -> BT Native Stack The Audio side of the Audio-BT HAL is waiting for the BT Native stack to ACK the SUSPEND command. More specifically, it is retrying few times with timeout of 250ms each iteration. 4) BT Native Stack -> BT JNI upcall - In the BT Native Stack the BtifAv FSM (see file btif/src/btif_av.cc) is in state StateStarted and has received the BTIF_AV_SUSPEND_STREAM_REQ_EVT because of the SUSPEND command from the Audio HAL. - As a result, the LocalSuspendPending flag has been set: peer_.SetFlags(BtifAvPeer::kFlagLocalSuspendPending); - Only after the above flag is reset, then the BT Native Stack will ACK the SUSPEND command from the HAL - The above flag will be reset when event BTA_AV_SUSPEND_EVT is received from the underlying stack - The BtifAv state machine has received the BTA_AV_SUSPEND_EVT event. However, prior to clearing the pending status, the FSM tries to report the audio state via JNI to the Java layer: btif_report_audio_state(); ... peer_.ClearFlags(BtifAvPeer::kFlagLocalSuspendPending); - Apparently, all the processing inside the BtifAv FSM is done on the JNI thread, including the btif_report_audio_state() upcall. 5) BT JNI upcall -> A2dpService - The btif_report_audio_state() upcall calls indirectly A2dpNativeInterface.onAudioStateChanged() -> sendMessageToService() -> A2dpService.messageFromNative() - Within the A2dpService.messageFromNative() processing, there is "synchronized (mStateMachines) {}" block, and the processing there blocks because per (1) above A2dpService.setActiveDevice() is already inside its own "synchronized (mStateMachines) {}" block The above deadlock is fixed by the following: - Modified the BTA_AV_SUSPEND_EVT processing such that the clearing of the kFlagLocalSuspendPending flag is done BEFORE the btif_report_audio_state() - Modified the BtifAv FSM such that the internal processing of the FSM events is done on the BTA thread instead of the JNI thread. Thus, the FSM processing cannot be blocked by JNI upcalls. Also: - Updated the do_in_bta_thread() function to have a return value so it is more aligned with the corresponding do_in_jni_thread() implementation - Updated the reordering of some other btif_report_*() upcalls inside btif_av.cc so they are after the FSM internal processing in the current state. - Added few extra logs to the Audio-BT HAL (file audio_a2dp_hw.cc). Bug: 72823323 Test: Disconnect/reconnect with Philips SBH7000 Headset Change-Id: I7ccb558e458a8e90d0414f94463bda8d4b3fdc97 Merged-In: I7ccb558e458a8e90d0414f94463bda8d4b3fdc97 (cherry picked from commit 2a3b9b597ee07f8728bd9903b0bc104c4e24fd6c) --- audio_a2dp_hw/src/audio_a2dp_hw.cc | 14 +++- bta/include/bta_closure_api.h | 6 +- bta/sys/bta_sys.h | 4 +- bta/sys/bta_sys_main.cc | 16 ++-- btif/co/bta_av_co.cc | 7 +- btif/src/btif_av.cc | 152 ++++++++++++++++++++----------------- 6 files changed, 112 insertions(+), 87 deletions(-) diff --git a/audio_a2dp_hw/src/audio_a2dp_hw.cc b/audio_a2dp_hw/src/audio_a2dp_hw.cc index a43a4fbaa..837e124bf 100644 --- a/audio_a2dp_hw/src/audio_a2dp_hw.cc +++ b/audio_a2dp_hw/src/audio_a2dp_hw.cc @@ -427,10 +427,12 @@ static int a2dp_command(struct a2dp_stream_common* common, tA2DP_CTRL_CMD cmd) { DEBUG("A2DP COMMAND %s", audio_a2dp_hw_dump_ctrl_event(cmd)); if (common->ctrl_fd == AUDIO_SKT_DISCONNECTED) { - INFO("starting up or recovering from previous error"); + INFO("starting up or recovering from previous error: command=%s", + audio_a2dp_hw_dump_ctrl_event(cmd)); a2dp_open_ctrl_path(common); if (common->ctrl_fd == AUDIO_SKT_DISCONNECTED) { - ERROR("failure to open ctrl path"); + ERROR("failure to open ctrl path: command=%s", + audio_a2dp_hw_dump_ctrl_event(cmd)); return -1; } } @@ -439,7 +441,8 @@ static int a2dp_command(struct a2dp_stream_common* common, tA2DP_CTRL_CMD cmd) { ssize_t sent; OSI_NO_INTR(sent = send(common->ctrl_fd, &cmd, 1, MSG_NOSIGNAL)); if (sent == -1) { - ERROR("cmd failed (%s)", strerror(errno)); + ERROR("cmd failed (%s): command=%s", strerror(errno), + audio_a2dp_hw_dump_ctrl_event(cmd)); skt_disconnect(common->ctrl_fd); common->ctrl_fd = AUDIO_SKT_DISCONNECTED; return -1; @@ -454,7 +457,10 @@ static int a2dp_command(struct a2dp_stream_common* common, tA2DP_CTRL_CMD cmd) { DEBUG("A2DP COMMAND %s DONE STATUS %d", audio_a2dp_hw_dump_ctrl_event(cmd), ack); - if (ack == A2DP_CTRL_ACK_INCALL_FAILURE) return ack; + if (ack == A2DP_CTRL_ACK_INCALL_FAILURE) { + ERROR("A2DP COMMAND %s error %d", audio_a2dp_hw_dump_ctrl_event(cmd), ack); + return ack; + } if (ack != A2DP_CTRL_ACK_SUCCESS) { ERROR("A2DP COMMAND %s error %d", audio_a2dp_hw_dump_ctrl_event(cmd), ack); return -1; diff --git a/bta/include/bta_closure_api.h b/bta/include/bta_closure_api.h index e0aad4720..a4c0188cf 100644 --- a/bta/include/bta_closure_api.h +++ b/bta/include/bta_closure_api.h @@ -23,6 +23,8 @@ #include #include +#include + /* * This method post a closure for execution on bta thread. Please see * documentation at @@ -30,7 +32,7 @@ * for how to handle dynamic memory ownership/smart pointers with base::Owned(), * base::Passed(), base::ConstRef() and others. */ -void do_in_bta_thread(const tracked_objects::Location& from_here, - const base::Closure& task); +bt_status_t do_in_bta_thread(const tracked_objects::Location& from_here, + const base::Closure& task); #endif /* BTA_CLOSURE_API_H */ diff --git a/bta/sys/bta_sys.h b/bta/sys/bta_sys.h index 84f22f294..a72f34b09 100644 --- a/bta/sys/bta_sys.h +++ b/bta/sys/bta_sys.h @@ -31,6 +31,8 @@ #include #include +#include "bta/include/bta_closure_api.h" + /***************************************************************************** * Constants and data types ****************************************************************************/ @@ -222,8 +224,6 @@ extern void bta_sys_deregister(uint8_t id); extern bool bta_sys_is_register(uint8_t id); extern uint16_t bta_sys_get_sys_features(void); extern void bta_sys_sendmsg(void* p_msg); -extern void do_in_bta_thread(const tracked_objects::Location& from_here, - const base::Closure& task); extern void bta_sys_start_timer(alarm_t* alarm, period_ms_t interval, uint16_t event, uint16_t layer_specific); extern void bta_sys_disable(tBTA_SYS_HW_MODULE module); diff --git a/bta/sys/bta_sys_main.cc b/bta/sys/bta_sys_main.cc index a196c79c5..bdedcde78 100644 --- a/bta/sys/bta_sys_main.cc +++ b/bta/sys/bta_sys_main.cc @@ -547,25 +547,29 @@ void bta_sys_sendmsg(void* p_msg) { * * Description Post a closure to be ran in the bta thread * - * Returns void + * Returns BT_STATUS_SUCCESS on success * ******************************************************************************/ -void do_in_bta_thread(const tracked_objects::Location& from_here, - const base::Closure& task) { +bt_status_t do_in_bta_thread(const tracked_objects::Location& from_here, + const base::Closure& task) { base::MessageLoop* bta_message_loop = get_message_loop(); if (!bta_message_loop) { APPL_TRACE_ERROR("%s: MessageLooper not initialized", __func__); - return; + return BT_STATUS_FAIL; } scoped_refptr task_runner = bta_message_loop->task_runner(); if (!task_runner.get()) { APPL_TRACE_ERROR("%s: task runner is dead", __func__); - return; + return BT_STATUS_FAIL; } - task_runner->PostTask(from_here, task); + if (!task_runner->PostTask(from_here, task)) { + APPL_TRACE_ERROR("%s: Post task to task runner failed!", __func__); + return BT_STATUS_FAIL; + } + return BT_STATUS_SUCCESS; } /******************************************************************************* diff --git a/btif/co/bta_av_co.cc b/btif/co/bta_av_co.cc index 2131f0e7e..d2f8b192a 100644 --- a/btif/co/bta_av_co.cc +++ b/btif/co/bta_av_co.cc @@ -1612,10 +1612,9 @@ bool BtaAvCo::ReportSourceCodecState(BtaAvCoPeer* p_peer) { APPL_TRACE_DEBUG("%s: peer %s codec_config=%s", __func__, p_peer->addr.ToString().c_str(), codec_config.ToString().c_str()); - do_in_jni_thread( - FROM_HERE, - base::Bind(&btif_av_report_source_codec_state, p_peer->addr, codec_config, - codecs_local_capabilities, codecs_selectable_capabilities)); + btif_av_report_source_codec_state(p_peer->addr, codec_config, + codecs_local_capabilities, + codecs_selectable_capabilities); return true; } diff --git a/btif/src/btif_av.cc b/btif/src/btif_av.cc index 31713f44a..723f882a7 100644 --- a/btif/src/btif_av.cc +++ b/btif/src/btif_av.cc @@ -33,7 +33,8 @@ #include "audio_a2dp_hw/include/audio_a2dp_hw.h" #include "bt_common.h" #include "bt_utils.h" -#include "bta_api.h" +#include "bta/include/bta_api.h" +#include "bta/include/bta_closure_api.h" #include "btif/include/btif_a2dp_source.h" #include "btif_a2dp.h" #include "btif_a2dp_audio_interface.h" @@ -64,7 +65,7 @@ static constexpr tBTA_AV_HNDL kBtaHandleUnknown = 0; typedef struct { int sample_rate; int channel_count; - RawAddress peer_bd; + RawAddress peer_address; } btif_av_sink_config_req_t; /** @@ -637,6 +638,8 @@ static void btif_report_connection_state(const RawAddress& peer_address, btav_connection_state_t state); static void btif_report_audio_state(const RawAddress& peer_address, btav_audio_state_t state); +static void btif_av_report_sink_audio_config_state( + const RawAddress& peer_address, int sample_rate, int channel_count); static void btif_av_source_initiate_av_open_timer_timeout(void* data); static void btif_av_sink_initiate_av_open_timer_timeout(void* data); static void bta_av_sink_media_callback(tBTA_AV_EVT event, @@ -931,11 +934,11 @@ void BtifAvSource::Cleanup() { btif_queue_cleanup(UUID_SERVCLASS_AUDIO_SOURCE); - do_in_jni_thread( + do_in_bta_thread( FROM_HERE, base::Bind(base::IgnoreResult(&BtifAvSource::SetActivePeer), base::Unretained(&btif_av_source), RawAddress::kEmpty)); - do_in_jni_thread(FROM_HERE, base::Bind(&btif_a2dp_source_cleanup)); + do_in_bta_thread(FROM_HERE, base::Bind(&btif_a2dp_source_cleanup)); btif_disable_service(BTA_A2DP_SOURCE_SERVICE_ID); CleanupAllPeers(); @@ -1109,11 +1112,11 @@ void BtifAvSink::Cleanup() { btif_queue_cleanup(UUID_SERVCLASS_AUDIO_SINK); - do_in_jni_thread( + do_in_bta_thread( FROM_HERE, base::Bind(base::IgnoreResult(&BtifAvSink::SetActivePeer), base::Unretained(&btif_av_sink), RawAddress::kEmpty)); - do_in_jni_thread(FROM_HERE, base::Bind(&btif_a2dp_sink_cleanup)); + do_in_bta_thread(FROM_HERE, base::Bind(&btif_a2dp_sink_cleanup)); btif_disable_service(BTA_A2DP_SINK_SERVICE_ID); CleanupAllPeers(); @@ -1284,10 +1287,10 @@ void BtifAvStateMachine::StateIdle::OnEnter() { // Delete peers that are re-entering the Idle state if (peer_.IsSink()) { - do_in_jni_thread(FROM_HERE, base::Bind(&BtifAvSource::DeleteIdlePeers, + do_in_bta_thread(FROM_HERE, base::Bind(&BtifAvSource::DeleteIdlePeers, base::Unretained(&btif_av_source))); } else if (peer_.IsSource()) { - do_in_jni_thread(FROM_HERE, base::Bind(&BtifAvSink::DeleteIdlePeers, + do_in_bta_thread(FROM_HERE, base::Bind(&BtifAvSink::DeleteIdlePeers, base::Unretained(&btif_av_sink))); } } @@ -1405,19 +1408,11 @@ bool BtifAvStateMachine::StateIdle::ProcessEvent(uint32_t event, void* p_data) { // Procedure, we have to handle Config and Open event in Idle state. // We hit these scenarios while running PTS test case for AVRCP Controller. case BTIF_AV_SINK_CONFIG_REQ_EVT: { - btif_av_sink_config_req_t req; - // Copy to avoid alignment problems - memcpy(&req, p_data, sizeof(req)); - - LOG_INFO(LOG_TAG, - "%s: Peer %s : event=%s sample_rate=%d channel_count=%d", - __PRETTY_FUNCTION__, peer_.PeerAddress().ToString().c_str(), - BtifAvEvent::EventName(event).c_str(), req.sample_rate, - req.channel_count); - if (btif_av_sink.Enabled()) { - HAL_CBACK(btif_av_sink.Callbacks(), audio_config_cb, req.peer_bd, - req.sample_rate, req.channel_count); - } + const btif_av_sink_config_req_t* p_config_req = + static_cast(p_data); + btif_av_report_sink_audio_config_state(p_config_req->peer_address, + p_config_req->sample_rate, + p_config_req->channel_count); } break; case BTA_AV_OPEN_EVT: { @@ -1625,18 +1620,12 @@ bool BtifAvStateMachine::StateOpening::ProcessEvent(uint32_t event, } break; case BTIF_AV_SINK_CONFIG_REQ_EVT: { - btif_av_sink_config_req_t req; - // Copy to avoid alignment problems - memcpy(&req, p_data, sizeof(req)); - - LOG_INFO(LOG_TAG, - "%s: Peer %s : event=%s sample_rate=%d channel_count=%d", - __PRETTY_FUNCTION__, peer_.PeerAddress().ToString().c_str(), - BtifAvEvent::EventName(event).c_str(), req.sample_rate, - req.channel_count); - if (peer_.IsSource() && btif_av_sink.Enabled()) { - HAL_CBACK(btif_av_sink.Callbacks(), audio_config_cb, - peer_.PeerAddress(), req.sample_rate, req.channel_count); + const btif_av_sink_config_req_t* p_config_req = + static_cast(p_data); + if (peer_.IsSource()) { + btif_av_report_sink_audio_config_state(p_config_req->peer_address, + p_config_req->sample_rate, + p_config_req->channel_count); } } break; @@ -1680,9 +1669,9 @@ bool BtifAvStateMachine::StateOpening::ProcessEvent(uint32_t event, break; case BTIF_AV_DISCONNECT_REQ_EVT: + BTA_AvClose(peer_.BtaHandle()); btif_report_connection_state(peer_.PeerAddress(), BTAV_CONNECTION_STATE_DISCONNECTED); - BTA_AvClose(peer_.BtaHandle()); peer_.StateMachine().TransitionTo(BtifAvStateMachine::kStateIdle); if (peer_.SelfInitiatedConnection()) { btif_queue_advance(); @@ -1831,15 +1820,15 @@ bool BtifAvStateMachine::StateOpened::ProcessEvent(uint32_t event, btif_a2dp_on_stopped(nullptr); } - // Inform the application that we are disconnected - btif_report_connection_state(peer_.PeerAddress(), - BTAV_CONNECTION_STATE_DISCONNECTED); - // Change state to Idle, send acknowledgement if start is pending if (peer_.CheckFlags(BtifAvPeer::kFlagPendingStart)) { btif_a2dp_command_ack(A2DP_CTRL_ACK_FAILURE); // Pending start flag will be cleared when exit current state } + + // Inform the application that we are disconnected + btif_report_connection_state(peer_.PeerAddress(), + BTAV_CONNECTION_STATE_DISCONNECTED); peer_.StateMachine().TransitionTo(BtifAvStateMachine::kStateIdle); break; @@ -1979,7 +1968,7 @@ bool BtifAvStateMachine::StateStarted::ProcessEvent(uint32_t event, peer_.StateMachine().TransitionTo(BtifAvStateMachine::kStateClosing); break; - case BTA_AV_SUSPEND_EVT: + case BTA_AV_SUSPEND_EVT: { LOG_INFO(LOG_TAG, "%s: Peer %s : event=%s status=%d initiator=%d flags=%s", __PRETTY_FUNCTION__, peer_.PeerAddress().ToString().c_str(), @@ -2000,6 +1989,7 @@ bool BtifAvStateMachine::StateStarted::ProcessEvent(uint32_t event, return false; } + btav_audio_state_t state = BTAV_AUDIO_STATE_REMOTE_SUSPEND; if (p_av->suspend.initiator != true) { // Remote suspend, notify HAL and await audioflinger to // suspend/stop stream. @@ -2008,18 +1998,16 @@ bool BtifAvStateMachine::StateStarted::ProcessEvent(uint32_t event, // stream only if we did not already initiate a local suspend. if (!peer_.CheckFlags(BtifAvPeer::kFlagLocalSuspendPending)) peer_.SetFlags(BtifAvPeer::kFlagRemoteSuspend); - - btif_report_audio_state(peer_.PeerAddress(), - BTAV_AUDIO_STATE_REMOTE_SUSPEND); } else { - btif_report_audio_state(peer_.PeerAddress(), BTAV_AUDIO_STATE_STOPPED); + state = BTAV_AUDIO_STATE_STOPPED; } - peer_.StateMachine().TransitionTo(BtifAvStateMachine::kStateOpened); - - // Suspend completed and state changed, clear pending status + // Suspend completed, clear pending status peer_.ClearFlags(BtifAvPeer::kFlagLocalSuspendPending); - break; + + btif_report_audio_state(peer_.PeerAddress(), state); + peer_.StateMachine().TransitionTo(BtifAvStateMachine::kStateOpened); + } break; case BTA_AV_STOP_EVT: LOG_INFO(LOG_TAG, "%s: Peer %s : event=%s flags=%s", __PRETTY_FUNCTION__, @@ -2221,11 +2209,13 @@ static void btif_report_connection_state(const RawAddress& peer_address, peer_address.ToString().c_str(), state); if (btif_av_source.Enabled()) { - HAL_CBACK(btif_av_source.Callbacks(), connection_state_cb, peer_address, - state); + do_in_jni_thread(FROM_HERE, + base::Bind(btif_av_source.Callbacks()->connection_state_cb, + peer_address, state)); } else if (btif_av_sink.Enabled()) { - HAL_CBACK(btif_av_sink.Callbacks(), connection_state_cb, peer_address, - state); + do_in_jni_thread(FROM_HERE, + base::Bind(btif_av_sink.Callbacks()->connection_state_cb, + peer_address, state)); } } @@ -2244,9 +2234,13 @@ static void btif_report_audio_state(const RawAddress& peer_address, peer_address.ToString().c_str(), state); if (btif_av_source.Enabled()) { - HAL_CBACK(btif_av_source.Callbacks(), audio_state_cb, peer_address, state); + do_in_jni_thread(FROM_HERE, + base::Bind(btif_av_source.Callbacks()->audio_state_cb, + peer_address, state)); } else if (btif_av_sink.Enabled()) { - HAL_CBACK(btif_av_sink.Callbacks(), audio_state_cb, peer_address, state); + do_in_jni_thread(FROM_HERE, + base::Bind(btif_av_sink.Callbacks()->audio_state_cb, + peer_address, state)); } } @@ -2259,9 +2253,29 @@ void btif_av_report_source_codec_state( BTIF_TRACE_EVENT("%s: peer_address=%s", __func__, peer_address.ToString().c_str()); if (btif_av_source.Enabled()) { - HAL_CBACK(btif_av_source.Callbacks(), audio_config_cb, peer_address, - codec_config, codecs_local_capabilities, - codecs_selectable_capabilities); + do_in_jni_thread( + FROM_HERE, + base::Bind(btif_av_source.Callbacks()->audio_config_cb, peer_address, + codec_config, codecs_local_capabilities, + codecs_selectable_capabilities)); + } +} + +/** + * Report the audio config state of the A2DP Sink connection. + * + * @param peer_address the peer address + * @param sample_rate the sample rate (in samples per second) + * @param channel_count the channel count (1 for Mono, 2 for Stereo) + */ +static void btif_av_report_sink_audio_config_state( + const RawAddress& peer_address, int sample_rate, int channel_count) { + LOG_INFO(LOG_TAG, "%s: Peer %s : sample_rate=%d channel_count=%d", __func__, + peer_address.ToString().c_str(), sample_rate, channel_count); + if (btif_av_sink.Enabled()) { + do_in_jni_thread(FROM_HERE, + base::Bind(btif_av_sink.Callbacks()->audio_config_cb, + peer_address, sample_rate, channel_count)); } } @@ -2451,14 +2465,14 @@ static void bta_av_source_callback(tBTA_AV_EVT event, tBTA_AV* p_data) { BtifAvEvent btif_av_event(event, p_data, sizeof(tBTA_AV)); BTIF_TRACE_EVENT("%s: event=%s", __func__, btif_av_event.ToString().c_str()); - do_in_jni_thread(FROM_HERE, + do_in_bta_thread(FROM_HERE, base::Bind(&btif_av_handle_bta_av_event, AVDT_TSEP_SNK /* peer_sep */, btif_av_event)); } static void bta_av_sink_callback(tBTA_AV_EVT event, tBTA_AV* p_data) { BtifAvEvent btif_av_event(event, p_data, sizeof(tBTA_AV)); - do_in_jni_thread(FROM_HERE, + do_in_bta_thread(FROM_HERE, base::Bind(&btif_av_handle_bta_av_event, AVDT_TSEP_SRC /* peer_sep */, btif_av_event)); } @@ -2499,12 +2513,12 @@ static void bta_av_sink_media_callback(tBTA_AV_EVT event, APPL_TRACE_ERROR("%s: Cannot get the channel count", __func__); break; } - config_req.peer_bd = p_data->avk_config.bd_addr; + config_req.peer_address = p_data->avk_config.bd_addr; BtifAvEvent btif_av_event(BTIF_AV_SINK_CONFIG_REQ_EVT, &config_req, sizeof(config_req)); - do_in_jni_thread(FROM_HERE, base::Bind(&btif_av_handle_event, + do_in_bta_thread(FROM_HERE, base::Bind(&btif_av_handle_event, AVDT_TSEP_SRC, // peer_sep - config_req.peer_bd, + config_req.peer_address, kBtaHandleUnknown, btif_av_event)); break; } @@ -2625,7 +2639,7 @@ static bt_status_t src_disconnect_sink(const RawAddress& peer_address) { BtifAvEvent btif_av_event(BTIF_AV_DISCONNECT_REQ_EVT, &peer_address, sizeof(peer_address)); - return do_in_jni_thread( + return do_in_bta_thread( FROM_HERE, base::Bind(&btif_av_handle_event, AVDT_TSEP_SNK, // peer_sep peer_address, kBtaHandleUnknown, btif_av_event)); @@ -2641,7 +2655,7 @@ static bt_status_t sink_disconnect_src(const RawAddress& peer_address) { BtifAvEvent btif_av_event(BTIF_AV_DISCONNECT_REQ_EVT, &peer_address, sizeof(peer_address)); - return do_in_jni_thread( + return do_in_bta_thread( FROM_HERE, base::Bind(&btif_av_handle_event, AVDT_TSEP_SRC, // peer_sep peer_address, kBtaHandleUnknown, btif_av_event)); @@ -2655,7 +2669,7 @@ static bt_status_t src_set_active_sink(const RawAddress& peer_address) { return BT_STATUS_NOT_READY; } - return do_in_jni_thread(FROM_HERE, base::Bind(&set_active_peer_int, + return do_in_bta_thread(FROM_HERE, base::Bind(&set_active_peer_int, AVDT_TSEP_SNK, // peer_sep peer_address)); } @@ -2670,7 +2684,7 @@ static bt_status_t codec_config_src( return BT_STATUS_NOT_READY; } - return do_in_jni_thread( + return do_in_bta_thread( FROM_HERE, base::Bind(&BtifAvSource::UpdateCodecConfig, base::Unretained(&btif_av_source), peer_address, codec_preferences)); @@ -2678,13 +2692,13 @@ static bt_status_t codec_config_src( static void cleanup_src(void) { BTIF_TRACE_EVENT("%s", __func__); - do_in_jni_thread(FROM_HERE, base::Bind(&BtifAvSource::Cleanup, + do_in_bta_thread(FROM_HERE, base::Bind(&BtifAvSource::Cleanup, base::Unretained(&btif_av_source))); } static void cleanup_sink(void) { BTIF_TRACE_EVENT("%s", __func__); - do_in_jni_thread(FROM_HERE, base::Bind(&BtifAvSink::Cleanup, + do_in_bta_thread(FROM_HERE, base::Bind(&BtifAvSink::Cleanup, base::Unretained(&btif_av_sink))); } @@ -2802,7 +2816,7 @@ static void btif_av_source_dispatch_sm_event(const RawAddress& peer_address, peer_address.ToString().c_str(), btif_av_event.ToString().c_str()); - do_in_jni_thread(FROM_HERE, + do_in_bta_thread(FROM_HERE, base::Bind(&btif_av_handle_event, AVDT_TSEP_SNK, // peer_sep peer_address, kBtaHandleUnknown, btif_av_event)); @@ -2815,7 +2829,7 @@ static void btif_av_sink_dispatch_sm_event(const RawAddress& peer_address, peer_address.ToString().c_str(), btif_av_event.ToString().c_str()); - do_in_jni_thread(FROM_HERE, + do_in_bta_thread(FROM_HERE, base::Bind(&btif_av_handle_event, AVDT_TSEP_SRC, // peer_sep peer_address, kBtaHandleUnknown, btif_av_event)); -- 2.11.0