Add LE Audio getProviderInfo information

Bug: 306225778
Test: mmm hardware/interfaces/bluetooth/audio/aidl/default
Change-Id: Ieb03a1a3096dbeb6a4e2ac4774ece6d3ef3e33be
diff --git a/bluetooth/audio/aidl/default/BluetoothAudioProvider.h b/bluetooth/audio/aidl/default/BluetoothAudioProvider.h
index ca33394..5064869 100644
--- a/bluetooth/audio/aidl/default/BluetoothAudioProvider.h
+++ b/bluetooth/audio/aidl/default/BluetoothAudioProvider.h
@@ -41,8 +41,7 @@
   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);
diff --git a/bluetooth/audio/aidl/default/BluetoothAudioProviderFactory.cpp b/bluetooth/audio/aidl/default/BluetoothAudioProviderFactory.cpp
index 3a64c4d..275cfec 100644
--- a/bluetooth/audio/aidl/default/BluetoothAudioProviderFactory.cpp
+++ b/bluetooth/audio/aidl/default/BluetoothAudioProviderFactory.cpp
@@ -37,6 +37,9 @@
 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 @@
     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();
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.cpp b/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.cpp
index 6e15b3b..1524f5e 100644
--- a/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.cpp
+++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.cpp
@@ -97,6 +97,8 @@
     {.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 @@
   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
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.h b/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.h
index e3d657b..01afb7a 100644
--- a/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.h
+++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.h
@@ -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 @@
 
   static std::vector<LeAudioCodecCapabilitiesSetting>
   GetLeAudioOffloadCodecCapabilities(const SessionType& session_type);
+  static std::vector<CodecInfo> GetLeAudioOffloadCodecInfo(
+      const SessionType& session_type);
 
  private:
   template <typename T>
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.cpp b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.cpp
index 26da5fb..8c7a740 100644
--- a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.cpp
+++ b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.cpp
@@ -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 @@
   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 @@
     return leAudioCodecCapabilities;
   }
 
+  isInvalidFileContent = true;
+
   if (!le_audio_offload_setting.has_value()) {
     LOG(ERROR)
         << __func__
@@ -65,40 +189,13 @@
     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 @@
   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::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) {
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.h b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.h
index 654e70c..5bf67e2 100644
--- a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.h
+++ b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.h
@@ -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 @@
       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 @@
   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(