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

Commit bd81727d authored by Rahul Arya's avatar Rahul Arya
Browse files

[Invisalign] Add CodecInterface

Not sure if this should belong in the core, or as an injected interface.
We only inject this one codec since A2DP lives outside the core, but SCO
is (currently) inside.

Bug: 254063018
Test: all existing tests

Change-Id: I0470a82f639595e33e82257f4031fc629706c97d
parent 563b517a
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -485,6 +485,8 @@ cc_test {
          "libaudio-a2dp-hw-utils",
          "libbluetooth-types",
          "libbt-audio-hal-interface",
          "libbt-sbc-decoder",
          "libbt-sbc-encoder",
          "libbt-stack",
          "libbtdevice",
          "lib-bt-packets",
@@ -604,6 +606,8 @@ cc_test {
          "libaudio-a2dp-hw-utils",
          "libbluetooth-types",
          "libbt-audio-hal-interface",
          "libbt-sbc-decoder",
          "libbt-sbc-encoder",
          "libbt-stack",
          "libbtdevice",
          "lib-bt-packets",
+22 −2
Original line number Diff line number Diff line
@@ -82,12 +82,30 @@ struct ConfigInterface {
  virtual ~ConfigInterface() = default;
};

// This interface lets us communicate with encoders used in profiles
struct CodecInterface {
  virtual void initialize() = 0;
  virtual void cleanup() = 0;

  virtual uint32_t encodePacket(int16_t* input, uint8_t* output) = 0;
  virtual bool decodePacket(const uint8_t* i_buf, int16_t* o_buf,
                            size_t out_len) = 0;

  explicit CodecInterface() = default;
  CodecInterface(const CodecInterface&) = delete;
  CodecInterface& operator=(const CodecInterface&) = delete;
  virtual ~CodecInterface() = default;
};

// This class defines the overall interface expected by bluetooth::core.
struct CoreInterface {
  // generic interface
  EventCallbacks* events;
  ConfigInterface* config;

  // codecs
  CodecInterface* msbcCodec;

  virtual void onBluetoothEnabled() = 0;
  virtual bt_status_t toggleProfile(tBTA_SERVICE_ID service_id,
                                    bool enable) = 0;
@@ -95,8 +113,10 @@ struct CoreInterface {
  virtual void onLinkDown(const RawAddress& bd_addr) = 0;

  CoreInterface(EventCallbacks* eventCallbacks,
                ConfigInterface* configInterface)
      : events{eventCallbacks}, config{configInterface} {};
                ConfigInterface* configInterface, CodecInterface* msbcCodec)
      : events{eventCallbacks},
        config{configInterface},
        msbcCodec{msbcCodec} {};

  CoreInterface(const CoreInterface&) = delete;
  CoreInterface& operator=(const CoreInterface&) = delete;
+40 −15
Original line number Diff line number Diff line
@@ -97,6 +97,8 @@
#include "stack/include/avdt_api.h"
#include "stack/include/btm_api.h"
#include "stack/include/btu.h"
#include "stack/include/hfp_msbc_decoder.h"
#include "stack/include/hfp_msbc_encoder.h"
#include "stack/include/hidh_api.h"
#include "stack/include/pan_api.h"
#include "types/raw_address.h"
@@ -196,6 +198,29 @@ struct ConfigInterfaceImpl : bluetooth::core::ConfigInterface {
  bool isAndroidTVDevice() override { return is_atv_device(); }
};

// TODO(aryarahul): remove unnecessary indirection through hfp_msbc_*.cc
struct MSBCCodec : bluetooth::core::CodecInterface {
  MSBCCodec() : bluetooth::core::CodecInterface(){};

  void initialize() override {
    hfp_msbc_decoder_init();
    hfp_msbc_encoder_init();
  }

  void cleanup() override {
    hfp_msbc_decoder_cleanup();
    hfp_msbc_encoder_cleanup();
  }

  uint32_t encodePacket(int16_t* input, uint8_t* output) {
    return hfp_msbc_encode_frames(input, output);
  }

  bool decodePacket(const uint8_t* i_buf, int16_t* o_buf, size_t out_len) {
    return hfp_msbc_decoder_decode_packet(i_buf, o_buf, out_len);
  }
};

struct CoreInterfaceImpl : bluetooth::core::CoreInterface {
  using bluetooth::core::CoreInterface::CoreInterface;

@@ -295,8 +320,9 @@ static bluetooth::core::CoreInterface* CreateInterfaceToProfiles() {
      .invoke_energy_info_cb = invoke_energy_info_cb,
      .invoke_link_quality_report_cb = invoke_link_quality_report_cb};
  static auto configInterface = ConfigInterfaceImpl();
  static auto msbcCodecInterface = MSBCCodec();
  static auto interfaceForCore =
      CoreInterfaceImpl(&eventCallbacks, &configInterface);
      CoreInterfaceImpl(&eventCallbacks, &configInterface, &msbcCodecInterface);
  return &interfaceForCore;
}

@@ -1207,9 +1233,9 @@ void invoke_energy_info_cb(bt_activity_energy_info energy_info,
          energy_info, uid_data));
}

void invoke_link_quality_report_cb(
    uint64_t timestamp, int report_id, int rssi, int snr,
    int retransmission_count, int packets_not_receive_count,
void invoke_link_quality_report_cb(uint64_t timestamp, int report_id, int rssi,
                                   int snr, int retransmission_count,
                                   int packets_not_receive_count,
                                   int negative_acknowledgement_count) {
  do_in_jni_thread(
      FROM_HERE,
@@ -1217,8 +1243,8 @@ void invoke_link_quality_report_cb(
          [](uint64_t timestamp, int report_id, int rssi, int snr,
             int retransmission_count, int packets_not_receive_count,
             int negative_acknowledgement_count) {
            HAL_CBACK(bt_hal_cbacks, link_quality_report_cb,
                      timestamp, report_id, rssi, snr, retransmission_count,
            HAL_CBACK(bt_hal_cbacks, link_quality_report_cb, timestamp,
                      report_id, rssi, snr, retransmission_count,
                      packets_not_receive_count,
                      negative_acknowledgement_count);
          },
@@ -1227,11 +1253,10 @@ void invoke_link_quality_report_cb(
}

void invoke_switch_buffer_size_cb(bool is_low_latency_buffer_size) {
  do_in_jni_thread(
      FROM_HERE,
      base::BindOnce(
  do_in_jni_thread(FROM_HERE, base::BindOnce(
                                  [](bool is_low_latency_buffer_size) {
            HAL_CBACK(bt_hal_cbacks, switch_buffer_size_cb,
                                    HAL_CBACK(bt_hal_cbacks,
                                              switch_buffer_size_cb,
                                              is_low_latency_buffer_size);
                                  },
                                  is_low_latency_buffer_size));
+9 −9
Original line number Diff line number Diff line
@@ -21,8 +21,8 @@

#include <memory>

#include "hfp_msbc_decoder.h"
#include "hfp_msbc_encoder.h"
#include "btif/include/core_callbacks.h"
#include "btif/include/stack_manager.h"
#include "osi/include/allocator.h"
#include "osi/include/log.h"
#include "stack/btm/btm_sco.h"
@@ -300,8 +300,7 @@ struct tBTM_MSBC_INFO {
static tBTM_MSBC_INFO* msbc_info = nullptr;

size_t init(size_t pkt_size) {
  hfp_msbc_decoder_init();
  hfp_msbc_encoder_init();
  GetInterfaceToProfiles()->msbcCodec->initialize();

  if (msbc_info) {
    LOG_WARN("Re-initiating mSBC buffer that is active or not cleaned");
@@ -314,8 +313,7 @@ size_t init(size_t pkt_size) {
}

void cleanup() {
  hfp_msbc_decoder_cleanup();
  hfp_msbc_encoder_cleanup();
  GetInterfaceToProfiles()->msbcCodec->cleanup();

  if (msbc_info == nullptr) return;

@@ -388,7 +386,8 @@ size_t decode(const uint8_t** out_data) {
    goto packet_loss;
  }

  if (!hfp_msbc_decoder_decode_packet(frame_head, msbc_info->decoded_pcm_buf,
  if (!GetInterfaceToProfiles()->msbcCodec->decodePacket(
          frame_head, msbc_info->decoded_pcm_buf,
          sizeof(msbc_info->decoded_pcm_buf))) {
    LOG_DEBUG("Decoding mSBC packet failed");
    goto packet_loss;
@@ -431,7 +430,8 @@ size_t encode(int16_t* data, size_t len) {
    return 0;
  }

  encoded_size = hfp_msbc_encode_frames(data, pkt_body);
  encoded_size =
      GetInterfaceToProfiles()->msbcCodec->encodePacket(data, pkt_body);
  if (encoded_size != BTM_MSBC_PKT_FRAME_LEN) {
    LOG_WARN("Encoding invalid packet size: %lu", (unsigned long)encoded_size);
    std::copy(std::begin(btm_msbc_zero_packet), std::end(btm_msbc_zero_packet),
+42 −7
Original line number Diff line number Diff line
@@ -23,9 +23,14 @@
#include <map>
#include <memory>

#include "btif/include/core_callbacks.h"
#include "btif/include/stack_manager.h"
#include "stack/btm/btm_sco.h"
#include "stack/include/hfp_msbc_decoder.h"
#include "stack/include/hfp_msbc_encoder.h"
#include "udrv/include/uipc.h"

extern bluetooth::core::CoreInterface* GetInterfaceToProfiles();
extern std::map<std::string, int> mock_function_count_map;
extern std::unique_ptr<tUIPC_STATE> mock_uipc_init_ret;
extern uint32_t mock_uipc_read_ret;
@@ -42,6 +47,28 @@ const uint8_t msbc_zero_packet[] = {
    0x77, 0x6d, 0xb6, 0xdd, 0xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6d, 0xdd, 0xb6,
    0xdb, 0x77, 0x6d, 0xb6, 0xdd, 0xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6c, 0x00};

struct CodecInterface : bluetooth::core::CodecInterface {
  CodecInterface() : bluetooth::core::CodecInterface(){};

  void initialize() override {
    hfp_msbc_decoder_init();
    hfp_msbc_encoder_init();
  }

  void cleanup() override {
    hfp_msbc_decoder_cleanup();
    hfp_msbc_encoder_cleanup();
  }

  uint32_t encodePacket(int16_t* input, uint8_t* output) {
    return hfp_msbc_encode_frames(input, output);
  }

  bool decodePacket(const uint8_t* i_buf, int16_t* o_buf, size_t out_len) {
    return hfp_msbc_decoder_decode_packet(i_buf, o_buf, out_len);
  }
};

class ScoHciTest : public Test {
 public:
 protected:
@@ -50,6 +77,9 @@ class ScoHciTest : public Test {
    mock_uipc_init_ret = nullptr;
    mock_uipc_read_ret = 0;
    mock_uipc_send_ret = true;

    static auto codec = CodecInterface{};
    GetInterfaceToProfiles()->msbcCodec = &codec;
  }
  void TearDown() override {}
};
@@ -65,10 +95,15 @@ class ScoHciWithOpenCleanTest : public ScoHciTest {
  void TearDown() override { bluetooth::audio::sco::cleanup(); }
};

class ScoHciWbsWithInitCleanTest : public Test {
class ScoHciWbsTest : public ScoHciTest {};

class ScoHciWbsWithInitCleanTest : public ScoHciTest {
 public:
 protected:
  void SetUp() override { bluetooth::audio::sco::wbs::init(60); }
  void SetUp() override {
    ScoHciTest::SetUp();
    bluetooth::audio::sco::wbs::init(60);
  }
  void TearDown() override { bluetooth::audio::sco::wbs::cleanup(); }
};

@@ -142,7 +177,7 @@ TEST_F(ScoHciWithOpenCleanTest, ScoOverHciWrite) {
  ASSERT_EQ(mock_function_count_map["UIPC_Send"], 2);
}

TEST(ScoHciWbsTest, WbsInit) {
TEST_F(ScoHciWbsTest, WbsInit) {
  ASSERT_EQ(bluetooth::audio::sco::wbs::init(60), size_t(60));
  ASSERT_EQ(bluetooth::audio::sco::wbs::init(72), size_t(72));
  // Fallback to 60 if the packet size is not supported
@@ -150,7 +185,7 @@ TEST(ScoHciWbsTest, WbsInit) {
  bluetooth::audio::sco::wbs::cleanup();
}

TEST(ScoHciWbsTest, WbsEnqueuePacketWithoutInit) {
TEST_F(ScoHciWbsTest, WbsEnqueuePacketWithoutInit) {
  uint8_t payload[60];
  // Return 0 if buffer is uninitialized
  ASSERT_EQ(
@@ -175,7 +210,7 @@ TEST_F(ScoHciWbsWithInitCleanTest, WbsEnqueuePacket) {
      size_t(0));
}

TEST(ScoHciWbsTest, WbsDecodeWithoutInit) {
TEST_F(ScoHciWbsTest, WbsDecodeWithoutInit) {
  const uint8_t* decoded = nullptr;
  // Return 0 if buffer is uninitialized
  ASSERT_EQ(bluetooth::audio::sco::wbs::decode(&decoded), size_t(0));
@@ -219,7 +254,7 @@ TEST_F(ScoHciWbsWithInitCleanTest, WbsDecode) {
  ASSERT_EQ(decoded, nullptr);
}

TEST(ScoHciWbsTest, WbsEncodeWithoutInit) {
TEST_F(ScoHciWbsTest, WbsEncodeWithoutInit) {
  int16_t data[120] = {0};
  // Return 0 if buffer is uninitialized
  ASSERT_EQ(bluetooth::audio::sco::wbs::encode(data, sizeof(data)), size_t(0));
@@ -241,7 +276,7 @@ TEST_F(ScoHciWbsWithInitCleanTest, WbsEncode) {
  ASSERT_EQ(bluetooth::audio::sco::wbs::encode(data, sizeof(data)), size_t(0));
}

TEST(ScoHciWbsTest, WbsDequeuePacketWithoutInit) {
TEST_F(ScoHciWbsTest, WbsDequeuePacketWithoutInit) {
  const uint8_t* encoded = nullptr;
  // Return 0 if buffer is uninitialized
  ASSERT_EQ(bluetooth::audio::sco::wbs::dequeue_packet(&encoded), size_t(0));
Loading