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

Commit dc595207 authored by Łukasz Rymanowski's avatar Łukasz Rymanowski
Browse files

leaudio: Fix reconfiguration for sonification types

There is a logic which prevents reconfiguration for the sonification
contexts. This is usefull especially after GAME or CONVERSATIONAL
stream, when in the end of stream there is either SOUNDEFFECT or
similar. In such a case we just stream that on previous configured
CISes.

However, there is a bug, that if CISes are not there, we keep using old
configurations for sonifications which could lead to send NOTIFICATIONS
on bidirectional CISes if NOTIFICATION is send after phone call.

This patch fixes that

Bug: 317660246
Test: atest bluetooth_le_audio_client_test
Flag: Exempt, regression tested with unit test and new test added to
cover error scenario

Change-Id: Ied7e09414edfbbeb3977d1898e034e77a886dc23
parent ab8f9b20
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -5082,7 +5082,7 @@ class LeAudioClientImpl : public LeAudioClient {
        LeAudioContextType::NOTIFICATIONS | LeAudioContextType::SOUNDEFFECTS |
        LeAudioContextType::INSTRUCTIONAL | LeAudioContextType::ALERTS |
        LeAudioContextType::EMERGENCYALARM | LeAudioContextType::UNSPECIFIED;
    if (config_context_candids.any() &&
    if (group->IsStreaming() && config_context_candids.any() &&
        (config_context_candids & ~no_reconfigure_contexts).none() &&
        (configuration_context_type_ != LeAudioContextType::UNINITIALIZED) &&
        (configuration_context_type_ != LeAudioContextType::UNSPECIFIED) &&
+91 −0
Original line number Diff line number Diff line
@@ -6247,6 +6247,97 @@ TEST_F(UnicastTest, TwoEarbudsStreamingContextSwitchNoReconfigure) {
  Mock::VerifyAndClearExpectations(&mock_le_audio_source_hal_client_);
}

TEST_F(UnicastTest, TwoEarbudsStopConversational_StartStreamSonification) {
  uint8_t group_size = 2;
  int group_id = 2;

  // Report working CSIS
  ON_CALL(mock_csis_client_module_, IsCsisClientRunning())
      .WillByDefault(Return(true));

  ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
      .WillByDefault(Invoke([&](int group_id) { return group_size; }));

  // First earbud
  const RawAddress test_address0 = GetTestAddress(0);
  EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address0, true))
      .Times(1);
  ConnectCsisDevice(test_address0, 1 /*conn_id*/,
                    codec_spec_conf::kLeAudioLocationFrontLeft,
                    codec_spec_conf::kLeAudioLocationFrontLeft, group_size,
                    group_id, 1 /* rank*/);

  // Second earbud
  const RawAddress test_address1 = GetTestAddress(1);
  EXPECT_CALL(mock_btif_storage_, AddLeaudioAutoconnect(test_address1, true))
      .Times(1);
  ConnectCsisDevice(test_address1, 2 /*conn_id*/,
                    codec_spec_conf::kLeAudioLocationFrontRight,
                    codec_spec_conf::kLeAudioLocationFrontRight, group_size,
                    group_id, 2 /* rank*/, true /*connect_through_csis*/);

  // Start streaming
  EXPECT_CALL(*mock_le_audio_source_hal_client_, Start(_, _, _)).Times(1);
  EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _, _)).Times(1);
  LeAudioClient::Get()->GroupSetActive(group_id);
  SyncOnMainLoop();
  Mock::VerifyAndClearExpectations(&mock_le_audio_source_hal_client_);

  // Start streaming with CONVERSATIONAL, there was no previous stream so start
  // with this new configuration
  auto initial_context = types::LeAudioContextType::CONVERSATIONAL;
  types::BidirectionalPair<types::AudioContexts> contexts = {
      .sink = types::AudioContexts(initial_context),
      .source = types::AudioContexts(initial_context)};
  EXPECT_CALL(mock_state_machine_, StartStream(_, initial_context, contexts, _))
      .Times(1);

  StartStreaming(AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_CONTENT_TYPE_SPEECH,
                 group_id);

  SyncOnMainLoop();
  Mock::VerifyAndClearExpectations(&mock_state_machine_);
  Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
  Mock::VerifyAndClearExpectations(&mock_le_audio_source_hal_client_);

  // Stop the stream but KEEP cis UP
  StopStreaming(group_id, true);
  SyncOnMainLoop();
  Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);

  types::BidirectionalPair<types::AudioContexts> reconfigure_contexts = {
      .sink = types::AudioContexts(types::LeAudioContextType::ALERTS),
      .source = types::AudioContexts()};

  EXPECT_CALL(mock_state_machine_,
              StartStream(_, initial_context, reconfigure_contexts, _))
      .Times(1);

  // Change context type but expect configuration to by as previous
  StartStreaming(AUDIO_USAGE_ALARM, AUDIO_CONTENT_TYPE_UNKNOWN, group_id);

  SyncOnMainLoop();
  Mock::VerifyAndClearExpectations(&mock_state_machine_);

  // Stop the stream and drop CISes
  StopStreaming(group_id, true);
  SyncOnMainLoop();
  // simulate suspend timeout passed, alarm executing
  fake_osi_alarm_set_on_mloop_.cb(fake_osi_alarm_set_on_mloop_.data);
  Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);

  auto reconfigure_context = types::LeAudioContextType::ALERTS;

  EXPECT_CALL(mock_state_machine_,
              StartStream(_, reconfigure_context, reconfigure_contexts, _))
      .Times(1);

  // Update metadata
  StartStreaming(AUDIO_USAGE_ALARM, AUDIO_CONTENT_TYPE_UNKNOWN, group_id);
  SyncOnMainLoop();
  Mock::VerifyAndClearExpectations(&mock_state_machine_);
}

TEST_F(UnicastTest, TwoEarbudsStreamingContextSwitchReconfigure) {
  uint8_t group_size = 2;
  int group_id = 2;