Loading system/btif/src/btif_av.cc +158 −6 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ #include <cstdint> #include <future> #include <mutex> #include <optional> #include <string> #include <vector> Loading Loading @@ -102,6 +103,11 @@ typedef struct { bool is_low_latency; } btif_av_set_latency_req_t; typedef struct { std::vector<btav_a2dp_codec_config_t> codec_preferences; std::promise<void> reconf_ready_promise; } btif_av_reconfig_req_t; /** * BTIF AV events */ Loading @@ -119,6 +125,7 @@ typedef enum { BTIF_AV_AVRCP_CLOSE_EVT, BTIF_AV_AVRCP_REMOTE_PLAY_EVT, BTIF_AV_SET_LATENCY_REQ_EVT, BTIF_AV_RECONFIGURE_REQ_EVT, } btif_av_sm_event_t; class BtifAvEvent { Loading Loading @@ -251,6 +258,7 @@ public: kFlagRemoteSuspend = 0x2, kFlagPendingStart = 0x4, kFlagPendingStop = 0x8, kFlagPendingReconfigure = 0x10, }; static constexpr uint64_t kTimeoutAvOpenOnRcMs = 2 * 1000; // 2s Loading Loading @@ -360,6 +368,16 @@ public: bool UseLatencyMode() const { return use_latency_mode_; } void SetUseLatencyMode(bool use_latency_mode) { use_latency_mode_ = use_latency_mode; } void SetReconfigureStreamData(btif_av_reconfig_req_t&& req) { reconfig_req_ = std::make_optional<btif_av_reconfig_req_t>(std::move(req)); } std::optional<btif_av_reconfig_req_t> GetReconfigureStreamData() { std::optional<btif_av_reconfig_req_t> data = std::move(reconfig_req_); reconfig_req_ = std::nullopt; return data; } private: const RawAddress peer_address_; uint8_t peer_sep_; // SEP type of peer device Loading @@ -374,6 +392,7 @@ private: uint16_t delay_report_; bool mandatory_codec_preferred_ = false; bool use_latency_mode_ = false; std::optional<btif_av_reconfig_req_t> reconfig_req_; }; class BtifAvSource { Loading Loading @@ -593,6 +612,33 @@ public: */ void DispatchSuspendStreamEvent(btif_av_sm_event_t event); /** * Set peer reconfigure stream data. * * @param peer_address the peer address to reconfigure stream * @param codec_preferences codec preferences for stream reconfiguration * @param reconf_ready_promise promise fulfilled when the reconfiguration done */ bt_status_t SetPeerReconfigureStreamData(const RawAddress& peer_address, std::vector<btav_a2dp_codec_config_t> codec_preferences, std::promise<void> reconf_ready_promise) { std::lock_guard<std::recursive_mutex> lock(btifavsource_peers_lock_); BtifAvPeer* peer = FindPeer(peer_address); if (peer == nullptr) { log::error("Can not find peer: {}", peer_address.ToString()); return BT_STATUS_NOT_READY; } btif_av_reconfig_req_t reconf_stream_req = { .codec_preferences = codec_preferences, .reconf_ready_promise = std::move(reconf_ready_promise), }; peer->SetReconfigureStreamData(std::move(reconf_stream_req)); return BT_STATUS_SUCCESS; } void DumpPeersInfo(int fd); void RegisterAllBtaHandles(); void DeregisterAllBtaHandles(); Loading Loading @@ -965,6 +1011,7 @@ const char* dump_av_sm_event_name(btif_av_sm_event_t event) { CASE_RETURN_STR(BTIF_AV_AVRCP_CLOSE_EVT) CASE_RETURN_STR(BTIF_AV_AVRCP_REMOTE_PLAY_EVT) CASE_RETURN_STR(BTIF_AV_SET_LATENCY_REQ_EVT) CASE_RETURN_STR(BTIF_AV_RECONFIGURE_REQ_EVT) default: return "UNKNOWN_EVENT"; } Loading Loading @@ -1120,6 +1167,12 @@ std::string BtifAvPeer::FlagsToString() const { } result += "PENDING_STOP"; } if (flags_ & BtifAvPeer::kFlagPendingReconfigure) { if (!result.empty()) { result += "|"; } result += "PENDING_RECONFIGURE"; } if (result.empty()) { result = "None"; } Loading Loading @@ -2057,6 +2110,15 @@ bool BtifAvStateMachine::StateIdle::ProcessEvent(uint32_t event, void* p_data) { btif_a2dp_on_offload_started(peer_.PeerAddress(), BTA_AV_FAIL); break; case BTIF_AV_RECONFIGURE_REQ_EVT: { // Unlock JNI thread only auto req_data = peer_.GetReconfigureStreamData(); if (req_data) { req_data.value().reconf_ready_promise.set_value(); } break; } default: log::warn("Peer {} : Unhandled event={}", peer_.PeerAddress(), BtifAvEvent::EventName(event)); return false; Loading Loading @@ -2318,6 +2380,15 @@ bool BtifAvStateMachine::StateOpening::ProcessEvent(uint32_t event, void* p_data } break; case BTIF_AV_RECONFIGURE_REQ_EVT: { // Unlock JNI thread only auto req_data = peer_.GetReconfigureStreamData(); if (req_data) { req_data.value().reconf_ready_promise.set_value(); } break; } CHECK_RC_EVENT(event, reinterpret_cast<tBTA_AV*>(p_data)); default: Loading Loading @@ -2439,6 +2510,16 @@ bool BtifAvStateMachine::StateOpened::ProcessEvent(uint32_t event, void* p_data) if (should_suspend) { btif_av_source_dispatch_sm_event(peer_.PeerAddress(), BTIF_AV_SUSPEND_STREAM_REQ_EVT); } if (com::android::bluetooth::flags::av_stream_reconfigure_fix() && peer_.CheckFlags(BtifAvPeer::kFlagPendingReconfigure)) { log::info( "Peer {} : Stream started but reconfiguration pending. " "Reconfiguring stream", peer_.PeerAddress()); btif_av_source_dispatch_sm_event(peer_.PeerAddress(), BTIF_AV_RECONFIGURE_REQ_EVT); } peer_.StateMachine().TransitionTo(BtifAvStateMachine::kStateStarted); break; } Loading Loading @@ -2548,6 +2629,33 @@ bool BtifAvStateMachine::StateOpened::ProcessEvent(uint32_t event, void* p_data) BTA_AvSetLatency(peer_.BtaHandle(), p_set_latency_req->is_low_latency); } break; case BTIF_AV_RECONFIGURE_REQ_EVT: { log::info("Peer {} : event={} flags={}", peer_.PeerAddress(), BtifAvEvent::EventName(event), peer_.FlagsToString()); if (!peer_.IsSink()) { log::verbose("Peer {} is not sink", peer_.PeerAddress()); break; } if (peer_.CheckFlags(BtifAvPeer::kFlagPendingStart)) { // The start stream request was sent but we wait for response. // Enable the reconfigure pending flag to schedule reconfiguration // after start stream response. peer_.SetFlags(BtifAvPeer::kFlagPendingReconfigure); } else { // Reconfigure peer_.ClearFlags(BtifAvPeer::kFlagPendingReconfigure); if (btif_av_source.Enabled()) { auto req_data = peer_.GetReconfigureStreamData(); if (req_data) { btif_av_source.UpdateCodecConfig(peer_.PeerAddress(), req_data.value().codec_preferences, std::move(req_data.value().reconf_ready_promise)); } } } } break; default: log::warn("Peer {} : Unhandled event={}", peer_.PeerAddress(), BtifAvEvent::EventName(event)); return false; Loading Loading @@ -2764,6 +2872,19 @@ bool BtifAvStateMachine::StateStarted::ProcessEvent(uint32_t event, void* p_data CHECK_RC_EVENT(event, reinterpret_cast<tBTA_AV*>(p_data)); case BTIF_AV_RECONFIGURE_REQ_EVT: { log::info("Peer {} : event={} flags={}", peer_.PeerAddress(), BtifAvEvent::EventName(event), peer_.FlagsToString()); peer_.ClearFlags(BtifAvPeer::kFlagPendingReconfigure); if (btif_av_source.Enabled()) { auto req_data = peer_.GetReconfigureStreamData(); if (req_data) { btif_av_source.UpdateCodecConfig(peer_.PeerAddress(), req_data.value().codec_preferences, std::move(req_data.value().reconf_ready_promise)); } } } break; default: log::warn("Peer {} : Unhandled event={}", peer_.PeerAddress(), BtifAvEvent::EventName(event)); return false; Loading Loading @@ -2838,6 +2959,15 @@ bool BtifAvStateMachine::StateClosing::ProcessEvent(uint32_t event, void* p_data peer_.StateMachine().TransitionTo(BtifAvStateMachine::kStateIdle); break; case BTIF_AV_RECONFIGURE_REQ_EVT: { // Unlock JNI thread only auto req_data = peer_.GetReconfigureStreamData(); if (req_data) { req_data.value().reconf_ready_promise.set_value(); } break; } default: log::warn("Peer {} : Unhandled event={}", peer_.PeerAddress(), BtifAvEvent::EventName(event)); return false; Loading Loading @@ -3688,14 +3818,36 @@ bt_status_t btif_av_source_set_codec_config_preference( std::promise<void> peer_ready_promise; std::future<void> peer_ready_future = peer_ready_promise.get_future(); bt_status_t status = do_in_main_thread( base::BindOnce(&BtifAvSource::UpdateCodecConfig, base::Unretained(&btif_av_source), peer_address, codec_preferences, std::move(peer_ready_promise))); if (status == BT_STATUS_SUCCESS) { peer_ready_future.wait(); bt_status_t status = BT_STATUS_FAIL; if (com::android::bluetooth::flags::av_stream_reconfigure_fix()) { status = btif_av_source.SetPeerReconfigureStreamData(peer_address, codec_preferences, std::move(peer_ready_promise)); if (status != BT_STATUS_SUCCESS) { log::error("SetPeerReconfigureStreamData failed, status: {}", status); return status; } BtifAvEvent btif_av_event(BTIF_AV_RECONFIGURE_REQ_EVT, nullptr, 0); status = do_in_main_thread(base::BindOnce(&btif_av_handle_event, AVDT_TSEP_SNK, // peer_sep peer_address, kBtaHandleUnknown, btif_av_event)); } else { log::warn("BTIF AV Source fails to config codec"); status = do_in_main_thread(base::BindOnce(&BtifAvSource::UpdateCodecConfig, base::Unretained(&btif_av_source), peer_address, codec_preferences, std::move(peer_ready_promise))); } if (status != BT_STATUS_SUCCESS) { log::error("do_in_main_thread failed, status: {}", status); return status; } if (peer_ready_future.wait_for(std::chrono::seconds(10)) != std::future_status::ready) { log::error("BTIF AV Source fails to config codec"); return BT_STATUS_FAIL; } return status; } Loading Loading
system/btif/src/btif_av.cc +158 −6 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ #include <cstdint> #include <future> #include <mutex> #include <optional> #include <string> #include <vector> Loading Loading @@ -102,6 +103,11 @@ typedef struct { bool is_low_latency; } btif_av_set_latency_req_t; typedef struct { std::vector<btav_a2dp_codec_config_t> codec_preferences; std::promise<void> reconf_ready_promise; } btif_av_reconfig_req_t; /** * BTIF AV events */ Loading @@ -119,6 +125,7 @@ typedef enum { BTIF_AV_AVRCP_CLOSE_EVT, BTIF_AV_AVRCP_REMOTE_PLAY_EVT, BTIF_AV_SET_LATENCY_REQ_EVT, BTIF_AV_RECONFIGURE_REQ_EVT, } btif_av_sm_event_t; class BtifAvEvent { Loading Loading @@ -251,6 +258,7 @@ public: kFlagRemoteSuspend = 0x2, kFlagPendingStart = 0x4, kFlagPendingStop = 0x8, kFlagPendingReconfigure = 0x10, }; static constexpr uint64_t kTimeoutAvOpenOnRcMs = 2 * 1000; // 2s Loading Loading @@ -360,6 +368,16 @@ public: bool UseLatencyMode() const { return use_latency_mode_; } void SetUseLatencyMode(bool use_latency_mode) { use_latency_mode_ = use_latency_mode; } void SetReconfigureStreamData(btif_av_reconfig_req_t&& req) { reconfig_req_ = std::make_optional<btif_av_reconfig_req_t>(std::move(req)); } std::optional<btif_av_reconfig_req_t> GetReconfigureStreamData() { std::optional<btif_av_reconfig_req_t> data = std::move(reconfig_req_); reconfig_req_ = std::nullopt; return data; } private: const RawAddress peer_address_; uint8_t peer_sep_; // SEP type of peer device Loading @@ -374,6 +392,7 @@ private: uint16_t delay_report_; bool mandatory_codec_preferred_ = false; bool use_latency_mode_ = false; std::optional<btif_av_reconfig_req_t> reconfig_req_; }; class BtifAvSource { Loading Loading @@ -593,6 +612,33 @@ public: */ void DispatchSuspendStreamEvent(btif_av_sm_event_t event); /** * Set peer reconfigure stream data. * * @param peer_address the peer address to reconfigure stream * @param codec_preferences codec preferences for stream reconfiguration * @param reconf_ready_promise promise fulfilled when the reconfiguration done */ bt_status_t SetPeerReconfigureStreamData(const RawAddress& peer_address, std::vector<btav_a2dp_codec_config_t> codec_preferences, std::promise<void> reconf_ready_promise) { std::lock_guard<std::recursive_mutex> lock(btifavsource_peers_lock_); BtifAvPeer* peer = FindPeer(peer_address); if (peer == nullptr) { log::error("Can not find peer: {}", peer_address.ToString()); return BT_STATUS_NOT_READY; } btif_av_reconfig_req_t reconf_stream_req = { .codec_preferences = codec_preferences, .reconf_ready_promise = std::move(reconf_ready_promise), }; peer->SetReconfigureStreamData(std::move(reconf_stream_req)); return BT_STATUS_SUCCESS; } void DumpPeersInfo(int fd); void RegisterAllBtaHandles(); void DeregisterAllBtaHandles(); Loading Loading @@ -965,6 +1011,7 @@ const char* dump_av_sm_event_name(btif_av_sm_event_t event) { CASE_RETURN_STR(BTIF_AV_AVRCP_CLOSE_EVT) CASE_RETURN_STR(BTIF_AV_AVRCP_REMOTE_PLAY_EVT) CASE_RETURN_STR(BTIF_AV_SET_LATENCY_REQ_EVT) CASE_RETURN_STR(BTIF_AV_RECONFIGURE_REQ_EVT) default: return "UNKNOWN_EVENT"; } Loading Loading @@ -1120,6 +1167,12 @@ std::string BtifAvPeer::FlagsToString() const { } result += "PENDING_STOP"; } if (flags_ & BtifAvPeer::kFlagPendingReconfigure) { if (!result.empty()) { result += "|"; } result += "PENDING_RECONFIGURE"; } if (result.empty()) { result = "None"; } Loading Loading @@ -2057,6 +2110,15 @@ bool BtifAvStateMachine::StateIdle::ProcessEvent(uint32_t event, void* p_data) { btif_a2dp_on_offload_started(peer_.PeerAddress(), BTA_AV_FAIL); break; case BTIF_AV_RECONFIGURE_REQ_EVT: { // Unlock JNI thread only auto req_data = peer_.GetReconfigureStreamData(); if (req_data) { req_data.value().reconf_ready_promise.set_value(); } break; } default: log::warn("Peer {} : Unhandled event={}", peer_.PeerAddress(), BtifAvEvent::EventName(event)); return false; Loading Loading @@ -2318,6 +2380,15 @@ bool BtifAvStateMachine::StateOpening::ProcessEvent(uint32_t event, void* p_data } break; case BTIF_AV_RECONFIGURE_REQ_EVT: { // Unlock JNI thread only auto req_data = peer_.GetReconfigureStreamData(); if (req_data) { req_data.value().reconf_ready_promise.set_value(); } break; } CHECK_RC_EVENT(event, reinterpret_cast<tBTA_AV*>(p_data)); default: Loading Loading @@ -2439,6 +2510,16 @@ bool BtifAvStateMachine::StateOpened::ProcessEvent(uint32_t event, void* p_data) if (should_suspend) { btif_av_source_dispatch_sm_event(peer_.PeerAddress(), BTIF_AV_SUSPEND_STREAM_REQ_EVT); } if (com::android::bluetooth::flags::av_stream_reconfigure_fix() && peer_.CheckFlags(BtifAvPeer::kFlagPendingReconfigure)) { log::info( "Peer {} : Stream started but reconfiguration pending. " "Reconfiguring stream", peer_.PeerAddress()); btif_av_source_dispatch_sm_event(peer_.PeerAddress(), BTIF_AV_RECONFIGURE_REQ_EVT); } peer_.StateMachine().TransitionTo(BtifAvStateMachine::kStateStarted); break; } Loading Loading @@ -2548,6 +2629,33 @@ bool BtifAvStateMachine::StateOpened::ProcessEvent(uint32_t event, void* p_data) BTA_AvSetLatency(peer_.BtaHandle(), p_set_latency_req->is_low_latency); } break; case BTIF_AV_RECONFIGURE_REQ_EVT: { log::info("Peer {} : event={} flags={}", peer_.PeerAddress(), BtifAvEvent::EventName(event), peer_.FlagsToString()); if (!peer_.IsSink()) { log::verbose("Peer {} is not sink", peer_.PeerAddress()); break; } if (peer_.CheckFlags(BtifAvPeer::kFlagPendingStart)) { // The start stream request was sent but we wait for response. // Enable the reconfigure pending flag to schedule reconfiguration // after start stream response. peer_.SetFlags(BtifAvPeer::kFlagPendingReconfigure); } else { // Reconfigure peer_.ClearFlags(BtifAvPeer::kFlagPendingReconfigure); if (btif_av_source.Enabled()) { auto req_data = peer_.GetReconfigureStreamData(); if (req_data) { btif_av_source.UpdateCodecConfig(peer_.PeerAddress(), req_data.value().codec_preferences, std::move(req_data.value().reconf_ready_promise)); } } } } break; default: log::warn("Peer {} : Unhandled event={}", peer_.PeerAddress(), BtifAvEvent::EventName(event)); return false; Loading Loading @@ -2764,6 +2872,19 @@ bool BtifAvStateMachine::StateStarted::ProcessEvent(uint32_t event, void* p_data CHECK_RC_EVENT(event, reinterpret_cast<tBTA_AV*>(p_data)); case BTIF_AV_RECONFIGURE_REQ_EVT: { log::info("Peer {} : event={} flags={}", peer_.PeerAddress(), BtifAvEvent::EventName(event), peer_.FlagsToString()); peer_.ClearFlags(BtifAvPeer::kFlagPendingReconfigure); if (btif_av_source.Enabled()) { auto req_data = peer_.GetReconfigureStreamData(); if (req_data) { btif_av_source.UpdateCodecConfig(peer_.PeerAddress(), req_data.value().codec_preferences, std::move(req_data.value().reconf_ready_promise)); } } } break; default: log::warn("Peer {} : Unhandled event={}", peer_.PeerAddress(), BtifAvEvent::EventName(event)); return false; Loading Loading @@ -2838,6 +2959,15 @@ bool BtifAvStateMachine::StateClosing::ProcessEvent(uint32_t event, void* p_data peer_.StateMachine().TransitionTo(BtifAvStateMachine::kStateIdle); break; case BTIF_AV_RECONFIGURE_REQ_EVT: { // Unlock JNI thread only auto req_data = peer_.GetReconfigureStreamData(); if (req_data) { req_data.value().reconf_ready_promise.set_value(); } break; } default: log::warn("Peer {} : Unhandled event={}", peer_.PeerAddress(), BtifAvEvent::EventName(event)); return false; Loading Loading @@ -3688,14 +3818,36 @@ bt_status_t btif_av_source_set_codec_config_preference( std::promise<void> peer_ready_promise; std::future<void> peer_ready_future = peer_ready_promise.get_future(); bt_status_t status = do_in_main_thread( base::BindOnce(&BtifAvSource::UpdateCodecConfig, base::Unretained(&btif_av_source), peer_address, codec_preferences, std::move(peer_ready_promise))); if (status == BT_STATUS_SUCCESS) { peer_ready_future.wait(); bt_status_t status = BT_STATUS_FAIL; if (com::android::bluetooth::flags::av_stream_reconfigure_fix()) { status = btif_av_source.SetPeerReconfigureStreamData(peer_address, codec_preferences, std::move(peer_ready_promise)); if (status != BT_STATUS_SUCCESS) { log::error("SetPeerReconfigureStreamData failed, status: {}", status); return status; } BtifAvEvent btif_av_event(BTIF_AV_RECONFIGURE_REQ_EVT, nullptr, 0); status = do_in_main_thread(base::BindOnce(&btif_av_handle_event, AVDT_TSEP_SNK, // peer_sep peer_address, kBtaHandleUnknown, btif_av_event)); } else { log::warn("BTIF AV Source fails to config codec"); status = do_in_main_thread(base::BindOnce(&BtifAvSource::UpdateCodecConfig, base::Unretained(&btif_av_source), peer_address, codec_preferences, std::move(peer_ready_promise))); } if (status != BT_STATUS_SUCCESS) { log::error("do_in_main_thread failed, status: {}", status); return status; } if (peer_ready_future.wait_for(std::chrono::seconds(10)) != std::future_status::ready) { log::error("BTIF AV Source fails to config codec"); return BT_STATUS_FAIL; } return status; } Loading