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

Commit 381e3089 authored by Łukasz Rymanowski's avatar Łukasz Rymanowski
Browse files

leaudio: Improve handling recording while media stream

We are doing 2 things in this patch
1. We allow to decide if Android should send multiple contexts types in
   the Metadata for the enable command.
   It could happen if e.g. media and recorder are enabled.
   To enable it please set persist.bluetooth.leaudio.allow.multiple.contexts
   which by default is false.
2. Fixing Media and Recording scenario - make sure that there is no
   reconfiguration to Media when Recording is enabled

Bug: 241746141
Test: atest BluetoothInstrumentationTests
Tag: #feature
Merged-In: I75c98bebfc270a40801efa8cea1788f30fe728e2
Change-Id: I75c98bebfc270a40801efa8cea1788f30fe728e2
(cherry picked from commit fa4219a1)
parent ceda8f90
Loading
Loading
Loading
Loading
+94 −18
Original line number Original line Diff line number Diff line
@@ -634,11 +634,72 @@ class LeAudioClientImpl : public LeAudioClient {
    group_remove_node(group, address, true);
    group_remove_node(group, address, true);
  }
  }


  AudioContexts adjustMetadataContexts(AudioContexts metadata_context_type) {
    /* This function takes already filtered contexts which we are plannig to use
     * in the Enable or UpdateMetadata command.
     * Note we are not changing stream configuration here, but just the list of
     * the contexts in the Metadata which will be provide to remote side.
     * Ideally, we should send all the bits we have, but not all headsets like
     * it.
     */
    if (osi_property_get_bool(kAllowMultipleContextsInMetadata, false)) {
      return metadata_context_type;
    }

    LOG_DEBUG("Converting to single context type: %lu",
              metadata_context_type.to_ulong());

    if (metadata_context_type.to_ulong() &
        static_cast<uint16_t>(LeAudioContextType::CONVERSATIONAL)) {
      return static_cast<uint16_t>(LeAudioContextType::CONVERSATIONAL);
    }
    if (metadata_context_type.to_ulong() &
        static_cast<uint16_t>(LeAudioContextType::GAME)) {
      return static_cast<uint16_t>(LeAudioContextType::GAME);
    }
    if (metadata_context_type.to_ulong() &
        static_cast<uint16_t>(LeAudioContextType::EMERGENCYALARM)) {
      return static_cast<uint16_t>(LeAudioContextType::EMERGENCYALARM);
    }
    if (metadata_context_type.to_ulong() &
        static_cast<uint16_t>(LeAudioContextType::ALERTS)) {
      return static_cast<uint16_t>(LeAudioContextType::ALERTS);
    }
    if (metadata_context_type.to_ulong() &
        static_cast<uint16_t>(LeAudioContextType::RINGTONE)) {
      return static_cast<uint16_t>(LeAudioContextType::RINGTONE);
    }
    if (metadata_context_type.to_ulong() &
        static_cast<uint16_t>(LeAudioContextType::VOICEASSISTANTS)) {
      return static_cast<uint16_t>(LeAudioContextType::VOICEASSISTANTS);
    }
    if (metadata_context_type.to_ulong() &
        static_cast<uint16_t>(LeAudioContextType::INSTRUCTIONAL)) {
      return static_cast<uint16_t>(LeAudioContextType::INSTRUCTIONAL);
    }
    if (metadata_context_type.to_ulong() &
        static_cast<uint16_t>(LeAudioContextType::NOTIFICATIONS)) {
      return static_cast<uint16_t>(LeAudioContextType::NOTIFICATIONS);
    }
    if (metadata_context_type.to_ulong() &
        static_cast<uint16_t>(LeAudioContextType::LIVE)) {
      return static_cast<uint16_t>(LeAudioContextType::LIVE);
    }
    if (metadata_context_type.to_ulong() &
        static_cast<uint16_t>(LeAudioContextType::MEDIA)) {
      return static_cast<uint16_t>(LeAudioContextType::MEDIA);
    }

    return static_cast<uint16_t>(LeAudioContextType::UNSPECIFIED);
  }

  bool GroupStream(const int group_id, const uint16_t context_type,
  bool GroupStream(const int group_id, const uint16_t context_type,
                   AudioContexts metadata_context_type) {
                   AudioContexts metadata_context_type) {
    LeAudioDeviceGroup* group = aseGroups_.FindById(group_id);
    LeAudioDeviceGroup* group = aseGroups_.FindById(group_id);
    auto final_context_type = context_type;
    auto final_context_type = context_type;


    auto adjusted_metadata_context_type =
        adjustMetadataContexts(metadata_context_type);
    DLOG(INFO) << __func__;
    DLOG(INFO) << __func__;
    if (context_type >= static_cast<uint16_t>(LeAudioContextType::RFU)) {
    if (context_type >= static_cast<uint16_t>(LeAudioContextType::RFU)) {
      LOG(ERROR) << __func__ << ", stream context type is not supported: "
      LOG(ERROR) << __func__ << ", stream context type is not supported: "
@@ -679,7 +740,8 @@ class LeAudioClientImpl : public LeAudioClient {


    bool result = groupStateMachine_->StartStream(
    bool result = groupStateMachine_->StartStream(
        group, static_cast<LeAudioContextType>(final_context_type),
        group, static_cast<LeAudioContextType>(final_context_type),
        metadata_context_type, GetAllCcids(metadata_context_type));
        adjusted_metadata_context_type,
        GetAllCcids(adjusted_metadata_context_type));
    if (result)
    if (result)
      stream_setup_start_timestamp_ =
      stream_setup_start_timestamp_ =
          bluetooth::common::time_get_os_boottime_us();
          bluetooth::common::time_get_os_boottime_us();
@@ -2904,8 +2966,8 @@ class LeAudioClientImpl : public LeAudioClient {
    timeoutMs = osi_property_get_int32(kAudioSuspentKeepIsoAliveTimeoutMsProp,
    timeoutMs = osi_property_get_int32(kAudioSuspentKeepIsoAliveTimeoutMsProp,
                                       timeoutMs);
                                       timeoutMs);


    DLOG(INFO) << __func__
    LOG_DEBUG("Stream suspend_timeout_ started: %d ms",
               << " Stream suspend_timeout_ started: " << suspend_timeout_;
              static_cast<int>(timeoutMs));
    if (alarm_is_scheduled(suspend_timeout_)) alarm_cancel(suspend_timeout_);
    if (alarm_is_scheduled(suspend_timeout_)) alarm_cancel(suspend_timeout_);


    alarm_set_on_mloop(
    alarm_set_on_mloop(
@@ -2917,9 +2979,9 @@ class LeAudioClientImpl : public LeAudioClient {
  }
  }


  void OnAudioSinkSuspend() {
  void OnAudioSinkSuspend() {
    DLOG(INFO) << __func__
    LOG_DEBUG(" IN: audio_receiver_state_: %s,  audio_sender_state_: %s",
               << " IN: audio_receiver_state_: " << audio_receiver_state_
              ToString(audio_receiver_state_).c_str(),
               << " audio_sender_state_: " << audio_sender_state_;
              ToString(audio_sender_state_).c_str());


    /* Note: This callback is from audio hal driver.
    /* Note: This callback is from audio hal driver.
     * Bluetooth peer is a Sink for Audio Framework.
     * Bluetooth peer is a Sink for Audio Framework.
@@ -3061,9 +3123,9 @@ class LeAudioClientImpl : public LeAudioClient {
  }
  }


  void OnAudioSourceSuspend() {
  void OnAudioSourceSuspend() {
    DLOG(INFO) << __func__
    LOG_DEBUG(" IN: audio_receiver_state_: %s,  audio_sender_state_: %s",
               << " IN: audio_receiver_state_: " << audio_receiver_state_
              ToString(audio_receiver_state_).c_str(),
               << " audio_sender_state_: " << audio_sender_state_;
              ToString(audio_sender_state_).c_str());


    /* Note: This callback is from audio hal driver.
    /* Note: This callback is from audio hal driver.
     * Bluetooth peer is a Source for Audio Framework.
     * Bluetooth peer is a Source for Audio Framework.
@@ -3224,20 +3286,22 @@ class LeAudioClientImpl : public LeAudioClient {
      return LeAudioContextType::UNSPECIFIED;
      return LeAudioContextType::UNSPECIFIED;
    }
    }


    auto adjusted_contexts = adjustMetadataContexts(available_contexts);

    using T = std::underlying_type<LeAudioContextType>::type;
    using T = std::underlying_type<LeAudioContextType>::type;


    /* Mini policy. Voice is prio 1, game prio 2, media is prio 3 */
    /* Mini policy. Voice is prio 1, game prio 2, media is prio 3 */
    if ((available_contexts &
    if ((adjusted_contexts &
         AudioContexts(static_cast<T>(LeAudioContextType::CONVERSATIONAL)))
         AudioContexts(static_cast<T>(LeAudioContextType::CONVERSATIONAL)))
            .any())
            .any())
      return LeAudioContextType::CONVERSATIONAL;
      return LeAudioContextType::CONVERSATIONAL;


    if ((available_contexts &
    if ((adjusted_contexts &
         AudioContexts(static_cast<T>(LeAudioContextType::GAME)))
         AudioContexts(static_cast<T>(LeAudioContextType::GAME)))
            .any())
            .any())
      return LeAudioContextType::GAME;
      return LeAudioContextType::GAME;


    if ((available_contexts &
    if ((adjusted_contexts &
         AudioContexts(static_cast<T>(LeAudioContextType::RINGTONE)))
         AudioContexts(static_cast<T>(LeAudioContextType::RINGTONE)))
            .any()) {
            .any()) {
      if (!in_call_) {
      if (!in_call_) {
@@ -3246,7 +3310,7 @@ class LeAudioClientImpl : public LeAudioClient {
      return LeAudioContextType::RINGTONE;
      return LeAudioContextType::RINGTONE;
    }
    }


    if ((available_contexts &
    if ((adjusted_contexts &
         AudioContexts(static_cast<T>(LeAudioContextType::MEDIA)))
         AudioContexts(static_cast<T>(LeAudioContextType::MEDIA)))
            .any())
            .any())
      return LeAudioContextType::MEDIA;
      return LeAudioContextType::MEDIA;
@@ -3254,8 +3318,8 @@ class LeAudioClientImpl : public LeAudioClient {
    /*TODO do something smarter here */
    /*TODO do something smarter here */
    /* Get context for the first non-zero bit */
    /* Get context for the first non-zero bit */
    uint16_t context_type = 0b1;
    uint16_t context_type = 0b1;
    while (available_contexts != 0b1) {
    while (adjusted_contexts != 0b1) {
      available_contexts = available_contexts >> 1;
      adjusted_contexts = adjusted_contexts >> 1;
      context_type = context_type << 1;
      context_type = context_type << 1;
    }
    }


@@ -3312,7 +3376,14 @@ class LeAudioClientImpl : public LeAudioClient {
    bool is_group_streaming =
    bool is_group_streaming =
        (group->GetTargetState() == AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
        (group->GetTargetState() == AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);


    metadata_context_types_ = GetAllowedAudioContextsFromSourceMetadata(
    if (audio_receiver_state_ == AudioState::STARTED) {
      /* If the receiver is starte. Take into account current context type */
      metadata_context_types_ = adjustMetadataContexts(metadata_context_types_);
    } else {
      metadata_context_types_ = 0;
    }

    metadata_context_types_ |= GetAllowedAudioContextsFromSourceMetadata(
        source_metadata, group->GetActiveContexts());
        source_metadata, group->GetActiveContexts());


    if (stack_config_get_interface()
    if (stack_config_get_interface()
@@ -3751,9 +3822,12 @@ class LeAudioClientImpl : public LeAudioClient {
        stream_setup_start_timestamp_ = 0;
        stream_setup_start_timestamp_ = 0;
        if (group && group->IsPendingConfiguration()) {
        if (group && group->IsPendingConfiguration()) {
          SuspendedForReconfiguration();
          SuspendedForReconfiguration();
          auto adjusted_metedata_context_type =
              adjustMetadataContexts(metadata_context_types_);
          if (groupStateMachine_->ConfigureStream(
          if (groupStateMachine_->ConfigureStream(
                  group, configuration_context_type_, metadata_context_types_,
                  group, configuration_context_type_,
                  GetAllCcids(metadata_context_types_))) {
                  adjusted_metedata_context_type,
                  GetAllCcids(adjusted_metedata_context_type))) {
            /* If configuration succeed wait for new status. */
            /* If configuration succeed wait for new status. */
            return;
            return;
          }
          }
@@ -3788,6 +3862,8 @@ class LeAudioClientImpl : public LeAudioClient {
  LeAudioGroupStateMachine* groupStateMachine_;
  LeAudioGroupStateMachine* groupStateMachine_;
  int active_group_id_;
  int active_group_id_;
  LeAudioContextType configuration_context_type_;
  LeAudioContextType configuration_context_type_;
  static constexpr char kAllowMultipleContextsInMetadata[] =
      "persist.bluetooth.leaudio.allow.multiple.contexts";
  AudioContexts metadata_context_types_;
  AudioContexts metadata_context_types_;
  uint64_t stream_setup_start_timestamp_;
  uint64_t stream_setup_start_timestamp_;
  uint64_t stream_setup_end_timestamp_;
  uint64_t stream_setup_end_timestamp_;