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

Commit 517d3c37 authored by Łukasz Rymanowski's avatar Łukasz Rymanowski Committed by Gerrit Code Review
Browse files

Merge "leaudio: Fix for context type while VOIP" into main

parents d55154ba 94b61d46
Loading
Loading
Loading
Loading
+48 −31
Original line number Original line Diff line number Diff line
@@ -4543,11 +4543,32 @@ class LeAudioClientImpl : public LeAudioClient {


  BidirectionalPair<AudioContexts> DirectionalRealignMetadataAudioContexts(
  BidirectionalPair<AudioContexts> DirectionalRealignMetadataAudioContexts(
      LeAudioDeviceGroup* group, int remote_direction) {
      LeAudioDeviceGroup* group, int remote_direction) {
    auto remote_other_direction =
        (remote_direction == le_audio::types::kLeAudioDirectionSink
             ? le_audio::types::kLeAudioDirectionSource
             : le_audio::types::kLeAudioDirectionSink);
    auto other_direction_hal =
        (remote_other_direction == le_audio::types::kLeAudioDirectionSource
             ? audio_receiver_state_
             : audio_sender_state_);
    auto is_streaming_other_direction =
        (other_direction_hal == AudioState::STARTED) ||
        (other_direction_hal == AudioState::READY_TO_START);
    auto is_releasing_for_reconfiguration =
        (((audio_receiver_state_ == AudioState::RELEASING) ||
          (audio_sender_state_ == AudioState::RELEASING)) &&
         group->IsPendingConfiguration() &&
         IsDirectionAvailableForCurrentConfiguration(group,
                                                     remote_other_direction));

    // Inject conversational when ringtone is played - this is required for all
    // Inject conversational when ringtone is played - this is required for all
    // the VoIP applications which are not using the telecom API.
    // the VoIP applications which are not using the telecom API.
    if ((remote_direction == le_audio::types::kLeAudioDirectionSink) &&
    constexpr AudioContexts possible_voip_contexts =
        local_metadata_context_types_.source.test(
        LeAudioContextType::RINGTONE | LeAudioContextType::CONVERSATIONAL;
            LeAudioContextType::RINGTONE)) {
    if (local_metadata_context_types_.source.test_any(possible_voip_contexts) &&
        ((remote_direction == le_audio::types::kLeAudioDirectionSink) ||
         (remote_direction == le_audio::types::kLeAudioDirectionSource &&
          is_streaming_other_direction))) {
      /* Simulate, we are already in the call. Sending RINGTONE when there is
      /* Simulate, we are already in the call. Sending RINGTONE when there is
       * no incoming call to accept or reject on TBS could confuse the remote
       * no incoming call to accept or reject on TBS could confuse the remote
       * device and interrupt the stream establish procedure.
       * device and interrupt the stream establish procedure.
@@ -4574,24 +4595,6 @@ class LeAudioClientImpl : public LeAudioClient {
          LeAudioContextType::CONVERSATIONAL);
          LeAudioContextType::CONVERSATIONAL);
    }
    }


    auto remote_other_direction =
        (remote_direction == le_audio::types::kLeAudioDirectionSink
             ? le_audio::types::kLeAudioDirectionSource
             : le_audio::types::kLeAudioDirectionSink);
    auto other_direction_hal =
        (remote_other_direction == le_audio::types::kLeAudioDirectionSource
             ? audio_receiver_state_
             : audio_sender_state_);
    auto is_streaming_other_direction =
        (other_direction_hal == AudioState::STARTED) ||
        (other_direction_hal == AudioState::READY_TO_START);
    auto is_releasing_for_reconfiguration =
        (((audio_receiver_state_ == AudioState::RELEASING) ||
          (audio_sender_state_ == AudioState::RELEASING)) &&
         group->IsPendingConfiguration() &&
         IsDirectionAvailableForCurrentConfiguration(group,
                                                     remote_other_direction));

    BidirectionalPair<AudioContexts> remote_metadata = {
    BidirectionalPair<AudioContexts> remote_metadata = {
        .sink = local_metadata_context_types_.source,
        .sink = local_metadata_context_types_.source,
        .source = local_metadata_context_types_.sink};
        .source = local_metadata_context_types_.sink};
@@ -4601,6 +4604,9 @@ class LeAudioClientImpl : public LeAudioClient {
      remote_metadata.sink.unset(LeAudioContextType::RINGTONE);
      remote_metadata.sink.unset(LeAudioContextType::RINGTONE);
    }
    }


    auto is_ongoing_call_on_other_direction =
        is_streaming_other_direction && (IsInVoipCall() || IsInCall());

    LOG_DEBUG("local_metadata_context_types_.source= %s",
    LOG_DEBUG("local_metadata_context_types_.source= %s",
              ToString(local_metadata_context_types_.source).c_str());
              ToString(local_metadata_context_types_.source).c_str());
    LOG_DEBUG("local_metadata_context_types_.sink= %s",
    LOG_DEBUG("local_metadata_context_types_.sink= %s",
@@ -4617,6 +4623,8 @@ class LeAudioClientImpl : public LeAudioClient {
              (is_streaming_other_direction ? "True" : "False"));
              (is_streaming_other_direction ? "True" : "False"));
    LOG_DEBUG("is_releasing_for_reconfiguration= %s",
    LOG_DEBUG("is_releasing_for_reconfiguration= %s",
              (is_releasing_for_reconfiguration ? "True" : "False"));
              (is_releasing_for_reconfiguration ? "True" : "False"));
    LOG_DEBUG("is_ongoing_call_on_other_direction=%s",
              (is_ongoing_call_on_other_direction ? "True" : "False"));


    if (remote_metadata.get(remote_other_direction)
    if (remote_metadata.get(remote_other_direction)
            .test_any(kLeAudioContextAllBidir) &&
            .test_any(kLeAudioContextAllBidir) &&
@@ -4636,6 +4644,14 @@ class LeAudioClientImpl : public LeAudioClient {
      LOG_DEBUG(
      LOG_DEBUG(
          "Aligning the other direction remote metadata to add this direction "
          "Aligning the other direction remote metadata to add this direction "
          "context");
          "context");

      if (is_ongoing_call_on_other_direction) {
        /* Other direction is streaming and is in call */
        remote_metadata.get(remote_direction)
            .unset_all(kLeAudioContextAllBidir);
        remote_metadata.get(remote_direction)
            .set(LeAudioContextType::CONVERSATIONAL);
      } else {
        if (!is_streaming_other_direction) {
        if (!is_streaming_other_direction) {
          // Do not take the obsolete metadata
          // Do not take the obsolete metadata
          remote_metadata.get(remote_other_direction).clear();
          remote_metadata.get(remote_other_direction).clear();
@@ -4648,6 +4664,7 @@ class LeAudioClientImpl : public LeAudioClient {
            .set_all(remote_metadata.get(remote_direction) &
            .set_all(remote_metadata.get(remote_direction) &
                     ~kLeAudioContextAllRemoteSinkOnly);
                     ~kLeAudioContextAllRemoteSinkOnly);
      }
      }
    }
    LOG_DEBUG("remote_metadata.source= %s",
    LOG_DEBUG("remote_metadata.source= %s",
              ToString(remote_metadata.source).c_str());
              ToString(remote_metadata.source).c_str());
    LOG_DEBUG("remote_metadata.sink= %s",
    LOG_DEBUG("remote_metadata.sink= %s",
+89 −1
Original line number Original line Diff line number Diff line
@@ -5377,6 +5377,9 @@ TEST_F(UnicastTest, TwoEarbudsStreamingContextSwitchReconfigure) {
  fake_osi_alarm_set_on_mloop_.cb(fake_osi_alarm_set_on_mloop_.data);
  fake_osi_alarm_set_on_mloop_.cb(fake_osi_alarm_set_on_mloop_.data);
  Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);
  Mock::VerifyAndClearExpectations(&mock_audio_hal_client_callbacks_);


  // SetInCall is used by GTBS - and only then we can expect CCID to be set.
  LeAudioClient::Get()->SetInCall(true);

  // Conversational is a bidirectional scenario so expect GTBS CCID
  // Conversational is a bidirectional scenario so expect GTBS CCID
  // in the metadata for both directions. Can be called twice when one
  // in the metadata for both directions. Can be called twice when one
  // direction resume after the other and metadata is updated.
  // direction resume after the other and metadata is updated.
@@ -5396,8 +5399,10 @@ TEST_F(UnicastTest, TwoEarbudsStreamingContextSwitchReconfigure) {
  cis_count_out = 2;
  cis_count_out = 2;
  cis_count_in = 2;
  cis_count_in = 2;
  TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 40);
  TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 40);

  LeAudioClient::Get()->SetInCall(false);
  // Stop
  // Stop
  StopStreaming(group_id);
  StopStreaming(group_id, true);


  // Switch back to MEDIA
  // Switch back to MEDIA
  ccids = {.sink = {gmcs_ccid}, .source = {}};
  ccids = {.sink = {gmcs_ccid}, .source = {}};
@@ -5417,6 +5422,87 @@ TEST_F(UnicastTest, TwoEarbudsStreamingContextSwitchReconfigure) {
  Mock::VerifyAndClearExpectations(&mock_le_audio_source_hal_client_);
  Mock::VerifyAndClearExpectations(&mock_le_audio_source_hal_client_);
}
}


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

  /*
   * Scenario
   * 1. Configure stream for the VOIP
   * 2. Verify CONVERSATIONAL metadata and context is used.
   * 3. Resume LocalSink
   * 4. Make sure there is no change of the metadata and context
   */

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

  // 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*/);

  constexpr int gtbs_ccid = 2;

  ON_CALL(mock_csis_client_module_, GetDesiredSize(group_id))
      .WillByDefault(Invoke([&](int group_id) { return 2; }));
  LeAudioClient::Get()->SetCcidInformation(gtbs_ccid, 2 /* Phone */);
  LeAudioClient::Get()->GroupSetActive(group_id);
  SyncOnMainLoop();

  // VOIP not using Telecom API has no ccids.
  types::BidirectionalPair<std::vector<uint8_t>> ccids = {.sink = {},
                                                          .source = {}};
  EXPECT_CALL(
      mock_state_machine_,
      StartStream(_, types::LeAudioContextType::CONVERSATIONAL, _, ccids))
      .Times(AtLeast(1));

  UpdateLocalSourceMetadata(AUDIO_USAGE_VOICE_COMMUNICATION,
                            AUDIO_CONTENT_TYPE_SPEECH);
  UpdateLocalSinkMetadata(AUDIO_SOURCE_MIC);

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

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

  // Verify Data transfer are sending. The LocalSink is not yet resumed.
  uint8_t cis_count_out = 2;
  uint8_t cis_count_in = 0;
  TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920, 0);

  types::BidirectionalPair<types::AudioContexts> contexts = {
      .sink = types::AudioContexts(types::LeAudioContextType::CONVERSATIONAL),
      .source =
          types::AudioContexts(types::LeAudioContextType::CONVERSATIONAL)};
  EXPECT_CALL(mock_state_machine_,
              StartStream(_, types::LeAudioContextType::CONVERSATIONAL,
                          contexts, ccids))
      .Times(AtLeast(1));

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

TEST_F(UnicastTest, TwoReconfigureAndVerifyEnableContextType) {
TEST_F(UnicastTest, TwoReconfigureAndVerifyEnableContextType) {
  uint8_t group_size = 2;
  uint8_t group_size = 2;
  int group_id = 2;
  int group_id = 2;
@@ -5509,6 +5595,8 @@ TEST_F(UnicastTest, TwoReconfigureAndVerifyEnableContextType) {
                          conversiational_contexts, ccids))
                          conversiational_contexts, ccids))
      .Times(AtLeast(1));
      .Times(AtLeast(1));


  LeAudioClient::Get()->SetInCall(true);

  LocalAudioSourceResume(true);
  LocalAudioSourceResume(true);
  SyncOnMainLoop();
  SyncOnMainLoop();