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

Commit 9d83176d authored by Grzegorz Kolodziejczyk's avatar Grzegorz Kolodziejczyk Committed by Gerrit Code Review
Browse files

Merge "le_audio: Add test_reactivation_conversational test"

parents 9562dcab 5cf38490
Loading
Loading
Loading
Loading
+157 −9
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@ using ::le_audio::types::AseState;
using ::le_audio::types::AudioContexts;
using ::le_audio::types::AudioLocations;
using ::le_audio::types::BidirectionalPair;
using ::le_audio::types::CisType;
using ::le_audio::types::LeAudioContextType;
using testing::_;
using testing::Invoke;
@@ -430,7 +431,8 @@ class LeAudioAseConfigurationTest : public Test {

  LeAudioDevice* AddTestDevice(int snk_ase_num, int src_ase_num,
                               int snk_ase_num_cached = 0,
                               int src_ase_num_cached = 0) {
                               int src_ase_num_cached = 0,
                               bool invert_ases_emplacement = false) {
    int index = group_->Size() + 1;
    auto device = (std::make_shared<LeAudioDevice>(
        GetTestAddress(index), DeviceConnectState::DISCONNECTED));
@@ -442,24 +444,42 @@ class LeAudioAseConfigurationTest : public Test {
    group_->AddNode(device);

    int ase_id = 1;
    for (int i = 0; i < src_ase_num; i++) {
      device->ases_.emplace_back(0x0000, 0x0000, kLeAudioDirectionSource,
    for (int i = 0; i < (invert_ases_emplacement ? snk_ase_num : src_ase_num);
         i++) {
      device->ases_.emplace_back(0x0000, 0x0000,
                                 invert_ases_emplacement
                                     ? kLeAudioDirectionSink
                                     : kLeAudioDirectionSource,
                                 ase_id++);
    }

    for (int i = 0; i < snk_ase_num; i++) {
      device->ases_.emplace_back(0x0000, 0x0000, kLeAudioDirectionSink,
    for (int i = 0; i < (invert_ases_emplacement ? src_ase_num : snk_ase_num);
         i++) {
      device->ases_.emplace_back(0x0000, 0x0000,
                                 invert_ases_emplacement
                                     ? kLeAudioDirectionSource
                                     : kLeAudioDirectionSink,
                                 ase_id++);
    }

    for (int i = 0; i < src_ase_num_cached; i++) {
      struct ase ase(0x0000, 0x0000, kLeAudioDirectionSource, ase_id++);
    for (int i = 0; i < (invert_ases_emplacement ? snk_ase_num_cached
                                                 : src_ase_num_cached);
         i++) {
      struct ase ase(0x0000, 0x0000,
                     invert_ases_emplacement ? kLeAudioDirectionSink
                                             : kLeAudioDirectionSource,
                     ase_id++);
      ase.state = AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED;
      device->ases_.push_back(ase);
    }

    for (int i = 0; i < snk_ase_num_cached; i++) {
      struct ase ase(0x0000, 0x0000, kLeAudioDirectionSink, ase_id++);
    for (int i = 0; i < (invert_ases_emplacement ? src_ase_num_cached
                                                 : snk_ase_num_cached);
         i++) {
      struct ase ase(0x0000, 0x0000,
                     invert_ases_emplacement ? kLeAudioDirectionSource
                                             : kLeAudioDirectionSink,
                     ase_id++);
      ase.state = AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED;
      device->ases_.push_back(ase);
    }
@@ -792,6 +812,18 @@ class LeAudioAseConfigurationTest : public Test {
    }
  }

  void SetAsesToCachedConfiguration(LeAudioDevice* device,
                                    LeAudioContextType context_type,
                                    uint8_t directions) {
    for (struct ase& ase : device->ases_) {
      if (ase.direction & directions) {
        ase.state = AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED;
        ase.active = false;
        ase.configured_for_context_type = context_type;
      }
    }
  }

  const int group_id_ = 6;
  std::vector<std::shared_ptr<LeAudioDevice>> devices_;
  std::vector<RawAddress> addresses_;
@@ -1218,6 +1250,122 @@ TEST_F(LeAudioAseConfigurationTest, test_reconnection_media) {

  TestActiveAses();
}

/*
 * Failure happens when restarting conversational scenario and when
 * remote device uses caching.
 *
 * Failing scenario.
 * 1. Conversational scenario set up with
 *  - ASE 1 and ASE 5 using bidirectional CIS 0
 *  - ASE 2  being unidirectional on CIS 1
 * 2. Stop stream and go to CONFIGURED STATE.
 * 3. Trying to configure ASES again would end up in incorrectly assigned
 *    CISes
 *  - ASE 1 and ASE 5 set to CIS 0
 *  - ASE 2 stay on CIS 1 but ASE 5 got reassigned to CIS 1 (error)
 *
 * The problem is finding matching_bidir_ase which shall not be just next
 * active ase with different direction, but it shall be also available (Cis
 * not assigned) or assigned to the same CIS ID as the opposite direction.
 */
TEST_F(LeAudioAseConfigurationTest, test_reactivation_conversational) {
  LeAudioDevice* tws_headset = AddTestDevice(0, 0, 2, 1, true);

  /* Change location as by default it is stereo */
  tws_headset->snk_audio_locations_ = kChannelAllocationStereo;
  tws_headset->src_audio_locations_ =
      ::le_audio::codec_spec_conf::kLeAudioLocationFrontLeft;
  group_->ReloadAudioLocations();

  auto all_configurations =
      ::le_audio::AudioSetConfigurationProvider::Get()->GetConfigurations(
          LeAudioContextType::CONVERSATIONAL);
  ASSERT_NE(nullptr, all_configurations);
  ASSERT_NE(all_configurations->end(), all_configurations->begin());

  /* Pick TWS configuration for conversational */
  auto iter = std::find_if(all_configurations->begin(),
                           all_configurations->end(), [](auto& configuration) {
                             return configuration->name ==
                                    "SingleDev_OneChanStereoSnk_OneChanMonoSrc_"
                                    "16_2_Low_Latency";
                           });

  ASSERT_NE(iter, all_configurations->end());

  auto conversational_configuration = *iter;

  // Build PACs for device
  PublishedAudioCapabilitiesBuilder snk_pac_builder, src_pac_builder;
  snk_pac_builder.Reset();
  src_pac_builder.Reset();

  /* Create PACs for conversational scenario which covers also media. Single
   * PAC for each direction is enough.
   */
  for (const auto& entry : (*conversational_configuration).confs) {
    if (entry.direction == kLeAudioDirectionSink) {
      snk_pac_builder.Add(entry.codec, 1);
    } else {
      src_pac_builder.Add(entry.codec, 1);
    }
  }

  tws_headset->snk_pacs_ = snk_pac_builder.Get();
  tws_headset->src_pacs_ = src_pac_builder.Get();

  ::le_audio::types::AudioLocations group_snk_audio_locations = 0;
  ::le_audio::types::AudioLocations group_src_audio_locations = 0;
  uint8_t number_of_already_active_ases = 0;

  BidirectionalPair<AudioLocations> group_audio_locations = {
      .sink = group_snk_audio_locations, .source = group_src_audio_locations};

  /* Get entry for the sink direction and use it to set configuration */
  BidirectionalPair<std::vector<uint8_t>> ccid_lists = {{}, {}};
  BidirectionalPair<AudioContexts> audio_contexts = {AudioContexts(),
                                                     AudioContexts()};

  /* Get entry for the sink direction and use it to set configuration */
  for (auto& ent : conversational_configuration->confs) {
    tws_headset->ConfigureAses(ent, group_->GetConfigurationContextType(),
                               &number_of_already_active_ases,
                               group_audio_locations, audio_contexts,
                               ccid_lists, false);
  }

  /* Generate CISes, simulate CIG creation and assign cis handles to ASEs.*/
  std::vector<uint16_t> handles = {0x0012, 0x0013};
  group_->CigGenerateCisIds(LeAudioContextType::CONVERSATIONAL);
  group_->CigAssignCisConnHandles(handles);
  group_->CigAssignCisIds(tws_headset);

  TestActiveAses();

  /* Simulate stopping stream with caching codec configuration in ASEs */
  group_->CigUnassignCis(tws_headset);
  SetAsesToCachedConfiguration(tws_headset, LeAudioContextType::CONVERSATIONAL,
                               kLeAudioDirectionSink | kLeAudioDirectionSource);

  /* As context type is the same as previous and no changes were made in PACs
   * the same CIS ID can be used. This would lead to only activating group
   * without reconfiguring CIG.
   */
  group_->Activate(LeAudioContextType::CONVERSATIONAL);

  TestActiveAses();

  /* Verify ASEs assigned CISes by counting assigned to bi-directional CISes */
  int bi_dir_ases_count = std::count_if(
      tws_headset->ases_.begin(), tws_headset->ases_.end(), [=](auto& ase) {
        return this->group_->cises_[ase.cis_id].type ==
               CisType::CIS_TYPE_BIDIRECTIONAL;
      });

  /* Only two ASEs can be bonded to one bi-directional CIS */
  ASSERT_EQ(bi_dir_ases_count, 2);
}
}  // namespace
}  // namespace internal
}  // namespace le_audio