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

Commit 11178a6e authored by Jakub Tyszkowski's avatar Jakub Tyszkowski
Browse files

LeAudio: Verify codec frame blocks pers SDU parameter

Bug: 308428644
Bug: 346568041
Test: atest VtsHalBluetoothAudioTargetTest
Change-Id: I6567950d24d1df8cabec2855c907c5611ca5bf6d
parent 2558bf60
Loading
Loading
Loading
Loading
+101 −31
Original line number Diff line number Diff line
@@ -195,6 +195,17 @@ void copy_codec_specific(CodecConfiguration::CodecSpecific& dst,
  }
}

static std::optional<CodecSpecificConfigurationLtv> GetConfigurationLtv(
    const std::vector<CodecSpecificConfigurationLtv>& configurationLtvs,
    CodecSpecificConfigurationLtv::Tag tag) {
  for (const auto ltv : configurationLtvs) {
    if (ltv.getTag() == tag) {
      return ltv;
    }
  }
  return std::nullopt;
}

class BluetoothAudioPort : public BnBluetoothAudioPort {
 public:
  BluetoothAudioPort() {}
@@ -2393,17 +2404,6 @@ class BluetoothAudioProviderLeAudioOutputHardwareAidl
    return capability;
  }

  std::optional<CodecSpecificConfigurationLtv> GetConfigurationLtv(
      const std::vector<CodecSpecificConfigurationLtv>& configurationLtvs,
      CodecSpecificConfigurationLtv::Tag tag) {
    for (const auto ltv : configurationLtvs) {
      if (ltv.getTag() == tag) {
        return ltv;
      }
    }
    return std::nullopt;
  }

  bool IsAseRequirementSatisfiedWithUnknownChannelCount(
      const std::vector<std::optional<AseDirectionRequirement>>&
          ase_requirements,
@@ -2560,6 +2560,67 @@ class BluetoothAudioProviderLeAudioOutputHardwareAidl
    return (num_of_satisfied_ase_requirements == ase_requirements.size());
  }

  static void VerifyCodecParameters(
      ::aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider::
          LeAudioAseConfigurationSetting::AseDirectionConfiguration config) {
    ASSERT_NE(config.aseConfiguration.codecConfiguration.size(), 0lu);
    ASSERT_TRUE(config.qosConfiguration.has_value());

    int32_t frame_blocks = 1;  // by default 1 if not set
    int8_t frame_duration = 0;
    int32_t octets_per_frame = 0;
    std::bitset<32> allocation_bitmask = 0;

    for (auto const& param : config.aseConfiguration.codecConfiguration) {
      if (param.getTag() ==
          ::aidl::android::hardware::bluetooth::audio::
              CodecSpecificConfigurationLtv::Tag::codecFrameBlocksPerSDU) {
        frame_blocks = param
                           .get<::aidl::android::hardware::bluetooth::audio::
                                    CodecSpecificConfigurationLtv::Tag::
                                        codecFrameBlocksPerSDU>()
                           .value;
      } else if (param.getTag() ==
                 ::aidl::android::hardware::bluetooth::audio::
                     CodecSpecificConfigurationLtv::Tag::frameDuration) {
        frame_duration = static_cast<int8_t>(
            param.get<::aidl::android::hardware::bluetooth::audio::
                          CodecSpecificConfigurationLtv::Tag::frameDuration>());
      } else if (param.getTag() ==
                 ::aidl::android::hardware::bluetooth::audio::
                     CodecSpecificConfigurationLtv::Tag::octetsPerCodecFrame) {
        octets_per_frame = static_cast<int32_t>(
            param
                .get<::aidl::android::hardware::bluetooth::audio::
                         CodecSpecificConfigurationLtv::Tag::
                             octetsPerCodecFrame>()
                .value);
      } else if (param.getTag() == ::aidl::android::hardware::bluetooth::audio::
                                       CodecSpecificConfigurationLtv::Tag::
                                           audioChannelAllocation) {
        allocation_bitmask = static_cast<int32_t>(
            param
                .get<::aidl::android::hardware::bluetooth::audio::
                         CodecSpecificConfigurationLtv::Tag::
                             audioChannelAllocation>()
                .bitmask);
      }
    }

    ASSERT_NE(frame_blocks, 0);
    ASSERT_NE(frame_duration, 0);
    ASSERT_NE(octets_per_frame, 0);

    auto const num_channels_per_cis = allocation_bitmask.count();
    ASSERT_NE(num_channels_per_cis, 0);

    // Verify if QoS takes the codec frame blocks per SDU into the account
    ASSERT_TRUE(config.qosConfiguration->sduIntervalUs >=
                frame_blocks * frame_duration);
    ASSERT_TRUE(config.qosConfiguration->maxSdu >=
                (frame_blocks * num_channels_per_cis * octets_per_frame));
  }

  void VerifyIfRequirementsSatisfied(
      const std::vector<LeAudioConfigurationRequirement>& requirements,
      const std::vector<LeAudioAseConfigurationSetting>& configurations) {
@@ -2592,32 +2653,52 @@ class BluetoothAudioProviderLeAudioOutputHardwareAidl
          continue;
        }

        bool sink_req_satisfied = false;
        if (req.sinkAseRequirement) {
          ASSERT_TRUE(conf.sinkAseConfiguration.has_value());
          sink_req_satisfied = IsAseRequirementSatisfied(
              *req.sinkAseRequirement, *conf.sinkAseConfiguration);

          ASSERT_NE(conf.sinkAseConfiguration->size(), 0lu);
          for (auto const& cfg : conf.sinkAseConfiguration.value()) {
            ASSERT_TRUE(cfg.has_value());
            VerifyCodecParameters(cfg.value());
          }
        }

        bool source_req_satisfied = false;
        if (req.sourceAseRequirement) {
          ASSERT_TRUE(conf.sourceAseConfiguration.has_value());
          source_req_satisfied = IsAseRequirementSatisfied(
              *req.sourceAseRequirement, *conf.sourceAseConfiguration);

          ASSERT_NE(conf.sourceAseConfiguration->size(), 0lu);
          for (auto const& cfg : conf.sourceAseConfiguration.value()) {
            ASSERT_TRUE(cfg.has_value());
            VerifyCodecParameters(cfg.value());
          }
        }

        if (req.sinkAseRequirement && req.sourceAseRequirement) {
          if (!conf.sinkAseConfiguration || !conf.sourceAseConfiguration) {
            continue;
          }

          if (!IsAseRequirementSatisfied(*req.sinkAseRequirement,
                                         *conf.sinkAseConfiguration) ||
              !IsAseRequirementSatisfied(*req.sourceAseRequirement,
                                         *conf.sourceAseConfiguration)) {
          if (!sink_req_satisfied || !source_req_satisfied) {
            continue;
          }
          num_of_satisfied_requirements +=
              std::bitset<32>(req.audioContext.bitmask).count();

          break;
        } else if (req.sinkAseRequirement) {
          if (!IsAseRequirementSatisfied(*req.sinkAseRequirement,
                                         *conf.sinkAseConfiguration)) {
          if (!sink_req_satisfied) {
            continue;
          }
          num_of_satisfied_requirements +=
              std::bitset<32>(req.audioContext.bitmask).count();
          break;
        } else if (req.sourceAseRequirement) {
          if (!IsAseRequirementSatisfied(*req.sourceAseRequirement,
                                         *conf.sourceAseConfiguration)) {
          if (!source_req_satisfied) {
            continue;
          }
          num_of_satisfied_requirements +=
@@ -4089,17 +4170,6 @@ class BluetoothAudioProviderLeAudioBroadcastHardwareAidl
    return media_audio_context;
  }

  std::optional<CodecSpecificConfigurationLtv> GetConfigurationLtv(
      const std::vector<CodecSpecificConfigurationLtv>& configurationLtvs,
      CodecSpecificConfigurationLtv::Tag tag) {
    for (const auto ltv : configurationLtvs) {
      if (ltv.getTag() == tag) {
        return ltv;
      }
    }
    return std::nullopt;
  }

  std::optional<CodecSpecificConfigurationLtv::SamplingFrequency>
  GetBisSampleFreq(const LeAudioBisConfiguration& bis_conf) {
    auto sample_freq_ltv = GetConfigurationLtv(