From 5558bf9bdc326ea1fad98a1222d7de9c757ea9ce Mon Sep 17 00:00:00 2001
From: Jakub Tyszkowski <tyszkowski@google.com>
Date: Tue, 1 Aug 2023 11:23:42 +0000
Subject: [PATCH] LeAudio: Improve data path setup

The data path configuration should be provided by the audio set
configuration provider. For now, these are based on the current
codec location (either HOST or ADSP). In future this should
be provided from the vendor interface over the AIDL.

Bug: 295972694
Test: atest bluetooth_le_audio_test bluetooth_le_audio_client_test bluetooth_test_broadcaster bluetooth_test_broadcaster_state_machine
Change-Id: If39a1d1ac089f236e4ed9258644c197a57f1e723
---
 system/bta/le_audio/codec_manager.cc          | 12 ++--
 system/bta/le_audio/devices.cc                |  2 +
 system/bta/le_audio/devices_test.cc           |  3 +-
 system/bta/le_audio/le_audio_client_test.cc   |  3 +-
 .../le_audio_set_configuration_provider.h     |  2 +-
 ...e_audio_set_configuration_provider_json.cc | 70 +++++++++++++------
 system/bta/le_audio/le_audio_types.h          | 13 ++++
 system/bta/le_audio/state_machine.cc          | 15 ++--
 system/bta/le_audio/state_machine_test.cc     |  5 +-
 9 files changed, 82 insertions(+), 43 deletions(-)

diff --git a/system/bta/le_audio/codec_manager.cc b/system/bta/le_audio/codec_manager.cc
index 6eb836af104..15d81a8d4e5 100644
--- a/system/bta/le_audio/codec_manager.cc
+++ b/system/bta/le_audio/codec_manager.cc
@@ -69,8 +69,7 @@ static std::unordered_map<
 
 struct codec_manager_impl {
  public:
-  codec_manager_impl(
-      const std::vector<btle_audio_codec_config_t>& offloading_preference) {
+  codec_manager_impl() {
     offload_enable_ = osi_property_get_bool(
                           "ro.bluetooth.leaudio_offload.supported", false) &&
                       !osi_property_get_bool(
@@ -96,7 +95,10 @@ struct codec_manager_impl {
     btm_configure_data_path(btm_data_direction::CONTROLLER_TO_HOST,
                             kIsoDataPathPlatformDefault, {});
     SetCodecLocation(CodecLocation::ADSP);
-    le_audio::AudioSetConfigurationProvider::Initialize();
+  }
+  void start(
+      const std::vector<btle_audio_codec_config_t>& offloading_preference) {
+    le_audio::AudioSetConfigurationProvider::Initialize(GetCodecLocation());
     UpdateOffloadCapability(offloading_preference);
   }
   ~codec_manager_impl() {
@@ -413,8 +415,8 @@ struct CodecManager::impl {
   void Start(
       const std::vector<btle_audio_codec_config_t>& offloading_preference) {
     LOG_ASSERT(!codec_manager_impl_);
-    codec_manager_impl_ =
-        std::make_unique<codec_manager_impl>(offloading_preference);
+    codec_manager_impl_ = std::make_unique<codec_manager_impl>();
+    codec_manager_impl_->start(offloading_preference);
   }
 
   void Stop() {
diff --git a/system/bta/le_audio/devices.cc b/system/bta/le_audio/devices.cc
index 1aed2b6c592..cc15566c6be 100644
--- a/system/bta/le_audio/devices.cc
+++ b/system/bta/le_audio/devices.cc
@@ -1583,6 +1583,8 @@ bool LeAudioDevice::ConfigureAses(
   for (; needed_ase && ase; needed_ase--) {
     ase->active = true;
     ase->configured_for_context_type = context_type;
+    ase->is_codec_in_controller = ent.is_codec_in_controller;
+    ase->data_path_id = ent.data_path_id;
     active_ases++;
 
     /* In case of late connect, we could be here for STREAMING ase.
diff --git a/system/bta/le_audio/devices_test.cc b/system/bta/le_audio/devices_test.cc
index 64be816ac4d..89ff7c60418 100644
--- a/system/bta/le_audio/devices_test.cc
+++ b/system/bta/le_audio/devices_test.cc
@@ -431,7 +431,8 @@ class LeAudioAseConfigurationTest : public Test {
     group_ = new LeAudioDeviceGroup(group_id_);
     bluetooth::manager::SetMockBtmInterface(&btm_interface_);
     controller::SetMockControllerInterface(&controller_interface_);
-    ::le_audio::AudioSetConfigurationProvider::Initialize();
+    ::le_audio::AudioSetConfigurationProvider::Initialize(
+        ::le_audio::types::CodecLocation::ADSP);
     MockCsisClient::SetMockInstanceForTesting(&mock_csis_client_module_);
     ON_CALL(mock_csis_client_module_, Get())
         .WillByDefault(Return(&mock_csis_client_module_));
diff --git a/system/bta/le_audio/le_audio_client_test.cc b/system/bta/le_audio/le_audio_client_test.cc
index a72507a3fc5..072caacaad4 100644
--- a/system/bta/le_audio/le_audio_client_test.cc
+++ b/system/bta/le_audio/le_audio_client_test.cc
@@ -1369,7 +1369,8 @@ class UnicastTestNoInit : public Test {
     available_src_context_types_ = 0xffff;
     supported_snk_context_types_ = 0xffff;
     supported_src_context_types_ = 0xffff;
-    le_audio::AudioSetConfigurationProvider::Initialize();
+    le_audio::AudioSetConfigurationProvider::Initialize(
+        ::le_audio::types::CodecLocation::ADSP);
     ASSERT_FALSE(LeAudioClient::IsLeAudioClientRunning());
   }
 
diff --git a/system/bta/le_audio/le_audio_set_configuration_provider.h b/system/bta/le_audio/le_audio_set_configuration_provider.h
index 7310868d68b..8ece4f21796 100644
--- a/system/bta/le_audio/le_audio_set_configuration_provider.h
+++ b/system/bta/le_audio/le_audio_set_configuration_provider.h
@@ -27,7 +27,7 @@ class AudioSetConfigurationProvider {
   AudioSetConfigurationProvider();
   virtual ~AudioSetConfigurationProvider() = default;
   static AudioSetConfigurationProvider* Get();
-  static void Initialize();
+  static void Initialize(types::CodecLocation location);
   static void DebugDump(int fd);
   static void Cleanup();
   virtual const set_configurations::AudioSetConfigurations* GetConfigurations(
diff --git a/system/bta/le_audio/le_audio_set_configuration_provider_json.cc b/system/bta/le_audio/le_audio_set_configuration_provider_json.cc
index 91a6bd5b374..6f75ad1a5ab 100644
--- a/system/bta/le_audio/le_audio_set_configuration_provider_json.cc
+++ b/system/bta/le_audio/le_audio_set_configuration_provider_json.cc
@@ -70,12 +70,12 @@ static const std::vector<
 struct AudioSetConfigurationProviderJson {
   static constexpr auto kDefaultScenario = "Media";
 
-  AudioSetConfigurationProviderJson() {
+  AudioSetConfigurationProviderJson(types::CodecLocation location) {
     dual_swb_bidirection_supported_ = osi_property_get_bool(
         "persist.bluetooth.leaudio_dual_bidirection_swb."
         "supported",
         true);
-    ASSERT_LOG(LoadContent(kLeAudioSetConfigs, kLeAudioSetScenarios),
+    ASSERT_LOG(LoadContent(kLeAudioSetConfigs, kLeAudioSetScenarios, location),
                ": Unable to load le audio set configuration files.");
   }
 
@@ -276,7 +276,7 @@ struct AudioSetConfigurationProviderJson {
 
   SetConfiguration SetConfigurationFromFlatSubconfig(
       const bluetooth::le_audio::AudioSetSubConfiguration* flat_subconfig,
-      QosConfigSetting qos) {
+      QosConfigSetting qos, types::CodecLocation location) {
     auto strategy_int =
         static_cast<int>(flat_subconfig->configuration_strategy());
 
@@ -290,12 +290,32 @@ struct AudioSetConfigurationProviderJson {
             ? static_cast<types::LeAudioConfigurationStrategy>(strategy_int)
             : types::LeAudioConfigurationStrategy::RFU;
 
-    return SetConfiguration(
+    auto config = SetConfiguration(
         flat_subconfig->direction(), flat_subconfig->device_cnt(),
         flat_subconfig->ase_cnt(),
         CodecCapabilitySettingFromFlat(flat_subconfig->codec_id(),
                                        flat_subconfig->codec_configuration()),
         qos, strategy);
+
+    // Note that these parameters are set here since for now, we are using the
+    // common configuration source for all the codec locations.
+    switch (location) {
+      case types::CodecLocation::ADSP:
+        config.is_codec_in_controller = false;
+        config.data_path_id =
+            bluetooth::hci::iso_manager::kIsoDataPathPlatformDefault;
+        break;
+      case types::CodecLocation::HOST:
+        config.is_codec_in_controller = false;
+        config.data_path_id = bluetooth::hci::iso_manager::kIsoDataPathHci;
+        break;
+      case types::CodecLocation::CONTROLLER:
+        config.is_codec_in_controller = true;
+        config.data_path_id =
+            bluetooth::hci::iso_manager::kIsoDataPathPlatformDefault;
+        break;
+    }
+    return config;
   }
 
   static uint8_t ValidateTargetLatency(int flat_target_latency) {
@@ -313,7 +333,8 @@ struct AudioSetConfigurationProviderJson {
   AudioSetConfiguration AudioSetConfigurationFromFlat(
       const bluetooth::le_audio::AudioSetConfiguration* flat_cfg,
       std::vector<const bluetooth::le_audio::CodecConfiguration*>* codec_cfgs,
-      std::vector<const bluetooth::le_audio::QosConfiguration*>* qos_cfgs) {
+      std::vector<const bluetooth::le_audio::QosConfiguration*>* qos_cfgs,
+      types::CodecLocation location) {
     ASSERT_LOG(flat_cfg != nullptr, "flat_cfg cannot be null");
     std::string codec_config_key = flat_cfg->codec_config_name()->str();
     auto* qos_config_key_array = flat_cfg->qos_config_name();
@@ -395,13 +416,13 @@ struct AudioSetConfigurationProviderJson {
       /* Load subconfigurations */
       for (auto subconfig : *codec_cfg->subconfigurations()) {
         if (subconfig->direction() == le_audio::types::kLeAudioDirectionSink) {
-          processSubconfig(*subconfig, qos_sink,
-                           dual_dev_one_chan_stereo_sink_swb,
-                           single_dev_one_chan_stereo_sink_swb, subconfigs);
+          processSubconfig(
+              *subconfig, qos_sink, dual_dev_one_chan_stereo_sink_swb,
+              single_dev_one_chan_stereo_sink_swb, subconfigs, location);
         } else {
-          processSubconfig(*subconfig, qos_source,
-                           dual_dev_one_chan_stereo_source_swb,
-                           single_dev_one_chan_stereo_source_swb, subconfigs);
+          processSubconfig(
+              *subconfig, qos_source, dual_dev_one_chan_stereo_source_swb,
+              single_dev_one_chan_stereo_source_swb, subconfigs, location);
         }
       }
     } else {
@@ -430,9 +451,10 @@ struct AudioSetConfigurationProviderJson {
       const bluetooth::le_audio::AudioSetSubConfiguration& subconfig,
       const QosConfigSetting& qos_setting, bool& dual_dev_one_chan_stereo_swb,
       bool& single_dev_one_chan_stereo_swb,
-      std::vector<SetConfiguration>& subconfigs) {
+      std::vector<SetConfiguration>& subconfigs,
+      types::CodecLocation location) {
     subconfigs.push_back(
-        SetConfigurationFromFlatSubconfig(&subconfig, qos_setting));
+        SetConfigurationFromFlatSubconfig(&subconfig, qos_setting, location));
 
     if (subconfigs.back().codec.GetConfigSamplingFrequency() <
         le_audio::LeAudioCodecConfiguration::kSampleRate32000) {
@@ -448,7 +470,8 @@ struct AudioSetConfigurationProviderJson {
   }
 
   bool LoadConfigurationsFromFiles(const char* schema_file,
-                                   const char* content_file) {
+                                   const char* content_file,
+                                   types::CodecLocation location) {
     flatbuffers::Parser configurations_parser_;
     std::string configurations_schema_binary_content;
     bool ok = flatbuffers::LoadFile(schema_file, true,
@@ -502,9 +525,9 @@ struct AudioSetConfigurationProviderJson {
 
     LOG_DEBUG(": Updating %d config entries.", flat_configs->size());
     for (auto const& flat_cfg : *flat_configs) {
-      configurations_.insert(
-          {flat_cfg->name()->str(),
-           AudioSetConfigurationFromFlat(flat_cfg, &codec_cfgs, &qos_cfgs)});
+      configurations_.insert({flat_cfg->name()->str(),
+                              AudioSetConfigurationFromFlat(
+                                  flat_cfg, &codec_cfgs, &qos_cfgs, location)});
     }
 
     return true;
@@ -580,9 +603,10 @@ struct AudioSetConfigurationProviderJson {
       std::vector<std::pair<const char* /*schema*/, const char* /*content*/>>
           config_files,
       std::vector<std::pair<const char* /*schema*/, const char* /*content*/>>
-          scenario_files) {
+          scenario_files,
+      types::CodecLocation location) {
     for (auto [schema, content] : config_files) {
-      if (!LoadConfigurationsFromFiles(schema, content)) return false;
+      if (!LoadConfigurationsFromFiles(schema, content, location)) return false;
     }
 
     for (auto [schema, content] : scenario_files) {
@@ -596,10 +620,10 @@ struct AudioSetConfigurationProvider::impl {
   impl(const AudioSetConfigurationProvider& config_provider)
       : config_provider_(config_provider) {}
 
-  void Initialize() {
+  void Initialize(types::CodecLocation location) {
     ASSERT_LOG(!config_provider_impl_, " Config provider not available.");
     config_provider_impl_ =
-        std::make_unique<AudioSetConfigurationProviderJson>();
+        std::make_unique<AudioSetConfigurationProviderJson>(location);
   }
 
   void Cleanup() {
@@ -652,13 +676,13 @@ std::mutex instance_mutex;
 AudioSetConfigurationProvider::AudioSetConfigurationProvider()
     : pimpl_(std::make_unique<AudioSetConfigurationProvider::impl>(*this)) {}
 
-void AudioSetConfigurationProvider::Initialize() {
+void AudioSetConfigurationProvider::Initialize(types::CodecLocation location) {
   std::scoped_lock<std::mutex> lock(instance_mutex);
   if (!config_provider)
     config_provider = std::make_unique<AudioSetConfigurationProvider>();
 
   if (!config_provider->pimpl_->IsRunning())
-    config_provider->pimpl_->Initialize();
+    config_provider->pimpl_->Initialize(location);
 }
 
 void AudioSetConfigurationProvider::DebugDump(int fd) {
diff --git a/system/bta/le_audio/le_audio_types.h b/system/bta/le_audio/le_audio_types.h
index 851bd9c31fb..e4c41249e03 100644
--- a/system/bta/le_audio/le_audio_types.h
+++ b/system/bta/le_audio/le_audio_types.h
@@ -718,6 +718,13 @@ struct ase {
   uint8_t framing;
   uint8_t preferred_phy;
 
+  /* Set to true, if the codec is implemented in BT controller, false if it's
+   * implemented in host, or in separate DSP
+   */
+  bool is_codec_in_controller;
+  /* Datapath ID used to configure an ISO channel for these ASEs */
+  uint8_t data_path_id;
+
   /* Qos configuration */
   uint16_t max_sdu_size;
   uint8_t retrans_nb;
@@ -794,6 +801,12 @@ struct SetConfiguration {
   uint8_t direction;  /* Direction of set */
   uint8_t device_cnt; /* How many devices must be in set */
   uint8_t ase_cnt;    /* How many ASE we need in configuration */
+
+  /* Whether the codec location is transparent to the controller */
+  bool is_codec_in_controller = false;
+  /* Datapath ID used to configure an ISO channel for these ASEs */
+  uint8_t data_path_id = bluetooth::hci::iso_manager::kIsoDataPathHci;
+
   CodecCapabilitySetting codec;
   QosConfigSetting qos;
   types::LeAudioConfigurationStrategy strategy;
diff --git a/system/bta/le_audio/state_machine.cc b/system/bta/le_audio/state_machine.cc
index 7ccedb75695..4c2da5bfb3f 100644
--- a/system/bta/le_audio/state_machine.cc
+++ b/system/bta/le_audio/state_machine.cc
@@ -1530,22 +1530,15 @@ class LeAudioGroupStateMachineImpl : public LeAudioGroupStateMachine {
   }
 
   static void PrepareDataPath(int group_id, const struct ase* ase) {
-    /* TODO: Handle HW offloading decode as we handle here, force to use SW
-     * decode for now */
-    auto data_path_id = bluetooth::hci::iso_manager::kIsoDataPathHci;
-    if (CodecManager::GetInstance()->GetCodecLocation() !=
-        CodecLocation::HOST) {
-      data_path_id = bluetooth::hci::iso_manager::kIsoDataPathPlatformDefault;
-    }
-    /* TODO: Need to set coding_format when we support the codec location inside
-     * the controller, force to use transparent for now */
     bluetooth::hci::iso_manager::iso_data_path_params param = {
         .data_path_dir =
             ase->direction == le_audio::types::kLeAudioDirectionSink
                 ? bluetooth::hci::iso_manager::kIsoDataPathDirectionIn
                 : bluetooth::hci::iso_manager::kIsoDataPathDirectionOut,
-        .data_path_id = data_path_id,
-        .codec_id_format = bluetooth::hci::kIsoCodingFormatTransparent,
+        .data_path_id = ase->data_path_id,
+        .codec_id_format = ase->is_codec_in_controller
+                               ? ase->codec_id.coding_format
+                               : bluetooth::hci::kIsoCodingFormatTransparent,
         .codec_id_company = ase->codec_id.vendor_company_id,
         .codec_id_vendor = ase->codec_id.vendor_codec_id,
         .controller_delay = 0x00000000,
diff --git a/system/bta/le_audio/state_machine_test.cc b/system/bta/le_audio/state_machine_test.cc
index 8effc072017..d6e596dc1ae 100644
--- a/system/bta/le_audio/state_machine_test.cc
+++ b/system/bta/le_audio/state_machine_test.cc
@@ -194,7 +194,6 @@ class StateMachineTestBase : public Test {
     do_not_send_cis_establish_event_ = false;
     cis_status_.clear();
 
-    ::le_audio::AudioSetConfigurationProvider::Initialize();
     LeAudioGroupStateMachine::Initialize(&mock_callbacks_);
 
     ContentControlIdKeeper::GetInstance()->Start();
@@ -1291,6 +1290,8 @@ class StateMachineTestBase : public Test {
 class StateMachineTest : public StateMachineTestBase {
   void SetUp() override {
     ConfigCodecManagerMock(types::CodecLocation::HOST);
+    ::le_audio::AudioSetConfigurationProvider::Initialize(
+        ::le_audio::types::CodecLocation::HOST);
     StateMachineTestBase::SetUp();
   }
 };
@@ -1298,6 +1299,8 @@ class StateMachineTest : public StateMachineTestBase {
 class StateMachineTestAdsp : public StateMachineTestBase {
   void SetUp() override {
     ConfigCodecManagerMock(types::CodecLocation::ADSP);
+    ::le_audio::AudioSetConfigurationProvider::Initialize(
+        ::le_audio::types::CodecLocation::ADSP);
     StateMachineTestBase::SetUp();
   }
 };
-- 
GitLab