diff options
| author | Chen Chen <cncn@google.com> | 2022-01-13 17:57:01 -0800 |
|---|---|---|
| committer | Chen Chen <cncn@google.com> | 2022-01-20 17:59:59 -0800 |
| commit | 31348f23ddc47bf1d54309d6f0ea0cd41c00e1be (patch) | |
| tree | b6d2518d74c36523be54cc009bde0dc05a0b1746 | |
| parent | e08c6a59957172be671dc3b499e601e38ce64c17 (diff) | |
SpatialAudio: Provide API to allow/disallow low latency audio
Bug: 214615268
Test: Manually test signal passing from framework to bluetooth/system
Tag: #feature
Change-Id: If7e1706c54bc6652698b0f5d5570de13ae54b519
| -rw-r--r-- | android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp | 20 | ||||
| -rw-r--r-- | android/app/src/com/android/bluetooth/btservice/AdapterService.java | 23 | ||||
| -rw-r--r-- | framework/java/android/bluetooth/BluetoothDevice.java | 30 | ||||
| -rw-r--r-- | system/binder/android/bluetooth/IBluetooth.aidl | 3 | ||||
| -rw-r--r-- | system/btif/src/bluetooth.cc | 9 | ||||
| -rw-r--r-- | system/include/hardware/bluetooth.h | 9 | ||||
| -rw-r--r-- | system/service/bluetooth_interface.cc | 9 | ||||
| -rw-r--r-- | system/service/hal/fake_bluetooth_interface.cc | 1 | ||||
| -rw-r--r-- | system/test/mock/mock_bluetooth_interface.cc | 7 |
9 files changed, 107 insertions, 4 deletions
diff --git a/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp b/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp index bbf46bb7df..5e3a2971a0 100644 --- a/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp +++ b/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp @@ -1714,6 +1714,22 @@ static int getMetricIdNative(JNIEnv* env, jobject obj, jbyteArray address) { return sBluetoothInterface->get_metric_id(addr_obj); } +static jboolean allowLowLatencyAudioNative(JNIEnv* env, jobject obj, + jboolean allowed, + jbyteArray address) { + ALOGV("%s", __func__); + if (!sBluetoothInterface) return false; + jbyte* addr = env->GetByteArrayElements(address, nullptr); + if (addr == nullptr) { + jniThrowIOException(env, EINVAL); + return false; + } + RawAddress addr_obj = {}; + addr_obj.FromOctets((uint8_t*)addr); + sBluetoothInterface->allow_low_latency_audio(allowed, addr_obj); + return true; +} + static JNINativeMethod sMethods[] = { /* name, signature, funcPtr */ {"classInitNative", "()V", (void*)classInitNative}, @@ -1753,7 +1769,9 @@ static JNINativeMethod sMethods[] = { {"createSocketChannelNative", "(ILjava/lang/String;[BIII)I", (void*)createSocketChannelNative}, {"requestMaximumTxDataLengthNative", "([B)V", - (void*)requestMaximumTxDataLengthNative}}; + (void*)requestMaximumTxDataLengthNative}, + {"allowLowLatencyAudioNative", "(Z[B)Z", (void*)allowLowLatencyAudioNative}, +}; int register_com_android_bluetooth_btservice_AdapterService(JNIEnv* env) { return jniRegisterNativeMethods( diff --git a/android/app/src/com/android/bluetooth/btservice/AdapterService.java b/android/app/src/com/android/bluetooth/btservice/AdapterService.java index af56c3dac6..028808f257 100644 --- a/android/app/src/com/android/bluetooth/btservice/AdapterService.java +++ b/android/app/src/com/android/bluetooth/btservice/AdapterService.java @@ -2633,6 +2633,16 @@ public class AdapterService extends Service { service.dump(fd, writer, args); writer.close(); } + + @Override + public boolean allowLowLatencyAudio(boolean allowed, BluetoothDevice device) { + AdapterService service = getService(); + if (service == null) { + return false; + } + enforceBluetoothPrivilegedPermission(service); + return service.allowLowLatencyAudio(allowed, device); + } } // ----API Methods-------- @@ -4116,6 +4126,17 @@ public class AdapterService extends Service { return getMetricIdNative(Utils.getByteAddress(device)); } + /** + * Allow audio low latency + * + * @param allowed true if audio low latency is being allowed + * @param device device whose audio low latency will be allowed or disallowed + * @return boolean true if audio low latency is successfully allowed or disallowed + */ + public boolean allowLowLatencyAudio(boolean allowed, BluetoothDevice device) { + return allowLowLatencyAudioNative(allowed, Utils.getByteAddress(device)); + } + static native void classInitNative(); native boolean initNative(boolean startRestricted, boolean isCommonCriteriaMode, @@ -4208,6 +4229,8 @@ public class AdapterService extends Service { /*package*/ native void requestMaximumTxDataLengthNative(byte[] address); + private native boolean allowLowLatencyAudioNative(boolean allowed, byte[] address); + // Returns if this is a mock object. This is currently used in testing so that we may not call // System.exit() while finalizing the object. Otherwise GC of mock objects unfortunately ends up // calling finalize() which in turn calls System.exit() and the process crashes. diff --git a/framework/java/android/bluetooth/BluetoothDevice.java b/framework/java/android/bluetooth/BluetoothDevice.java index 1edf5cc96b..70971a0c22 100644 --- a/framework/java/android/bluetooth/BluetoothDevice.java +++ b/framework/java/android/bluetooth/BluetoothDevice.java @@ -2828,4 +2828,34 @@ public final class BluetoothDevice implements Parcelable, Attributable { public static @MetadataKey int getMaxMetadataKey() { return METADATA_UNTETHERED_CASE_LOW_BATTERY_THRESHOLD; } + + /** + * Enable or disable audio low latency for this {@link BluetoothDevice}. + * + * @param allowed true if low latency is allowed, false if low latency is disallowed. + * @return true if the value is successfully set, + * false if there is a error when setting the value. + * @hide + */ + @SystemApi + @RequiresBluetoothConnectPermission + @RequiresPermission(allOf = { + android.Manifest.permission.BLUETOOTH_CONNECT, + android.Manifest.permission.BLUETOOTH_PRIVILEGED, + }) + public boolean setLowLatencyAudioAllowed(boolean allowed) { + final IBluetooth service = sService; + Log.i(TAG, "Allowing bluetooth audio low latency: " + allowed); + if (service == null) { + Log.e(TAG, "Bluetooth is not enabled. Cannot allow low latency"); + return false; + } + try { + service.allowLowLatencyAudio(allowed, this); + } catch (RemoteException e) { + Log.e(TAG, "allowLowLatencyAudio fail ", e); + e.rethrowFromSystemServer(); + } + return true; + } } diff --git a/system/binder/android/bluetooth/IBluetooth.aidl b/system/binder/android/bluetooth/IBluetooth.aidl index b93cd623a0..956159e8bb 100644 --- a/system/binder/android/bluetooth/IBluetooth.aidl +++ b/system/binder/android/bluetooth/IBluetooth.aidl @@ -253,4 +253,7 @@ interface IBluetooth boolean canBondWithoutDialog(in BluetoothDevice device, in AttributionSource attributionSource); @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT,android.Manifest.permission.BLUETOOTH_PRIVILEGED})") void generateLocalOobData(in int transport, IBluetoothOobDataCallback callback, in AttributionSource attributionSource); + + @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT,android.Manifest.permission.BLUETOOTH_PRIVILEGED})") + boolean allowLowLatencyAudio(in boolean allowed, in BluetoothDevice device); } diff --git a/system/btif/src/bluetooth.cc b/system/btif/src/bluetooth.cc index 7427eb4fa6..2d6bedb384 100644 --- a/system/btif/src/bluetooth.cc +++ b/system/btif/src/bluetooth.cc @@ -591,6 +591,12 @@ static int set_dynamic_audio_buffer_size(int codec, int size) { return btif_set_dynamic_audio_buffer_size(codec, size); } +static bool allow_low_latency_audio(bool allowed, const RawAddress& address) { + LOG_INFO("%s %s", __func__, allowed ? "true" : "false"); + // Call HAL here + return true; +} + EXPORT_SYMBOL bt_interface_t bluetoothInterface = { sizeof(bluetoothInterface), init, @@ -629,7 +635,8 @@ EXPORT_SYMBOL bt_interface_t bluetoothInterface = { obfuscate_address, get_metric_id, set_dynamic_audio_buffer_size, - generate_local_oob_data}; + generate_local_oob_data, + allow_low_latency_audio}; // callback reporting helpers diff --git a/system/include/hardware/bluetooth.h b/system/include/hardware/bluetooth.h index a1d16cebbe..45321db5c3 100644 --- a/system/include/hardware/bluetooth.h +++ b/system/include/hardware/bluetooth.h @@ -754,6 +754,15 @@ typedef struct { * Fetches the local Out of Band data. */ int (*generate_local_oob_data)(tBT_TRANSPORT transport); + + /** + * Allow or disallow audio low latency + * + * @param allowed true if allowing audio low latency + * @param address Bluetooth MAC address of Bluetooth device + * @return true if audio low latency is successfully allowed or disallowed + */ + bool (*allow_low_latency_audio)(bool allowed, const RawAddress& address); } bt_interface_t; #define BLUETOOTH_INTERFACE_STRING "bluetoothInterface" diff --git a/system/service/bluetooth_interface.cc b/system/service/bluetooth_interface.cc index ee58ef3103..155b13dc3d 100644 --- a/system/service/bluetooth_interface.cc +++ b/system/service/bluetooth_interface.cc @@ -584,6 +584,12 @@ static int set_dynamic_audio_buffer_size(int codec, int size) { return btif_set_dynamic_audio_buffer_size(codec, size); } +static bool allow_low_latency_audio(bool allowed, const RawAddress& address) { + LOG_INFO("%s %s", __func__, allowed ? "true" : "false"); + // Call HAL here + return true; +} + EXPORT_SYMBOL bt_interface_t bluetoothInterface = { sizeof(bluetoothInterface), init, @@ -622,7 +628,8 @@ EXPORT_SYMBOL bt_interface_t bluetoothInterface = { obfuscate_address, get_metric_id, set_dynamic_audio_buffer_size, - generate_local_oob_data}; + generate_local_oob_data, + allow_low_latency_audio}; // callback reporting helpers diff --git a/system/service/hal/fake_bluetooth_interface.cc b/system/service/hal/fake_bluetooth_interface.cc index e32c380e10..729778d4cd 100644 --- a/system/service/hal/fake_bluetooth_interface.cc +++ b/system/service/hal/fake_bluetooth_interface.cc @@ -80,6 +80,7 @@ bt_interface_t fake_bt_iface = { nullptr, /* get_metric_id */ nullptr, /* set_dynamic_audio_buffer_size */ nullptr, /* generate_local_oob_data */ + nullptr, /* allow_low_latency_audio */ }; } // namespace diff --git a/system/test/mock/mock_bluetooth_interface.cc b/system/test/mock/mock_bluetooth_interface.cc index c778c16c47..8f1423e77a 100644 --- a/system/test/mock/mock_bluetooth_interface.cc +++ b/system/test/mock/mock_bluetooth_interface.cc @@ -145,6 +145,10 @@ static int get_metric_id(const RawAddress& address) { return 0; } static int set_dynamic_audio_buffer_size(int codec, int size) { return 0; } +static bool allow_low_latency_audio(bool allowed, const RawAddress& address) { + return true; +} + EXPORT_SYMBOL bt_interface_t bluetoothInterface = { sizeof(bluetoothInterface), init, @@ -183,7 +187,8 @@ EXPORT_SYMBOL bt_interface_t bluetoothInterface = { obfuscate_address, get_metric_id, set_dynamic_audio_buffer_size, - generate_local_oob_data}; + generate_local_oob_data, + allow_low_latency_audio}; // callback reporting helpers |
