Loading system/btif/src/btif_a2dp_source.cc +32 −33 Original line number Original line Diff line number Diff line Loading @@ -434,12 +434,10 @@ bool btif_a2dp_source_restart_session(const RawAddress& old_peer_address, } } // Start the session. // Start the session. // If audio was streaming before, start audio streaming as well. btif_a2dp_source_start_session(new_peer_address, btif_a2dp_source_start_session(new_peer_address, std::move(peer_ready_promise)); std::move(peer_ready_promise)); if (is_streaming) { // If audio was streaming before, DON'T start audio streaming, but leave the btif_a2dp_source_start_audio_req(); // control to the audio HAL. } return true; return true; } } Loading Loading @@ -707,35 +705,33 @@ void btif_a2dp_source_on_stopped(tBTA_AV_SUSPEND* p_av_suspend) { if (btif_a2dp_source_cb.State() == BtifA2dpSource::kStateOff) return; if (btif_a2dp_source_cb.State() == BtifA2dpSource::kStateOff) return; /* allow using this api for other than suspend */ // allow using this API for other (acknowledgement and stopping media task) if (p_av_suspend != nullptr) { // than suspend if (p_av_suspend->status != BTA_AV_SUCCESS) { if (p_av_suspend != nullptr && p_av_suspend->status != BTA_AV_SUCCESS) { LOG_ERROR(LOG_TAG, "%s: A2DP stop request failed: status=%d", __func__, LOG_ERROR(LOG_TAG, "%s: A2DP stop failed: status=%d, initiator=%s", p_av_suspend->status); __func__, p_av_suspend->status, (p_av_suspend->initiator ? "true" : "false")); if (p_av_suspend->initiator) { if (p_av_suspend->initiator) { LOG_WARN(LOG_TAG, "%s: A2DP stop request failed: status=%d", __func__, p_av_suspend->status); if (bluetooth::audio::a2dp::is_hal_2_0_enabled()) { if (bluetooth::audio::a2dp::is_hal_2_0_enabled()) { bluetooth::audio::a2dp::ack_stream_suspended(A2DP_CTRL_ACK_FAILURE); bluetooth::audio::a2dp::ack_stream_suspended(A2DP_CTRL_ACK_FAILURE); } else { } else { btif_a2dp_command_ack(A2DP_CTRL_ACK_FAILURE); btif_a2dp_command_ack(A2DP_CTRL_ACK_FAILURE); } } } } return; } else if (btif_av_is_a2dp_offload_enabled()) { } } if (btif_av_is_a2dp_offload_enabled()) { bluetooth::audio::a2dp::ack_stream_suspended(A2DP_CTRL_ACK_SUCCESS); bluetooth::audio::a2dp::ack_stream_suspended(A2DP_CTRL_ACK_SUCCESS); return; return; } } /* ensure tx frames are immediately suspended */ btif_a2dp_source_cb.tx_flush = true; /* request to stop media task */ // ensure tx frames are immediately suspended btif_a2dp_source_cb.tx_flush = true; // ensure tx frames are immediately flushed btif_a2dp_source_audio_tx_flush_req(); btif_a2dp_source_audio_tx_flush_req(); // request to stop media task btif_a2dp_source_stop_audio_req(); btif_a2dp_source_stop_audio_req(); /* once stream is fully stopped we will ack back */ // once software stream is fully stopped we will ack back } } void btif_a2dp_source_on_suspended(tBTA_AV_SUSPEND* p_av_suspend) { void btif_a2dp_source_on_suspended(tBTA_AV_SUSPEND* p_av_suspend) { Loading @@ -744,29 +740,32 @@ void btif_a2dp_source_on_suspended(tBTA_AV_SUSPEND* p_av_suspend) { if (btif_a2dp_source_cb.State() == BtifA2dpSource::kStateOff) return; if (btif_a2dp_source_cb.State() == BtifA2dpSource::kStateOff) return; /* check for status failures */ CHECK(p_av_suspend != nullptr) << "Suspend result could not be nullptr"; // check for status failures if (p_av_suspend->status != BTA_AV_SUCCESS) { if (p_av_suspend->status != BTA_AV_SUCCESS) { LOG_WARN(LOG_TAG, "%s: A2DP suspend failed: status=%d, initiator=%s", __func__, p_av_suspend->status, (p_av_suspend->initiator ? "true" : "false")); if (p_av_suspend->initiator) { if (p_av_suspend->initiator) { LOG_WARN(LOG_TAG, "%s: A2DP suspend request failed: status=%d", __func__, p_av_suspend->status); if (bluetooth::audio::a2dp::is_hal_2_0_enabled()) { if (bluetooth::audio::a2dp::is_hal_2_0_enabled()) { bluetooth::audio::a2dp::ack_stream_suspended(A2DP_CTRL_ACK_FAILURE); bluetooth::audio::a2dp::ack_stream_suspended(A2DP_CTRL_ACK_FAILURE); } else { } else { btif_a2dp_command_ack(A2DP_CTRL_ACK_FAILURE); btif_a2dp_command_ack(A2DP_CTRL_ACK_FAILURE); } } } } } } else if (btif_av_is_a2dp_offload_enabled()) { if (btif_av_is_a2dp_offload_enabled()) { bluetooth::audio::a2dp::ack_stream_suspended(A2DP_CTRL_ACK_SUCCESS); bluetooth::audio::a2dp::ack_stream_suspended(A2DP_CTRL_ACK_SUCCESS); return; return; } } /* once stream is fully stopped we will ack back */ /* ensure tx frames are immediately flushed */ // ensure tx frames are immediately suspended btif_a2dp_source_cb.tx_flush = true; btif_a2dp_source_cb.tx_flush = true; /* stop timer tick */ // stop timer tick btif_a2dp_source_stop_audio_req(); btif_a2dp_source_stop_audio_req(); // once software stream is fully stopped we will ack back } } /* when true media task discards any tx frames */ /* when true media task discards any tx frames */ Loading Loading @@ -853,7 +852,7 @@ static void btif_a2dp_source_audio_tx_stop_event(void) { UIPC_Close(*a2dp_uipc, UIPC_CH_ID_AV_AUDIO); UIPC_Close(*a2dp_uipc, UIPC_CH_ID_AV_AUDIO); /* /* * Try to send acknowldegment once the media stream is * Try to send acknowledgement once the media stream is * stopped. This will make sure that the A2DP HAL layer is * stopped. This will make sure that the A2DP HAL layer is * un-blocked on wait for acknowledgment for the sent command. * un-blocked on wait for acknowledgment for the sent command. * This resolves a corner cases AVDTP SUSPEND collision * This resolves a corner cases AVDTP SUSPEND collision Loading system/btif/src/btif_av.cc +43 −26 Original line number Original line Diff line number Diff line Loading @@ -1830,18 +1830,27 @@ bool BtifAvStateMachine::StateOpened::ProcessEvent(uint32_t event, // If remote tries to start A2DP when DUT is A2DP Source, then Suspend. // If remote tries to start A2DP when DUT is A2DP Source, then Suspend. // If A2DP is Sink and call is active, then disconnect the AVDTP channel. // If A2DP is Sink and call is active, then disconnect the AVDTP channel. bool should_suspend = false; bool should_suspend = false; if (peer_.IsSink() && !peer_.CheckFlags(BtifAvPeer::kFlagPendingStart | if (peer_.IsSink()) { if (!peer_.CheckFlags(BtifAvPeer::kFlagPendingStart | BtifAvPeer::kFlagRemoteSuspend)) { BtifAvPeer::kFlagRemoteSuspend)) { LOG(WARNING) << __PRETTY_FUNCTION__ << ": Peer " << peer_.PeerAddress() LOG(WARNING) << __PRETTY_FUNCTION__ << ": Peer " << peer_.PeerAddress() << " : trigger Suspend as remote initiated"; << " : trigger Suspend as remote initiated"; should_suspend = true; should_suspend = true; } else if (!peer_.IsActivePeer()) { LOG(WARNING) << __PRETTY_FUNCTION__ << ": Peer " << peer_.PeerAddress() << " : trigger Suspend as non-active"; should_suspend = true; } } // If peer is A2DP Source, do ACK commands to audio HAL and start media task // If peer is A2DP Source, do ACK commands to audio HAL and start media if (peer_.IsSink() && btif_a2dp_on_started(peer_.PeerAddress(), &p_av->start)) { // task if (btif_a2dp_on_started(peer_.PeerAddress(), &p_av->start)) { // Only clear pending flag after acknowledgement // Only clear pending flag after acknowledgement peer_.ClearFlags(BtifAvPeer::kFlagPendingStart); peer_.ClearFlags(BtifAvPeer::kFlagPendingStart); } } } // Remain in Open state if status failed // Remain in Open state if status failed if (p_av->start.status != BTA_AV_SUCCESS) return false; if (p_av->start.status != BTA_AV_SUCCESS) return false; Loading Loading @@ -1875,17 +1884,20 @@ bool BtifAvStateMachine::StateOpened::ProcessEvent(uint32_t event, case BTA_AV_CLOSE_EVT: case BTA_AV_CLOSE_EVT: // AVDTP link is closed // AVDTP link is closed if (peer_.IsActivePeer()) { btif_a2dp_on_stopped(nullptr); } // Change state to Idle, send acknowledgement if start is pending // Change state to Idle, send acknowledgement if start is pending if (peer_.CheckFlags(BtifAvPeer::kFlagPendingStart)) { if (peer_.CheckFlags(BtifAvPeer::kFlagPendingStart)) { BTIF_TRACE_WARNING("%s: Peer %s : failed pending start request", BTIF_TRACE_WARNING("%s: Peer %s : failed pending start request", __PRETTY_FUNCTION__, __PRETTY_FUNCTION__, peer_.PeerAddress().ToString().c_str()); peer_.PeerAddress().ToString().c_str()); btif_a2dp_command_ack(A2DP_CTRL_ACK_FAILURE); tBTA_AV_START av_start = {.chnl = p_av->close.chnl, .hndl = p_av->close.hndl, .status = BTA_AV_FAIL_STREAM, .initiator = true, .suspending = true}; btif_a2dp_on_started(peer_.PeerAddress(), &av_start); // Pending start flag will be cleared when exit current state // Pending start flag will be cleared when exit current state } else if (peer_.IsActivePeer()) { btif_a2dp_on_stopped(nullptr); } } // Inform the application that we are disconnected // Inform the application that we are disconnected Loading Loading @@ -2020,16 +2032,15 @@ bool BtifAvStateMachine::StateStarted::ProcessEvent(uint32_t event, // always overrides. // always overrides. peer_.ClearFlags(BtifAvPeer::kFlagRemoteSuspend); peer_.ClearFlags(BtifAvPeer::kFlagRemoteSuspend); if (peer_.IsSink()) { if (peer_.IsSink() && (peer_.IsActivePeer() || !btif_av_stream_started_ready())) { // Immediately stop transmission of frames while suspend is pending // Immediately stop transmission of frames while suspend is pending if (peer_.IsActivePeer()) { if (event == BTIF_AV_STOP_STREAM_REQ_EVT) { if (event == BTIF_AV_STOP_STREAM_REQ_EVT) { btif_a2dp_on_stopped(nullptr); btif_a2dp_on_stopped(nullptr); } else { } else { // (event == BTIF_AV_SUSPEND_STREAM_REQ_EVT) // ensure tx frames are immediately suspended btif_a2dp_source_set_tx_flush(true); btif_a2dp_source_set_tx_flush(true); } } } } else if (peer_.IsSource()) { } else if (peer_.IsSource()) { btif_a2dp_on_stopped(nullptr); btif_a2dp_on_stopped(nullptr); } } Loading Loading @@ -2064,7 +2075,9 @@ bool BtifAvStateMachine::StateStarted::ProcessEvent(uint32_t event, p_av->suspend.initiator, peer_.FlagsToString().c_str()); p_av->suspend.initiator, peer_.FlagsToString().c_str()); // A2DP suspended, stop A2DP encoder / decoder until resumed // A2DP suspended, stop A2DP encoder / decoder until resumed if (peer_.IsActivePeer() || !btif_av_stream_started_ready()) { btif_a2dp_on_suspended(&p_av->suspend); btif_a2dp_on_suspended(&p_av->suspend); } // If not successful, remain in current state // If not successful, remain in current state if (p_av->suspend.status != BTA_AV_SUCCESS) { if (p_av->suspend.status != BTA_AV_SUCCESS) { Loading Loading @@ -2106,7 +2119,11 @@ bool BtifAvStateMachine::StateStarted::ProcessEvent(uint32_t event, peer_.SetFlags(BtifAvPeer::kFlagPendingStop); peer_.SetFlags(BtifAvPeer::kFlagPendingStop); peer_.ClearFlags(BtifAvPeer::kFlagLocalSuspendPending); peer_.ClearFlags(BtifAvPeer::kFlagLocalSuspendPending); // Don't change the encoder and audio provider state by a non-active peer // since they are shared between peers if (peer_.IsActivePeer() || !btif_av_stream_started_ready()) { btif_a2dp_on_stopped(&p_av->suspend); btif_a2dp_on_stopped(&p_av->suspend); } btif_report_audio_state(peer_.PeerAddress(), BTAV_AUDIO_STATE_STOPPED); btif_report_audio_state(peer_.PeerAddress(), BTAV_AUDIO_STATE_STOPPED); Loading Loading
system/btif/src/btif_a2dp_source.cc +32 −33 Original line number Original line Diff line number Diff line Loading @@ -434,12 +434,10 @@ bool btif_a2dp_source_restart_session(const RawAddress& old_peer_address, } } // Start the session. // Start the session. // If audio was streaming before, start audio streaming as well. btif_a2dp_source_start_session(new_peer_address, btif_a2dp_source_start_session(new_peer_address, std::move(peer_ready_promise)); std::move(peer_ready_promise)); if (is_streaming) { // If audio was streaming before, DON'T start audio streaming, but leave the btif_a2dp_source_start_audio_req(); // control to the audio HAL. } return true; return true; } } Loading Loading @@ -707,35 +705,33 @@ void btif_a2dp_source_on_stopped(tBTA_AV_SUSPEND* p_av_suspend) { if (btif_a2dp_source_cb.State() == BtifA2dpSource::kStateOff) return; if (btif_a2dp_source_cb.State() == BtifA2dpSource::kStateOff) return; /* allow using this api for other than suspend */ // allow using this API for other (acknowledgement and stopping media task) if (p_av_suspend != nullptr) { // than suspend if (p_av_suspend->status != BTA_AV_SUCCESS) { if (p_av_suspend != nullptr && p_av_suspend->status != BTA_AV_SUCCESS) { LOG_ERROR(LOG_TAG, "%s: A2DP stop request failed: status=%d", __func__, LOG_ERROR(LOG_TAG, "%s: A2DP stop failed: status=%d, initiator=%s", p_av_suspend->status); __func__, p_av_suspend->status, (p_av_suspend->initiator ? "true" : "false")); if (p_av_suspend->initiator) { if (p_av_suspend->initiator) { LOG_WARN(LOG_TAG, "%s: A2DP stop request failed: status=%d", __func__, p_av_suspend->status); if (bluetooth::audio::a2dp::is_hal_2_0_enabled()) { if (bluetooth::audio::a2dp::is_hal_2_0_enabled()) { bluetooth::audio::a2dp::ack_stream_suspended(A2DP_CTRL_ACK_FAILURE); bluetooth::audio::a2dp::ack_stream_suspended(A2DP_CTRL_ACK_FAILURE); } else { } else { btif_a2dp_command_ack(A2DP_CTRL_ACK_FAILURE); btif_a2dp_command_ack(A2DP_CTRL_ACK_FAILURE); } } } } return; } else if (btif_av_is_a2dp_offload_enabled()) { } } if (btif_av_is_a2dp_offload_enabled()) { bluetooth::audio::a2dp::ack_stream_suspended(A2DP_CTRL_ACK_SUCCESS); bluetooth::audio::a2dp::ack_stream_suspended(A2DP_CTRL_ACK_SUCCESS); return; return; } } /* ensure tx frames are immediately suspended */ btif_a2dp_source_cb.tx_flush = true; /* request to stop media task */ // ensure tx frames are immediately suspended btif_a2dp_source_cb.tx_flush = true; // ensure tx frames are immediately flushed btif_a2dp_source_audio_tx_flush_req(); btif_a2dp_source_audio_tx_flush_req(); // request to stop media task btif_a2dp_source_stop_audio_req(); btif_a2dp_source_stop_audio_req(); /* once stream is fully stopped we will ack back */ // once software stream is fully stopped we will ack back } } void btif_a2dp_source_on_suspended(tBTA_AV_SUSPEND* p_av_suspend) { void btif_a2dp_source_on_suspended(tBTA_AV_SUSPEND* p_av_suspend) { Loading @@ -744,29 +740,32 @@ void btif_a2dp_source_on_suspended(tBTA_AV_SUSPEND* p_av_suspend) { if (btif_a2dp_source_cb.State() == BtifA2dpSource::kStateOff) return; if (btif_a2dp_source_cb.State() == BtifA2dpSource::kStateOff) return; /* check for status failures */ CHECK(p_av_suspend != nullptr) << "Suspend result could not be nullptr"; // check for status failures if (p_av_suspend->status != BTA_AV_SUCCESS) { if (p_av_suspend->status != BTA_AV_SUCCESS) { LOG_WARN(LOG_TAG, "%s: A2DP suspend failed: status=%d, initiator=%s", __func__, p_av_suspend->status, (p_av_suspend->initiator ? "true" : "false")); if (p_av_suspend->initiator) { if (p_av_suspend->initiator) { LOG_WARN(LOG_TAG, "%s: A2DP suspend request failed: status=%d", __func__, p_av_suspend->status); if (bluetooth::audio::a2dp::is_hal_2_0_enabled()) { if (bluetooth::audio::a2dp::is_hal_2_0_enabled()) { bluetooth::audio::a2dp::ack_stream_suspended(A2DP_CTRL_ACK_FAILURE); bluetooth::audio::a2dp::ack_stream_suspended(A2DP_CTRL_ACK_FAILURE); } else { } else { btif_a2dp_command_ack(A2DP_CTRL_ACK_FAILURE); btif_a2dp_command_ack(A2DP_CTRL_ACK_FAILURE); } } } } } } else if (btif_av_is_a2dp_offload_enabled()) { if (btif_av_is_a2dp_offload_enabled()) { bluetooth::audio::a2dp::ack_stream_suspended(A2DP_CTRL_ACK_SUCCESS); bluetooth::audio::a2dp::ack_stream_suspended(A2DP_CTRL_ACK_SUCCESS); return; return; } } /* once stream is fully stopped we will ack back */ /* ensure tx frames are immediately flushed */ // ensure tx frames are immediately suspended btif_a2dp_source_cb.tx_flush = true; btif_a2dp_source_cb.tx_flush = true; /* stop timer tick */ // stop timer tick btif_a2dp_source_stop_audio_req(); btif_a2dp_source_stop_audio_req(); // once software stream is fully stopped we will ack back } } /* when true media task discards any tx frames */ /* when true media task discards any tx frames */ Loading Loading @@ -853,7 +852,7 @@ static void btif_a2dp_source_audio_tx_stop_event(void) { UIPC_Close(*a2dp_uipc, UIPC_CH_ID_AV_AUDIO); UIPC_Close(*a2dp_uipc, UIPC_CH_ID_AV_AUDIO); /* /* * Try to send acknowldegment once the media stream is * Try to send acknowledgement once the media stream is * stopped. This will make sure that the A2DP HAL layer is * stopped. This will make sure that the A2DP HAL layer is * un-blocked on wait for acknowledgment for the sent command. * un-blocked on wait for acknowledgment for the sent command. * This resolves a corner cases AVDTP SUSPEND collision * This resolves a corner cases AVDTP SUSPEND collision Loading
system/btif/src/btif_av.cc +43 −26 Original line number Original line Diff line number Diff line Loading @@ -1830,18 +1830,27 @@ bool BtifAvStateMachine::StateOpened::ProcessEvent(uint32_t event, // If remote tries to start A2DP when DUT is A2DP Source, then Suspend. // If remote tries to start A2DP when DUT is A2DP Source, then Suspend. // If A2DP is Sink and call is active, then disconnect the AVDTP channel. // If A2DP is Sink and call is active, then disconnect the AVDTP channel. bool should_suspend = false; bool should_suspend = false; if (peer_.IsSink() && !peer_.CheckFlags(BtifAvPeer::kFlagPendingStart | if (peer_.IsSink()) { if (!peer_.CheckFlags(BtifAvPeer::kFlagPendingStart | BtifAvPeer::kFlagRemoteSuspend)) { BtifAvPeer::kFlagRemoteSuspend)) { LOG(WARNING) << __PRETTY_FUNCTION__ << ": Peer " << peer_.PeerAddress() LOG(WARNING) << __PRETTY_FUNCTION__ << ": Peer " << peer_.PeerAddress() << " : trigger Suspend as remote initiated"; << " : trigger Suspend as remote initiated"; should_suspend = true; should_suspend = true; } else if (!peer_.IsActivePeer()) { LOG(WARNING) << __PRETTY_FUNCTION__ << ": Peer " << peer_.PeerAddress() << " : trigger Suspend as non-active"; should_suspend = true; } } // If peer is A2DP Source, do ACK commands to audio HAL and start media task // If peer is A2DP Source, do ACK commands to audio HAL and start media if (peer_.IsSink() && btif_a2dp_on_started(peer_.PeerAddress(), &p_av->start)) { // task if (btif_a2dp_on_started(peer_.PeerAddress(), &p_av->start)) { // Only clear pending flag after acknowledgement // Only clear pending flag after acknowledgement peer_.ClearFlags(BtifAvPeer::kFlagPendingStart); peer_.ClearFlags(BtifAvPeer::kFlagPendingStart); } } } // Remain in Open state if status failed // Remain in Open state if status failed if (p_av->start.status != BTA_AV_SUCCESS) return false; if (p_av->start.status != BTA_AV_SUCCESS) return false; Loading Loading @@ -1875,17 +1884,20 @@ bool BtifAvStateMachine::StateOpened::ProcessEvent(uint32_t event, case BTA_AV_CLOSE_EVT: case BTA_AV_CLOSE_EVT: // AVDTP link is closed // AVDTP link is closed if (peer_.IsActivePeer()) { btif_a2dp_on_stopped(nullptr); } // Change state to Idle, send acknowledgement if start is pending // Change state to Idle, send acknowledgement if start is pending if (peer_.CheckFlags(BtifAvPeer::kFlagPendingStart)) { if (peer_.CheckFlags(BtifAvPeer::kFlagPendingStart)) { BTIF_TRACE_WARNING("%s: Peer %s : failed pending start request", BTIF_TRACE_WARNING("%s: Peer %s : failed pending start request", __PRETTY_FUNCTION__, __PRETTY_FUNCTION__, peer_.PeerAddress().ToString().c_str()); peer_.PeerAddress().ToString().c_str()); btif_a2dp_command_ack(A2DP_CTRL_ACK_FAILURE); tBTA_AV_START av_start = {.chnl = p_av->close.chnl, .hndl = p_av->close.hndl, .status = BTA_AV_FAIL_STREAM, .initiator = true, .suspending = true}; btif_a2dp_on_started(peer_.PeerAddress(), &av_start); // Pending start flag will be cleared when exit current state // Pending start flag will be cleared when exit current state } else if (peer_.IsActivePeer()) { btif_a2dp_on_stopped(nullptr); } } // Inform the application that we are disconnected // Inform the application that we are disconnected Loading Loading @@ -2020,16 +2032,15 @@ bool BtifAvStateMachine::StateStarted::ProcessEvent(uint32_t event, // always overrides. // always overrides. peer_.ClearFlags(BtifAvPeer::kFlagRemoteSuspend); peer_.ClearFlags(BtifAvPeer::kFlagRemoteSuspend); if (peer_.IsSink()) { if (peer_.IsSink() && (peer_.IsActivePeer() || !btif_av_stream_started_ready())) { // Immediately stop transmission of frames while suspend is pending // Immediately stop transmission of frames while suspend is pending if (peer_.IsActivePeer()) { if (event == BTIF_AV_STOP_STREAM_REQ_EVT) { if (event == BTIF_AV_STOP_STREAM_REQ_EVT) { btif_a2dp_on_stopped(nullptr); btif_a2dp_on_stopped(nullptr); } else { } else { // (event == BTIF_AV_SUSPEND_STREAM_REQ_EVT) // ensure tx frames are immediately suspended btif_a2dp_source_set_tx_flush(true); btif_a2dp_source_set_tx_flush(true); } } } } else if (peer_.IsSource()) { } else if (peer_.IsSource()) { btif_a2dp_on_stopped(nullptr); btif_a2dp_on_stopped(nullptr); } } Loading Loading @@ -2064,7 +2075,9 @@ bool BtifAvStateMachine::StateStarted::ProcessEvent(uint32_t event, p_av->suspend.initiator, peer_.FlagsToString().c_str()); p_av->suspend.initiator, peer_.FlagsToString().c_str()); // A2DP suspended, stop A2DP encoder / decoder until resumed // A2DP suspended, stop A2DP encoder / decoder until resumed if (peer_.IsActivePeer() || !btif_av_stream_started_ready()) { btif_a2dp_on_suspended(&p_av->suspend); btif_a2dp_on_suspended(&p_av->suspend); } // If not successful, remain in current state // If not successful, remain in current state if (p_av->suspend.status != BTA_AV_SUCCESS) { if (p_av->suspend.status != BTA_AV_SUCCESS) { Loading Loading @@ -2106,7 +2119,11 @@ bool BtifAvStateMachine::StateStarted::ProcessEvent(uint32_t event, peer_.SetFlags(BtifAvPeer::kFlagPendingStop); peer_.SetFlags(BtifAvPeer::kFlagPendingStop); peer_.ClearFlags(BtifAvPeer::kFlagLocalSuspendPending); peer_.ClearFlags(BtifAvPeer::kFlagLocalSuspendPending); // Don't change the encoder and audio provider state by a non-active peer // since they are shared between peers if (peer_.IsActivePeer() || !btif_av_stream_started_ready()) { btif_a2dp_on_stopped(&p_av->suspend); btif_a2dp_on_stopped(&p_av->suspend); } btif_report_audio_state(peer_.PeerAddress(), BTAV_AUDIO_STATE_STOPPED); btif_report_audio_state(peer_.PeerAddress(), BTAV_AUDIO_STATE_STOPPED); Loading