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

Commit f82b192a authored by Henri Chataing's avatar Henri Chataing
Browse files

Implement A2dpCodecConfigExt to extend A2dpCodecs with unknown offloaded codecs

Bug: 308958546
Bug: 308686081
Test: m com.android.btservices
Change-Id: I29abee42c03ba76c09f21b728f672bc6b7402211
parent f7ecb84a
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -206,6 +206,7 @@ cc_library_static {
        "bluetooth_flags_c_lib",
        "lib-bt-packets",
        "libbase",
        "libbt-audio-hal-interface",
        "libbt-platform-protos-lite",
        "libbt_shim_bridge",
        "libcom.android.sysprop.bluetooth.wrapped",
+10 −1
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@
#include <mutex>
#include <vector>

#include "audio_hal_interface/a2dp_encoding.h"
#include "bta/include/bta_av_api.h"
#include "bta/include/bta_av_ci.h"
#include "btif/include/btif_a2dp_source.h"
@@ -937,8 +938,16 @@ tA2DP_STATUS BtaAvCo::ProcessSourceGetConfig(

  p_peer->num_rx_sinks++;

  // Bypass the validation for codecs that are offloaded:
  // the stack does not need to know about the peer capabilities,
  // since the validation and selection will be performed by the
  // bluetooth audio HAL for offloaded codecs.
  auto codec_index = A2DP_SourceCodecIndex(p_codec_info);
  bool is_offloaded_codec =
      ::bluetooth::audio::a2dp::provider::supports_codec(codec_index);

  // Check the peer's Sink codec
  if (A2DP_IsPeerSinkCodecValid(p_codec_info)) {
  if (is_offloaded_codec || A2DP_IsPeerSinkCodecValid(p_codec_info)) {
    // If there is room for a new one
    if (p_peer->num_sup_sinks < BTA_AV_CO_NUM_ELEMENTS(p_peer->sinks)) {
      BtaAvCoSep* p_sink = &p_peer->sinks[p_peer->num_sup_sinks++];
+3 −0
Original line number Diff line number Diff line
@@ -84,6 +84,7 @@ cc_library_static {
        "a2dp/a2dp_aac_encoder.cc",
        "a2dp/a2dp_api.cc",
        "a2dp/a2dp_codec_config.cc",
        "a2dp/a2dp_ext.cc",
        "a2dp/a2dp_sbc.cc",
        "a2dp/a2dp_sbc_decoder.cc",
        "a2dp/a2dp_sbc_encoder.cc",
@@ -1146,12 +1147,14 @@ cc_test {
    ],
    srcs: [
        ":TestCommonMockFunctions",
        ":TestMockAudioHalInterface",
        ":TestMockBta",
        ":TestMockStackA2dpApi",
        "a2dp/a2dp_aac.cc",
        "a2dp/a2dp_aac_decoder.cc",
        "a2dp/a2dp_aac_encoder.cc",
        "a2dp/a2dp_codec_config.cc",
        "a2dp/a2dp_ext.cc",
        "a2dp/a2dp_sbc.cc",
        "a2dp/a2dp_sbc_decoder.cc",
        "a2dp/a2dp_sbc_encoder.cc",
+1 −0
Original line number Diff line number Diff line
@@ -55,6 +55,7 @@ source_set("stack") {
  sources = [
    "a2dp/a2dp_api.cc",
    "a2dp/a2dp_codec_config.cc",
    "a2dp/a2dp_ext.cc",
    "a2dp/a2dp_sbc.cc",
    "a2dp/a2dp_sbc_decoder.cc",
    "a2dp/a2dp_sbc_encoder.cc",
+56 −25
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@

#include "a2dp_aac.h"
#include "a2dp_codec_api.h"
#include "a2dp_ext.h"
#include "a2dp_sbc.h"
#include "a2dp_vendor.h"

@@ -34,9 +35,7 @@
#include "a2dp_vendor_opus.h"
#endif

#if !defined(UNIT_TESTS)
#include "audio_hal_interface/a2dp_encoding.h"
#endif
#include "bta/av/bta_av_int.h"
#include "device/include/device_iot_config.h"
#include "osi/include/log.h"
@@ -113,6 +112,13 @@ A2dpCodecConfig* A2dpCodecConfig::createCodec(
    btav_a2dp_codec_priority_t codec_priority) {
  LOG_INFO("%s", A2DP_CodecIndexStr(codec_index));

  // Hardware offload codec extensibility:
  // management of the codec is moved under the ProviderInfo
  // class of the aidl audio HAL client.
  if (::bluetooth::audio::a2dp::provider::supports_codec(codec_index)) {
    return new A2dpCodecConfigExt(codec_index, true);
  }

  A2dpCodecConfig* codec_config = nullptr;
  switch (codec_index) {
    case BTAV_A2DP_CODEC_INDEX_SOURCE_SBC:
@@ -951,10 +957,19 @@ bool A2dpCodecs::setPeerSinkCodecCapabilities(
    const uint8_t* p_peer_codec_capabilities) {
  std::lock_guard<std::recursive_mutex> lock(codec_mutex_);

  if (!A2DP_IsPeerSinkCodecValid(p_peer_codec_capabilities)) return false;
  A2dpCodecConfig* a2dp_codec_config =
      findSourceCodecConfig(p_peer_codec_capabilities);
  if (a2dp_codec_config == nullptr) return false;

  // Bypass the validation for codecs that are offloaded:
  // the stack does not need to know about the peer capabilities,
  // since the validation and selection will be performed by the
  // bluetooth audio HAL for offloaded codecs.
  if (!::bluetooth::audio::a2dp::provider::supports_codec(
          a2dp_codec_config->codecIndex()) &&
      !A2DP_IsPeerSinkCodecValid(p_peer_codec_capabilities))
    return false;

  return a2dp_codec_config->setPeerCodecCapabilities(p_peer_codec_capabilities);
}

@@ -1385,6 +1400,11 @@ const tA2DP_ENCODER_INTERFACE* A2DP_GetEncoderInterface(

  LOG_VERBOSE("%s: codec_type = 0x%x", __func__, codec_type);

  if (::bluetooth::audio::a2dp::provider::supports_codec(
          A2DP_SourceCodecIndex(p_codec_info))) {
    return A2DP_GetEncoderInterfaceExt(p_codec_info);
  }

  switch (codec_type) {
    case A2DP_MEDIA_CT_SBC:
      return A2DP_GetEncoderInterfaceSbc(p_codec_info);
@@ -1450,6 +1470,12 @@ btav_a2dp_codec_index_t A2DP_SourceCodecIndex(const uint8_t* p_codec_info) {

  LOG_VERBOSE("%s: codec_type = 0x%x", __func__, codec_type);

  auto ext_codec_index =
      bluetooth::audio::a2dp::provider::source_codec_index(p_codec_info);
  if (ext_codec_index.has_value()) {
    return ext_codec_index.value();
  }

  switch (codec_type) {
    case A2DP_MEDIA_CT_SBC:
      return A2DP_SourceCodecIndexSbc(p_codec_info);
@@ -1472,6 +1498,12 @@ btav_a2dp_codec_index_t A2DP_SinkCodecIndex(const uint8_t* p_codec_info) {

  LOG_VERBOSE("%s: codec_type = 0x%x", __func__, codec_type);

  auto ext_codec_index =
      bluetooth::audio::a2dp::provider::sink_codec_index(p_codec_info);
  if (ext_codec_index.has_value()) {
    return ext_codec_index.value();
  }

  switch (codec_type) {
    case A2DP_MEDIA_CT_SBC:
      return A2DP_SinkCodecIndexSbc(p_codec_info);
@@ -1490,6 +1522,17 @@ btav_a2dp_codec_index_t A2DP_SinkCodecIndex(const uint8_t* p_codec_info) {
}

const char* A2DP_CodecIndexStr(btav_a2dp_codec_index_t codec_index) {
  if ((codec_index >= BTAV_A2DP_CODEC_INDEX_SOURCE_EXT_MIN &&
       codec_index < BTAV_A2DP_CODEC_INDEX_SOURCE_EXT_MAX) ||
      (codec_index >= BTAV_A2DP_CODEC_INDEX_SINK_EXT_MIN &&
       codec_index < BTAV_A2DP_CODEC_INDEX_SINK_EXT_MAX)) {
    auto codec_index_str =
        bluetooth::audio::a2dp::provider::codec_index_str(codec_index);
    if (codec_index_str.has_value()) {
      return codec_index_str.value();
    }
  }

  switch (codec_index) {
    case BTAV_A2DP_CODEC_INDEX_SOURCE_SBC:
      return A2DP_CodecIndexStrSbc();
@@ -1521,6 +1564,11 @@ bool A2DP_InitCodecConfig(btav_a2dp_codec_index_t codec_index,
  p_cfg->num_protect = 0;
  p_cfg->protect_info[0] = 0;

  if (::bluetooth::audio::a2dp::provider::supports_codec(codec_index)) {
    return ::bluetooth::audio::a2dp::provider::codec_info(
        codec_index, p_cfg->codec_info, nullptr);
  }

  switch (codec_index) {
    case BTAV_A2DP_CODEC_INDEX_SOURCE_SBC:
      return A2DP_InitCodecConfigSbc(p_cfg);
@@ -1564,26 +1612,9 @@ std::string A2DP_CodecInfoString(const uint8_t* p_codec_info) {
}

int A2DP_GetEecoderEffectiveFrameSize(const uint8_t* p_codec_info) {
  tA2DP_CODEC_TYPE codec_type = A2DP_GetCodecType(p_codec_info);

  const tA2DP_ENCODER_INTERFACE* a2dp_encoder_interface = nullptr;
  switch (codec_type) {
    case A2DP_MEDIA_CT_SBC:
      a2dp_encoder_interface = A2DP_GetEncoderInterfaceSbc(p_codec_info);
      break;
#if !defined(EXCLUDE_NONSTANDARD_CODECS)
    case A2DP_MEDIA_CT_AAC:
      a2dp_encoder_interface = A2DP_GetEncoderInterfaceAac(p_codec_info);
      break;
    case A2DP_MEDIA_CT_NON_A2DP:
      a2dp_encoder_interface = A2DP_VendorGetEncoderInterface(p_codec_info);
      break;
#endif
    default:
      break;
  }
  if (a2dp_encoder_interface == nullptr) {
    return 0;
  }
  return a2dp_encoder_interface->get_effective_frame_size();
  const tA2DP_ENCODER_INTERFACE* a2dp_encoder_interface =
      A2DP_GetEncoderInterface(p_codec_info);
  return a2dp_encoder_interface
             ? a2dp_encoder_interface->get_effective_frame_size()
             : 0;
}
Loading