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

Commit a279ce41 authored by Jakub Tyszkowski's avatar Jakub Tyszkowski
Browse files

LeAudio: Reduce number of reconfigurations

To play sonification events we don't really need high quality
stream and we can play them at any configuration. For example
a button click when resuming recording should not trigger
reconfiguration to Media.

This change allows to play these events without the reconfiguration
if these types of events are the only contributors to the current
audio stream (using allow list of contexts).

Bug: 261417889
Tag: #feature
Test: atest --host bluetooth_le_audio_test bluetooth_le_audio_client_test --no-bazel-mode
Change-Id: I5dbd66e3a4ef0944894550f9902cddf9d0422681
Merged-In: I5dbd66e3a4ef0944894550f9902cddf9d0422681
(cherry picked from commit 41224874)
parent f7cfc29e
Loading
Loading
Loading
Loading
+35 −0
Original line number Diff line number Diff line
@@ -280,6 +280,19 @@ class LeAudioClientImpl : public LeAudioClient {
      return;
    }

    /* For sonification events we don't really need to reconfigure to HQ
     * configuration, but if the previous configuration was for HQ Media,
     * we might want to go back to that scenario.
     */

    if ((configuration_context_type_ != LeAudioContextType::MEDIA) &&
        (configuration_context_type_ != LeAudioContextType::GAME)) {
      LOG_INFO(
          "Keeping the old configuration as no HQ Media playback is needed "
          "right now.");
      return;
    }

    /* Test the existing metadata against the recent availability */
    metadata_context_types_.sink &= group->GetAvailableContexts();
    if (metadata_context_types_.sink.none()) {
@@ -3655,6 +3668,28 @@ class LeAudioClientImpl : public LeAudioClient {
    auto new_configuration_context =
        ChooseConfigurationContextType(new_metadata_context_types_);

    /* For the following contexts we don't actually need HQ audio:
     * LeAudioContextType::NOTIFICATIONS
     * LeAudioContextType::SOUNDEFFECTS
     * LeAudioContextType::INSTRUCTIONAL
     * LeAudioContextType::ALERTS
     * LeAudioContextType::EMERGENCYALARM
     * So do not reconfigure if the remote sink is already available at any
     * quality and these are the only contributors to the current audio stream.
     */
    auto no_reconfigure_contexts =
        LeAudioContextType::NOTIFICATIONS | LeAudioContextType::SOUNDEFFECTS |
        LeAudioContextType::INSTRUCTIONAL | LeAudioContextType::ALERTS |
        LeAudioContextType::EMERGENCYALARM;
    if ((new_metadata_context_types_ & ~no_reconfigure_contexts).none() &&
        IsDirectionAvailableForCurrentConfiguration(
            group, le_audio::types::kLeAudioDirectionSink)) {
      LOG_INFO(
          "There is no need to reconfigure for the sonification events. Keep "
          "the configuration unchanged.");
      new_configuration_context = configuration_context_type_;
    }

    LOG_DEBUG("new_configuration_context= %s",
              ToString(new_configuration_context).c_str());
    ReconfigureOrUpdateMetadata(group, new_configuration_context,
+21 −9
Original line number Diff line number Diff line
@@ -3434,10 +3434,12 @@ TEST_F(UnicastTest, TwoEarbudsStreamingContextSwitchNoReconfigure) {
  LeAudioClient::Get()->GroupSetActive(group_id);
  Mock::VerifyAndClearExpectations(&mock_le_audio_source_hal_client_);

  // Start streaming with reconfiguration from default media stream setup
  // Start streaming with new metadata, but use the existing configuration
  EXPECT_CALL(
      mock_state_machine_,
      StartStream(_, le_audio::types::LeAudioContextType::NOTIFICATIONS, _, _))
      StartStream(
          _, types::LeAudioContextType::MEDIA,
          types::AudioContexts(types::LeAudioContextType::NOTIFICATIONS), _))
      .Times(1);

  StartStreaming(AUDIO_USAGE_NOTIFICATION, AUDIO_CONTENT_TYPE_UNKNOWN,
@@ -3447,37 +3449,47 @@ TEST_F(UnicastTest, TwoEarbudsStreamingContextSwitchNoReconfigure) {
  Mock::VerifyAndClearExpectations(&mock_le_audio_source_hal_client_);
  SyncOnMainLoop();

  // Do a content switch to ALERTS
  // Do a metadata content switch to ALERTS but stay on MEDIA configuration
  EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(0);
  EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop).Times(0);
  EXPECT_CALL(*mock_le_audio_source_hal_client_, Start).Times(0);
  EXPECT_CALL(mock_state_machine_,
              StartStream(_, le_audio::types::LeAudioContextType::ALERTS, _, _))
  EXPECT_CALL(
      mock_state_machine_,
      StartStream(
          _, le_audio::types::LeAudioContextType::MEDIA,
          types::AudioContexts(le_audio::types::LeAudioContextType::ALERTS), _))
      .Times(1);
  UpdateMetadata(AUDIO_USAGE_ALARM, AUDIO_CONTENT_TYPE_UNKNOWN);
  Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
  Mock::VerifyAndClearExpectations(&mock_le_audio_source_hal_client_);

  // Do a content switch to EMERGENCY
  // Do a metadata content switch to EMERGENCY but stay on MEDIA configuration
  EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(0);
  EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop).Times(0);
  EXPECT_CALL(*mock_le_audio_source_hal_client_, Start).Times(0);

  EXPECT_CALL(
      mock_state_machine_,
      StartStream(_, le_audio::types::LeAudioContextType::EMERGENCYALARM, _, _))
      StartStream(_, le_audio::types::LeAudioContextType::MEDIA,
                  types::AudioContexts(
                      le_audio::types::LeAudioContextType::EMERGENCYALARM),
                  _))
      .Times(1);
  UpdateMetadata(AUDIO_USAGE_EMERGENCY, AUDIO_CONTENT_TYPE_UNKNOWN);
  Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
  Mock::VerifyAndClearExpectations(&mock_le_audio_source_hal_client_);

  // Do a content switch to INSTRUCTIONAL
  // Do a metadata content switch to INSTRUCTIONAL but stay on MEDIA
  // configuration
  EXPECT_CALL(*mock_le_audio_source_hal_client_, OnDestroyed()).Times(0);
  EXPECT_CALL(*mock_le_audio_source_hal_client_, Stop).Times(0);
  EXPECT_CALL(*mock_le_audio_source_hal_client_, Start).Times(0);
  EXPECT_CALL(
      mock_state_machine_,
      StartStream(_, le_audio::types::LeAudioContextType::INSTRUCTIONAL, _, _))
      StartStream(_, le_audio::types::LeAudioContextType::MEDIA,
                  types::AudioContexts(
                      le_audio::types::LeAudioContextType::INSTRUCTIONAL),
                  _))
      .Times(1);
  UpdateMetadata(AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE,
                 AUDIO_CONTENT_TYPE_UNKNOWN);
+2 −0
Original line number Diff line number Diff line
@@ -61,6 +61,8 @@ LeAudioContextType AudioContentToLeAudioContext(
      return LeAudioContextType::EMERGENCYALARM;
    case AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
      return LeAudioContextType::INSTRUCTIONAL;
    case AUDIO_USAGE_ASSISTANCE_SONIFICATION:
      return LeAudioContextType::SOUNDEFFECTS;
    default:
      break;
  }