Loading android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp +19 −1 Original line number Diff line number Diff line Loading @@ -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}, Loading Loading @@ -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( Loading android/app/src/com/android/bluetooth/btservice/AdapterService.java +23 −0 Original line number Diff line number Diff line Loading @@ -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-------- Loading Loading @@ -4121,6 +4131,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, Loading Loading @@ -4213,6 +4234,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. Loading framework/java/android/bluetooth/BluetoothDevice.java +30 −0 Original line number Diff line number Diff line Loading @@ -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; } } system/binder/android/bluetooth/IBluetooth.aidl +3 −0 Original line number Diff line number Diff line Loading @@ -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); } system/btif/src/bluetooth.cc +8 −1 Original line number Diff line number Diff line Loading @@ -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, Loading Loading @@ -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 Loading Loading
android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp +19 −1 Original line number Diff line number Diff line Loading @@ -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}, Loading Loading @@ -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( Loading
android/app/src/com/android/bluetooth/btservice/AdapterService.java +23 −0 Original line number Diff line number Diff line Loading @@ -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-------- Loading Loading @@ -4121,6 +4131,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, Loading Loading @@ -4213,6 +4234,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. Loading
framework/java/android/bluetooth/BluetoothDevice.java +30 −0 Original line number Diff line number Diff line Loading @@ -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; } }
system/binder/android/bluetooth/IBluetooth.aidl +3 −0 Original line number Diff line number Diff line Loading @@ -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); }
system/btif/src/bluetooth.cc +8 −1 Original line number Diff line number Diff line Loading @@ -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, Loading Loading @@ -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 Loading