SpatialAudio: Add API to switch buffer size
Bug: 214615268
Test: Manually test signal passing from bluetooth/system to framework
Tag: #feature
Change-Id: Ie556c1d271b54834f360cf64249385fe44011181
diff --git a/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp b/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp
index 5e3a297..e8e2643 100644
--- a/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp
+++ b/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp
@@ -71,6 +71,7 @@
static jmethodID method_aclStateChangeCallback;
static jmethodID method_discoveryStateChangeCallback;
static jmethodID method_linkQualityReportCallback;
+static jmethodID method_switchBufferSizeCallback;
static jmethodID method_setWakeAlarm;
static jmethodID method_acquireWakeLock;
static jmethodID method_releaseWakeLock;
@@ -598,6 +599,34 @@
(jint)negative_acknowledgement_count);
}
+static void switch_buffer_size_callback(RawAddress* bd_addr,
+ bool is_low_latency_buffer_size) {
+
+ if (!bd_addr) {
+ ALOGE("Address is null in %s", __func__);
+ return;
+ }
+ CallbackEnv sCallbackEnv(__func__);
+ if (!sCallbackEnv.valid()) return;
+
+ ScopedLocalRef<jbyteArray> addr(
+ sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress)));
+ if (!addr.get()) {
+ ALOGE("Error while allocating in: %s", __func__);
+ return;
+ }
+
+ sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress),
+ (jbyte*)bd_addr);
+
+ ALOGV("%s: SwitchBufferSizeCallback: %s", __func__,
+ is_low_latency_buffer_size ? "true" : "false");
+
+ sCallbackEnv->CallVoidMethod(
+ sJniCallbacksObj, method_switchBufferSizeCallback, addr.get(),
+ (jboolean)is_low_latency_buffer_size);
+}
+
static void callback_thread_event(bt_cb_thread_evt event) {
if (event == ASSOCIATE_JVM) {
JavaVMAttachArgs args;
@@ -674,7 +703,8 @@
le_test_mode_recv_callback,
energy_info_recv_callback,
link_quality_report_callback,
- generate_local_oob_data_callback};
+ generate_local_oob_data_callback,
+ switch_buffer_size_callback};
// The callback to call when the wake alarm fires.
static alarm_cb sAlarmCallback;
@@ -893,6 +923,9 @@
method_linkQualityReportCallback = env->GetMethodID(
jniCallbackClass, "linkQualityReportCallback", "(JIIIIII)V");
+ method_switchBufferSizeCallback =
+ env->GetMethodID(jniCallbackClass, "switchBufferSizeCallback", "([BZ)V");
+
method_setWakeAlarm = env->GetMethodID(clazz, "setWakeAlarm", "(JZ)Z");
method_acquireWakeLock =
env->GetMethodID(clazz, "acquireWakeLock", "(Ljava/lang/String;)Z");
diff --git a/android/app/res/values/config.xml b/android/app/res/values/config.xml
index 4653c91..1f86bc3 100644
--- a/android/app/res/values/config.xml
+++ b/android/app/res/values/config.xml
@@ -145,4 +145,10 @@
-->
<bool name="enable_gd_up_to_scanning_layer">true</bool>
+ <!-- Package of fastpair service -->
+ <string name="peripheral_link_package">com.google.android.gms</string>
+ <!-- Service name of fastpair-->
+ <string name="peripheral_link_service">.nearby.discovery.service.DiscoveryService</string>
+
+
</resources>
diff --git a/android/app/src/com/android/bluetooth/btservice/AdapterService.java b/android/app/src/com/android/bluetooth/btservice/AdapterService.java
index a206b7a..58faee2 100644
--- a/android/app/src/com/android/bluetooth/btservice/AdapterService.java
+++ b/android/app/src/com/android/bluetooth/btservice/AdapterService.java
@@ -811,6 +811,20 @@
}
}
+ void switchBufferSizeCallback(byte[] address, boolean isLowLatencyBufferSize) {
+ BluetoothDevice device = getDeviceFromByte(address);
+ // Send intent to fastpair
+ Intent switchBufferSizeIntent = new Intent(BluetoothDevice.ACTION_SWITCH_BUFFER_SIZE);
+ switchBufferSizeIntent.setClassName(
+ getString(com.android.bluetooth.R.string.peripheral_link_package),
+ getString(com.android.bluetooth.R.string.peripheral_link_package)
+ + getString(com.android.bluetooth.R.string.peripheral_link_service));
+ switchBufferSizeIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
+ switchBufferSizeIntent.putExtra(
+ BluetoothDevice.EXTRA_LOW_LATENCY_BUFFER_SIZE, isLowLatencyBufferSize);
+ sendBroadcast(switchBufferSizeIntent);
+ }
+
/**
* Enable/disable BluetoothInCallService
*
diff --git a/android/app/src/com/android/bluetooth/btservice/JniCallbacks.java b/android/app/src/com/android/bluetooth/btservice/JniCallbacks.java
index 03d9264..5d7b49d 100644
--- a/android/app/src/com/android/bluetooth/btservice/JniCallbacks.java
+++ b/android/app/src/com/android/bluetooth/btservice/JniCallbacks.java
@@ -106,4 +106,8 @@
packets_not_receive_count, negative_acknowledgement_count);
}
+ void switchBufferSizeCallback(byte[] mac_address, boolean is_low_latency_buffer_size) {
+ mAdapterService.switchBufferSizeCallback(mac_address, is_low_latency_buffer_size);
+ }
+
}
diff --git a/framework/java/android/bluetooth/BluetoothDevice.java b/framework/java/android/bluetooth/BluetoothDevice.java
index 4c138f8..89ec4b2 100644
--- a/framework/java/android/bluetooth/BluetoothDevice.java
+++ b/framework/java/android/bluetooth/BluetoothDevice.java
@@ -232,6 +232,25 @@
"android.bluetooth.device.action.BATTERY_LEVEL_CHANGED";
/**
+ * Broadcast Action: Indicates the audio buffer size should be switched
+ * between a low latency buffer size and a higher and larger latency buffer size.
+ * <p>Always contains the extra fields {@link #EXTRA_DEVICE} and {@link
+ * #EXTRA_LOW_LATENCY_BUFFER_SIZE}.
+ *
+ * @hide
+ */
+ @SuppressLint("ActionValue")
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.BLUETOOTH_CONNECT,
+ android.Manifest.permission.BLUETOOTH_PRIVILEGED,
+ })
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ @SystemApi
+ public static final String ACTION_SWITCH_BUFFER_SIZE =
+ "android.bluetooth.device.action.SWITCH_BUFFER_SIZE";
+
+ /**
* Used as an Integer extra field in {@link #ACTION_BATTERY_LEVEL_CHANGED}
* intent. It contains the most recently retrieved battery level information
* ranging from 0% to 100% for a remote device, {@link #BATTERY_LEVEL_UNKNOWN}
@@ -310,6 +329,17 @@
*/
public static final String EXTRA_PREVIOUS_BOND_STATE =
"android.bluetooth.device.extra.PREVIOUS_BOND_STATE";
+
+ /**
+ * Used as a boolean extra field to indicate if audio buffer size is low latency or not
+ *
+ * @hide
+ */
+ @SuppressLint("ActionValue")
+ @SystemApi
+ public static final String EXTRA_LOW_LATENCY_BUFFER_SIZE =
+ "android.bluetooth.device.extra.LOW_LATENCY_BUFFER_SIZE";
+
/**
* Indicates the remote device is not bonded (paired).
* <p>There is no shared link key with the remote device, so communication
diff --git a/system/btif/include/btif_common.h b/system/btif/include/btif_common.h
index f932c04..3782b50 100644
--- a/system/btif/include/btif_common.h
+++ b/system/btif/include/btif_common.h
@@ -232,4 +232,7 @@
int retransmission_count, int packets_not_receive_count,
int negative_acknowledgement_count);
+void invoke_switch_buffer_size_cb(RawAddress remote_addr,
+ bool is_low_latency_buffer_size);
+
#endif /* BTIF_COMMON_H */
diff --git a/system/btif/src/bluetooth.cc b/system/btif/src/bluetooth.cc
index 9b5f5d3..7d7a2f8 100644
--- a/system/btif/src/bluetooth.cc
+++ b/system/btif/src/bluetooth.cc
@@ -895,3 +895,15 @@
timestamp, report_id, rssi, snr, retransmission_count,
packets_not_receive_count, negative_acknowledgement_count));
}
+
+void invoke_switch_buffer_size_cb(RawAddress remote_addr,
+ bool is_low_latency_buffer_size) {
+ do_in_jni_thread(
+ FROM_HERE,
+ base::BindOnce(
+ [](RawAddress remote_addr, bool is_low_latency_buffer_size) {
+ HAL_CBACK(bt_hal_cbacks, switch_buffer_size_cb, &remote_addr,
+ is_low_latency_buffer_size);
+ },
+ remote_addr, is_low_latency_buffer_size));
+}
diff --git a/system/gd/rust/topshim/src/btif.rs b/system/gd/rust/topshim/src/btif.rs
index 34283ff..e854f57 100644
--- a/system/gd/rust/topshim/src/btif.rs
+++ b/system/gd/rust/topshim/src/btif.rs
@@ -699,6 +699,7 @@
// energy_info_cb
// link_quality_report_cb
// generate_local_oob_data_cb
+ // switch_buffer_size_cb
}
pub struct BaseCallbacksDispatcher {
@@ -814,6 +815,7 @@
energy_info_cb: None,
link_quality_report_cb: None,
generate_local_oob_data_cb: None,
+ switch_buffer_size_cb: None,
});
let rawcb: *mut bindings::bt_callbacks_t = &mut *callbacks;
diff --git a/system/include/hardware/bluetooth.h b/system/include/hardware/bluetooth.h
index c174d91..d907dbe 100644
--- a/system/include/hardware/bluetooth.h
+++ b/system/include/hardware/bluetooth.h
@@ -469,6 +469,10 @@
int retransmission_count, int packets_not_receive_count,
int negative_acknowledgement_count);
+/** Switch the buffer size callback */
+typedef void (*switch_buffer_size_callback)(RawAddress* remote_addr,
+ bool is_low_latency_buffer_size);
+
typedef enum { ASSOCIATE_JVM, DISASSOCIATE_JVM } bt_cb_thread_evt;
/** Thread Associate/Disassociate JVM Callback */
@@ -526,6 +530,7 @@
energy_info_callback energy_info_cb;
link_quality_report_callback link_quality_report_cb;
generate_local_oob_data_callback generate_local_oob_data_cb;
+ switch_buffer_size_callback switch_buffer_size_cb;
} bt_callbacks_t;
typedef void (*alarm_cb)(void* data);
diff --git a/system/service/hal/bluetooth_interface.cc b/system/service/hal/bluetooth_interface.cc
index 2e5b83a..c47a3ed 100644
--- a/system/service/hal/bluetooth_interface.cc
+++ b/system/service/hal/bluetooth_interface.cc
@@ -217,6 +217,16 @@
packets_not_receive_count, negative_acknowledgement_count));
}
+void SwitchBufferSizeCallback(RawAddress* remote_addr,
+ bool is_low_latency_buffer_size) {
+ shared_lock<shared_mutex_impl> lock(g_instance_lock);
+ VERIFY_INTERFACE_OR_RETURN();
+ LOG(WARNING) << __func__ << " - is_low_latency_buffer_size: "
+ << is_low_latency_buffer_size;
+ FOR_EACH_BLUETOOTH_OBSERVER(
+ SwitchBufferSizeCallback(remote_addr, is_low_latency_buffer_size));
+}
+
// The HAL Bluetooth DM callbacks.
bt_callbacks_t bt_callbacks = {
sizeof(bt_callbacks_t),
@@ -235,7 +245,8 @@
nullptr, /* le_test_mode_cb */
nullptr, /* energy_info_cb */
LinkQualityReportCallback,
- nullptr /* generate_local_oob_data_cb */
+ nullptr /* generate_local_oob_data_cb */,
+ SwitchBufferSizeCallback
};
bt_os_callouts_t bt_os_callouts = {sizeof(bt_os_callouts_t),
@@ -425,6 +436,11 @@
// Do nothing.
}
+void BluetoothInterface::Observer::SwitchBufferSizeCallback(
+ RawAddress* /* remote_addr */, bool /* is_low_latency_buffer_size */) {
+ // Do nothing.
+}
+
// static
bool BluetoothInterface::Initialize() {
unique_lock<shared_mutex_impl> lock(g_instance_lock);
diff --git a/system/service/hal/bluetooth_interface.h b/system/service/hal/bluetooth_interface.h
index 0390cb0..50c35f6 100644
--- a/system/service/hal/bluetooth_interface.h
+++ b/system/service/hal/bluetooth_interface.h
@@ -83,6 +83,9 @@
int retransmission_count, int packets_not_receive_count,
int negative_acknowledgement_count);
+ virtual void SwitchBufferSizeCallback(RawAddress* remote_addr,
+ bool is_low_latency_buffer_size);
+
// TODO(armansito): Complete the list of callbacks.
};
diff --git a/system/test/headless/headless.cc b/system/test/headless/headless.cc
index fd6a35e..d9b12fd 100644
--- a/system/test/headless/headless.cc
+++ b/system/test/headless/headless.cc
@@ -136,6 +136,12 @@
LOG_INFO("%s", __func__);
}
+/** Switch buffer size callback */
+void switch_buffer_size(RawAddress* remote_addr,
+ bool is_low_latency_buffer_size) {
+ LOG_INFO("%s", __func__);
+}
+
void thread_event(bt_cb_thread_evt evt) { LOG_INFO("%s", __func__); }
void dut_mode_recv(uint16_t opcode, uint8_t* buf, uint8_t len) {
@@ -169,6 +175,7 @@
.le_test_mode_cb = le_test_mode,
.energy_info_cb = energy_info,
.link_quality_report_cb = link_quality_report,
+ .switch_buffer_size_cb = switch_buffer_size,
};
// HAL HARDWARE CALLBACKS