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

Commit 9e59d28e authored by Qasim Javed's avatar Qasim Javed
Browse files

Wait until A2DP source shutdown completes when active peer is set to the empty address.

Currently, there is a race condition when switching A2DP devices. We
first set the active peer to the empty address and then to the newly
active device. When the active peer is set to the empty address, we
shutdown the A2DP source which takes time. Before that shutdown
completes, we try to set the active peer to the newly active device.
Since the source has not finished shutting down completely, this request
to start a new A2DP source is ignored by the stack.

Fix this by waiting until shutdown is complete and A2DP source state is
set to kStateOff. This way, when setActivePeer with empty address
returns, A2DP source state would already have been set to kStateOff.

Bug: 253974905
Tag: #refactor
Test: manual by using log patterns

Change-Id: I2a51abfd3a68e5efd66dc117fda4b0697816bb04
parent 064b49b4
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -63,7 +63,7 @@ bool btif_a2dp_source_end_session(const RawAddress& peer_address);

// Shutdown the A2DP Source module.
// This function should be called by the BTIF state machine to stop streaming.
void btif_a2dp_source_shutdown(void);
void btif_a2dp_source_shutdown(std::promise<void>);

// Cleanup the A2DP Source module.
// This function should be called by the BTIF state machine during graceful
+11 −5
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@
#include <string.h>

#include <algorithm>
#include <future>

#include "audio_a2dp_hw/include/audio_a2dp_hw.h"
#include "audio_hal_interface/a2dp_encoding.h"
@@ -242,7 +243,7 @@ static void btif_a2dp_source_start_session_delayed(
    const RawAddress& peer_address, std::promise<void> start_session_promise);
static void btif_a2dp_source_end_session_delayed(
    const RawAddress& peer_address);
static void btif_a2dp_source_shutdown_delayed(void);
static void btif_a2dp_source_shutdown_delayed(std::promise<void>);
static void btif_a2dp_source_cleanup_delayed(void);
static void btif_a2dp_source_audio_tx_start_event(void);
static void btif_a2dp_source_audio_tx_stop_event(void);
@@ -479,7 +480,7 @@ static void btif_a2dp_source_end_session_delayed(
  }
}

void btif_a2dp_source_shutdown(void) {
void btif_a2dp_source_shutdown(std::promise<void> shutdown_complete_promise) {
  LOG_INFO("%s: state=%s", __func__, btif_a2dp_source_cb.StateStr().c_str());

  if ((btif_a2dp_source_cb.State() == BtifA2dpSource::kStateOff) ||
@@ -491,10 +492,12 @@ void btif_a2dp_source_shutdown(void) {
  btif_a2dp_source_cb.SetState(BtifA2dpSource::kStateShuttingDown);

  btif_a2dp_source_thread.DoInThread(
      FROM_HERE, base::Bind(&btif_a2dp_source_shutdown_delayed));
      FROM_HERE, base::BindOnce(&btif_a2dp_source_shutdown_delayed,
                                std::move(shutdown_complete_promise)));
}

static void btif_a2dp_source_shutdown_delayed(void) {
static void btif_a2dp_source_shutdown_delayed(
    std::promise<void> shutdown_complete_promise) {
  LOG_INFO("%s: state=%s", __func__, btif_a2dp_source_cb.StateStr().c_str());

  // Stop the timer
@@ -510,13 +513,16 @@ static void btif_a2dp_source_shutdown_delayed(void) {
  btif_a2dp_source_cb.tx_audio_queue = nullptr;

  btif_a2dp_source_cb.SetState(BtifA2dpSource::kStateOff);

  shutdown_complete_promise.set_value();
}

void btif_a2dp_source_cleanup(void) {
  LOG_INFO("%s: state=%s", __func__, btif_a2dp_source_cb.StateStr().c_str());

  // Make sure the source is shutdown
  btif_a2dp_source_shutdown();
  std::promise<void> shutdown_complete_promise;
  btif_a2dp_source_shutdown(std::move(shutdown_complete_promise));

  btif_a2dp_source_thread.DoInThread(
      FROM_HERE, base::Bind(&btif_a2dp_source_cleanup_delayed));
+10 −1
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@
#include <frameworks/proto_logging/stats/enums/bluetooth/a2dp/enums.pb.h>
#include <frameworks/proto_logging/stats/enums/bluetooth/enums.pb.h>

#include <chrono>
#include <cstdint>
#include <future>
#include <memory>
@@ -501,7 +502,15 @@ class BtifAvSource {
                     << ": unable to set active peer to empty in BtaAvCo";
      }
      btif_a2dp_source_end_session(active_peer_);
      btif_a2dp_source_shutdown();
      std::promise<void> shutdown_complete_promise;
      std::future<void> shutdown_complete_future =
          shutdown_complete_promise.get_future();
      btif_a2dp_source_shutdown(std::move(shutdown_complete_promise));
      using namespace std::chrono_literals;
      if (shutdown_complete_future.wait_for(1s) ==
          std::future_status::timeout) {
        LOG_ERROR("Timed out waiting for A2DP source shutdown to complete.");
      }
      active_peer_ = peer_address;
      peer_ready_promise.set_value();
      return true;