/*
 * Copyright 2020 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 "BTAudioProviderSessionCodecsDB"

#include "BluetoothAudioSupportedCodecsDB.h"

#include <android-base/logging.h>

namespace android {
namespace bluetooth {
namespace audio {

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::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::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;
using ::android::hardware::bluetooth::audio::V2_1::SampleRate;

// Default Supported PCM Parameters
static const ::android::hardware::bluetooth::audio::V2_0::PcmParameters
    kDefaultSoftwarePcmCapabilities = {
        .sampleRate = static_cast<
            android::hardware::bluetooth::audio::V2_0::SampleRate>(
            android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_44100 |
            android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_48000 |
            android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_88200 |
            android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_96000 |
            android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_16000),
        .channelMode =
            static_cast<ChannelMode>(ChannelMode::MONO | ChannelMode::STEREO),
        .bitsPerSample = static_cast<BitsPerSample>(BitsPerSample::BITS_16 |
                                                    BitsPerSample::BITS_24 |
                                                    BitsPerSample::BITS_32)};

static const PcmParameters kDefaultSoftwarePcmCapabilities_2_1 = {
    .sampleRate = static_cast<SampleRate>(
        SampleRate::RATE_48000 | SampleRate::RATE_44100 |
        SampleRate::RATE_32000 | SampleRate::RATE_24000 |
        SampleRate::RATE_16000 | SampleRate::RATE_8000),
    .channelMode =
        static_cast<ChannelMode>(ChannelMode::MONO | ChannelMode::STEREO),
    .bitsPerSample = static_cast<BitsPerSample>(BitsPerSample::BITS_16)};

// Default Supported Codecs
// SBC: mSampleRate:(44100), mBitsPerSample:(16), mChannelMode:(MONO|STEREO)
//      all blocks | subbands 8 | Loudness
static const SbcParameters kDefaultOffloadSbcCapability = {
    .sampleRate =
        android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_44100,
    .channelMode = static_cast<SbcChannelMode>(SbcChannelMode::MONO |
                                               SbcChannelMode::JOINT_STEREO),
    .blockLength = static_cast<SbcBlockLength>(
        SbcBlockLength::BLOCKS_4 | SbcBlockLength::BLOCKS_8 |
        SbcBlockLength::BLOCKS_12 | SbcBlockLength::BLOCKS_16),
    .numSubbands = SbcNumSubbands::SUBBAND_8,
    .allocMethod = SbcAllocMethod::ALLOC_MD_L,
    .bitsPerSample = BitsPerSample::BITS_16,
    .minBitpool = 2,
    .maxBitpool = 53};

// AAC: mSampleRate:(44100), mBitsPerSample:(16), mChannelMode:(STEREO)
static const AacParameters kDefaultOffloadAacCapability = {
    .objectType = AacObjectType::MPEG2_LC,
    .sampleRate =
        android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_44100,
    .channelMode = ChannelMode::STEREO,
    .variableBitRateEnabled = AacVariableBitRate::ENABLED,
    .bitsPerSample = BitsPerSample::BITS_16};

// LDAC: mSampleRate:(44100|48000|88200|96000), mBitsPerSample:(16|24|32),
//       mChannelMode:(DUAL|STEREO)
static const LdacParameters kDefaultOffloadLdacCapability = {
    .sampleRate =
        static_cast<android::hardware::bluetooth::audio::V2_0::SampleRate>(
            android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_44100 |
            android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_48000 |
            android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_88200 |
            android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_96000),
    .channelMode = static_cast<LdacChannelMode>(LdacChannelMode::DUAL |
                                                LdacChannelMode::STEREO),
    .qualityIndex = LdacQualityIndex::QUALITY_HIGH,
    .bitsPerSample = static_cast<BitsPerSample>(BitsPerSample::BITS_16 |
                                                BitsPerSample::BITS_24 |
                                                BitsPerSample::BITS_32)};

// aptX: mSampleRate:(44100|48000), mBitsPerSample:(16), mChannelMode:(STEREO)
static const AptxParameters kDefaultOffloadAptxCapability = {
    .sampleRate =
        static_cast<android::hardware::bluetooth::audio::V2_0::SampleRate>(
            android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_44100 |
            android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_48000),
    .channelMode = ChannelMode::STEREO,
    .bitsPerSample = BitsPerSample::BITS_16,
};

// aptX HD: mSampleRate:(44100|48000), mBitsPerSample:(24),
//          mChannelMode:(STEREO)
static const AptxParameters kDefaultOffloadAptxHdCapability = {
    .sampleRate =
        static_cast<android::hardware::bluetooth::audio::V2_0::SampleRate>(
            android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_44100 |
            android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_48000),
    .channelMode = ChannelMode::STEREO,
    .bitsPerSample = BitsPerSample::BITS_24,
};

const std::vector<CodecCapabilities> kDefaultOffloadA2dpCodecCapabilities = {
    {.codecType = CodecType::SBC, .capabilities = {}},
    {.codecType = CodecType::AAC, .capabilities = {}},
    {.codecType = CodecType::LDAC, .capabilities = {}},
    {.codecType = CodecType::APTX, .capabilities = {}},
    {.codecType = CodecType::APTX_HD, .capabilities = {}}};

static bool IsSingleBit(uint32_t bitmasks, uint32_t bitfield) {
  bool single = false;
  uint32_t test_bit = 0x00000001;
  while (test_bit <= bitmasks && test_bit <= bitfield) {
    if (bitfield & test_bit && bitmasks & test_bit) {
      if (single) return false;
      single = true;
    }
    if (test_bit == 0x80000000) break;
    test_bit <<= 1;
  }
  return single;
}

static bool IsOffloadSbcConfigurationValid(
    const CodecConfiguration::CodecSpecific& codec_specific);
static bool IsOffloadAacConfigurationValid(
    const CodecConfiguration::CodecSpecific& codec_specific);
static bool IsOffloadLdacConfigurationValid(
    const CodecConfiguration::CodecSpecific& codec_specific);
static bool IsOffloadAptxConfigurationValid(
    const CodecConfiguration::CodecSpecific& codec_specific);
static bool IsOffloadAptxHdConfigurationValid(
    const CodecConfiguration::CodecSpecific& codec_specific);

static bool IsOffloadSbcConfigurationValid(
    const CodecConfiguration::CodecSpecific& codec_specific) {
  if (codec_specific.getDiscriminator() !=
      CodecConfiguration::CodecSpecific::hidl_discriminator::sbcConfig) {
    LOG(WARNING) << __func__
                 << ": Invalid CodecSpecific=" << toString(codec_specific);
    return false;
  }
  const SbcParameters sbc_data = codec_specific.sbcConfig();
  if (!IsSingleBit(static_cast<uint32_t>(sbc_data.sampleRate), 0xff) ||
      !IsSingleBit(static_cast<uint32_t>(sbc_data.channelMode), 0x0f) ||
      !IsSingleBit(static_cast<uint32_t>(sbc_data.blockLength), 0xf0) ||
      !IsSingleBit(static_cast<uint32_t>(sbc_data.numSubbands), 0x0c) ||
      !IsSingleBit(static_cast<uint32_t>(sbc_data.allocMethod), 0x03) ||
      !IsSingleBit(static_cast<uint32_t>(sbc_data.bitsPerSample), 0x07) ||
      sbc_data.minBitpool > sbc_data.maxBitpool) {
    LOG(WARNING) << __func__
                 << ": Invalid CodecSpecific=" << toString(codec_specific);
    return false;
  } else if ((sbc_data.sampleRate & kDefaultOffloadSbcCapability.sampleRate) &&
             (sbc_data.channelMode &
              kDefaultOffloadSbcCapability.channelMode) &&
             (sbc_data.blockLength &
              kDefaultOffloadSbcCapability.blockLength) &&
             (sbc_data.numSubbands &
              kDefaultOffloadSbcCapability.numSubbands) &&
             (sbc_data.allocMethod &
              kDefaultOffloadSbcCapability.allocMethod) &&
             (sbc_data.bitsPerSample &
              kDefaultOffloadSbcCapability.bitsPerSample) &&
             (kDefaultOffloadSbcCapability.minBitpool <= sbc_data.minBitpool &&
              sbc_data.maxBitpool <= kDefaultOffloadSbcCapability.maxBitpool)) {
    return true;
  }
  LOG(WARNING) << __func__
               << ": Unsupported CodecSpecific=" << toString(codec_specific);
  return false;
}

static bool IsOffloadAacConfigurationValid(
    const CodecConfiguration::CodecSpecific& codec_specific) {
  if (codec_specific.getDiscriminator() !=
      CodecConfiguration::CodecSpecific::hidl_discriminator::aacConfig) {
    LOG(WARNING) << __func__
                 << ": Invalid CodecSpecific=" << toString(codec_specific);
    return false;
  }
  const AacParameters aac_data = codec_specific.aacConfig();
  if (!IsSingleBit(static_cast<uint32_t>(aac_data.objectType), 0xf0) ||
      !IsSingleBit(static_cast<uint32_t>(aac_data.sampleRate), 0xff) ||
      !IsSingleBit(static_cast<uint32_t>(aac_data.channelMode), 0x03) ||
      !IsSingleBit(static_cast<uint32_t>(aac_data.bitsPerSample), 0x07)) {
    LOG(WARNING) << __func__
                 << ": Invalid CodecSpecific=" << toString(codec_specific);
    return false;
  } else if ((aac_data.objectType & kDefaultOffloadAacCapability.objectType) &&
             (aac_data.sampleRate & kDefaultOffloadAacCapability.sampleRate) &&
             (aac_data.channelMode &
              kDefaultOffloadAacCapability.channelMode) &&
             (aac_data.variableBitRateEnabled == AacVariableBitRate::DISABLED ||
              kDefaultOffloadAacCapability.variableBitRateEnabled ==
                  AacVariableBitRate::ENABLED) &&
             (aac_data.bitsPerSample &
              kDefaultOffloadAacCapability.bitsPerSample)) {
    return true;
  }
  LOG(WARNING) << __func__
               << ": Unsupported CodecSpecific=" << toString(codec_specific);
  return false;
}

static bool IsOffloadLdacConfigurationValid(
    const CodecConfiguration::CodecSpecific& codec_specific) {
  if (codec_specific.getDiscriminator() !=
      CodecConfiguration::CodecSpecific::hidl_discriminator::ldacConfig) {
    LOG(WARNING) << __func__
                 << ": Invalid CodecSpecific=" << toString(codec_specific);
    return false;
  }
  const LdacParameters ldac_data = codec_specific.ldacConfig();
  if (!IsSingleBit(static_cast<uint32_t>(ldac_data.sampleRate), 0xff) ||
      !IsSingleBit(static_cast<uint32_t>(ldac_data.channelMode), 0x07) ||
      (ldac_data.qualityIndex > LdacQualityIndex::QUALITY_LOW &&
       ldac_data.qualityIndex != LdacQualityIndex::QUALITY_ABR) ||
      !IsSingleBit(static_cast<uint32_t>(ldac_data.bitsPerSample), 0x07)) {
    LOG(WARNING) << __func__
                 << ": Invalid CodecSpecific=" << toString(codec_specific);
    return false;
  } else if ((ldac_data.sampleRate &
              kDefaultOffloadLdacCapability.sampleRate) &&
             (ldac_data.channelMode &
              kDefaultOffloadLdacCapability.channelMode) &&
             (ldac_data.bitsPerSample &
              kDefaultOffloadLdacCapability.bitsPerSample)) {
    return true;
  }
  LOG(WARNING) << __func__
               << ": Unsupported CodecSpecific=" << toString(codec_specific);
  return false;
}

static bool IsOffloadAptxConfigurationValid(
    const CodecConfiguration::CodecSpecific& codec_specific) {
  if (codec_specific.getDiscriminator() !=
      CodecConfiguration::CodecSpecific::hidl_discriminator::aptxConfig) {
    LOG(WARNING) << __func__
                 << ": Invalid CodecSpecific=" << toString(codec_specific);
    return false;
  }
  const AptxParameters aptx_data = codec_specific.aptxConfig();
  if (!IsSingleBit(static_cast<uint32_t>(aptx_data.sampleRate), 0xff) ||
      !IsSingleBit(static_cast<uint32_t>(aptx_data.channelMode), 0x03) ||
      !IsSingleBit(static_cast<uint32_t>(aptx_data.bitsPerSample), 0x07)) {
    LOG(WARNING) << __func__
                 << ": Invalid CodecSpecific=" << toString(codec_specific);
    return false;
  } else if ((aptx_data.sampleRate &
              kDefaultOffloadAptxCapability.sampleRate) &&
             (aptx_data.channelMode &
              kDefaultOffloadAptxCapability.channelMode) &&
             (aptx_data.bitsPerSample &
              kDefaultOffloadAptxCapability.bitsPerSample)) {
    return true;
  }
  LOG(WARNING) << __func__
               << ": Unsupported CodecSpecific=" << toString(codec_specific);
  return false;
}

static bool IsOffloadAptxHdConfigurationValid(
    const CodecConfiguration::CodecSpecific& codec_specific) {
  if (codec_specific.getDiscriminator() !=
      CodecConfiguration::CodecSpecific::hidl_discriminator::aptxConfig) {
    LOG(WARNING) << __func__
                 << ": Invalid CodecSpecific=" << toString(codec_specific);
    return false;
  }
  const AptxParameters aptx_data = codec_specific.aptxConfig();
  if (!IsSingleBit(static_cast<uint32_t>(aptx_data.sampleRate), 0xff) ||
      !IsSingleBit(static_cast<uint32_t>(aptx_data.channelMode), 0x03) ||
      !IsSingleBit(static_cast<uint32_t>(aptx_data.bitsPerSample), 0x07)) {
    LOG(WARNING) << __func__
                 << ": Invalid CodecSpecific=" << toString(codec_specific);
    return false;
  } else if ((aptx_data.sampleRate &
              kDefaultOffloadAptxHdCapability.sampleRate) &&
             (aptx_data.channelMode &
              kDefaultOffloadAptxHdCapability.channelMode) &&
             (aptx_data.bitsPerSample &
              kDefaultOffloadAptxHdCapability.bitsPerSample)) {
    return true;
  }
  LOG(WARNING) << __func__
               << ": Unsupported CodecSpecific=" << toString(codec_specific);
  return false;
}

std::vector<::android::hardware::bluetooth::audio::V2_0::PcmParameters>
GetSoftwarePcmCapabilities() {
  return std::vector<
      ::android::hardware::bluetooth::audio::V2_0::PcmParameters>(
      1, kDefaultSoftwarePcmCapabilities);
}

std::vector<PcmParameters> GetSoftwarePcmCapabilities_2_1() {
  return std::vector<PcmParameters>(1, kDefaultSoftwarePcmCapabilities_2_1);
}

std::vector<CodecCapabilities> GetOffloadCodecCapabilities(
    const ::android::hardware::bluetooth::audio::V2_0::SessionType&
        session_type) {
  return GetOffloadCodecCapabilities(static_cast<SessionType>(session_type));
}

std::vector<CodecCapabilities> GetOffloadCodecCapabilities(
    const SessionType& session_type) {
  if (session_type != SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH) {
    return std::vector<CodecCapabilities>(0);
  }
  std::vector<CodecCapabilities> offload_a2dp_codec_capabilities =
      kDefaultOffloadA2dpCodecCapabilities;
  for (auto& codec_capability : offload_a2dp_codec_capabilities) {
    switch (codec_capability.codecType) {
      case CodecType::SBC:
        codec_capability.capabilities.sbcCapabilities(
            kDefaultOffloadSbcCapability);
        break;
      case CodecType::AAC:
        codec_capability.capabilities.aacCapabilities(
            kDefaultOffloadAacCapability);
        break;
      case CodecType::LDAC:
        codec_capability.capabilities.ldacCapabilities(
            kDefaultOffloadLdacCapability);
        break;
      case CodecType::APTX:
        codec_capability.capabilities.aptxCapabilities(
            kDefaultOffloadAptxCapability);
        break;
      case CodecType::APTX_HD:
        codec_capability.capabilities.aptxCapabilities(
            kDefaultOffloadAptxHdCapability);
        break;
      case CodecType::UNKNOWN:
        codec_capability = {};
        break;
    }
  }
  return offload_a2dp_codec_capabilities;
}

bool IsSoftwarePcmConfigurationValid(
    const ::android::hardware::bluetooth::audio::V2_0::PcmParameters&
        pcm_config) {
  if ((pcm_config.sampleRate !=
           android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_44100 &&
       pcm_config.sampleRate !=
           android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_48000 &&
       pcm_config.sampleRate !=
           android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_88200 &&
       pcm_config.sampleRate !=
           android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_96000 &&
       pcm_config.sampleRate !=
           android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_16000 &&
       pcm_config.sampleRate !=
           android::hardware::bluetooth::audio::V2_0::SampleRate::RATE_24000) ||
      (pcm_config.bitsPerSample != BitsPerSample::BITS_16 &&
       pcm_config.bitsPerSample != BitsPerSample::BITS_24 &&
       pcm_config.bitsPerSample != BitsPerSample::BITS_32) ||
      (pcm_config.channelMode != ChannelMode::MONO &&
       pcm_config.channelMode != ChannelMode::STEREO)) {
    LOG(WARNING) << __func__
                 << ": Invalid PCM Configuration=" << toString(pcm_config);
    return false;
  } else if (pcm_config.sampleRate &
                 kDefaultSoftwarePcmCapabilities.sampleRate &&
             pcm_config.bitsPerSample &
                 kDefaultSoftwarePcmCapabilities.bitsPerSample &&
             pcm_config.channelMode &
                 kDefaultSoftwarePcmCapabilities.channelMode) {
    return true;
  }
  LOG(WARNING) << __func__
               << ": Unsupported PCM Configuration=" << toString(pcm_config);
  return false;
}

bool IsSoftwarePcmConfigurationValid_2_1(const PcmParameters& pcm_config) {
  if ((pcm_config.sampleRate != SampleRate::RATE_96000 &&
       pcm_config.sampleRate != SampleRate::RATE_88200 &&
       pcm_config.sampleRate != SampleRate::RATE_48000 &&
       pcm_config.sampleRate != SampleRate::RATE_44100 &&
       pcm_config.sampleRate != SampleRate::RATE_32000 &&
       pcm_config.sampleRate != SampleRate::RATE_24000 &&
       pcm_config.sampleRate != SampleRate::RATE_16000 &&
       pcm_config.sampleRate != SampleRate::RATE_8000) ||
      (pcm_config.bitsPerSample != BitsPerSample::BITS_16 &&
       pcm_config.bitsPerSample != BitsPerSample::BITS_24 &&
       pcm_config.bitsPerSample != BitsPerSample::BITS_32) ||
      (pcm_config.channelMode != ChannelMode::MONO &&
       pcm_config.channelMode != ChannelMode::STEREO)) {
    LOG(WARNING) << __func__
                 << ": Invalid PCM Configuration=" << toString(pcm_config);
    return false;
  } else if (pcm_config.sampleRate &
                 kDefaultSoftwarePcmCapabilities_2_1.sampleRate &&
             pcm_config.bitsPerSample &
                 kDefaultSoftwarePcmCapabilities_2_1.bitsPerSample &&
             pcm_config.channelMode &
                 kDefaultSoftwarePcmCapabilities_2_1.channelMode &&
             pcm_config.dataIntervalUs != 0) {
    return true;
  }
  LOG(WARNING) << __func__
               << ": Unsupported PCM Configuration=" << toString(pcm_config);
  return false;
}

bool IsOffloadCodecConfigurationValid(const SessionType& session_type,
                                      const CodecConfiguration& codec_config) {
  if (session_type != SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH) {
    LOG(ERROR) << __func__
               << ": Invalid SessionType=" << toString(session_type);
    return false;
  } else if (codec_config.encodedAudioBitrate < 0x00000001 ||
             0x00ffffff < codec_config.encodedAudioBitrate) {
    LOG(ERROR) << __func__ << ": Unsupported Codec Configuration="
               << toString(codec_config);
    return false;
  }
  const CodecConfiguration::CodecSpecific& codec_specific = codec_config.config;
  switch (codec_config.codecType) {
    case CodecType::SBC:
      if (IsOffloadSbcConfigurationValid(codec_specific)) {
        return true;
      }
      return false;
    case CodecType::AAC:
      if (IsOffloadAacConfigurationValid(codec_specific)) {
        return true;
      }
      return false;
    case CodecType::LDAC:
      if (IsOffloadLdacConfigurationValid(codec_specific)) {
        return true;
      }
      return false;
    case CodecType::APTX:
      if (IsOffloadAptxConfigurationValid(codec_specific)) {
        return true;
      }
      return false;
    case CodecType::APTX_HD:
      if (IsOffloadAptxHdConfigurationValid(codec_specific)) {
        return true;
      }
      return false;
    case CodecType::UNKNOWN:
      return false;
  }
  return false;
}

}  // namespace audio
}  // namespace bluetooth
}  // namespace android
