Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0041aaa1 authored by Bao Do's avatar Bao Do
Browse files

Populate `audioLocation` from XML file for LE Audio codec provider

Bug: 331809026
Test: mmm hardware/interfaces/bluetooth/audio/utils
Change-Id: I480ea5523c8c90f2724179f377c5cfe1a278b0bd
parent 487f0c6a
Loading
Loading
Loading
Loading
+0 −3
Original line number Diff line number Diff line
@@ -90,9 +90,6 @@ cc_library_shared {

cc_test {
    name: "BluetoothLeAudioCodecsProviderTest",
    defaults: [
        "latest_android_hardware_bluetooth_audio_ndk_shared",
    ],
    srcs: [
        "aidl_session/BluetoothLeAudioCodecsProvider.cpp",
        "aidl_session/BluetoothLeAudioCodecsProviderTest.cpp",
+148 −42
Original line number Diff line number Diff line
@@ -119,6 +119,7 @@ BluetoothLeAudioCodecsProvider::GetLeAudioCodecInfo(
    // Mapping octetsPerCodecFrame to bitdepth for easier comparison.
    transport.bitdepth.push_back(codec_config.getOctetsPerCodecFrame());
    transport.frameDurationUs.push_back(codec_config.getFrameDurationUs());
    if (strategy_config.hasAudioLocation()) {
      switch (strategy_config.getAudioLocation()) {
        case setting::AudioLocation::MONO:
          if (strategy_config_channel_count == 1)
@@ -133,6 +134,22 @@ BluetoothLeAudioCodecsProvider::GetLeAudioCodecInfo(
          transport.channelMode.push_back(ChannelMode::UNKNOWN);
          break;
      }
    } else if (strategy_config.hasAudioChannelAllocation()) {
      auto count =
          std::bitset<32>(strategy_config.getAudioChannelAllocation()).count();
      if (count <= 1) {
        if (strategy_config_channel_count == 1)
          transport.channelMode.push_back(ChannelMode::MONO);
        else
          transport.channelMode.push_back(ChannelMode::DUALMONO);
      } else if (count == 2) {
        transport.channelMode.push_back(ChannelMode::STEREO);
      } else {
        transport.channelMode.push_back(ChannelMode::UNKNOWN);
      }
    } else {
      transport.channelMode.push_back(ChannelMode::UNKNOWN);
    }
  }

  // Goes through every scenario, deduplicate configuration, skip the invalid
@@ -336,8 +353,12 @@ BluetoothLeAudioCodecsProvider::ComposeLeAudioCodecCapabilities(
  for (const auto& scenario : supported_scenarios) {
    UnicastCapability unicast_encode_capability =
        GetUnicastCapability(scenario.getEncode());
    LOG(INFO) << __func__ << ": Unicast capability encode = "
              << unicast_encode_capability.toString();
    UnicastCapability unicast_decode_capability =
        GetUnicastCapability(scenario.getDecode());
    LOG(INFO) << __func__ << ": Unicast capability decode = "
              << unicast_decode_capability.toString();
    BroadcastCapability broadcast_capability = {.codecType =
                                                    CodecType::UNKNOWN};

@@ -384,22 +405,36 @@ UnicastCapability BluetoothLeAudioCodecsProvider::GetUnicastCapability(
    return {.codecType = CodecType::UNKNOWN};
  }

  // Populate audio location
  AudioLocation audio_location = AudioLocation::UNKNOWN;
  if (strategy_configuration_iter->second.hasAudioLocation()) {
    audio_location = GetAudioLocation(
        strategy_configuration_iter->second.getAudioLocation());
  }

  // Populate audio channel allocation
  std::optional<CodecSpecificConfigurationLtv::AudioChannelAllocation>
      audio_channel_allocation = std::nullopt;
  if (strategy_configuration_iter->second.hasAudioChannelAllocation()) {
    LOG(INFO) << __func__ << ": has allocation";
    CodecSpecificConfigurationLtv::AudioChannelAllocation tmp;
    tmp.bitmask =
        strategy_configuration_iter->second.getAudioChannelAllocation();
    audio_channel_allocation = tmp;
  }

  CodecType codec_type =
      GetCodecType(codec_configuration_iter->second.getCodec());
  if (codec_type == CodecType::LC3) {
    return ComposeUnicastCapability(
        codec_type,
        GetAudioLocation(
            strategy_configuration_iter->second.getAudioLocation()),
        codec_type, audio_location, audio_channel_allocation,
        strategy_configuration_iter->second.getConnectedDevice(),
        strategy_configuration_iter->second.getChannelCount(),
        ComposeLc3Capability(codec_configuration_iter->second));
  } else if (codec_type == CodecType::APTX_ADAPTIVE_LE ||
             codec_type == CodecType::APTX_ADAPTIVE_LEX) {
    return ComposeUnicastCapability(
        codec_type,
        GetAudioLocation(
            strategy_configuration_iter->second.getAudioLocation()),
        codec_type, audio_location, audio_channel_allocation,
        strategy_configuration_iter->second.getConnectedDevice(),
        strategy_configuration_iter->second.getChannelCount(),
        ComposeAptxAdaptiveLeCapability(codec_configuration_iter->second));
@@ -435,11 +470,27 @@ BroadcastCapability BluetoothLeAudioCodecsProvider::GetBroadcastCapability(
  std::vector<std::optional<Lc3Capabilities>> bcastLc3Cap(
      1, std::optional(ComposeLc3Capability(codec_configuration_iter->second)));

  // Populate audio location
  AudioLocation audio_location = AudioLocation::UNKNOWN;
  if (strategy_configuration_iter->second.hasAudioLocation()) {
    audio_location = GetAudioLocation(
        strategy_configuration_iter->second.getAudioLocation());
  }

  // Populate audio channel allocation
  std::optional<CodecSpecificConfigurationLtv::AudioChannelAllocation>
      audio_channel_allocation = std::nullopt;
  if (strategy_configuration_iter->second.hasAudioChannelAllocation()) {
    LOG(INFO) << __func__ << ": has allocation";
    CodecSpecificConfigurationLtv::AudioChannelAllocation tmp;
    tmp.bitmask =
        strategy_configuration_iter->second.getAudioChannelAllocation();
    audio_channel_allocation = tmp;
  }

  if (codec_type == CodecType::LC3) {
    return ComposeBroadcastCapability(
        codec_type,
        GetAudioLocation(
            strategy_configuration_iter->second.getAudioLocation()),
        codec_type, audio_location, audio_channel_allocation,
        strategy_configuration_iter->second.getChannelCount(), bcastLc3Cap);
  }
  return {.codecType = CodecType::UNKNOWN};
@@ -448,16 +499,21 @@ BroadcastCapability BluetoothLeAudioCodecsProvider::GetBroadcastCapability(
template <class T>
BroadcastCapability BluetoothLeAudioCodecsProvider::ComposeBroadcastCapability(
    const CodecType& codec_type, const AudioLocation& audio_location,
    const std::optional<CodecSpecificConfigurationLtv::AudioChannelAllocation>&
        audio_channel_allocation,
    const uint8_t& channel_count, const std::vector<T>& capability) {
  return {.codecType = codec_type,
          .supportedChannel = audio_location,
          .channelCountPerStream = channel_count,
          .leAudioCodecCapabilities = std::optional(capability)};
          .leAudioCodecCapabilities = std::optional(capability),
          .audioLocation = audio_channel_allocation};
}

template <class T>
UnicastCapability BluetoothLeAudioCodecsProvider::ComposeUnicastCapability(
    const CodecType& codec_type, const AudioLocation& audio_location,
    const std::optional<CodecSpecificConfigurationLtv::AudioChannelAllocation>&
        audio_channel_allocation,
    const uint8_t& device_cnt, const uint8_t& channel_count,
    const T& capability) {
  return {
@@ -467,6 +523,7 @@ UnicastCapability BluetoothLeAudioCodecsProvider::ComposeUnicastCapability(
      .channelCountPerDevice = channel_count,
      .leAudioCodecCapabilities =
          UnicastCapability::LeAudioCodecCapabilities(capability),
      .audioLocation = audio_channel_allocation,
  };
}

@@ -519,16 +576,8 @@ bool BluetoothLeAudioCodecsProvider::IsValidCodecConfiguration(
         codec_configuration.hasOctetsPerCodecFrame();
}

bool BluetoothLeAudioCodecsProvider::IsValidStrategyConfiguration(
bool IsValidStereoAudioLocation(
    const setting::StrategyConfiguration& strategy_configuration) {
  if (!strategy_configuration.hasName() ||
      !strategy_configuration.hasAudioLocation() ||
      !strategy_configuration.hasConnectedDevice() ||
      !strategy_configuration.hasChannelCount()) {
    return false;
  }
  if (strategy_configuration.getAudioLocation() ==
      setting::AudioLocation::STEREO) {
  if ((strategy_configuration.getConnectedDevice() == 2 &&
       strategy_configuration.getChannelCount() == 1) ||
      (strategy_configuration.getConnectedDevice() == 1 &&
@@ -542,15 +591,72 @@ bool BluetoothLeAudioCodecsProvider::IsValidStrategyConfiguration(
    // Broadcast
    return true;
  }
  } else if (strategy_configuration.getAudioLocation() ==
             setting::AudioLocation::MONO) {
  return false;
}

bool IsValidMonoAudioLocation(
    const setting::StrategyConfiguration& strategy_configuration) {
  if (strategy_configuration.getConnectedDevice() == 1 &&
      strategy_configuration.getChannelCount() == 1) {
      // Mono
    return true;
  }
  return false;
}

bool IsValidAudioLocation(
    const setting::StrategyConfiguration& strategy_configuration) {
  if (strategy_configuration.getAudioLocation() ==
      setting::AudioLocation::STEREO)
    return IsValidStereoAudioLocation(strategy_configuration);
  else if (strategy_configuration.getAudioLocation() ==
           setting::AudioLocation::MONO)
    return IsValidMonoAudioLocation(strategy_configuration);
  return false;
}

bool IsValidAudioChannelAllocation(
    const setting::StrategyConfiguration& strategy_configuration) {
  // First, ensure that there's only 2 bitmask enabled
  int audio_channel_allocation =
      strategy_configuration.getAudioChannelAllocation();
  int count = 0;
  for (int bit = 0; bit < 32; ++bit)
    if (audio_channel_allocation & (1 << bit)) ++count;
  if (count > 2) {
    LOG(WARNING) << "Cannot parse more than 2 audio location, input is "
                 << audio_channel_allocation;
    return false;
  }

  if (count == 2)
    return IsValidStereoAudioLocation(strategy_configuration);
  else
    return IsValidMonoAudioLocation(strategy_configuration);
}

bool BluetoothLeAudioCodecsProvider::IsValidStrategyConfiguration(
    const setting::StrategyConfiguration& strategy_configuration) {
  if (!strategy_configuration.hasName() ||
      !strategy_configuration.hasConnectedDevice() ||
      !strategy_configuration.hasChannelCount()) {
    return false;
  }

  // Both audio location field cannot be empty
  if (!strategy_configuration.hasAudioLocation() &&
      !strategy_configuration.hasAudioChannelAllocation())
    return false;

  // Any audio location field that presents must be valid
  if (strategy_configuration.hasAudioLocation() &&
      !IsValidAudioLocation(strategy_configuration))
    return false;

  if (strategy_configuration.hasAudioChannelAllocation() &&
      !IsValidAudioChannelAllocation(strategy_configuration))
    return false;

  return true;
}

}  // namespace audio
+7 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@
#include <vector>

#include "aidl/android/hardware/bluetooth/audio/CodecInfo.h"
#include "aidl/android/hardware/bluetooth/audio/CodecSpecificConfigurationLtv.h"
#include "aidl/android/hardware/bluetooth/audio/SessionType.h"
#include "aidl_android_hardware_bluetooth_audio_setting.h"

@@ -84,12 +85,18 @@ class BluetoothLeAudioCodecsProvider {
  template <class T>
  static inline UnicastCapability ComposeUnicastCapability(
      const CodecType& codec_type, const AudioLocation& audio_location,
      const std::optional<
          CodecSpecificConfigurationLtv::AudioChannelAllocation>&
          audio_channel_allocation,
      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 std::optional<
          CodecSpecificConfigurationLtv::AudioChannelAllocation>&
          audio_channel_allocation,
      const uint8_t& channel_count, const std::vector<T>& capability);

  static inline Lc3Capabilities ComposeLc3Capability(
+4 −4
Original line number Diff line number Diff line
@@ -69,9 +69,9 @@
    <codecConfiguration name="APTX_ADAPTIVE_LEX_96k" codec="APTX_ADAPTIVE_LEX" samplingFrequency="96000" frameDurationUs="10000" octetsPerCodecFrame="816"/>
  </codecConfigurationList>
  <strategyConfigurationList>
    <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"/>
    <strategyConfiguration name="STEREO_ONE_CIS_PER_DEVICE" audioLocation="STEREO" connectedDevice="2" channelCount="1" audioChannelAllocation="3"/>
    <strategyConfiguration name="STEREO_TWO_CISES_PER_DEVICE" audioLocation="STEREO" connectedDevice="1" channelCount="2" audioChannelAllocation="3"/>
    <strategyConfiguration name="MONO_ONE_CIS_PER_DEVICE" audioLocation="MONO" connectedDevice="1" channelCount="1" audioChannelAllocation="4"/>
    <strategyConfiguration name="BROADCAST_STEREO" audioLocation="STEREO" connectedDevice="0" channelCount="2" audioChannelAllocation="3"/>
  </strategyConfigurationList>
</leAudioOffloadSetting>
+3 −0
Original line number Diff line number Diff line
@@ -56,9 +56,12 @@
  <xs:element name="strategyConfiguration">
    <xs:complexType>
      <xs:attribute name="name" type="xs:string"/>
      <!-- Deprecated definition of Audio Location, please use audioLocationInt -->
      <xs:attribute name="audioLocation" type="audioLocation"/>
      <xs:attribute name="connectedDevice" type="xs:unsignedByte"/>
      <xs:attribute name="channelCount" type="xs:unsignedByte"/>
      <!-- Integer Audio Location to populate to audioLocation if present -->
      <xs:attribute name="audioChannelAllocation" type="xs:int"/>
    </xs:complexType>
  </xs:element>
  <xs:simpleType name="audioLocation">
Loading