OSDN Git Service

Dynamic Audio Buffer (3/3)
authorMore Kuo <morekuo@google.com>
Thu, 13 Aug 2020 06:30:33 +0000 (14:30 +0800)
committerMore Kuo <morekuo@google.com>
Wed, 20 Jan 2021 06:26:02 +0000 (14:26 +0800)
Handle the dynamic audio buffer in the BT stack:
1. Send HCI VSC command to the controller.
2. Receive HCI VSC event from the controller.
3. Communicate with framework.

Bug: 163968696
Tag: #feature
Test: Run dynamic audio buffer test
Change-Id: I6a699c2c24b714ce76d1fad858574f2438b64262

18 files changed:
binder/android/bluetooth/BufferConstraints.aidl [new file with mode: 0644]
binder/android/bluetooth/IBluetoothA2dp.aidl
btif/include/btif_a2dp_source.h
btif/include/btif_api.h
btif/include/btif_av.h
btif/src/bluetooth.cc
btif/src/btif_a2dp_source.cc
btif/src/btif_av.cc
btif/src/btif_core.cc
btif/src/btif_dm.cc
include/hardware/bluetooth.h
service/hal/fake_bluetooth_interface.cc
stack/btm/btm_ble_gap.cc
stack/btm/btm_ble_int_types.h
stack/btm/btm_int_types.h
stack/include/btm_ble_api.h
stack/include/btm_ble_api_types.h
stack/include/hcidefs.h

diff --git a/binder/android/bluetooth/BufferConstraints.aidl b/binder/android/bluetooth/BufferConstraints.aidl
new file mode 100644 (file)
index 0000000..751f5ac
--- /dev/null
@@ -0,0 +1,3 @@
+package android.bluetooth;
+
+parcelable BufferConstraints;
index 39157e5..9963104 100644 (file)
@@ -19,6 +19,7 @@ package android.bluetooth;
 import android.bluetooth.BluetoothCodecConfig;
 import android.bluetooth.BluetoothCodecStatus;
 import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BufferConstraints;
 
 /**
  * APIs for Bluetooth A2DP service
@@ -52,5 +53,8 @@ interface IBluetoothA2dp {
     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);
 }
index 6d2cbb1..2db8aa9 100644 (file)
@@ -126,4 +126,8 @@ BT_HDR* btif_a2dp_source_audio_readbuf(void);
 // 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 */
index 9fde531..618e2b1 100644 (file)
@@ -378,4 +378,15 @@ bt_status_t btif_config_hci_snoop_log(uint8_t enable);
  ******************************************************************************/
 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 */
index 8ddfc6a..0651e7b 100644 (file)
@@ -216,4 +216,11 @@ bool btif_av_is_a2dp_offload_running(void);
  */
 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 */
index 0fa0784..c5a08d4 100644 (file)
@@ -542,6 +542,10 @@ static int get_metric_id(const RawAddress& address) {
       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,
@@ -579,6 +583,7 @@ EXPORT_SYMBOL bt_interface_t bluetoothInterface = {
     get_avrcp_service,
     obfuscate_address,
     get_metric_id,
+    set_dynamic_audio_buffer_size,
 };
 
 // callback reporting helpers
index 9114691..ffaf22d 100644 (file)
@@ -229,6 +229,9 @@ static bluetooth::common::MessageLoopThread btif_a2dp_source_thread(
     "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(
@@ -950,10 +953,10 @@ static bool btif_a2dp_source_enqueue_callback(BT_HDR* p_buf, size_t frames_n,
   // 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;
@@ -1320,6 +1323,11 @@ static void btif_a2dp_source_update_metrics(void) {
   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__);
index a7bfb95..2c8b33e 100644 (file)
@@ -3439,3 +3439,7 @@ bool btif_av_is_a2dp_offload_running() {
 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);
+}
index 295d540..6917a31 100644 (file)
@@ -85,6 +85,11 @@ static void bt_jni_msg_ready(void* context);
 #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
  ******************************************************************************/
@@ -242,6 +247,70 @@ bt_status_t btif_init_bluetooth() {
   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
@@ -288,6 +357,9 @@ void 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);
 
@@ -755,3 +827,77 @@ void btif_disable_service(tBTA_SERVICE_ID service_id) {
     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;
+}
index 3b1bb1a..e3d06b6 100644 (file)
@@ -1706,6 +1706,9 @@ static void btif_dm_upstreams_evt(uint16_t event, char* p_param) {
       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;
     }
index 80780e1..d2655eb 100644 (file)
@@ -196,8 +196,22 @@ typedef struct {
   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 */
@@ -302,6 +316,8 @@ typedef enum {
    */
   BT_PROPERTY_LOCAL_IO_CAPS_BLE,
 
+  BT_PROPERTY_DYNAMIC_AUDIO_BUFFER,
+
   BT_PROPERTY_REMOTE_DEVICE_TIMESTAMP = 0xFF,
 } bt_property_type_t;
 
@@ -677,6 +693,11 @@ typedef struct {
    * @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"
index 4af8bc6..5427d91 100644 (file)
@@ -76,6 +76,7 @@ bt_interface_t fake_bt_iface = {
     nullptr, /* get_avrcp_service */
     nullptr, /* obfuscate_address */
     nullptr, /* get_metric_id */
+    nullptr, /* set_dynamic_audio_buffer_size */
 };
 
 }  // namespace
index d57a63f..dae1245 100644 (file)
@@ -69,6 +69,7 @@ extern void btm_clear_all_pending_le_entry(void);
 #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 {
 
@@ -453,6 +454,60 @@ tBTM_STATUS BTM_BleObserve(bool start, uint8_t duration,
 }
 
 #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
@@ -503,6 +558,28 @@ static void btm_ble_vendor_capability_vsc_cmpl_cback(
     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(
@@ -547,6 +624,17 @@ extern void BTM_BleGetVendorCapabilities(tBTM_BLE_VSC_CB* p_cmn_vsc_cb) {
   }
 }
 
+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
index 7eb22ea..4d87ded 100644 (file)
@@ -73,6 +73,7 @@ typedef enum : uint8_t {
 
 #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;
index 9b5073c..5b39f0b 100644 (file)
@@ -290,6 +290,10 @@ typedef struct {
   // 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};
index 263136f..4dd4f1b 100644 (file)
@@ -95,6 +95,21 @@ extern void BTM_BleSetScanParams(uint32_t scan_interval, uint32_t scan_window,
  *
  ******************************************************************************/
 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
index f98f2ab..9749fe5 100644 (file)
@@ -314,8 +314,21 @@ typedef struct {
   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
index 51a1750..3cbb599 100644 (file)
 /* 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