/*
 * Copyright 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#define LOG_TAG "bluetooth"

#include "codec_status.h"
#include "client_interface.h"

#include "a2dp_aac_constants.h"
#include "a2dp_sbc_constants.h"
#include "a2dp_vendor_aptx_constants.h"
#include "a2dp_vendor_aptx_hd_constants.h"
#include "a2dp_vendor_ldac_constants.h"
#include "bta/av/bta_av_int.h"

namespace {

using ::android::hardware::bluetooth::audio::V2_0::AacObjectType;
using ::android::hardware::bluetooth::audio::V2_0::AacParameters;
using ::android::hardware::bluetooth::audio::V2_0::AacVariableBitRate;
using ::android::hardware::bluetooth::audio::V2_0::AptxParameters;
using ::android::hardware::bluetooth::audio::V2_0::AudioCapabilities;
using ::android::hardware::bluetooth::audio::V2_0::BitsPerSample;
using ::android::hardware::bluetooth::audio::V2_0::ChannelMode;
using ::android::hardware::bluetooth::audio::V2_0::CodecType;
using ::android::hardware::bluetooth::audio::V2_0::LdacChannelMode;
using ::android::hardware::bluetooth::audio::V2_0::LdacParameters;
using ::android::hardware::bluetooth::audio::V2_0::LdacQualityIndex;
using ::android::hardware::bluetooth::audio::V2_0::SampleRate;
using ::android::hardware::bluetooth::audio::V2_0::SbcAllocMethod;
using ::android::hardware::bluetooth::audio::V2_0::SbcBlockLength;
using ::android::hardware::bluetooth::audio::V2_0::SbcChannelMode;
using ::android::hardware::bluetooth::audio::V2_0::SbcNumSubbands;
using ::android::hardware::bluetooth::audio::V2_0::SbcParameters;

// capabilities from BluetoothAudioClientInterface::GetAudioCapabilities()
std::vector<AudioCapabilities> audio_hal_capabilities(0);
// capabilities that audio HAL supports and frameworks / Bluetooth SoC / runtime
// preference would like to use.
std::vector<AudioCapabilities> offloading_preference(0);

bool sbc_offloading_capability_match(const SbcParameters& sbc_capability,
                                     const SbcParameters& sbc_config) {
  if ((static_cast<SampleRate>(sbc_capability.sampleRate &
                               sbc_config.sampleRate) ==
       SampleRate::RATE_UNKNOWN) ||
      (static_cast<SbcChannelMode>(sbc_capability.channelMode &
                                   sbc_config.channelMode) ==
       SbcChannelMode::UNKNOWN) ||
      (static_cast<SbcBlockLength>(sbc_capability.blockLength &
                                   sbc_config.blockLength) ==
       static_cast<SbcBlockLength>(0)) ||
      (static_cast<SbcNumSubbands>(sbc_capability.numSubbands &
                                   sbc_config.numSubbands) ==
       static_cast<SbcNumSubbands>(0)) ||
      (static_cast<SbcAllocMethod>(sbc_capability.allocMethod &
                                   sbc_config.allocMethod) ==
       static_cast<SbcAllocMethod>(0)) ||
      (static_cast<BitsPerSample>(sbc_capability.bitsPerSample &
                                  sbc_config.bitsPerSample) ==
       BitsPerSample::BITS_UNKNOWN) ||
      (sbc_config.minBitpool < sbc_capability.minBitpool ||
       sbc_config.maxBitpool < sbc_config.minBitpool ||
       sbc_capability.maxBitpool < sbc_config.maxBitpool)) {
    LOG(WARNING) << __func__ << ": software codec=" << toString(sbc_config)
                 << " capability=" << toString(sbc_capability);
    return false;
  }
  VLOG(1) << __func__ << ": offloading codec=" << toString(sbc_config)
          << " capability=" << toString(sbc_capability);
  return true;
}

bool aac_offloading_capability_match(const AacParameters& aac_capability,
                                     const AacParameters& aac_config) {
  if ((static_cast<AacObjectType>(aac_capability.objectType &
                                  aac_config.objectType) ==
       static_cast<AacObjectType>(0)) ||
      (static_cast<SampleRate>(aac_capability.sampleRate &
                               aac_config.sampleRate) ==
       SampleRate::RATE_UNKNOWN) ||
      (static_cast<ChannelMode>(aac_capability.channelMode &
                                aac_config.channelMode) ==
       ChannelMode::UNKNOWN) ||
      (aac_capability.variableBitRateEnabled != AacVariableBitRate::ENABLED &&
       aac_config.variableBitRateEnabled != AacVariableBitRate::DISABLED) ||
      (static_cast<BitsPerSample>(aac_capability.bitsPerSample &
                                  aac_config.bitsPerSample) ==
       BitsPerSample::BITS_UNKNOWN)) {
    LOG(WARNING) << __func__ << ": software codec=" << toString(aac_config)
                 << " capability=" << toString(aac_capability);
    return false;
  }
  VLOG(1) << __func__ << ": offloading codec=" << toString(aac_config)
          << " capability=" << toString(aac_capability);
  return true;
}

bool aptx_offloading_capability_match(const AptxParameters& aptx_capability,
                                      const AptxParameters& aptx_config) {
  if ((static_cast<SampleRate>(aptx_capability.sampleRate &
                               aptx_config.sampleRate) ==
       SampleRate::RATE_UNKNOWN) ||
      (static_cast<ChannelMode>(aptx_capability.channelMode &
                                aptx_config.channelMode) ==
       ChannelMode::UNKNOWN) ||
      (static_cast<BitsPerSample>(aptx_capability.bitsPerSample &
                                  aptx_config.bitsPerSample) ==
       BitsPerSample::BITS_UNKNOWN)) {
    LOG(WARNING) << __func__ << ": software codec=" << toString(aptx_config)
                 << " capability=" << toString(aptx_capability);
    return false;
  }
  VLOG(1) << __func__ << ": offloading codec=" << toString(aptx_config)
          << " capability=" << toString(aptx_capability);
  return true;
}

bool ldac_offloading_capability_match(const LdacParameters& ldac_capability,
                                      const LdacParameters& ldac_config) {
  if ((static_cast<SampleRate>(ldac_capability.sampleRate &
                               ldac_config.sampleRate) ==
       SampleRate::RATE_UNKNOWN) ||
      (static_cast<LdacChannelMode>(ldac_capability.channelMode &
                                    ldac_config.channelMode) ==
       LdacChannelMode::UNKNOWN) ||
      (static_cast<BitsPerSample>(ldac_capability.bitsPerSample &
                                  ldac_config.bitsPerSample) ==
       BitsPerSample::BITS_UNKNOWN)) {
    LOG(WARNING) << __func__ << ": software codec=" << toString(ldac_config)
                 << " capability=" << toString(ldac_capability);
    return false;
  }
  VLOG(1) << __func__ << ": offloading codec=" << toString(ldac_config)
          << " capability=" << toString(ldac_capability);
  return true;
}
}  // namespace

namespace bluetooth {
namespace audio {
namespace codec {

const CodecConfiguration kInvalidCodecConfiguration = {
    .codecType = CodecType::UNKNOWN,
    .encodedAudioBitrate = 0x00000000,
    .peerMtu = 0xffff,
    .isScmstEnabled = false,
    .config = {}};

SampleRate A2dpCodecToHalSampleRate(
    const btav_a2dp_codec_config_t& a2dp_codec_config) {
  switch (a2dp_codec_config.sample_rate) {
    case BTAV_A2DP_CODEC_SAMPLE_RATE_44100:
      return SampleRate::RATE_44100;
    case BTAV_A2DP_CODEC_SAMPLE_RATE_48000:
      return SampleRate::RATE_48000;
    case BTAV_A2DP_CODEC_SAMPLE_RATE_88200:
      return SampleRate::RATE_88200;
    case BTAV_A2DP_CODEC_SAMPLE_RATE_96000:
      return SampleRate::RATE_96000;
    case BTAV_A2DP_CODEC_SAMPLE_RATE_176400:
      return SampleRate::RATE_176400;
    case BTAV_A2DP_CODEC_SAMPLE_RATE_192000:
      return SampleRate::RATE_192000;
    case BTAV_A2DP_CODEC_SAMPLE_RATE_16000:
      return SampleRate::RATE_16000;
    case BTAV_A2DP_CODEC_SAMPLE_RATE_24000:
      return SampleRate::RATE_24000;
    default:
      return SampleRate::RATE_UNKNOWN;
  }
}

BitsPerSample A2dpCodecToHalBitsPerSample(
    const btav_a2dp_codec_config_t& a2dp_codec_config) {
  switch (a2dp_codec_config.bits_per_sample) {
    case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16:
      return BitsPerSample::BITS_16;
    case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_24:
      return BitsPerSample::BITS_24;
    case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_32:
      return BitsPerSample::BITS_32;
    default:
      return BitsPerSample::BITS_UNKNOWN;
  }
}

ChannelMode A2dpCodecToHalChannelMode(
    const btav_a2dp_codec_config_t& a2dp_codec_config) {
  switch (a2dp_codec_config.channel_mode) {
    case BTAV_A2DP_CODEC_CHANNEL_MODE_MONO:
      return ChannelMode::MONO;
    case BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO:
      return ChannelMode::STEREO;
    default:
      return ChannelMode::UNKNOWN;
  }
}

bool A2dpSbcToHalConfig(CodecConfiguration* codec_config,
                        A2dpCodecConfig* a2dp_config) {
  btav_a2dp_codec_config_t current_codec = a2dp_config->getCodecConfig();
  if (current_codec.codec_type != BTAV_A2DP_CODEC_INDEX_SOURCE_SBC &&
      current_codec.codec_type != BTAV_A2DP_CODEC_INDEX_SINK_SBC) {
    *codec_config = {};
    return false;
  }
  tBT_A2DP_OFFLOAD a2dp_offload;
  a2dp_config->getCodecSpecificConfig(&a2dp_offload);
  codec_config->codecType = CodecType::SBC;
  codec_config->config.sbcConfig({});
  auto sbc_config = codec_config->config.sbcConfig();
  sbc_config.sampleRate = A2dpCodecToHalSampleRate(current_codec);
  if (sbc_config.sampleRate == SampleRate::RATE_UNKNOWN) {
    LOG(ERROR) << __func__
               << ": Unknown SBC sample_rate=" << current_codec.sample_rate;
    return false;
  }
  uint8_t channel_mode = a2dp_offload.codec_info[3] & A2DP_SBC_IE_CH_MD_MSK;
  switch (channel_mode) {
    case A2DP_SBC_IE_CH_MD_JOINT:
      sbc_config.channelMode = SbcChannelMode::JOINT_STEREO;
      break;
    case A2DP_SBC_IE_CH_MD_STEREO:
      sbc_config.channelMode = SbcChannelMode::STEREO;
      break;
    case A2DP_SBC_IE_CH_MD_DUAL:
      sbc_config.channelMode = SbcChannelMode::DUAL;
      break;
    case A2DP_SBC_IE_CH_MD_MONO:
      sbc_config.channelMode = SbcChannelMode::MONO;
      break;
    default:
      LOG(ERROR) << __func__ << ": Unknown SBC channel_mode=" << channel_mode;
      sbc_config.channelMode = SbcChannelMode::UNKNOWN;
      return false;
  }
  uint8_t block_length = a2dp_offload.codec_info[0] & A2DP_SBC_IE_BLOCKS_MSK;
  switch (block_length) {
    case A2DP_SBC_IE_BLOCKS_4:
      sbc_config.blockLength = SbcBlockLength::BLOCKS_4;
      break;
    case A2DP_SBC_IE_BLOCKS_8:
      sbc_config.blockLength = SbcBlockLength::BLOCKS_8;
      break;
    case A2DP_SBC_IE_BLOCKS_12:
      sbc_config.blockLength = SbcBlockLength::BLOCKS_12;
      break;
    case A2DP_SBC_IE_BLOCKS_16:
      sbc_config.blockLength = SbcBlockLength::BLOCKS_16;
      break;
    default:
      LOG(ERROR) << __func__ << ": Unknown SBC block_length=" << block_length;
      return false;
  }
  uint8_t sub_bands = a2dp_offload.codec_info[0] & A2DP_SBC_IE_SUBBAND_MSK;
  switch (sub_bands) {
    case A2DP_SBC_IE_SUBBAND_4:
      sbc_config.numSubbands = SbcNumSubbands::SUBBAND_4;
      break;
    case A2DP_SBC_IE_SUBBAND_8:
      sbc_config.numSubbands = SbcNumSubbands::SUBBAND_8;
      break;
    default:
      LOG(ERROR) << __func__ << ": Unknown SBC Subbands=" << sub_bands;
      return false;
  }
  uint8_t alloc_method = a2dp_offload.codec_info[0] & A2DP_SBC_IE_ALLOC_MD_MSK;
  switch (alloc_method) {
    case A2DP_SBC_IE_ALLOC_MD_S:
      sbc_config.allocMethod = SbcAllocMethod::ALLOC_MD_S;
      break;
    case A2DP_SBC_IE_ALLOC_MD_L:
      sbc_config.allocMethod = SbcAllocMethod::ALLOC_MD_L;
      break;
    default:
      LOG(ERROR) << __func__ << ": Unknown SBC alloc_method=" << alloc_method;
      return false;
  }
  sbc_config.minBitpool = a2dp_offload.codec_info[1];
  sbc_config.maxBitpool = a2dp_offload.codec_info[2];
  sbc_config.bitsPerSample = A2dpCodecToHalBitsPerSample(current_codec);
  if (sbc_config.bitsPerSample == BitsPerSample::BITS_UNKNOWN) {
    LOG(ERROR) << __func__ << ": Unknown SBC bits_per_sample="
               << current_codec.bits_per_sample;
    return false;
  }
  codec_config->config.sbcConfig(sbc_config);
  return true;
}

bool A2dpAacToHalConfig(CodecConfiguration* codec_config,
                        A2dpCodecConfig* a2dp_config) {
  btav_a2dp_codec_config_t current_codec = a2dp_config->getCodecConfig();
  if (current_codec.codec_type != BTAV_A2DP_CODEC_INDEX_SOURCE_AAC &&
      current_codec.codec_type != BTAV_A2DP_CODEC_INDEX_SINK_AAC) {
    *codec_config = {};
    return false;
  }
  tBT_A2DP_OFFLOAD a2dp_offload;
  a2dp_config->getCodecSpecificConfig(&a2dp_offload);
  codec_config->codecType = CodecType::AAC;
  codec_config->config.aacConfig({});
  auto aac_config = codec_config->config.aacConfig();
  uint8_t object_type = a2dp_offload.codec_info[0];
  switch (object_type) {
    case A2DP_AAC_OBJECT_TYPE_MPEG2_LC:
      aac_config.objectType = AacObjectType::MPEG2_LC;
      break;
    case A2DP_AAC_OBJECT_TYPE_MPEG4_LC:
      aac_config.objectType = AacObjectType::MPEG4_LC;
      break;
    case A2DP_AAC_OBJECT_TYPE_MPEG4_LTP:
      aac_config.objectType = AacObjectType::MPEG4_LTP;
      break;
    case A2DP_AAC_OBJECT_TYPE_MPEG4_SCALABLE:
      aac_config.objectType = AacObjectType::MPEG4_SCALABLE;
      break;
    default:
      LOG(ERROR) << __func__ << ": Unknown AAC object_type=" << +object_type;
      return false;
  }
  aac_config.sampleRate = A2dpCodecToHalSampleRate(current_codec);
  if (aac_config.sampleRate == SampleRate::RATE_UNKNOWN) {
    LOG(ERROR) << __func__
               << ": Unknown AAC sample_rate=" << current_codec.sample_rate;
    return false;
  }
  aac_config.channelMode = A2dpCodecToHalChannelMode(current_codec);
  if (aac_config.channelMode == ChannelMode::UNKNOWN) {
    LOG(ERROR) << __func__
               << ": Unknown AAC channel_mode=" << current_codec.channel_mode;
    return false;
  }
  uint8_t vbr_enabled =
      a2dp_offload.codec_info[1] & A2DP_AAC_VARIABLE_BIT_RATE_MASK;
  switch (vbr_enabled) {
    case A2DP_AAC_VARIABLE_BIT_RATE_ENABLED:
      aac_config.variableBitRateEnabled = AacVariableBitRate::ENABLED;
      break;
    case A2DP_AAC_VARIABLE_BIT_RATE_DISABLED:
      aac_config.variableBitRateEnabled = AacVariableBitRate::DISABLED;
      break;
    default:
      LOG(ERROR) << __func__ << ": Unknown AAC VBR=" << +vbr_enabled;
      return false;
  }
  aac_config.bitsPerSample = A2dpCodecToHalBitsPerSample(current_codec);
  if (aac_config.bitsPerSample == BitsPerSample::BITS_UNKNOWN) {
    LOG(ERROR) << __func__ << ": Unknown AAC bits_per_sample="
               << current_codec.bits_per_sample;
    return false;
  }
  codec_config->config.aacConfig(aac_config);
  return true;
}

bool A2dpAptxToHalConfig(CodecConfiguration* codec_config,
                         A2dpCodecConfig* a2dp_config) {
  btav_a2dp_codec_config_t current_codec = a2dp_config->getCodecConfig();
  if (current_codec.codec_type != BTAV_A2DP_CODEC_INDEX_SOURCE_APTX &&
      current_codec.codec_type != BTAV_A2DP_CODEC_INDEX_SOURCE_APTX_HD) {
    *codec_config = {};
    return false;
  }
  tBT_A2DP_OFFLOAD a2dp_offload;
  a2dp_config->getCodecSpecificConfig(&a2dp_offload);
  if (current_codec.codec_type == BTAV_A2DP_CODEC_INDEX_SOURCE_APTX) {
    codec_config->codecType = CodecType::APTX;
  } else {
    codec_config->codecType = CodecType::APTX_HD;
  }
  codec_config->config.aptxConfig({});
  auto aptx_config = codec_config->config.aptxConfig();
  aptx_config.sampleRate = A2dpCodecToHalSampleRate(current_codec);
  if (aptx_config.sampleRate == SampleRate::RATE_UNKNOWN) {
    LOG(ERROR) << __func__
               << ": Unknown aptX sample_rate=" << current_codec.sample_rate;
    return false;
  }
  aptx_config.channelMode = A2dpCodecToHalChannelMode(current_codec);
  if (aptx_config.channelMode == ChannelMode::UNKNOWN) {
    LOG(ERROR) << __func__
               << ": Unknown aptX channel_mode=" << current_codec.channel_mode;
    return false;
  }
  aptx_config.bitsPerSample = A2dpCodecToHalBitsPerSample(current_codec);
  if (aptx_config.bitsPerSample == BitsPerSample::BITS_UNKNOWN) {
    LOG(ERROR) << __func__ << ": Unknown aptX bits_per_sample="
               << current_codec.bits_per_sample;
    return false;
  }
  codec_config->config.aptxConfig(aptx_config);
  return true;
}

bool A2dpLdacToHalConfig(CodecConfiguration* codec_config,
                         A2dpCodecConfig* a2dp_config) {
  btav_a2dp_codec_config_t current_codec = a2dp_config->getCodecConfig();
  if (current_codec.codec_type != BTAV_A2DP_CODEC_INDEX_SOURCE_LDAC) {
    codec_config = {};
    return false;
  }
  tBT_A2DP_OFFLOAD a2dp_offload;
  a2dp_config->getCodecSpecificConfig(&a2dp_offload);
  codec_config->codecType = CodecType::LDAC;
  codec_config->config.ldacConfig({});
  auto ldac_config = codec_config->config.ldacConfig();
  ldac_config.sampleRate = A2dpCodecToHalSampleRate(current_codec);
  if (ldac_config.sampleRate == SampleRate::RATE_UNKNOWN) {
    LOG(ERROR) << __func__
               << ": Unknown LDAC sample_rate=" << current_codec.sample_rate;
    return false;
  }
  switch (a2dp_offload.codec_info[7]) {
    case A2DP_LDAC_CHANNEL_MODE_STEREO:
      ldac_config.channelMode = LdacChannelMode::STEREO;
      break;
    case A2DP_LDAC_CHANNEL_MODE_DUAL:
      ldac_config.channelMode = LdacChannelMode::DUAL;
      break;
    case A2DP_LDAC_CHANNEL_MODE_MONO:
      ldac_config.channelMode = LdacChannelMode::MONO;
      break;
    default:
      LOG(ERROR) << __func__ << ": Unknown LDAC channel_mode="
                 << a2dp_offload.codec_info[7];
      ldac_config.channelMode = LdacChannelMode::UNKNOWN;
      return false;
  }
  switch (a2dp_offload.codec_info[6]) {
    case A2DP_LDAC_QUALITY_HIGH:
      ldac_config.qualityIndex = LdacQualityIndex::QUALITY_HIGH;
      break;
    case A2DP_LDAC_QUALITY_MID:
      ldac_config.qualityIndex = LdacQualityIndex::QUALITY_MID;
      break;
    case A2DP_LDAC_QUALITY_LOW:
      ldac_config.qualityIndex = LdacQualityIndex::QUALITY_LOW;
      break;
    case A2DP_LDAC_QUALITY_ABR_OFFLOAD:
      ldac_config.qualityIndex = LdacQualityIndex::QUALITY_ABR;
      break;
    default:
      LOG(ERROR) << __func__ << ": Unknown LDAC QualityIndex="
                 << a2dp_offload.codec_info[6];
      return false;
  }
  ldac_config.bitsPerSample = A2dpCodecToHalBitsPerSample(current_codec);
  if (ldac_config.bitsPerSample == BitsPerSample::BITS_UNKNOWN) {
    LOG(ERROR) << __func__ << ": Unknown LDAC bits_per_sample="
               << current_codec.bits_per_sample;
    return false;
  }
  codec_config->config.ldacConfig(ldac_config);
  return true;
}

bool UpdateOffloadingCapabilities(
    const std::vector<btav_a2dp_codec_config_t>& framework_preference) {
  audio_hal_capabilities = BluetoothAudioClientInterface::GetAudioCapabilities(
      SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH);
  uint32_t codec_type_masks = static_cast<uint32_t>(CodecType::UNKNOWN);
  for (auto preference : framework_preference) {
    switch (preference.codec_type) {
      case BTAV_A2DP_CODEC_INDEX_SOURCE_SBC:
        codec_type_masks |= CodecType::SBC;
        break;
      case BTAV_A2DP_CODEC_INDEX_SOURCE_AAC:
        codec_type_masks |= CodecType::AAC;
        break;
      case BTAV_A2DP_CODEC_INDEX_SOURCE_APTX:
        codec_type_masks |= CodecType::APTX;
        break;
      case BTAV_A2DP_CODEC_INDEX_SOURCE_APTX_HD:
        codec_type_masks |= CodecType::APTX_HD;
        break;
      case BTAV_A2DP_CODEC_INDEX_SOURCE_LDAC:
        codec_type_masks |= CodecType::LDAC;
        break;
      case BTAV_A2DP_CODEC_INDEX_SINK_SBC:
        [[fallthrough]];
      case BTAV_A2DP_CODEC_INDEX_SINK_AAC:
        [[fallthrough]];
      case BTAV_A2DP_CODEC_INDEX_SINK_LDAC:
        LOG(WARNING) << __func__
                     << ": Ignore sink codec_type=" << preference.codec_type;
        break;
      case BTAV_A2DP_CODEC_INDEX_MAX:
        [[fallthrough]];
      default:
        LOG(ERROR) << __func__
                   << ": Unknown codec_type=" << preference.codec_type;
        return false;
    }
  }
  offloading_preference.clear();
  for (auto capability : audio_hal_capabilities) {
    if (static_cast<CodecType>(capability.codecCapabilities().codecType &
                               codec_type_masks) != CodecType::UNKNOWN) {
      LOG(INFO) << __func__
                << ": enabled offloading capability=" << toString(capability);
      offloading_preference.push_back(capability);
    } else {
      LOG(INFO) << __func__
                << ": disabled offloading capability=" << toString(capability);
    }
  }
  // TODO: Bluetooth SoC and runtime property
  return true;
}

// Check whether this codec is supported by the audio HAL and is allowed to use
// by prefernece of framework / Bluetooth SoC / runtime property.
bool IsCodecOffloadingEnabled(const CodecConfiguration& codec_config) {
  for (auto preference : offloading_preference) {
    if (codec_config.codecType != preference.codecCapabilities().codecType)
      continue;
    auto codec_capability = preference.codecCapabilities();
    switch (codec_capability.codecType) {
      case CodecType::SBC: {
        auto sbc_capability = codec_capability.capabilities.sbcCapabilities();
        auto sbc_config = codec_config.config.sbcConfig();
        return sbc_offloading_capability_match(sbc_capability, sbc_config);
      }
      case CodecType::AAC: {
        auto aac_capability = codec_capability.capabilities.aacCapabilities();
        auto aac_config = codec_config.config.aacConfig();
        return aac_offloading_capability_match(aac_capability, aac_config);
      }
      case CodecType::APTX:
        [[fallthrough]];
      case CodecType::APTX_HD: {
        auto aptx_capability = codec_capability.capabilities.aptxCapabilities();
        auto aptx_config = codec_config.config.aptxConfig();
        return aptx_offloading_capability_match(aptx_capability, aptx_config);
      }
      case CodecType::LDAC: {
        auto ldac_capability = codec_capability.capabilities.ldacCapabilities();
        auto ldac_config = codec_config.config.ldacConfig();
        return ldac_offloading_capability_match(ldac_capability, ldac_config);
      }
      case CodecType::UNKNOWN:
        [[fallthrough]];
      default:
        LOG(ERROR) << __func__ << ": Unknown codecType="
                   << toString(codec_capability.codecType);
        return false;
    }
  }
  LOG(INFO) << __func__ << ": software codec=" << toString(codec_config);
  return false;
}

}  // namespace codec
}  // namespace audio
}  // namespace bluetooth
