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

Commit 786b57c6 authored by Jakub Tyszkowski's avatar Jakub Tyszkowski
Browse files

LeAudio: Minor refactor using BidirectionalPair

- replace other sink/source pair structures with the generic
  BidirectionalPair<>
- replace the legacy Active Context naming with Available Context
- store the BidirectionalPair of supported contexts for group instead of
  one combined value - important the upcoming patches

Bug: 285647765
Test: atest bluetooth_le_audio_test bluetooth_le_audio_client_test
Change-Id: Ic6759c06d060880235b222f20eefd9a9ad0713bb
parent 0f19378a
Loading
Loading
Loading
Loading
+44 −47
Original line number Diff line number Diff line
@@ -1437,14 +1437,15 @@ class LeAudioClientImpl : public LeAudioClient {
          le_audio::types::kLeAudioDirectionSource;
    }

    leAudioDevice->SetSupportedContexts(
        AudioContexts(sink_supported_context_types),
        AudioContexts(source_supported_context_types));
    BidirectionalPair<AudioContexts> supported_contexts = {
        .sink = AudioContexts(sink_supported_context_types),
        .source = AudioContexts(source_supported_context_types),
    };

    leAudioDevice->SetSupportedContexts(supported_contexts);

    /* Use same as or supported ones for now. */
    leAudioDevice->SetAvailableContexts(
        AudioContexts(sink_supported_context_types),
        AudioContexts(source_supported_context_types));
    /* Use same as supported ones for now. */
    leAudioDevice->SetAvailableContexts(supported_contexts);

    if (!DeserializeHandles(leAudioDevice, handles)) {
      LOG_WARN("Could not load Handles");
@@ -1810,15 +1811,11 @@ class LeAudioClientImpl : public LeAudioClient {
       */
      UpdateLocationsAndContextsAvailability(leAudioDevice->group_id_);
    } else if (hdl == leAudioDevice->audio_avail_hdls_.val_hdl) {
      le_audio::client_parser::pacs::acs_available_audio_contexts
          avail_audio_contexts;
      le_audio::client_parser::pacs::ParseAvailableAudioContexts(
          avail_audio_contexts, len, value);

      auto updated_context_bits = leAudioDevice->SetAvailableContexts(
          avail_audio_contexts.snk_avail_cont,
          avail_audio_contexts.src_avail_cont);

      BidirectionalPair<AudioContexts> contexts;
      if (le_audio::client_parser::pacs::ParseAvailableAudioContexts(
              contexts, len, value)) {
        auto updated_context_bits =
            leAudioDevice->SetAvailableContexts(contexts);
        if (updated_context_bits.any()) {
          /* Update scenario map considering changed available context types */
          LeAudioDeviceGroup* group =
@@ -1838,23 +1835,23 @@ class LeAudioClientImpl : public LeAudioClient {
              return;
            }

          /* Available contexts change requires audio set config invalidation */
            /* Available contexts change requires audio set config invalidation
             */
            UpdateContexts(group, updated_context_bits);
          }
        }
      }
    } else if (hdl == leAudioDevice->audio_supp_cont_hdls_.val_hdl) {
      le_audio::client_parser::pacs::acs_supported_audio_contexts
          supp_audio_contexts;
      le_audio::client_parser::pacs::ParseSupportedAudioContexts(
          supp_audio_contexts, len, value);
      BidirectionalPair<AudioContexts> supp_audio_contexts;
      if (le_audio::client_parser::pacs::ParseSupportedAudioContexts(
              supp_audio_contexts, len, value)) {
        /* Just store if for now */
      leAudioDevice->SetSupportedContexts(supp_audio_contexts.snk_supp_cont,
                                          supp_audio_contexts.src_supp_cont);
        leAudioDevice->SetSupportedContexts(supp_audio_contexts);

        btif_storage_set_leaudio_supported_context_types(
          leAudioDevice->address_, supp_audio_contexts.snk_supp_cont.value(),
          supp_audio_contexts.src_supp_cont.value());

            leAudioDevice->address_, supp_audio_contexts.sink.value(),
            supp_audio_contexts.source.value());
      }
    } else if (hdl == leAudioDevice->ctp_hdls_.val_hdl) {
      auto ntf =
          std::make_unique<struct le_audio::client_parser::ascs::ctp_ntf>();
+14 −16
Original line number Diff line number Diff line
@@ -661,40 +661,38 @@ bool ParseAudioLocations(types::AudioLocations& audio_locations, uint16_t len,
  return true;
}

bool ParseSupportedAudioContexts(struct acs_supported_audio_contexts& contexts,
                                 uint16_t len, const uint8_t* value) {
bool ParseSupportedAudioContexts(
    types::BidirectionalPair<types::AudioContexts>& contexts, uint16_t len,
    const uint8_t* value) {
  if (len != kAseAudioSuppContRspMinLen) {
    LOG(ERROR) << "Wrong len of Audio Supported Context characteristic";
    return false;
  }

  STREAM_TO_UINT16(contexts.snk_supp_cont.value_ref(), value);
  STREAM_TO_UINT16(contexts.src_supp_cont.value_ref(), value);
  STREAM_TO_UINT16(contexts.sink.value_ref(), value);
  STREAM_TO_UINT16(contexts.source.value_ref(), value);

  LOG(INFO) << "Supported Audio Contexts: "
            << "\n\tSupported Sink Contexts: "
            << contexts.snk_supp_cont.to_string()
            << "\n\tSupported Source Contexts: "
            << contexts.src_supp_cont.to_string();
            << "\n\tSupported Sink Contexts: " << contexts.sink.to_string()
            << "\n\tSupported Source Contexts: " << contexts.source.to_string();

  return true;
}

bool ParseAvailableAudioContexts(struct acs_available_audio_contexts& contexts,
                                 uint16_t len, const uint8_t* value) {
bool ParseAvailableAudioContexts(
    types::BidirectionalPair<types::AudioContexts>& contexts, uint16_t len,
    const uint8_t* value) {
  if (len != kAseAudioAvailRspMinLen) {
    LOG(ERROR) << "Wrong len of Audio Availability characteristic";
    return false;
  }

  STREAM_TO_UINT16(contexts.snk_avail_cont.value_ref(), value);
  STREAM_TO_UINT16(contexts.src_avail_cont.value_ref(), value);
  STREAM_TO_UINT16(contexts.sink.value_ref(), value);
  STREAM_TO_UINT16(contexts.source.value_ref(), value);

  LOG(INFO) << "Available Audio Contexts: "
            << "\n\tAvailable Sink Contexts: "
            << contexts.snk_avail_cont.to_string()
            << "\n\tAvailable Source Contexts: "
            << contexts.src_avail_cont.to_string();
            << "\n\tAvailable Sink Contexts: " << contexts.sink.to_string()
            << "\n\tAvailable Source Contexts: " << contexts.source.to_string();

  return true;
}
+6 −12
Original line number Diff line number Diff line
@@ -230,16 +230,8 @@ constexpr uint16_t kAcsPacDiscoverRspMinLen = 1;
constexpr uint16_t kAudioLocationsRspMinLen = 4;

constexpr uint16_t kAseAudioAvailRspMinLen = 4;
struct acs_available_audio_contexts {
  types::AudioContexts snk_avail_cont;
  types::AudioContexts src_avail_cont;
};

constexpr uint16_t kAseAudioSuppContRspMinLen = 4;
struct acs_supported_audio_contexts {
  types::AudioContexts snk_supp_cont;
  types::AudioContexts src_supp_cont;
};

int ParseSinglePac(std::vector<struct types::acs_ac_record>& pac_recs,
                   uint16_t len, const uint8_t* value);
@@ -247,10 +239,12 @@ bool ParsePacs(std::vector<struct types::acs_ac_record>& pac_recs, uint16_t len,
               const uint8_t* value);
bool ParseAudioLocations(types::AudioLocations& audio_locations, uint16_t len,
                         const uint8_t* value);
bool ParseAvailableAudioContexts(struct acs_available_audio_contexts& rsp,
                                 uint16_t len, const uint8_t* value);
bool ParseSupportedAudioContexts(struct acs_supported_audio_contexts& rsp,
                                 uint16_t len, const uint8_t* value);
bool ParseAvailableAudioContexts(
    types::BidirectionalPair<types::AudioContexts>& rsp, uint16_t len,
    const uint8_t* value);
bool ParseSupportedAudioContexts(
    types::BidirectionalPair<types::AudioContexts>& rsp, uint16_t len,
    const uint8_t* value);
}  // namespace pacs

namespace tmap {
+12 −12
Original line number Diff line number Diff line
@@ -522,7 +522,7 @@ TEST(LeAudioClientParserTest, testParseAudioLocations) {
}

TEST(LeAudioClientParserTest, testParseAvailableAudioContextsInvalidLength) {
  acs_available_audio_contexts avail_contexts;
  types::BidirectionalPair<types::AudioContexts> avail_contexts;
  const uint8_t value1[] = {
      // Sink available contexts
      0x01, 0x02,
@@ -530,12 +530,12 @@ TEST(LeAudioClientParserTest, testParseAvailableAudioContextsInvalidLength) {
  };

  ParseAvailableAudioContexts(avail_contexts, sizeof(value1), value1);
  ASSERT_EQ(avail_contexts.snk_avail_cont.value(), 0u);
  ASSERT_EQ(avail_contexts.src_avail_cont.value(), 0u);
  ASSERT_EQ(avail_contexts.sink.value(), 0u);
  ASSERT_EQ(avail_contexts.source.value(), 0u);
}

TEST(LeAudioClientParserTest, testParseAvailableAudioContexts) {
  acs_available_audio_contexts avail_contexts;
  types::BidirectionalPair<types::AudioContexts> avail_contexts;
  const uint8_t value1[] = {
      // Sink available contexts
      0x01,
@@ -546,12 +546,12 @@ TEST(LeAudioClientParserTest, testParseAvailableAudioContexts) {
  };

  ParseAvailableAudioContexts(avail_contexts, sizeof(value1), value1);
  ASSERT_EQ(avail_contexts.snk_avail_cont.value(), 0x0201u);
  ASSERT_EQ(avail_contexts.src_avail_cont.value(), 0x0403u);
  ASSERT_EQ(avail_contexts.sink.value(), 0x0201u);
  ASSERT_EQ(avail_contexts.source.value(), 0x0403u);
}

TEST(LeAudioClientParserTest, testParseSupportedAudioContextsInvalidLength) {
  acs_supported_audio_contexts supp_contexts;
  types::BidirectionalPair<types::AudioContexts> supp_contexts;
  const uint8_t value1[] = {
      // Sink supported contexts
      0x01, 0x02,
@@ -559,12 +559,12 @@ TEST(LeAudioClientParserTest, testParseSupportedAudioContextsInvalidLength) {
  };

  ParseSupportedAudioContexts(supp_contexts, sizeof(value1), value1);
  ASSERT_EQ(supp_contexts.snk_supp_cont.value(), 0u);
  ASSERT_EQ(supp_contexts.src_supp_cont.value(), 0u);
  ASSERT_EQ(supp_contexts.sink.value(), 0u);
  ASSERT_EQ(supp_contexts.source.value(), 0u);
}

TEST(LeAudioClientParserTest, testParseSupportedAudioContexts) {
  acs_supported_audio_contexts supp_contexts;
  types::BidirectionalPair<types::AudioContexts> supp_contexts;
  const uint8_t value1[] = {
      // Sink supported contexts
      0x01,
@@ -575,8 +575,8 @@ TEST(LeAudioClientParserTest, testParseSupportedAudioContexts) {
  };

  ParseSupportedAudioContexts(supp_contexts, sizeof(value1), value1);
  ASSERT_EQ(supp_contexts.snk_supp_cont.value(), 0x0201u);
  ASSERT_EQ(supp_contexts.src_supp_cont.value(), 0x0403u);
  ASSERT_EQ(supp_contexts.sink.value(), 0x0201u);
  ASSERT_EQ(supp_contexts.source.value(), 0x0403u);
}

}  // namespace pacs
+43 −30
Original line number Diff line number Diff line
@@ -51,7 +51,6 @@ using le_audio::types::AseState;
using le_audio::types::AudioContexts;
using le_audio::types::AudioLocations;
using le_audio::types::AudioStreamDataPathState;
using le_audio::types::BidirectAsesPair;
using le_audio::types::BidirectionalPair;
using le_audio::types::CisType;
using le_audio::types::LeAudioCodecId;
@@ -267,6 +266,17 @@ bool LeAudioDeviceGroup::Activate(LeAudioContextType context_type) {
  return is_activate;
}

AudioContexts LeAudioDeviceGroup::GetSupportedContexts(int direction) const {
  AudioContexts context;
  for (auto& device : leAudioDevices_) {
    auto shared_dev = device.lock();
    if (shared_dev) {
      context |= shared_dev->GetSupportedContexts(direction);
    }
  }
  return context;
}

LeAudioDevice* LeAudioDeviceGroup::GetFirstDevice(void) const {
  auto iter = std::find_if(leAudioDevices_.begin(), leAudioDevices_.end(),
                           [](auto& iter) { return !iter.expired(); });
@@ -276,7 +286,7 @@ LeAudioDevice* LeAudioDeviceGroup::GetFirstDevice(void) const {
  return (iter->lock()).get();
}

LeAudioDevice* LeAudioDeviceGroup::GetFirstDeviceWithActiveContext(
LeAudioDevice* LeAudioDeviceGroup::GetFirstDeviceWithAvailableContext(
    types::LeAudioContextType context_type) const {
  auto iter = std::find_if(
      leAudioDevices_.begin(), leAudioDevices_.end(),
@@ -312,7 +322,7 @@ LeAudioDevice* LeAudioDeviceGroup::GetNextDevice(
  return (iter->lock()).get();
}

LeAudioDevice* LeAudioDeviceGroup::GetNextDeviceWithActiveContext(
LeAudioDevice* LeAudioDeviceGroup::GetNextDeviceWithAvailableContext(
    LeAudioDevice* leAudioDevice,
    types::LeAudioContextType context_type) const {
  auto iter = std::find_if(leAudioDevices_.begin(), leAudioDevices_.end(),
@@ -786,9 +796,13 @@ uint16_t LeAudioDeviceGroup::GetRemoteDelay(uint8_t direction) const {
}

bool LeAudioDeviceGroup::UpdateAudioSetConfigurationCache(void) {
  LOG_DEBUG(" group id: %d, available contexts: %s", group_id_,
            group_available_contexts_.to_string().c_str());
  return UpdateAudioSetConfigurationCache(group_available_contexts_);
  LOG_DEBUG(
      " group id: %d, available contexts sink: %s, available contexts source: "
      "%s",
      group_id_, group_available_contexts_.sink.to_string().c_str(),
      group_available_contexts_.source.to_string().c_str());
  return UpdateAudioSetConfigurationCache(
      get_bidirectional(group_available_contexts_));
}

/* Returns true if support for any type in the whole group has changed,
@@ -864,7 +878,8 @@ bool LeAudioDeviceGroup::UpdateAudioSetConfigurationCache(

  /* Some contexts have changed, return new available context bitset */
  if (active_contexts_has_been_modified) {
    SetAvailableContexts(new_contexts);
    // TODO: Set the correct directional context availability
    SetAvailableContexts({new_contexts, new_contexts});
  }

  return active_contexts_has_been_modified;
@@ -1354,9 +1369,9 @@ bool LeAudioDeviceGroup::IsAudioSetConfigurationSupported(
      return false;
    }

    for (auto* device = GetFirstDeviceWithActiveContext(context_type);
    for (auto* device = GetFirstDeviceWithAvailableContext(context_type);
         device != nullptr && required_device_cnt > 0;
         device = GetNextDeviceWithActiveContext(device, context_type)) {
         device = GetNextDeviceWithAvailableContext(device, context_type)) {
      /* Skip if device has ASE configured in this direction already */

      if (device->ases_.empty()) continue;
@@ -1708,9 +1723,9 @@ bool LeAudioDeviceGroup::ConfigureAses(
        required_device_cnt, ent.ase_cnt, max_required_ase_per_dev,
        (int)strategy);

    for (auto* device = GetFirstDeviceWithActiveContext(context_type);
    for (auto* device = GetFirstDeviceWithAvailableContext(context_type);
         device != nullptr && required_device_cnt > 0;
         device = GetNextDeviceWithActiveContext(device, context_type)) {
         device = GetNextDeviceWithAvailableContext(device, context_type)) {
      /* For the moment, we configure only connected devices and when it is
       * ready to stream i.e. All ASEs are discovered and device is reported as
       * connected
@@ -2241,6 +2256,8 @@ void LeAudioDeviceGroup::PrintDebugState(void) const {
            << ", target state: "
            << bluetooth::common::ToString(GetTargetState())
            << ", cig state: " << bluetooth::common::ToString(cig_state_)
            << ", \n group supported contexts: "
            << bluetooth::common::ToString(GetSupportedContexts())
            << ", \n group available contexts: "
            << bluetooth::common::ToString(GetAvailableContexts())
            << ", \n configuration context type: "
@@ -2297,6 +2314,7 @@ void LeAudioDeviceGroup::Dump(int fd, int active_group_id) const {
         << "      state: " << GetState()
         << ",\ttarget state: " << GetTargetState()
         << ",\tcig state: " << cig_state_ << "\n"
         << "      group supported contexts: " << GetSupportedContexts() << "\n"
         << "      group available contexts: " << GetAvailableContexts() << "\n"
         << "      configuration context type: "
         << bluetooth::common::ToString(GetConfigurationContextType()).c_str()
@@ -2555,8 +2573,9 @@ struct ase* LeAudioDevice::GetAseToMatchBidirectionCis(struct ase* base_ase) {
  return (iter == ases_.end()) ? nullptr : &(*iter);
}

BidirectAsesPair LeAudioDevice::GetAsesByCisConnHdl(uint16_t conn_hdl) {
  BidirectAsesPair ases = {nullptr, nullptr};
BidirectionalPair<struct ase*> LeAudioDevice::GetAsesByCisConnHdl(
    uint16_t conn_hdl) {
  BidirectionalPair<struct ase*> ases = {nullptr, nullptr};

  for (auto& ase : ases_) {
    if (ase.cis_conn_hdl == conn_hdl) {
@@ -2571,8 +2590,8 @@ BidirectAsesPair LeAudioDevice::GetAsesByCisConnHdl(uint16_t conn_hdl) {
  return ases;
}

BidirectAsesPair LeAudioDevice::GetAsesByCisId(uint8_t cis_id) {
  BidirectAsesPair ases = {nullptr, nullptr};
BidirectionalPair<struct ase*> LeAudioDevice::GetAsesByCisId(uint8_t cis_id) {
  BidirectionalPair<struct ase*> ases = {nullptr, nullptr};

  for (auto& ase : ases_) {
    if (ase.cis_id == cis_id) {
@@ -2791,12 +2810,6 @@ uint8_t LeAudioDevice::GetPhyBitmask(void) {
  return phy_bitfield;
}

void LeAudioDevice::SetSupportedContexts(AudioContexts snk_contexts,
                                         AudioContexts src_contexts) {
  supp_contexts_.sink = snk_contexts;
  supp_contexts_.source = src_contexts;
}

void LeAudioDevice::PrintDebugState(void) {
  std::stringstream debug_str;

@@ -2922,23 +2935,23 @@ void LeAudioDevice::DisconnectAcl(void) {
}

/* Returns XOR of updated sink and source bitset context types */
AudioContexts LeAudioDevice::SetAvailableContexts(AudioContexts snk_contexts,
                                                  AudioContexts src_contexts) {
AudioContexts LeAudioDevice::SetAvailableContexts(
    types::BidirectionalPair<types::AudioContexts> contexts) {
  AudioContexts updated_contexts;

  updated_contexts = snk_contexts ^ avail_contexts_.sink;
  updated_contexts |= src_contexts ^ avail_contexts_.source;
  updated_contexts = contexts.sink ^ avail_contexts_.sink;
  updated_contexts |= contexts.source ^ avail_contexts_.source;

  LOG_DEBUG(
      "\n\t avail_contexts_.sink: %s \n\t avail_contexts_.source: %s  \n\t "
      "snk_contexts: %s \n\t src_contexts: %s \n\t updated_contexts: %s",
      "contexts.sink: %s \n\t contexts.source: %s \n\t updated_contexts: %s",
      avail_contexts_.sink.to_string().c_str(),
      avail_contexts_.source.to_string().c_str(),
      snk_contexts.to_string().c_str(), src_contexts.to_string().c_str(),
      contexts.sink.to_string().c_str(), contexts.source.to_string().c_str(),
      updated_contexts.to_string().c_str());

  avail_contexts_.sink = snk_contexts;
  avail_contexts_.source = src_contexts;
  avail_contexts_.sink = contexts.sink;
  avail_contexts_.source = contexts.source;

  return updated_contexts;
}
@@ -3152,7 +3165,7 @@ LeAudioDevice* LeAudioDevices::FindByCisConnHdl(uint8_t cig_id,
  auto iter = std::find_if(leAudioDevices_.begin(), leAudioDevices_.end(),
                           [&conn_hdl, &cig_id](auto& d) {
                             LeAudioDevice* dev;
                             BidirectAsesPair ases;
                             BidirectionalPair<struct ase*> ases;

                             dev = d.get();
                             if (dev->group_id_ != cig_id) {
Loading