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

Commit 2d064031 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "A2DP: When changing codec, resume the audio session after AVDTP_Reconfig done"

parents d1e5fa6a b441fff5
Loading
Loading
Loading
Loading
+16 −22
Original line number Diff line number Diff line
@@ -417,10 +417,14 @@ class BtaAvCo {
   *
   * @param peer_address the peer address
   * @param codec_user_config the codec user configuration to set
   * @param p_restart_output if there is a change in the encoder configuration
   * that requires restarting of the A2DP connection, flag |p_restart_output|
   * will be set to true.
   * @return true on success, otherwise false
   */
  bool SetCodecUserConfig(const RawAddress& peer_address,
                          const btav_a2dp_codec_config_t& codec_user_config);
                          const btav_a2dp_codec_config_t& codec_user_config,
                          bool* p_restart_output);

  /**
   * Set the codec audio configuration.
@@ -1379,31 +1383,17 @@ void BtaAvCo::ProcessAudioDelay(tBTA_AV_HNDL bta_av_handle,

void BtaAvCo::UpdateMtu(tBTA_AV_HNDL bta_av_handle,
                        const RawAddress& peer_address, uint16_t mtu) {
  APPL_TRACE_DEBUG("%s: peer %s bta_av_handle: 0x%x mtu: %d", __func__,
                   peer_address.ToString().c_str(), bta_av_handle, mtu);
  LOG(INFO) << __func__ << ": peer " << peer_address
            << " bta_av_handle: " << loghex(bta_av_handle) << " mtu: " << mtu;

  // Find the peer
  BtaAvCoPeer* p_peer = FindPeerAndUpdate(bta_av_handle, peer_address);
  if (p_peer == nullptr) {
    APPL_TRACE_ERROR(
        "%s: could not find peer entry for bta_av_handle 0x%x peer %s",
        __func__, bta_av_handle, peer_address.ToString().c_str());
    LOG(ERROR) << __func__ << ": could not find peer entry for bta_av_handle "
               << loghex(bta_av_handle) << " peer " << peer_address;
    return;
  }

  if (p_peer->mtu == mtu) return;

  p_peer->mtu = mtu;
  if (active_peer_ == p_peer) {
    LOG(INFO) << __func__ << ": update the codec encoder with peer "
              << peer_address << " bta_av_handle: " << loghex(bta_av_handle)
              << ", new MTU: " << mtu;
    // Send a request with NONE config values to update only the MTU.
    SetCodecAudioConfig(
        {.sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_NONE,
         .bits_per_sample = BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE,
         .channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_NONE});
  }
}

bool BtaAvCo::SetActivePeer(const RawAddress& peer_address) {
@@ -1472,7 +1462,7 @@ const tA2DP_DECODER_INTERFACE* BtaAvCo::GetSinkDecoderInterface() {

bool BtaAvCo::SetCodecUserConfig(
    const RawAddress& peer_address,
    const btav_a2dp_codec_config_t& codec_user_config) {
    const btav_a2dp_codec_config_t& codec_user_config, bool* p_restart_output) {
  uint8_t result_codec_config[AVDT_CODEC_SIZE];
  const BtaAvCoSep* p_sink = nullptr;
  bool restart_input = false;
@@ -1483,6 +1473,8 @@ bool BtaAvCo::SetCodecUserConfig(
  VLOG(1) << __func__ << ": peer_address=" << peer_address
          << " codec_user_config={" << codec_user_config.ToString() << "}";

  *p_restart_output = false;

  BtaAvCoPeer* p_peer = FindPeer(peer_address);
  if (p_peer == nullptr) {
    LOG(ERROR) << __func__ << ": cannot find peer " << peer_address
@@ -1544,6 +1536,7 @@ bool BtaAvCo::SetCodecUserConfig(
            << loghex(p_peer->BtaAvHandle()) << ")";
    BTA_AvReconfig(p_peer->BtaAvHandle(), true, p_sink->sep_info_idx,
                   p_peer->codec_config, num_protect, bta_av_co_cp_scmst);
    *p_restart_output = true;
  }

done:
@@ -2177,8 +2170,9 @@ const tA2DP_DECODER_INTERFACE* bta_av_co_get_decoder_interface(void) {

bool bta_av_co_set_codec_user_config(
    const RawAddress& peer_address,
    const btav_a2dp_codec_config_t& codec_user_config) {
  return bta_av_co_cb.SetCodecUserConfig(peer_address, codec_user_config);
    const btav_a2dp_codec_config_t& codec_user_config, bool* p_restart_output) {
  return bta_av_co_cb.SetCodecUserConfig(peer_address, codec_user_config,
                                         p_restart_output);
}

bool bta_av_co_set_codec_audio_config(
+2 −1
Original line number Diff line number Diff line
@@ -89,7 +89,8 @@ void btif_a2dp_source_stop_audio_req(void);
// |codec_user_config| contains the preferred codec user configuration.
void btif_a2dp_source_encoder_user_config_update_req(
    const RawAddress& peer_addr,
    const btav_a2dp_codec_config_t& codec_user_config);
    const std::vector<btav_a2dp_codec_config_t>& codec_user_preferences,
    std::promise<void> peer_ready_promise);

// Process a request to update the A2DP audio encoding with new audio
// configuration feeding parameters stored in |codec_audio_config|.
+2 −1
Original line number Diff line number Diff line
@@ -48,10 +48,11 @@ const tA2DP_DECODER_INTERFACE* bta_av_co_get_decoder_interface(void);
// Sets the user preferred codec configuration.
// The peer address is |peer_addr|.
// |codec_user_config| contains the preferred codec configuration.
// |restart_output| is used to know whether AV is reconfiguring with remote.
// Returns true on success, otherwise false.
bool bta_av_co_set_codec_user_config(
    const RawAddress& peer_addr,
    const btav_a2dp_codec_config_t& codec_user_config);
    const btav_a2dp_codec_config_t& codec_user_config, bool* p_restart_output);

// Sets the Audio HAL selected audio feeding parameters.
// Those parameters are applied only to the currently selected codec.
+49 −14
Original line number Diff line number Diff line
@@ -246,7 +246,8 @@ static void btif_a2dp_source_setup_codec_delayed(
    const RawAddress& peer_address);
static void btif_a2dp_source_encoder_user_config_update_event(
    const RawAddress& peer_address,
    const btav_a2dp_codec_config_t& codec_user_config);
    const std::vector<btav_a2dp_codec_config_t>& codec_user_preferences,
    std::promise<void> peer_ready_promise);
static void btif_a2dp_source_audio_feeding_update_event(
    const btav_a2dp_codec_config_t& codec_audio_config);
static bool btif_a2dp_source_audio_tx_flush_req(void);
@@ -618,23 +619,57 @@ void btif_a2dp_source_stop_audio_req(void) {

void btif_a2dp_source_encoder_user_config_update_req(
    const RawAddress& peer_address,
    const btav_a2dp_codec_config_t& codec_user_config) {
  LOG_INFO(LOG_TAG, "%s: peer_address=%s state=%s", __func__,
           peer_address.ToString().c_str(),
           btif_a2dp_source_cb.StateStr().c_str());
  btif_a2dp_source_thread.DoInThread(
      FROM_HERE, base::Bind(&btif_a2dp_source_encoder_user_config_update_event,
                            peer_address, codec_user_config));
    const std::vector<btav_a2dp_codec_config_t>& codec_user_preferences,
    std::promise<void> peer_ready_promise) {
  LOG(INFO) << __func__ << ": peer_address=" << peer_address
            << " state=" << btif_a2dp_source_cb.StateStr() << " "
            << codec_user_preferences.size() << " codec_preference(s)";
  if (!btif_a2dp_source_thread.DoInThread(
          FROM_HERE,
          base::BindOnce(&btif_a2dp_source_encoder_user_config_update_event,
                         peer_address, codec_user_preferences,
                         std::move(peer_ready_promise)))) {
    // cannot set promise but triggers crash
    LOG(FATAL) << __func__ << ": peer_address=" << peer_address
               << " state=" << btif_a2dp_source_cb.StateStr()
               << " fails to context switch";
  }
}

static void btif_a2dp_source_encoder_user_config_update_event(
    const RawAddress& peer_address,
    const btav_a2dp_codec_config_t& codec_user_config) {
  LOG_INFO(LOG_TAG, "%s: peer_address=%s state=%s", __func__,
           peer_address.ToString().c_str(),
           btif_a2dp_source_cb.StateStr().c_str());
  if (!bta_av_co_set_codec_user_config(peer_address, codec_user_config)) {
    LOG_ERROR(LOG_TAG, "%s: cannot update codec user configuration", __func__);
    const std::vector<btav_a2dp_codec_config_t>& codec_user_preferences,
    std::promise<void> peer_ready_promise) {
  bool restart_output = false;
  bool success = false;
  for (auto codec_user_config : codec_user_preferences) {
    success = bta_av_co_set_codec_user_config(peer_address, codec_user_config,
                                              &restart_output);
    if (success) {
      LOG(INFO) << __func__ << ": peer_address=" << peer_address
                << " state=" << btif_a2dp_source_cb.StateStr()
                << " codec_preference={" << codec_user_config.ToString()
                << "} restart_output=" << (restart_output ? "true" : "false");
      break;
    }
  }
  if (success && restart_output) {
    // Codec reconfiguration is in progress, and it is safe to unlock since
    // remaining tasks like starting audio session and reporting new codec
    // will be handled by BTA_AV_RECONFIG_EVT later.
    peer_ready_promise.set_value();
    return;
  }
  if (!success) {
    LOG(ERROR) << __func__ << ": cannot update codec user configuration(s)";
  }
  if (!peer_address.IsEmpty() && peer_address == btif_av_source_active_peer()) {
    // No more actions needed with remote, and if succeed, user had changed the
    // config like the bits per sample only. Let's resume the session now.
    btif_a2dp_source_start_session(peer_address, std::move(peer_ready_promise));
  } else {
    // Unlock for non-active peer
    peer_ready_promise.set_value();
  }
}

+37 −25
Original line number Diff line number Diff line
@@ -494,23 +494,12 @@ class BtifAvSource {
      const std::vector<btav_a2dp_codec_config_t>& codec_preferences,
      std::promise<void> peer_ready_promise) {
    // Restart the session if the codec for the active peer is updated
    bool restart_session =
        ((active_peer_ == peer_address) && !active_peer_.IsEmpty());
    if (restart_session) {
    if (!peer_address.IsEmpty() && active_peer_ == peer_address) {
      btif_a2dp_source_end_session(active_peer_);
    }

    for (auto cp : codec_preferences) {
      BTIF_TRACE_DEBUG("%s: codec_preference=%s", __func__,
                       cp.ToString().c_str());
      btif_a2dp_source_encoder_user_config_update_req(peer_address, cp);
    }
    if (restart_session) {
      btif_a2dp_source_start_session(active_peer_,
                                     std::move(peer_ready_promise));
    } else {
      peer_ready_promise.set_value();
    }
    btif_a2dp_source_encoder_user_config_update_req(
        peer_address, codec_preferences, std::move(peer_ready_promise));
  }

  const std::map<RawAddress, BtifAvPeer*>& Peers() const { return peers_; }
@@ -1906,19 +1895,37 @@ bool BtifAvStateMachine::StateOpened::ProcessEvent(uint32_t event,
      break;

    case BTA_AV_RECONFIG_EVT:
      if (peer_.CheckFlags(BtifAvPeer::kFlagPendingStart) &&
          (p_av->reconfig.status == BTA_AV_SUCCESS)) {
        LOG_INFO(LOG_TAG,
                 "%s : Peer %s : Reconfig done - calling BTA_AvStart()",
                 __PRETTY_FUNCTION__, peer_.PeerAddress().ToString().c_str());
        BTA_AvStart(peer_.BtaHandle());
      } else if (peer_.CheckFlags(BtifAvPeer::kFlagPendingStart)) {
        BTIF_TRACE_WARNING("%s: Peer %s : failed reconfiguration",
                           __PRETTY_FUNCTION__,
                           peer_.PeerAddress().ToString().c_str());
      if (p_av->reconfig.status != BTA_AV_SUCCESS) {
        LOG(WARNING) << __PRETTY_FUNCTION__ << ": Peer " << peer_.PeerAddress()
                     << " : failed reconfiguration";
        if (peer_.CheckFlags(BtifAvPeer::kFlagPendingStart)) {
          LOG(ERROR) << __PRETTY_FUNCTION__ << ": Peer " << peer_.PeerAddress()
                     << " : cannot proceed to do AvStart";
          peer_.ClearFlags(BtifAvPeer::kFlagPendingStart);
          btif_a2dp_command_ack(A2DP_CTRL_ACK_FAILURE);
        }
        if (peer_.IsSink()) {
          src_disconnect_sink(peer_.PeerAddress());
        } else if (peer_.IsSource()) {
          sink_disconnect_src(peer_.PeerAddress());
        }
        break;
      }

      if (peer_.IsActivePeer()) {
        LOG(INFO) << __PRETTY_FUNCTION__ << " : Peer " << peer_.PeerAddress()
                  << " : Reconfig done - calling startSession() to audio HAL";
        std::promise<void> peer_ready_promise;
        std::future<void> peer_ready_future = peer_ready_promise.get_future();
        btif_a2dp_source_start_session(peer_.PeerAddress(),
                                       std::move(peer_ready_promise));
      }
      if (peer_.CheckFlags(BtifAvPeer::kFlagPendingStart)) {
        LOG(INFO) << __PRETTY_FUNCTION__ << " : Peer " << peer_.PeerAddress()
                  << " : Reconfig done - calling BTA_AvStart("
                  << loghex(peer_.BtaHandle()) << ")";
        BTA_AvStart(peer_.BtaHandle());
      }
      break;

    case BTIF_AV_CONNECT_REQ_EVT: {
@@ -2805,6 +2812,11 @@ static bt_status_t codec_config_src(
    return BT_STATUS_NOT_READY;
  }

  if (peer_address.IsEmpty()) {
    LOG(WARNING) << __func__ << ": BTIF AV Source needs peer to config";
    return BT_STATUS_PARM_INVALID;
  }

  std::promise<void> peer_ready_promise;
  std::future<void> peer_ready_future = peer_ready_promise.get_future();
  bt_status_t status = do_in_main_thread(