Start/End session is called when setting/changing the Active (remote)
device.
Also:
* For A2DP Source, btif_a2dp_source_setup_codec() is called only for
Start session. All other calls to btif_a2dp_source_setup_codec are
removed.
* Updated the btif_a2dp_source_setup_codec() implementation to
call btif_a2dp_source_audio_tx_flush_req() and flush the incoming audio
data. This removes 2 seconds hold-up delay when switching the active
device and streaming audio.
* Removed unnecessary lock inside btif/src/btif_a2dp_sink.cc
Bug:
74952724
Test: Manual - Connect two headsets, switch active device,
connect/disconnect.
Change-Id: I43702e1ddc108628de93161905465647471f554c
Merged-In: I43702e1ddc108628de93161905465647471f554c
(cherry picked from commit
03adb3f7ba37d637329d3c13aa4a3bb1ec28f143)
// streaming.
bool btif_a2dp_sink_startup(void);
+// Start the A2DP Sink session.
+// This function should be called by the BTIF state machine after
+// btif_a2dp_sink_startup() to start the streaming session for |peer_address|.
+bool btif_a2dp_sink_start_session(const RawAddress& peer_address);
+
+// End the A2DP Sink session.
+// This function should be called by the BTIF state machine to end the
+// streaming session for |peer_address|.
+bool btif_a2dp_sink_end_session(const RawAddress& peer_address);
+
// 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.
// btif_a2dp_source_init() to prepare to start streaming.
bool btif_a2dp_source_startup(void);
+// Start the A2DP Source session.
+// This function should be called by the BTIF state machine after
+// btif_a2dp_source_startup() to start the streaming session for |peer_address|.
+bool btif_a2dp_source_start_session(const RawAddress& peer_address);
+
+// End the A2DP Source session.
+// This function should be called by the BTIF state machine to end the
+// streaming session for |peer_address|.
+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);
ack = true;
}
} else {
- /* We were remotely started, make sure codec
- * is setup before datapath is started.
- */
- btif_a2dp_source_setup_codec(peer_addr);
+ // We were started remotely
if (btif_av_is_a2dp_offload_enabled()) {
btif_av_stream_start_offload();
}
static void btif_a2dp_sink_init_delayed(void* context);
static void btif_a2dp_sink_startup_delayed(void* context);
+static void btif_a2dp_sink_start_session_delayed(void* context);
+static void btif_a2dp_sink_end_session_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);
bool btif_a2dp_sink_startup(void) {
LOG_INFO(LOG_TAG, "%s", __func__);
- LockGuard lock(g_mutex);
thread_post(btif_a2dp_sink_cb.worker_thread, btif_a2dp_sink_startup_delayed,
NULL);
return true;
// Nothing to do
}
-void btif_a2dp_sink_shutdown(void) {
+bool btif_a2dp_sink_start_session(const RawAddress& peer_address) {
+ LOG_INFO(LOG_TAG, "%s: peer_address=%s", __func__,
+ peer_address.ToString().c_str());
+ thread_post(btif_a2dp_sink_cb.worker_thread,
+ btif_a2dp_sink_start_session_delayed, NULL);
+ return true;
+}
+
+static void btif_a2dp_sink_start_session_delayed(UNUSED_ATTR void* context) {
+ LOG_INFO(LOG_TAG, "%s", __func__);
+ LockGuard lock(g_mutex);
+ // Nothing to do
+}
+
+bool btif_a2dp_sink_end_session(const RawAddress& peer_address) {
+ LOG_INFO(LOG_TAG, "%s: peer_address=%s", __func__,
+ peer_address.ToString().c_str());
+ thread_post(btif_a2dp_sink_cb.worker_thread,
+ btif_a2dp_sink_end_session_delayed, NULL);
+ return true;
+}
+
+static void btif_a2dp_sink_end_session_delayed(UNUSED_ATTR void* context) {
LOG_INFO(LOG_TAG, "%s", __func__);
LockGuard lock(g_mutex);
+ // Nothing to do
+}
+
+void btif_a2dp_sink_shutdown(void) {
+ LOG_INFO(LOG_TAG, "%s", __func__);
thread_post(btif_a2dp_sink_cb.worker_thread, btif_a2dp_sink_shutdown_delayed,
NULL);
}
static void btif_a2dp_source_init_delayed(void);
static void btif_a2dp_source_startup_delayed(void);
+static void btif_a2dp_source_start_session_delayed(
+ const RawAddress& peer_address);
+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_cleanup_delayed(void);
static void btif_a2dp_source_audio_tx_start_event(void);
system_bt_osi::CONNECTION_TECHNOLOGY_TYPE_BREDR, 0);
}
+bool btif_a2dp_source_start_session(const RawAddress& peer_address) {
+ LOG_INFO(LOG_TAG, "%s: peer_address=%s", __func__,
+ peer_address.ToString().c_str());
+ btif_a2dp_source_setup_codec(peer_address);
+ btif_a2dp_source_thread.DoInThread(
+ FROM_HERE,
+ base::Bind(&btif_a2dp_source_start_session_delayed, peer_address));
+ return true;
+}
+
+static void btif_a2dp_source_start_session_delayed(
+ const RawAddress& peer_address) {
+ LOG_INFO(LOG_TAG, "%s: peer_address=%s", __func__,
+ peer_address.ToString().c_str());
+ if (btif_a2dp_source_cb.State() != BtifA2dpSource::kStateRunning) {
+ LOG_ERROR(LOG_TAG, "%s: A2DP Source media task is not running", __func__);
+ return;
+ }
+}
+
+bool btif_a2dp_source_end_session(const RawAddress& peer_address) {
+ LOG_INFO(LOG_TAG, "%s: peer_address=%s", __func__,
+ peer_address.ToString().c_str());
+ btif_a2dp_source_thread.DoInThread(
+ FROM_HERE,
+ base::Bind(&btif_a2dp_source_end_session_delayed, peer_address));
+ return true;
+}
+
+static void btif_a2dp_source_end_session_delayed(
+ const RawAddress& peer_address) {
+ LOG_INFO(LOG_TAG, "%s: peer_address=%s", __func__,
+ peer_address.ToString().c_str());
+ if (btif_a2dp_source_cb.State() != BtifA2dpSource::kStateRunning) {
+ LOG_ERROR(LOG_TAG, "%s: A2DP Source media task is not running", __func__);
+ return;
+ }
+}
+
void btif_a2dp_source_shutdown(void) {
LOG_INFO(LOG_TAG, "%s", __func__);
// we're using that in frame size calculations now.
CHECK(CHAR_BIT == 8);
+ btif_a2dp_source_audio_tx_flush_req();
btif_a2dp_source_thread.DoInThread(
FROM_HERE,
base::Bind(&btif_a2dp_source_setup_codec_delayed, peer_address));
BTIF_TRACE_WARNING("%s: unable to set active peer to empty in BtaAvCo",
__func__);
}
+ btif_a2dp_source_end_session(active_peer_);
btif_a2dp_source_shutdown();
active_peer_ = peer_address;
return true;
__func__, peer_address.ToString().c_str());
return false;
}
+
+ // Start/restart the session
+ if (!active_peer_.IsEmpty()) {
+ btif_a2dp_source_end_session(active_peer_);
+ }
bool should_startup = active_peer_.IsEmpty();
active_peer_ = peer_address;
if (should_startup) {
__func__);
btif_a2dp_source_startup();
}
+ btif_a2dp_source_start_session(peer_address);
return true;
}
BTIF_TRACE_WARNING("%s: unable to set active peer to empty in BtaAvCo",
__func__);
}
+ btif_a2dp_sink_end_session(active_peer_);
btif_a2dp_sink_shutdown();
active_peer_ = peer_address;
return true;
__func__, peer_address.ToString().c_str());
return false;
}
+
+ // Start/restart the session
+ if (!active_peer_.IsEmpty()) {
+ btif_a2dp_sink_end_session(active_peer_);
+ }
bool should_startup = active_peer_.IsEmpty();
active_peer_ = peer_address;
if (should_startup) {
__func__);
btif_a2dp_sink_startup();
}
+ btif_a2dp_sink_start_session(peer_address);
return true;
}
break; // Ignore
case BTIF_AV_START_STREAM_REQ_EVT:
- if (peer_.IsSink()) {
- btif_a2dp_source_setup_codec(peer_.PeerAddress());
- }
BTA_AvStart(peer_.BtaHandle());
peer_.SetFlags(BtifAvPeer::kFlagPendingStart);
break;