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

Commit 49a00ea1 authored by Jakub Pawłowski's avatar Jakub Pawłowski Committed by Gerrit Code Review
Browse files

Merge "leaudio: Fix assert on reenabling ASE from QoS Configured" into main

parents 07d37e03 b88373eb
Loading
Loading
Loading
Loading
+0 −2
Original line number Diff line number Diff line
@@ -966,13 +966,11 @@ class LeAudioGroupStateMachineImpl : public LeAudioGroupStateMachine {
          ases_pair.sink->state == AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) {
        ases_pair.sink->state =
            AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED;
        ases_pair.sink->active = false;
      }
      if (ases_pair.source && ases_pair.source->state ==
                                  AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) {
        ases_pair.source->state =
            AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED;
        ases_pair.source->active = false;
      }
    }

+119 −0
Original line number Diff line number Diff line
@@ -490,6 +490,7 @@ class StateMachineTest : public Test {
    addresses_.clear();
    cached_codec_configuration_map_.clear();
    cached_ase_to_cis_id_map_.clear();
    cached_remote_qos_configuration_for_ase_.clear();
    LeAudioGroupStateMachine::Cleanup();
    ::le_audio::AudioSetConfigurationProvider::Cleanup();
  }
@@ -625,6 +626,8 @@ class StateMachineTest : public Test {
        UINT16_TO_STREAM(p, conf->max_transport_latency);
        UINT24_TO_STREAM(p, conf->pres_delay);

        cached_remote_qos_configuration_for_ase_[ase] = notif_value;

        LeAudioGroupStateMachine::Get()->ProcessGattNotifEvent(
            notif_value.data(), notif_value.size(), ase, device, group);
      } break;
@@ -1280,6 +1283,8 @@ class StateMachineTest : public Test {
      cached_codec_configuration_map_;

  std::map<RawAddress, std::map<int, int>> cached_ase_to_cis_id_map_;
  std::map<types::ase*, std::vector<uint8_t>>
      cached_remote_qos_configuration_for_ase_;

  MockLeAudioGroupStateMachineCallbacks mock_callbacks_;
  std::vector<std::shared_ptr<LeAudioDevice>> le_audio_devices_;
@@ -3705,6 +3710,120 @@ TEST_F(StateMachineTest, testAttachDeviceToTheStream) {
  ASSERT_NE(ase->retrans_nb, 0);
}

TEST_F(StateMachineTest,
       testAttachDeviceToTheStream_autonomusQoSConfiguredState) {
  const auto context_type = kContextTypeMedia;
  const auto leaudio_group_id = 6;
  const auto num_devices = 2;

  ContentControlIdKeeper::GetInstance()->SetCcid(media_context, media_ccid);

  // Prepare multiple fake connected devices in a group
  auto* group =
      PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
  ASSERT_EQ(group->Size(), num_devices);

  PrepareConfigureCodecHandler(group);
  PrepareConfigureQosHandler(group);
  PrepareEnableHandler(group);
  PrepareDisableHandler(group);
  PrepareReleaseHandler(group);

  auto* leAudioDevice = group->GetFirstDevice();
  LeAudioDevice* lastDevice;
  LeAudioDevice* fistDevice = leAudioDevice;

  auto expected_devices_written = 0;
  while (leAudioDevice) {
    /* Three Writes:
     * 1: Codec Config
     * 2: Codec QoS
     * 3: Enabling
     */
    lastDevice = leAudioDevice;
    EXPECT_CALL(gatt_queue,
                WriteCharacteristic(leAudioDevice->conn_id_,
                                    leAudioDevice->ctp_hdls_.val_hdl, _,
                                    GATT_WRITE_NO_RSP, _, _))
        .Times(AtLeast(3));
    expected_devices_written++;
    leAudioDevice = group->GetNextDevice(leAudioDevice);
  }
  ASSERT_EQ(expected_devices_written, num_devices);

  EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
  EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
  EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(2);

  InjectInitialIdleNotification(group);

  // Start the configuration and stream Media content
  LeAudioGroupStateMachine::Get()->StartStream(
      group, context_type,
      {.sink = types::AudioContexts(context_type),
       .source = types::AudioContexts(context_type)},
      {.sink = std::vector<uint8_t>(1, media_ccid),
       .source = std::vector<uint8_t>(1, media_ccid)});

  // Check if group has transitioned to a proper state
  ASSERT_EQ(group->GetState(),
            types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
  testing::Mock::VerifyAndClearExpectations(&mock_iso_manager_);

  // Inject CIS and ACL disconnection of first device
  InjectCisDisconnected(group, lastDevice, HCI_ERR_CONNECTION_TOUT);

  // Check if group keeps streaming
  ASSERT_EQ(group->GetState(),
            types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);

  // Make sure ASE with disconnected CIS are not left in STREAMING
  ASSERT_EQ(lastDevice->GetFirstAseWithState(
                ::le_audio::types::kLeAudioDirectionSink,
                types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING),
            nullptr);
  ASSERT_EQ(lastDevice->GetFirstAseWithState(
                ::le_audio::types::kLeAudioDirectionSource,
                types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING),
            nullptr);

  EXPECT_CALL(gatt_queue, WriteCharacteristic(lastDevice->conn_id_,
                                              lastDevice->ctp_hdls_.val_hdl, _,
                                              GATT_WRITE_NO_RSP, _, _))
      .Times(1);

  EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
  EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(1);

  for (auto& ase : lastDevice->ases_) {
    if (cached_remote_qos_configuration_for_ase_.count(&ase) > 0) {
      InjectAseStateNotification(
          &ase, lastDevice, group, ascs::kAseStateQoSConfigured,
          &(cached_remote_qos_configuration_for_ase_[&ase]));
    }
  }

  // Check if group keeps streaming
  ASSERT_EQ(group->GetState(),
            types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);

  // Verify that the joining device receives the right CCID list
  auto lastMeta = lastDevice->GetFirstActiveAse()->metadata;
  bool parsedOk = false;
  auto ltv = le_audio::types::LeAudioLtvMap::Parse(lastMeta.data(),
                                                   lastMeta.size(), parsedOk);
  ASSERT_TRUE(parsedOk);

  auto ccids = ltv.Find(le_audio::types::kLeAudioMetadataTypeCcidList);
  ASSERT_TRUE(ccids.has_value());
  ASSERT_NE(std::find(ccids->begin(), ccids->end(), media_ccid), ccids->end());

  /* Verify that ASE of first device are still good*/
  auto ase = fistDevice->GetFirstActiveAse();
  ASSERT_NE(ase->max_transport_latency, 0);
  ASSERT_NE(ase->retrans_nb, 0);
}

TEST_F(StateMachineTest, testAttachDeviceToTheStreamDoNotAttach) {
  const auto context_type = kContextTypeMedia;
  const auto leaudio_group_id = 6;