Loading system/audio_hal_interface/aidl/client_interface_aidl.cc +27 −9 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ #include "client_interface_aidl.h" #include <android/binder_manager.h> #include <android_bluetooth_flags.h> namespace bluetooth { namespace audio { Loading Loading @@ -155,8 +156,8 @@ BluetoothAudioSinkClientInterface::BluetoothAudioSinkClientInterface( BluetoothAudioSinkClientInterface::~BluetoothAudioSinkClientInterface() { if (provider_factory_ != nullptr) { AIBinder_unlinkToDeath(provider_factory_->asBinder().get(), death_recipient_.get(), nullptr); AIBinder_unlinkToDeath(provider_factory_->asBinder().get(), death_recipient_.get(), nullptr); } } Loading @@ -169,8 +170,8 @@ BluetoothAudioSourceClientInterface::BluetoothAudioSourceClientInterface( BluetoothAudioSourceClientInterface::~BluetoothAudioSourceClientInterface() { if (provider_factory_ != nullptr) { AIBinder_unlinkToDeath(provider_factory_->asBinder().get(), death_recipient_.get(), nullptr); AIBinder_unlinkToDeath(provider_factory_->asBinder().get(), death_recipient_.get(), nullptr); } } Loading @@ -196,7 +197,12 @@ bool BluetoothAudioClientInterface::UpdateAudioConfig( transport_->GetSessionType() == SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH || transport_->GetSessionType() == SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH); SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH || (IS_FLAG_ENABLED(is_sco_managed_by_audio) && (transport_->GetSessionType() == SessionType::HFP_SOFTWARE_ENCODING_DATAPATH || transport_->GetSessionType() == SessionType::HFP_SOFTWARE_DECODING_DATAPATH))); bool is_a2dp_offload_session = (transport_->GetSessionType() == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH); Loading @@ -221,9 +227,15 @@ bool BluetoothAudioClientInterface::UpdateAudioConfig( bool is_leaudio_broadcast_offload_audio_config = (is_leaudio_broadcast_offload_session && audio_config_tag == AudioConfiguration::leAudioBroadcastConfig); bool is_hfp_offload_audio_config = (IS_FLAG_ENABLED(is_sco_managed_by_audio) && transport_->GetSessionType() == SessionType::HFP_HARDWARE_OFFLOAD_DATAPATH && audio_config_tag == AudioConfiguration::hfpConfig); if (!is_software_audio_config && !is_a2dp_offload_audio_config && !is_leaudio_unicast_offload_audio_config && !is_leaudio_broadcast_offload_audio_config) { !is_leaudio_broadcast_offload_audio_config && !is_hfp_offload_audio_config) { return false; } transport_->UpdateAudioConfiguration(audio_config); Loading Loading @@ -315,7 +327,10 @@ int BluetoothAudioClientInterface::StartSession() { SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH || transport_->GetSessionType() == SessionType:: LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH) { LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH || (IS_FLAG_ENABLED(is_sco_managed_by_audio) && transport_->GetSessionType() == SessionType::HFP_HARDWARE_OFFLOAD_DATAPATH)) { transport_->ResetPresentationPosition(); session_started_ = true; return 0; Loading Loading @@ -406,7 +421,10 @@ void BluetoothAudioClientInterface::FlushAudioData() { transport_->GetSessionType() == SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH || transport_->GetSessionType() == SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH) { SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH || (IS_FLAG_ENABLED(is_sco_managed_by_audio) && transport_->GetSessionType() == SessionType::HFP_HARDWARE_OFFLOAD_DATAPATH)) { return; } Loading system/audio_hal_interface/aidl/hfp_client_interface_aidl.h 0 → 100644 +166 −0 Original line number Diff line number Diff line /* * Copyright 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include <cstdint> #include "client_interface_aidl.h" #include "common/message_loop_thread.h" namespace bluetooth { namespace audio { namespace aidl { namespace hfp { using ::aidl::android::hardware::bluetooth::audio::LatencyMode; typedef enum { HFP_CTRL_CMD_NONE, HFP_CTRL_CMD_CHECK_READY, HFP_CTRL_CMD_START, HFP_CTRL_CMD_STOP, HFP_CTRL_CMD_SUSPEND, HFP_CTRL_GET_INPUT_AUDIO_CONFIG, HFP_CTRL_GET_OUTPUT_AUDIO_CONFIG, HFP_CTRL_SET_OUTPUT_AUDIO_CONFIG, HFP_CTRL_GET_PRESENTATION_POSITION, } tHFP_CTRL_CMD; // Provide call-in APIs for the Bluetooth Audio HAL class HfpTransport { public: HfpTransport(); BluetoothAudioCtrlAck StartRequest(); BluetoothAudioCtrlAck SuspendRequest(); void StopRequest(); void SetLatencyMode(LatencyMode latency_mode); bool GetPresentationPosition(uint64_t* remote_delay_report_ns, uint64_t* total_bytes_read, timespec* data_position); void SourceMetadataChanged(const source_metadata_v7_t& source_metadata); void SinkMetadataChanged(const sink_metadata_v7_t&); void ResetPresentationPosition(); uint8_t GetPendingCmd() const; void ResetPendingCmd(); void LogBytesProcessed(size_t bytes_read); private: tHFP_CTRL_CMD hfp_pending_cmd_; }; // Sink transport implementation class HfpDecodingTransport : public ::bluetooth::audio::aidl::IBluetoothSinkTransportInstance { public: HfpDecodingTransport(SessionType sessionType); ~HfpDecodingTransport(); BluetoothAudioCtrlAck StartRequest(bool is_low_latency); BluetoothAudioCtrlAck SuspendRequest(); void StopRequest(); void SetLatencyMode(LatencyMode latency_mode); bool GetPresentationPosition(uint64_t* remote_delay_report_ns, uint64_t* total_bytes_read, timespec* data_position); void SourceMetadataChanged(const source_metadata_v7_t& source_metadata); void SinkMetadataChanged(const sink_metadata_v7_t& sink_metadata); void ResetPresentationPosition(); void LogBytesRead(size_t bytes_read) override; uint8_t GetPendingCmd() const; void ResetPendingCmd(); static inline HfpDecodingTransport* instance_ = nullptr; static inline BluetoothAudioSinkClientInterface* software_hal_interface = nullptr; static inline BluetoothAudioSinkClientInterface* offloading_hal_interface = nullptr; static inline BluetoothAudioSinkClientInterface* active_hal_interface = nullptr; private: HfpTransport* transport_; }; class HfpEncodingTransport : public ::bluetooth::audio::aidl::IBluetoothSourceTransportInstance { public: HfpEncodingTransport(SessionType sessionType); ~HfpEncodingTransport(); BluetoothAudioCtrlAck StartRequest(bool is_low_latency); BluetoothAudioCtrlAck SuspendRequest(); void StopRequest(); void SetLatencyMode(LatencyMode latency_mode); bool GetPresentationPosition(uint64_t* remote_delay_report_ns, uint64_t* total_bytes_read, timespec* data_position); void SourceMetadataChanged(const source_metadata_v7_t& source_metadata); void SinkMetadataChanged(const sink_metadata_v7_t& sink_metadata); void ResetPresentationPosition(); void LogBytesWritten(size_t bytes_written) override; uint8_t GetPendingCmd() const; void ResetPendingCmd(); static inline HfpEncodingTransport* instance_ = nullptr; static inline BluetoothAudioSourceClientInterface* software_hal_interface = nullptr; static inline BluetoothAudioSourceClientInterface* offloading_hal_interface = nullptr; static inline BluetoothAudioSourceClientInterface* active_hal_interface = nullptr; private: HfpTransport* transport_; }; } // namespace hfp } // namespace aidl } // namespace audio } // namespace bluetooth system/audio_hal_interface/hfp_client_interface.h 0 → 100644 +84 −0 Original line number Diff line number Diff line /* * Copyright 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include "bta/ag/bta_ag_int.h" #include "common/message_loop_thread.h" namespace bluetooth { namespace audio { namespace hfp { class HfpClientInterface { private: class IClientInterfaceEndpoint { public: virtual ~IClientInterfaceEndpoint() = default; virtual void Cleanup() = 0; virtual void StartSession() = 0; virtual void StopSession() = 0; virtual void UpdateAudioConfigToHal( const ::hfp::offload_config& config) = 0; }; public: class Decode : public IClientInterfaceEndpoint { public: Decode(){}; virtual ~Decode() = default; void Cleanup() override; void StartSession() override; void StopSession() override; void UpdateAudioConfigToHal(const ::hfp::offload_config& config) override; size_t Read(uint8_t* p_buf, uint32_t len); }; class Encode : public IClientInterfaceEndpoint { public: virtual ~Encode() = default; void Cleanup() override; void StartSession() override; void StopSession() override; void UpdateAudioConfigToHal(const ::hfp::offload_config& config) override; size_t Write(const uint8_t* p_buf, uint32_t len); }; // Get HFP sink client interface if it's not previously acquired and not // yet released. Decode* GetDecode(bluetooth::common::MessageLoopThread* message_loop); // Release sink interface if belongs to HFP client interface bool ReleaseDecode(Decode* sink); // Get HFP source client interface if it's not previously acquired and // not yet released. Encode* GetEncode(bluetooth::common::MessageLoopThread* message_loop); // Release source interface if belongs to HFP client interface bool ReleaseEncode(Encode* source); // Get interface, if previously not initialized - it'll initialize singleton. static HfpClientInterface* Get(); private: static HfpClientInterface* interface; Decode* decode_ = nullptr; Encode* encode_ = nullptr; }; } // namespace hfp } // namespace audio } // namespace bluetooth system/bta/include/bta_ag_api.h +11 −0 Original line number Diff line number Diff line Loading @@ -292,6 +292,17 @@ typedef uint16_t tBTA_AG_PEER_CODEC; #define BTA_AG_AT_MAX_LEN 256 #endif // Define hfp offload config structure namespace hfp { struct offload_config { tBTA_AG_PEER_CODEC sco_codec; int32_t connection_handle; bool is_controller_codec; bool is_nrec; }; } // namespace hfp /* data associated with BTA_AG_IND_RES */ typedef struct { uint16_t id; Loading Loading
system/audio_hal_interface/aidl/client_interface_aidl.cc +27 −9 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ #include "client_interface_aidl.h" #include <android/binder_manager.h> #include <android_bluetooth_flags.h> namespace bluetooth { namespace audio { Loading Loading @@ -155,8 +156,8 @@ BluetoothAudioSinkClientInterface::BluetoothAudioSinkClientInterface( BluetoothAudioSinkClientInterface::~BluetoothAudioSinkClientInterface() { if (provider_factory_ != nullptr) { AIBinder_unlinkToDeath(provider_factory_->asBinder().get(), death_recipient_.get(), nullptr); AIBinder_unlinkToDeath(provider_factory_->asBinder().get(), death_recipient_.get(), nullptr); } } Loading @@ -169,8 +170,8 @@ BluetoothAudioSourceClientInterface::BluetoothAudioSourceClientInterface( BluetoothAudioSourceClientInterface::~BluetoothAudioSourceClientInterface() { if (provider_factory_ != nullptr) { AIBinder_unlinkToDeath(provider_factory_->asBinder().get(), death_recipient_.get(), nullptr); AIBinder_unlinkToDeath(provider_factory_->asBinder().get(), death_recipient_.get(), nullptr); } } Loading @@ -196,7 +197,12 @@ bool BluetoothAudioClientInterface::UpdateAudioConfig( transport_->GetSessionType() == SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH || transport_->GetSessionType() == SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH); SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH || (IS_FLAG_ENABLED(is_sco_managed_by_audio) && (transport_->GetSessionType() == SessionType::HFP_SOFTWARE_ENCODING_DATAPATH || transport_->GetSessionType() == SessionType::HFP_SOFTWARE_DECODING_DATAPATH))); bool is_a2dp_offload_session = (transport_->GetSessionType() == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH); Loading @@ -221,9 +227,15 @@ bool BluetoothAudioClientInterface::UpdateAudioConfig( bool is_leaudio_broadcast_offload_audio_config = (is_leaudio_broadcast_offload_session && audio_config_tag == AudioConfiguration::leAudioBroadcastConfig); bool is_hfp_offload_audio_config = (IS_FLAG_ENABLED(is_sco_managed_by_audio) && transport_->GetSessionType() == SessionType::HFP_HARDWARE_OFFLOAD_DATAPATH && audio_config_tag == AudioConfiguration::hfpConfig); if (!is_software_audio_config && !is_a2dp_offload_audio_config && !is_leaudio_unicast_offload_audio_config && !is_leaudio_broadcast_offload_audio_config) { !is_leaudio_broadcast_offload_audio_config && !is_hfp_offload_audio_config) { return false; } transport_->UpdateAudioConfiguration(audio_config); Loading Loading @@ -315,7 +327,10 @@ int BluetoothAudioClientInterface::StartSession() { SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH || transport_->GetSessionType() == SessionType:: LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH) { LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH || (IS_FLAG_ENABLED(is_sco_managed_by_audio) && transport_->GetSessionType() == SessionType::HFP_HARDWARE_OFFLOAD_DATAPATH)) { transport_->ResetPresentationPosition(); session_started_ = true; return 0; Loading Loading @@ -406,7 +421,10 @@ void BluetoothAudioClientInterface::FlushAudioData() { transport_->GetSessionType() == SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH || transport_->GetSessionType() == SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH) { SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH || (IS_FLAG_ENABLED(is_sco_managed_by_audio) && transport_->GetSessionType() == SessionType::HFP_HARDWARE_OFFLOAD_DATAPATH)) { return; } Loading
system/audio_hal_interface/aidl/hfp_client_interface_aidl.h 0 → 100644 +166 −0 Original line number Diff line number Diff line /* * Copyright 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include <cstdint> #include "client_interface_aidl.h" #include "common/message_loop_thread.h" namespace bluetooth { namespace audio { namespace aidl { namespace hfp { using ::aidl::android::hardware::bluetooth::audio::LatencyMode; typedef enum { HFP_CTRL_CMD_NONE, HFP_CTRL_CMD_CHECK_READY, HFP_CTRL_CMD_START, HFP_CTRL_CMD_STOP, HFP_CTRL_CMD_SUSPEND, HFP_CTRL_GET_INPUT_AUDIO_CONFIG, HFP_CTRL_GET_OUTPUT_AUDIO_CONFIG, HFP_CTRL_SET_OUTPUT_AUDIO_CONFIG, HFP_CTRL_GET_PRESENTATION_POSITION, } tHFP_CTRL_CMD; // Provide call-in APIs for the Bluetooth Audio HAL class HfpTransport { public: HfpTransport(); BluetoothAudioCtrlAck StartRequest(); BluetoothAudioCtrlAck SuspendRequest(); void StopRequest(); void SetLatencyMode(LatencyMode latency_mode); bool GetPresentationPosition(uint64_t* remote_delay_report_ns, uint64_t* total_bytes_read, timespec* data_position); void SourceMetadataChanged(const source_metadata_v7_t& source_metadata); void SinkMetadataChanged(const sink_metadata_v7_t&); void ResetPresentationPosition(); uint8_t GetPendingCmd() const; void ResetPendingCmd(); void LogBytesProcessed(size_t bytes_read); private: tHFP_CTRL_CMD hfp_pending_cmd_; }; // Sink transport implementation class HfpDecodingTransport : public ::bluetooth::audio::aidl::IBluetoothSinkTransportInstance { public: HfpDecodingTransport(SessionType sessionType); ~HfpDecodingTransport(); BluetoothAudioCtrlAck StartRequest(bool is_low_latency); BluetoothAudioCtrlAck SuspendRequest(); void StopRequest(); void SetLatencyMode(LatencyMode latency_mode); bool GetPresentationPosition(uint64_t* remote_delay_report_ns, uint64_t* total_bytes_read, timespec* data_position); void SourceMetadataChanged(const source_metadata_v7_t& source_metadata); void SinkMetadataChanged(const sink_metadata_v7_t& sink_metadata); void ResetPresentationPosition(); void LogBytesRead(size_t bytes_read) override; uint8_t GetPendingCmd() const; void ResetPendingCmd(); static inline HfpDecodingTransport* instance_ = nullptr; static inline BluetoothAudioSinkClientInterface* software_hal_interface = nullptr; static inline BluetoothAudioSinkClientInterface* offloading_hal_interface = nullptr; static inline BluetoothAudioSinkClientInterface* active_hal_interface = nullptr; private: HfpTransport* transport_; }; class HfpEncodingTransport : public ::bluetooth::audio::aidl::IBluetoothSourceTransportInstance { public: HfpEncodingTransport(SessionType sessionType); ~HfpEncodingTransport(); BluetoothAudioCtrlAck StartRequest(bool is_low_latency); BluetoothAudioCtrlAck SuspendRequest(); void StopRequest(); void SetLatencyMode(LatencyMode latency_mode); bool GetPresentationPosition(uint64_t* remote_delay_report_ns, uint64_t* total_bytes_read, timespec* data_position); void SourceMetadataChanged(const source_metadata_v7_t& source_metadata); void SinkMetadataChanged(const sink_metadata_v7_t& sink_metadata); void ResetPresentationPosition(); void LogBytesWritten(size_t bytes_written) override; uint8_t GetPendingCmd() const; void ResetPendingCmd(); static inline HfpEncodingTransport* instance_ = nullptr; static inline BluetoothAudioSourceClientInterface* software_hal_interface = nullptr; static inline BluetoothAudioSourceClientInterface* offloading_hal_interface = nullptr; static inline BluetoothAudioSourceClientInterface* active_hal_interface = nullptr; private: HfpTransport* transport_; }; } // namespace hfp } // namespace aidl } // namespace audio } // namespace bluetooth
system/audio_hal_interface/hfp_client_interface.h 0 → 100644 +84 −0 Original line number Diff line number Diff line /* * Copyright 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include "bta/ag/bta_ag_int.h" #include "common/message_loop_thread.h" namespace bluetooth { namespace audio { namespace hfp { class HfpClientInterface { private: class IClientInterfaceEndpoint { public: virtual ~IClientInterfaceEndpoint() = default; virtual void Cleanup() = 0; virtual void StartSession() = 0; virtual void StopSession() = 0; virtual void UpdateAudioConfigToHal( const ::hfp::offload_config& config) = 0; }; public: class Decode : public IClientInterfaceEndpoint { public: Decode(){}; virtual ~Decode() = default; void Cleanup() override; void StartSession() override; void StopSession() override; void UpdateAudioConfigToHal(const ::hfp::offload_config& config) override; size_t Read(uint8_t* p_buf, uint32_t len); }; class Encode : public IClientInterfaceEndpoint { public: virtual ~Encode() = default; void Cleanup() override; void StartSession() override; void StopSession() override; void UpdateAudioConfigToHal(const ::hfp::offload_config& config) override; size_t Write(const uint8_t* p_buf, uint32_t len); }; // Get HFP sink client interface if it's not previously acquired and not // yet released. Decode* GetDecode(bluetooth::common::MessageLoopThread* message_loop); // Release sink interface if belongs to HFP client interface bool ReleaseDecode(Decode* sink); // Get HFP source client interface if it's not previously acquired and // not yet released. Encode* GetEncode(bluetooth::common::MessageLoopThread* message_loop); // Release source interface if belongs to HFP client interface bool ReleaseEncode(Encode* source); // Get interface, if previously not initialized - it'll initialize singleton. static HfpClientInterface* Get(); private: static HfpClientInterface* interface; Decode* decode_ = nullptr; Encode* encode_ = nullptr; }; } // namespace hfp } // namespace audio } // namespace bluetooth
system/bta/include/bta_ag_api.h +11 −0 Original line number Diff line number Diff line Loading @@ -292,6 +292,17 @@ typedef uint16_t tBTA_AG_PEER_CODEC; #define BTA_AG_AT_MAX_LEN 256 #endif // Define hfp offload config structure namespace hfp { struct offload_config { tBTA_AG_PEER_CODEC sco_codec; int32_t connection_handle; bool is_controller_codec; bool is_nrec; }; } // namespace hfp /* data associated with BTA_AG_IND_RES */ typedef struct { uint16_t id; Loading