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

Commit 2886c6c2 authored by Jack He's avatar Jack He Committed by Automerger Merge Worker
Browse files

Merge changes Idaf3ed15,I8613df78,I132c7667,I050f310b,I80459064, ... am: 50383a6f

parents 19fb26aa 50383a6f
Loading
Loading
Loading
Loading
+2 −5
Original line number Diff line number Diff line
@@ -584,7 +584,6 @@ std::vector<AudioSetConfiguration> get_offload_capabilities() {
      audio_set_config.confs.push_back(SetConfiguration(
          ::le_audio::types::kLeAudioDirectionSink, hal_encode_cap.deviceCount,
          hal_encode_cap.deviceCount * hal_encode_cap.channelCountPerDevice,
          ::le_audio::types::kTargetLatencyBalancedLatencyReliability,
          encode_cap));
      str_capability_log = " Encode Capability: " + hal_encode_cap.toString();
    }
@@ -594,16 +593,14 @@ std::vector<AudioSetConfiguration> get_offload_capabilities() {
          ::le_audio::types::kLeAudioDirectionSource,
          hal_decode_cap.deviceCount,
          hal_decode_cap.deviceCount * hal_decode_cap.channelCountPerDevice,
          ::le_audio::types::kTargetLatencyBalancedLatencyReliability,
          decode_cap));
      str_capability_log += " Decode Capability: " + hal_decode_cap.toString();
    }

    if (hal_bcast_capability_to_stack_format(hal_bcast_cap, bcast_cap)) {
      // Set device_cnt, ase_cnt, target_latency to zero to ignore these fields
      // for broadcast
      // Set device_cnt, ase_cnt to zero to ignore these fields for broadcast
      audio_set_config.confs.push_back(SetConfiguration(
          ::le_audio::types::kLeAudioDirectionSink, 0, 0, 0, bcast_cap));
          ::le_audio::types::kLeAudioDirectionSink, 0, 0, bcast_cap));
      str_capability_log +=
          " Broadcast Capability: " + hal_bcast_cap.toString();
    }
+1 −1
Original line number Diff line number Diff line
@@ -56,7 +56,6 @@ enum AudioSetConfigurationTargetLatency : byte {
    HIGH_RELIABILITY = 0x03,
}
table AudioSetSubConfiguration {
    target_latency: AudioSetConfigurationTargetLatency = BALANCED_RELIABILITY;
    device_cnt: ubyte;
    ase_cnt: ubyte;
    direction: AudioSetConfigurationDirection = SINK;
@@ -70,6 +69,7 @@ table CodecConfiguration {
}
table QosConfiguration {
    name: string (key, required);
    target_latency: AudioSetConfigurationTargetLatency = BALANCED_RELIABILITY;
    retransmission_number: ubyte;
    max_transport_latency : ushort;
}
+1014 −320

File changed.

Preview size limit exceeded, changes collapsed.

+197 −154

File changed.

Preview size limit exceeded, changes collapsed.

+239 −55
Original line number Diff line number Diff line
@@ -1057,11 +1057,12 @@ class LeAudioClientImpl : public LeAudioClient {
      }
    }

    /* Mini policy: Try configure audio HAL sessions with most frequent context.
    /* Mini policy: Try configure audio HAL sessions with most recent context.
     * If reconfiguration is not needed it means, context type is not supported.
     * If most frequest scenario is not supported, try to find first supported.
     * If most recent scenario is not supported, try to find first supported.
     */
    LeAudioContextType default_context_type = LeAudioContextType::UNSPECIFIED;
    LeAudioContextType default_context_type = configuration_context_type_;
    if (!group->IsContextSupported(default_context_type)) {
      if (group->IsContextSupported(LeAudioContextType::MEDIA)) {
        default_context_type = LeAudioContextType::MEDIA;
      } else {
@@ -1073,6 +1074,7 @@ class LeAudioClientImpl : public LeAudioClient {
          }
        }
      }
    }
    UpdateConfigAndCheckIfReconfigurationIsNeeded(group_id,
                                                  default_context_type);
    if (current_source_codec_config.IsInvalid() &&
@@ -3338,6 +3340,7 @@ class LeAudioClientImpl : public LeAudioClient {
    if (!group) {
      LOG(ERROR) << __func__
                 << ", Invalid group: " << static_cast<int>(active_group_id_);
      le_audio_source_hal_client_->CancelStreamingRequest();
      return;
    }

@@ -3494,9 +3497,17 @@ class LeAudioClientImpl : public LeAudioClient {
    if (!group) {
      LOG(ERROR) << __func__
                 << ", Invalid group: " << static_cast<int>(active_group_id_);
      le_audio_sink_hal_client_->CancelStreamingRequest();
      return;
    }

    /* We need new configuration_context_type_ to be selected before we go any
     * further.
     */
    if (audio_receiver_state_ == AudioState::IDLE) {
      ReconfigureOrUpdateRemoteSource(group);
    }

    /* Check if the device resume is expected */
    if (!group->GetCodecConfigurationByDirection(
            configuration_context_type_,
@@ -3642,16 +3653,17 @@ class LeAudioClientImpl : public LeAudioClient {
      }
    }

    /* We keepo the existing configuration, when not in a call, but the user
     * adjusts the ringtone volume while there is no other valid audio stream.
    /* Use BAP mandated UNSPECIFIED only if we don't have any other valid
     * configuration
     */
    if (available_remote_contexts.test(LeAudioContextType::RINGTONE)) {
      return configuration_context_type_;
    auto fallback_config = LeAudioContextType::UNSPECIFIED;
    if (configuration_context_type_ != LeAudioContextType::UNINITIALIZED) {
      fallback_config = configuration_context_type_;
    }

    /* Fallback to BAP mandated context type */
    LOG_WARN("Invalid/unknown context, using 'UNSPECIFIED'");
    return LeAudioContextType::UNSPECIFIED;
    LOG_DEBUG("Selecting configuration context type: %s",
              ToString(fallback_config).c_str());
    return fallback_config;
  }

  bool SetConfigurationAndStopStreamWhenNeeded(
@@ -3709,19 +3721,63 @@ class LeAudioClientImpl : public LeAudioClient {
     */
    StopVbcCloseTimeout();

    LOG_DEBUG("group state=%s, target_state=%s",
              ToString(group->GetState()).c_str(),
              ToString(group->GetTargetState()).c_str());
    LOG_INFO(
        "group_id %d state=%s, target_state=%s, audio_receiver_state_: %s, "
        "audio_sender_state_: %s",
        group->group_id_, ToString(group->GetState()).c_str(),
        ToString(group->GetTargetState()).c_str(),
        ToString(audio_receiver_state_).c_str(),
        ToString(audio_sender_state_).c_str());

    // Make sure the other direction is tested against the available contexts
    metadata_context_types_.source &= group->GetAvailableContexts();
    /* When a certain context became unavailable while it was already in
     * an active stream, it means that it is unavailable to other clients
     * but we can keep using it.
     */
    auto current_available_contexts = group->GetAvailableContexts();
    if ((audio_sender_state_ == AudioState::STARTED) ||
        (audio_sender_state_ == AudioState::READY_TO_START)) {
      current_available_contexts |= metadata_context_types_.sink;
    }

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

    /* Make sure we have CONVERSATIONAL when in a call */
    if (in_call_) {
      LOG_DEBUG(" In Call preference used.");
      metadata_context_types_.sink |=
          AudioContexts(LeAudioContextType::CONVERSATIONAL);
      metadata_context_types_.source |=
          AudioContexts(LeAudioContextType::CONVERSATIONAL);
    }

    metadata_context_types_.sink =
        ChooseMetadataContextType(metadata_context_types_.sink);

    /* Mixed contexts in the voiceback channel scenarios can confuse the remote
     * on how to configure each channel. We should align both direction
     * metadata.
     */
    auto non_mixing_contexts = LeAudioContextType::GAME |
                               LeAudioContextType::LIVE |
                               LeAudioContextType::CONVERSATIONAL |
                               LeAudioContextType::VOICEASSISTANTS;
    if (metadata_context_types_.sink.test_any(non_mixing_contexts)) {
      if (osi_property_get_bool(kAllowMultipleContextsInMetadata, true)) {
        LOG_DEBUG("Aligning remote source metadata to add the sink context");
        metadata_context_types_.source =
            metadata_context_types_.source | metadata_context_types_.sink;
      } else {
        LOG_DEBUG("Replacing remote source metadata to match the sink context");
        metadata_context_types_.source = metadata_context_types_.sink;
      }
    }

    ReconfigureOrUpdateRemoteSink(group);
  }

  void ReconfigureOrUpdateRemoteSink(LeAudioDeviceGroup* group) {
    if (stack_config_get_interface()
            ->get_pts_force_le_audio_multiple_contexts_metadata()) {
      // Use common audio stream contexts exposed by the PTS
@@ -3748,14 +3804,6 @@ class LeAudioClientImpl : public LeAudioClient {
      return;
    }

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

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

@@ -3775,12 +3823,27 @@ class LeAudioClientImpl : public LeAudioClient {
        (audio_receiver_state_ == AudioState::READY_TO_START)) {
      LOG_DEBUG("Other direction is streaming. Taking its contexts %s",
                ToString(metadata_context_types_.source).c_str());

      // If current direction has no valid context take the other direction
      // context
      if (metadata_context_types_.sink.none()) {
        if (metadata_context_types_.source.any()) {
          LOG_DEBUG(
              "Aligning remote sink metadata to match the source context");
          metadata_context_types_.sink = metadata_context_types_.source;
        }
      }

      configuration_context_candidates =
          ChooseMetadataContextType(get_bidirectional(metadata_context_types_));
    }
    LOG_DEBUG("configuration_context_candidates= %s",
              ToString(configuration_context_candidates).c_str());

    RealignMetadataAudioContextsIfNeeded(
        le_audio::types::kLeAudioDirectionSink);

    /* Choose the right configuration context */
    auto new_configuration_context =
        ChooseConfigurationContextType(configuration_context_candidates);
    LOG_DEBUG("new_configuration_context= %s",
@@ -3792,14 +3855,17 @@ class LeAudioClientImpl : public LeAudioClient {
     * LeAudioContextType::INSTRUCTIONAL
     * LeAudioContextType::ALERTS
     * LeAudioContextType::EMERGENCYALARM
     * LeAudioContextType::UNSPECIFIED
     * So do not reconfigure if the remote sink is already available at any
     * quality and these are the only contributors to the current audio stream.
     */
    auto no_reconfigure_contexts =
        LeAudioContextType::NOTIFICATIONS | LeAudioContextType::SOUNDEFFECTS |
        LeAudioContextType::INSTRUCTIONAL | LeAudioContextType::ALERTS |
        LeAudioContextType::EMERGENCYALARM;
    if ((configuration_context_candidates & ~no_reconfigure_contexts).none() &&
        LeAudioContextType::EMERGENCYALARM | LeAudioContextType::UNSPECIFIED;
    if (configuration_context_candidates.any() &&
        (configuration_context_candidates & ~no_reconfigure_contexts).none() &&
        (configuration_context_type_ != LeAudioContextType::UNINITIALIZED) &&
        IsDirectionAvailableForCurrentConfiguration(
            group, le_audio::types::kLeAudioDirectionSink)) {
      LOG_INFO(
@@ -3816,6 +3882,77 @@ class LeAudioClientImpl : public LeAudioClient {
    ReconfigureOrUpdateMetadata(group, new_configuration_context);
  }

  void RealignMetadataAudioContextsIfNeeded(int remote_dir) {
    // We expect at least some context when this direction gets enabled
    if (metadata_context_types_.get(remote_dir).none()) {
      LOG_WARN(
          "invalid/unknown %s context metadata, using 'UNSPECIFIED' instead",
          (remote_dir == le_audio::types::kLeAudioDirectionSink) ? "sink"
                                                                 : "source");
      metadata_context_types_.get_ref(remote_dir) =
          AudioContexts(LeAudioContextType::UNSPECIFIED);
    }

    /* Don't mix UNSPECIFIED with any other context */
    if (metadata_context_types_.sink.test(LeAudioContextType::UNSPECIFIED)) {
      /* Try to use the other direction context if not UNSPECIFIED and active */
      if (metadata_context_types_.sink ==
          AudioContexts(LeAudioContextType::UNSPECIFIED)) {
        auto is_other_direction_streaming =
            (audio_receiver_state_ == AudioState::STARTED) ||
            (audio_receiver_state_ == AudioState::READY_TO_START);
        if (is_other_direction_streaming &&
            (metadata_context_types_.source !=
             AudioContexts(LeAudioContextType::UNSPECIFIED))) {
          LOG_INFO(
              "Other direction is streaming. Aligning remote sink metadata to "
              "match the source context: %s",
              ToString(metadata_context_types_.source).c_str());
          metadata_context_types_.sink = metadata_context_types_.source;
        } else {
          LOG_INFO(
              "Other direction is not streaming. Replacing the existing remote "
              "sink context: %s with UNSPECIFIED",
              ToString(metadata_context_types_.source).c_str());
          metadata_context_types_.source =
              AudioContexts(LeAudioContextType::UNSPECIFIED);
        }
      } else {
        LOG_DEBUG("Removing UNSPECIFIED from the remote sink context: %s",
                  ToString(metadata_context_types_.source).c_str());
        metadata_context_types_.sink.unset(LeAudioContextType::UNSPECIFIED);
      }
    }

    if (metadata_context_types_.source.test(LeAudioContextType::UNSPECIFIED)) {
      /* Try to use the other direction context if not UNSPECIFIED and active */
      if (metadata_context_types_.source ==
          AudioContexts(LeAudioContextType::UNSPECIFIED)) {
        auto is_other_direction_streaming =
            (audio_sender_state_ == AudioState::STARTED) ||
            (audio_sender_state_ == AudioState::READY_TO_START);
        if (is_other_direction_streaming &&
            (metadata_context_types_.sink !=
             AudioContexts(LeAudioContextType::UNSPECIFIED))) {
          LOG_DEBUG(
              "Other direction is streaming. Aligning remote source metadata "
              "to "
              "match the sink context: %s",
              ToString(metadata_context_types_.sink).c_str());
          metadata_context_types_.source = metadata_context_types_.sink;
        }
      } else {
        LOG_DEBUG("Removing UNSPECIFIED from the remote source context: %s",
                  ToString(metadata_context_types_.source).c_str());
        metadata_context_types_.source.unset(LeAudioContextType::UNSPECIFIED);
      }
    }

    LOG_DEBUG("Metadata audio context: sink=%s, source=%s",
              ToString(metadata_context_types_.sink).c_str(),
              ToString(metadata_context_types_.source).c_str());
  }

  void OnLocalAudioSinkMetadataUpdate(
      std::vector<struct record_track_metadata> sink_metadata) {
    if (active_group_id_ == bluetooth::groups::kGroupUnknown) {
@@ -3830,26 +3967,68 @@ class LeAudioClientImpl : public LeAudioClient {
      return;
    }

    LOG_DEBUG("group state=%s, target_state=%s",
              ToString(group->GetState()).c_str(),
              ToString(group->GetTargetState()).c_str());
    LOG_INFO(
        "group_id %d state=%s, target_state=%s, audio_receiver_state_: %s, "
        "audio_sender_state_: %s",
        group->group_id_, ToString(group->GetState()).c_str(),
        ToString(group->GetTargetState()).c_str(),
        ToString(audio_receiver_state_).c_str(),
        ToString(audio_sender_state_).c_str());

    // Make sure the other direction is tested against the available contexts
    metadata_context_types_.sink &= group->GetAvailableContexts();
    /* When a certain context became unavailable while it was already in
     * an active stream, it means that it is unavailable to other clients
     * but we can keep using it.
     */
    auto current_available_contexts = group->GetAvailableContexts();
    if ((audio_receiver_state_ == AudioState::STARTED) ||
        (audio_receiver_state_ == AudioState::READY_TO_START)) {
      current_available_contexts |= metadata_context_types_.source;
    }

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

    /* Make sure we have CONVERSATIONAL when in a call */
    if (in_call_) {
      LOG_DEBUG(" In Call preference used.");
      metadata_context_types_.sink |=
          AudioContexts(LeAudioContextType::CONVERSATIONAL);
      metadata_context_types_.source |=
          AudioContexts(LeAudioContextType::CONVERSATIONAL);
    }

    metadata_context_types_.source =
        ChooseMetadataContextType(metadata_context_types_.source);

    /* Mixed contexts in the voiceback channel scenarios can confuse the remote
     * on how to configure each channel. We should align both direction
     * metadata.
     */
    auto non_mixing_contexts = LeAudioContextType::GAME |
                               LeAudioContextType::LIVE |
                               LeAudioContextType::CONVERSATIONAL |
                               LeAudioContextType::VOICEASSISTANTS;
    if (metadata_context_types_.source.test_any(non_mixing_contexts)) {
      if (osi_property_get_bool(kAllowMultipleContextsInMetadata, true)) {
        LOG_DEBUG("Aligning remote sink metadata to add the source context");
        metadata_context_types_.sink =
            metadata_context_types_.sink | metadata_context_types_.source;
      } else {
        LOG_DEBUG("Replacing remote sink metadata to match the source context");
        metadata_context_types_.sink = metadata_context_types_.source;
      }
    }

    /* Reconfigure or update only if the stream is already started
     * otherwise wait for the local sink to resume.
     */
    if (audio_receiver_state_ == AudioState::STARTED) {
      ReconfigureOrUpdateRemoteSource(group);
    }
  }

  void ReconfigureOrUpdateRemoteSource(LeAudioDeviceGroup* group) {
    if (stack_config_get_interface()
            ->get_pts_force_le_audio_multiple_contexts_metadata()) {
      // Use common audio stream contexts exposed by the PTS
@@ -3874,15 +4053,6 @@ class LeAudioClientImpl : public LeAudioClient {
      metadata_context_types_.source.set(new_configuration_context);
    }

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

@@ -3900,14 +4070,28 @@ class LeAudioClientImpl : public LeAudioClient {
    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());

      // If current direction has no valid context take the other direction
      // context
      if (metadata_context_types_.source.none()) {
        if (metadata_context_types_.sink.any()) {
          LOG_DEBUG(
              "Aligning remote source metadata to match the sink context");
          metadata_context_types_.source = metadata_context_types_.sink;
        }
      }

      configuration_context_candidates =
          ChooseMetadataContextType(get_bidirectional(metadata_context_types_));
    }
    LOG_DEBUG("configuration_context_candidates= %s",
              ToString(configuration_context_candidates).c_str());

    RealignMetadataAudioContextsIfNeeded(
        le_audio::types::kLeAudioDirectionSource);

    /* Choose the right configuration context */
    auto new_configuration_context =
        ChooseConfigurationContextType(configuration_context_candidates);
Loading