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

Commit 4eddbdb0 authored by Jakub Tyszkowski's avatar Jakub Tyszkowski
Browse files

LeAudio: Do not reconfigure on sink metadata update

Instead we should reconfigure on the local sink resume, since
sink metadata update event does not necessary means that the
sink will ever resume.

Bug: 268333427
Tag: #feature
Test: atest --host bluetooth_le_audio_client_test bluetooth_le_audio_test --no-bazel-mode
Change-Id: I132c766788b992065ebd181b9aa56f1b22c57564
parent 18429f61
Loading
Loading
Loading
Loading
+34 −6
Original line number Diff line number Diff line
@@ -3495,6 +3495,13 @@ class LeAudioClientImpl : public LeAudioClient {
      return;
    }

    /* We need new configuration_context_type_ to be selected before we go any
     * further.
     */
    if (audio_receiver_state_ == AudioState::IDLE) {
      ReconfigureOrUpdateRemoteSource(group);
    }

    /* Check if the device resume is expected */
    if (!group->GetCodecConfigurationByDirection(
            configuration_context_type_,
@@ -3708,9 +3715,13 @@ class LeAudioClientImpl : public LeAudioClient {
     */
    StopVbcCloseTimeout();

    LOG_DEBUG("group state=%s, target_state=%s",
              ToString(group->GetState()).c_str(),
              ToString(group->GetTargetState()).c_str());
    LOG_INFO(
        "group_id %d state=%s, target_state=%s, audio_receiver_state_: %s, "
        "audio_sender_state_: %s",
        group->group_id_, ToString(group->GetState()).c_str(),
        ToString(group->GetTargetState()).c_str(),
        ToString(audio_receiver_state_).c_str(),
        ToString(audio_sender_state_).c_str());

    /* When a certain context became unavailable while it was already in
     * an active stream, it means that it is unavailable to other clients
@@ -3728,6 +3739,10 @@ class LeAudioClientImpl : public LeAudioClient {
    metadata_context_types_.sink =
        ChooseMetadataContextType(metadata_context_types_.sink);

    ReconfigureOrUpdateRemoteSink(group);
  }

  void ReconfigureOrUpdateRemoteSink(LeAudioDeviceGroup* group) {
    if (stack_config_get_interface()
            ->get_pts_force_le_audio_multiple_contexts_metadata()) {
      // Use common audio stream contexts exposed by the PTS
@@ -3839,9 +3854,13 @@ class LeAudioClientImpl : public LeAudioClient {
      return;
    }

    LOG_DEBUG("group state=%s, target_state=%s",
              ToString(group->GetState()).c_str(),
              ToString(group->GetTargetState()).c_str());
    LOG_INFO(
        "group_id %d state=%s, target_state=%s, audio_receiver_state_: %s, "
        "audio_sender_state_: %s",
        group->group_id_, ToString(group->GetState()).c_str(),
        ToString(group->GetTargetState()).c_str(),
        ToString(audio_receiver_state_).c_str(),
        ToString(audio_sender_state_).c_str());

    /* When a certain context became unavailable while it was already in
     * an active stream, it means that it is unavailable to other clients
@@ -3866,6 +3885,15 @@ class LeAudioClientImpl : public LeAudioClient {
          AudioContexts(LeAudioContextType::CONVERSATIONAL);
    }

    /* Reconfigure or update only if the stream is already started
     * otherwise wait for the local sink to resume.
     */
    if (audio_receiver_state_ == AudioState::STARTED) {
      ReconfigureOrUpdateRemoteSource(group);
    }
  }

  void ReconfigureOrUpdateRemoteSource(LeAudioDeviceGroup* group) {
    if (stack_config_get_interface()
            ->get_pts_force_le_audio_multiple_contexts_metadata()) {
      // Use common audio stream contexts exposed by the PTS
+45 −13
Original line number Diff line number Diff line
@@ -3637,7 +3637,10 @@ TEST_F(UnicastTest, TwoEarbudsStreamingContextSwitchReconfigure) {
  Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);

  ccids = {.sink = {gtbs_ccid}, .source = {}};
  EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, ccids));
  // Can be called twice to update metadata if local sink resumes after the
  // source
  EXPECT_CALL(mock_state_machine_, StartStream(_, _, _, ccids))
      .Times(AtLeast(1));
  StartStreaming(AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_CONTENT_TYPE_SPEECH,
                 group_id);

@@ -3886,32 +3889,61 @@ TEST_F(UnicastTest, MicrophoneAttachToCurrentMediaScenario) {
  EXPECT_CALL(*mock_le_audio_sink_hal_client_, Start(_, _)).Times(1);
  LeAudioClient::Get()->GroupSetActive(group_id);

  // When the local audio source resumes we have no knowledge of recording
  EXPECT_CALL(mock_state_machine_,
              StartStream(_, le_audio::types::LeAudioContextType::LIVE, _, _))
              StartStream(_, le_audio::types::LeAudioContextType::MEDIA, _, _))
      .Times(1);

  StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id,
                 AUDIO_SOURCE_MIC);
                 AUDIO_SOURCE_INVALID);
  SyncOnMainLoop();

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

  // Verify Data transfer on one audio source cis
  uint8_t cis_count_out = 1;
  uint8_t cis_count_in = 0;
  TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);

  // Suspend
  /*TODO Need a way to verify STOP */
  LeAudioClient::Get()->GroupSuspend(group_id);
  Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
  Mock::VerifyAndClearExpectations(&mock_le_audio_source_hal_client_);
  // When the local audio sink resumes we should reconfigure
  EXPECT_CALL(
      mock_state_machine_,
      ConfigureStream(_, le_audio::types::LeAudioContextType::LIVE, _, _))
      .Times(1);
  EXPECT_CALL(*mock_le_audio_source_hal_client_, ReconfigurationComplete())
      .Times(1);

  // Update metadata on local audio sink
  UpdateSourceMetadata(AUDIO_SOURCE_MIC);

  // Resume on local audio sink
  ASSERT_NE(unicast_sink_hal_cb_, nullptr);
  do_in_main_thread(
      FROM_HERE,
      base::BindOnce(
          [](LeAudioSinkAudioHalClient::Callbacks* cb) { cb->OnAudioResume(); },
          unicast_sink_hal_cb_));

  /* The above will trigger reconfiguration. After that Audio Hal action
   * is needed to restart the stream */
  SyncOnMainLoop();

  // Resume
  StartStreaming(AUDIO_USAGE_MEDIA, AUDIO_CONTENT_TYPE_MUSIC, group_id,
                 AUDIO_SOURCE_MIC);
  Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
  Mock::VerifyAndClearExpectations(&mock_le_audio_source_hal_client_);
  Mock::VerifyAndClearExpectations(&mock_state_machine_);

  SinkAudioResume();
  do_in_main_thread(
      FROM_HERE,
      base::BindOnce(
          [](LeAudioSinkAudioHalClient::Callbacks* cb) { cb->OnAudioResume(); },
          unicast_sink_hal_cb_));
  SyncOnMainLoop();

  // Verify Data transfer on one audio source and sink cis
  cis_count_out = 1;
  cis_count_in = 1;
  TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 60);

  // Stop
  StopStreaming(group_id);