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

Commit 064c98b7 authored by Jakub Pawłowski's avatar Jakub Pawłowski Committed by Gerrit Code Review
Browse files

Merge "LeAudio: Add missing direction contexts for metadata passing"

parents c93419c7 faf04238
Loading
Loading
Loading
Loading
+130 −135
Original line number Diff line number Diff line
@@ -314,8 +314,7 @@ class LeAudioClientImpl : public LeAudioClient {

    LOG_DEBUG("new_configuration_context= %s",
              ToString(new_configuration_context).c_str());
    ReconfigureOrUpdateMetadata(group, new_configuration_context,
                                metadata_context_types_.sink);
    ReconfigureOrUpdateMetadata(group, new_configuration_context);
  }

  void StartVbcCloseTimeout() {
@@ -792,13 +791,12 @@ class LeAudioClientImpl : public LeAudioClient {
    return AudioContexts(LeAudioContextType::UNSPECIFIED);
  }

  bool GroupStream(const int group_id, LeAudioContextType context_type,
                   AudioContexts metadata_context_type) {
  bool GroupStream(
      const int group_id, LeAudioContextType context_type,
      const BidirectionalPair<AudioContexts>& metadata_context_types) {
    LeAudioDeviceGroup* group = aseGroups_.FindById(group_id);
    auto final_context_type = context_type;

    auto adjusted_metadata_context_type =
        ChooseMetadataContextType(metadata_context_type);
    DLOG(INFO) << __func__;
    if (context_type >= LeAudioContextType::RFU) {
      LOG(ERROR) << __func__ << ", stream context type is not supported: "
@@ -851,17 +849,21 @@ class LeAudioClientImpl : public LeAudioClient {
          bluetooth::common::time_get_os_boottime_us();
    }

    BidirectionalPair<std::vector<uint8_t>> ccids = {
        .sink = ContentControlIdKeeper::GetInstance()->GetAllCcids(
            metadata_context_types.sink),
        .source = ContentControlIdKeeper::GetInstance()->GetAllCcids(
            metadata_context_types.source)};
    bool result = groupStateMachine_->StartStream(
        group, final_context_type, adjusted_metadata_context_type,
        ContentControlIdKeeper::GetInstance()->GetAllCcids(
            adjusted_metadata_context_type));
        group, final_context_type, metadata_context_types, ccids);

    return result;
  }

  void GroupStream(const int group_id, const uint16_t context_type) override {
    GroupStream(group_id, LeAudioContextType(context_type),
                AudioContexts(context_type));
    BidirectionalPair<AudioContexts> initial_contexts = {
        AudioContexts(context_type), AudioContexts(context_type)};
    GroupStream(group_id, LeAudioContextType(context_type), initial_contexts);
  }

  void GroupSuspend(const int group_id) override {
@@ -3239,7 +3241,7 @@ class LeAudioClientImpl : public LeAudioClient {
      return true;
    }
    return GroupStream(active_group_id_, configuration_context_type_,
                       get_bidirectional(metadata_context_types_));
                       metadata_context_types_);
  }

  void OnAudioSuspend() {
@@ -3707,40 +3709,14 @@ class LeAudioClientImpl : public LeAudioClient {
              ToString(group->GetState()).c_str(),
              ToString(group->GetTargetState()).c_str());

    auto new_metadata_context_types_ = AudioContexts();

    /* If the local sink is started, ready to start or any direction is
     * reconfiguring to start sit remote source configuration, then take
     * into the account current context type. If the metadata seem
     * invalid, keep the old one, but verify against the availability.
     * Otherwise start empty and add the tracks contexts.
     */
    auto is_releasing_for_reconfiguration =
        (((audio_receiver_state_ == AudioState::RELEASING) ||
          (audio_sender_state_ == AudioState::RELEASING)) &&
         group->IsPendingConfiguration() &&
         IsDirectionAvailableForCurrentConfiguration(
             group, le_audio::types::kLeAudioDirectionSource));
    if (is_releasing_for_reconfiguration ||
        (audio_receiver_state_ == AudioState::STARTED) ||
        (audio_receiver_state_ == AudioState::READY_TO_START)) {
      LOG_DEBUG("Other direction is streaming. Taking its contexts %s",
                ToString(metadata_context_types_.source).c_str());
      new_metadata_context_types_ =
          ChooseMetadataContextType(metadata_context_types_.source);

    } else if (source_metadata.empty()) {
      LOG_DEBUG("Not a valid sink metadata update. Keeping the old contexts");
      new_metadata_context_types_ &= group->GetAvailableContexts();

    } else {
      LOG_DEBUG("No other direction is streaming. Start with empty contexts.");
    }
    // Make sure the other direction is tested against the available contexts
    metadata_context_types_.source &= group->GetAvailableContexts();

    /* Set the remote sink metadata context from the playback tracks metadata */
    metadata_context_types_.sink = GetAllowedAudioContextsFromSourceMetadata(
        source_metadata, group->GetAvailableContexts());
    new_metadata_context_types_ |= metadata_context_types_.sink;
    metadata_context_types_.sink =
        ChooseMetadataContextType(metadata_context_types_.sink);

    if (stack_config_get_interface()
            ->get_pts_force_le_audio_multiple_contexts_metadata()) {
@@ -3764,19 +3740,47 @@ class LeAudioClientImpl : public LeAudioClient {
      LOG_DEBUG("new_configuration_context= %s.",
                ToString(new_configuration_context).c_str());
      GroupStream(active_group_id_, new_configuration_context,
                  metadata_context_types_.sink);
                  metadata_context_types_);
      return;
    }

    if (new_metadata_context_types_.none()) {
      LOG_WARN("invalid/unknown context metadata, using 'UNSPECIFIED' instead");
      new_metadata_context_types_ =
    // We expect at least some context when remote sink gets enabled
    if (metadata_context_types_.sink.none()) {
      LOG_WARN(
          "invalid/unknown sink context metadata, using 'UNSPECIFIED' instead");
      metadata_context_types_.sink =
          AudioContexts(LeAudioContextType::UNSPECIFIED);
    }

    /* Choose the right configuration context */
    /* Start with only this direction context metadata */
    auto configuration_context_candidates = metadata_context_types_.sink;

    /* If the local sink is started, ready to start or any direction is
     * reconfiguring when the remote sink configuration is active, then take
     * into the account current context type for this direction when
     * configuration context is selected.
     */
    auto is_releasing_for_reconfiguration =
        (((audio_receiver_state_ == AudioState::RELEASING) ||
          (audio_sender_state_ == AudioState::RELEASING)) &&
         group->IsPendingConfiguration() &&
         IsDirectionAvailableForCurrentConfiguration(
             group, le_audio::types::kLeAudioDirectionSource));
    if (is_releasing_for_reconfiguration ||
        (audio_receiver_state_ == AudioState::STARTED) ||
        (audio_receiver_state_ == AudioState::READY_TO_START)) {
      LOG_DEBUG("Other direction is streaming. Taking its contexts %s",
                ToString(metadata_context_types_.source).c_str());
      configuration_context_candidates =
          ChooseMetadataContextType(get_bidirectional(metadata_context_types_));
    }
    LOG_DEBUG("configuration_context_candidates= %s",
              ToString(configuration_context_candidates).c_str());

    auto new_configuration_context =
        ChooseConfigurationContextType(new_metadata_context_types_);
        ChooseConfigurationContextType(configuration_context_candidates);
    LOG_DEBUG("new_configuration_context= %s",
              ToString(new_configuration_context).c_str());

    /* For the following contexts we don't actually need HQ audio:
     * LeAudioContextType::NOTIFICATIONS
@@ -3791,19 +3795,21 @@ class LeAudioClientImpl : public LeAudioClient {
        LeAudioContextType::NOTIFICATIONS | LeAudioContextType::SOUNDEFFECTS |
        LeAudioContextType::INSTRUCTIONAL | LeAudioContextType::ALERTS |
        LeAudioContextType::EMERGENCYALARM;
    if ((new_metadata_context_types_ & ~no_reconfigure_contexts).none() &&
    if ((configuration_context_candidates & ~no_reconfigure_contexts).none() &&
        IsDirectionAvailableForCurrentConfiguration(
            group, le_audio::types::kLeAudioDirectionSink)) {
      LOG_INFO(
          "There is no need to reconfigure for the sonification events. Keep "
          "the configuration unchanged.");
          "There is no need to reconfigure for the sonification events, "
          "staying with the existing configuration context of %s",
          ToString(configuration_context_type_).c_str());
      new_configuration_context = configuration_context_type_;
    }

    LOG_DEBUG("new_configuration_context= %s",
              ToString(new_configuration_context).c_str());
    ReconfigureOrUpdateMetadata(group, new_configuration_context,
                                std::move(new_metadata_context_types_));
    LOG_DEBUG("metadata_context_types_.sink= %s",
              ToString(metadata_context_types_.sink).c_str());
    LOG_DEBUG("metadata_context_types_.source= %s",
              ToString(metadata_context_types_.source).c_str());
    ReconfigureOrUpdateMetadata(group, new_configuration_context);
  }

  void OnLocalAudioSinkMetadataUpdate(
@@ -3824,39 +3830,14 @@ class LeAudioClientImpl : public LeAudioClient {
              ToString(group->GetState()).c_str(),
              ToString(group->GetTargetState()).c_str());

    auto new_metadata_context_types = AudioContexts();

    /* If the local source is started, ready to start or any direction is
     * reconfiguring to start sit remote sink configuration, then take
     * into the account current context type. If the metadata seem
     * invalid, keep the old one, but verify against the availability.
     * Otherwise start empty and add the tracks contexts.
     */
    auto is_releasing_for_reconfiguration =
        (((audio_receiver_state_ == AudioState::RELEASING) ||
          (audio_sender_state_ == AudioState::RELEASING)) &&
         group->IsPendingConfiguration() &&
         IsDirectionAvailableForCurrentConfiguration(
             group, le_audio::types::kLeAudioDirectionSink));
    if (is_releasing_for_reconfiguration ||
        (audio_sender_state_ == AudioState::STARTED) ||
        (audio_sender_state_ == AudioState::READY_TO_START)) {
      LOG_DEBUG("Other direction is streaming. Taking its contexts %s",
                ToString(metadata_context_types_.sink).c_str());
      new_metadata_context_types =
          ChooseMetadataContextType(metadata_context_types_.sink);

    } else if (sink_metadata.empty()) {
      LOG_DEBUG("Not a valid sink metadata update. Keeping the old contexts");
      new_metadata_context_types &= group->GetAvailableContexts();

    } else {
      LOG_DEBUG("No other direction is streaming. Start with empty contexts.");
    }
    // Make sure the other direction is tested against the available contexts
    metadata_context_types_.sink &= group->GetAvailableContexts();

    /* Set remote source metadata context from the recording tracks metadata */
    metadata_context_types_.source = GetAllowedAudioContextsFromSinkMetadata(
        sink_metadata, group->GetAvailableContexts());
    metadata_context_types_.source =
        ChooseMetadataContextType(metadata_context_types_.source);

    /* Make sure we have CONVERSATIONAL when in a call */
    if (in_call_) {
@@ -3865,44 +3846,67 @@ class LeAudioClientImpl : public LeAudioClient {
          AudioContexts(LeAudioContextType::CONVERSATIONAL);
    }

    /* Append the remote source context types */
    new_metadata_context_types |= metadata_context_types_.source;

    if (stack_config_get_interface()
            ->get_pts_force_le_audio_multiple_contexts_metadata()) {
      // Use common audio stream contexts exposed by the PTS
      new_metadata_context_types = AudioContexts(0xFFFF);
      metadata_context_types_.source = AudioContexts(0xFFFF);
      for (auto device = group->GetFirstDevice(); device != nullptr;
           device = group->GetNextDevice(device)) {
        new_metadata_context_types &= device->GetAvailableContexts();
        metadata_context_types_.source &= device->GetAvailableContexts();
      }
      if (new_metadata_context_types.value() == 0xFFFF) {
        new_metadata_context_types =
      if (metadata_context_types_.source.value() == 0xFFFF) {
        metadata_context_types_.source =
            AudioContexts(LeAudioContextType::UNSPECIFIED);
      }
      LOG_WARN("Overriding new_metadata_context_types with: %su",
               new_metadata_context_types.to_string().c_str());
      LOG_WARN("Overriding metadata_context_types_.source with: %su",
               metadata_context_types_.source.to_string().c_str());

      /* Choose the right configuration context */
      const auto new_configuration_context =
          ChooseConfigurationContextType(new_metadata_context_types);
          ChooseConfigurationContextType(metadata_context_types_.source);

      LOG_DEBUG("new_configuration_context= %s.",
                ToString(new_configuration_context).c_str());
      new_metadata_context_types.set(new_configuration_context);
      metadata_context_types_.source.set(new_configuration_context);
    }

    if (new_metadata_context_types.none()) {
      LOG_WARN("invalid/unknown context metadata, using 'UNSPECIFIED' instead");
      new_metadata_context_types =
    // We expect at least some context when remote source gets enabled
    if (metadata_context_types_.source.none()) {
      LOG_WARN(
          "invalid/unknown source context metadata, using 'UNSPECIFIED' "
          "instead");
      metadata_context_types_.source =
          AudioContexts(LeAudioContextType::UNSPECIFIED);
    }

    /* Start with only this direction context metadata */
    auto configuration_context_candidates = metadata_context_types_.source;

    /* If the local source is started, ready to start or any direction is
     * reconfiguring when the remote sink configuration is active, then take
     * into the account current context type for this direction when
     * configuration context is selected.
     */
    auto is_releasing_for_reconfiguration =
        (((audio_receiver_state_ == AudioState::RELEASING) ||
          (audio_sender_state_ == AudioState::RELEASING)) &&
         group->IsPendingConfiguration() &&
         IsDirectionAvailableForCurrentConfiguration(
             group, le_audio::types::kLeAudioDirectionSink));
    if (is_releasing_for_reconfiguration ||
        (audio_sender_state_ == AudioState::STARTED) ||
        (audio_sender_state_ == AudioState::READY_TO_START)) {
      configuration_context_candidates =
          ChooseMetadataContextType(get_bidirectional(metadata_context_types_));
      LOG_DEBUG("Other direction is streaming. Taking its contexts %s",
                ToString(metadata_context_types_.sink).c_str());
    }
    LOG_DEBUG("configuration_context_candidates= %s",
              ToString(configuration_context_candidates).c_str());

    /* Choose the right configuration context */
    const auto new_configuration_context =
        ChooseConfigurationContextType(new_metadata_context_types);
    LOG_DEBUG("new_configuration_context= %s",
              ToString(new_configuration_context).c_str());
    auto new_configuration_context =
        ChooseConfigurationContextType(configuration_context_candidates);

    /* Do nothing if audio source is not valid for the new configuration */
    const auto is_audio_source_context =
@@ -3931,27 +3935,22 @@ class LeAudioClientImpl : public LeAudioClient {
          "context in %s. Not switching to %s right now.",
          ToString(configuration_context_type_).c_str(),
          ToString(new_configuration_context).c_str());
      return;
      new_configuration_context = configuration_context_type_;
    }

    ReconfigureOrUpdateMetadata(group, new_configuration_context,
                                std::move(new_metadata_context_types));
    LOG_DEBUG("metadata_context_types_.sink= %s",
              ToString(metadata_context_types_.sink).c_str());
    LOG_DEBUG("metadata_context_types_.source= %s",
              ToString(metadata_context_types_.source).c_str());
    ReconfigureOrUpdateMetadata(group, new_configuration_context);
  }

  void ReconfigureOrUpdateMetadata(LeAudioDeviceGroup* group,
                                   LeAudioContextType new_configuration_context,
                                   AudioContexts new_metadata_context_types) {
  void ReconfigureOrUpdateMetadata(
      LeAudioDeviceGroup* group, LeAudioContextType new_configuration_context) {
    if (new_configuration_context != configuration_context_type_) {
      LOG_DEBUG(
          "Changing configuration context from %s to %s, new "
          "metadata_contexts: %s",
      LOG_DEBUG("Changing configuration context from %s to %s",
                ToString(configuration_context_type_).c_str(),
          ToString(new_configuration_context).c_str(),
          ToString(new_metadata_context_types).c_str());
      // TODO: This should also cache the combined metadata context for the
      //       reconfiguration, so that once the group reaches IDLE state and
      //       is about to reconfigure, we would know if we reconfigure with
      //       sink or source or both metadata.
                ToString(new_configuration_context).c_str());
      if (SetConfigurationAndStopStreamWhenNeeded(group,
                                                  new_configuration_context)) {
        return;
@@ -3960,13 +3959,13 @@ class LeAudioClientImpl : public LeAudioClient {

    if (group->GetTargetState() == AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) {
      LOG_DEBUG(
          "The %s configuration did not change. Changing only the metadata "
          "contexts from %s to %s",
          "The %s configuration did not change. Updating the metadata to "
          "sink=%s, source=%s",
          ToString(configuration_context_type_).c_str(),
          ToString(get_bidirectional(metadata_context_types_)).c_str(),
          ToString(new_metadata_context_types).c_str());
      GroupStream(group->group_id_, new_configuration_context,
                  new_metadata_context_types);
          ToString(metadata_context_types_.sink).c_str(),
          ToString(metadata_context_types_.source).c_str());
      GroupStream(group->group_id_, configuration_context_type_,
                  metadata_context_types_);
    }
  }

@@ -4336,18 +4335,14 @@ class LeAudioClientImpl : public LeAudioClient {
      case GroupStreamStatus::IDLE: {
        if (group && group->IsPendingConfiguration()) {
          SuspendedForReconfiguration();
          // TODO: It is not certain to which directions we will
          //       reconfigure. We would have know the exact
          //       configuration but this is yet to be selected or have
          //       the metadata cached from earlier when reconfiguration
          //       was scheduled.
          auto adjusted_metedata_context_type = ChooseMetadataContextType(
              get_bidirectional(metadata_context_types_));
          BidirectionalPair<std::vector<uint8_t>> ccids = {
              .sink = ContentControlIdKeeper::GetInstance()->GetAllCcids(
                  metadata_context_types_.sink),
              .source = ContentControlIdKeeper::GetInstance()->GetAllCcids(
                  metadata_context_types_.source)};
          if (groupStateMachine_->ConfigureStream(
                  group, configuration_context_type_,
                  adjusted_metedata_context_type,
                  ContentControlIdKeeper::GetInstance()->GetAllCcids(
                      adjusted_metedata_context_type))) {
                  group, configuration_context_type_, metadata_context_types_,
                  ccids)) {
            /* If configuration succeed wait for new status. */
            return;
          }
+50 −50

File changed.

Preview size limit exceeded, changes collapsed.

+34 −20
Original line number Diff line number Diff line
@@ -163,18 +163,23 @@ class LeAudioDevice {
                             codec_capability_setting);
  uint8_t GetLc3SupportedChannelCount(uint8_t direction);
  uint8_t GetPhyBitmask(void);
  bool ConfigureAses(const le_audio::set_configurations::SetConfiguration& ent,
  bool ConfigureAses(
      const le_audio::set_configurations::SetConfiguration& ent,
      types::LeAudioContextType context_type,
      uint8_t* number_of_already_active_group_ase,
                     types::AudioLocations& group_snk_audio_locations,
                     types::AudioLocations& group_src_audio_locations,
                     bool reconnect, types::AudioContexts metadata_context_type,
                     const std::vector<uint8_t>& ccid_list);
      types::BidirectionalPair<types::AudioLocations>&
          group_audio_locations_out,
      const types::BidirectionalPair<types::AudioContexts>&
          metadata_context_types,
      const types::BidirectionalPair<std::vector<uint8_t>>& ccid_lists,
      bool reuse_cis_id);
  void SetSupportedContexts(types::AudioContexts snk_contexts,
                            types::AudioContexts src_contexts);
  types::AudioContexts GetAvailableContexts(
  inline types::AudioContexts GetAvailableContexts(
      int direction = (types::kLeAudioDirectionSink |
                       types::kLeAudioDirectionSource));
                       types::kLeAudioDirectionSource)) {
    return avail_contexts_.get(direction);
  }
  types::AudioContexts SetAvailableContexts(types::AudioContexts snk_cont_val,
                                            types::AudioContexts src_cont_val);
  void DeactivateAllAses(void);
@@ -186,8 +191,9 @@ class LeAudioDevice {
  void DisconnectAcl(void);
  std::vector<uint8_t> GetMetadata(types::AudioContexts context_type,
                                   const std::vector<uint8_t>& ccid_list);
  bool IsMetadataChanged(types::AudioContexts context_type,
                         const std::vector<uint8_t>& ccid_list);
  bool IsMetadataChanged(
      const types::BidirectionalPair<types::AudioContexts>& context_types,
      const types::BidirectionalPair<std::vector<uint8_t>>& ccid_lists);

 private:
  types::BidirectionalPair<types::AudioContexts> avail_contexts_;
@@ -245,7 +251,10 @@ class LeAudioDeviceGroup {
        transport_latency_mtos_us_(0),
        transport_latency_stom_us_(0),
        configuration_context_type_(types::LeAudioContextType::UNINITIALIZED),
        metadata_context_type_(types::LeAudioContextType::UNINITIALIZED),
        metadata_context_type_({.sink = types::AudioContexts(
                                    types::LeAudioContextType::UNINITIALIZED),
                                .source = types::AudioContexts(
                                    types::LeAudioContextType::UNINITIALIZED)}),
        group_available_contexts_(types::LeAudioContextType::UNINITIALIZED),
        pending_group_available_contexts_change_(
            types::LeAudioContextType::UNINITIALIZED),
@@ -296,8 +305,10 @@ class LeAudioDeviceGroup {
  void CigAssignCisConnHandlesToAses(void);
  void CigUnassignCis(LeAudioDevice* leAudioDevice);
  bool Configure(types::LeAudioContextType context_type,
                 types::AudioContexts metadata_context_type,
                 std::vector<uint8_t> ccid_list = {});
                 const types::BidirectionalPair<types::AudioContexts>&
                     metadata_context_types,
                 types::BidirectionalPair<std::vector<uint8_t>> ccid_lists = {
                     .sink = {}, .source = {}});
  uint32_t GetSduInterval(uint8_t direction);
  uint8_t GetSCA(void);
  uint8_t GetPacking(void);
@@ -325,8 +336,9 @@ class LeAudioDeviceGroup {
  std::optional<LeAudioCodecConfiguration> GetCodecConfigurationByDirection(
      types::LeAudioContextType group_context_type, uint8_t direction) const;
  bool IsContextSupported(types::LeAudioContextType group_context_type);
  bool IsMetadataChanged(types::AudioContexts group_context_type,
                         const std::vector<uint8_t>& ccid_list);
  bool IsMetadataChanged(
      const types::BidirectionalPair<types::AudioContexts>& context_types,
      const types::BidirectionalPair<std::vector<uint8_t>>& ccid_lists);
  void CreateStreamVectorForOffloader(uint8_t direction);
  void StreamOffloaderUpdated(uint8_t direction);

@@ -363,7 +375,8 @@ class LeAudioDeviceGroup {
    return configuration_context_type_;
  }

  inline types::AudioContexts GetMetadataContexts(void) const {
  inline types::BidirectionalPair<types::AudioContexts> GetMetadataContexts()
      const {
    return metadata_context_type_;
  }

@@ -386,8 +399,9 @@ class LeAudioDeviceGroup {
  bool ConfigureAses(
      const set_configurations::AudioSetConfiguration* audio_set_conf,
      types::LeAudioContextType context_type,
      types::AudioContexts metadata_context_type,
      const std::vector<uint8_t>& ccid_list);
      const types::BidirectionalPair<types::AudioContexts>&
          metadata_context_types,
      const types::BidirectionalPair<std::vector<uint8_t>>& ccid_lists);
  bool IsConfigurationSupported(
      const set_configurations::AudioSetConfiguration* audio_set_configuration,
      types::LeAudioContextType context_type,
@@ -396,7 +410,7 @@ class LeAudioDeviceGroup {

  /* Current configuration and metadata context types */
  types::LeAudioContextType configuration_context_type_;
  types::AudioContexts metadata_context_type_;
  types::BidirectionalPair<types::AudioContexts> metadata_context_type_;

  /* Mask of contexts that the whole group can handle at it's current state
   * It's being updated each time group members connect, disconnect or their
+31 −17

File changed.

Preview size limit exceeded, changes collapsed.

+102 −85

File changed.

Preview size limit exceeded, changes collapsed.

Loading