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

Commit 84b719fd authored by Łukasz Rymanowski's avatar Łukasz Rymanowski
Browse files

leaudio: Fix possible Assert OnLeAudioDeviceSetStateTimeout

Failing scenario:
1) stream is started and Codec Configure sent to peer device
2) after 1) state_machine.cc starts transition timer
3) device gets disconnected before device response with Codec Configured
 - here all ases are disactivated but transition timeout is still
   enabled
4) transition timeout fires and asserts there is no active device

Bug: 218795097
test: atest --host bluetooth_le_audio_test
Change-Id: Ic6e92a0441fa01b3d5b5b0383b77d0e28fd05924
parent 9d718b1d
Loading
Loading
Loading
Loading
+9 −7
Original line number Diff line number Diff line
@@ -499,6 +499,13 @@ class LeAudioGroupStateMachineImpl : public LeAudioGroupStateMachine {
      return;
    }

    /* If group is in Idle there is nothing to do here */
    if ((group->GetState() == AseState::BTA_LE_AUDIO_ASE_STATE_IDLE) &&
        (group->GetTargetState() == AseState::BTA_LE_AUDIO_ASE_STATE_IDLE)) {
      LOG(INFO) << __func__ << " group: " << group->group_id_ << " is in IDLE";
      return;
    }

    auto* stream_conf = &group->stream_conf;
    if (!stream_conf->sink_streams.empty() ||
        !stream_conf->source_streams.empty()) {
@@ -544,13 +551,8 @@ class LeAudioGroupStateMachineImpl : public LeAudioGroupStateMachine {
    }

    /* Group is not connected and all the CISes are down.
     * If group is in Idle there is nothing to do here */
    if (group->GetState() == AseState::BTA_LE_AUDIO_ASE_STATE_IDLE) {
      LOG(INFO) << __func__ << " group: " << group->group_id_ << " is in IDLE";
      return;
    }

    /* Clean states and destroy HCI group */
     * Clean states and destroy HCI group
     */
    group->SetState(AseState::BTA_LE_AUDIO_ASE_STATE_IDLE);
    group->SetTargetState(AseState::BTA_LE_AUDIO_ASE_STATE_IDLE);
    if (alarm_is_scheduled(watchdog_)) alarm_cancel(watchdog_);
+25 −0
Original line number Diff line number Diff line
@@ -2123,6 +2123,31 @@ TEST_F(StateMachineTest, testAseAutonomousRelease) {
  }
}

TEST_F(StateMachineTest, testStateTransitionTimeoutOnIdleState) {
  const auto context_type = kContextTypeRingtone;
  const int leaudio_group_id = 4;

  // Prepare fake connected device group
  auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type);

  auto* leAudioDevice = group->GetFirstDevice();
  EXPECT_CALL(gatt_queue,
              WriteCharacteristic(1, leAudioDevice->ctp_hdls_.val_hdl, _,
                                  GATT_WRITE_NO_RSP, _, _))
      .Times(1);

  // Start the configuration and stream Media content
  ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
      group, static_cast<types::LeAudioContextType>(context_type)));

  // Disconnect device
  LeAudioGroupStateMachine::Get()->ProcessHciNotifAclDisconnected(
      group, leAudioDevice);

  // Make sure timeout is cleared
  ASSERT_TRUE(fake_osi_alarm_set_on_mloop_.cb == nullptr);
}

TEST_F(StateMachineTest, testStateTransitionTimeout) {
  const auto context_type = kContextTypeRingtone;
  const int leaudio_group_id = 4;
+8 −3
Original line number Diff line number Diff line
@@ -380,15 +380,21 @@ alarm_t* alarm_new_periodic(const char* name) {
  mock_function_count_map[__func__]++;
  return nullptr;
}
struct fake_osi_alarm_set_on_mloop fake_osi_alarm_set_on_mloop_;
bool alarm_is_scheduled(const alarm_t* alarm) {
  mock_function_count_map[__func__]++;
  return false;
  return (fake_osi_alarm_set_on_mloop_.cb != nullptr);
}
uint64_t alarm_get_remaining_ms(const alarm_t* alarm) {
  mock_function_count_map[__func__]++;
  return 0;
}
void alarm_cancel(alarm_t* alarm) { mock_function_count_map[__func__]++; }
void alarm_cancel(alarm_t* alarm) {
  mock_function_count_map[__func__]++;
  fake_osi_alarm_set_on_mloop_.interval_ms = 0;
  fake_osi_alarm_set_on_mloop_.cb = nullptr;
  fake_osi_alarm_set_on_mloop_.data = nullptr;
}
void alarm_cleanup(void) { mock_function_count_map[__func__]++; }
void alarm_debug_dump(int fd) { mock_function_count_map[__func__]++; }
void alarm_free(alarm_t* alarm) { mock_function_count_map[__func__]++; }
@@ -397,7 +403,6 @@ void alarm_set(alarm_t* alarm, uint64_t interval_ms, alarm_callback_t cb,
  mock_function_count_map[__func__]++;
}

struct fake_osi_alarm_set_on_mloop fake_osi_alarm_set_on_mloop_;
void alarm_set_on_mloop(alarm_t* alarm, uint64_t interval_ms,
                        alarm_callback_t cb, void* data) {
  mock_function_count_map[__func__]++;