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

Commit 1c07cf8c authored by Łukasz Rymanowski's avatar Łukasz Rymanowski Committed by Gerrit Code Review
Browse files

Merge "leaudio: Fix double iso data path removal" into main

parents 2b63eb73 0ca5d01b
Loading
Loading
Loading
Loading
+7 −3
Original line number Diff line number Diff line
@@ -787,9 +787,13 @@ uint32_t AdjustAllocationForOffloader(uint32_t allocation) {
namespace types {
std::ostream& operator<<(std::ostream& os,
                         const AudioStreamDataPathState& state) {
  static const char* char_value_[6] = {
      "IDLE",        "CIS_DISCONNECTING", "CIS_ASSIGNED",
      "CIS_PENDING", "CIS_ESTABLISHED",   "DATA_PATH_ESTABLISHED"};
  static const char* char_value_[7] = {"IDLE",
                                       "CIS_DISCONNECTING",
                                       "CIS_ASSIGNED",
                                       "CIS_PENDING",
                                       "CIS_ESTABLISHED",
                                       "DATA_PATH_ESTABLISHED",
                                       "DATA_PATH_REMOVING"};

  os << char_value_[static_cast<uint8_t>(state)] << " ("
     << "0x" << std::setfill('0') << std::setw(2) << static_cast<int>(state)
+1 −0
Original line number Diff line number Diff line
@@ -350,6 +350,7 @@ enum class AudioStreamDataPathState {
  CIS_PENDING,
  CIS_ESTABLISHED,
  DATA_PATH_ESTABLISHED,
  DATA_PATH_REMOVING,
};

enum class CisType {
+7 −4
Original line number Diff line number Diff line
@@ -568,15 +568,14 @@ class LeAudioGroupStateMachineImpl : public LeAudioGroupStateMachine {

    auto ases_pair = leAudioDevice->GetAsesByCisConnHdl(conn_hdl);
    if (ases_pair.sink && (ases_pair.sink->data_path_state ==
                           AudioStreamDataPathState::DATA_PATH_ESTABLISHED)) {
                           AudioStreamDataPathState::DATA_PATH_REMOVING)) {
      ases_pair.sink->data_path_state =
          AudioStreamDataPathState::CIS_DISCONNECTING;
      do_disconnect = true;
    }

    if (ases_pair.source &&
        ases_pair.source->data_path_state ==
            AudioStreamDataPathState::DATA_PATH_ESTABLISHED) {
    if (ases_pair.source && ases_pair.source->data_path_state ==
                                AudioStreamDataPathState::DATA_PATH_REMOVING) {
      ases_pair.source->data_path_state =
          AudioStreamDataPathState::CIS_DISCONNECTING;
      do_disconnect = true;
@@ -862,12 +861,16 @@ class LeAudioGroupStateMachineImpl : public LeAudioGroupStateMachine {
    if (ases_pair.sink && ases_pair.sink->data_path_state ==
                              AudioStreamDataPathState::DATA_PATH_ESTABLISHED) {
      value |= bluetooth::hci::iso_manager::kRemoveIsoDataPathDirectionInput;
      ases_pair.sink->data_path_state =
          AudioStreamDataPathState::DATA_PATH_REMOVING;
    }

    if (ases_pair.source &&
        ases_pair.source->data_path_state ==
            AudioStreamDataPathState::DATA_PATH_ESTABLISHED) {
      value |= bluetooth::hci::iso_manager::kRemoveIsoDataPathDirectionOutput;
      ases_pair.source->data_path_state =
          AudioStreamDataPathState::DATA_PATH_REMOVING;
    }

    if (value == 0) {
+70 −0
Original line number Diff line number Diff line
@@ -4538,6 +4538,76 @@ TEST_F(StateMachineTest, StreamClearAfterReleaseAndConnectionTimeout) {
  testing::Mock::VerifyAndClearExpectations(&mock_iso_manager_);
}

TEST_F(StateMachineTest, VerifyThereIsNoDoubleDataPathRemoval) {
  auto context_type = kContextTypeConversational;
  const auto leaudio_group_id = 4;
  const auto num_devices = 1;

  /* Symulate banded headphonse */
  channel_count_ = kLeAudioCodecLC3ChannelCountSingleChannel |
                   kLeAudioCodecLC3ChannelCountTwoChannel;

  /* Scenario
  1. Phone call to 1 device
  2. Stop the stream
  3. Get both ASE sink and Source to releasing
  4. Verify only 1 RemoveDataPath is called
  */

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

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

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

  /*Test ends before full clean*/
  EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(0);
  EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(0);

  InjectInitialIdleNotification(group);

  // Validate GroupStreamStatus
  EXPECT_CALL(
      mock_callbacks_,
      StatusReportCb(leaudio_group_id,
                     bluetooth::le_audio::GroupStreamStatus::STREAMING));

  ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
      group, context_type,
      {.sink = types::AudioContexts(context_type),
       .source = types::AudioContexts(context_type)}));

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

  EXPECT_CALL(
      mock_callbacks_,
      StatusReportCb(leaudio_group_id,
                     bluetooth::le_audio::GroupStreamStatus::RELEASING));

  /* Do not trigger any action on removeIsoData path.*/
  ON_CALL(*mock_iso_manager_, RemoveIsoDataPath).WillByDefault(Return());

  LeAudioGroupStateMachine::Get()->StopStream(group);

  testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
  testing::Mock::VerifyAndClearExpectations(&mock_iso_manager_);
}

TEST_F(StateMachineTest, StreamStartWithDifferentContextFromConfiguredState) {
  auto context_type = kContextTypeConversational;
  const auto leaudio_group_id = 6;