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

Commit 9eacdff6 authored by Jakub Tyszkowski's avatar Jakub Tyszkowski
Browse files

LeAudio: Fix crash on active group deactivation

If there are multiple calls scheduled on the main loop, it might happen
that the active LE Audio group is deactivated while the state machine
goes to streaming state. We should handle it gracefully rather than assert.

Bug: 338937189
Test: atest bluetooth_le_audio_client_test
Flag: Exempt; trivial fix, unit tested
Change-Id: I893694717035983fb079377752fb1e9f89e9b8d7
parent e3bb9309
Loading
Loading
Loading
Loading
+6 −2
Original line number Original line Diff line number Diff line
@@ -5628,8 +5628,12 @@ class LeAudioClientImpl : public LeAudioClient {


    switch (status) {
    switch (status) {
      case GroupStreamStatus::STREAMING: {
      case GroupStreamStatus::STREAMING: {
        log::assert_that(group_id == active_group_id_,
        if (group_id != active_group_id_) {
                         "invalid group id {}!={}", group_id, active_group_id_);
          log::error("Streaming group {} is no longer active. Stop the group.",
                     group_id);
          GroupStop(group_id);
          return;
        }


        take_stream_time();
        take_stream_time();


+43 −0
Original line number Original line Diff line number Diff line
@@ -5113,6 +5113,49 @@ TEST_F(UnicastTest, TestUpdateConfigurationCallbackWhileStreaming) {
  Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
  Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
}
}


TEST_F(UnicastTest, TestDeactivateWhileStartingStream) {
  const RawAddress test_address0 = GetTestAddress(0);
  int group_id = bluetooth::groups::kGroupUnknown;

  SetSampleDatabaseEarbudsValid(
      1, test_address0, codec_spec_conf::kLeAudioLocationStereo,
      codec_spec_conf::kLeAudioLocationStereo, default_channel_cnt,
      default_channel_cnt, 0x0004,
      /* source sample freq 16khz */ false /*add_csis*/, true /*add_cas*/,
      true /*add_pacs*/, default_ase_cnt /*add_ascs_cnt*/, 1 /*set_size*/,
      0 /*rank*/);
  EXPECT_CALL(mock_audio_hal_client_callbacks_,
              OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
      .WillOnce(DoAll(SaveArg<1>(&group_id)));

  ConnectLeAudio(test_address0);
  ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);

  // Start streaming
  LeAudioClient::Get()->GroupSetActive(group_id);
  SyncOnMainLoop();
  StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id);

  // Deactivate while starting to stream
  LeAudioClient::Get()->GroupSetActive(bluetooth::groups::kGroupUnknown);

  // Inject STREAMING Status from state machine.
  auto group = streaming_groups.at(group_id);
  do_in_main_thread(
      FROM_HERE,
      base::BindOnce(
          [](int group_id,
             bluetooth::le_audio::LeAudioGroupStateMachine::Callbacks*
                 state_machine_callbacks,
             LeAudioDeviceGroup* group) {
            state_machine_callbacks->StatusReportCb(
                group_id, GroupStreamStatus::STREAMING);
          },
          group_id, base::Unretained(this->state_machine_callbacks_),
          std::move(group)));
  SyncOnMainLoop();
}

TEST_F(UnicastTest, RemoveNodeWhileStreaming) {
TEST_F(UnicastTest, RemoveNodeWhileStreaming) {
  const RawAddress test_address0 = GetTestAddress(0);
  const RawAddress test_address0 = GetTestAddress(0);
  int group_id = bluetooth::groups::kGroupUnknown;
  int group_id = bluetooth::groups::kGroupUnknown;