Merge "Parse broadcast offload capabilities" am: 47c304ee1e am: 6f1550dd65

Original change: https://android-review.googlesource.com/c/platform/hardware/interfaces/+/2314065

Change-Id: I8da75b12f9e6220e90af5a24878268db9d693ad5
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/bluetooth/audio/aidl/vts/VtsHalBluetoothAudioTargetTest.cpp b/bluetooth/audio/aidl/vts/VtsHalBluetoothAudioTargetTest.cpp
index e9b74b7..128ef61 100644
--- a/bluetooth/audio/aidl/vts/VtsHalBluetoothAudioTargetTest.cpp
+++ b/bluetooth/audio/aidl/vts/VtsHalBluetoothAudioTargetTest.cpp
@@ -1566,6 +1566,7 @@
   };
 
   for (auto& lc3_config : lc3_codec_configs) {
+    le_audio_broadcast_config.streamMap.resize(1);
     le_audio_broadcast_config.streamMap[0]
         .leAudioCodecConfig.set<LeAudioCodecConfiguration::lc3Config>(
             lc3_config);
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.cpp b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.cpp
index 1dec900..0a804bb 100644
--- a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.cpp
+++ b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.cpp
@@ -200,13 +200,21 @@
         GetUnicastCapability(scenario.getEncode());
     UnicastCapability unicast_decode_capability =
         GetUnicastCapability(scenario.getDecode());
-    // encode and decode cannot be unknown at the same time
-    if (unicast_encode_capability.codecType == CodecType::UNKNOWN &&
-        unicast_decode_capability.codecType == CodecType::UNKNOWN) {
-      continue;
-    }
     BroadcastCapability broadcast_capability = {.codecType =
                                                     CodecType::UNKNOWN};
+
+    if (scenario.hasBroadcast()) {
+      broadcast_capability = GetBroadcastCapability(scenario.getBroadcast());
+    }
+
+    // At least one capability should be valid
+    if (unicast_encode_capability.codecType == CodecType::UNKNOWN &&
+        unicast_decode_capability.codecType == CodecType::UNKNOWN &&
+        broadcast_capability.codecType == CodecType::UNKNOWN) {
+      LOG(ERROR) << __func__ << ": None of the capability is valid.";
+      continue;
+    }
+
     le_audio_codec_capabilities.push_back(
         {.unicastEncodeCapability = unicast_encode_capability,
          .unicastDecodeCapability = unicast_decode_capability,
@@ -252,6 +260,54 @@
   return {.codecType = CodecType::UNKNOWN};
 }
 
+BroadcastCapability BluetoothLeAudioCodecsProvider::GetBroadcastCapability(
+    const std::string& coding_direction) {
+  if (coding_direction == "invalid") {
+    return {.codecType = CodecType::UNKNOWN};
+  }
+
+  auto configuration_iter = configuration_map_.find(coding_direction);
+  if (configuration_iter == configuration_map_.end()) {
+    return {.codecType = CodecType::UNKNOWN};
+  }
+
+  auto codec_configuration_iter = codec_configuration_map_.find(
+      configuration_iter->second.getCodecConfiguration());
+  if (codec_configuration_iter == codec_configuration_map_.end()) {
+    return {.codecType = CodecType::UNKNOWN};
+  }
+
+  auto strategy_configuration_iter = strategy_configuration_map_.find(
+      configuration_iter->second.getStrategyConfiguration());
+  if (strategy_configuration_iter == strategy_configuration_map_.end()) {
+    return {.codecType = CodecType::UNKNOWN};
+  }
+
+  CodecType codec_type =
+      GetCodecType(codec_configuration_iter->second.getCodec());
+  std::vector<std::optional<Lc3Capabilities>> bcastLc3Cap(
+      1, std::optional(ComposeLc3Capability(codec_configuration_iter->second)));
+
+  if (codec_type == CodecType::LC3) {
+    return ComposeBroadcastCapability(
+        codec_type,
+        GetAudioLocation(
+            strategy_configuration_iter->second.getAudioLocation()),
+        strategy_configuration_iter->second.getChannelCount(), bcastLc3Cap);
+  }
+  return {.codecType = CodecType::UNKNOWN};
+}
+
+template <class T>
+BroadcastCapability BluetoothLeAudioCodecsProvider::ComposeBroadcastCapability(
+    const CodecType& codec_type, const AudioLocation& audio_location,
+    const uint8_t& channel_count, const std::vector<T>& capability) {
+  return {.codecType = codec_type,
+          .supportedChannel = audio_location,
+          .channelCountPerStream = channel_count,
+          .leAudioCodecCapabilities = std::optional(capability)};
+}
+
 template <class T>
 UnicastCapability BluetoothLeAudioCodecsProvider::ComposeUnicastCapability(
     const CodecType& codec_type, const AudioLocation& audio_location,
@@ -322,6 +378,10 @@
       // 1. two connected device, one for L one for R
       // 2. one connected device for both L and R
       return true;
+    } else if (strategy_configuration.getConnectedDevice() == 0 &&
+               strategy_configuration.getChannelCount() == 2) {
+      // Broadcast
+      return true;
     }
   } else if (strategy_configuration.getAudioLocation() ==
              setting::AudioLocation::MONO) {
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.h b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.h
index e879984..06e4595 100644
--- a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.h
+++ b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.h
@@ -20,6 +20,7 @@
 #include <android-base/logging.h>
 
 #include <unordered_map>
+#include <vector>
 
 #include "aidl_android_hardware_bluetooth_audio_setting.h"
 
@@ -66,12 +67,20 @@
 
   static UnicastCapability GetUnicastCapability(
       const std::string& coding_direction);
+  static BroadcastCapability GetBroadcastCapability(
+      const std::string& coding_direction);
+
   template <class T>
   static inline UnicastCapability ComposeUnicastCapability(
       const CodecType& codec_type, const AudioLocation& audio_location,
       const uint8_t& device_cnt, const uint8_t& channel_count,
       const T& capability);
 
+  template <class T>
+  static inline BroadcastCapability ComposeBroadcastCapability(
+      const CodecType& codec_type, const AudioLocation& audio_location,
+      const uint8_t& channel_count, const std::vector<T>& capability);
+
   static inline Lc3Capabilities ComposeLc3Capability(
       const setting::CodecConfiguration& codec_configuration);
 
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProviderTest.cpp b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProviderTest.cpp
index 5393cd7..dba2749 100644
--- a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProviderTest.cpp
+++ b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProviderTest.cpp
@@ -46,7 +46,11 @@
 // Define valid components for each list
 // Scenario
 static const Scenario kValidScenario(std::make_optional("OneChanStereo_16_1"),
-                                     std::make_optional("OneChanStereo_16_1"));
+                                     std::make_optional("OneChanStereo_16_1"),
+                                     std::nullopt);
+static const Scenario kValidBroadcastScenario(
+    std::nullopt, std::nullopt, std::make_optional("BcastStereo_16_2"));
+
 // Configuration
 static const Configuration kValidConfigOneChanStereo_16_1(
     std::make_optional("OneChanStereo_16_1"), std::make_optional("LC3_16k_1"),
@@ -69,11 +73,15 @@
     std::make_optional("MONO_ONE_CIS_PER_DEVICE"),
     std::make_optional(AudioLocation::MONO), std::make_optional(1),
     std::make_optional(1));
+static const StrategyConfiguration kValidStrategyBroadcastStereo(
+    std::make_optional("BROADCAST_STEREO"),
+    std::make_optional(AudioLocation::STEREO), std::make_optional(0),
+    std::make_optional(2));
 
 // Define valid test list built from above valid components
 // Scenario, Configuration, CodecConfiguration, StrategyConfiguration
-static const std::vector<ScenarioList> kValidScenarioList = {
-    ScenarioList(std::vector<Scenario>{kValidScenario})};
+static const std::vector<ScenarioList> kValidScenarioList = {ScenarioList(
+    std::vector<Scenario>{kValidScenario, kValidBroadcastScenario})};
 static const std::vector<ConfigurationList> kValidConfigurationList = {
     ConfigurationList(
         std::vector<Configuration>{kValidConfigOneChanStereo_16_1})};
@@ -84,7 +92,7 @@
     kValidStrategyConfigurationList = {
         StrategyConfigurationList(std::vector<StrategyConfiguration>{
             kValidStrategyStereoOneCis, kValidStrategyStereoTwoCis,
-            kValidStrategyMonoOneCis})};
+            kValidStrategyMonoOneCis, kValidStrategyBroadcastStereo})};
 
 class BluetoothLeAudioCodecsProviderTest
     : public ::testing::TestWithParam<OffloadSetting> {
@@ -151,13 +159,15 @@
   static std::vector<ScenarioList> CreateInvalidScenarios() {
     std::vector<ScenarioList> invalid_scenario_test_cases;
     invalid_scenario_test_cases.push_back(ScenarioList(std::vector<Scenario>{
-        Scenario(std::nullopt, std::make_optional("OneChanStereo_16_1"))}));
-
-    invalid_scenario_test_cases.push_back(ScenarioList(std::vector<Scenario>{
-        Scenario(std::make_optional("OneChanStereo_16_1"), std::nullopt)}));
+        Scenario(std::nullopt, std::make_optional("OneChanStereo_16_1"),
+                 std::nullopt)}));
 
     invalid_scenario_test_cases.push_back(ScenarioList(
-        std::vector<Scenario>{Scenario(std::nullopt, std::nullopt)}));
+        std::vector<Scenario>{Scenario(std::make_optional("OneChanStereo_16_1"),
+                                       std::nullopt, std::nullopt)}));
+
+    invalid_scenario_test_cases.push_back(ScenarioList(std::vector<Scenario>{
+        Scenario(std::nullopt, std::nullopt, std::nullopt)}));
 
     invalid_scenario_test_cases.push_back(
         ScenarioList(std::vector<Scenario>{}));
diff --git a/bluetooth/audio/utils/le_audio_codec_capabilities/le_audio_codec_capabilities.xml b/bluetooth/audio/utils/le_audio_codec_capabilities/le_audio_codec_capabilities.xml
index c7904b3..c8d1af0 100644
--- a/bluetooth/audio/utils/le_audio_codec_capabilities/le_audio_codec_capabilities.xml
+++ b/bluetooth/audio/utils/le_audio_codec_capabilities/le_audio_codec_capabilities.xml
@@ -40,6 +40,8 @@
     <scenario encode="OneChanStereo_16_2" decode="OneChanMono_16_2"/>
     <scenario encode="TwoChanStereo_16_2" decode="OneChanMono_16_2"/>
     <scenario encode="OneChanMono_16_2" decode="OneChanMono_16_2"/>
+    <!-- broadcast -->
+    <scenario encode="invalid" decode="invalid" broadcast="BcastStereo_16_2"/>
   </scenarioList>
   <configurationList>
     <configuration name="OneChanMono_16_1" codecConfiguration="LC3_16k_1" strategyConfiguration="MONO_ONE_CIS_PER_DEVICE"/>
@@ -48,6 +50,7 @@
     <configuration name="OneChanMono_16_2" codecConfiguration="LC3_16k_2" strategyConfiguration="MONO_ONE_CIS_PER_DEVICE"/>
     <configuration name="TwoChanStereo_16_2" codecConfiguration="LC3_16k_2" strategyConfiguration="STEREO_TWO_CISES_PER_DEVICE"/>
     <configuration name="OneChanStereo_16_2" codecConfiguration="LC3_16k_2" strategyConfiguration="STEREO_ONE_CIS_PER_DEVICE"/>
+    <configuration name="BcastStereo_16_2" codecConfiguration="LC3_16k_2" strategyConfiguration="BROADCAST_STEREO"/>
   </configurationList>
   <codecConfigurationList>
     <codecConfiguration name="LC3_16k_1" codec="LC3" samplingFrequency="16000" frameDurationUs="7500" octetsPerCodecFrame="30"/>
@@ -57,5 +60,6 @@
     <strategyConfiguration name="STEREO_ONE_CIS_PER_DEVICE" audioLocation="STEREO" connectedDevice="2" channelCount="1"/>
     <strategyConfiguration name="STEREO_TWO_CISES_PER_DEVICE" audioLocation="STEREO" connectedDevice="1" channelCount="2"/>
     <strategyConfiguration name="MONO_ONE_CIS_PER_DEVICE" audioLocation="MONO" connectedDevice="1" channelCount="1"/>
+    <strategyConfiguration name="BROADCAST_STEREO" audioLocation="STEREO" connectedDevice="0" channelCount="2"/>
   </strategyConfigurationList>
 </leAudioOffloadSetting>
diff --git a/bluetooth/audio/utils/le_audio_codec_capabilities/le_audio_codec_capabilities.xsd b/bluetooth/audio/utils/le_audio_codec_capabilities/le_audio_codec_capabilities.xsd
index 213e597..8c2d6a1 100644
--- a/bluetooth/audio/utils/le_audio_codec_capabilities/le_audio_codec_capabilities.xsd
+++ b/bluetooth/audio/utils/le_audio_codec_capabilities/le_audio_codec_capabilities.xsd
@@ -32,6 +32,7 @@
     <xs:complexType>
       <xs:attribute name="encode" type="xs:string"/>
       <xs:attribute name="decode" type="xs:string"/>
+      <xs:attribute name="broadcast" type="xs:string"/>
     </xs:complexType>
   </xs:element>
   <xs:element name="configuration">
diff --git a/bluetooth/audio/utils/le_audio_codec_capabilities/schema/current.txt b/bluetooth/audio/utils/le_audio_codec_capabilities/schema/current.txt
index 06aa21a..886350e 100644
--- a/bluetooth/audio/utils/le_audio_codec_capabilities/schema/current.txt
+++ b/bluetooth/audio/utils/le_audio_codec_capabilities/schema/current.txt
@@ -64,8 +64,10 @@
 
   public class Scenario {
     ctor public Scenario();
+    method public String getBroadcast();
     method public String getDecode();
     method public String getEncode();
+    method public void setBroadcast(String);
     method public void setDecode(String);
     method public void setEncode(String);
   }