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

Commit 352ee339 authored by Jakub Tyszkowski's avatar Jakub Tyszkowski Committed by Grzegorz Kołodziejczyk
Browse files

leaudio: Use common CCID keeper in unicast and broadcast

Broadcast source needs to access the same CCID information
as the unicast client.

Bug: 150670922
Bug: 230340466
Tag: #feature
Sponsor: jpawlowski@
Test: atest LeAudioBroadcastServiceTest bluetooth_test_broadcaster_sm bluetooth_test_broadcaster bluetooth_le_audio_client_test
Change-Id: I109d599ddac080fa2919ef586aa4510e4ab6fe8a
Merged-In: I109d599ddac080fa2919ef586aa4510e4ab6fe8a
(cherry picked from commit 1c852e06)
parent 6706a403
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -93,6 +93,7 @@ cc_library_static {
        "le_audio/broadcaster/state_machine.cc",
        "le_audio/client.cc",
        "le_audio/codec_manager.cc",
        "le_audio/content_control_id_keeper.cc",
        "le_audio/devices.cc",
        "le_audio/hal_verifier.cc",
        "le_audio/state_machine.cc",
@@ -623,6 +624,7 @@ cc_test {
        "le_audio/client.cc",
        "le_audio/client_audio.cc",
        "le_audio/client_parser.cc",
        "le_audio/content_control_id_keeper.cc",
        "le_audio/devices.cc",
        "le_audio/le_audio_client_test.cc",
        "le_audio/le_audio_set_configuration_provider_json.cc",
@@ -762,6 +764,7 @@ cc_test {
        "le_audio/broadcaster/broadcaster_types.cc",
        "le_audio/broadcaster/mock_ble_advertising_manager.cc",
        "le_audio/broadcaster/mock_state_machine.cc",
        "le_audio/content_control_id_keeper.cc",
        "le_audio/client_audio.cc",
        "le_audio/le_audio_types.cc",
        "le_audio/mock_iso_manager.cc",
+11 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@
#include "bta/include/bta_le_audio_api.h"
#include "bta/include/bta_le_audio_broadcaster_api.h"
#include "bta/le_audio/broadcaster/state_machine.h"
#include "bta/le_audio/content_control_id_keeper.h"
#include "bta/le_audio/le_audio_types.h"
#include "device/include/controller.h"
#include "embdrv/lc3/include/lc3.h"
@@ -36,6 +37,7 @@ using bluetooth::hci::iso_manager::big_terminate_cmpl_evt;
using bluetooth::hci::iso_manager::BigCallbacks;
using bluetooth::le_audio::BasicAudioAnnouncementData;
using bluetooth::le_audio::BroadcastId;
using le_audio::ContentControlIdKeeper;
using le_audio::broadcaster::BigConfig;
using le_audio::broadcaster::BroadcastCodecWrapper;
using le_audio::broadcaster::BroadcastQosConfig;
@@ -214,6 +216,15 @@ class LeAudioBroadcasterImpl : public LeAudioBroadcaster, public BigCallbacks {
      STREAM_TO_UINT16(context_type, pp);
    }

    // Append the CCID list
    // TODO: We currently support only one context (and CCID) at a time for both
    //       Unicast and broadcast.
    auto ccid = ContentControlIdKeeper::GetInstance()->GetCcid(context_type);
    if (ccid != -1) {
      ltv.Add(le_audio::types::kLeAudioMetadataTypeCcidList,
              {static_cast<uint8_t>(ccid)});
    }

    auto codec_qos_pair =
        le_audio::broadcaster::getStreamConfigForContext(context_type);
    BroadcastStateMachineConfig msg = {
+16 −2
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@
#include "bta/include/bta_le_audio_api.h"
#include "bta/include/bta_le_audio_broadcaster_api.h"
#include "bta/le_audio/broadcaster/mock_state_machine.h"
#include "bta/le_audio/content_control_id_keeper.h"
#include "bta/le_audio/le_audio_types.h"
#include "bta/le_audio/mock_iso_manager.h"
#include "bta/test/common/mock_controller.h"
@@ -118,6 +119,7 @@ static const std::vector<uint8_t> default_metadata = {
    le_audio::types::kLeAudioMetadataTypeStreamingAudioContext,
    default_context & 0x00FF, (default_context & 0xFF00) >> 8};

static constexpr uint8_t media_ccid = 0xC0;
static constexpr auto media_context =
    static_cast<std::underlying_type<LeAudioContextType>::type>(
        LeAudioContextType::MEDIA);
@@ -200,6 +202,8 @@ class BroadcasterTest : public Test {
    LeAudioBroadcaster::Initialize(&mock_broadcaster_callbacks_,
                                   base::Bind([]() -> bool { return true; }));

    ContentControlIdKeeper::GetInstance()->Start();

    /* Simulate random generator */
    uint8_t random[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
    generator_cb.Run(random);
@@ -512,14 +516,24 @@ TEST_F(BroadcasterTest, StreamParamsAlerts) {

TEST_F(BroadcasterTest, StreamParamsMedia) {
  uint8_t expected_channels = 2u;
  ContentControlIdKeeper::GetInstance()->SetCcid(media_context, media_ccid);
  InstantiateBroadcast(media_metadata);
  auto config = MockBroadcastStateMachine::GetLastInstance()->cfg;

  // Check audio configuration
  ASSERT_EQ(config.codec_wrapper.GetNumChannels(), expected_channels);

  auto& subgroup = config.announcement.subgroup_configs[0];

  // Matches number of bises in the announcement
  ASSERT_EQ(config.announcement.subgroup_configs[0].bis_configs.size(),
            expected_channels);
  ASSERT_EQ(subgroup.bis_configs.size(), expected_channels);
  // Verify CCID for Media
  auto ccid_list_opt = types::LeAudioLtvMap(subgroup.metadata)
                           .Find(le_audio::types::kLeAudioMetadataTypeCcidList);
  ASSERT_TRUE(ccid_list_opt.has_value());
  auto ccid_list = ccid_list_opt.value();
  ASSERT_EQ(1u, ccid_list.size());
  ASSERT_EQ(media_ccid, ccid_list[0]);
  // Note: Num of bises at IsoManager level is verified by state machine tests
}

+11 −23
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@
#include "client_parser.h"
#include "codec_manager.h"
#include "common/time_util.h"
#include "content_control_id_keeper.h"
#include "device/include/controller.h"
#include "devices.h"
#include "embdrv/lc3/include/lc3.h"
@@ -61,6 +62,7 @@ using bluetooth::le_audio::GroupNodeStatus;
using bluetooth::le_audio::GroupStatus;
using bluetooth::le_audio::GroupStreamStatus;
using le_audio::CodecManager;
using le_audio::ContentControlIdKeeper;
using le_audio::LeAudioDevice;
using le_audio::LeAudioDeviceGroup;
using le_audio::LeAudioDeviceGroups;
@@ -333,12 +335,8 @@ class LeAudioClientImpl : public LeAudioClient {
    group_remove_node(group, address);
  }

  int GetCcid(le_audio::types::LeAudioContextType context_type) {
    if (ccids_.count(context_type) == 0) {
      return -1;
    }

    return ccids_[context_type];
  int GetCcid(uint16_t context_type) {
    return ContentControlIdKeeper::GetInstance()->GetCcid(context_type);
  }

  /* This callback happens if kLeAudioDeviceSetStateTimeoutMs timeout happens
@@ -647,7 +645,7 @@ class LeAudioClientImpl : public LeAudioClient {

    bool result = groupStateMachine_->StartStream(
        group, static_cast<LeAudioContextType>(final_context_type),
        GetCcid(static_cast<LeAudioContextType>(final_context_type)));
        GetCcid(final_context_type));
    if (result)
      stream_setup_start_timestamp_ =
          bluetooth::common::time_get_os_boottime_us();
@@ -738,17 +736,7 @@ class LeAudioClientImpl : public LeAudioClient {

  void SetCcidInformation(int ccid, int context_type) override {
    LOG_DEBUG("Ccid: %d, context type %d", ccid, context_type);

    std::bitset<16> test{static_cast<uint16_t>(context_type)};
    auto ctx_type =
        static_cast<le_audio::types::LeAudioContextType>(context_type);
    if (test.count() > 1 ||
        ctx_type >= le_audio::types::LeAudioContextType::RFU) {
      LOG_ERROR("Unknownd context type %d", context_type);
      return;
    }

    ccids_[ctx_type] = ccid;
    ContentControlIdKeeper::GetInstance()->SetCcid(context_type, ccid);
  }

  void StartAudioSession(LeAudioDeviceGroup* group,
@@ -3560,7 +3548,9 @@ class LeAudioClientImpl : public LeAudioClient {
          SuspendedForReconfiguration();
          if (groupStateMachine_->ConfigureStream(
                  group, current_context_type_,
                  GetCcid(current_context_type_))) {
                  GetCcid(static_cast<
                          std::underlying_type<LeAudioContextType>::type>(
                      current_context_type_)))) {
            /* If configuration succeed wait for new status. */
            return;
          }
@@ -3602,10 +3592,6 @@ class LeAudioClientImpl : public LeAudioClient {
  /* Speaker(s) */
  AudioState audio_sender_state_;

  /* Ccid informations */
  std::map<le_audio::types::LeAudioContextType /* context */, int /*ccid */>
      ccids_;

  /* Current stream configuration */
  LeAudioCodecConfiguration current_source_codec_config;
  LeAudioCodecConfiguration current_sink_codec_config;
@@ -3907,6 +3893,7 @@ void LeAudioClient::Initialize(

  IsoManager::GetInstance()->RegisterCigCallbacks(stateMachineHciCallbacks);
  CodecManager::GetInstance()->Start(offloading_preference);
  ContentControlIdKeeper::GetInstance()->Start();

  callbacks_->OnInitialized();
}
@@ -3949,6 +3936,7 @@ void LeAudioClient::Cleanup(base::Callback<void()> cleanupCb) {
  }

  CodecManager::GetInstance()->Stop();
  ContentControlIdKeeper::GetInstance()->Stop();
  LeAudioGroupStateMachine::Cleanup();
  IsoManager::GetInstance()->Stop();
  le_audio::MetricsCollector::Get()->Flush();
+123 −0
Original line number Diff line number Diff line
/*
 * Copyright 2022 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.
 */

#include "content_control_id_keeper.h"

#include <bitset>
#include <map>

#include "le_audio_types.h"
#include "osi/include/log.h"

namespace {

using le_audio::types::LeAudioContextType;

}  // namespace

namespace le_audio {

struct ccid_keeper {
 public:
  ccid_keeper() {}

  ~ccid_keeper() {}

  void SetCcid(uint16_t context_type, int ccid) {
    LOG_DEBUG("Ccid: %d, context type %d", ccid, context_type);

    std::bitset<16> test{context_type};
    if (test.count() > 1 ||
        context_type >=
            static_cast<std::underlying_type<LeAudioContextType>::type>(
                LeAudioContextType::RFU)) {
      LOG_ERROR("Unknownd context type %d", context_type);
      return;
    }

    auto ctx_type = static_cast<LeAudioContextType>(context_type);
    ccids_.insert_or_assign(ctx_type, ccid);
  }

  int GetCcid(uint16_t context_type) const {
    std::bitset<16> test{context_type};
    if (test.count() > 1 ||
        context_type >=
            static_cast<std::underlying_type<LeAudioContextType>::type>(
                LeAudioContextType::RFU)) {
      LOG_ERROR("Unknownd context type %d", context_type);
      return -1;
    }

    auto ctx_type = static_cast<LeAudioContextType>(context_type);

    if (ccids_.count(ctx_type) == 0) {
      return -1;
    }

    return ccids_.at(ctx_type);
  }

 private:
  /* Ccid informations */
  std::map<LeAudioContextType /* context */, int /*ccid */> ccids_;
};

struct ContentControlIdKeeper::impl {
  impl(const ContentControlIdKeeper& ccid_keeper) : ccid_keeper_(ccid_keeper) {}

  void Start() {
    LOG_ASSERT(!ccid_keeper_impl_);
    ccid_keeper_impl_ = std::make_unique<ccid_keeper>();
  }

  void Stop() {
    LOG_ASSERT(ccid_keeper_impl_);
    ccid_keeper_impl_.reset();
  }

  bool IsRunning() { return ccid_keeper_impl_ ? true : false; }

  const ContentControlIdKeeper& ccid_keeper_;
  std::unique_ptr<ccid_keeper> ccid_keeper_impl_;
};

ContentControlIdKeeper::ContentControlIdKeeper()
    : pimpl_(std::make_unique<impl>(*this)) {}

void ContentControlIdKeeper::Start() {
  if (!pimpl_->IsRunning()) pimpl_->Start();
}

void ContentControlIdKeeper::Stop() {
  if (pimpl_->IsRunning()) pimpl_->Stop();
}

int ContentControlIdKeeper::GetCcid(uint16_t context_type) const {
  if (!pimpl_->IsRunning()) {
    return -1;
  }

  return pimpl_->ccid_keeper_impl_->GetCcid(context_type);
}

void ContentControlIdKeeper::SetCcid(uint16_t context_type, int ccid) {
  if (pimpl_->IsRunning()) {
    pimpl_->ccid_keeper_impl_->SetCcid(context_type, ccid);
  }
}

}  // namespace le_audio
Loading