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

Commit 588637ec authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "leaudio: Allow unidirectional Assistant." into main

parents 484eb019 bd74936e
Loading
Loading
Loading
Loading
+51 −6
Original line number Diff line number Diff line
@@ -332,8 +332,9 @@ class LeAudioClientImpl : public LeAudioClient {
    }

    /* Choose the right configuration context */
    auto new_configuration_context =
        ChooseConfigurationContextType(local_metadata_context_types_.source);
    auto new_configuration_context = AdjustForVoiceAssistant(
        group,
        ChooseConfigurationContextType(local_metadata_context_types_.source));

    log::debug("new_configuration_context= {}",
               ToString(new_configuration_context));
@@ -4953,6 +4954,50 @@ class LeAudioClientImpl : public LeAudioClient {
    return remote_metadata;
  }

  LeAudioContextType AdjustForVoiceAssistant(
      LeAudioDeviceGroup* group, LeAudioContextType new_configuration_context) {
    if (!IS_FLAG_ENABLED(le_audio_support_unidirectional_voice_assistant)) {
      log::debug(
          "Flag le_audio_support_unidirectional_voice_assistant NOT enabled");
      return new_configuration_context;
    }

    /* Some remote devices expect VOICE ASSISTANT to be unidirectional Phone is
     * Source and Earbuds are Sink */
    if (new_configuration_context != LeAudioContextType::VOICEASSISTANTS) {
      return new_configuration_context;
    }

    auto sink_supported_contexts = group->GetSupportedContexts(
        bluetooth::le_audio::types::kLeAudioDirectionSink);
    auto source_supported_contexts = group->GetSupportedContexts(
        bluetooth::le_audio::types::kLeAudioDirectionSource);

    log::debug(" group_id: {}, sink_supported: {}, source_supported {}",
               group->group_id_, ToString(sink_supported_contexts),
               ToString(source_supported_contexts));
    if (sink_supported_contexts.test(LeAudioContextType::VOICEASSISTANTS) &&
        source_supported_contexts.test(LeAudioContextType::VOICEASSISTANTS)) {
      return new_configuration_context;
    }

    if (sink_supported_contexts.test(LeAudioContextType::VOICEASSISTANTS)) {
      log::info(
          "group_id {} supports only Sink direction for Voice Assistant. "
          "Selecting configurarion context type {}",
          group->group_id_, ToString(LeAudioContextType::INSTRUCTIONAL));

      return LeAudioContextType::INSTRUCTIONAL;
    }

    log::warn(
        " group_id: {},  unexpected configuration, sink_supported: {}, "
        "source_supported {}",
        group->group_id_, ToString(sink_supported_contexts),
        ToString(source_supported_contexts));
    return new_configuration_context;
  }

  /* Return true if stream is started */
  bool ReconfigureOrUpdateRemote(LeAudioDeviceGroup* group,
                                 int remote_direction) {
@@ -4972,8 +5017,8 @@ class LeAudioClientImpl : public LeAudioClient {
                override_contexts.to_string());

      /* Choose the right configuration context */
      auto new_configuration_context =
          ChooseConfigurationContextType(override_contexts);
      auto new_configuration_context = AdjustForVoiceAssistant(
          group, ChooseConfigurationContextType(override_contexts));

      log::debug("new_configuration_context= {}.",
                 ToString(new_configuration_context));
@@ -4993,8 +5038,8 @@ class LeAudioClientImpl : public LeAudioClient {

    /* Choose the right configuration context */
    auto config_context_candids = get_bidirectional(remote_metadata);
    auto new_config_context =
        ChooseConfigurationContextType(config_context_candids);
    auto new_config_context = AdjustForVoiceAssistant(
        group, ChooseConfigurationContextType(config_context_candids));
    log::debug("config_context_candids= {}, new_config_context= {}",
               ToString(config_context_candids), ToString(new_config_context));

+141 −0
Original line number Diff line number Diff line
@@ -5923,6 +5923,147 @@ TEST_F(UnicastTest, SpeakerStreamingNonDefault) {
  LocalAudioSourceResume();
}

TEST_F_WITH_FLAGS(UnicastTest, TestUnidirectionalVoiceAssistant_Sink,
                  REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(
                      TEST_BT,
                      le_audio_support_unidirectional_voice_assistant))) {
  const RawAddress test_address0 = GetTestAddress(0);
  int group_id = bluetooth::groups::kGroupUnknown;

  /**
   * Scenario test steps
   * 1. Configure group to support VOICEASSISTANT only on SINK
   * 2. Start stream
   * 5. Verify that Unidirectional VOICEASSISTANT has been created
   */

  available_snk_context_types_ = (types::LeAudioContextType::VOICEASSISTANTS |
                                  types::LeAudioContextType::MEDIA |
                                  types::LeAudioContextType::UNSPECIFIED)
                                     .value();
  supported_snk_context_types_ = available_snk_context_types_;

  available_src_context_types_ =
      (types::LeAudioContextType::LIVE | types::LeAudioContextType::UNSPECIFIED)
          .value();
  supported_src_context_types_ = available_src_context_types_;

  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_,
              OnConnectionState(ConnectionState::CONNECTED, test_address0))
      .Times(1);
  EXPECT_CALL(mock_audio_hal_client_callbacks_,
              OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
      .WillOnce(DoAll(SaveArg<1>(&group_id)));

  types::BidirectionalPair<types::AudioContexts> metadata_contexts = {
      .sink = types::AudioContexts(types::LeAudioContextType::VOICEASSISTANTS),
      .source = types::AudioContexts()};
  EXPECT_CALL(mock_state_machine_,
              StartStream(_, types::LeAudioContextType::INSTRUCTIONAL,
                          metadata_contexts, _))
      .Times(1);
  ConnectLeAudio(test_address0);
  ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);

  // Start streaming
  uint8_t cis_count_out = 1;
  uint8_t cis_count_in = 0;

  // Audio sessions are started only when device gets active
  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();

  StartStreaming(AUDIO_USAGE_ASSISTANT, AUDIO_CONTENT_TYPE_UNKNOWN, group_id);

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

  // Verify Data transfer on one local audio source cis
  TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);
  SyncOnMainLoop();
}

TEST_F_WITH_FLAGS(UnicastTest, TestUnidirectionalVoiceAssistant_Source,
                  REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(
                      TEST_BT,
                      le_audio_support_unidirectional_voice_assistant))) {
  const RawAddress test_address0 = GetTestAddress(0);
  int group_id = bluetooth::groups::kGroupUnknown;

  /**
   * Scenario test steps
   * 1. Configure group to support VOICEASSISTANT only on SOURCE
   * 2. Start stream
   * 5. Verify that bi-direction VOICEASSISTANT has been created
   */

  available_snk_context_types_ = (types::LeAudioContextType::MEDIA |
                                  types::LeAudioContextType::UNSPECIFIED)
                                     .value();
  supported_snk_context_types_ = available_snk_context_types_;

  available_src_context_types_ =
      (types::LeAudioContextType::VOICEASSISTANTS |
       types::LeAudioContextType::LIVE | types::LeAudioContextType::UNSPECIFIED)
          .value();
  supported_src_context_types_ = available_src_context_types_;

  SetSampleDatabaseEarbudsValid(
      1, test_address0, codec_spec_conf::kLeAudioLocationFrontLeftOfCenter,
      codec_spec_conf::kLeAudioLocationFrontLeftOfCenter, 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*/, 2 /*set_size*/,
      1 /*rank*/);
  EXPECT_CALL(mock_audio_hal_client_callbacks_,
              OnConnectionState(ConnectionState::CONNECTED, test_address0))
      .Times(1);
  EXPECT_CALL(mock_audio_hal_client_callbacks_,
              OnGroupNodeStatus(test_address0, _, GroupNodeStatus::ADDED))
      .WillOnce(DoAll(SaveArg<1>(&group_id)));

  types::BidirectionalPair<types::AudioContexts> metadata_contexts = {
      .sink = types::AudioContexts(types::LeAudioContextType::UNSPECIFIED),
      .source =
          types::AudioContexts(types::LeAudioContextType::VOICEASSISTANTS)};
  EXPECT_CALL(mock_state_machine_,
              StartStream(_, types::LeAudioContextType::VOICEASSISTANTS,
                          metadata_contexts, _))
      .Times(1);
  ConnectLeAudio(test_address0);
  ASSERT_NE(group_id, bluetooth::groups::kGroupUnknown);

  // Start streaming
  uint8_t cis_count_out = 1;
  uint8_t cis_count_in = 1;

  // Audio sessions are started only when device gets active
  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();

  StartStreaming(AUDIO_USAGE_ASSISTANT, AUDIO_CONTENT_TYPE_UNKNOWN, group_id,
                 AUDIO_SOURCE_VOICE_RECOGNITION);

  // Verify Data transfer on one local audio source cis
  TestAudioDataTransfer(group_id, cis_count_out, cis_count_in, 1920);

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

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