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

Commit ef856c32 authored by Jakub Tyszkowski's avatar Jakub Tyszkowski Committed by Automerger Merge Worker
Browse files

Merge "LeAudio: Improve handling codec frame blocks other than 1" into main am: 186971da

parents d415f438 186971da
Loading
Loading
Loading
Loading
+21 −2
Original line number Diff line number Diff line
@@ -1160,12 +1160,19 @@ class LeAudioClientImpl : public LeAudioClient {

    L2CA_SetEcosystemBaseInterval(frame_duration_us / 1250);

    audio_framework_source_config.data_interval_us = frame_duration_us;
    // Scale by the codec frame blocks per SDU if set
    uint8_t codec_frame_blocks_per_sdu =
        group->stream_conf.stream_params.source.codec_frames_blocks_per_sdu
            ?: 1;
    audio_framework_source_config.data_interval_us =
        frame_duration_us * codec_frame_blocks_per_sdu;

    le_audio_source_hal_client_->Start(audio_framework_source_config,
                                       audioSinkReceiver, dsa_modes);

    /* We use same frame duration for sink/source */
    audio_framework_sink_config.data_interval_us = frame_duration_us;
    audio_framework_sink_config.data_interval_us =
        frame_duration_us * codec_frame_blocks_per_sdu;

    /* If group supports more than 16kHz for the microphone in converstional
     * case let's use that also for Audio Framework.
@@ -3393,6 +3400,12 @@ class LeAudioClientImpl : public LeAudioClient {
        right_cis_handle = cis_handle;
    }

    if (stream_params.codec_frames_blocks_per_sdu != 1) {
      log::error(
          "Codec Frame Blocks of {} is not supported by the software encoding",
          +stream_params.codec_frames_blocks_per_sdu);
    }

    uint16_t byte_count = stream_params.octets_per_codec_frame;
    bool mix_to_mono = (left_cis_handle == 0) || (right_cis_handle == 0);
    if (mix_to_mono) {
@@ -3441,6 +3454,12 @@ class LeAudioClientImpl : public LeAudioClient {
      return;
    }

    if (stream_params.codec_frames_blocks_per_sdu != 1) {
      log::error(
          "Codec Frame Blocks of {} is not supported by the software encoding",
          +stream_params.codec_frames_blocks_per_sdu);
    }

    uint16_t byte_count = stream_params.octets_per_codec_frame;
    bool mix_to_mono = (num_channels == 1);
    if (mix_to_mono) {
+89 −21
Original line number Diff line number Diff line
@@ -718,12 +718,15 @@ class LeAudioAseConfigurationTest
      // configurations
      ON_CALL(*mock_codec_manager_, IsDualBiDirSwbSupported)
          .WillByDefault(Return(true));
    }

    ON_CALL(*mock_codec_manager_, GetCodecConfig)
        .WillByDefault(Invoke(
              [](const bluetooth::le_audio::CodecManager::
            [&](const bluetooth::le_audio::CodecManager::
                    UnicastConfigurationRequirements& requirements,
                bluetooth::le_audio::CodecManager::UnicastConfigurationVerifier
                    verifier) {
              if (codec_coding_format_ == kLeAudioCodingFormatLC3) {
                auto filtered =
                    *bluetooth::le_audio::AudioSetConfigurationProvider::Get()
                         ->GetConfigurations(requirements.audio_context_type);
@@ -745,18 +748,10 @@ class LeAudioAseConfigurationTest
                  return std::unique_ptr<AudioSetConfiguration>(nullptr);
                }
                return std::make_unique<AudioSetConfiguration>(*cfg);
              }));
              } else {
      // Provide a configuration for the vendor codec
      ON_CALL(*mock_codec_manager_, GetCodecConfig)
          .WillByDefault(Invoke(
              [](const bluetooth::le_audio::CodecManager::
                     UnicastConfigurationRequirements& requirements,
                 bluetooth::le_audio::CodecManager::UnicastConfigurationVerifier
                     verifier) {
                return MockVendorCodecProvider(requirements);
              }));
              }
            }));

    ON_CALL(*mock_codec_manager_, CheckCodecConfigIsBiDirSwb)
        .WillByDefault(Invoke([](const bluetooth::le_audio::set_configurations::
@@ -1125,7 +1120,8 @@ class LeAudioAseConfigurationTest
  }

  void TestAsesActive(LeAudioCodecId codec_id, uint8_t sampling_frequency,
                      uint8_t frame_duration, uint16_t octets_per_frame) {
                      uint8_t frame_duration, uint16_t octets_per_frame,
                      uint8_t codec_frame_blocks_per_sdu = 1) {
    bool active_ase = false;

    for (const auto& device : devices_) {
@@ -1144,6 +1140,8 @@ class LeAudioAseConfigurationTest
          ASSERT_EQ(core_config.sampling_frequency, sampling_frequency);
          ASSERT_EQ(core_config.frame_duration, frame_duration);
          ASSERT_EQ(core_config.octets_per_codec_frame, octets_per_frame);
          ASSERT_EQ(core_config.codec_frames_blocks_per_sdu.value_or(0),
                    codec_frame_blocks_per_sdu);
        }
      }
    }
@@ -1177,7 +1175,8 @@ class LeAudioAseConfigurationTest
    }
  }

  void TestLc3CodecConfig(LeAudioContextType context_type) {
  void TestLc3CodecConfig(LeAudioContextType context_type,
                          uint8_t max_codec_frames_per_sdu = 1) {
    for (int i = Lc3SettingIdBegin; i < Lc3SettingIdEnd; i++) {
      // test each configuration parameter against valid and invalid value
      std::array<Lc3SettingId, 2> test_variants = {static_cast<Lc3SettingId>(i),
@@ -1198,7 +1197,7 @@ class LeAudioAseConfigurationTest
                            frame_duration,
                            kLeAudioCodecChannelCountSingleChannel |
                                kLeAudioCodecChannelCountTwoChannel,
                            octets_per_frame);
                            octets_per_frame, max_codec_frames_per_sdu);
            for (auto& device : devices_) {
              /* For simplicity configure both PACs with the same
              parameters*/
@@ -1224,7 +1223,8 @@ class LeAudioAseConfigurationTest
                      group_->Configure(context_type, group_audio_locations));
            if (success_expected) {
              TestAsesActive(LeAudioCodecIdLc3, sampling_frequency,
                             frame_duration, octets_per_frame);
                             frame_duration, octets_per_frame,
                             max_codec_frames_per_sdu);
              group_->Deactivate();
            }

@@ -2072,6 +2072,74 @@ TEST_P(LeAudioAseConfigurationTest, test_lc3_config_media) {
  TestLc3CodecConfig(LeAudioContextType::MEDIA);
}

TEST_P(LeAudioAseConfigurationTest,
       test_lc3_config_media_codec_extensibility_fb2) {
  if (codec_coding_format_ != kLeAudioCodingFormatLC3) GTEST_SKIP();

  bool is_fb2_passed_as_requirement = false;
  auto max_codec_frames_per_sdu = 2;

  // Mock the configuration provider to give us config with 2 frame blocks per
  // SDU if it receives the proper PAC entry in the requirements
  // ON_CALL(*mock_codec_manager_, IsUsingCodecExtensibility)
  //       .WillByDefault(Return(true));
  ON_CALL(*mock_codec_manager_, GetCodecConfig)
      .WillByDefault(Invoke([&](const bluetooth::le_audio::CodecManager::
                                    UnicastConfigurationRequirements&
                                        requirements,
                                bluetooth::le_audio::CodecManager::
                                    UnicastConfigurationVerifier verifier) {
        auto filtered =
            *bluetooth::le_audio::AudioSetConfigurationProvider::Get()
                 ->GetConfigurations(requirements.audio_context_type);
        // Filter out the dual bidir SWB configurations
        if (!bluetooth::le_audio::CodecManager::GetInstance()
                 ->IsDualBiDirSwbSupported()) {
          filtered.erase(
              std::remove_if(filtered.begin(), filtered.end(),
                             [](auto const& el) {
                               if (el->confs.source.empty()) return false;
                               return AudioSetConfigurationProvider::Get()
                                   ->CheckConfigurationIsDualBiDirSwb(*el);
                             }),
              filtered.end());
        }
        auto cfg = verifier(requirements, &filtered);
        if (cfg == nullptr) {
          return std::unique_ptr<AudioSetConfiguration>(nullptr);
        }

        auto config = *cfg;

        if (requirements.sink_pacs.has_value()) {
          for (auto const& rec : requirements.sink_pacs.value()) {
            auto caps = rec.codec_spec_caps.GetAsCoreCodecCapabilities();
            if (caps.HasSupportedMaxCodecFramesPerSdu()) {
              if (caps.supported_max_codec_frames_per_sdu.value() ==
                  max_codec_frames_per_sdu) {
                // Inject the proper Codec Frames Per SDU as the json
                // configs are conservative and will always give us 1
                for (auto& entry : config.confs.sink) {
                  entry.codec.params.Add(
                      codec_spec_conf::kLeAudioLtvTypeCodecFrameBlocksPerSdu,
                      (uint8_t)max_codec_frames_per_sdu);
                }
                is_fb2_passed_as_requirement = true;
              }
            }
          }
        }
        return std::make_unique<AudioSetConfiguration>(config);
      }));

  AddTestDevice(1, 1);

  TestLc3CodecConfig(LeAudioContextType::MEDIA, max_codec_frames_per_sdu);

  // Make sure the CodecManager mock gets the proper PAC record
  ASSERT_TRUE(is_fb2_passed_as_requirement);
}

TEST_P(LeAudioAseConfigurationTest, test_unsupported_codec) {
  if (codec_coding_format_ == kLeAudioCodingFormatVendorSpecific) GTEST_SKIP();

+252 −5
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@
#include "bta_groups.h"
#include "bta_le_audio_api.h"
#include "bta_le_audio_broadcaster_api.h"
#include "btif/include/mock_core_callbacks.h"
#include "btif_storage_mock.h"
#include "btm_api_mock.h"
#include "btm_iso_api.h"
@@ -41,6 +42,7 @@
#include "hci/controller_interface_mock.h"
#include "internal_include/stack_config.h"
#include "le_audio/codec_manager.h"
#include "le_audio/mock_codec_interface.h"
#include "le_audio_health_status.h"
#include "le_audio_set_configuration_provider.h"
#include "le_audio_types.h"
@@ -1156,6 +1158,8 @@ class UnicastTestNoInit : public Test {
                    stream_conf->stream_params.source
                        .codec_frames_blocks_per_sdu =
                        *core_config.codec_frames_blocks_per_sdu;
                    stream_conf->stream_params.source.frame_duration_us =
                        core_config.GetFrameDurationUs();
                  } else {
                    log::assert_that(
                        stream_conf->stream_params.source
@@ -1228,6 +1232,8 @@ class UnicastTestNoInit : public Test {
                    stream_conf->stream_params.sink
                        .codec_frames_blocks_per_sdu =
                        *core_config.codec_frames_blocks_per_sdu;
                    stream_conf->stream_params.sink.frame_duration_us =
                        core_config.GetFrameDurationUs();
                  } else {
                    log::assert_that(
                        stream_conf->stream_params.sink
@@ -2347,6 +2353,25 @@ class UnicastTestNoInit : public Test {
                        std::move(ascs), std::move(pacs));
  }

  struct SampleDatabaseParameters {
    uint16_t conn_id;
    RawAddress addr;

    uint32_t sink_audio_allocation = codec_spec_conf::kLeAudioLocationStereo;
    uint32_t source_audio_allocation = codec_spec_conf::kLeAudioLocationStereo;
    uint8_t sink_channel_cnt = 0x03;
    uint8_t source_channel_cnt = 0x03;
    uint16_t sample_freq_mask = 0x0004;
    bool add_csis = true;
    bool add_cas = true;
    bool add_pacs = true;
    int add_ascs_cnt = 1;
    uint8_t set_size = 2;
    uint8_t rank = 1;
    GattStatus gatt_status = GATT_SUCCESS;
    uint8_t max_supported_codec_frames_per_sdu = 1;
  };

  void SetSampleDatabaseEarbudsValid(
      uint16_t conn_id, RawAddress addr, uint32_t sink_audio_allocation,
      uint32_t source_audio_allocation, uint8_t sink_channel_cnt = 0x03,
@@ -2354,6 +2379,43 @@ class UnicastTestNoInit : public Test {
      bool add_csis = true, bool add_cas = true, bool add_pacs = true,
      int add_ascs_cnt = 1, uint8_t set_size = 2, uint8_t rank = 1,
      GattStatus gatt_status = GATT_SUCCESS) {
    SetSampleDatabaseEarbudsValid(SampleDatabaseParameters{
        .conn_id = conn_id,
        .addr = addr,
        .sink_audio_allocation = sink_audio_allocation,
        .source_audio_allocation = source_audio_allocation,
        .sink_channel_cnt = sink_channel_cnt,
        .source_channel_cnt = source_channel_cnt,
        .sample_freq_mask = sample_freq_mask,
        .add_csis = add_csis,
        .add_cas = add_cas,
        .add_pacs = add_pacs,
        .add_ascs_cnt = add_ascs_cnt,
        .set_size = set_size,
        .rank = rank,
        .gatt_status = gatt_status,
        .max_supported_codec_frames_per_sdu = 1,
    });
  }

  void SetSampleDatabaseEarbudsValid(const SampleDatabaseParameters& params) {
    auto conn_id = params.conn_id;
    auto addr = params.addr;
    auto sink_audio_allocation = params.sink_audio_allocation;
    auto source_audio_allocation = params.source_audio_allocation;
    auto sink_channel_cnt = params.sink_channel_cnt;
    auto source_channel_cnt = params.source_channel_cnt;
    auto sample_freq_mask = params.sample_freq_mask;
    auto add_csis = params.add_csis;
    auto add_cas = params.add_cas;
    auto add_pacs = params.add_pacs;
    auto add_ascs_cnt = params.add_ascs_cnt;
    auto set_size = params.set_size;
    auto rank = params.rank;
    auto gatt_status = params.gatt_status;
    auto max_supported_codec_frames_per_sdu =
        params.max_supported_codec_frames_per_sdu;

    auto csis = std::make_unique<NiceMock<MockDeviceWrapper::csis_mock>>();
    if (add_csis) {
      // attribute handles
@@ -2451,9 +2513,7 @@ class UnicastTestNoInit : public Test {

      // Set pacs default read values
      ON_CALL(*peer_devices.at(conn_id)->pacs, OnReadCharacteristic(_, _, _))
          .WillByDefault([this, conn_id, snk_allocation, src_allocation,
                          sample_freq, sink_channel_cnt, source_channel_cnt,
                          gatt_status](uint16_t handle, GATT_READ_OP_CB cb,
          .WillByDefault([=, this](uint16_t handle, GATT_READ_OP_CB cb,
                                   void* cb_data) {
            auto& pacs = peer_devices.at(conn_id)->pacs;
            std::vector<uint8_t> value;
@@ -2498,7 +2558,7 @@ class UnicastTestNoInit : public Test {
                      0x00,
                      0x00,
                      // Codec Spec. Caps. Len
                      0x10,
                      0x13,
                      0x03, /* sample freq */
                      0x01,
                      0x80, /* 48kHz */
@@ -2515,6 +2575,9 @@ class UnicastTestNoInit : public Test {
                      0x00,
                      0x78,
                      0x00,
                      0x02, /* Max supported codec frames per SDU */
                      0x05,
                      max_supported_codec_frames_per_sdu,
                      // Metadata Length
                      0x00,
                  };
@@ -2900,6 +2963,8 @@ class UnicastTest : public UnicastTestNoInit {
  }

  void TearDown() override {
    MockCodecInterface::ClearMockInstanceHookList();

    // Clear the default actions before the parent class teardown is called
    Mock::VerifyAndClear(&mock_btm_interface_);
    Mock::VerifyAndClear(&mock_gatt_interface_);
@@ -10882,4 +10947,186 @@ TEST_F_WITH_FLAGS(UnicastTest, NoContextvalidateStreamingRequest,
  Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
  Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
}

TEST_F(UnicastTest, CodecFrameBlocks2) {
  auto const max_codec_frames_per_sdu = 2;
  uint32_t data_len = 1920;

  // Register a on-the-fly hook for codec interface mock mutation to prepare the
  // codec mock for encoding
  std::list<MockCodecInterface*> codec_mocks;
  MockCodecInterface::RegisterMockInstanceHook([&](MockCodecInterface* mock,
                                                   bool is_destroyed) {
    if (is_destroyed) {
      log::debug("Codec Interface Destroyed: {}", (long)mock);
      codec_mocks.remove(mock);
    } else {
      log::debug("Codec Interface Created: {}", (long)mock);
      ON_CALL(*mock, GetNumOfSamplesPerChannel()).WillByDefault(Return(960));
      ON_CALL(*mock, GetNumOfBytesPerSample())
          .WillByDefault(Return(2));  // 16bits samples
      ON_CALL(*mock, Encode(_, _, _, _, _))
          .WillByDefault(Return(CodecInterface::Status::STATUS_OK));
      codec_mocks.push_back(mock);
    }
  });

  // Add a frame block PAC passing verifier
  bool is_fb2_passed_as_requirement = false;
  ON_CALL(*mock_codec_manager_, GetCodecConfig)
      .WillByDefault(Invoke([&](const bluetooth::le_audio::CodecManager::
                                    UnicastConfigurationRequirements&
                                        requirements,
                                bluetooth::le_audio::CodecManager::
                                    UnicastConfigurationVerifier verifier) {
        auto filtered =
            *bluetooth::le_audio::AudioSetConfigurationProvider::Get()
                 ->GetConfigurations(requirements.audio_context_type);
        // Filter out the dual bidir SWB configurations
        if (!bluetooth::le_audio::CodecManager::GetInstance()
                 ->IsDualBiDirSwbSupported()) {
          filtered.erase(
              std::remove_if(filtered.begin(), filtered.end(),
                             [](auto const& el) {
                               if (el->confs.source.empty()) return false;
                               return AudioSetConfigurationProvider::Get()
                                   ->CheckConfigurationIsDualBiDirSwb(*el);
                             }),
              filtered.end());
        }
        auto cfg = verifier(requirements, &filtered);
        if (cfg == nullptr) {
          return std::unique_ptr<set_configurations::AudioSetConfiguration>(
              nullptr);
        }

        auto config = *cfg;

        if (requirements.sink_pacs.has_value()) {
          for (auto const& rec : requirements.sink_pacs.value()) {
            auto caps = rec.codec_spec_caps.GetAsCoreCodecCapabilities();
            if (caps.HasSupportedMaxCodecFramesPerSdu()) {
              if (caps.supported_max_codec_frames_per_sdu.value() ==
                  max_codec_frames_per_sdu) {
                // Inject the proper Codec Frames Per SDU as the json
                // configs are conservative and will always give us 1
                for (auto& entry : config.confs.sink) {
                  entry.codec.params.Add(
                      codec_spec_conf::kLeAudioLtvTypeCodecFrameBlocksPerSdu,
                      (uint8_t)max_codec_frames_per_sdu);
                }
                is_fb2_passed_as_requirement = true;
              }
            }
          }
        }
        return std::make_unique<set_configurations::AudioSetConfiguration>(
            config);
      }));

  types::BidirectionalPair<stream_parameters> codec_manager_stream_params;
  ON_CALL(*mock_codec_manager_, UpdateActiveAudioConfig)
      .WillByDefault(Invoke(
          [&](const types::BidirectionalPair<stream_parameters>& stream_params,
              types::BidirectionalPair<uint16_t> delays_ms,
              std::function<void(const offload_config& config,
                                 uint8_t direction)>
                  updater) { codec_manager_stream_params = stream_params; }));

  const RawAddress test_address0 = GetTestAddress(0);
  int group_id = bluetooth::groups::kGroupUnknown;

  SampleDatabaseParameters remote_params{
      .conn_id = 1,
      .addr = test_address0,
      .add_csis = false,
      .set_size = 0,
      .rank = 0,
      .max_supported_codec_frames_per_sdu = 2,
  };
  SetSampleDatabaseEarbudsValid(remote_params);

  EXPECT_CALL(mock_audio_hal_client_callbacks_,
              OnConnectionState(ConnectionState::CONNECTED, test_address0))
      .Times(1);
  EXPECT_CALL(mock_audio_hal_client_callbacks_,
              OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
      .WillOnce(DoAll(SaveArg<1>(&group_id)));

  ConnectLeAudio(test_address0);
  ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);

  constexpr int gmcs_ccid = 1;
  constexpr int gtbs_ccid = 2;

  // Audio sessions are started only when device gets active
  EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
  EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
  LeAudioClient::Get()->SetCcidInformation(gmcs_ccid, 4 /* Media */);
  LeAudioClient::Get()->SetCcidInformation(gtbs_ccid, 2 /* Phone */);
  LeAudioClient::Get()->GroupSetActive(group_id);
  SyncOnMainLoop();

  types::BidirectionalPair<std::vector<uint8_t>> ccids = {.sink = {gmcs_ccid},
                                                          .source = {}};
  EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, ccids)).Times(1);

  block_streaming_state_callback = true;

  UpdateLocalSourceMetadata(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC);
  LocalAudioSourceResume(false);

  SyncOnMainLoop();
  Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
  Mock::VerifyAndClearExpectations(mock_le_audio_source_hal_client_);
  ASSERT_TRUE(is_fb2_passed_as_requirement);

  // Verify codec fram blocks per SDU has been applied to the device
  ASSERT_NE(0lu, streaming_groups.count(group_id));
  uint8_t device_configured_codec_frame_blocks_per_sdu = 0;
  auto group = streaming_groups.at(group_id);
  for (LeAudioDevice* device = group->GetFirstDevice(); device != nullptr;
       device = group->GetNextDevice(device)) {
    for (auto& ase : device->ases_) {
      if (ase.active) {
        auto cfg = ase.codec_config.GetAsCoreCodecConfig();
        ASSERT_TRUE(cfg.codec_frames_blocks_per_sdu.has_value());
        device_configured_codec_frame_blocks_per_sdu =
            cfg.codec_frames_blocks_per_sdu.value();
      }
    }
  }

  // Verify the configured codec frame blocks per SDU
  ASSERT_EQ(device_configured_codec_frame_blocks_per_sdu,
            remote_params.max_supported_codec_frames_per_sdu);

  EXPECT_CALL(mock_state_machine_, StopStream(_)).Times(0);
  do_in_main_thread(
      FROM_HERE,
      base::BindOnce(
          [](int group_id,
             bluetooth::le_audio::LeAudioGroupStateMachine::Callbacks*
                 state_machine_callbacks) {
            state_machine_callbacks->StatusReportCb(
                group_id, GroupStreamStatus::STREAMING);
          },
          group_id, base::Unretained(state_machine_callbacks_)));
  SyncOnMainLoop();
  Mock::VerifyAndClearExpectations(&mock_state_machine_);

  // Verify Data transfer on one audio source cis
  constexpr uint8_t cis_count_out = 1;
  constexpr uint8_t cis_count_in = 0;
  TestAudioDataTransfer(
      group_id, cis_count_out, cis_count_in,
      data_len * device_configured_codec_frame_blocks_per_sdu);

  ASSERT_NE(codec_mocks.size(), 0ul);

  // Verify that the initially started session was updated with the new params
  ASSERT_EQ(codec_manager_stream_params.sink.codec_frames_blocks_per_sdu,
            max_codec_frames_per_sdu);
}

}  // namespace bluetooth::le_audio
+3 −1
Original line number Diff line number Diff line
@@ -133,7 +133,9 @@ uint32_t CodecConfigSetting::GetSamplingFrequencyHz() const {
uint32_t CodecConfigSetting::GetDataIntervalUs() const {
  switch (id.coding_format) {
    case kLeAudioCodingFormatLC3:
      return params.GetAsCoreCodecConfig().GetFrameDurationUs();
      return params.GetAsCoreCodecConfig().GetFrameDurationUs() *
             params.GetAsCoreCodecConfig().codec_frames_blocks_per_sdu.value_or(
                 1);
    default:
      log::warn(", invalid codec id: 0x{:02x}", id.coding_format);
      return 0;
+23 −1
Original line number Diff line number Diff line
@@ -16,6 +16,11 @@

#include "mock_codec_interface.h"

#include "le_audio/codec_interface.h"

static std::list<std::function<void(MockCodecInterface*, bool)>>
    mock_life_listener_list;

namespace bluetooth::le_audio {

struct CodecInterface::Impl : public MockCodecInterface {
@@ -31,8 +36,16 @@ struct CodecInterface::Impl : public MockCodecInterface {

CodecInterface::CodecInterface(const types::LeAudioCodecId& codec_id) {
  impl = new Impl(codec_id);
  for (auto& foo : mock_life_listener_list) {
    foo(impl, false);
  }
}
CodecInterface::~CodecInterface() {
  for (auto& foo : mock_life_listener_list) {
    foo(impl, true);
  }
  delete impl;
}
CodecInterface::~CodecInterface() { delete impl; }
bool CodecInterface::IsReady() { return impl->IsReady(); };
CodecInterface::Status CodecInterface::InitEncoder(
    const LeAudioCodecConfiguration& pcm_config,
@@ -65,3 +78,12 @@ uint8_t CodecInterface::GetNumOfBytesPerSample() {
  return impl->GetNumOfBytesPerSample();
};
}  // namespace bluetooth::le_audio

void MockCodecInterface::RegisterMockInstanceHook(
    std::function<void(MockCodecInterface*, bool)> listener) {
  mock_life_listener_list.push_back(std::move(listener));
}

void MockCodecInterface::ClearMockInstanceHookList() {
  mock_life_listener_list.clear();
}
Loading