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

Commit 088729eb authored by Sandeep Samdaria's avatar Sandeep Samdaria Committed by Automerger Merge Worker
Browse files

Merge "BTA AV CO active device management" into main am: 4634570c

parents dfc2c667 4634570c
Loading
Loading
Loading
Loading
+150 −25
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@

#include "btif/include/bta_av_co.h"

#include <android_bluetooth_flags.h>
#include <bluetooth/log.h>

#include <mutex>
@@ -105,6 +106,8 @@ void BtaAvCo::Init(

void BtaAvCo::Reset() {
  bta_av_legacy_state_.Reset();
  bta_av_source_state_.Reset();
  bta_av_sink_state_.Reset();
  content_protect_flag_ = 0;

  if (ContentProtectEnabled()) {
@@ -130,7 +133,13 @@ bool BtaAvCo::IsSupportedCodec(btav_a2dp_codec_index_t codec_index) {
A2dpCodecConfig* BtaAvCo::GetActivePeerCurrentCodec() {
  std::lock_guard<std::recursive_mutex> lock(peer_cache_->codec_lock_);

  BtaAvCoPeer* active_peer = bta_av_legacy_state_.getActivePeer();
  BtaAvCoState* reference_state = nullptr;
  if (IS_FLAG_ENABLED(a2dp_concurrent_source_sink)) {
    reference_state = &bta_av_source_state_;
  } else {
    reference_state = &bta_av_legacy_state_;
  }
  BtaAvCoPeer* active_peer = reference_state->getActivePeer();
  if (active_peer == nullptr || active_peer->GetCodecs() == nullptr) {
    return nullptr;
  }
@@ -530,7 +539,8 @@ void BtaAvCo::ProcessSetConfig(tBTA_AV_HNDL bta_av_handle,
      if (codec_config_supported) {
        // If Peer is Source, and our config subset matches with what is
        // requested by peer, then just accept what peer wants.
        SaveNewCodecConfig(p_peer, p_codec_info, num_protect, p_protect_info);
        SaveNewCodecConfig(p_peer, p_codec_info, num_protect, p_protect_info,
                           t_local_sep);
      }
    }
    if (t_local_sep == AVDT_TSEP_SRC) {
@@ -541,7 +551,7 @@ void BtaAvCo::ProcessSetConfig(tBTA_AV_HNDL bta_av_handle,
      bool dummy_restart_output = false;
      if ((p_peer->GetCodecs() == nullptr) ||
          !SetCodecOtaConfig(p_peer, p_codec_info, num_protect, p_protect_info,
                             &dummy_restart_output)) {
                             &dummy_restart_output, t_local_sep)) {
        log::error("cannot set source codec {} for peer {}",
                   A2DP_CodecName(p_codec_info),
                   ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr));
@@ -596,10 +606,14 @@ void BtaAvCo::ProcessOpen(tBTA_AV_HNDL bta_av_handle,
  p_peer->opened = true;
  p_peer->mtu = mtu;

  // The first connected peer becomes the active peer
  BtaAvCoPeer* active_peer = bta_av_legacy_state_.getActivePeer();
  BtaAvCoState* reference_state = getStateFromPeer(p_peer);
  if (reference_state == nullptr) {
    log::warn("Invalid bta av state");
    return;
  }
  BtaAvCoPeer* active_peer = reference_state->getActivePeer();
  if (active_peer == nullptr) {
    bta_av_legacy_state_.setActivePeer(p_peer);
    reference_state->setActivePeer(p_peer);
  }
}

@@ -618,10 +632,17 @@ void BtaAvCo::ProcessClose(tBTA_AV_HNDL bta_av_handle,
    return;
  }
  // Reset the active peer
  BtaAvCoPeer* active_peer = bta_av_legacy_state_.getActivePeer();

  BtaAvCoState* reference_state = getStateFromPeer(p_peer);
  if (reference_state == nullptr) {
    log::warn("Invalid bta av state");
    return;
  }
  BtaAvCoPeer* active_peer = reference_state->getActivePeer();
  if (active_peer == p_peer) {
    bta_av_legacy_state_.setActivePeer(nullptr);
    reference_state->setActivePeer(nullptr);
  }

  // Mark the peer closed and clean the peer info
  p_peer->Init(peer_cache_->codec_priorities_);
}
@@ -686,7 +707,13 @@ BT_HDR* BtaAvCo::GetNextSourceDataPacket(const uint8_t* p_codec_info,
    return nullptr;
  }

  BtaAvCoPeer* active_peer = bta_av_legacy_state_.getActivePeer();
  BtaAvCoState* reference_state = nullptr;
  if (IS_FLAG_ENABLED(a2dp_concurrent_source_sink)) {
    reference_state = &bta_av_source_state_;
  } else {
    reference_state = &bta_av_legacy_state_;
  }
  BtaAvCoPeer* active_peer = reference_state->getActivePeer();
  // if offset is 0, the decremental operation may result in
  // underflow and OOB access
  if (ContentProtectEnabled() && (active_peer != nullptr) &&
@@ -731,12 +758,19 @@ void BtaAvCo::UpdateMtu(tBTA_AV_HNDL bta_av_handle,
  p_peer->mtu = mtu;
}

bool BtaAvCo::SetActivePeer(const RawAddress& peer_address) {
bool BtaAvCo::SetActivePeer(const RawAddress& peer_address,
                            const uint8_t t_local_sep) {
  log::info("peer_address={}", ADDRESS_TO_LOGGABLE_STR(peer_address));

  std::lock_guard<std::recursive_mutex> lock(peer_cache_->codec_lock_);

  BtaAvCoState* reference_state = &bta_av_legacy_state_;
  BtaAvCoState* reference_state = getStateFromLocalProfile(t_local_sep);
  if (reference_state == nullptr) {
    log::warn(
        "Invalid bta av state for peer_address : {} with local sep as :{}",
        ADDRESS_TO_LOGGABLE_CSTR(peer_address), t_local_sep);
    return false;
  }
  if (peer_address.IsEmpty()) {
    // Reset the active peer;
    reference_state->setActivePeer(nullptr);
@@ -759,9 +793,28 @@ bool BtaAvCo::SetActivePeer(const RawAddress& peer_address) {
  return true;
}

BtaAvCoState* BtaAvCo::getStateFromLocalProfile(const uint8_t t_local_sep) {
  if (IS_FLAG_ENABLED(a2dp_concurrent_source_sink)) {
    if (t_local_sep == AVDT_TSEP_SRC) {
      return &bta_av_source_state_;
    } else if (t_local_sep == AVDT_TSEP_SNK) {
      return &bta_av_sink_state_;
    } else {
      log::warn("Invalid bta av state for local sep type {}", t_local_sep);
      return nullptr;
    }
  } else {
    return &bta_av_legacy_state_;
  }
}

void BtaAvCo::SaveCodec(const uint8_t* new_codec_config) {
  if (IS_FLAG_ENABLED(a2dp_concurrent_source_sink)) {
    bta_av_sink_state_.setCodecConfig(new_codec_config);
  } else {
    bta_av_legacy_state_.setCodecConfig(new_codec_config);
  }
}

void BtaAvCo::GetPeerEncoderParameters(
    const RawAddress& peer_address,
@@ -792,7 +845,9 @@ void BtaAvCo::GetPeerEncoderParameters(

const tA2DP_ENCODER_INTERFACE* BtaAvCo::GetSourceEncoderInterface() {
  std::lock_guard<std::recursive_mutex> lock(peer_cache_->codec_lock_);

  if (IS_FLAG_ENABLED(a2dp_concurrent_source_sink)) {
    return A2DP_GetEncoderInterface(bta_av_source_state_.getCodecConfig());
  }
  return A2DP_GetEncoderInterface(bta_av_legacy_state_.getCodecConfig());
}

@@ -887,7 +942,12 @@ done:
  // and informing the Media Framework about the change.

  // Find the peer that is currently open
  BtaAvCoPeer* active_peer = bta_av_legacy_state_.getActivePeer();
  BtaAvCoPeer* active_peer;
  if (IS_FLAG_ENABLED(a2dp_concurrent_source_sink)) {
    active_peer = bta_av_source_state_.getActivePeer();
  } else {
    active_peer = bta_av_legacy_state_.getActivePeer();
  }
  if (p_peer != nullptr &&
      (!restart_output || !success || p_peer != active_peer)) {
    return ReportSourceCodecState(p_peer);
@@ -905,7 +965,12 @@ bool BtaAvCo::SetCodecAudioConfig(
  log::verbose("codec_audio_config: {}", codec_audio_config.ToString());

  // Find the peer that is currently open
  BtaAvCoPeer* p_peer = bta_av_legacy_state_.getActivePeer();
  BtaAvCoPeer* p_peer;
  if (IS_FLAG_ENABLED(a2dp_concurrent_source_sink)) {
    p_peer = bta_av_source_state_.getActivePeer();
  } else {
    p_peer = bta_av_legacy_state_.getActivePeer();
  }
  if (p_peer == nullptr) {
    log::error("no active peer to configure");
    return false;
@@ -942,7 +1007,7 @@ bool BtaAvCo::SetCodecAudioConfig(
    }

    SaveNewCodecConfig(p_peer, result_codec_config, p_sink->num_protect,
                       p_sink->protect_info);
                       p_sink->protect_info, AVDT_TSEP_SRC);

    p_peer->acceptor = false;
    log::verbose("call BTA_AvReconfig({})", loghex(p_peer->BtaAvHandle()));
@@ -962,6 +1027,10 @@ bool BtaAvCo::SetCodecAudioConfig(
int BtaAvCo::GetSourceEncoderEffectiveFrameSize() {
  std::lock_guard<std::recursive_mutex> lock(peer_cache_->codec_lock_);

  if (IS_FLAG_ENABLED(a2dp_concurrent_source_sink)) {
    return A2DP_GetEecoderEffectiveFrameSize(
        bta_av_source_state_.getCodecConfig());
  }
  return A2DP_GetEecoderEffectiveFrameSize(
      bta_av_legacy_state_.getCodecConfig());
}
@@ -1022,6 +1091,18 @@ void BtaAvCo::DebugDump(int fd) {
      a2dp_codecs->debug_codec_dump(fd);
    }
  }
  if (bta_av_source_state_.getActivePeer() != nullptr) {
    A2dpCodecs* a2dp_codecs = bta_av_source_state_.getActivePeer()->GetCodecs();
    if (a2dp_codecs != nullptr) {
      a2dp_codecs->debug_codec_dump(fd);
    }
  }
  if (bta_av_sink_state_.getActivePeer() != nullptr) {
    A2dpCodecs* a2dp_codecs = bta_av_sink_state_.getActivePeer()->GetCodecs();
    if (a2dp_codecs != nullptr) {
      a2dp_codecs->debug_codec_dump(fd);
    }
  }

  dprintf(fd, "\nA2DP Peers State:\n");
  dprintf(
@@ -1029,6 +1110,16 @@ void BtaAvCo::DebugDump(int fd) {
      (bta_av_legacy_state_.getActivePeer() != nullptr)
          ? ADDRESS_TO_LOGGABLE_CSTR(bta_av_legacy_state_.getActivePeer()->addr)
          : "null");
  dprintf(
      fd, "  Source: active peer: %s\n",
      (bta_av_source_state_.getActivePeer() != nullptr)
          ? ADDRESS_TO_LOGGABLE_CSTR(bta_av_source_state_.getActivePeer()->addr)
          : "null");
  dprintf(
      fd, "  Sink: active peer: %s\n",
      (bta_av_sink_state_.getActivePeer() != nullptr)
          ? ADDRESS_TO_LOGGABLE_CSTR(bta_av_sink_state_.getActivePeer()->addr)
          : "null");

  for (size_t i = 0; i < BTA_AV_CO_NUM_ELEMENTS(peer_cache_->peers_); i++) {
    const BtaAvCoPeer& peer = peer_cache_->peers_[i];
@@ -1108,7 +1199,7 @@ BtaAvCoSep* BtaAvCo::SelectProviderCodecConfiguration(
  p_peer->GetCodecs()->setCurrentCodecConfig(codec_config);
  p_peer->p_sink = p_sink;
  SaveNewCodecConfig(p_peer, provider_codec_config.codec_config,
                     p_sink->num_protect, p_sink->protect_info);
                     p_sink->num_protect, p_sink->protect_info, AVDT_TSEP_SRC);

  return p_sink;
}
@@ -1216,7 +1307,7 @@ const BtaAvCoSep* BtaAvCo::AttemptSourceCodecSelection(
  p_peer->p_sink = p_sink;

  SaveNewCodecConfig(p_peer, new_codec_config, p_sink->num_protect,
                     p_sink->protect_info);
                     p_sink->protect_info, AVDT_TSEP_SRC);

  return p_sink;
}
@@ -1243,7 +1334,7 @@ const BtaAvCoSep* BtaAvCo::AttemptSinkCodecSelection(
  p_peer->p_source = p_source;

  SaveNewCodecConfig(p_peer, new_codec_config, p_source->num_protect,
                     p_source->protect_info);
                     p_source->protect_info, AVDT_TSEP_SNK);

  return p_source;
}
@@ -1318,12 +1409,20 @@ bool BtaAvCo::UpdateSelectableSinkCodec(const A2dpCodecConfig& codec_config,
void BtaAvCo::SaveNewCodecConfig(BtaAvCoPeer* p_peer,
                                 const uint8_t* new_codec_config,
                                 uint8_t num_protect,
                                 const uint8_t* p_protect_info) {
                                 const uint8_t* p_protect_info,
                                 const uint8_t t_local_sep) {
  log::verbose("peer {}", ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr));
  log::verbose("codec: {}", A2DP_CodecInfoString(new_codec_config));

  std::lock_guard<std::recursive_mutex> lock(peer_cache_->codec_lock_);
  bta_av_legacy_state_.setCodecConfig(new_codec_config);
  BtaAvCoState* reference_state = getStateFromLocalProfile(t_local_sep);
  if (reference_state == nullptr) {
    log::warn(
        "Invalid bta av state for peer_address : {} with local sep as :{}",
        ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr), t_local_sep);
    return;
  }
  reference_state->setCodecConfig(new_codec_config);
  memcpy(p_peer->codec_config, new_codec_config, AVDT_CODEC_SIZE);

  if (ContentProtectEnabled()) {
@@ -1333,11 +1432,29 @@ void BtaAvCo::SaveNewCodecConfig(BtaAvCoPeer* p_peer,
  }
}

BtaAvCoState* BtaAvCo::getStateFromPeer(const BtaAvCoPeer* p_peer) {
  if (IS_FLAG_ENABLED(a2dp_concurrent_source_sink)) {
    if (p_peer->uuid_to_connect == UUID_SERVCLASS_AUDIO_SINK) {
      return &bta_av_source_state_;
    } else if (p_peer->uuid_to_connect == UUID_SERVCLASS_AUDIO_SOURCE) {
      return &bta_av_sink_state_;
    } else {
      log::warn("Invalid bta av state for peer_address : {} with uuid as :{}",
                ADDRESS_TO_LOGGABLE_CSTR(p_peer->addr),
                p_peer->uuid_to_connect);
      return nullptr;
    }
  } else {
    return &bta_av_legacy_state_;
  }
}

bool BtaAvCo::SetCodecOtaConfig(BtaAvCoPeer* p_peer,
                                const uint8_t* p_ota_codec_config,
                                uint8_t num_protect,
                                const uint8_t* p_protect_info,
                                bool* p_restart_output) {
                                bool* p_restart_output,
                                const uint8_t t_local_sep) {
  uint8_t result_codec_config[AVDT_CODEC_SIZE];
  bool restart_input = false;
  bool restart_output = false;
@@ -1376,8 +1493,8 @@ bool BtaAvCo::SetCodecOtaConfig(BtaAvCoPeer* p_peer,

    *p_restart_output = true;
    p_peer->p_sink = p_sink;
    SaveNewCodecConfig(p_peer, result_codec_config, num_protect,
                       p_protect_info);
    SaveNewCodecConfig(p_peer, result_codec_config, num_protect, p_protect_info,
                       t_local_sep);
  }

  if (restart_input || config_updated) {
@@ -1569,7 +1686,15 @@ void bta_av_co_audio_update_mtu(tBTA_AV_HNDL bta_av_handle,
}

bool bta_av_co_set_active_peer(const RawAddress& peer_address) {
  return bta_av_co_cb.SetActivePeer(peer_address);
  return bta_av_co_cb.SetActivePeer(peer_address, AVDT_TSEP_INVALID);
}

bool bta_av_co_set_active_sink_peer(const RawAddress& peer_address) {
  return bta_av_co_cb.SetActivePeer(peer_address, AVDT_TSEP_SNK);
}

bool bta_av_co_set_active_source_peer(const RawAddress& peer_address) {
  return bta_av_co_cb.SetActivePeer(peer_address, AVDT_TSEP_SRC);
}

void bta_av_co_save_codec(const uint8_t* new_codec_config) {
+25 −4
Original line number Diff line number Diff line
@@ -288,9 +288,10 @@ class BtaAvCo {
   * Set the active peer.
   *
   * @param peer_address the peer address
   * @param t_local_sep update the active peer for the profile type.
   * @return true on success, otherwise false
   */
  bool SetActivePeer(const RawAddress& peer_address);
  bool SetActivePeer(const RawAddress& peer_address, const uint8_t t_local_sep);

  /**
   * Save the reconfig codec
@@ -434,9 +435,12 @@ class BtaAvCo {
   * @param new_codec_config the new codec configuration to use
   * @param num_protect the number of content protection elements
   * @param p_protect_info the content protection info to use
   * @param t_local_sep the profile for which the codec config needs to be
   * saved.
   */
  void SaveNewCodecConfig(BtaAvCoPeer* p_peer, const uint8_t* new_codec_config,
                          uint8_t num_protect, const uint8_t* p_protect_info);
                          uint8_t num_protect, const uint8_t* p_protect_info,
                          const uint8_t t_local_sep);

  /**
   * Set the Over-The-Air preferred codec configuration.
@@ -455,11 +459,12 @@ class BtaAvCo {
   * @param p_restart_output if there is a change in the encoder configuration
   * that requires restarting of the A2DP connection, flag |p_restart_output|
   * is set to true.
   * @param t_local_sep the profile for which ota config needs to be set.
   * @return true on success, otherwise false
   */
  bool SetCodecOtaConfig(BtaAvCoPeer* p_peer, const uint8_t* p_ota_codec_config,
                         uint8_t num_protect, const uint8_t* p_protect_info,
                         bool* p_restart_output);
                         bool* p_restart_output, const uint8_t t_local_sep);

  /**
   * Update all selectable Source codecs with the corresponding codec
@@ -540,9 +545,25 @@ class BtaAvCo {
      const ::bluetooth::audio::a2dp::provider::a2dp_configuration&
          provider_codec_config);

  /**
   * Returns the state that needs to be accessed.
   * @param p_peer peer address.
   * @return state of the profile.
   */
  BtaAvCoState* getStateFromPeer(const BtaAvCoPeer* p_peer);

  /**
   * Returns the state based on the local profile of the stack.
   * @param t_local_sep local sep type
   * @return state of the profile.
   */
  BtaAvCoState* getStateFromLocalProfile(const uint8_t t_local_sep);

  bool ContentProtectEnabled() const { return content_protect_enabled_; }

  const bool content_protect_enabled_;  // True if Content Protect is enabled
  uint8_t content_protect_flag_;        // Content Protect flag
  BtaAvCoState bta_av_legacy_state_;
  BtaAvCoState bta_av_legacy_state_;    // Legacy state
  BtaAvCoState bta_av_source_state_;    // Source profile state
  BtaAvCoState bta_av_sink_state_;      // Sink profile state
};
+14 −0
Original line number Diff line number Diff line
@@ -27,6 +27,20 @@
// Returns true on success, otherwise false.
bool bta_av_co_set_active_peer(const RawAddress& peer_addr);

/**
 * Sets the active peer within the sink profile of the bta av co instance.
 * @param peer_address peer address of the remote device.
 * @return true on success, otherwise false.
 */
bool bta_av_co_set_active_sink_peer(const RawAddress& peer_address);

/**
 * Sets the active peer within the sink profile of the bta av co instance.
 * @param peer_address peer address of the remote device.
 * @return true on success, otherwise false.
 */
bool bta_av_co_set_active_source_peer(const RawAddress& peer_address);

void bta_av_co_save_codec(const uint8_t* new_codec_config);

// Gets the A2DP peer parameters that are used to initialize the encoder.
+15 −6
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@

#include "btif/include/btif_a2dp_sink.h"

#include <android_bluetooth_flags.h>
#include <base/functional/bind.h>
#include <base/logging.h>
#include <bluetooth/log.h>
@@ -258,13 +259,21 @@ bool btif_a2dp_sink_restart_session(const RawAddress& old_peer_address,
  if (!old_peer_address.IsEmpty()) {
    btif_a2dp_sink_end_session(old_peer_address);
  }

  if (IS_FLAG_ENABLED(a2dp_concurrent_source_sink)) {
    if (!bta_av_co_set_active_sink_peer(new_peer_address)) {
      log::error("Cannot stream audio: cannot set active peer to {}",
                 ADDRESS_TO_LOGGABLE_STR(new_peer_address));
      peer_ready_promise.set_value();
      return false;
    }
  } else {
    if (!bta_av_co_set_active_peer(new_peer_address)) {
      log::error("Cannot stream audio: cannot set active peer to {}",
                 ADDRESS_TO_LOGGABLE_STR(new_peer_address));
      peer_ready_promise.set_value();
      return false;
    }
  }

  if (old_peer_address.IsEmpty()) {
    btif_a2dp_sink_startup();
+12 −5
Original line number Diff line number Diff line
@@ -578,12 +578,19 @@ static void btif_a2dp_source_setup_codec_delayed(

  tA2DP_ENCODER_INIT_PEER_PARAMS peer_params;
  bta_av_co_get_peer_params(peer_address, &peer_params);

  if (IS_FLAG_ENABLED(a2dp_concurrent_source_sink)) {
    if (!bta_av_co_set_active_source_peer(peer_address)) {
      log::error("Cannot stream audio: cannot set active peer to {}",
                 ADDRESS_TO_LOGGABLE_CSTR(peer_address));
      return;
    }
  } else {
    if (!bta_av_co_set_active_peer(peer_address)) {
      log::error("Cannot stream audio: cannot set active peer to {}",
                 ADDRESS_TO_LOGGABLE_CSTR(peer_address));
      return;
    }
  }
  btif_a2dp_source_cb.encoder_interface = bta_av_co_get_encoder_interface();
  if (btif_a2dp_source_cb.encoder_interface == nullptr) {
    log::error("Cannot stream audio: no source encoder interface");
Loading