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

Commit 6eb81c0d authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "Add explicit init/cleanup steps for A2DP Source and Sink"

parents 9c6a8400 5107d68a
Loading
Loading
Loading
Loading
+15 −4
Original line number Diff line number Diff line
@@ -38,16 +38,27 @@ typedef enum {
  BTIF_A2DP_SINK_FOCUS_GRANTED = 1
} btif_a2dp_sink_focus_state_t;

// Initialize and startup the A2DP Sink module.
// Initialize the A2DP Sink module.
// This function should be called by the BTIF state machine prior to using the
// module.
bool btif_a2dp_sink_init(void);

// Startup the A2DP Sink module.
// This function should be called by the BTIF state machine after
// btif_a2dp_sink_init() to prepare for receiving and processing audio
// streaming.
bool btif_a2dp_sink_startup(void);

// Shutdown and cleanup the A2DP Sink module.
// This function should be called by the BTIF state machine during
// graceful shutdown and cleanup.
// Shutdown the A2DP Sink module.
// This function should be called by the BTIF state machine before
// btif_a2dp_sink_cleanup() to shutdown the processing of the audio streaming.
void btif_a2dp_sink_shutdown(void);

// Cleanup the A2DP Sink module.
// This function should be called by the BTIF state machine during graceful
// cleanup.
void btif_a2dp_sink_cleanup(void);

// Get the audio sample rate for the A2DP Sink module.
tA2DP_SAMPLE_RATE btif_a2dp_sink_get_sample_rate(void);

+13 −4
Original line number Diff line number Diff line
@@ -24,16 +24,25 @@

#include "bta_av_api.h"

// Initialize and startup the A2DP Source module.
// Initialize the A2DP Source module.
// This function should be called by the BTIF state machine prior to using the
// module.
bool btif_a2dp_source_init(void);

// Startup the A2DP Source module.
// This function should be called by the BTIF state machine after
// btif_a2dp_source_init() to prepare to start streaming.
bool btif_a2dp_source_startup(void);

// Shutdown and cleanup the A2DP Source module.
// This function should be called by the BTIF state machine during
// graceful shutdown and cleanup.
// Shutdown the A2DP Source module.
// This function should be called by the BTIF state machine to stop streaming.
void btif_a2dp_source_shutdown(void);

// Cleanup the A2DP Source module.
// This function should be called by the BTIF state machine during graceful
// cleanup.
void btif_a2dp_source_cleanup(void);

// Check whether the A2DP Source media task is running.
// Returns true if the A2DP Source media task is running, otherwise false.
bool btif_a2dp_source_media_task_is_running(void);
+34 −6
Original line number Diff line number Diff line
@@ -93,8 +93,10 @@ static tBTIF_A2DP_SINK_CB btif_a2dp_sink_cb;

static std::atomic<int> btif_a2dp_sink_state{BTIF_A2DP_SINK_STATE_OFF};

static void btif_a2dp_sink_init_delayed(void* context);
static void btif_a2dp_sink_startup_delayed(void* context);
static void btif_a2dp_sink_shutdown_delayed(void* context);
static void btif_a2dp_sink_cleanup_delayed(void* context);
static void btif_a2dp_sink_command_ready(fixed_queue_t* queue, void* context);
static void btif_a2dp_sink_audio_handle_stop_decoding(void);
static void btif_decode_alarm_cb(void* context);
@@ -123,7 +125,7 @@ UNUSED_ATTR static const char* dump_media_event(uint16_t event) {
  return "UNKNOWN A2DP SINK EVENT";
}

bool btif_a2dp_sink_startup(void) {
bool btif_a2dp_sink_init(void) {
  LockGuard lock(g_mutex);

  if (btif_a2dp_sink_state != BTIF_A2DP_SINK_STATE_OFF) {
@@ -156,22 +158,48 @@ bool btif_a2dp_sink_startup(void) {

  APPL_TRACE_EVENT("## A2DP SINK MEDIA THREAD STARTED ##");

  /* Schedule the rest of the startup operations */
  thread_post(btif_a2dp_sink_cb.worker_thread, btif_a2dp_sink_startup_delayed,
  /* Schedule the rest of the operations */
  thread_post(btif_a2dp_sink_cb.worker_thread, btif_a2dp_sink_init_delayed,
              NULL);

  return true;
}

static void btif_a2dp_sink_startup_delayed(UNUSED_ATTR void* context) {
static void btif_a2dp_sink_init_delayed(UNUSED_ATTR void* context) {
  raise_priority_a2dp(TASK_HIGH_MEDIA);
  btif_a2dp_sink_state = BTIF_A2DP_SINK_STATE_RUNNING;
}

bool btif_a2dp_sink_startup(void) {
  LockGuard lock(g_mutex);
  thread_post(btif_a2dp_sink_cb.worker_thread, btif_a2dp_sink_startup_delayed,
              NULL);
  return true;
}

static void btif_a2dp_sink_startup_delayed(UNUSED_ATTR void* context) {
  LockGuard lock(g_mutex);
  // Nothing to do
}

void btif_a2dp_sink_shutdown(void) {
  LockGuard lock(g_mutex);
  thread_post(btif_a2dp_sink_cb.worker_thread, btif_a2dp_sink_shutdown_delayed,
              NULL);
}

static void btif_a2dp_sink_shutdown_delayed(UNUSED_ATTR void* context) {
  // Nothing to do
}

void btif_a2dp_sink_cleanup(void) {
  alarm_t* decode_alarm;
  fixed_queue_t* cmd_msg_queue;
  thread_t* worker_thread;

  // Make sure the sink is shutdown
  btif_a2dp_sink_shutdown();

  {
    LockGuard lock(g_mutex);
    if ((btif_a2dp_sink_state == BTIF_A2DP_SINK_STATE_OFF) ||
@@ -198,11 +226,11 @@ void btif_a2dp_sink_shutdown(void) {

  // Exit the thread
  fixed_queue_free(cmd_msg_queue, NULL);
  thread_post(worker_thread, btif_a2dp_sink_shutdown_delayed, NULL);
  thread_post(worker_thread, btif_a2dp_sink_cleanup_delayed, NULL);
  thread_free(worker_thread);
}

static void btif_a2dp_sink_shutdown_delayed(UNUSED_ATTR void* context) {
static void btif_a2dp_sink_cleanup_delayed(UNUSED_ATTR void* context) {
  LockGuard lock(g_mutex);
  fixed_queue_free(btif_a2dp_sink_cb.rx_audio_queue, NULL);
  btif_a2dp_sink_cb.rx_audio_queue = NULL;
+36 −10
Original line number Diff line number Diff line
@@ -296,8 +296,10 @@ class BtifA2dpSource {
static BtWorkerThread btif_a2dp_source_thread("btif_a2dp_source_thread");
static BtifA2dpSource btif_a2dp_source_cb;

static void btif_a2dp_source_init_delayed(void);
static void btif_a2dp_source_startup_delayed(void);
static void btif_a2dp_source_shutdown_delayed(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);
static void btif_a2dp_source_audio_tx_flush_event(void);
@@ -372,6 +374,21 @@ void btif_a2dp_source_accumulate_stats(BtifMediaStats* src,
  src->Reset();
}

bool btif_a2dp_source_init(void) {
  // Start A2DP Source media task
  APPL_TRACE_EVENT("## A2DP SOURCE START MEDIA THREAD ##");
  btif_a2dp_source_thread.StartUp();
  APPL_TRACE_EVENT("## A2DP SOURCE MEDIA THREAD STARTED ##");

  btif_a2dp_source_thread.DoInThread(
      FROM_HERE, base::Bind(&btif_a2dp_source_init_delayed));
  return true;
}

static void btif_a2dp_source_init_delayed(void) {
  // Nothing to do
}

bool btif_a2dp_source_startup(void) {
  if (btif_a2dp_source_cb.State() != BtifA2dpSource::kStateOff) {
    APPL_TRACE_ERROR("%s: A2DP Source media task already running", __func__);
@@ -382,13 +399,6 @@ bool btif_a2dp_source_startup(void) {
  btif_a2dp_source_cb.SetState(BtifA2dpSource::kStateStartingUp);
  btif_a2dp_source_cb.tx_audio_queue = fixed_queue_new(SIZE_MAX);

  APPL_TRACE_EVENT("## A2DP SOURCE START MEDIA THREAD ##");

  /* Start A2DP Source media task */
  btif_a2dp_source_thread.StartUp();

  APPL_TRACE_EVENT("## A2DP SOURCE MEDIA THREAD STARTED ##");

  /* Schedule the rest of the startup operations */
  btif_a2dp_source_thread.DoInThread(
      FROM_HERE, base::Bind(&btif_a2dp_source_startup_delayed));
@@ -413,12 +423,12 @@ void btif_a2dp_source_shutdown(void) {
  /* Make sure no channels are restarted while shutting down */
  btif_a2dp_source_cb.SetState(BtifA2dpSource::kStateShuttingDown);

  APPL_TRACE_EVENT("## A2DP SOURCE STOP MEDIA THREAD ##");
  // Stop the timer
  alarm_free(btif_a2dp_source_cb.media_alarm);
  btif_a2dp_source_cb.media_alarm = nullptr;

  // Exit the thread
  btif_a2dp_source_thread.DoInThread(
      FROM_HERE, base::Bind(&btif_a2dp_source_shutdown_delayed));
  btif_a2dp_source_thread.ShutDown();
}

static void btif_a2dp_source_shutdown_delayed(void) {
@@ -435,6 +445,22 @@ static void btif_a2dp_source_shutdown_delayed(void) {
      system_bt_osi::DISCONNECT_REASON_UNKNOWN, 0);
}

void btif_a2dp_source_cleanup(void) {
  // Make sure the source is shutdown
  btif_a2dp_source_shutdown();

  btif_a2dp_source_thread.DoInThread(
      FROM_HERE, base::Bind(&btif_a2dp_source_cleanup_delayed));

  // Exit the thread
  APPL_TRACE_EVENT("## A2DP SOURCE STOP MEDIA THREAD ##");
  btif_a2dp_source_thread.ShutDown();
}

static void btif_a2dp_source_cleanup_delayed(void) {
  // Nothing to do
}

bool btif_a2dp_source_media_task_is_running(void) {
  return (btif_a2dp_source_cb.State() == BtifA2dpSource::kStateRunning);
}
+6 −6
Original line number Diff line number Diff line
@@ -822,8 +822,8 @@ bt_status_t BtifAvSource::Init(
  codec_priorities_ = codec_priorities;
  bta_av_co_init(codec_priorities_);

  if (!btif_a2dp_source_startup()) {
    return BT_STATUS_FAIL;  // Already running
  if (!btif_a2dp_source_init()) {
    return BT_STATUS_FAIL;
  }
  btif_enable_service(BTA_A2DP_SOURCE_SERVICE_ID);
  enabled_ = true;
@@ -834,7 +834,7 @@ void BtifAvSource::Cleanup() {
  if (!enabled_) return;

  btif_queue_cleanup(UUID_SERVCLASS_AUDIO_SOURCE);
  do_in_jni_thread(FROM_HERE, base::Bind(&btif_a2dp_source_shutdown));
  do_in_jni_thread(FROM_HERE, base::Bind(&btif_a2dp_source_cleanup));

  btif_disable_service(BTA_A2DP_SOURCE_SERVICE_ID);
  CleanupAllPeers();
@@ -993,8 +993,8 @@ bt_status_t BtifAvSink::Init(btav_sink_callbacks_t* callbacks) {
                             kDefaultMaxConnectedAudioDevices);
  callbacks_ = callbacks;

  if (!btif_a2dp_sink_startup()) {
    return BT_STATUS_FAIL;  // Already running
  if (!btif_a2dp_sink_init()) {
    return BT_STATUS_FAIL;
  }
  btif_enable_service(BTA_A2DP_SINK_SERVICE_ID);
  enabled_ = true;
@@ -1005,7 +1005,7 @@ void BtifAvSink::Cleanup() {
  if (!enabled_) return;

  btif_queue_cleanup(UUID_SERVCLASS_AUDIO_SINK);
  do_in_jni_thread(FROM_HERE, base::Bind(&btif_a2dp_sink_shutdown));
  do_in_jni_thread(FROM_HERE, base::Bind(&btif_a2dp_sink_cleanup));

  btif_disable_service(BTA_A2DP_SINK_SERVICE_ID);
  CleanupAllPeers();