Parse broadcast offload capabilities

1. Parse the broadcast capability from capability file
2. Convert broadcast HAL format to stack format
3. Update test to validate broadcast capability parsing
4. Correct the map size before accessing in VTS test

Tag: #feature
Bug: 242472419
Test: atest BluetoothLeAudioCodecsProviderTest
Test: atest VtsHalBluetoothAudioTargetTest
Change-Id: I8ac88c1e9024ca03757620bf48eacdd60ada7eb4
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) {