Add LE Audio getProviderInfo information

Bug: 306225778
Test: mmm hardware/interfaces/bluetooth/audio/aidl/default
Change-Id: Ieb03a1a3096dbeb6a4e2ac4774ece6d3ef3e33be
This commit is contained in:
Bao Do
2023-12-11 10:53:18 +00:00
parent ccceb2f3b3
commit 6aeb5d7217
6 changed files with 225 additions and 33 deletions

View File

@@ -41,8 +41,7 @@ class BluetoothAudioProvider : public BnBluetoothAudioProvider {
ndk::ScopedAStatus startSession(
const std::shared_ptr<IBluetoothAudioPort>& host_if,
const AudioConfiguration& audio_config,
const std::vector<LatencyMode>& latency_modes,
DataMQDesc* _aidl_return);
const std::vector<LatencyMode>& latency_modes, DataMQDesc* _aidl_return);
ndk::ScopedAStatus endSession();
ndk::ScopedAStatus streamStarted(BluetoothAudioStatus status);
ndk::ScopedAStatus streamSuspended(BluetoothAudioStatus status);

View File

@@ -37,6 +37,9 @@ namespace hardware {
namespace bluetooth {
namespace audio {
static const std::string kLeAudioOffloadProviderName =
"LE_AUDIO_OFFLOAD_HARDWARE_OFFLOAD_PROVIDER";
BluetoothAudioProviderFactory::BluetoothAudioProviderFactory() {}
ndk::ScopedAStatus BluetoothAudioProviderFactory::openProvider(
@@ -158,6 +161,22 @@ ndk::ScopedAStatus BluetoothAudioProviderFactory::getProviderInfo(
provider_info.name = A2dpOffloadCodecFactory::GetInstance()->name;
for (auto codec : A2dpOffloadCodecFactory::GetInstance()->codecs)
provider_info.codecInfos.push_back(codec->info);
} else if (session_type ==
SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
session_type ==
SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH ||
session_type ==
SessionType::
LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
std::vector<CodecInfo> db_codec_info =
BluetoothAudioCodecs::GetLeAudioOffloadCodecInfo(session_type);
if (!db_codec_info.empty()) {
auto& provider_info = _aidl_return->emplace();
provider_info.name = kLeAudioOffloadProviderName;
provider_info.codecInfos = db_codec_info;
*_aidl_return = provider_info;
}
return ndk::ScopedAStatus::ok();
}
return ndk::ScopedAStatus::ok();

View File

@@ -97,6 +97,8 @@ const std::vector<CodecCapabilities> kDefaultOffloadA2dpCodecCapabilities = {
{.codecType = CodecType::OPUS, .capabilities = {}}};
std::vector<LeAudioCodecCapabilitiesSetting> kDefaultOffloadLeAudioCapabilities;
std::unordered_map<SessionType, std::vector<CodecInfo>>
kDefaultOffloadLeAudioCodecInfoMap;
template <class T>
bool BluetoothAudioCodecs::ContainedInVector(
@@ -411,6 +413,31 @@ BluetoothAudioCodecs::GetLeAudioOffloadCodecCapabilities(
return kDefaultOffloadLeAudioCapabilities;
}
std::vector<CodecInfo> BluetoothAudioCodecs::GetLeAudioOffloadCodecInfo(
const SessionType& session_type) {
if (session_type !=
SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
session_type !=
SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH &&
session_type !=
SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
return std::vector<CodecInfo>();
}
if (kDefaultOffloadLeAudioCodecInfoMap.empty()) {
auto le_audio_offload_setting =
BluetoothLeAudioCodecsProvider::ParseFromLeAudioOffloadSettingFile();
auto kDefaultOffloadLeAudioCodecInfoMap =
BluetoothLeAudioCodecsProvider::GetLeAudioCodecInfo(
le_audio_offload_setting);
}
auto codec_info_map_iter =
kDefaultOffloadLeAudioCodecInfoMap.find(session_type);
if (codec_info_map_iter == kDefaultOffloadLeAudioCodecInfoMap.end())
return std::vector<CodecInfo>();
return codec_info_map_iter->second;
}
} // namespace audio
} // namespace bluetooth
} // namespace hardware

View File

@@ -18,6 +18,7 @@
#include <aidl/android/hardware/bluetooth/audio/CodecCapabilities.h>
#include <aidl/android/hardware/bluetooth/audio/CodecConfiguration.h>
#include <aidl/android/hardware/bluetooth/audio/CodecInfo.h>
#include <aidl/android/hardware/bluetooth/audio/LeAudioCodecCapabilitiesSetting.h>
#include <aidl/android/hardware/bluetooth/audio/LeAudioConfiguration.h>
#include <aidl/android/hardware/bluetooth/audio/OpusConfiguration.h>
@@ -46,6 +47,8 @@ class BluetoothAudioCodecs {
static std::vector<LeAudioCodecCapabilitiesSetting>
GetLeAudioOffloadCodecCapabilities(const SessionType& session_type);
static std::vector<CodecInfo> GetLeAudioOffloadCodecInfo(
const SessionType& session_type);
private:
template <typename T>

View File

@@ -14,6 +14,11 @@
* limitations under the License.
*/
#include <set>
#include "aidl/android/hardware/bluetooth/audio/ChannelMode.h"
#include "aidl/android/hardware/bluetooth/audio/CodecId.h"
#include "aidl_android_hardware_bluetooth_audio_setting_enums.h"
#define LOG_TAG "BTAudioCodecsProviderAidl"
#include "BluetoothLeAudioCodecsProvider.h"
@@ -50,6 +55,123 @@ BluetoothLeAudioCodecsProvider::ParseFromLeAudioOffloadSettingFile() {
return le_audio_offload_setting;
}
std::unordered_map<SessionType, std::vector<CodecInfo>>
BluetoothLeAudioCodecsProvider::GetLeAudioCodecInfo(
const std::optional<setting::LeAudioOffloadSetting>&
le_audio_offload_setting) {
// Load from previous storage if present
if (!session_codecs_map_.empty()) return session_codecs_map_;
isInvalidFileContent = true;
if (!le_audio_offload_setting.has_value()) return {};
// Load scenario, configuration, codec configuration and strategy
LoadConfigurationToMap(le_audio_offload_setting);
if (supported_scenarios_.empty() || configuration_map_.empty() ||
codec_configuration_map_.empty() || strategy_configuration_map_.empty())
return {};
// Map each configuration into a CodecInfo
std::unordered_map<std::string, CodecInfo> config_codec_info_map_;
for (auto& p : configuration_map_) {
// Initialize new CodecInfo for the config
auto config_name = p.first;
if (config_codec_info_map_.count(config_name) == 0)
config_codec_info_map_[config_name] = CodecInfo();
// Getting informations from codecConfig and strategyConfig
const auto codec_config_name = p.second.getCodecConfiguration();
const auto strategy_config_name = p.second.getStrategyConfiguration();
const auto codec_configuration_map_iter =
codec_configuration_map_.find(codec_config_name);
if (codec_configuration_map_iter == codec_configuration_map_.end())
continue;
const auto strategy_configuration_map_iter =
strategy_configuration_map_.find(strategy_config_name);
if (strategy_configuration_map_iter == strategy_configuration_map_.end())
continue;
const auto& codec_config = codec_configuration_map_iter->second;
const auto codec = codec_config.getCodec();
const auto& strategy_config = strategy_configuration_map_iter->second;
const auto strategy_config_channel_count =
strategy_config.getChannelCount();
// Initiate information
auto& codec_info = config_codec_info_map_[config_name];
switch (codec) {
case setting::CodecType::LC3:
codec_info.name = "LC3";
codec_info.id = CodecId::Core::LC3;
break;
default:
codec_info.name = "UNDEFINE";
codec_info.id = CodecId::make<CodecId::Tag::undef>();
break;
}
codec_info.transport =
CodecInfo::Transport::make<CodecInfo::Transport::Tag::leAudio>();
// Mapping codec configuration information
auto& transport =
codec_info.transport.get<CodecInfo::Transport::Tag::leAudio>();
transport.samplingFrequencyHz.push_back(
codec_config.getSamplingFrequency());
// Mapping octetsPerCodecFrame to bitdepth for easier comparison.
transport.bitdepth.push_back(codec_config.getOctetsPerCodecFrame());
transport.frameDurationUs.push_back(codec_config.getFrameDurationUs());
switch (strategy_config.getAudioLocation()) {
case setting::AudioLocation::MONO:
if (strategy_config_channel_count == 1)
transport.channelMode.push_back(ChannelMode::MONO);
else
transport.channelMode.push_back(ChannelMode::DUALMONO);
break;
case setting::AudioLocation::STEREO:
transport.channelMode.push_back(ChannelMode::STEREO);
break;
default:
transport.channelMode.push_back(ChannelMode::UNKNOWN);
break;
}
}
// Goes through every scenario, deduplicate configuration
std::set<std::string> encoding_config, decoding_config, broadcast_config;
for (auto& s : supported_scenarios_) {
if (s.hasEncode()) encoding_config.insert(s.getEncode());
if (s.hasDecode()) decoding_config.insert(s.getDecode());
if (s.hasBroadcast()) broadcast_config.insert(s.getBroadcast());
}
// Split by session types and add results
const auto encoding_path =
SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH;
const auto decoding_path =
SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH;
const auto broadcast_path =
SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH;
session_codecs_map_ =
std::unordered_map<SessionType, std::vector<CodecInfo>>();
session_codecs_map_[encoding_path] = std::vector<CodecInfo>();
session_codecs_map_[decoding_path] = std::vector<CodecInfo>();
session_codecs_map_[broadcast_path] = std::vector<CodecInfo>();
session_codecs_map_[encoding_path].reserve(encoding_config.size());
session_codecs_map_[decoding_path].reserve(decoding_config.size());
session_codecs_map_[broadcast_path].reserve(broadcast_config.size());
for (auto& c : encoding_config)
session_codecs_map_[encoding_path].push_back(config_codec_info_map_[c]);
for (auto& c : decoding_config)
session_codecs_map_[decoding_path].push_back(config_codec_info_map_[c]);
for (auto& c : broadcast_config)
session_codecs_map_[broadcast_path].push_back(config_codec_info_map_[c]);
isInvalidFileContent = session_codecs_map_.empty();
return session_codecs_map_;
}
std::vector<LeAudioCodecCapabilitiesSetting>
BluetoothLeAudioCodecsProvider::GetLeAudioCodecCapabilities(
const std::optional<setting::LeAudioOffloadSetting>&
@@ -58,6 +180,8 @@ BluetoothLeAudioCodecsProvider::GetLeAudioCodecCapabilities(
return leAudioCodecCapabilities;
}
isInvalidFileContent = true;
if (!le_audio_offload_setting.has_value()) {
LOG(ERROR)
<< __func__
@@ -65,40 +189,13 @@ BluetoothLeAudioCodecsProvider::GetLeAudioCodecCapabilities(
return {};
}
ClearLeAudioCodecCapabilities();
isInvalidFileContent = true;
std::vector<setting::Scenario> supported_scenarios =
GetScenarios(le_audio_offload_setting);
if (supported_scenarios.empty()) {
LOG(ERROR) << __func__ << ": No scenarios in "
<< kLeAudioCodecCapabilitiesFile;
LoadConfigurationToMap(le_audio_offload_setting);
if (supported_scenarios_.empty() || configuration_map_.empty() ||
codec_configuration_map_.empty() || strategy_configuration_map_.empty())
return {};
}
UpdateConfigurationsToMap(le_audio_offload_setting);
if (configuration_map_.empty()) {
LOG(ERROR) << __func__ << ": No configurations in "
<< kLeAudioCodecCapabilitiesFile;
return {};
}
UpdateCodecConfigurationsToMap(le_audio_offload_setting);
if (codec_configuration_map_.empty()) {
LOG(ERROR) << __func__ << ": No codec configurations in "
<< kLeAudioCodecCapabilitiesFile;
return {};
}
UpdateStrategyConfigurationsToMap(le_audio_offload_setting);
if (strategy_configuration_map_.empty()) {
LOG(ERROR) << __func__ << ": No strategy configurations in "
<< kLeAudioCodecCapabilitiesFile;
return {};
}
leAudioCodecCapabilities =
ComposeLeAudioCodecCapabilities(supported_scenarios);
ComposeLeAudioCodecCapabilities(supported_scenarios_);
isInvalidFileContent = leAudioCodecCapabilities.empty();
return leAudioCodecCapabilities;
@@ -109,6 +206,8 @@ void BluetoothLeAudioCodecsProvider::ClearLeAudioCodecCapabilities() {
configuration_map_.clear();
codec_configuration_map_.clear();
strategy_configuration_map_.clear();
session_codecs_map_.clear();
supported_scenarios_.clear();
}
std::vector<setting::Scenario> BluetoothLeAudioCodecsProvider::GetScenarios(
@@ -191,6 +290,40 @@ void BluetoothLeAudioCodecsProvider::UpdateStrategyConfigurationsToMap(
}
}
void BluetoothLeAudioCodecsProvider::LoadConfigurationToMap(
const std::optional<setting::LeAudioOffloadSetting>&
le_audio_offload_setting) {
ClearLeAudioCodecCapabilities();
supported_scenarios_ = GetScenarios(le_audio_offload_setting);
if (supported_scenarios_.empty()) {
LOG(ERROR) << __func__ << ": No scenarios in "
<< kLeAudioCodecCapabilitiesFile;
return;
}
UpdateConfigurationsToMap(le_audio_offload_setting);
if (configuration_map_.empty()) {
LOG(ERROR) << __func__ << ": No configurations in "
<< kLeAudioCodecCapabilitiesFile;
return;
}
UpdateCodecConfigurationsToMap(le_audio_offload_setting);
if (codec_configuration_map_.empty()) {
LOG(ERROR) << __func__ << ": No codec configurations in "
<< kLeAudioCodecCapabilitiesFile;
return;
}
UpdateStrategyConfigurationsToMap(le_audio_offload_setting);
if (strategy_configuration_map_.empty()) {
LOG(ERROR) << __func__ << ": No strategy configurations in "
<< kLeAudioCodecCapabilitiesFile;
return;
}
}
std::vector<LeAudioCodecCapabilitiesSetting>
BluetoothLeAudioCodecsProvider::ComposeLeAudioCodecCapabilities(
const std::vector<setting::Scenario>& supported_scenarios) {

View File

@@ -22,6 +22,8 @@
#include <unordered_map>
#include <vector>
#include "aidl/android/hardware/bluetooth/audio/CodecInfo.h"
#include "aidl/android/hardware/bluetooth/audio/SessionType.h"
#include "aidl_android_hardware_bluetooth_audio_setting.h"
namespace aidl {
@@ -39,14 +41,20 @@ class BluetoothLeAudioCodecsProvider {
const std::optional<setting::LeAudioOffloadSetting>&
le_audio_offload_setting);
static void ClearLeAudioCodecCapabilities();
static std::unordered_map<SessionType, std::vector<CodecInfo>>
GetLeAudioCodecInfo(const std::optional<setting::LeAudioOffloadSetting>&
le_audio_offload_setting);
private:
static inline std::vector<setting::Scenario> supported_scenarios_;
static inline std::unordered_map<std::string, setting::Configuration>
configuration_map_;
static inline std::unordered_map<std::string, setting::CodecConfiguration>
codec_configuration_map_;
static inline std::unordered_map<std::string, setting::StrategyConfiguration>
strategy_configuration_map_;
static inline std::unordered_map<SessionType, std::vector<CodecInfo>>
session_codecs_map_;
static std::vector<setting::Scenario> GetScenarios(
const std::optional<setting::LeAudioOffloadSetting>&
@@ -60,6 +68,9 @@ class BluetoothLeAudioCodecsProvider {
static void UpdateStrategyConfigurationsToMap(
const std::optional<setting::LeAudioOffloadSetting>&
le_audio_offload_setting);
static void LoadConfigurationToMap(
const std::optional<setting::LeAudioOffloadSetting>&
le_audio_offload_setting);
static std::vector<LeAudioCodecCapabilitiesSetting>
ComposeLeAudioCodecCapabilities(