--- /dev/null
+package android.bluetooth;
+
+parcelable BufferConstraints;
import android.bluetooth.BluetoothCodecConfig;
import android.bluetooth.BluetoothCodecStatus;
import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BufferConstraints;
/**
* APIs for Bluetooth A2DP service
int supportsOptionalCodecs(in BluetoothDevice device);
int getOptionalCodecsEnabled(in BluetoothDevice device);
oneway void setOptionalCodecsEnabled(in BluetoothDevice device, int value);
+ int getDynamicBufferSupport();
+ BufferConstraints getBufferConstraints();
+ boolean setBufferMillis(int codec, int size);
int getPriority(in BluetoothDevice device);
}
// information.
void btif_a2dp_source_debug_dump(int fd);
+// Set the dynamic audio buffer size
+void btif_a2dp_source_set_dynamic_audio_buffer_size(
+ uint8_t dynamic_audio_buffer_size);
+
#endif /* BTIF_A2DP_SOURCE_H */
******************************************************************************/
void btif_debug_bond_event_dump(int fd);
+/*******************************************************************************
+ *
+ * Function btif_set_dynamic_audio_buffer_size
+ *
+ * Description Set dynamic audio buffer size
+ *
+ * Returns BT_STATUS_SUCCESS on success
+ *
+ ******************************************************************************/
+bt_status_t btif_set_dynamic_audio_buffer_size(int codec, int size);
+
#endif /* BTIF_API_H */
*/
bool btif_av_is_peer_silenced(const RawAddress& peer_address);
+/**
+ * Set the dynamic audio buffer size
+ *
+ * @param dynamic_audio_buffer_size to set
+ */
+void btif_av_set_dynamic_audio_buffer_size(uint8_t dynamic_audio_buffer_size);
+
#endif /* BTIF_AV_H */
address);
}
+static int set_dynamic_audio_buffer_size(int codec, int size) {
+ return btif_set_dynamic_audio_buffer_size(codec, size);
+}
+
EXPORT_SYMBOL bt_interface_t bluetoothInterface = {
sizeof(bluetoothInterface),
init,
get_avrcp_service,
obfuscate_address,
get_metric_id,
+ set_dynamic_audio_buffer_size,
};
// callback reporting helpers
"bt_a2dp_source_worker_thread");
static BtifA2dpSource btif_a2dp_source_cb;
+static uint8_t btif_a2dp_source_dynamic_audio_buffer_size =
+ MAX_OUTPUT_A2DP_FRAME_QUEUE_SZ;
+
static void btif_a2dp_source_init_delayed(void);
static void btif_a2dp_source_startup_delayed(void);
static void btif_a2dp_source_start_session_delayed(
// Check for TX queue overflow
// TODO: Using frames_n here is probably wrong: should be "+ 1" instead.
if (fixed_queue_length(btif_a2dp_source_cb.tx_audio_queue) + frames_n >
- MAX_OUTPUT_A2DP_FRAME_QUEUE_SZ) {
+ btif_a2dp_source_dynamic_audio_buffer_size) {
LOG_WARN("%s: TX queue buffer size now=%u adding=%u max=%d", __func__,
(uint32_t)fixed_queue_length(btif_a2dp_source_cb.tx_audio_queue),
- (uint32_t)frames_n, MAX_OUTPUT_A2DP_FRAME_QUEUE_SZ);
+ (uint32_t)frames_n, btif_a2dp_source_dynamic_audio_buffer_size);
// Keep track of drop-outs
btif_a2dp_source_cb.stats.tx_queue_dropouts++;
btif_a2dp_source_cb.stats.tx_queue_last_dropouts_us = now_us;
BluetoothMetricsLogger::GetInstance()->LogA2dpSession(metrics);
}
+void btif_a2dp_source_set_dynamic_audio_buffer_size(
+ uint8_t dynamic_audio_buffer_size) {
+ btif_a2dp_source_dynamic_audio_buffer_size = dynamic_audio_buffer_size;
+}
+
static void btm_read_rssi_cb(void* data) {
if (data == nullptr) {
LOG_ERROR("%s: Read RSSI request timed out", __func__);
bool btif_av_is_peer_silenced(const RawAddress& peer_address) {
return btif_av_source.IsPeerSilenced(peer_address);
}
+
+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);
+}
#endif // defined(OS_GENERIC)
#endif // BTE_DID_CONF_FILE
+#define CODEC_TYPE_NUMBER 32
+#define DEFAULT_BUFFER_TIME (MAX_PCM_FRAME_NUM_PER_TICK * 2)
+#define MAXIMUM_BUFFER_TIME (MAX_PCM_FRAME_NUM_PER_TICK * 2)
+#define MINIMUM_BUFFER_TIME MAX_PCM_FRAME_NUM_PER_TICK
+
/*******************************************************************************
* Static variables
******************************************************************************/
return BT_STATUS_SUCCESS;
}
+static bool btif_is_a2dp_offload_enabled() {
+ char value_sup[PROPERTY_VALUE_MAX] = {'\0'};
+ char value_dis[PROPERTY_VALUE_MAX] = {'\0'};
+ bool a2dp_offload_enabled_;
+
+ osi_property_get("ro.bluetooth.a2dp_offload.supported", value_sup, "false");
+ osi_property_get("persist.bluetooth.a2dp_offload.disabled", value_dis,
+ "false");
+ a2dp_offload_enabled_ =
+ (strcmp(value_sup, "true") == 0) && (strcmp(value_dis, "false") == 0);
+ BTIF_TRACE_DEBUG("a2dp_offload.enable = %d", a2dp_offload_enabled_);
+
+ return a2dp_offload_enabled_;
+}
+
+void btif_dynamic_audio_buffer_init() {
+ LOG_INFO("%s entered", __func__);
+
+ char buf[512];
+ bt_property_t prop;
+ prop.type = BT_PROPERTY_DYNAMIC_AUDIO_BUFFER;
+ prop.val = (void*)buf;
+
+ bt_dynamic_audio_buffer_item_t dynamic_audio_buffer_item;
+ prop.len = sizeof(bt_dynamic_audio_buffer_item_t);
+ LOG_DEBUG("%s prop.len = %d", __func__, prop.len);
+
+ tBTM_BLE_VSC_CB cmn_vsc_cb;
+ BTM_BleGetVendorCapabilities(&cmn_vsc_cb);
+
+ if (btif_is_a2dp_offload_enabled() == false) {
+ BTIF_TRACE_DEBUG("%s Get buffer time for A2DP software encoding", __func__);
+ for (int i = 0; i < CODEC_TYPE_NUMBER; i++) {
+ dynamic_audio_buffer_item.dab_item[i] = {
+ .default_buffer_time = DEFAULT_BUFFER_TIME,
+ .maximum_buffer_time = MAXIMUM_BUFFER_TIME,
+ .minimum_buffer_time = MINIMUM_BUFFER_TIME};
+ }
+ memcpy(prop.val, &dynamic_audio_buffer_item, prop.len);
+ invoke_adapter_properties_cb(BT_STATUS_SUCCESS, 1, &prop);
+ } else {
+ if (cmn_vsc_cb.dynamic_audio_buffer_support != 0) {
+ BTIF_TRACE_DEBUG("%s Get buffer time for A2DP Offload", __func__);
+ tBTM_BT_DYNAMIC_AUDIO_BUFFER_CB
+ bt_dynamic_audio_buffer_cb[CODEC_TYPE_NUMBER];
+ BTM_BleGetDynamicAudioBuffer(bt_dynamic_audio_buffer_cb);
+
+ for (int i = 0; i < CODEC_TYPE_NUMBER; i++) {
+ dynamic_audio_buffer_item.dab_item[i] = {
+ .default_buffer_time =
+ bt_dynamic_audio_buffer_cb[i].default_buffer_time,
+ .maximum_buffer_time =
+ bt_dynamic_audio_buffer_cb[i].maximum_buffer_time,
+ .minimum_buffer_time =
+ bt_dynamic_audio_buffer_cb[i].minimum_buffer_time};
+ }
+ memcpy(prop.val, &dynamic_audio_buffer_item, prop.len);
+ invoke_adapter_properties_cb(BT_STATUS_SUCCESS, 1, &prop);
+ } else {
+ BTIF_TRACE_DEBUG("%s Don't support Dynamic Audio Buffer", __func__);
+ }
+ }
+}
+
/*******************************************************************************
*
* Function btif_enable_bluetooth_evt
/* init pan */
btif_pan_init();
+ /* init dynamic audio buffer */
+ btif_dynamic_audio_buffer_init();
+
/* load did configuration */
bte_load_did_conf(BTE_DID_CONF_FILE);
btif_dm_enable_service(service_id, false);
}
}
+
+void DynamicAudiobufferSizeCompleteCallback(tBTM_VSC_CMPL* p_vsc_cmpl_params) {
+ LOG(INFO) << __func__;
+
+ if (p_vsc_cmpl_params->param_len < 1) {
+ LOG(ERROR) << __func__
+ << ": The length of returned parameters is less than 1";
+ return;
+ }
+ uint8_t* p_event_param_buf = p_vsc_cmpl_params->p_param_buf;
+ uint8_t status = 0xff;
+ uint8_t opcode = 0xff;
+ uint16_t respond_buffer_time = 0xffff;
+
+ // [Return Parameter] | [Size] | [Purpose]
+ // Status | 1 octet | Command complete status
+ // Dynamic_Audio_Buffer_opcode| 1 octet | 0x02 - Set buffer time
+ // Audio_Codec_Buffer_Time | 2 octet | Current buffer time
+ STREAM_TO_UINT8(status, p_event_param_buf);
+ if (status != HCI_SUCCESS) {
+ LOG(ERROR) << __func__
+ << ": Fail to configure DFTB. status: " << loghex(status);
+ return;
+ }
+
+ if (p_vsc_cmpl_params->param_len != 4) {
+ LOG(FATAL) << __func__
+ << ": The length of returned parameters is not equal to 4: "
+ << std::to_string(p_vsc_cmpl_params->param_len);
+ return;
+ }
+
+ STREAM_TO_UINT8(opcode, p_event_param_buf);
+ LOG(INFO) << __func__ << ": opcode = " << loghex(opcode);
+
+ if (opcode == 0x02) {
+ STREAM_TO_UINT16(respond_buffer_time, p_event_param_buf);
+ LOG(INFO) << __func__
+ << ": Succeed to configure Media Tx Buffer, used_buffer_time = "
+ << loghex(respond_buffer_time);
+ }
+}
+
+bt_status_t btif_set_dynamic_audio_buffer_size(int codec, int size) {
+ BTIF_TRACE_DEBUG("%s", __func__);
+
+ tBTM_BLE_VSC_CB cmn_vsc_cb;
+ BTM_BleGetVendorCapabilities(&cmn_vsc_cb);
+
+ if (!btif_av_is_a2dp_offload_enabled()) {
+ BTIF_TRACE_DEBUG("%s Set buffer size (%d) for A2DP software encoding",
+ __func__, size);
+ btif_av_set_dynamic_audio_buffer_size((uint8_t(size)));
+ } else {
+ if (cmn_vsc_cb.dynamic_audio_buffer_support != 0) {
+ BTIF_TRACE_DEBUG("%s Set buffer size (%d) for A2DP offload", __func__,
+ size);
+ uint16_t firmware_tx_buffer_length_byte;
+ uint8_t param[3] = {0};
+ uint8_t* p_param = param;
+
+ firmware_tx_buffer_length_byte = static_cast<uint16_t>(size);
+ LOG(INFO) << __func__ << "firmware_tx_buffer_length_byte: "
+ << firmware_tx_buffer_length_byte;
+
+ UINT8_TO_STREAM(p_param, HCI_CONTROLLER_DAB_SET_BUFFER_TIME);
+ UINT16_TO_STREAM(p_param, firmware_tx_buffer_length_byte);
+ BTM_VendorSpecificCommand(HCI_CONTROLLER_DAB, p_param - param, param,
+ DynamicAudiobufferSizeCompleteCallback);
+ }
+ }
+
+ return BT_STATUS_SUCCESS;
+}
local_le_features.le_maximum_advertising_data_length =
controller->get_ble_maxium_advertising_data_length();
+ local_le_features.dynamic_audio_buffer_supported =
+ cmn_vsc_cb.dynamic_audio_buffer_support;
+
invoke_adapter_properties_cb(BT_STATUS_SUCCESS, 1, &prop);
break;
}
bool le_extended_advertising_supported;
bool le_periodic_advertising_supported;
uint16_t le_maximum_advertising_data_length;
+ uint32_t dynamic_audio_buffer_supported;
} bt_local_le_features_t;
+/* Stored the default/maximum/minimum buffer time for dynamic audio buffer.
+ * For A2DP offload usage, the unit is millisecond.
+ * For A2DP legacy usage, the unit is buffer queue size*/
+typedef struct {
+ uint16_t default_buffer_time;
+ uint16_t maximum_buffer_time;
+ uint16_t minimum_buffer_time;
+} bt_dynamic_audio_buffer_type_t;
+
+typedef struct {
+ bt_dynamic_audio_buffer_type_t dab_item[32];
+} bt_dynamic_audio_buffer_item_t;
+
/* Bluetooth Adapter and Remote Device property types */
typedef enum {
/* Properties common to both adapter and remote device */
*/
BT_PROPERTY_LOCAL_IO_CAPS_BLE,
+ BT_PROPERTY_DYNAMIC_AUDIO_BUFFER,
+
BT_PROPERTY_REMOTE_DEVICE_TIMESTAMP = 0xFF,
} bt_property_type_t;
* @return int incremental Bluetooth id
*/
int (*get_metric_id)(const RawAddress& address);
+
+ /**
+ * Set the dynamic audio buffer size to the Controller
+ */
+ int (*set_dynamic_audio_buffer_size)(int codec, int size);
} bt_interface_t;
#define BLUETOOTH_INTERFACE_STRING "bluetoothInterface"
nullptr, /* get_avrcp_service */
nullptr, /* obfuscate_address */
nullptr, /* get_metric_id */
+ nullptr, /* set_dynamic_audio_buffer_size */
};
} // namespace
#define BTM_VSC_CHIP_CAPABILITY_RSP_LEN_L_RELEASE \
BTM_VSC_CHIP_CAPABILITY_RSP_LEN
#define BTM_VSC_CHIP_CAPABILITY_RSP_LEN_M_RELEASE 15
+#define BTM_VSC_CHIP_CAPABILITY_RSP_LEN_S_RELEASE 25
namespace {
}
#if (BLE_VND_INCLUDED == TRUE)
+
+static void btm_get_dynamic_audio_buffer_vsc_cmpl_cback(
+ tBTM_VSC_CMPL* p_vsc_cmpl_params) {
+ LOG(INFO) << __func__;
+
+ if (p_vsc_cmpl_params->param_len < 1) {
+ LOG(ERROR) << __func__
+ << ": The length of returned parameters is less than 1";
+ return;
+ }
+ uint8_t* p_event_param_buf = p_vsc_cmpl_params->p_param_buf;
+ uint8_t status = 0xff;
+ uint8_t opcode = 0xff;
+ uint32_t codec_mask = 0xffffffff;
+
+ // [Return Parameter] | [Size] | [Purpose]
+ // Status | 1 octet | Command complete status
+ // Dynamic_Audio_Buffer_opcode| 1 octet | 0x01 - Get buffer time
+ // Audio_Codedc_Type_Supported| 4 octet | Bit masks for selected codec types
+ // Audio_Codec_Buffer_Time | 192 octet| Default/Max/Min buffer time
+ STREAM_TO_UINT8(status, p_event_param_buf);
+ if (status != HCI_SUCCESS) {
+ LOG(ERROR) << __func__
+ << ": Fail to configure DFTB. status: " << loghex(status);
+ return;
+ }
+
+ if (p_vsc_cmpl_params->param_len != 198) {
+ LOG(FATAL) << __func__
+ << ": The length of returned parameters is not equal to 198: "
+ << std::to_string(p_vsc_cmpl_params->param_len);
+ return;
+ }
+
+ STREAM_TO_UINT8(opcode, p_event_param_buf);
+ LOG(INFO) << __func__ << ": opcode = " << loghex(opcode);
+
+ if (opcode == 0x01) {
+ STREAM_TO_UINT32(codec_mask, p_event_param_buf);
+ LOG(INFO) << __func__ << ": codec_mask = " << loghex(codec_mask);
+
+ for (int i = 0; i < BTM_CODEC_TYPE_MAX_RECORDS; i++) {
+ STREAM_TO_UINT16(btm_cb.dynamic_audio_buffer_cb[i].default_buffer_time,
+ p_event_param_buf);
+ STREAM_TO_UINT16(btm_cb.dynamic_audio_buffer_cb[i].maximum_buffer_time,
+ p_event_param_buf);
+ STREAM_TO_UINT16(btm_cb.dynamic_audio_buffer_cb[i].minimum_buffer_time,
+ p_event_param_buf);
+ }
+
+ LOG(INFO) << __func__ << ": Succeed to receive Media Tx Buffer.";
+ }
+}
+
/*******************************************************************************
*
* Function btm_vsc_brcm_features_complete
STREAM_TO_UINT8(btm_cb.cmn_ble_vsc_cb.extended_scan_support, p);
STREAM_TO_UINT8(btm_cb.cmn_ble_vsc_cb.debug_logging_supported, p);
}
+
+ if (btm_cb.cmn_ble_vsc_cb.version_supported >=
+ BTM_VSC_CHIP_CAPABILITY_S_VERSION) {
+ if (p_vcs_cplt_params->param_len >=
+ BTM_VSC_CHIP_CAPABILITY_RSP_LEN_S_RELEASE) {
+ STREAM_TO_UINT8(
+ btm_cb.cmn_ble_vsc_cb.le_address_generation_offloading_support, p);
+ STREAM_TO_UINT32(
+ btm_cb.cmn_ble_vsc_cb.a2dp_source_offload_capability_mask, p);
+ STREAM_TO_UINT8(btm_cb.cmn_ble_vsc_cb.quality_report_support, p);
+ STREAM_TO_UINT32(btm_cb.cmn_ble_vsc_cb.dynamic_audio_buffer_support, p);
+
+ if (btm_cb.cmn_ble_vsc_cb.dynamic_audio_buffer_support != 0) {
+ uint8_t param[3] = {0};
+ uint8_t* p_param = param;
+
+ UINT8_TO_STREAM(p_param, HCI_CONTROLLER_DAB_GET_BUFFER_TIME);
+ BTM_VendorSpecificCommand(HCI_CONTROLLER_DAB, p_param - param, param,
+ btm_get_dynamic_audio_buffer_vsc_cmpl_cback);
+ }
+ }
+ }
btm_cb.cmn_ble_vsc_cb.values_read = true;
BTM_TRACE_DEBUG(
}
}
+extern void BTM_BleGetDynamicAudioBuffer(
+ tBTM_BT_DYNAMIC_AUDIO_BUFFER_CB p_dynamic_audio_buffer_cb[]) {
+ BTM_TRACE_DEBUG("BTM_BleGetDynamicAudioBuffer");
+
+ if (NULL != p_dynamic_audio_buffer_cb) {
+ for (int i = 0; i < 32; i++) {
+ p_dynamic_audio_buffer_cb[i] = btm_cb.dynamic_audio_buffer_cb[i];
+ }
+ }
+}
+
/******************************************************************************
*
* Function BTM_BleReadControllerFeatures
#define BTM_VSC_CHIP_CAPABILITY_L_VERSION 55
#define BTM_VSC_CHIP_CAPABILITY_M_VERSION 95
+#define BTM_VSC_CHIP_CAPABILITY_S_VERSION 98
typedef struct {
uint16_t data_mask;
// BQR Receiver
tBTM_BT_QUALITY_REPORT_RECEIVER* p_bqr_report_receiver{nullptr};
+#define BTM_CODEC_TYPE_MAX_RECORDS 32
+ tBTM_BT_DYNAMIC_AUDIO_BUFFER_CB
+ dynamic_audio_buffer_cb[BTM_CODEC_TYPE_MAX_RECORDS];
+
tACL_CB acl_cb_;
std::shared_ptr<TimestampedStringCircularBuffer> history_{nullptr};
*
******************************************************************************/
extern void BTM_BleGetVendorCapabilities(tBTM_BLE_VSC_CB* p_cmn_vsc_cb);
+
+/*******************************************************************************
+ *
+ * Function BTM_BleGetDynamicAudioBuffer
+ *
+ * Description This function reads dynamic audio buffer
+ *
+ * Parameters p_dynamic_audio_buffer_cb : Dynamic Audio Buffer structure
+ *
+ * Returns void
+ *
+ ******************************************************************************/
+extern void BTM_BleGetDynamicAudioBuffer(
+ tBTM_BT_DYNAMIC_AUDIO_BUFFER_CB* p_dynamic_audio_buffer_cb);
+
/*******************************************************************************
*
* Function BTM_BleSetStorageConfig
uint16_t total_trackable_advertisers;
uint8_t extended_scan_support;
uint8_t debug_logging_supported;
+ uint8_t le_address_generation_offloading_support;
+ uint32_t a2dp_source_offload_capability_mask;
+ uint8_t quality_report_support;
+ uint32_t dynamic_audio_buffer_support;
} tBTM_BLE_VSC_CB;
+/* Stored the default/maximum/minimum buffer time for dynamic audio buffer.
+ * For A2DP offload usage, the unit is millisecond.
+ * For A2DP legacy usage, the unit is buffer queue size*/
+typedef struct {
+ uint16_t default_buffer_time;
+ uint16_t maximum_buffer_time;
+ uint16_t minimum_buffer_time;
+} tBTM_BT_DYNAMIC_AUDIO_BUFFER_CB;
+
typedef void(tBTM_BLE_ADV_DATA_CMPL_CBACK)(tBTM_STATUS status);
#ifndef BTM_BLE_MULTI_ADV_MAX
/* Bluetooth Quality Report opcode */
#define HCI_CONTROLLER_BQR (0x015E | HCI_GRP_VENDOR_SPECIFIC)
+/* Bluetooth Dynamic Audio Buffer opcode */
+#define HCI_CONTROLLER_DAB (0x015F | HCI_GRP_VENDOR_SPECIFIC)
+#define HCI_CONTROLLER_DAB_GET_BUFFER_TIME 0x01
+#define HCI_CONTROLLER_DAB_SET_BUFFER_TIME 0x02
+
/* subcode for multi adv feature */
#define BTM_BLE_MULTI_ADV_SET_PARAM 0x01
#define BTM_BLE_MULTI_ADV_WRITE_ADV_DATA 0x02