Support setting BT controller Low Latency mode(1/2)
Handle audio api StartRequest and SetLatencyMode in a2dp to send stream latency
through btif_av to bta event.
Bug: 240637363
Bug: 223126227
Tag: #feature
Ignore-AOSP-First: TM QPR1 feature
Test: test on sink device support dynamic spatial audio
Change-Id: I9ad4a23a58eeca6128a9f04a530ae6c90c773da5
diff --git a/system/audio_hal_interface/aidl/a2dp_encoding_aidl.cc b/system/audio_hal_interface/aidl/a2dp_encoding_aidl.cc
index faa735a..1ea3b3c 100644
--- a/system/audio_hal_interface/aidl/a2dp_encoding_aidl.cc
+++ b/system/audio_hal_interface/aidl/a2dp_encoding_aidl.cc
@@ -90,7 +90,7 @@
* procedure is completed, othewise send it now.
*/
a2dp_pending_cmd_ = A2DP_CTRL_CMD_START;
- btif_av_stream_start();
+ btif_av_stream_start_with_latency(is_low_latency);
if (btif_av_get_peer_sep() != AVDT_TSEP_SRC) {
LOG(INFO) << __func__ << ": accepted";
return a2dp_ack_to_bt_audio_ctrl_ack(A2DP_CTRL_ACK_PENDING);
@@ -138,6 +138,10 @@
btif_av_stream_stop(RawAddress::kEmpty);
}
+void A2dpTransport::SetLowLatency(bool is_low_latency) {
+ btif_av_set_low_latency(is_low_latency);
+}
+
bool A2dpTransport::GetPresentationPosition(uint64_t* remote_delay_report_ns,
uint64_t* total_bytes_read,
timespec* data_position) {
@@ -569,4 +573,4 @@
} // namespace a2dp
} // namespace aidl
} // namespace audio
-} // namespace bluetooth
\ No newline at end of file
+} // namespace bluetooth
diff --git a/system/audio_hal_interface/aidl/a2dp_transport.h b/system/audio_hal_interface/aidl/a2dp_transport.h
index 5732754..1b53da0 100644
--- a/system/audio_hal_interface/aidl/a2dp_transport.h
+++ b/system/audio_hal_interface/aidl/a2dp_transport.h
@@ -39,6 +39,8 @@
void StopRequest() override;
+ void SetLowLatency(bool is_low_latency) override;
+
bool GetPresentationPosition(uint64_t* remote_delay_report_ns,
uint64_t* total_bytes_read,
timespec* data_position) override;
@@ -69,4 +71,4 @@
} // namespace a2dp
} // namespace aidl
} // namespace audio
-} // namespace bluetooth
\ No newline at end of file
+} // namespace bluetooth
diff --git a/system/audio_hal_interface/aidl/bluetooth_audio_port_impl.cc b/system/audio_hal_interface/aidl/bluetooth_audio_port_impl.cc
index d9ce929..813648a 100644
--- a/system/audio_hal_interface/aidl/bluetooth_audio_port_impl.cc
+++ b/system/audio_hal_interface/aidl/bluetooth_audio_port_impl.cc
@@ -137,6 +137,7 @@
LatencyMode latency_mode) {
bool is_low_latency = latency_mode == LatencyMode::LOW_LATENCY ? true : false;
invoke_switch_buffer_size_cb(is_low_latency);
+ transport_instance_->SetLowLatency(is_low_latency);
return ndk::ScopedAStatus::ok();
}
@@ -148,4 +149,4 @@
} // namespace aidl
} // namespace audio
-} // namespace bluetooth
\ No newline at end of file
+} // namespace bluetooth
diff --git a/system/audio_hal_interface/aidl/hearing_aid_software_encoding_aidl.cc b/system/audio_hal_interface/aidl/hearing_aid_software_encoding_aidl.cc
index 91b4dca..1cab476 100644
--- a/system/audio_hal_interface/aidl/hearing_aid_software_encoding_aidl.cc
+++ b/system/audio_hal_interface/aidl/hearing_aid_software_encoding_aidl.cc
@@ -74,6 +74,8 @@
}
}
+ void SetLowLatency(bool is_low_latency) override {}
+
bool GetPresentationPosition(uint64_t* remote_delay_report_ns,
uint64_t* total_bytes_read,
timespec* data_position) override {
@@ -267,4 +269,4 @@
} // namespace hearing_aid
} // namespace aidl
} // namespace audio
-} // namespace bluetooth
\ No newline at end of file
+} // namespace bluetooth
diff --git a/system/audio_hal_interface/aidl/le_audio_software_aidl.cc b/system/audio_hal_interface/aidl/le_audio_software_aidl.cc
index 80aed9e..ffc213f 100644
--- a/system/audio_hal_interface/aidl/le_audio_software_aidl.cc
+++ b/system/audio_hal_interface/aidl/le_audio_software_aidl.cc
@@ -93,6 +93,8 @@
}
}
+void LeAudioTransport::SetLowLatency(bool is_low_latency) {}
+
bool LeAudioTransport::GetPresentationPosition(uint64_t* remote_delay_report_ns,
uint64_t* total_bytes_processed,
timespec* data_position) {
@@ -244,6 +246,10 @@
void LeAudioSinkTransport::StopRequest() { transport_->StopRequest(); }
+void LeAudioSinkTransport::SetLowLatency(bool is_low_latency) {
+ transport_->SetLowLatency(is_low_latency);
+}
+
bool LeAudioSinkTransport::GetPresentationPosition(
uint64_t* remote_delay_report_ns, uint64_t* total_bytes_read,
timespec* data_position) {
@@ -327,6 +333,10 @@
void LeAudioSourceTransport::StopRequest() { transport_->StopRequest(); }
+void LeAudioSourceTransport::SetLowLatency(bool is_low_latency) {
+ transport_->SetLowLatency(is_low_latency);
+}
+
bool LeAudioSourceTransport::GetPresentationPosition(
uint64_t* remote_delay_report_ns, uint64_t* total_bytes_written,
timespec* data_position) {
@@ -538,4 +548,4 @@
} // namespace le_audio
} // namespace aidl
} // namespace audio
-} // namespace bluetooth
\ No newline at end of file
+} // namespace bluetooth
diff --git a/system/audio_hal_interface/aidl/le_audio_software_aidl.h b/system/audio_hal_interface/aidl/le_audio_software_aidl.h
index 2958d26..1b54c84 100644
--- a/system/audio_hal_interface/aidl/le_audio_software_aidl.h
+++ b/system/audio_hal_interface/aidl/le_audio_software_aidl.h
@@ -76,6 +76,8 @@
void StopRequest();
+ void SetLowLatency(bool is_low_latency);
+
bool GetPresentationPosition(uint64_t* remote_delay_report_ns,
uint64_t* total_bytes_processed,
timespec* data_position);
@@ -129,6 +131,8 @@
void StopRequest() override;
+ void SetLowLatency(bool is_low_latency) override;
+
bool GetPresentationPosition(uint64_t* remote_delay_report_ns,
uint64_t* total_bytes_read,
timespec* data_position) override;
@@ -181,6 +185,8 @@
void StopRequest() override;
+ void SetLowLatency(bool is_low_latency) override;
+
bool GetPresentationPosition(uint64_t* remote_delay_report_ns,
uint64_t* total_bytes_written,
timespec* data_position) override;
@@ -214,4 +220,4 @@
} // namespace le_audio
} // namespace aidl
} // namespace audio
-} // namespace bluetooth
\ No newline at end of file
+} // namespace bluetooth
diff --git a/system/audio_hal_interface/aidl/transport_instance.h b/system/audio_hal_interface/aidl/transport_instance.h
index 11b9a21..e7967ab 100644
--- a/system/audio_hal_interface/aidl/transport_instance.h
+++ b/system/audio_hal_interface/aidl/transport_instance.h
@@ -71,6 +71,8 @@
virtual void StopRequest() = 0;
+ virtual void SetLowLatency(bool is_low_latency) = 0;
+
virtual bool GetPresentationPosition(uint64_t* remote_delay_report_ns,
uint64_t* total_bytes_readed,
timespec* data_position) = 0;
@@ -122,4 +124,4 @@
} // namespace aidl
} // namespace audio
-} // namespace bluetooth
\ No newline at end of file
+} // namespace bluetooth
diff --git a/system/bta/av/bta_av_aact.cc b/system/bta/av/bta_av_aact.cc
index 9e48782..92a8af7 100644
--- a/system/bta/av/bta_av_aact.cc
+++ b/system/bta/av/bta_av_aact.cc
@@ -1824,6 +1824,7 @@
if (p_scb->role & BTA_AV_ROLE_SUSPEND) {
notify_start_failed(p_scb);
} else {
+ bta_av_set_use_latency_mode(p_scb, p_data->do_start.use_latency_mode);
bta_av_start_ok(p_scb, NULL);
}
return;
@@ -1858,6 +1859,8 @@
LOG_ERROR("%s: AVDT_StartReq failed for peer %s result:%d", __func__,
p_scb->PeerAddress().ToString().c_str(), result);
bta_av_start_failed(p_scb, p_data);
+ } else {
+ bta_av_set_use_latency_mode(p_scb, p_data->do_start.use_latency_mode);
}
LOG_INFO(
"%s: peer %s start requested: sco_occupied:%s role:0x%x "
diff --git a/system/bta/av/bta_av_act.cc b/system/bta/av/bta_av_act.cc
index 177377c..9d3c90d 100644
--- a/system/bta/av/bta_av_act.cc
+++ b/system/bta/av/bta_av_act.cc
@@ -1339,6 +1339,19 @@
alarm_cancel(p_scb->link_signalling_timer);
}
+/*******************************************************************************
+ *
+ * Function bta_av_set_use_latency_mode
+ *
+ * Description Sets stream use latency mode.
+ *
+ * Returns void
+ *
+ ******************************************************************************/
+void bta_av_set_use_latency_mode(tBTA_AV_SCB* p_scb, bool use_latency_mode) {
+ L2CA_UseLatencyMode(p_scb->PeerAddress(), use_latency_mode);
+}
+
/**
* Find the index for the free LCB entry to use.
*
diff --git a/system/bta/av/bta_av_api.cc b/system/bta/av/bta_av_api.cc
index 9a8ccfd..defaea1 100644
--- a/system/bta/av/bta_av_api.cc
+++ b/system/bta/av/bta_av_api.cc
@@ -215,13 +215,17 @@
* Returns void
*
******************************************************************************/
-void BTA_AvStart(tBTA_AV_HNDL handle) {
- LOG_INFO("Starting audio/video stream data transfer bta_handle:%hhu", handle);
+void BTA_AvStart(tBTA_AV_HNDL handle, bool use_latency_mode) {
+ LOG_INFO(
+ "Starting audio/video stream data transfer bta_handle:%hhu, "
+ "use_latency_mode:%s",
+ handle, use_latency_mode ? "true" : "false");
- BT_HDR_RIGID* p_buf = (BT_HDR_RIGID*)osi_malloc(sizeof(BT_HDR_RIGID));
-
- p_buf->event = BTA_AV_API_START_EVT;
- p_buf->layer_specific = handle;
+ tBTA_AV_DO_START* p_buf =
+ (tBTA_AV_DO_START*)osi_malloc(sizeof(tBTA_AV_DO_START));
+ p_buf->hdr.event = BTA_AV_API_START_EVT;
+ p_buf->hdr.layer_specific = handle;
+ p_buf->use_latency_mode = use_latency_mode;
bta_sys_sendmsg(p_buf);
}
@@ -613,3 +617,26 @@
bta_sys_sendmsg(p_buf);
}
+
+/*******************************************************************************
+ *
+ * Function BTA_AvSetLatency
+ *
+ * Description Set audio/video stream latency.
+ *
+ * Returns void
+ *
+ ******************************************************************************/
+void BTA_AvSetLatency(tBTA_AV_HNDL handle, bool is_low_latency) {
+ LOG_INFO(
+ "Set audio/video stream low latency bta_handle:%hhu, is_low_latency:%s",
+ handle, is_low_latency ? "true" : "false");
+
+ tBTA_AV_API_SET_LATENCY* p_buf =
+ (tBTA_AV_API_SET_LATENCY*)osi_malloc(sizeof(tBTA_AV_API_SET_LATENCY));
+ p_buf->hdr.event = BTA_AV_API_SET_LATENCY_EVT;
+ p_buf->hdr.layer_specific = handle;
+ p_buf->is_low_latency = is_low_latency;
+
+ bta_sys_sendmsg(p_buf);
+}
diff --git a/system/bta/av/bta_av_int.h b/system/bta/av/bta_av_int.h
index 0b3e914..49b3ce4 100644
--- a/system/bta/av/bta_av_int.h
+++ b/system/bta/av/bta_av_int.h
@@ -114,7 +114,8 @@
BTA_AV_AVDT_RPT_CONN_EVT,
BTA_AV_API_START_EVT, /* the following 2 events must be in the same order as
the *AP_*EVT */
- BTA_AV_API_STOP_EVT
+ BTA_AV_API_STOP_EVT,
+ BTA_AV_API_SET_LATENCY_EVT,
};
/* events for AV control block state machine */
@@ -264,6 +265,18 @@
uint16_t uuid; /* uuid of initiator */
} tBTA_AV_API_OPEN;
+/* data type for BTA_AV_API_SET_LATENCY_EVT */
+typedef struct {
+ BT_HDR_RIGID hdr;
+ bool is_low_latency;
+} tBTA_AV_API_SET_LATENCY;
+
+/* data type for BTA_AV_API_START_EVT and bta_av_do_start */
+typedef struct {
+ BT_HDR_RIGID hdr;
+ bool use_latency_mode;
+} tBTA_AV_DO_START;
+
/* data type for BTA_AV_API_STOP_EVT */
typedef struct {
BT_HDR_RIGID hdr;
@@ -429,6 +442,8 @@
tBTA_AV_API_ENABLE api_enable;
tBTA_AV_API_REG api_reg;
tBTA_AV_API_OPEN api_open;
+ tBTA_AV_API_SET_LATENCY api_set_latency;
+ tBTA_AV_DO_START do_start;
tBTA_AV_API_STOP api_stop;
tBTA_AV_API_DISCNT api_discnt;
tBTA_AV_API_PROTECT_REQ api_protect_req;
@@ -724,6 +739,8 @@
/* nsm action functions */
extern void bta_av_api_disconnect(tBTA_AV_DATA* p_data);
+extern void bta_av_set_use_latency_mode(tBTA_AV_SCB* p_scb,
+ bool use_latency_mode);
extern void bta_av_sig_chg(tBTA_AV_DATA* p_data);
extern void bta_av_signalling_timer(tBTA_AV_DATA* p_data);
extern void bta_av_rc_disc_done(tBTA_AV_DATA* p_data);
diff --git a/system/bta/include/bta_av_api.h b/system/bta/include/bta_av_api.h
index fd1dd00..9112a32 100644
--- a/system/bta/include/bta_av_api.h
+++ b/system/bta/include/bta_av_api.h
@@ -500,7 +500,7 @@
* Returns void
*
******************************************************************************/
-void BTA_AvStart(tBTA_AV_HNDL handle);
+void BTA_AvStart(tBTA_AV_HNDL handle, bool use_latency_mode);
/*******************************************************************************
*
@@ -676,6 +676,17 @@
/*******************************************************************************
*
+ * Function BTA_AvSetLatency
+ *
+ * Description Set audio/video stream latency.
+ *
+ * Returns void
+ *
+ ******************************************************************************/
+void BTA_AvSetLatency(tBTA_AV_HNDL handle, bool is_low_latency);
+
+/*******************************************************************************
+ *
* Function BTA_AvOffloadStart
*
* Description Request Starting of A2DP Offload.
diff --git a/system/btif/include/btif_av.h b/system/btif/include/btif_av.h
index 0a3095e..09c0e27 100644
--- a/system/btif/include/btif_av.h
+++ b/system/btif/include/btif_av.h
@@ -52,6 +52,11 @@
void btif_av_stream_start(void);
/**
+ * Start streaming with latency setting.
+ */
+void btif_av_stream_start_with_latency(bool use_latency_mode);
+
+/**
* Stop streaming.
*
* @param peer_address the peer address or RawAddress::kEmpty to stop all peers
@@ -228,4 +233,11 @@
*/
void btif_av_set_dynamic_audio_buffer_size(uint8_t dynamic_audio_buffer_size);
+/**
+ * Enable/disable the low latency
+ *
+ * @param is_low_latency to set
+ */
+void btif_av_set_low_latency(bool is_low_latency);
+
#endif /* BTIF_AV_H */
diff --git a/system/btif/src/btif_av.cc b/system/btif/src/btif_av.cc
index 8ae8db8..7f613b8 100644
--- a/system/btif/src/btif_av.cc
+++ b/system/btif/src/btif_av.cc
@@ -80,6 +80,14 @@
RawAddress peer_address;
} btif_av_sink_config_req_t;
+typedef struct {
+ bool use_latency_mode;
+} btif_av_start_stream_req_t;
+
+typedef struct {
+ bool is_low_latency;
+} btif_av_set_latency_req_t;
+
/**
* BTIF AV events
*/
@@ -96,6 +104,7 @@
BTIF_AV_AVRCP_OPEN_EVT,
BTIF_AV_AVRCP_CLOSE_EVT,
BTIF_AV_AVRCP_REMOTE_PLAY_EVT,
+ BTIF_AV_SET_LATENCY_REQ_EVT,
} btif_av_sm_event_t;
class BtifAvEvent {
@@ -340,6 +349,11 @@
bool SelfInitiatedConnection() const { return self_initiated_connection_; }
void SetSelfInitiatedConnection(bool v) { self_initiated_connection_ = v; }
+ bool UseLatencyMode() const { return use_latency_mode_; }
+ void SetUseLatencyMode(bool use_latency_mode) {
+ use_latency_mode_ = use_latency_mode;
+ }
+
private:
const RawAddress peer_address_;
const uint8_t peer_sep_; // SEP type of peer device
@@ -353,6 +367,7 @@
bool is_silenced_;
uint16_t delay_report_;
bool mandatory_codec_preferred_ = false;
+ bool use_latency_mode_ = false;
};
class BtifAvSource {
@@ -769,6 +784,7 @@
CASE_RETURN_STR(BTIF_AV_AVRCP_OPEN_EVT)
CASE_RETURN_STR(BTIF_AV_AVRCP_CLOSE_EVT)
CASE_RETURN_STR(BTIF_AV_AVRCP_REMOTE_PLAY_EVT)
+ CASE_RETURN_STR(BTIF_AV_SET_LATENCY_REQ_EVT)
default:
return "UNKNOWN_EVENT";
}
@@ -1908,14 +1924,22 @@
case BTIF_AV_ACL_DISCONNECTED:
break; // Ignore
- case BTIF_AV_START_STREAM_REQ_EVT:
+ case BTIF_AV_START_STREAM_REQ_EVT: {
LOG_INFO("%s: Peer %s : event=%s flags=%s", __PRETTY_FUNCTION__,
peer_.PeerAddress().ToString().c_str(),
BtifAvEvent::EventName(event).c_str(),
peer_.FlagsToString().c_str());
- BTA_AvStart(peer_.BtaHandle());
+ if (p_data) {
+ const btif_av_start_stream_req_t* p_start_steam_req =
+ static_cast<const btif_av_start_stream_req_t*>(p_data);
+ LOG_INFO("Stream use_latency_mode=%s",
+ p_start_steam_req->use_latency_mode ? "true" : "false");
+ peer_.SetUseLatencyMode(p_start_steam_req->use_latency_mode);
+ }
+
+ BTA_AvStart(peer_.BtaHandle(), peer_.UseLatencyMode());
peer_.SetFlags(BtifAvPeer::kFlagPendingStart);
- break;
+ } break;
case BTA_AV_START_EVT: {
LOG_INFO(
@@ -2039,7 +2063,7 @@
LOG(INFO) << __PRETTY_FUNCTION__ << " : Peer " << peer_.PeerAddress()
<< " : Reconfig done - calling BTA_AvStart("
<< loghex(peer_.BtaHandle()) << ")";
- BTA_AvStart(peer_.BtaHandle());
+ BTA_AvStart(peer_.BtaHandle(), peer_.UseLatencyMode());
}
break;
@@ -2070,6 +2094,18 @@
CHECK_RC_EVENT(event, (tBTA_AV*)p_data);
+ case BTIF_AV_SET_LATENCY_REQ_EVT: {
+ const btif_av_set_latency_req_t* p_set_latency_req =
+ static_cast<const btif_av_set_latency_req_t*>(p_data);
+ LOG_INFO("Peer %s : event=%s flags=%s is_low_latency=%s",
+ peer_.PeerAddress().ToString().c_str(),
+ BtifAvEvent::EventName(event).c_str(),
+ peer_.FlagsToString().c_str(),
+ p_set_latency_req->is_low_latency ? "true" : "false");
+
+ BTA_AvSetLatency(peer_.BtaHandle(), p_set_latency_req->is_low_latency);
+ } break;
+
default:
BTIF_TRACE_WARNING("%s: Peer %s : Unhandled event=%s",
__PRETTY_FUNCTION__,
@@ -2273,6 +2309,18 @@
btif_a2dp_on_offload_started(peer_.PeerAddress(), p_av->status);
break;
+ case BTIF_AV_SET_LATENCY_REQ_EVT: {
+ const btif_av_set_latency_req_t* p_set_latency_req =
+ static_cast<const btif_av_set_latency_req_t*>(p_data);
+ LOG_INFO("Peer %s : event=%s flags=%s is_low_latency=%s",
+ peer_.PeerAddress().ToString().c_str(),
+ BtifAvEvent::EventName(event).c_str(),
+ peer_.FlagsToString().c_str(),
+ p_set_latency_req->is_low_latency ? "true" : "false");
+
+ BTA_AvSetLatency(peer_.BtaHandle(), p_set_latency_req->is_low_latency);
+ } break;
+
CHECK_RC_EVENT(event, (tBTA_AV*)p_data);
default:
@@ -3117,6 +3165,24 @@
BTIF_AV_START_STREAM_REQ_EVT);
}
+void btif_av_stream_start_with_latency(bool use_latency_mode) {
+ LOG_INFO("%s", __func__);
+
+ btif_av_start_stream_req_t start_stream_req;
+ start_stream_req.use_latency_mode = use_latency_mode;
+ BtifAvEvent btif_av_event(BTIF_AV_START_STREAM_REQ_EVT, &start_stream_req,
+ sizeof(start_stream_req));
+ LOG_INFO("peer_address=%s event=%s use_latency_mode=%s",
+ btif_av_source_active_peer().ToString().c_str(),
+ btif_av_event.ToString().c_str(),
+ use_latency_mode ? "true" : "false");
+
+ do_in_main_thread(FROM_HERE, base::Bind(&btif_av_handle_event,
+ AVDT_TSEP_SNK, // peer_sep
+ btif_av_source_active_peer(),
+ kBtaHandleUnknown, btif_av_event));
+}
+
void src_do_suspend_in_main_thread(btif_av_sm_event_t event) {
if (event != BTIF_AV_SUSPEND_STREAM_REQ_EVT &&
event != BTIF_AV_STOP_STREAM_REQ_EVT)
@@ -3534,3 +3600,19 @@
void btif_av_set_dynamic_audio_buffer_size(uint8_t dynamic_audio_buffer_size) {
btif_a2dp_source_set_dynamic_audio_buffer_size(dynamic_audio_buffer_size);
}
+
+void btif_av_set_low_latency(bool is_low_latency) {
+ LOG_INFO("is_low_latency: %s", is_low_latency ? "true" : "false");
+
+ btif_av_set_latency_req_t set_latency_req;
+ set_latency_req.is_low_latency = is_low_latency;
+ BtifAvEvent btif_av_event(BTIF_AV_SET_LATENCY_REQ_EVT, &set_latency_req,
+ sizeof(set_latency_req));
+ LOG_INFO("peer_address=%s event=%s",
+ btif_av_source_active_peer().ToString().c_str(),
+ btif_av_event.ToString().c_str());
+ do_in_main_thread(FROM_HERE, base::Bind(&btif_av_handle_event,
+ AVDT_TSEP_SNK, // peer_sep
+ btif_av_source_active_peer(),
+ kBtaHandleUnknown, btif_av_event));
+}
diff --git a/system/stack/include/l2c_api.h b/system/stack/include/l2c_api.h
index 92cf17f..1a2bc40 100644
--- a/system/stack/include/l2c_api.h
+++ b/system/stack/include/l2c_api.h
@@ -636,6 +636,18 @@
/*******************************************************************************
*
+ * Function L2CA_UseLatencyMode
+ *
+ * Description Sets use latency mode for an ACL channel.
+ *
+ * Returns true if a valid channel, else false
+ *
+ ******************************************************************************/
+extern bool L2CA_UseLatencyMode(const RawAddress& bd_addr,
+ bool use_latency_mode);
+
+/*******************************************************************************
+ *
* Function L2CA_SetAclPriority
*
* Description Sets the transmission priority for an ACL channel.
diff --git a/system/stack/l2cap/l2c_api.cc b/system/stack/l2cap/l2c_api.cc
index 6eedcbb..a7eaf6a 100644
--- a/system/stack/l2cap/l2c_api.cc
+++ b/system/stack/l2cap/l2c_api.cc
@@ -1029,6 +1029,29 @@
/*******************************************************************************
*
+ * Function L2CA_UseLatencyMode
+ *
+ * Description Sets acl use latency mode.
+ *
+ * Returns true if a valid channel, else false
+ *
+ ******************************************************************************/
+bool L2CA_UseLatencyMode(const RawAddress& bd_addr, bool use_latency_mode) {
+ /* Find the link control block for the acl channel */
+ tL2C_LCB* p_lcb = l2cu_find_lcb_by_bd_addr(bd_addr, BT_TRANSPORT_BR_EDR);
+ if (p_lcb == nullptr) {
+ LOG_WARN("L2CAP - no LCB for L2CA_SetUseLatencyMode, BDA: %s",
+ bd_addr.ToString().c_str());
+ return false;
+ }
+ LOG_INFO("BDA: %s, use_latency_mode: %s", bd_addr.ToString().c_str(),
+ use_latency_mode ? "true" : "false");
+ p_lcb->use_latency_mode = use_latency_mode;
+ return true;
+}
+
+/*******************************************************************************
+ *
* Function L2CA_SetAclPriority
*
* Description Sets the transmission priority for a channel.
diff --git a/system/stack/l2cap/l2c_int.h b/system/stack/l2cap/l2c_int.h
index 39ba1ec..b6f70ae 100644
--- a/system/stack/l2cap/l2c_int.h
+++ b/system/stack/l2cap/l2c_int.h
@@ -497,6 +497,8 @@
return false;
}
+ bool use_latency_mode = false;
+
tL2C_CCB* p_fixed_ccbs[L2CAP_NUM_FIXED_CHNLS];
private:
diff --git a/system/test/mock/mock_bta_av_api.cc b/system/test/mock/mock_bta_av_api.cc
index 4c4e93d..6017d03 100644
--- a/system/test/mock/mock_bta_av_api.cc
+++ b/system/test/mock/mock_bta_av_api.cc
@@ -93,7 +93,9 @@
uint8_t buf_len) {
mock_function_count_map[__func__]++;
}
-void BTA_AvStart(tBTA_AV_HNDL handle) { mock_function_count_map[__func__]++; }
+void BTA_AvStart(tBTA_AV_HNDL handle, bool use_latency_mode) {
+ mock_function_count_map[__func__]++;
+}
void BTA_AvStop(tBTA_AV_HNDL handle, bool suspend) {
mock_function_count_map[__func__]++;
}
@@ -105,3 +107,6 @@
uint8_t* p_data, uint16_t len, uint32_t company_id) {
mock_function_count_map[__func__]++;
}
+void BTA_AvSetLatency(tBTA_AV_HNDL handle, bool is_low_latency) {
+ mock_function_count_map[__func__]++;
+}
diff --git a/system/test/mock/mock_stack_l2cap_api.cc b/system/test/mock/mock_stack_l2cap_api.cc
index 96d4eef..81e71b0 100644
--- a/system/test/mock/mock_stack_l2cap_api.cc
+++ b/system/test/mock/mock_stack_l2cap_api.cc
@@ -83,6 +83,7 @@
struct L2CA_GetRemoteCid L2CA_GetRemoteCid;
struct L2CA_SetIdleTimeoutByBdAddr L2CA_SetIdleTimeoutByBdAddr;
struct L2CA_SetTraceLevel L2CA_SetTraceLevel;
+struct L2CA_UseLatencyMode L2CA_UseLatencyMode;
struct L2CA_SetAclPriority L2CA_SetAclPriority;
struct L2CA_SetTxPriority L2CA_SetTxPriority;
struct L2CA_GetPeerFeatures L2CA_GetPeerFeatures;
@@ -210,6 +211,11 @@
mock_function_count_map[__func__]++;
return test::mock::stack_l2cap_api::L2CA_SetTraceLevel(new_level);
}
+bool L2CA_UseLatencyMode(const RawAddress& bd_addr, bool use_latency_mode) {
+ mock_function_count_map[__func__]++;
+ return test::mock::stack_l2cap_api::L2CA_UseLatencyMode(bd_addr,
+ use_latency_mode);
+}
bool L2CA_SetAclPriority(const RawAddress& bd_addr, tL2CAP_PRIORITY priority) {
mock_function_count_map[__func__]++;
return test::mock::stack_l2cap_api::L2CA_SetAclPriority(bd_addr, priority);
diff --git a/system/test/mock/mock_stack_l2cap_api.h b/system/test/mock/mock_stack_l2cap_api.h
index 6f682fc..b3e52b5 100644
--- a/system/test/mock/mock_stack_l2cap_api.h
+++ b/system/test/mock/mock_stack_l2cap_api.h
@@ -302,6 +302,17 @@
uint8_t operator()(uint8_t new_level) { return body(new_level); };
};
extern struct L2CA_SetTraceLevel L2CA_SetTraceLevel;
+// Name: L2CA_UseLatencyMode
+// Params: const RawAddress& bd_addr, bool use_latency_mode
+// Returns: bool
+struct L2CA_UseLatencyMode {
+ std::function<bool(const RawAddress& bd_addr, bool use_latency_mode)> body{
+ [](const RawAddress& bd_addr, bool use_latency_mode) { return false; }};
+ bool operator()(const RawAddress& bd_addr, bool use_latency_mode) {
+ return body(bd_addr, use_latency_mode);
+ };
+};
+extern struct L2CA_UseLatencyMode L2CA_UseLatencyMode;
// Name: L2CA_SetAclPriority
// Params: const RawAddress& bd_addr, tL2CAP_PRIORITY priority
// Returns: bool