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

Commit fa4219a1 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
Change-Id: I75c98bebfc270a40801efa8cea1788f30fe728e2
parent 59acd539
Loading
Loading
Loading
Loading
+94 −18
Original line number Diff line number Diff line
@@ -634,11 +634,72 @@ class LeAudioClientImpl : public LeAudioClient {
    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,
                   AudioContexts metadata_context_type) {
    LeAudioDeviceGroup* group = aseGroups_.FindById(group_id);
    auto final_context_type = context_type;

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

    bool result = groupStateMachine_->StartStream(
        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)
      stream_setup_start_timestamp_ =
          bluetooth::common::time_get_os_boottime_us();
@@ -2903,8 +2965,8 @@ class LeAudioClientImpl : public LeAudioClient {
    timeoutMs = osi_property_get_int32(kAudioSuspentKeepIsoAliveTimeoutMsProp,
                                       timeoutMs);

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

    alarm_set_on_mloop(
@@ -2916,9 +2978,9 @@ class LeAudioClientImpl : public LeAudioClient {
  }

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

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

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

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

    auto adjusted_contexts = adjustMetadataContexts(available_contexts);

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

    /* 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)))
            .any())
      return LeAudioContextType::CONVERSATIONAL;

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

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

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

@@ -3311,7 +3375,14 @@ class LeAudioClientImpl : public LeAudioClient {
    bool is_group_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());

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