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

Commit f09101db authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "A2DP: HAL codec offloading capabilities check preparation"

parents d06f9fa3 16bd6eb3
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@ cc_library_static {
    srcs: [
        "a2dp_encoding.cc",
        "client_interface.cc",
        "codec_status.cc",
        "hearing_aid_software_encoding.cc",
    ],
    shared_libs: [
@@ -36,6 +37,7 @@ cc_test {
    defaults: ["fluoride_defaults"],
    include_dirs: [
        "packages/modules/Bluetooth/system",
        "packages/modules/Bluetooth/system/stack/include",
    ],
    srcs: [
        "client_interface_unittest.cc",
+30 −294
Original line number Diff line number Diff line
@@ -16,11 +16,8 @@

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

#include "a2dp_aac_constants.h"
#include "a2dp_sbc_constants.h"
#include "a2dp_vendor_ldac_constants.h"
#include "bta/av/bta_av_int.h"
#include "btif_a2dp_source.h"
#include "btif_av.h"
#include "btif_av_co.h"
@@ -29,30 +26,23 @@

namespace {

using ::android::hardware::bluetooth::audio::V2_0::AacObjectType;
using ::android::hardware::bluetooth::audio::V2_0::AacVariableBitRate;
using ::android::hardware::bluetooth::audio::V2_0::CodecType;
using ::android::hardware::bluetooth::audio::V2_0::LdacChannelMode;
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 ::bluetooth::audio::AudioCapabilities;
using ::bluetooth::audio::AudioConfiguration;
using ::bluetooth::audio::BitsPerSample;
using ::bluetooth::audio::BluetoothAudioCtrlAck;
using ::bluetooth::audio::ChannelMode;
using ::bluetooth::audio::CodecConfiguration;
using ::bluetooth::audio::PcmParameters;
using ::bluetooth::audio::SampleRate;
using ::bluetooth::audio::SessionType;

const CodecConfiguration kInvalidCodecConfiguration = {
    .codecType = CodecType::UNKNOWN,
    .encodedAudioBitrate = 0x00000000,
    .peerMtu = 0xffff,
    .isScmstEnabled = false,
    .config = {}};
using ::bluetooth::audio::codec::A2dpAacToHalConfig;
using ::bluetooth::audio::codec::A2dpAptxToHalConfig;
using ::bluetooth::audio::codec::A2dpCodecToHalBitsPerSample;
using ::bluetooth::audio::codec::A2dpCodecToHalChannelMode;
using ::bluetooth::audio::codec::A2dpCodecToHalSampleRate;
using ::bluetooth::audio::codec::A2dpLdacToHalConfig;
using ::bluetooth::audio::codec::A2dpSbcToHalConfig;
using ::bluetooth::audio::codec::CodecConfiguration;

BluetoothAudioCtrlAck a2dp_ack_to_bt_audio_ctrl_ack(tA2DP_CTRL_ACK ack);

@@ -226,301 +216,43 @@ BluetoothAudioCtrlAck a2dp_ack_to_bt_audio_ctrl_ack(tA2DP_CTRL_ACK ack) {
  }
}

SampleRate a2dp_codec_to_hal_sample_rate(
    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 a2dp_codec_to_hal_bits_per_sample(
    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 a2dp_codec_to_hal_channel_mode(
    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 a2dp_get_selected_hal_codec_config(CodecConfiguration* codec_config) {
  A2dpCodecConfig* a2dp_codec_configs = bta_av_get_a2dp_current_codec();
  if (a2dp_codec_configs == nullptr) {
  A2dpCodecConfig* a2dp_config = bta_av_get_a2dp_current_codec();
  if (a2dp_config == nullptr) {
    LOG(WARNING) << __func__ << ": failure to get A2DP codec config";
    *codec_config = kInvalidCodecConfiguration;
    *codec_config = ::bluetooth::audio::codec::kInvalidCodecConfiguration;
    return false;
  }
  btav_a2dp_codec_config_t current_codec = a2dp_codec_configs->getCodecConfig();
  tBT_A2DP_OFFLOAD a2dp_offload;
  a2dp_codec_configs->getCodecSpecificConfig(&a2dp_offload);
  btav_a2dp_codec_config_t current_codec = a2dp_config->getCodecConfig();
  switch (current_codec.codec_type) {
    case BTAV_A2DP_CODEC_INDEX_SOURCE_SBC:
      [[fallthrough]];
    case BTAV_A2DP_CODEC_INDEX_SINK_SBC: {
      codec_config->codecType = CodecType::SBC;
      codec_config->config.sbcConfig({});
      auto sbc_config = codec_config->config.sbcConfig();
      sbc_config.sampleRate = a2dp_codec_to_hal_sample_rate(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;
      if (!A2dpSbcToHalConfig(codec_config, a2dp_config)) {
        return false;
      }
      sbc_config.minBitpool = a2dp_offload.codec_info[1];
      sbc_config.maxBitpool = a2dp_offload.codec_info[2];
      sbc_config.bitsPerSample =
          a2dp_codec_to_hal_bits_per_sample(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);
      break;
    }
    case BTAV_A2DP_CODEC_INDEX_SOURCE_AAC:
      [[fallthrough]];
    case BTAV_A2DP_CODEC_INDEX_SINK_AAC: {
      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 = a2dp_codec_to_hal_sample_rate(current_codec);
      if (aac_config.sampleRate == SampleRate::RATE_UNKNOWN) {
        LOG(ERROR) << __func__
                   << ": Unknown AAC sample_rate=" << current_codec.sample_rate;
      if (!A2dpAacToHalConfig(codec_config, a2dp_config)) {
        return false;
      }
      aac_config.channelMode = a2dp_codec_to_hal_channel_mode(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 =
          a2dp_codec_to_hal_bits_per_sample(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);
      break;
    }
    case BTAV_A2DP_CODEC_INDEX_SOURCE_APTX:
      [[fallthrough]];
    case BTAV_A2DP_CODEC_INDEX_SOURCE_APTX_HD: {
      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 = a2dp_codec_to_hal_sample_rate(current_codec);
      if (aptx_config.sampleRate == SampleRate::RATE_UNKNOWN) {
        LOG(ERROR) << __func__ << ": Unknown aptX sample_rate="
                   << current_codec.sample_rate;
      if (!A2dpAptxToHalConfig(codec_config, a2dp_config)) {
        return false;
      }
      aptx_config.channelMode = a2dp_codec_to_hal_channel_mode(current_codec);
      if (aptx_config.channelMode == ChannelMode::UNKNOWN) {
        LOG(ERROR) << __func__ << ": Unknown aptX channel_mode="
                   << current_codec.channel_mode;
        return false;
      }
      aptx_config.bitsPerSample =
          a2dp_codec_to_hal_bits_per_sample(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);
      break;
    }
    case BTAV_A2DP_CODEC_INDEX_SOURCE_LDAC: {
      codec_config->codecType = CodecType::LDAC;
      codec_config->config.ldacConfig({});
      auto ldac_config = codec_config->config.ldacConfig();
      ldac_config.sampleRate = a2dp_codec_to_hal_sample_rate(current_codec);
      if (ldac_config.sampleRate == SampleRate::RATE_UNKNOWN) {
        LOG(ERROR) << __func__ << ": Unknown LDAC sample_rate="
                   << current_codec.sample_rate;
      if (!A2dpLdacToHalConfig(codec_config, a2dp_config)) {
        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 =
          a2dp_codec_to_hal_bits_per_sample(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);
      break;
    }
    case BTAV_A2DP_CODEC_INDEX_MAX:
@@ -528,16 +260,15 @@ bool a2dp_get_selected_hal_codec_config(CodecConfiguration* codec_config) {
    default:
      LOG(ERROR) << __func__
                 << ": Unknown codec_type=" << current_codec.codec_type;
      codec_config->codecType = CodecType::UNKNOWN;
      codec_config->config = {};
      *codec_config = ::bluetooth::audio::codec::kInvalidCodecConfiguration;
      return false;
  }
  codec_config->encodedAudioBitrate = a2dp_codec_configs->getTrackBitRate();
  codec_config->encodedAudioBitrate = a2dp_config->getTrackBitRate();
  // Obtain the MTU
  RawAddress peer_addr = btif_av_source_active_peer();
  tA2DP_ENCODER_INIT_PEER_PARAMS peer_param;
  bta_av_co_get_peer_params(peer_addr, &peer_param);
  int effectiveMtu = a2dp_codec_configs->getEffectiveMtu();
  int effectiveMtu = a2dp_config->getEffectiveMtu();
  if (effectiveMtu > 0 && effectiveMtu < peer_param.peer_mtu) {
    codec_config->peerMtu = effectiveMtu;
  } else {
@@ -558,9 +289,9 @@ bool a2dp_get_selected_hal_pcm_config(PcmParameters* pcm_config) {
  }

  btav_a2dp_codec_config_t current_codec = a2dp_codec_configs->getCodecConfig();
  pcm_config->sampleRate = a2dp_codec_to_hal_sample_rate(current_codec);
  pcm_config->bitsPerSample = a2dp_codec_to_hal_bits_per_sample(current_codec);
  pcm_config->channelMode = a2dp_codec_to_hal_channel_mode(current_codec);
  pcm_config->sampleRate = A2dpCodecToHalSampleRate(current_codec);
  pcm_config->bitsPerSample = A2dpCodecToHalBitsPerSample(current_codec);
  pcm_config->channelMode = A2dpCodecToHalChannelMode(current_codec);
  return (pcm_config->sampleRate != SampleRate::RATE_UNKNOWN &&
          pcm_config->bitsPerSample != BitsPerSample::BITS_UNKNOWN &&
          pcm_config->channelMode != ChannelMode::UNKNOWN);
@@ -574,13 +305,18 @@ bool is_hal_2_0_force_disabled() {
  }
  return btaudio_a2dp_disabled;
}

}  // namespace

namespace bluetooth {
namespace audio {
namespace a2dp {

bool update_codec_offloading_capabilities(
    const std::vector<btav_a2dp_codec_config_t>& framework_preference) {
  return ::bluetooth::audio::codec::UpdateOffloadingCapabilities(
      framework_preference);
}

// Checking if new bluetooth_audio is enabled
bool is_hal_2_0_enabled() { return a2dp_hal_clientif != nullptr; }

+5 −0
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

#pragma once

#include <vector>

#include "audio_a2dp_hw/include/audio_a2dp_hw.h"
#include "common/message_loop_thread.h"

@@ -23,6 +25,9 @@ namespace bluetooth {
namespace audio {
namespace a2dp {

bool update_codec_offloading_capabilities(
    const std::vector<btav_a2dp_codec_config_t>& framework_preference);

// Check if new bluetooth_audio is enabled
bool is_hal_2_0_enabled();

+61 −23
Original line number Diff line number Diff line
@@ -207,19 +207,8 @@ BluetoothAudioClientInterface::BluetoothAudioClientInterface(IBluetoothTransport
                                                             bluetooth::common::MessageLoopThread* message_loop)
    : sink_(sink), provider_(nullptr), session_started_(false), mDataMQ(nullptr),
      death_recipient_(new BluetoothAudioDeathRecipient(this, message_loop)) {
  auto service_manager = android::hardware::defaultServiceManager1_2();
  CHECK(service_manager != nullptr);
  size_t instance_count = 0;
  auto listManifestByInterface_cb = [&instance_count](const hidl_vec<android::hardware::hidl_string>& instanceNames) {
    instance_count = instanceNames.size();
    LOG(INFO) << "listManifestByInterface_cb returns " << instance_count << " instance(s)";
  };
  auto hidl_retval = service_manager->listManifestByInterface(kFullyQualifiedInterfaceName, listManifestByInterface_cb);
  if (!hidl_retval.isOk()) {
    LOG(FATAL) << __func__ << ": IServiceManager::listByInterface failure: " << hidl_retval.description();
  }
  if (instance_count > 0) {
    fetch_audio_provider();
  if (IsSupported()) {
    FetchAudioProvider();
  } else {
    LOG(WARNING) << "IBluetoothAudioProvidersFactory not declared";
  }
@@ -239,7 +228,57 @@ BluetoothAudioClientInterface::GetAudioCapabilities() const {
  return capabilities_;
}

void BluetoothAudioClientInterface::fetch_audio_provider() {
bool BluetoothAudioClientInterface::IsSupported() {
  auto service_manager = android::hardware::defaultServiceManager1_2();
  CHECK(service_manager != nullptr);
  size_t instance_count = 0;
  auto listManifestByInterface_cb =
      [&instance_count](
          const hidl_vec<android::hardware::hidl_string>& instanceNames) {
        instance_count = instanceNames.size();
        LOG(INFO) << "listManifestByInterface_cb returns " << instance_count
                  << " instance(s)";
      };
  auto hidl_retval = service_manager->listManifestByInterface(
      kFullyQualifiedInterfaceName, listManifestByInterface_cb);
  if (!hidl_retval.isOk()) {
    LOG(FATAL) << __func__ << ": IServiceManager::listByInterface failure: "
               << hidl_retval.description();
    return false;
  }
  return (instance_count > 0);
}

std::vector<AudioCapabilities>
BluetoothAudioClientInterface::GetAudioCapabilities(SessionType session_type) {
  std::vector<AudioCapabilities> capabilities(0);
  if (!IsSupported()) return capabilities;

  android::sp<IBluetoothAudioProvidersFactory> providersFactory =
      IBluetoothAudioProvidersFactory::getService();
  CHECK(providersFactory != nullptr)
      << "IBluetoothAudioProvidersFactory::getService() failed";
  LOG(INFO) << "IBluetoothAudioProvidersFactory::getService() returned "
            << providersFactory.get()
            << (providersFactory->isRemote() ? " (remote)" : " (local)");

  auto getProviderCapabilities_cb =
      [&capabilities](const hidl_vec<AudioCapabilities>& audioCapabilities) {
        for (auto capability : audioCapabilities) {
          capabilities.push_back(capability);
        }
      };
  auto hidl_retval = providersFactory->getProviderCapabilities(
      session_type, getProviderCapabilities_cb);
  if (!hidl_retval.isOk()) {
    LOG(FATAL) << __func__
               << ": BluetoothAudioHal::getProviderCapabilities failure: "
               << hidl_retval.description();
  }
  return capabilities;
}

void BluetoothAudioClientInterface::FetchAudioProvider() {
  if (provider_ != nullptr) {
    LOG(WARNING) << __func__ << ": reflash";
  }
@@ -251,20 +290,16 @@ void BluetoothAudioClientInterface::fetch_audio_provider() {
            << providersFactory.get()
            << (providersFactory->isRemote() ? " (remote)" : " (local)");

  std::promise<void> getProviderCapabilities_promise;
  auto getProviderCapabilities_future =
      getProviderCapabilities_promise.get_future();
  auto getProviderCapabilities_cb =
      [& capabilities = this->capabilities_, &getProviderCapabilities_promise](
      [& capabilities = this->capabilities_](
          const hidl_vec<AudioCapabilities>& audioCapabilities) {
        capabilities.clear();
        for (auto capability : audioCapabilities) {
          capabilities.push_back(capability);
        }
        getProviderCapabilities_promise.set_value();
      };
  auto hidl_retval = providersFactory->getProviderCapabilities(
      sink_->GetSessionType(), getProviderCapabilities_cb);
  getProviderCapabilities_future.get();
  if (!hidl_retval.isOk()) {
    LOG(FATAL) << __func__ << ": BluetoothAudioHal::getProviderCapabilities failure: " << hidl_retval.description();
    return;
@@ -508,10 +543,13 @@ size_t BluetoothAudioClientInterface::WriteAudioData(uint8_t* p_buf,
void BluetoothAudioClientInterface::RenewAudioProviderAndSession() {
  // NOTE: must be invoked on the same thread where this
  // BluetoothAudioClientInterface is running
  fetch_audio_provider();
  FetchAudioProvider();
  if (session_started_) {
    LOG(INFO) << __func__ << ": Restart the session while audio HAL recovering";
    session_started_ = false;
    StartSession();
  }
}

}  // namespace audio
}  // namespace bluetooth
+6 −3
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@

#include <time.h>
#include <mutex>
#include <vector>

#include <android/hardware/bluetooth/audio/2.0/IBluetoothAudioProvider.h>
#include <android/hardware/bluetooth/audio/2.0/types.h>
@@ -35,8 +36,6 @@ using ::android::hardware::bluetooth::audio::V2_0::AudioCapabilities;
using ::android::hardware::bluetooth::audio::V2_0::AudioConfiguration;
using ::android::hardware::bluetooth::audio::V2_0::BitsPerSample;
using ::android::hardware::bluetooth::audio::V2_0::ChannelMode;
using ::android::hardware::bluetooth::audio::V2_0::CodecConfiguration;
using ::android::hardware::bluetooth::audio::V2_0::CodecType;
using ::android::hardware::bluetooth::audio::V2_0::IBluetoothAudioProvider;
using ::android::hardware::bluetooth::audio::V2_0::PcmParameters;
using ::android::hardware::bluetooth::audio::V2_0::SampleRate;
@@ -136,6 +135,8 @@ class BluetoothAudioClientInterface {
  }

  std::vector<AudioCapabilities> GetAudioCapabilities() const;
  static std::vector<AudioCapabilities> GetAudioCapabilities(
      SessionType session_type);

  bool UpdateAudioConfig(const AudioConfiguration& audioConfig);

@@ -163,8 +164,10 @@ class BluetoothAudioClientInterface {
  };

 private:
  static bool IsSupported();

  // Helper function to connect to an IBluetoothAudioProvider
  void fetch_audio_provider();
  void FetchAudioProvider();

  mutable std::mutex internal_mutex_;
  IBluetoothTransportInstance* sink_;
Loading