/*
 * 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 BluetoothAudioSinkClientInterface::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 =
      BluetoothAudioSinkClientInterface::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
