// btif_a2dp_sink_startup() to start the streaming session for |peer_address|.
bool btif_a2dp_sink_start_session(const RawAddress& peer_address);
+// Restart the A2DP Sink session.
+// This function should be called by the BTIF state machine after
+// btif_a2dp_sink_startup() to restart the streaming session.
+// |old_peer_address| is the peer address of the old session. This address
+// can be empty.
+// |new_peer_address| is the peer address of the new session. This address
+// cannot be empty.
+bool btif_a2dp_sink_restart_session(const RawAddress& old_peer_address,
+ const RawAddress& new_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|.
// information.
void btif_a2dp_sink_debug_dump(int fd);
-// Update the A2DP Sink related metrics.
-// This function should be called before collecting the metrics.
-void btif_a2dp_sink_update_metrics(void);
-
// Create a request to set the audio focus state for the audio track.
// |state| is the new state value - see |btif_a2dp_sink_focus_state_t|
// for valid values.
// btif_a2dp_source_startup() to start the streaming session for |peer_address|.
bool btif_a2dp_source_start_session(const RawAddress& peer_address);
+// Restart the A2DP Source session.
+// This function should be called by the BTIF state machine after
+// btif_a2dp_source_startup() to restart the streaming session.
+// |old_peer_address| is the peer address of the old session. This address
+// can be empty.
+// |new_peer_address| is the peer address of the new session. This address
+// cannot be empty.
+bool btif_a2dp_source_restart_session(const RawAddress& old_peer_address,
+ const RawAddress& new_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|.
// Return true if the A2DP Source module is streaming.
bool btif_a2dp_source_is_streaming(void);
-// Setup the A2DP Source codec, and prepare the encoder.
-// The peer address is |peer_addr|.
-// This function should be called prior to starting A2DP streaming.
-void btif_a2dp_source_setup_codec(const RawAddress& peer_addr);
-
// Process a request to start the A2DP audio encoding task.
void btif_a2dp_source_start_audio_req(void);
// information.
void btif_a2dp_source_debug_dump(int fd);
-// Update the A2DP Source related metrics.
-// This function should be called before collecting the metrics.
-void btif_a2dp_source_update_metrics(void);
-
#endif /* BTIF_A2DP_SOURCE_H */
// Nothing to do
}
+bool btif_a2dp_sink_restart_session(const RawAddress& old_peer_address,
+ const RawAddress& new_peer_address) {
+ LOG_INFO(LOG_TAG, "%s: old_peer_address=%s new_peer_address=%s", __func__,
+ old_peer_address.ToString().c_str(),
+ new_peer_address.ToString().c_str());
+
+ CHECK(!new_peer_address.IsEmpty());
+
+ if (!old_peer_address.IsEmpty()) {
+ btif_a2dp_sink_end_session(old_peer_address);
+ }
+
+ if (!bta_av_co_set_active_peer(new_peer_address)) {
+ LOG_ERROR(LOG_TAG, "%s: Cannot stream audio: cannot set active peer to %s",
+ __func__, new_peer_address.ToString().c_str());
+ return false;
+ }
+
+ if (old_peer_address.IsEmpty()) {
+ btif_a2dp_sink_startup();
+ }
+ btif_a2dp_sink_start_session(new_peer_address);
+
+ return true;
+}
+
bool btif_a2dp_sink_end_session(const RawAddress& peer_address) {
LOG_INFO(LOG_TAG, "%s: peer_address=%s", __func__,
peer_address.ToString().c_str());
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);
+// Set up the A2DP Source codec, and prepare the encoder.
+// The peer address is |peer_addr|.
+// This function should be called prior to starting A2DP streaming.
+static void btif_a2dp_source_setup_codec(const RawAddress& peer_addr);
static void btif_a2dp_source_setup_codec_delayed(
const RawAddress& peer_address);
static void btif_a2dp_source_encoder_user_config_update_event(
static void log_tstamps_us(const char* comment, uint64_t timestamp_us);
static void update_scheduling_stats(SchedulingStats* stats, uint64_t now_us,
uint64_t expected_delta);
+// Update the A2DP Source related metrics.
+// This function should be called before collecting the metrics.
+static void btif_a2dp_source_update_metrics(void);
static void btm_read_rssi_cb(void* data);
static void btm_read_failed_contact_counter_cb(void* data);
static void btm_read_automatic_flush_timeout_cb(void* data);
}
}
+bool btif_a2dp_source_restart_session(const RawAddress& old_peer_address,
+ const RawAddress& new_peer_address) {
+ bool is_streaming = alarm_is_scheduled(btif_a2dp_source_cb.media_alarm);
+ LOG_INFO(LOG_TAG,
+ "%s: old_peer_address=%s new_peer_address=%s is_streaming=%s",
+ __func__, old_peer_address.ToString().c_str(),
+ new_peer_address.ToString().c_str(), logbool(is_streaming).c_str());
+
+ CHECK(!new_peer_address.IsEmpty());
+
+ // Must stop first the audio streaming
+ if (is_streaming) {
+ btif_a2dp_source_stop_audio_req();
+ }
+
+ // If the old active peer was valid, end the old session.
+ // Otherwise, time to startup the A2DP Source processing.
+ if (!old_peer_address.IsEmpty()) {
+ btif_a2dp_source_end_session(old_peer_address);
+ } else {
+ btif_a2dp_source_startup();
+ }
+
+ // Start the session.
+ // If audio was streaming before, start audio streaming as well.
+ btif_a2dp_source_start_session(new_peer_address);
+ if (is_streaming) {
+ btif_a2dp_source_start_audio_req();
+ }
+ return true;
+}
+
bool btif_a2dp_source_end_session(const RawAddress& peer_address) {
LOG_INFO(LOG_TAG, "%s: peer_address=%s", __func__,
peer_address.ToString().c_str());
return alarm_is_scheduled(btif_a2dp_source_cb.media_alarm);
}
-void btif_a2dp_source_setup_codec(const RawAddress& peer_address) {
+static void btif_a2dp_source_setup_codec(const RawAddress& peer_address) {
LOG_INFO(LOG_TAG, "%s: peer_address=%s", __func__,
peer_address.ToString().c_str());
(unsigned long long)ave_time_us / 1000);
}
-void btif_a2dp_source_update_metrics(void) {
+static void btif_a2dp_source_update_metrics(void) {
const BtifMediaStats& stats = btif_a2dp_source_cb.stats;
const SchedulingStats& enqueue_stats = stats.tx_queue_enqueue_stats;
A2dpSessionMetrics metrics;
peer->PeerAddress().ToString().c_str());
return false;
}
- if (!bta_av_co_set_active_peer(peer_address)) {
- BTIF_TRACE_ERROR("%s: unable to set active peer to %s in BtaAvCo",
- __func__, peer_address.ToString().c_str());
- return false;
- }
- // Start/restart the session
- if (!active_peer_.IsEmpty()) {
- btif_a2dp_source_end_session(active_peer_);
+ if (!btif_a2dp_source_restart_session(active_peer_, peer_address)) {
+ return false;
}
- bool should_startup = active_peer_.IsEmpty();
active_peer_ = peer_address;
- if (should_startup) {
- BTIF_TRACE_EVENT("%s: active peer is empty, startup the Audio source",
- __func__);
- btif_a2dp_source_startup();
- }
- btif_a2dp_source_start_session(peer_address);
return true;
}
peer->PeerAddress().ToString().c_str());
return false;
}
- if (!bta_av_co_set_active_peer(peer_address)) {
- BTIF_TRACE_ERROR("%s: unable to set active peer to %s in BtaAvCo",
- __func__, peer_address.ToString().c_str());
- return false;
- }
- // Start/restart the session
- if (!active_peer_.IsEmpty()) {
- btif_a2dp_sink_end_session(active_peer_);
+ if (!btif_a2dp_sink_restart_session(active_peer_, peer_address)) {
+ return false;
}
- bool should_startup = active_peer_.IsEmpty();
active_peer_ = peer_address;
- if (should_startup) {
- BTIF_TRACE_EVENT("%s: active peer is empty, startup the Audio sink",
- __func__);
- btif_a2dp_sink_startup();
- }
- btif_a2dp_sink_start_session(peer_address);
return true;
}
}
bool BtifAvStateMachine::StateIdle::ProcessEvent(uint32_t event, void* p_data) {
- BTIF_TRACE_DEBUG("%s: Peer %s : event=%s flags=%s", __PRETTY_FUNCTION__,
- peer_.PeerAddress().ToString().c_str(),
+ BTIF_TRACE_DEBUG("%s: Peer %s : event=%s flags=%s active_peer=%s",
+ __PRETTY_FUNCTION__, peer_.PeerAddress().ToString().c_str(),
BtifAvEvent::EventName(event).c_str(),
- peer_.FlagsToString().c_str());
+ peer_.FlagsToString().c_str(),
+ logbool(peer_.IsActivePeer()).c_str());
switch (event) {
case BTA_AV_ENABLE_EVT:
bool BtifAvStateMachine::StateOpening::ProcessEvent(uint32_t event,
void* p_data) {
- BTIF_TRACE_DEBUG("%s: Peer %s : event=%s flags=%s", __PRETTY_FUNCTION__,
- peer_.PeerAddress().ToString().c_str(),
+ BTIF_TRACE_DEBUG("%s: Peer %s : event=%s flags=%s active_peer=%s",
+ __PRETTY_FUNCTION__, peer_.PeerAddress().ToString().c_str(),
BtifAvEvent::EventName(event).c_str(),
- peer_.FlagsToString().c_str());
+ peer_.FlagsToString().c_str(),
+ logbool(peer_.IsActivePeer()).c_str());
switch (event) {
case BTIF_AV_STOP_STREAM_REQ_EVT:
void* p_data) {
tBTA_AV* p_av = (tBTA_AV*)p_data;
- BTIF_TRACE_DEBUG("%s: Peer %s : event=%s flags=%s", __PRETTY_FUNCTION__,
- peer_.PeerAddress().ToString().c_str(),
+ BTIF_TRACE_DEBUG("%s: Peer %s : event=%s flags=%s active_peer=%s",
+ __PRETTY_FUNCTION__, peer_.PeerAddress().ToString().c_str(),
BtifAvEvent::EventName(event).c_str(),
- peer_.FlagsToString().c_str());
+ peer_.FlagsToString().c_str(),
+ logbool(peer_.IsActivePeer()).c_str());
if ((event == BTA_AV_REMOTE_CMD_EVT) &&
peer_.CheckFlags(BtifAvPeer::kFlagRemoteSuspend) &&
void* p_data) {
tBTA_AV* p_av = (tBTA_AV*)p_data;
- BTIF_TRACE_DEBUG("%s: Peer %s : event=%s flags=%s", __PRETTY_FUNCTION__,
- peer_.PeerAddress().ToString().c_str(),
+ BTIF_TRACE_DEBUG("%s: Peer %s : event=%s flags=%s active_peer=%s",
+ __PRETTY_FUNCTION__, peer_.PeerAddress().ToString().c_str(),
BtifAvEvent::EventName(event).c_str(),
- peer_.FlagsToString().c_str());
+ peer_.FlagsToString().c_str(),
+ logbool(peer_.IsActivePeer()).c_str());
switch (event) {
case BTIF_AV_ACL_DISCONNECTED:
if (peer_.IsSink()) {
// Immediately stop transmission of frames while suspend is pending
if (peer_.IsActivePeer()) {
- btif_a2dp_source_set_tx_flush(true);
+ if (event == BTIF_AV_STOP_STREAM_REQ_EVT) {
+ btif_a2dp_on_stopped(nullptr);
+ } else {
+ // (event == BTIF_AV_SUSPEND_STREAM_REQ_EVT)
+ btif_a2dp_source_set_tx_flush(true);
+ }
}
} else if (peer_.IsSource()) {
btif_a2dp_on_stopped(nullptr);
bool BtifAvStateMachine::StateClosing::ProcessEvent(uint32_t event,
void* p_data) {
- BTIF_TRACE_DEBUG("%s: Peer %s : event=%s flags=%s", __PRETTY_FUNCTION__,
- peer_.PeerAddress().ToString().c_str(),
+ BTIF_TRACE_DEBUG("%s: Peer %s : event=%s flags=%s active_peer=%s",
+ __PRETTY_FUNCTION__, peer_.PeerAddress().ToString().c_str(),
BtifAvEvent::EventName(event).c_str(),
- peer_.FlagsToString().c_str());
+ peer_.FlagsToString().c_str(),
+ logbool(peer_.IsActivePeer()).c_str());
switch (event) {
case BTIF_AV_SUSPEND_STREAM_REQ_EVT: