Loading system/audio_hal_interface/Android.bp +2 −0 Original line number Diff line number Diff line Loading @@ -13,6 +13,7 @@ cc_library_static { srcs: [ "a2dp_encoding.cc", "client_interface.cc", "codec_status.cc", "hearing_aid_software_encoding.cc", ], shared_libs: [ Loading @@ -36,6 +37,7 @@ cc_test { defaults: ["fluoride_defaults"], include_dirs: [ "packages/modules/Bluetooth/system", "packages/modules/Bluetooth/system/stack/include", ], srcs: [ "client_interface_unittest.cc", Loading system/audio_hal_interface/a2dp_encoding.cc +30 −294 Original line number Diff line number Diff line Loading @@ -16,11 +16,8 @@ #include "a2dp_encoding.h" #include "client_interface.h" #include "codec_status.h" #include "a2dp_aac_constants.h" #include "a2dp_sbc_constants.h" #include "a2dp_vendor_ldac_constants.h" #include "bta/av/bta_av_int.h" #include "btif_a2dp_source.h" #include "btif_av.h" #include "btif_av_co.h" Loading @@ -29,30 +26,23 @@ namespace { using ::android::hardware::bluetooth::audio::V2_0::AacObjectType; using ::android::hardware::bluetooth::audio::V2_0::AacVariableBitRate; using ::android::hardware::bluetooth::audio::V2_0::CodecType; using ::android::hardware::bluetooth::audio::V2_0::LdacChannelMode; using ::android::hardware::bluetooth::audio::V2_0::LdacQualityIndex; using ::android::hardware::bluetooth::audio::V2_0::SbcAllocMethod; using ::android::hardware::bluetooth::audio::V2_0::SbcBlockLength; using ::android::hardware::bluetooth::audio::V2_0::SbcChannelMode; using ::android::hardware::bluetooth::audio::V2_0::SbcNumSubbands; using ::bluetooth::audio::AudioCapabilities; using ::bluetooth::audio::AudioConfiguration; using ::bluetooth::audio::BitsPerSample; using ::bluetooth::audio::BluetoothAudioCtrlAck; using ::bluetooth::audio::ChannelMode; using ::bluetooth::audio::CodecConfiguration; using ::bluetooth::audio::PcmParameters; using ::bluetooth::audio::SampleRate; using ::bluetooth::audio::SessionType; const CodecConfiguration kInvalidCodecConfiguration = { .codecType = CodecType::UNKNOWN, .encodedAudioBitrate = 0x00000000, .peerMtu = 0xffff, .isScmstEnabled = false, .config = {}}; using ::bluetooth::audio::codec::A2dpAacToHalConfig; using ::bluetooth::audio::codec::A2dpAptxToHalConfig; using ::bluetooth::audio::codec::A2dpCodecToHalBitsPerSample; using ::bluetooth::audio::codec::A2dpCodecToHalChannelMode; using ::bluetooth::audio::codec::A2dpCodecToHalSampleRate; using ::bluetooth::audio::codec::A2dpLdacToHalConfig; using ::bluetooth::audio::codec::A2dpSbcToHalConfig; using ::bluetooth::audio::codec::CodecConfiguration; BluetoothAudioCtrlAck a2dp_ack_to_bt_audio_ctrl_ack(tA2DP_CTRL_ACK ack); Loading Loading @@ -226,301 +216,43 @@ BluetoothAudioCtrlAck a2dp_ack_to_bt_audio_ctrl_ack(tA2DP_CTRL_ACK ack) { } } SampleRate a2dp_codec_to_hal_sample_rate( const btav_a2dp_codec_config_t& a2dp_codec_config) { switch (a2dp_codec_config.sample_rate) { case BTAV_A2DP_CODEC_SAMPLE_RATE_44100: return SampleRate::RATE_44100; case BTAV_A2DP_CODEC_SAMPLE_RATE_48000: return SampleRate::RATE_48000; case BTAV_A2DP_CODEC_SAMPLE_RATE_88200: return SampleRate::RATE_88200; case BTAV_A2DP_CODEC_SAMPLE_RATE_96000: return SampleRate::RATE_96000; case BTAV_A2DP_CODEC_SAMPLE_RATE_176400: return SampleRate::RATE_176400; case BTAV_A2DP_CODEC_SAMPLE_RATE_192000: return SampleRate::RATE_192000; case BTAV_A2DP_CODEC_SAMPLE_RATE_16000: return SampleRate::RATE_16000; case BTAV_A2DP_CODEC_SAMPLE_RATE_24000: return SampleRate::RATE_24000; default: return SampleRate::RATE_UNKNOWN; } } BitsPerSample a2dp_codec_to_hal_bits_per_sample( const btav_a2dp_codec_config_t& a2dp_codec_config) { switch (a2dp_codec_config.bits_per_sample) { case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16: return BitsPerSample::BITS_16; case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_24: return BitsPerSample::BITS_24; case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_32: return BitsPerSample::BITS_32; default: return BitsPerSample::BITS_UNKNOWN; } } ChannelMode a2dp_codec_to_hal_channel_mode( const btav_a2dp_codec_config_t& a2dp_codec_config) { switch (a2dp_codec_config.channel_mode) { case BTAV_A2DP_CODEC_CHANNEL_MODE_MONO: return ChannelMode::MONO; case BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO: return ChannelMode::STEREO; default: return ChannelMode::UNKNOWN; } } bool a2dp_get_selected_hal_codec_config(CodecConfiguration* codec_config) { A2dpCodecConfig* a2dp_codec_configs = bta_av_get_a2dp_current_codec(); if (a2dp_codec_configs == nullptr) { A2dpCodecConfig* a2dp_config = bta_av_get_a2dp_current_codec(); if (a2dp_config == nullptr) { LOG(WARNING) << __func__ << ": failure to get A2DP codec config"; *codec_config = kInvalidCodecConfiguration; *codec_config = ::bluetooth::audio::codec::kInvalidCodecConfiguration; return false; } btav_a2dp_codec_config_t current_codec = a2dp_codec_configs->getCodecConfig(); tBT_A2DP_OFFLOAD a2dp_offload; a2dp_codec_configs->getCodecSpecificConfig(&a2dp_offload); btav_a2dp_codec_config_t current_codec = a2dp_config->getCodecConfig(); switch (current_codec.codec_type) { case BTAV_A2DP_CODEC_INDEX_SOURCE_SBC: [[fallthrough]]; case BTAV_A2DP_CODEC_INDEX_SINK_SBC: { codec_config->codecType = CodecType::SBC; codec_config->config.sbcConfig({}); auto sbc_config = codec_config->config.sbcConfig(); sbc_config.sampleRate = a2dp_codec_to_hal_sample_rate(current_codec); if (sbc_config.sampleRate == SampleRate::RATE_UNKNOWN) { LOG(ERROR) << __func__ << ": Unknown SBC sample_rate=" << current_codec.sample_rate; return false; } uint8_t channel_mode = a2dp_offload.codec_info[3] & A2DP_SBC_IE_CH_MD_MSK; switch (channel_mode) { case A2DP_SBC_IE_CH_MD_JOINT: sbc_config.channelMode = SbcChannelMode::JOINT_STEREO; break; case A2DP_SBC_IE_CH_MD_STEREO: sbc_config.channelMode = SbcChannelMode::STEREO; break; case A2DP_SBC_IE_CH_MD_DUAL: sbc_config.channelMode = SbcChannelMode::DUAL; break; case A2DP_SBC_IE_CH_MD_MONO: sbc_config.channelMode = SbcChannelMode::MONO; break; default: LOG(ERROR) << __func__ << ": Unknown SBC channel_mode=" << channel_mode; sbc_config.channelMode = SbcChannelMode::UNKNOWN; return false; } uint8_t block_length = a2dp_offload.codec_info[0] & A2DP_SBC_IE_BLOCKS_MSK; switch (block_length) { case A2DP_SBC_IE_BLOCKS_4: sbc_config.blockLength = SbcBlockLength::BLOCKS_4; break; case A2DP_SBC_IE_BLOCKS_8: sbc_config.blockLength = SbcBlockLength::BLOCKS_8; break; case A2DP_SBC_IE_BLOCKS_12: sbc_config.blockLength = SbcBlockLength::BLOCKS_12; break; case A2DP_SBC_IE_BLOCKS_16: sbc_config.blockLength = SbcBlockLength::BLOCKS_16; break; default: LOG(ERROR) << __func__ << ": Unknown SBC block_length=" << block_length; return false; } uint8_t sub_bands = a2dp_offload.codec_info[0] & A2DP_SBC_IE_SUBBAND_MSK; switch (sub_bands) { case A2DP_SBC_IE_SUBBAND_4: sbc_config.numSubbands = SbcNumSubbands::SUBBAND_4; break; case A2DP_SBC_IE_SUBBAND_8: sbc_config.numSubbands = SbcNumSubbands::SUBBAND_8; break; default: LOG(ERROR) << __func__ << ": Unknown SBC Subbands=" << sub_bands; return false; } uint8_t alloc_method = a2dp_offload.codec_info[0] & A2DP_SBC_IE_ALLOC_MD_MSK; switch (alloc_method) { case A2DP_SBC_IE_ALLOC_MD_S: sbc_config.allocMethod = SbcAllocMethod::ALLOC_MD_S; break; case A2DP_SBC_IE_ALLOC_MD_L: sbc_config.allocMethod = SbcAllocMethod::ALLOC_MD_L; break; default: LOG(ERROR) << __func__ << ": Unknown SBC alloc_method=" << alloc_method; if (!A2dpSbcToHalConfig(codec_config, a2dp_config)) { return false; } sbc_config.minBitpool = a2dp_offload.codec_info[1]; sbc_config.maxBitpool = a2dp_offload.codec_info[2]; sbc_config.bitsPerSample = a2dp_codec_to_hal_bits_per_sample(current_codec); if (sbc_config.bitsPerSample == BitsPerSample::BITS_UNKNOWN) { LOG(ERROR) << __func__ << ": Unknown SBC bits_per_sample=" << current_codec.bits_per_sample; return false; } codec_config->config.sbcConfig(sbc_config); break; } case BTAV_A2DP_CODEC_INDEX_SOURCE_AAC: [[fallthrough]]; case BTAV_A2DP_CODEC_INDEX_SINK_AAC: { codec_config->codecType = CodecType::AAC; codec_config->config.aacConfig({}); auto aac_config = codec_config->config.aacConfig(); uint8_t object_type = a2dp_offload.codec_info[0]; switch (object_type) { case A2DP_AAC_OBJECT_TYPE_MPEG2_LC: aac_config.objectType = AacObjectType::MPEG2_LC; break; case A2DP_AAC_OBJECT_TYPE_MPEG4_LC: aac_config.objectType = AacObjectType::MPEG4_LC; break; case A2DP_AAC_OBJECT_TYPE_MPEG4_LTP: aac_config.objectType = AacObjectType::MPEG4_LTP; break; case A2DP_AAC_OBJECT_TYPE_MPEG4_SCALABLE: aac_config.objectType = AacObjectType::MPEG4_SCALABLE; break; default: LOG(ERROR) << __func__ << ": Unknown AAC object_type=" << +object_type; return false; } aac_config.sampleRate = a2dp_codec_to_hal_sample_rate(current_codec); if (aac_config.sampleRate == SampleRate::RATE_UNKNOWN) { LOG(ERROR) << __func__ << ": Unknown AAC sample_rate=" << current_codec.sample_rate; if (!A2dpAacToHalConfig(codec_config, a2dp_config)) { return false; } aac_config.channelMode = a2dp_codec_to_hal_channel_mode(current_codec); if (aac_config.channelMode == ChannelMode::UNKNOWN) { LOG(ERROR) << __func__ << ": Unknown AAC channel_mode=" << current_codec.channel_mode; return false; } uint8_t vbr_enabled = a2dp_offload.codec_info[1] & A2DP_AAC_VARIABLE_BIT_RATE_MASK; switch (vbr_enabled) { case A2DP_AAC_VARIABLE_BIT_RATE_ENABLED: aac_config.variableBitRateEnabled = AacVariableBitRate::ENABLED; break; case A2DP_AAC_VARIABLE_BIT_RATE_DISABLED: aac_config.variableBitRateEnabled = AacVariableBitRate::DISABLED; break; default: LOG(ERROR) << __func__ << ": Unknown AAC VBR=" << +vbr_enabled; return false; } aac_config.bitsPerSample = a2dp_codec_to_hal_bits_per_sample(current_codec); if (aac_config.bitsPerSample == BitsPerSample::BITS_UNKNOWN) { LOG(ERROR) << __func__ << ": Unknown AAC bits_per_sample=" << current_codec.bits_per_sample; return false; } codec_config->config.aacConfig(aac_config); break; } case BTAV_A2DP_CODEC_INDEX_SOURCE_APTX: [[fallthrough]]; case BTAV_A2DP_CODEC_INDEX_SOURCE_APTX_HD: { if (current_codec.codec_type == BTAV_A2DP_CODEC_INDEX_SOURCE_APTX) { codec_config->codecType = CodecType::APTX; } else { codec_config->codecType = CodecType::APTX_HD; } codec_config->config.aptxConfig({}); auto aptx_config = codec_config->config.aptxConfig(); aptx_config.sampleRate = a2dp_codec_to_hal_sample_rate(current_codec); if (aptx_config.sampleRate == SampleRate::RATE_UNKNOWN) { LOG(ERROR) << __func__ << ": Unknown aptX sample_rate=" << current_codec.sample_rate; if (!A2dpAptxToHalConfig(codec_config, a2dp_config)) { return false; } aptx_config.channelMode = a2dp_codec_to_hal_channel_mode(current_codec); if (aptx_config.channelMode == ChannelMode::UNKNOWN) { LOG(ERROR) << __func__ << ": Unknown aptX channel_mode=" << current_codec.channel_mode; return false; } aptx_config.bitsPerSample = a2dp_codec_to_hal_bits_per_sample(current_codec); if (aptx_config.bitsPerSample == BitsPerSample::BITS_UNKNOWN) { LOG(ERROR) << __func__ << ": Unknown aptX bits_per_sample=" << current_codec.bits_per_sample; return false; } codec_config->config.aptxConfig(aptx_config); break; } case BTAV_A2DP_CODEC_INDEX_SOURCE_LDAC: { codec_config->codecType = CodecType::LDAC; codec_config->config.ldacConfig({}); auto ldac_config = codec_config->config.ldacConfig(); ldac_config.sampleRate = a2dp_codec_to_hal_sample_rate(current_codec); if (ldac_config.sampleRate == SampleRate::RATE_UNKNOWN) { LOG(ERROR) << __func__ << ": Unknown LDAC sample_rate=" << current_codec.sample_rate; if (!A2dpLdacToHalConfig(codec_config, a2dp_config)) { return false; } switch (a2dp_offload.codec_info[7]) { case A2DP_LDAC_CHANNEL_MODE_STEREO: ldac_config.channelMode = LdacChannelMode::STEREO; break; case A2DP_LDAC_CHANNEL_MODE_DUAL: ldac_config.channelMode = LdacChannelMode::DUAL; break; case A2DP_LDAC_CHANNEL_MODE_MONO: ldac_config.channelMode = LdacChannelMode::MONO; break; default: LOG(ERROR) << __func__ << ": Unknown LDAC channel_mode=" << a2dp_offload.codec_info[7]; ldac_config.channelMode = LdacChannelMode::UNKNOWN; return false; } switch (a2dp_offload.codec_info[6]) { case A2DP_LDAC_QUALITY_HIGH: ldac_config.qualityIndex = LdacQualityIndex::QUALITY_HIGH; break; case A2DP_LDAC_QUALITY_MID: ldac_config.qualityIndex = LdacQualityIndex::QUALITY_MID; break; case A2DP_LDAC_QUALITY_LOW: ldac_config.qualityIndex = LdacQualityIndex::QUALITY_LOW; break; case A2DP_LDAC_QUALITY_ABR_OFFLOAD: ldac_config.qualityIndex = LdacQualityIndex::QUALITY_ABR; break; default: LOG(ERROR) << __func__ << ": Unknown LDAC QualityIndex=" << a2dp_offload.codec_info[6]; return false; } ldac_config.bitsPerSample = a2dp_codec_to_hal_bits_per_sample(current_codec); if (ldac_config.bitsPerSample == BitsPerSample::BITS_UNKNOWN) { LOG(ERROR) << __func__ << ": Unknown LDAC bits_per_sample=" << current_codec.bits_per_sample; return false; } codec_config->config.ldacConfig(ldac_config); break; } case BTAV_A2DP_CODEC_INDEX_MAX: Loading @@ -528,16 +260,15 @@ bool a2dp_get_selected_hal_codec_config(CodecConfiguration* codec_config) { default: LOG(ERROR) << __func__ << ": Unknown codec_type=" << current_codec.codec_type; codec_config->codecType = CodecType::UNKNOWN; codec_config->config = {}; *codec_config = ::bluetooth::audio::codec::kInvalidCodecConfiguration; return false; } codec_config->encodedAudioBitrate = a2dp_codec_configs->getTrackBitRate(); codec_config->encodedAudioBitrate = a2dp_config->getTrackBitRate(); // Obtain the MTU RawAddress peer_addr = btif_av_source_active_peer(); tA2DP_ENCODER_INIT_PEER_PARAMS peer_param; bta_av_co_get_peer_params(peer_addr, &peer_param); int effectiveMtu = a2dp_codec_configs->getEffectiveMtu(); int effectiveMtu = a2dp_config->getEffectiveMtu(); if (effectiveMtu > 0 && effectiveMtu < peer_param.peer_mtu) { codec_config->peerMtu = effectiveMtu; } else { Loading @@ -558,9 +289,9 @@ bool a2dp_get_selected_hal_pcm_config(PcmParameters* pcm_config) { } btav_a2dp_codec_config_t current_codec = a2dp_codec_configs->getCodecConfig(); pcm_config->sampleRate = a2dp_codec_to_hal_sample_rate(current_codec); pcm_config->bitsPerSample = a2dp_codec_to_hal_bits_per_sample(current_codec); pcm_config->channelMode = a2dp_codec_to_hal_channel_mode(current_codec); pcm_config->sampleRate = A2dpCodecToHalSampleRate(current_codec); pcm_config->bitsPerSample = A2dpCodecToHalBitsPerSample(current_codec); pcm_config->channelMode = A2dpCodecToHalChannelMode(current_codec); return (pcm_config->sampleRate != SampleRate::RATE_UNKNOWN && pcm_config->bitsPerSample != BitsPerSample::BITS_UNKNOWN && pcm_config->channelMode != ChannelMode::UNKNOWN); Loading @@ -574,13 +305,18 @@ bool is_hal_2_0_force_disabled() { } return btaudio_a2dp_disabled; } } // namespace namespace bluetooth { namespace audio { namespace a2dp { bool update_codec_offloading_capabilities( const std::vector<btav_a2dp_codec_config_t>& framework_preference) { return ::bluetooth::audio::codec::UpdateOffloadingCapabilities( framework_preference); } // Checking if new bluetooth_audio is enabled bool is_hal_2_0_enabled() { return a2dp_hal_clientif != nullptr; } Loading system/audio_hal_interface/a2dp_encoding.h +5 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ #pragma once #include <vector> #include "audio_a2dp_hw/include/audio_a2dp_hw.h" #include "common/message_loop_thread.h" Loading @@ -23,6 +25,9 @@ namespace bluetooth { namespace audio { namespace a2dp { bool update_codec_offloading_capabilities( const std::vector<btav_a2dp_codec_config_t>& framework_preference); // Check if new bluetooth_audio is enabled bool is_hal_2_0_enabled(); Loading system/audio_hal_interface/client_interface.cc +61 −23 Original line number Diff line number Diff line Loading @@ -207,19 +207,8 @@ BluetoothAudioClientInterface::BluetoothAudioClientInterface(IBluetoothTransport bluetooth::common::MessageLoopThread* message_loop) : sink_(sink), provider_(nullptr), session_started_(false), mDataMQ(nullptr), death_recipient_(new BluetoothAudioDeathRecipient(this, message_loop)) { auto service_manager = android::hardware::defaultServiceManager1_2(); CHECK(service_manager != nullptr); size_t instance_count = 0; auto listManifestByInterface_cb = [&instance_count](const hidl_vec<android::hardware::hidl_string>& instanceNames) { instance_count = instanceNames.size(); LOG(INFO) << "listManifestByInterface_cb returns " << instance_count << " instance(s)"; }; auto hidl_retval = service_manager->listManifestByInterface(kFullyQualifiedInterfaceName, listManifestByInterface_cb); if (!hidl_retval.isOk()) { LOG(FATAL) << __func__ << ": IServiceManager::listByInterface failure: " << hidl_retval.description(); } if (instance_count > 0) { fetch_audio_provider(); if (IsSupported()) { FetchAudioProvider(); } else { LOG(WARNING) << "IBluetoothAudioProvidersFactory not declared"; } Loading @@ -239,7 +228,57 @@ BluetoothAudioClientInterface::GetAudioCapabilities() const { return capabilities_; } void BluetoothAudioClientInterface::fetch_audio_provider() { bool BluetoothAudioClientInterface::IsSupported() { auto service_manager = android::hardware::defaultServiceManager1_2(); CHECK(service_manager != nullptr); size_t instance_count = 0; auto listManifestByInterface_cb = [&instance_count]( const hidl_vec<android::hardware::hidl_string>& instanceNames) { instance_count = instanceNames.size(); LOG(INFO) << "listManifestByInterface_cb returns " << instance_count << " instance(s)"; }; auto hidl_retval = service_manager->listManifestByInterface( kFullyQualifiedInterfaceName, listManifestByInterface_cb); if (!hidl_retval.isOk()) { LOG(FATAL) << __func__ << ": IServiceManager::listByInterface failure: " << hidl_retval.description(); return false; } return (instance_count > 0); } std::vector<AudioCapabilities> BluetoothAudioClientInterface::GetAudioCapabilities(SessionType session_type) { std::vector<AudioCapabilities> capabilities(0); if (!IsSupported()) return capabilities; android::sp<IBluetoothAudioProvidersFactory> providersFactory = IBluetoothAudioProvidersFactory::getService(); CHECK(providersFactory != nullptr) << "IBluetoothAudioProvidersFactory::getService() failed"; LOG(INFO) << "IBluetoothAudioProvidersFactory::getService() returned " << providersFactory.get() << (providersFactory->isRemote() ? " (remote)" : " (local)"); auto getProviderCapabilities_cb = [&capabilities](const hidl_vec<AudioCapabilities>& audioCapabilities) { for (auto capability : audioCapabilities) { capabilities.push_back(capability); } }; auto hidl_retval = providersFactory->getProviderCapabilities( session_type, getProviderCapabilities_cb); if (!hidl_retval.isOk()) { LOG(FATAL) << __func__ << ": BluetoothAudioHal::getProviderCapabilities failure: " << hidl_retval.description(); } return capabilities; } void BluetoothAudioClientInterface::FetchAudioProvider() { if (provider_ != nullptr) { LOG(WARNING) << __func__ << ": reflash"; } Loading @@ -251,20 +290,16 @@ void BluetoothAudioClientInterface::fetch_audio_provider() { << providersFactory.get() << (providersFactory->isRemote() ? " (remote)" : " (local)"); std::promise<void> getProviderCapabilities_promise; auto getProviderCapabilities_future = getProviderCapabilities_promise.get_future(); auto getProviderCapabilities_cb = [& capabilities = this->capabilities_, &getProviderCapabilities_promise]( [& capabilities = this->capabilities_]( const hidl_vec<AudioCapabilities>& audioCapabilities) { capabilities.clear(); for (auto capability : audioCapabilities) { capabilities.push_back(capability); } getProviderCapabilities_promise.set_value(); }; auto hidl_retval = providersFactory->getProviderCapabilities( sink_->GetSessionType(), getProviderCapabilities_cb); getProviderCapabilities_future.get(); if (!hidl_retval.isOk()) { LOG(FATAL) << __func__ << ": BluetoothAudioHal::getProviderCapabilities failure: " << hidl_retval.description(); return; Loading Loading @@ -508,10 +543,13 @@ size_t BluetoothAudioClientInterface::WriteAudioData(uint8_t* p_buf, void BluetoothAudioClientInterface::RenewAudioProviderAndSession() { // NOTE: must be invoked on the same thread where this // BluetoothAudioClientInterface is running fetch_audio_provider(); FetchAudioProvider(); if (session_started_) { LOG(INFO) << __func__ << ": Restart the session while audio HAL recovering"; session_started_ = false; StartSession(); } } } // namespace audio } // namespace bluetooth system/audio_hal_interface/client_interface.h +6 −3 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ #include <time.h> #include <mutex> #include <vector> #include <android/hardware/bluetooth/audio/2.0/IBluetoothAudioProvider.h> #include <android/hardware/bluetooth/audio/2.0/types.h> Loading @@ -35,8 +36,6 @@ using ::android::hardware::bluetooth::audio::V2_0::AudioCapabilities; using ::android::hardware::bluetooth::audio::V2_0::AudioConfiguration; using ::android::hardware::bluetooth::audio::V2_0::BitsPerSample; using ::android::hardware::bluetooth::audio::V2_0::ChannelMode; using ::android::hardware::bluetooth::audio::V2_0::CodecConfiguration; using ::android::hardware::bluetooth::audio::V2_0::CodecType; using ::android::hardware::bluetooth::audio::V2_0::IBluetoothAudioProvider; using ::android::hardware::bluetooth::audio::V2_0::PcmParameters; using ::android::hardware::bluetooth::audio::V2_0::SampleRate; Loading Loading @@ -136,6 +135,8 @@ class BluetoothAudioClientInterface { } std::vector<AudioCapabilities> GetAudioCapabilities() const; static std::vector<AudioCapabilities> GetAudioCapabilities( SessionType session_type); bool UpdateAudioConfig(const AudioConfiguration& audioConfig); Loading Loading @@ -163,8 +164,10 @@ class BluetoothAudioClientInterface { }; private: static bool IsSupported(); // Helper function to connect to an IBluetoothAudioProvider void fetch_audio_provider(); void FetchAudioProvider(); mutable std::mutex internal_mutex_; IBluetoothTransportInstance* sink_; Loading Loading
system/audio_hal_interface/Android.bp +2 −0 Original line number Diff line number Diff line Loading @@ -13,6 +13,7 @@ cc_library_static { srcs: [ "a2dp_encoding.cc", "client_interface.cc", "codec_status.cc", "hearing_aid_software_encoding.cc", ], shared_libs: [ Loading @@ -36,6 +37,7 @@ cc_test { defaults: ["fluoride_defaults"], include_dirs: [ "packages/modules/Bluetooth/system", "packages/modules/Bluetooth/system/stack/include", ], srcs: [ "client_interface_unittest.cc", Loading
system/audio_hal_interface/a2dp_encoding.cc +30 −294 Original line number Diff line number Diff line Loading @@ -16,11 +16,8 @@ #include "a2dp_encoding.h" #include "client_interface.h" #include "codec_status.h" #include "a2dp_aac_constants.h" #include "a2dp_sbc_constants.h" #include "a2dp_vendor_ldac_constants.h" #include "bta/av/bta_av_int.h" #include "btif_a2dp_source.h" #include "btif_av.h" #include "btif_av_co.h" Loading @@ -29,30 +26,23 @@ namespace { using ::android::hardware::bluetooth::audio::V2_0::AacObjectType; using ::android::hardware::bluetooth::audio::V2_0::AacVariableBitRate; using ::android::hardware::bluetooth::audio::V2_0::CodecType; using ::android::hardware::bluetooth::audio::V2_0::LdacChannelMode; using ::android::hardware::bluetooth::audio::V2_0::LdacQualityIndex; using ::android::hardware::bluetooth::audio::V2_0::SbcAllocMethod; using ::android::hardware::bluetooth::audio::V2_0::SbcBlockLength; using ::android::hardware::bluetooth::audio::V2_0::SbcChannelMode; using ::android::hardware::bluetooth::audio::V2_0::SbcNumSubbands; using ::bluetooth::audio::AudioCapabilities; using ::bluetooth::audio::AudioConfiguration; using ::bluetooth::audio::BitsPerSample; using ::bluetooth::audio::BluetoothAudioCtrlAck; using ::bluetooth::audio::ChannelMode; using ::bluetooth::audio::CodecConfiguration; using ::bluetooth::audio::PcmParameters; using ::bluetooth::audio::SampleRate; using ::bluetooth::audio::SessionType; const CodecConfiguration kInvalidCodecConfiguration = { .codecType = CodecType::UNKNOWN, .encodedAudioBitrate = 0x00000000, .peerMtu = 0xffff, .isScmstEnabled = false, .config = {}}; using ::bluetooth::audio::codec::A2dpAacToHalConfig; using ::bluetooth::audio::codec::A2dpAptxToHalConfig; using ::bluetooth::audio::codec::A2dpCodecToHalBitsPerSample; using ::bluetooth::audio::codec::A2dpCodecToHalChannelMode; using ::bluetooth::audio::codec::A2dpCodecToHalSampleRate; using ::bluetooth::audio::codec::A2dpLdacToHalConfig; using ::bluetooth::audio::codec::A2dpSbcToHalConfig; using ::bluetooth::audio::codec::CodecConfiguration; BluetoothAudioCtrlAck a2dp_ack_to_bt_audio_ctrl_ack(tA2DP_CTRL_ACK ack); Loading Loading @@ -226,301 +216,43 @@ BluetoothAudioCtrlAck a2dp_ack_to_bt_audio_ctrl_ack(tA2DP_CTRL_ACK ack) { } } SampleRate a2dp_codec_to_hal_sample_rate( const btav_a2dp_codec_config_t& a2dp_codec_config) { switch (a2dp_codec_config.sample_rate) { case BTAV_A2DP_CODEC_SAMPLE_RATE_44100: return SampleRate::RATE_44100; case BTAV_A2DP_CODEC_SAMPLE_RATE_48000: return SampleRate::RATE_48000; case BTAV_A2DP_CODEC_SAMPLE_RATE_88200: return SampleRate::RATE_88200; case BTAV_A2DP_CODEC_SAMPLE_RATE_96000: return SampleRate::RATE_96000; case BTAV_A2DP_CODEC_SAMPLE_RATE_176400: return SampleRate::RATE_176400; case BTAV_A2DP_CODEC_SAMPLE_RATE_192000: return SampleRate::RATE_192000; case BTAV_A2DP_CODEC_SAMPLE_RATE_16000: return SampleRate::RATE_16000; case BTAV_A2DP_CODEC_SAMPLE_RATE_24000: return SampleRate::RATE_24000; default: return SampleRate::RATE_UNKNOWN; } } BitsPerSample a2dp_codec_to_hal_bits_per_sample( const btav_a2dp_codec_config_t& a2dp_codec_config) { switch (a2dp_codec_config.bits_per_sample) { case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16: return BitsPerSample::BITS_16; case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_24: return BitsPerSample::BITS_24; case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_32: return BitsPerSample::BITS_32; default: return BitsPerSample::BITS_UNKNOWN; } } ChannelMode a2dp_codec_to_hal_channel_mode( const btav_a2dp_codec_config_t& a2dp_codec_config) { switch (a2dp_codec_config.channel_mode) { case BTAV_A2DP_CODEC_CHANNEL_MODE_MONO: return ChannelMode::MONO; case BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO: return ChannelMode::STEREO; default: return ChannelMode::UNKNOWN; } } bool a2dp_get_selected_hal_codec_config(CodecConfiguration* codec_config) { A2dpCodecConfig* a2dp_codec_configs = bta_av_get_a2dp_current_codec(); if (a2dp_codec_configs == nullptr) { A2dpCodecConfig* a2dp_config = bta_av_get_a2dp_current_codec(); if (a2dp_config == nullptr) { LOG(WARNING) << __func__ << ": failure to get A2DP codec config"; *codec_config = kInvalidCodecConfiguration; *codec_config = ::bluetooth::audio::codec::kInvalidCodecConfiguration; return false; } btav_a2dp_codec_config_t current_codec = a2dp_codec_configs->getCodecConfig(); tBT_A2DP_OFFLOAD a2dp_offload; a2dp_codec_configs->getCodecSpecificConfig(&a2dp_offload); btav_a2dp_codec_config_t current_codec = a2dp_config->getCodecConfig(); switch (current_codec.codec_type) { case BTAV_A2DP_CODEC_INDEX_SOURCE_SBC: [[fallthrough]]; case BTAV_A2DP_CODEC_INDEX_SINK_SBC: { codec_config->codecType = CodecType::SBC; codec_config->config.sbcConfig({}); auto sbc_config = codec_config->config.sbcConfig(); sbc_config.sampleRate = a2dp_codec_to_hal_sample_rate(current_codec); if (sbc_config.sampleRate == SampleRate::RATE_UNKNOWN) { LOG(ERROR) << __func__ << ": Unknown SBC sample_rate=" << current_codec.sample_rate; return false; } uint8_t channel_mode = a2dp_offload.codec_info[3] & A2DP_SBC_IE_CH_MD_MSK; switch (channel_mode) { case A2DP_SBC_IE_CH_MD_JOINT: sbc_config.channelMode = SbcChannelMode::JOINT_STEREO; break; case A2DP_SBC_IE_CH_MD_STEREO: sbc_config.channelMode = SbcChannelMode::STEREO; break; case A2DP_SBC_IE_CH_MD_DUAL: sbc_config.channelMode = SbcChannelMode::DUAL; break; case A2DP_SBC_IE_CH_MD_MONO: sbc_config.channelMode = SbcChannelMode::MONO; break; default: LOG(ERROR) << __func__ << ": Unknown SBC channel_mode=" << channel_mode; sbc_config.channelMode = SbcChannelMode::UNKNOWN; return false; } uint8_t block_length = a2dp_offload.codec_info[0] & A2DP_SBC_IE_BLOCKS_MSK; switch (block_length) { case A2DP_SBC_IE_BLOCKS_4: sbc_config.blockLength = SbcBlockLength::BLOCKS_4; break; case A2DP_SBC_IE_BLOCKS_8: sbc_config.blockLength = SbcBlockLength::BLOCKS_8; break; case A2DP_SBC_IE_BLOCKS_12: sbc_config.blockLength = SbcBlockLength::BLOCKS_12; break; case A2DP_SBC_IE_BLOCKS_16: sbc_config.blockLength = SbcBlockLength::BLOCKS_16; break; default: LOG(ERROR) << __func__ << ": Unknown SBC block_length=" << block_length; return false; } uint8_t sub_bands = a2dp_offload.codec_info[0] & A2DP_SBC_IE_SUBBAND_MSK; switch (sub_bands) { case A2DP_SBC_IE_SUBBAND_4: sbc_config.numSubbands = SbcNumSubbands::SUBBAND_4; break; case A2DP_SBC_IE_SUBBAND_8: sbc_config.numSubbands = SbcNumSubbands::SUBBAND_8; break; default: LOG(ERROR) << __func__ << ": Unknown SBC Subbands=" << sub_bands; return false; } uint8_t alloc_method = a2dp_offload.codec_info[0] & A2DP_SBC_IE_ALLOC_MD_MSK; switch (alloc_method) { case A2DP_SBC_IE_ALLOC_MD_S: sbc_config.allocMethod = SbcAllocMethod::ALLOC_MD_S; break; case A2DP_SBC_IE_ALLOC_MD_L: sbc_config.allocMethod = SbcAllocMethod::ALLOC_MD_L; break; default: LOG(ERROR) << __func__ << ": Unknown SBC alloc_method=" << alloc_method; if (!A2dpSbcToHalConfig(codec_config, a2dp_config)) { return false; } sbc_config.minBitpool = a2dp_offload.codec_info[1]; sbc_config.maxBitpool = a2dp_offload.codec_info[2]; sbc_config.bitsPerSample = a2dp_codec_to_hal_bits_per_sample(current_codec); if (sbc_config.bitsPerSample == BitsPerSample::BITS_UNKNOWN) { LOG(ERROR) << __func__ << ": Unknown SBC bits_per_sample=" << current_codec.bits_per_sample; return false; } codec_config->config.sbcConfig(sbc_config); break; } case BTAV_A2DP_CODEC_INDEX_SOURCE_AAC: [[fallthrough]]; case BTAV_A2DP_CODEC_INDEX_SINK_AAC: { codec_config->codecType = CodecType::AAC; codec_config->config.aacConfig({}); auto aac_config = codec_config->config.aacConfig(); uint8_t object_type = a2dp_offload.codec_info[0]; switch (object_type) { case A2DP_AAC_OBJECT_TYPE_MPEG2_LC: aac_config.objectType = AacObjectType::MPEG2_LC; break; case A2DP_AAC_OBJECT_TYPE_MPEG4_LC: aac_config.objectType = AacObjectType::MPEG4_LC; break; case A2DP_AAC_OBJECT_TYPE_MPEG4_LTP: aac_config.objectType = AacObjectType::MPEG4_LTP; break; case A2DP_AAC_OBJECT_TYPE_MPEG4_SCALABLE: aac_config.objectType = AacObjectType::MPEG4_SCALABLE; break; default: LOG(ERROR) << __func__ << ": Unknown AAC object_type=" << +object_type; return false; } aac_config.sampleRate = a2dp_codec_to_hal_sample_rate(current_codec); if (aac_config.sampleRate == SampleRate::RATE_UNKNOWN) { LOG(ERROR) << __func__ << ": Unknown AAC sample_rate=" << current_codec.sample_rate; if (!A2dpAacToHalConfig(codec_config, a2dp_config)) { return false; } aac_config.channelMode = a2dp_codec_to_hal_channel_mode(current_codec); if (aac_config.channelMode == ChannelMode::UNKNOWN) { LOG(ERROR) << __func__ << ": Unknown AAC channel_mode=" << current_codec.channel_mode; return false; } uint8_t vbr_enabled = a2dp_offload.codec_info[1] & A2DP_AAC_VARIABLE_BIT_RATE_MASK; switch (vbr_enabled) { case A2DP_AAC_VARIABLE_BIT_RATE_ENABLED: aac_config.variableBitRateEnabled = AacVariableBitRate::ENABLED; break; case A2DP_AAC_VARIABLE_BIT_RATE_DISABLED: aac_config.variableBitRateEnabled = AacVariableBitRate::DISABLED; break; default: LOG(ERROR) << __func__ << ": Unknown AAC VBR=" << +vbr_enabled; return false; } aac_config.bitsPerSample = a2dp_codec_to_hal_bits_per_sample(current_codec); if (aac_config.bitsPerSample == BitsPerSample::BITS_UNKNOWN) { LOG(ERROR) << __func__ << ": Unknown AAC bits_per_sample=" << current_codec.bits_per_sample; return false; } codec_config->config.aacConfig(aac_config); break; } case BTAV_A2DP_CODEC_INDEX_SOURCE_APTX: [[fallthrough]]; case BTAV_A2DP_CODEC_INDEX_SOURCE_APTX_HD: { if (current_codec.codec_type == BTAV_A2DP_CODEC_INDEX_SOURCE_APTX) { codec_config->codecType = CodecType::APTX; } else { codec_config->codecType = CodecType::APTX_HD; } codec_config->config.aptxConfig({}); auto aptx_config = codec_config->config.aptxConfig(); aptx_config.sampleRate = a2dp_codec_to_hal_sample_rate(current_codec); if (aptx_config.sampleRate == SampleRate::RATE_UNKNOWN) { LOG(ERROR) << __func__ << ": Unknown aptX sample_rate=" << current_codec.sample_rate; if (!A2dpAptxToHalConfig(codec_config, a2dp_config)) { return false; } aptx_config.channelMode = a2dp_codec_to_hal_channel_mode(current_codec); if (aptx_config.channelMode == ChannelMode::UNKNOWN) { LOG(ERROR) << __func__ << ": Unknown aptX channel_mode=" << current_codec.channel_mode; return false; } aptx_config.bitsPerSample = a2dp_codec_to_hal_bits_per_sample(current_codec); if (aptx_config.bitsPerSample == BitsPerSample::BITS_UNKNOWN) { LOG(ERROR) << __func__ << ": Unknown aptX bits_per_sample=" << current_codec.bits_per_sample; return false; } codec_config->config.aptxConfig(aptx_config); break; } case BTAV_A2DP_CODEC_INDEX_SOURCE_LDAC: { codec_config->codecType = CodecType::LDAC; codec_config->config.ldacConfig({}); auto ldac_config = codec_config->config.ldacConfig(); ldac_config.sampleRate = a2dp_codec_to_hal_sample_rate(current_codec); if (ldac_config.sampleRate == SampleRate::RATE_UNKNOWN) { LOG(ERROR) << __func__ << ": Unknown LDAC sample_rate=" << current_codec.sample_rate; if (!A2dpLdacToHalConfig(codec_config, a2dp_config)) { return false; } switch (a2dp_offload.codec_info[7]) { case A2DP_LDAC_CHANNEL_MODE_STEREO: ldac_config.channelMode = LdacChannelMode::STEREO; break; case A2DP_LDAC_CHANNEL_MODE_DUAL: ldac_config.channelMode = LdacChannelMode::DUAL; break; case A2DP_LDAC_CHANNEL_MODE_MONO: ldac_config.channelMode = LdacChannelMode::MONO; break; default: LOG(ERROR) << __func__ << ": Unknown LDAC channel_mode=" << a2dp_offload.codec_info[7]; ldac_config.channelMode = LdacChannelMode::UNKNOWN; return false; } switch (a2dp_offload.codec_info[6]) { case A2DP_LDAC_QUALITY_HIGH: ldac_config.qualityIndex = LdacQualityIndex::QUALITY_HIGH; break; case A2DP_LDAC_QUALITY_MID: ldac_config.qualityIndex = LdacQualityIndex::QUALITY_MID; break; case A2DP_LDAC_QUALITY_LOW: ldac_config.qualityIndex = LdacQualityIndex::QUALITY_LOW; break; case A2DP_LDAC_QUALITY_ABR_OFFLOAD: ldac_config.qualityIndex = LdacQualityIndex::QUALITY_ABR; break; default: LOG(ERROR) << __func__ << ": Unknown LDAC QualityIndex=" << a2dp_offload.codec_info[6]; return false; } ldac_config.bitsPerSample = a2dp_codec_to_hal_bits_per_sample(current_codec); if (ldac_config.bitsPerSample == BitsPerSample::BITS_UNKNOWN) { LOG(ERROR) << __func__ << ": Unknown LDAC bits_per_sample=" << current_codec.bits_per_sample; return false; } codec_config->config.ldacConfig(ldac_config); break; } case BTAV_A2DP_CODEC_INDEX_MAX: Loading @@ -528,16 +260,15 @@ bool a2dp_get_selected_hal_codec_config(CodecConfiguration* codec_config) { default: LOG(ERROR) << __func__ << ": Unknown codec_type=" << current_codec.codec_type; codec_config->codecType = CodecType::UNKNOWN; codec_config->config = {}; *codec_config = ::bluetooth::audio::codec::kInvalidCodecConfiguration; return false; } codec_config->encodedAudioBitrate = a2dp_codec_configs->getTrackBitRate(); codec_config->encodedAudioBitrate = a2dp_config->getTrackBitRate(); // Obtain the MTU RawAddress peer_addr = btif_av_source_active_peer(); tA2DP_ENCODER_INIT_PEER_PARAMS peer_param; bta_av_co_get_peer_params(peer_addr, &peer_param); int effectiveMtu = a2dp_codec_configs->getEffectiveMtu(); int effectiveMtu = a2dp_config->getEffectiveMtu(); if (effectiveMtu > 0 && effectiveMtu < peer_param.peer_mtu) { codec_config->peerMtu = effectiveMtu; } else { Loading @@ -558,9 +289,9 @@ bool a2dp_get_selected_hal_pcm_config(PcmParameters* pcm_config) { } btav_a2dp_codec_config_t current_codec = a2dp_codec_configs->getCodecConfig(); pcm_config->sampleRate = a2dp_codec_to_hal_sample_rate(current_codec); pcm_config->bitsPerSample = a2dp_codec_to_hal_bits_per_sample(current_codec); pcm_config->channelMode = a2dp_codec_to_hal_channel_mode(current_codec); pcm_config->sampleRate = A2dpCodecToHalSampleRate(current_codec); pcm_config->bitsPerSample = A2dpCodecToHalBitsPerSample(current_codec); pcm_config->channelMode = A2dpCodecToHalChannelMode(current_codec); return (pcm_config->sampleRate != SampleRate::RATE_UNKNOWN && pcm_config->bitsPerSample != BitsPerSample::BITS_UNKNOWN && pcm_config->channelMode != ChannelMode::UNKNOWN); Loading @@ -574,13 +305,18 @@ bool is_hal_2_0_force_disabled() { } return btaudio_a2dp_disabled; } } // namespace namespace bluetooth { namespace audio { namespace a2dp { bool update_codec_offloading_capabilities( const std::vector<btav_a2dp_codec_config_t>& framework_preference) { return ::bluetooth::audio::codec::UpdateOffloadingCapabilities( framework_preference); } // Checking if new bluetooth_audio is enabled bool is_hal_2_0_enabled() { return a2dp_hal_clientif != nullptr; } Loading
system/audio_hal_interface/a2dp_encoding.h +5 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ #pragma once #include <vector> #include "audio_a2dp_hw/include/audio_a2dp_hw.h" #include "common/message_loop_thread.h" Loading @@ -23,6 +25,9 @@ namespace bluetooth { namespace audio { namespace a2dp { bool update_codec_offloading_capabilities( const std::vector<btav_a2dp_codec_config_t>& framework_preference); // Check if new bluetooth_audio is enabled bool is_hal_2_0_enabled(); Loading
system/audio_hal_interface/client_interface.cc +61 −23 Original line number Diff line number Diff line Loading @@ -207,19 +207,8 @@ BluetoothAudioClientInterface::BluetoothAudioClientInterface(IBluetoothTransport bluetooth::common::MessageLoopThread* message_loop) : sink_(sink), provider_(nullptr), session_started_(false), mDataMQ(nullptr), death_recipient_(new BluetoothAudioDeathRecipient(this, message_loop)) { auto service_manager = android::hardware::defaultServiceManager1_2(); CHECK(service_manager != nullptr); size_t instance_count = 0; auto listManifestByInterface_cb = [&instance_count](const hidl_vec<android::hardware::hidl_string>& instanceNames) { instance_count = instanceNames.size(); LOG(INFO) << "listManifestByInterface_cb returns " << instance_count << " instance(s)"; }; auto hidl_retval = service_manager->listManifestByInterface(kFullyQualifiedInterfaceName, listManifestByInterface_cb); if (!hidl_retval.isOk()) { LOG(FATAL) << __func__ << ": IServiceManager::listByInterface failure: " << hidl_retval.description(); } if (instance_count > 0) { fetch_audio_provider(); if (IsSupported()) { FetchAudioProvider(); } else { LOG(WARNING) << "IBluetoothAudioProvidersFactory not declared"; } Loading @@ -239,7 +228,57 @@ BluetoothAudioClientInterface::GetAudioCapabilities() const { return capabilities_; } void BluetoothAudioClientInterface::fetch_audio_provider() { bool BluetoothAudioClientInterface::IsSupported() { auto service_manager = android::hardware::defaultServiceManager1_2(); CHECK(service_manager != nullptr); size_t instance_count = 0; auto listManifestByInterface_cb = [&instance_count]( const hidl_vec<android::hardware::hidl_string>& instanceNames) { instance_count = instanceNames.size(); LOG(INFO) << "listManifestByInterface_cb returns " << instance_count << " instance(s)"; }; auto hidl_retval = service_manager->listManifestByInterface( kFullyQualifiedInterfaceName, listManifestByInterface_cb); if (!hidl_retval.isOk()) { LOG(FATAL) << __func__ << ": IServiceManager::listByInterface failure: " << hidl_retval.description(); return false; } return (instance_count > 0); } std::vector<AudioCapabilities> BluetoothAudioClientInterface::GetAudioCapabilities(SessionType session_type) { std::vector<AudioCapabilities> capabilities(0); if (!IsSupported()) return capabilities; android::sp<IBluetoothAudioProvidersFactory> providersFactory = IBluetoothAudioProvidersFactory::getService(); CHECK(providersFactory != nullptr) << "IBluetoothAudioProvidersFactory::getService() failed"; LOG(INFO) << "IBluetoothAudioProvidersFactory::getService() returned " << providersFactory.get() << (providersFactory->isRemote() ? " (remote)" : " (local)"); auto getProviderCapabilities_cb = [&capabilities](const hidl_vec<AudioCapabilities>& audioCapabilities) { for (auto capability : audioCapabilities) { capabilities.push_back(capability); } }; auto hidl_retval = providersFactory->getProviderCapabilities( session_type, getProviderCapabilities_cb); if (!hidl_retval.isOk()) { LOG(FATAL) << __func__ << ": BluetoothAudioHal::getProviderCapabilities failure: " << hidl_retval.description(); } return capabilities; } void BluetoothAudioClientInterface::FetchAudioProvider() { if (provider_ != nullptr) { LOG(WARNING) << __func__ << ": reflash"; } Loading @@ -251,20 +290,16 @@ void BluetoothAudioClientInterface::fetch_audio_provider() { << providersFactory.get() << (providersFactory->isRemote() ? " (remote)" : " (local)"); std::promise<void> getProviderCapabilities_promise; auto getProviderCapabilities_future = getProviderCapabilities_promise.get_future(); auto getProviderCapabilities_cb = [& capabilities = this->capabilities_, &getProviderCapabilities_promise]( [& capabilities = this->capabilities_]( const hidl_vec<AudioCapabilities>& audioCapabilities) { capabilities.clear(); for (auto capability : audioCapabilities) { capabilities.push_back(capability); } getProviderCapabilities_promise.set_value(); }; auto hidl_retval = providersFactory->getProviderCapabilities( sink_->GetSessionType(), getProviderCapabilities_cb); getProviderCapabilities_future.get(); if (!hidl_retval.isOk()) { LOG(FATAL) << __func__ << ": BluetoothAudioHal::getProviderCapabilities failure: " << hidl_retval.description(); return; Loading Loading @@ -508,10 +543,13 @@ size_t BluetoothAudioClientInterface::WriteAudioData(uint8_t* p_buf, void BluetoothAudioClientInterface::RenewAudioProviderAndSession() { // NOTE: must be invoked on the same thread where this // BluetoothAudioClientInterface is running fetch_audio_provider(); FetchAudioProvider(); if (session_started_) { LOG(INFO) << __func__ << ": Restart the session while audio HAL recovering"; session_started_ = false; StartSession(); } } } // namespace audio } // namespace bluetooth
system/audio_hal_interface/client_interface.h +6 −3 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ #include <time.h> #include <mutex> #include <vector> #include <android/hardware/bluetooth/audio/2.0/IBluetoothAudioProvider.h> #include <android/hardware/bluetooth/audio/2.0/types.h> Loading @@ -35,8 +36,6 @@ using ::android::hardware::bluetooth::audio::V2_0::AudioCapabilities; using ::android::hardware::bluetooth::audio::V2_0::AudioConfiguration; using ::android::hardware::bluetooth::audio::V2_0::BitsPerSample; using ::android::hardware::bluetooth::audio::V2_0::ChannelMode; using ::android::hardware::bluetooth::audio::V2_0::CodecConfiguration; using ::android::hardware::bluetooth::audio::V2_0::CodecType; using ::android::hardware::bluetooth::audio::V2_0::IBluetoothAudioProvider; using ::android::hardware::bluetooth::audio::V2_0::PcmParameters; using ::android::hardware::bluetooth::audio::V2_0::SampleRate; Loading Loading @@ -136,6 +135,8 @@ class BluetoothAudioClientInterface { } std::vector<AudioCapabilities> GetAudioCapabilities() const; static std::vector<AudioCapabilities> GetAudioCapabilities( SessionType session_type); bool UpdateAudioConfig(const AudioConfiguration& audioConfig); Loading Loading @@ -163,8 +164,10 @@ class BluetoothAudioClientInterface { }; private: static bool IsSupported(); // Helper function to connect to an IBluetoothAudioProvider void fetch_audio_provider(); void FetchAudioProvider(); mutable std::mutex internal_mutex_; IBluetoothTransportInstance* sink_; Loading