Parse LE Audio Set Configuration into LeAudioAseConfiguration

Bug: 306225778
Test: mmm hardware/interfaces/bluetooth/audio/utils
Change-Id: Ia08568322e1cee1834e08172781cc77342cbd025
diff --git a/bluetooth/audio/utils/Android.bp b/bluetooth/audio/utils/Android.bp
index 16ee70a..f5f8163 100644
--- a/bluetooth/audio/utils/Android.bp
+++ b/bluetooth/audio/utils/Android.bp
@@ -69,6 +69,12 @@
         "le_audio_codec_capabilities",
         "AIDLLeAudioSetConfigSchemas_h",
     ],
+    required: [
+        "aidl_audio_set_configurations_bfbs",
+        "aidl_audio_set_configurations_json",
+        "aidl_audio_set_scenarios_bfbs",
+        "aidl_audio_set_scenarios_json",
+    ],
 }
 
 cc_test {
@@ -155,6 +161,7 @@
     src: ":AIDLLeAudioSetScenariosSchema_bfbs",
     filename: "aidl_audio_set_scenarios.bfbs",
     sub_dir: "aidl/le_audio",
+    vendor: true,
 }
 
 prebuilt_etc {
@@ -162,6 +169,7 @@
     src: "le_audio_configuration_set/audio_set_scenarios.json",
     filename: "aidl_audio_set_scenarios.json",
     sub_dir: "aidl/le_audio",
+    vendor: true,
 }
 
 prebuilt_etc {
@@ -169,6 +177,7 @@
     src: ":AIDLLeAudioSetConfigsSchema_bfbs",
     filename: "aidl_audio_set_configurations.bfbs",
     sub_dir: "aidl/le_audio",
+    vendor: true,
 }
 
 prebuilt_etc {
@@ -176,4 +185,5 @@
     src: "le_audio_configuration_set/audio_set_configurations.json",
     filename: "aidl_audio_set_configurations.json",
     sub_dir: "aidl/le_audio",
+    vendor: true,
 }
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioAseConfigurationSettingProvider.cpp b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioAseConfigurationSettingProvider.cpp
new file mode 100644
index 0000000..56a4e17
--- /dev/null
+++ b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioAseConfigurationSettingProvider.cpp
@@ -0,0 +1,747 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#define STREAM_TO_UINT8(u8, p) \
+  {                            \
+    (u8) = (uint8_t)(*(p));    \
+    (p) += 1;                  \
+  }
+#define STREAM_TO_UINT16(u16, p)                                  \
+  {                                                               \
+    (u16) = ((uint16_t)(*(p)) + (((uint16_t)(*((p) + 1))) << 8)); \
+    (p) += 2;                                                     \
+  }
+#define STREAM_TO_UINT32(u32, p)                                      \
+  {                                                                   \
+    (u32) = (((uint32_t)(*(p))) + ((((uint32_t)(*((p) + 1)))) << 8) + \
+             ((((uint32_t)(*((p) + 2)))) << 16) +                     \
+             ((((uint32_t)(*((p) + 3)))) << 24));                     \
+    (p) += 4;                                                         \
+  }
+
+#define LOG_TAG "BTAudioCodecsAidl"
+
+#include "BluetoothLeAudioAseConfigurationSettingProvider.h"
+
+#include <aidl/android/hardware/bluetooth/audio/AudioConfiguration.h>
+#include <aidl/android/hardware/bluetooth/audio/AudioContext.h>
+#include <aidl/android/hardware/bluetooth/audio/BluetoothAudioStatus.h>
+#include <aidl/android/hardware/bluetooth/audio/CodecId.h>
+#include <aidl/android/hardware/bluetooth/audio/CodecSpecificCapabilitiesLtv.h>
+#include <aidl/android/hardware/bluetooth/audio/CodecSpecificConfigurationLtv.h>
+#include <aidl/android/hardware/bluetooth/audio/ConfigurationFlags.h>
+#include <aidl/android/hardware/bluetooth/audio/LeAudioAseConfiguration.h>
+#include <aidl/android/hardware/bluetooth/audio/Phy.h>
+#include <android-base/logging.h>
+
+#include "flatbuffers/idl.h"
+#include "flatbuffers/util.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+/* Internal structure definition */
+std::map<std::string,
+         std::tuple<std::vector<std::optional<AseDirectionConfiguration>>*,
+                    std::vector<std::optional<AseDirectionConfiguration>>*,
+                    ConfigurationFlags*>>
+    configurations_;
+
+std::vector<LeAudioAseConfigurationSetting> ase_configuration_settings_;
+
+constexpr uint8_t kIsoDataPathHci = 0x00;
+constexpr uint8_t kIsoDataPathPlatformDefault = 0x01;
+constexpr uint8_t kIsoDataPathDisabled = 0xFF;
+
+constexpr uint8_t kLeAudioDirectionSink = 0x01;
+constexpr uint8_t kLeAudioDirectionSource = 0x02;
+constexpr uint8_t kLeAudioDirectionBoth =
+    kLeAudioDirectionSink | kLeAudioDirectionSource;
+
+/* Sampling Frequencies */
+constexpr uint8_t kLeAudioSamplingFreq8000Hz = 0x01;
+constexpr uint8_t kLeAudioSamplingFreq11025Hz = 0x02;
+constexpr uint8_t kLeAudioSamplingFreq16000Hz = 0x03;
+constexpr uint8_t kLeAudioSamplingFreq22050Hz = 0x04;
+constexpr uint8_t kLeAudioSamplingFreq24000Hz = 0x05;
+constexpr uint8_t kLeAudioSamplingFreq32000Hz = 0x06;
+constexpr uint8_t kLeAudioSamplingFreq44100Hz = 0x07;
+constexpr uint8_t kLeAudioSamplingFreq48000Hz = 0x08;
+constexpr uint8_t kLeAudioSamplingFreq88200Hz = 0x09;
+constexpr uint8_t kLeAudioSamplingFreq96000Hz = 0x0A;
+constexpr uint8_t kLeAudioSamplingFreq176400Hz = 0x0B;
+constexpr uint8_t kLeAudioSamplingFreq192000Hz = 0x0C;
+constexpr uint8_t kLeAudioSamplingFreq384000Hz = 0x0D;
+
+/* Frame Durations */
+constexpr uint8_t kLeAudioCodecFrameDur7500us = 0x00;
+constexpr uint8_t kLeAudioCodecFrameDur10000us = 0x01;
+
+/* Audio Allocations */
+constexpr uint32_t kLeAudioLocationNotAllowed = 0x00000000;
+constexpr uint32_t kLeAudioLocationFrontLeft = 0x00000001;
+constexpr uint32_t kLeAudioLocationFrontRight = 0x00000002;
+constexpr uint32_t kLeAudioLocationFrontCenter = 0x00000004;
+constexpr uint32_t kLeAudioLocationLowFreqEffects1 = 0x00000008;
+constexpr uint32_t kLeAudioLocationBackLeft = 0x00000010;
+constexpr uint32_t kLeAudioLocationBackRight = 0x00000020;
+constexpr uint32_t kLeAudioLocationFrontLeftOfCenter = 0x00000040;
+constexpr uint32_t kLeAudioLocationFrontRightOfCenter = 0x00000080;
+constexpr uint32_t kLeAudioLocationBackCenter = 0x00000100;
+constexpr uint32_t kLeAudioLocationLowFreqEffects2 = 0x00000200;
+constexpr uint32_t kLeAudioLocationSideLeft = 0x00000400;
+constexpr uint32_t kLeAudioLocationSideRight = 0x00000800;
+constexpr uint32_t kLeAudioLocationTopFrontLeft = 0x00001000;
+constexpr uint32_t kLeAudioLocationTopFrontRight = 0x00002000;
+constexpr uint32_t kLeAudioLocationTopFrontCenter = 0x00004000;
+constexpr uint32_t kLeAudioLocationTopCenter = 0x00008000;
+constexpr uint32_t kLeAudioLocationTopBackLeft = 0x00010000;
+constexpr uint32_t kLeAudioLocationTopBackRight = 0x00020000;
+constexpr uint32_t kLeAudioLocationTopSideLeft = 0x00040000;
+constexpr uint32_t kLeAudioLocationTopSideRight = 0x00080000;
+constexpr uint32_t kLeAudioLocationTopBackCenter = 0x00100000;
+constexpr uint32_t kLeAudioLocationBottomFrontCenter = 0x00200000;
+constexpr uint32_t kLeAudioLocationBottomFrontLeft = 0x00400000;
+constexpr uint32_t kLeAudioLocationBottomFrontRight = 0x00800000;
+constexpr uint32_t kLeAudioLocationFrontLeftWide = 0x01000000;
+constexpr uint32_t kLeAudioLocationFrontRightWide = 0x02000000;
+constexpr uint32_t kLeAudioLocationLeftSurround = 0x04000000;
+constexpr uint32_t kLeAudioLocationRightSurround = 0x08000000;
+
+constexpr uint32_t kLeAudioLocationAnyLeft =
+    kLeAudioLocationFrontLeft | kLeAudioLocationBackLeft |
+    kLeAudioLocationFrontLeftOfCenter | kLeAudioLocationSideLeft |
+    kLeAudioLocationTopFrontLeft | kLeAudioLocationTopBackLeft |
+    kLeAudioLocationTopSideLeft | kLeAudioLocationBottomFrontLeft |
+    kLeAudioLocationFrontLeftWide | kLeAudioLocationLeftSurround;
+
+constexpr uint32_t kLeAudioLocationAnyRight =
+    kLeAudioLocationFrontRight | kLeAudioLocationBackRight |
+    kLeAudioLocationFrontRightOfCenter | kLeAudioLocationSideRight |
+    kLeAudioLocationTopFrontRight | kLeAudioLocationTopBackRight |
+    kLeAudioLocationTopSideRight | kLeAudioLocationBottomFrontRight |
+    kLeAudioLocationFrontRightWide | kLeAudioLocationRightSurround;
+
+constexpr uint32_t kLeAudioLocationStereo =
+    kLeAudioLocationFrontLeft | kLeAudioLocationFrontRight;
+
+/* Octets Per Frame */
+constexpr uint16_t kLeAudioCodecFrameLen30 = 30;
+constexpr uint16_t kLeAudioCodecFrameLen40 = 40;
+constexpr uint16_t kLeAudioCodecFrameLen60 = 60;
+constexpr uint16_t kLeAudioCodecFrameLen80 = 80;
+constexpr uint16_t kLeAudioCodecFrameLen100 = 100;
+constexpr uint16_t kLeAudioCodecFrameLen120 = 120;
+
+/* Helper map for matching various sampling frequency notations */
+const std::map<uint8_t, CodecSpecificConfigurationLtv::SamplingFrequency>
+    sampling_freq_map = {
+        {kLeAudioSamplingFreq8000Hz,
+         CodecSpecificConfigurationLtv::SamplingFrequency::HZ8000},
+        {kLeAudioSamplingFreq16000Hz,
+         CodecSpecificConfigurationLtv::SamplingFrequency::HZ16000},
+        {kLeAudioSamplingFreq24000Hz,
+         CodecSpecificConfigurationLtv::SamplingFrequency::HZ24000},
+        {kLeAudioSamplingFreq32000Hz,
+         CodecSpecificConfigurationLtv::SamplingFrequency::HZ32000},
+        {kLeAudioSamplingFreq44100Hz,
+         CodecSpecificConfigurationLtv::SamplingFrequency::HZ44100},
+        {kLeAudioSamplingFreq48000Hz,
+         CodecSpecificConfigurationLtv::SamplingFrequency::HZ48000}};
+
+/* Helper map for matching various frame durations notations */
+const std::map<uint8_t, CodecSpecificConfigurationLtv::FrameDuration>
+    frame_duration_map = {
+        {kLeAudioCodecFrameDur7500us,
+         CodecSpecificConfigurationLtv::FrameDuration::US7500},
+        {kLeAudioCodecFrameDur10000us,
+         CodecSpecificConfigurationLtv::FrameDuration::US10000}};
+
+/* Helper map for matching various audio channel allocation notations */
+std::map<uint32_t, uint32_t> audio_channel_allocation_map = {
+    {kLeAudioLocationNotAllowed,
+     CodecSpecificConfigurationLtv::AudioChannelAllocation::NOT_ALLOWED},
+    {kLeAudioLocationFrontLeft,
+     CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_LEFT},
+    {kLeAudioLocationFrontRight,
+     CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_RIGHT},
+    {kLeAudioLocationFrontCenter,
+     CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_CENTER},
+    {kLeAudioLocationLowFreqEffects1,
+     CodecSpecificConfigurationLtv::AudioChannelAllocation::
+         LOW_FREQUENCY_EFFECTS_1},
+    {kLeAudioLocationBackLeft,
+     CodecSpecificConfigurationLtv::AudioChannelAllocation::BACK_LEFT},
+    {kLeAudioLocationBackRight,
+     CodecSpecificConfigurationLtv::AudioChannelAllocation::BACK_RIGHT},
+    {kLeAudioLocationFrontLeftOfCenter,
+     CodecSpecificConfigurationLtv::AudioChannelAllocation::
+         FRONT_LEFT_OF_CENTER},
+    {kLeAudioLocationFrontRightOfCenter,
+     CodecSpecificConfigurationLtv::AudioChannelAllocation::
+         FRONT_RIGHT_OF_CENTER},
+    {kLeAudioLocationBackCenter,
+     CodecSpecificConfigurationLtv::AudioChannelAllocation::BACK_CENTER},
+    {kLeAudioLocationLowFreqEffects2,
+     CodecSpecificConfigurationLtv::AudioChannelAllocation::
+         LOW_FREQUENCY_EFFECTS_2},
+    {kLeAudioLocationSideLeft,
+     CodecSpecificConfigurationLtv::AudioChannelAllocation::SIDE_LEFT},
+    {kLeAudioLocationSideRight,
+     CodecSpecificConfigurationLtv::AudioChannelAllocation::SIDE_RIGHT},
+    {kLeAudioLocationTopFrontLeft,
+     CodecSpecificConfigurationLtv::AudioChannelAllocation::TOP_FRONT_LEFT},
+    {kLeAudioLocationTopFrontRight,
+     CodecSpecificConfigurationLtv::AudioChannelAllocation::TOP_FRONT_RIGHT},
+    {kLeAudioLocationTopFrontCenter,
+     CodecSpecificConfigurationLtv::AudioChannelAllocation::TOP_FRONT_CENTER},
+    {kLeAudioLocationTopCenter,
+     CodecSpecificConfigurationLtv::AudioChannelAllocation::TOP_CENTER},
+    {kLeAudioLocationTopBackLeft,
+     CodecSpecificConfigurationLtv::AudioChannelAllocation::TOP_BACK_LEFT},
+    {kLeAudioLocationTopBackRight,
+     CodecSpecificConfigurationLtv::AudioChannelAllocation::TOP_BACK_RIGHT},
+    {kLeAudioLocationTopSideLeft,
+     CodecSpecificConfigurationLtv::AudioChannelAllocation::TOP_SIDE_LEFT},
+    {kLeAudioLocationTopSideRight,
+     CodecSpecificConfigurationLtv::AudioChannelAllocation::TOP_SIDE_RIGHT},
+    {kLeAudioLocationTopBackCenter,
+     CodecSpecificConfigurationLtv::AudioChannelAllocation::TOP_BACK_CENTER},
+    {kLeAudioLocationBottomFrontCenter,
+     CodecSpecificConfigurationLtv::AudioChannelAllocation::
+         BOTTOM_FRONT_CENTER},
+    {kLeAudioLocationBottomFrontLeft,
+     CodecSpecificConfigurationLtv::AudioChannelAllocation::BOTTOM_FRONT_LEFT},
+    {kLeAudioLocationBottomFrontRight,
+     CodecSpecificConfigurationLtv::AudioChannelAllocation::BOTTOM_FRONT_RIGHT},
+    {kLeAudioLocationFrontLeftWide,
+     CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_LEFT_WIDE},
+    {kLeAudioLocationFrontRightWide,
+     CodecSpecificConfigurationLtv::AudioChannelAllocation::FRONT_RIGHT_WIDE},
+    {kLeAudioLocationLeftSurround,
+     CodecSpecificConfigurationLtv::AudioChannelAllocation::LEFT_SURROUND},
+    {kLeAudioLocationRightSurround,
+     CodecSpecificConfigurationLtv::AudioChannelAllocation::RIGHT_SURROUND},
+};
+
+static const std::vector<
+    std::pair<const char* /*schema*/, const char* /*content*/>>
+    kLeAudioSetConfigs = {{"/vendor/etc/aidl/le_audio/"
+                           "aidl_audio_set_configurations.bfbs",
+                           "/vendor/etc/aidl/le_audio/"
+                           "aidl_audio_set_configurations.json"}};
+static const std::vector<
+    std::pair<const char* /*schema*/, const char* /*content*/>>
+    kLeAudioSetScenarios = {{"/vendor/etc/aidl/le_audio/"
+                             "aidl_audio_set_scenarios.bfbs",
+                             "/vendor/etc/aidl/le_audio/"
+                             "aidl_audio_set_configurations.json"}};
+
+/* Implementation */
+
+std::vector<LeAudioAseConfigurationSetting>
+AudioSetConfigurationProviderJson::GetLeAudioAseConfigurationSettings() {
+  AudioSetConfigurationProviderJson::LoadAudioSetConfigurationProviderJson();
+  return ase_configuration_settings_;
+}
+
+void AudioSetConfigurationProviderJson::
+    LoadAudioSetConfigurationProviderJson() {
+  if (configurations_.empty() && ase_configuration_settings_.empty()) {
+    auto loaded = LoadContent(kLeAudioSetConfigs, kLeAudioSetScenarios,
+                              CodecLocation::HOST);
+    if (!loaded)
+      LOG(ERROR) << ": Unable to load le audio set configuration files.";
+  } else
+    LOG(INFO) << ": Reusing loaded le audio set configuration";
+}
+
+const le_audio::CodecSpecificConfiguration*
+AudioSetConfigurationProviderJson::LookupCodecSpecificParam(
+    const flatbuffers::Vector<flatbuffers::Offset<
+        le_audio::CodecSpecificConfiguration>>* flat_codec_specific_params,
+    le_audio::CodecSpecificLtvGenericTypes type) {
+  auto it = std::find_if(
+      flat_codec_specific_params->cbegin(), flat_codec_specific_params->cend(),
+      [&type](const auto& csc) { return (csc->type() == type); });
+  return (it != flat_codec_specific_params->cend()) ? *it : nullptr;
+}
+
+void AudioSetConfigurationProviderJson::populateAudioChannelAllocation(
+    CodecSpecificConfigurationLtv::AudioChannelAllocation&
+        audio_channel_allocation,
+    uint32_t audio_location) {
+  audio_channel_allocation.bitmask = 0;
+  for (auto [allocation, bitmask] : audio_channel_allocation_map) {
+    if (audio_location & allocation)
+      audio_channel_allocation.bitmask |= bitmask;
+  }
+}
+
+void AudioSetConfigurationProviderJson::populateConfigurationData(
+    LeAudioAseConfiguration& ase,
+    const flatbuffers::Vector<
+        flatbuffers::Offset<le_audio::CodecSpecificConfiguration>>*
+        flat_codec_specific_params) {
+  uint8_t sampling_frequency = 0;
+  uint8_t frame_duration = 0;
+  uint32_t audio_channel_allocation = 0;
+  uint16_t octets_per_codec_frame = 0;
+  uint8_t codec_frames_blocks_per_sdu = 0;
+
+  auto param = LookupCodecSpecificParam(
+      flat_codec_specific_params,
+      le_audio::CodecSpecificLtvGenericTypes_SUPPORTED_SAMPLING_FREQUENCY);
+  if (param) {
+    auto ptr = param->compound_value()->value()->data();
+    STREAM_TO_UINT8(sampling_frequency, ptr);
+  }
+
+  param = LookupCodecSpecificParam(
+      flat_codec_specific_params,
+      le_audio::CodecSpecificLtvGenericTypes_SUPPORTED_FRAME_DURATION);
+  if (param) {
+    auto ptr = param->compound_value()->value()->data();
+    STREAM_TO_UINT8(frame_duration, ptr);
+  }
+
+  param = LookupCodecSpecificParam(
+      flat_codec_specific_params,
+      le_audio::
+          CodecSpecificLtvGenericTypes_SUPPORTED_AUDIO_CHANNEL_ALLOCATION);
+  if (param) {
+    auto ptr = param->compound_value()->value()->data();
+    STREAM_TO_UINT32(audio_channel_allocation, ptr);
+  }
+
+  param = LookupCodecSpecificParam(
+      flat_codec_specific_params,
+      le_audio::CodecSpecificLtvGenericTypes_SUPPORTED_OCTETS_PER_CODEC_FRAME);
+  if (param) {
+    auto ptr = param->compound_value()->value()->data();
+    STREAM_TO_UINT16(octets_per_codec_frame, ptr);
+  }
+
+  param = LookupCodecSpecificParam(
+      flat_codec_specific_params,
+      le_audio::
+          CodecSpecificLtvGenericTypes_SUPPORTED_CODEC_FRAME_BLOCKS_PER_SDU);
+  if (param) {
+    auto ptr = param->compound_value()->value()->data();
+    STREAM_TO_UINT8(codec_frames_blocks_per_sdu, ptr);
+  }
+
+  // Make the correct value
+  ase.codecConfiguration = std::vector<CodecSpecificConfigurationLtv>();
+
+  auto sampling_freq_it = sampling_freq_map.find(sampling_frequency);
+  if (sampling_freq_it != sampling_freq_map.end())
+    ase.codecConfiguration.push_back(sampling_freq_it->second);
+  auto frame_duration_it = frame_duration_map.find(frame_duration);
+  if (frame_duration_it != frame_duration_map.end())
+    ase.codecConfiguration.push_back(frame_duration_it->second);
+
+  CodecSpecificConfigurationLtv::AudioChannelAllocation channel_allocation;
+  populateAudioChannelAllocation(channel_allocation, audio_channel_allocation);
+  ase.codecConfiguration.push_back(channel_allocation);
+
+  auto octet_structure = CodecSpecificConfigurationLtv::OctetsPerCodecFrame();
+  octet_structure.value = octets_per_codec_frame;
+  ase.codecConfiguration.push_back(octet_structure);
+
+  auto frame_sdu_structure =
+      CodecSpecificConfigurationLtv::CodecFrameBlocksPerSDU();
+  frame_sdu_structure.value = codec_frames_blocks_per_sdu;
+  ase.codecConfiguration.push_back(frame_sdu_structure);
+  // TODO: Channel count
+}
+
+void AudioSetConfigurationProviderJson::populateAseConfiguration(
+    LeAudioAseConfiguration& ase,
+    const le_audio::AudioSetSubConfiguration* flat_subconfig,
+    const le_audio::QosConfiguration* qos_cfg) {
+  // Target latency
+  switch (qos_cfg->target_latency()) {
+    case le_audio::AudioSetConfigurationTargetLatency::
+        AudioSetConfigurationTargetLatency_BALANCED_RELIABILITY:
+      ase.targetLatency =
+          LeAudioAseConfiguration::TargetLatency::BALANCED_LATENCY_RELIABILITY;
+      break;
+    case le_audio::AudioSetConfigurationTargetLatency::
+        AudioSetConfigurationTargetLatency_HIGH_RELIABILITY:
+      ase.targetLatency =
+          LeAudioAseConfiguration::TargetLatency::HIGHER_RELIABILITY;
+      break;
+    case le_audio::AudioSetConfigurationTargetLatency::
+        AudioSetConfigurationTargetLatency_LOW:
+      ase.targetLatency = LeAudioAseConfiguration::TargetLatency::LOWER;
+      break;
+    default:
+      ase.targetLatency = LeAudioAseConfiguration::TargetLatency::UNDEFINED;
+      break;
+  };
+
+  ase.targetPhy = Phy::TWO_M;
+  // Making CodecId
+  if (flat_subconfig->codec_id()->coding_format() ==
+      (uint8_t)CodecId::Core::LC3) {
+    ase.codecId = CodecId::Core::LC3;
+  } else {
+    auto vendorC = CodecId::Vendor();
+    vendorC.codecId = flat_subconfig->codec_id()->vendor_codec_id();
+    vendorC.id = flat_subconfig->codec_id()->vendor_company_id();
+    ase.codecId = vendorC;
+  }
+  // Codec configuration data
+  populateConfigurationData(ase, flat_subconfig->codec_configuration());
+}
+
+void AudioSetConfigurationProviderJson::populateAseQosConfiguration(
+    LeAudioAseQosConfiguration& qos,
+    const le_audio::QosConfiguration* qos_cfg) {
+  qos.maxTransportLatencyMs = qos_cfg->max_transport_latency();
+  qos.retransmissionNum = qos_cfg->retransmission_number();
+}
+
+// Parse into AseDirectionConfiguration
+AseDirectionConfiguration
+AudioSetConfigurationProviderJson::SetConfigurationFromFlatSubconfig(
+    const le_audio::AudioSetSubConfiguration* flat_subconfig,
+    const le_audio::QosConfiguration* qos_cfg, CodecLocation location) {
+  AseDirectionConfiguration direction_conf;
+
+  LeAudioAseConfiguration ase;
+  LeAudioAseQosConfiguration qos;
+  LeAudioDataPathConfiguration path;
+
+  // Translate into LeAudioAseConfiguration
+  populateAseConfiguration(ase, flat_subconfig, qos_cfg);
+
+  // Translate into LeAudioAseQosConfiguration
+  populateAseQosConfiguration(qos, qos_cfg);
+
+  // Translate location to data path id
+  switch (location) {
+    case CodecLocation::ADSP:
+      path.isoDataPathConfiguration.isTransparent = true;
+      path.dataPathId = kIsoDataPathPlatformDefault;
+      break;
+    case CodecLocation::HOST:
+      path.isoDataPathConfiguration.isTransparent = true;
+      path.dataPathId = kIsoDataPathHci;
+      break;
+    case CodecLocation::CONTROLLER:
+      path.isoDataPathConfiguration.isTransparent = false;
+      path.dataPathId = kIsoDataPathPlatformDefault;
+      break;
+  }
+
+  direction_conf.aseConfiguration = ase;
+  direction_conf.qosConfiguration = qos;
+  direction_conf.dataPathConfiguration = path;
+
+  return direction_conf;
+}
+
+// Parse into AseDirectionConfiguration and the ConfigurationFlags
+// and put them in the given list.
+void AudioSetConfigurationProviderJson::processSubconfig(
+    const le_audio::AudioSetSubConfiguration* subconfig,
+    const le_audio::QosConfiguration* qos_cfg,
+    std::vector<std::optional<AseDirectionConfiguration>>&
+        directionAseConfiguration,
+    CodecLocation location) {
+  directionAseConfiguration.push_back(
+      SetConfigurationFromFlatSubconfig(subconfig, qos_cfg, location));
+}
+
+void AudioSetConfigurationProviderJson::PopulateAseConfigurationFromFlat(
+    const le_audio::AudioSetConfiguration* flat_cfg,
+    std::vector<const le_audio::CodecConfiguration*>* codec_cfgs,
+    std::vector<const le_audio::QosConfiguration*>* qos_cfgs,
+    CodecLocation location,
+    std::vector<std::optional<AseDirectionConfiguration>>&
+        sourceAseConfiguration,
+    std::vector<std::optional<AseDirectionConfiguration>>& sinkAseConfiguration,
+    ConfigurationFlags& /*configurationFlags*/) {
+  if (flat_cfg == nullptr) {
+    LOG(ERROR) << "flat_cfg cannot be null";
+    return;
+  }
+  std::string codec_config_key = flat_cfg->codec_config_name()->str();
+  auto* qos_config_key_array = flat_cfg->qos_config_name();
+
+  constexpr std::string_view default_qos = "QoS_Config_Balanced_Reliability";
+
+  std::string qos_sink_key(default_qos);
+  std::string qos_source_key(default_qos);
+
+  /* We expect maximum two QoS settings. First for Sink and second for Source
+   */
+  if (qos_config_key_array->size() > 0) {
+    qos_sink_key = qos_config_key_array->Get(0)->str();
+    if (qos_config_key_array->size() > 1) {
+      qos_source_key = qos_config_key_array->Get(1)->str();
+    } else {
+      qos_source_key = qos_sink_key;
+    }
+  }
+
+  LOG(INFO) << "Audio set config " << flat_cfg->name()->c_str()
+            << ": codec config " << codec_config_key.c_str() << ", qos_sink "
+            << qos_sink_key.c_str() << ", qos_source "
+            << qos_source_key.c_str();
+
+  // Find the first qos config that match the name
+  const le_audio::QosConfiguration* qos_sink_cfg = nullptr;
+  for (auto i = qos_cfgs->begin(); i != qos_cfgs->end(); ++i) {
+    if ((*i)->name()->str() == qos_sink_key) {
+      qos_sink_cfg = *i;
+      break;
+    }
+  }
+
+  const le_audio::QosConfiguration* qos_source_cfg = nullptr;
+  for (auto i = qos_cfgs->begin(); i != qos_cfgs->end(); ++i) {
+    if ((*i)->name()->str() == qos_source_key) {
+      qos_source_cfg = *i;
+      break;
+    }
+  }
+
+  // First codec_cfg with the same name
+  const le_audio::CodecConfiguration* codec_cfg = nullptr;
+  for (auto i = codec_cfgs->begin(); i != codec_cfgs->end(); ++i) {
+    if ((*i)->name()->str() == codec_config_key) {
+      codec_cfg = *i;
+      break;
+    }
+  }
+
+  // Process each subconfig and put it into the correct list
+  if (codec_cfg != nullptr && codec_cfg->subconfigurations()) {
+    /* Load subconfigurations */
+    for (auto subconfig : *codec_cfg->subconfigurations()) {
+      if (subconfig->direction() == kLeAudioDirectionSink) {
+        processSubconfig(subconfig, qos_sink_cfg, sinkAseConfiguration,
+                         location);
+      } else {
+        processSubconfig(subconfig, qos_source_cfg, sourceAseConfiguration,
+                         location);
+      }
+    }
+  } else {
+    if (codec_cfg == nullptr) {
+      LOG(ERROR) << "No codec config matching key " << codec_config_key.c_str()
+                 << " found";
+    } else {
+      LOG(ERROR) << "Configuration '" << flat_cfg->name()->c_str()
+                 << "' has no valid subconfigurations.";
+    }
+  }
+
+  // TODO: Populate information for ConfigurationFlags
+}
+
+bool AudioSetConfigurationProviderJson::LoadConfigurationsFromFiles(
+    const char* schema_file, const char* content_file, CodecLocation location) {
+  flatbuffers::Parser configurations_parser_;
+  std::string configurations_schema_binary_content;
+  bool ok = flatbuffers::LoadFile(schema_file, true,
+                                  &configurations_schema_binary_content);
+  LOG(INFO) << __func__ << "Loading file " << schema_file;
+  if (!ok) return ok;
+
+  /* Load the binary schema */
+  ok = configurations_parser_.Deserialize(
+      (uint8_t*)configurations_schema_binary_content.c_str(),
+      configurations_schema_binary_content.length());
+  if (!ok) return ok;
+
+  /* Load the content from JSON */
+  std::string configurations_json_content;
+  LOG(INFO) << __func__ << "Loading file " << schema_file;
+  ok = flatbuffers::LoadFile(content_file, false, &configurations_json_content);
+  if (!ok) return ok;
+
+  /* Parse */
+  LOG(INFO) << __func__ << "Parse JSON content" << schema_file;
+  ok = configurations_parser_.Parse(configurations_json_content.c_str());
+  if (!ok) return ok;
+
+  /* Import from flatbuffers */
+  LOG(INFO) << __func__ << "Build flat buffer structure" << schema_file;
+  auto configurations_root = le_audio::GetAudioSetConfigurations(
+      configurations_parser_.builder_.GetBufferPointer());
+  if (!configurations_root) return false;
+
+  auto flat_qos_configs = configurations_root->qos_configurations();
+  if ((flat_qos_configs == nullptr) || (flat_qos_configs->size() == 0))
+    return false;
+
+  LOG(DEBUG) << ": Updating " << flat_qos_configs->size()
+             << " qos config entries.";
+  std::vector<const le_audio::QosConfiguration*> qos_cfgs;
+  for (auto const& flat_qos_cfg : *flat_qos_configs) {
+    qos_cfgs.push_back(flat_qos_cfg);
+  }
+
+  auto flat_codec_configs = configurations_root->codec_configurations();
+  if ((flat_codec_configs == nullptr) || (flat_codec_configs->size() == 0))
+    return false;
+
+  LOG(DEBUG) << ": Updating " << flat_codec_configs->size()
+             << " codec config entries.";
+  std::vector<const le_audio::CodecConfiguration*> codec_cfgs;
+  for (auto const& flat_codec_cfg : *flat_codec_configs) {
+    codec_cfgs.push_back(flat_codec_cfg);
+  }
+
+  auto flat_configs = configurations_root->configurations();
+  if ((flat_configs == nullptr) || (flat_configs->size() == 0)) return false;
+
+  LOG(DEBUG) << ": Updating " << flat_configs->size() << " config entries.";
+  for (auto const& flat_cfg : *flat_configs) {
+    // Create 3 vector to use
+    std::vector<std::optional<AseDirectionConfiguration>>
+        sourceAseConfiguration;
+    std::vector<std::optional<AseDirectionConfiguration>> sinkAseConfiguration;
+    ConfigurationFlags configurationFlags;
+    PopulateAseConfigurationFromFlat(flat_cfg, &codec_cfgs, &qos_cfgs, location,
+                                     sourceAseConfiguration,
+                                     sinkAseConfiguration, configurationFlags);
+    if (sourceAseConfiguration.empty() && sinkAseConfiguration.empty())
+      continue;
+    configurations_[flat_cfg->name()->str()] = std::make_tuple(
+        &sourceAseConfiguration, &sinkAseConfiguration, &configurationFlags);
+  }
+
+  return true;
+}
+
+bool AudioSetConfigurationProviderJson::LoadScenariosFromFiles(
+    const char* schema_file, const char* content_file) {
+  flatbuffers::Parser scenarios_parser_;
+  std::string scenarios_schema_binary_content;
+  bool ok = flatbuffers::LoadFile(schema_file, true,
+                                  &scenarios_schema_binary_content);
+  if (!ok) return ok;
+
+  /* Load the binary schema */
+  ok = scenarios_parser_.Deserialize(
+      (uint8_t*)scenarios_schema_binary_content.c_str(),
+      scenarios_schema_binary_content.length());
+  if (!ok) return ok;
+
+  /* Load the content from JSON */
+  std::string scenarios_json_content;
+  ok = flatbuffers::LoadFile(content_file, false, &scenarios_json_content);
+  if (!ok) return ok;
+
+  /* Parse */
+  ok = scenarios_parser_.Parse(scenarios_json_content.c_str());
+  if (!ok) return ok;
+
+  /* Import from flatbuffers */
+  auto scenarios_root = le_audio::GetAudioSetScenarios(
+      scenarios_parser_.builder_.GetBufferPointer());
+  if (!scenarios_root) return false;
+
+  auto flat_scenarios = scenarios_root->scenarios();
+  if ((flat_scenarios == nullptr) || (flat_scenarios->size() == 0))
+    return false;
+
+  AudioContext media_context = AudioContext();
+  media_context.bitmask =
+      (AudioContext::ALERTS | AudioContext::INSTRUCTIONAL |
+       AudioContext::NOTIFICATIONS | AudioContext::EMERGENCY_ALARM |
+       AudioContext::UNSPECIFIED | AudioContext::MEDIA);
+
+  AudioContext conversational_context = AudioContext();
+  conversational_context.bitmask =
+      (AudioContext::RINGTONE_ALERTS | AudioContext::CONVERSATIONAL);
+
+  AudioContext live_context = AudioContext();
+  live_context.bitmask = AudioContext::LIVE_AUDIO;
+
+  AudioContext game_context = AudioContext();
+  game_context.bitmask = AudioContext::GAME;
+
+  AudioContext voice_assistants_context = AudioContext();
+  voice_assistants_context.bitmask = AudioContext::VOICE_ASSISTANTS;
+
+  LOG(DEBUG) << ": Updating " << flat_scenarios->size() << " scenarios.";
+  for (auto const& scenario : *flat_scenarios) {
+    LOG(DEBUG) << "Scenario " << scenario->name()->c_str() << " configs:";
+
+    if (!scenario->configurations()) continue;
+    std::string scenario_name = scenario->name()->c_str();
+    AudioContext context;
+    if (scenario_name == "Media")
+      context = AudioContext(media_context);
+    else if (scenario_name == "Conversational")
+      context = AudioContext(conversational_context);
+    else if (scenario_name == "Live")
+      context = AudioContext(live_context);
+    else if (scenario_name == "Game")
+      context = AudioContext(game_context);
+    else if (scenario_name == "VoiceAssistants")
+      context = AudioContext(voice_assistants_context);
+
+    for (auto config_name : *scenario->configurations()) {
+      if (configurations_.count(config_name->str()) == 0) continue;
+      auto [source, sink, flags] = configurations_.at(config_name->str());
+      // Each configuration will create a LeAudioAseConfigurationSetting
+      // with the same {context, packing}
+      // and different data
+      LeAudioAseConfigurationSetting setting;
+      setting.audioContext = context;
+      // TODO: Packing
+      setting.sourceAseConfiguration = *source;
+      setting.sinkAseConfiguration = *sink;
+      setting.flags = *flags;
+      // Add to list of setting
+      ase_configuration_settings_.push_back(setting);
+    }
+  }
+
+  return true;
+}
+
+bool AudioSetConfigurationProviderJson::LoadContent(
+    std::vector<std::pair<const char* /*schema*/, const char* /*content*/>>
+        config_files,
+    std::vector<std::pair<const char* /*schema*/, const char* /*content*/>>
+        scenario_files,
+    CodecLocation location) {
+  for (auto [schema, content] : config_files) {
+    if (!LoadConfigurationsFromFiles(schema, content, location)) return false;
+  }
+
+  for (auto [schema, content] : scenario_files) {
+    if (!LoadScenariosFromFiles(schema, content)) return false;
+  }
+  return true;
+}
+
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl