Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7fbc0636 authored by Bao Do's avatar Bao Do Committed by Automerger Merge Worker
Browse files

Add LE Audio getProviderInfo information am: 6aeb5d72 am: f503dcd5 am: 42aaa6ad

parents ba84a27d 42aaa6ad
Loading
Loading
Loading
Loading
+1 −2
Original line number Diff line number Diff line
@@ -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);
+19 −0
Original line number Diff line number Diff line
@@ -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();
+27 −0
Original line number Diff line number Diff line
@@ -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
+3 −0
Original line number Diff line number Diff line
@@ -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>
+164 −31
Original line number Diff line number Diff line
@@ -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) {
Loading