Loading android/app/src/com/android/bluetooth/gatt/GattService.java +63 −51 Original line number Diff line number Diff line Loading @@ -16,7 +16,7 @@ package com.android.bluetooth.gatt; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static com.android.bluetooth.Utils.enforceBluetoothPrivilegedPermission; import android.annotation.RequiresPermission; import android.annotation.SuppressLint; Loading Loading @@ -52,6 +52,7 @@ import android.content.Context; import android.content.Intent; import android.net.MacAddress; import android.os.Binder; import android.os.Build; import android.os.Handler; import android.os.IBinder; import android.os.Message; Loading Loading @@ -426,40 +427,37 @@ public class GattService extends ProfileService { sGattService = instance; } // Suppressed since we're not actually enforcing here // Suppressed because we are conditionally enforcing @SuppressLint("AndroidFrameworkRequiresPermission") private boolean permissionCheck(UUID characteristicUuid) { return !isHidCharUuid(characteristicUuid) || (checkCallingOrSelfPermission(BLUETOOTH_PRIVILEGED) == PERMISSION_GRANTED); private void permissionCheck(UUID characteristicUuid) { if (!isHidCharUuid(characteristicUuid)) { return; } enforceBluetoothPrivilegedPermission(this); } // Suppressed since we're not actually enforcing here // Suppressed because we are conditionally enforcing @SuppressLint("AndroidFrameworkRequiresPermission") private boolean permissionCheck(int connId, int handle) { Set<Integer> restrictedHandles = mRestrictedHandles.get(connId); if (restrictedHandles == null || !restrictedHandles.contains(handle)) { return true; private void permissionCheck(int connId, int handle) { if (!isHandleRestricted(connId, handle)) { return; } return (checkCallingOrSelfPermission(BLUETOOTH_PRIVILEGED) == PERMISSION_GRANTED); enforceBluetoothPrivilegedPermission(this); } // Suppressed since we're not actually enforcing here // Suppressed because we are conditionally enforcing @SuppressLint("AndroidFrameworkRequiresPermission") private boolean permissionCheck(ClientMap.App app, int connId, int handle) { Set<Integer> restrictedHandles = mRestrictedHandles.get(connId); if (restrictedHandles == null || !restrictedHandles.contains(handle)) { return true; private void permissionCheck(ClientMap.App app, int connId, int handle) { if (!isHandleRestricted(connId, handle) || app.hasBluetoothPrivilegedPermission) { return; } if (!app.hasBluetoothPrivilegedPermission && checkCallingOrSelfPermission(BLUETOOTH_PRIVILEGED)== PERMISSION_GRANTED) { enforceBluetoothPrivilegedPermission(this); app.hasBluetoothPrivilegedPermission = true; } return app.hasBluetoothPrivilegedPermission; private boolean isHandleRestricted(int connId, int handle) { Set<Integer> restrictedHandles = mRestrictedHandles.get(connId); return restrictedHandles != null && restrictedHandles.contains(handle); } @Override Loading Loading @@ -2302,7 +2300,13 @@ public class GattService extends ProfileService { ClientMap.App app = mClientMap.getByConnId(connId); if (app != null) { if (!permissionCheck(app, connId, handle)) { try { permissionCheck(connId, handle); } catch (SecurityException ex) { // Only throws on T+ as this is an older API and did not throw prior to T if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { throw ex; } Log.w(TAG, "onNotify() - permission check failed!"); return; } Loading Loading @@ -3255,7 +3259,7 @@ public class GattService extends ProfileService { this, attributionSource, "GattService getOwnAddress")) { return; } enforcePrivilegedPermission(); enforceBluetoothPrivilegedPermission(this); mAdvertiseManager.getOwnAddress(advertiserId); } Loading Loading @@ -3539,7 +3543,13 @@ public class GattService extends ProfileService { return; } if (!permissionCheck(connId, handle)) { try { permissionCheck(connId, handle); } catch (SecurityException ex) { // Only throws on T+ as this is an older API and did not throw prior to T if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { throw ex; } Log.w(TAG, "readCharacteristic() - permission check failed!"); return; } Loading @@ -3565,7 +3575,13 @@ public class GattService extends ProfileService { return; } if (!permissionCheck(uuid)) { try { permissionCheck(uuid); } catch (SecurityException ex) { // Only throws on T+ as this is an older API and did not throw prior to T if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { throw ex; } Log.w(TAG, "readUsingCharacteristicUuid() - permission check failed!"); return; } Loading Loading @@ -3595,11 +3611,7 @@ public class GattService extends ProfileService { Log.e(TAG, "writeCharacteristic() - No connection for " + address + "..."); return BluetoothStatusCodes.ERROR_DEVICE_NOT_CONNECTED; } if (!permissionCheck(connId, handle)) { Log.w(TAG, "writeCharacteristic() - permission check failed!"); return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_PRIVILEGED_PERMISSION; } permissionCheck(connId, handle); Log.d(TAG, "writeCharacteristic() - trying to acquire permit."); // Lock the thread until onCharacteristicWrite callback comes back. Loading Loading @@ -3640,7 +3652,13 @@ public class GattService extends ProfileService { return; } if (!permissionCheck(connId, handle)) { try { permissionCheck(connId, handle); } catch (SecurityException ex) { // Only throws on T+ as this is an older API and did not throw prior to T if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { throw ex; } Log.w(TAG, "readDescriptor() - permission check failed!"); return; } Loading @@ -3664,11 +3682,7 @@ public class GattService extends ProfileService { Log.e(TAG, "writeDescriptor() - No connection for " + address + "..."); return BluetoothStatusCodes.ERROR_DEVICE_NOT_CONNECTED; } if (!permissionCheck(connId, handle)) { Log.w(TAG, "writeDescriptor() - permission check failed!"); return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_PRIVILEGED_PERMISSION; } permissionCheck(connId, handle); gattClientWriteDescriptorNative(connId, handle, authReq, value); return BluetoothStatusCodes.SUCCESS; Loading Loading @@ -3724,7 +3738,13 @@ public class GattService extends ProfileService { return; } if (!permissionCheck(connId, handle)) { try { permissionCheck(connId, handle); } catch (SecurityException ex) { // Only throws on T+ as this is an older API and did not throw prior to T if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { throw ex; } Log.w(TAG, "registerForNotification() - permission check failed!"); return; } Loading Loading @@ -4449,25 +4469,17 @@ public class GattService extends ProfileService { == BluetoothDevice.ADDRESS_TYPE_PUBLIC && filter.getIrk() == null) { // Do not enforce } else { enforcePrivilegedPermission(); } enforceBluetoothPrivilegedPermission(this); } } } } // Enforce caller has BLUETOOTH_PRIVILEGED permission. A {@link SecurityException} will be // thrown if the caller app does not have BLUETOOTH_PRIVILEGED permission. @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) private void enforcePrivilegedPermission() { enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, "Need BLUETOOTH_PRIVILEGED permission"); } @SuppressLint("AndroidFrameworkRequiresPermission") private void enforcePrivilegedPermissionIfNeeded(ScanSettings settings) { if (needsPrivilegedPermissionForScan(settings)) { enforcePrivilegedPermission(); enforceBluetoothPrivilegedPermission(this); } } Loading framework/api/current.txt +0 −1 Original line number Diff line number Diff line Loading @@ -1056,7 +1056,6 @@ package android.bluetooth { field public static final int ERROR_GATT_WRITE_NOT_ALLOWED = 200; // 0xc8 field public static final int ERROR_GATT_WRITE_REQUEST_BUSY = 201; // 0xc9 field public static final int ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION = 6; // 0x6 field public static final int ERROR_MISSING_BLUETOOTH_PRIVILEGED_PERMISSION = 8; // 0x8 field public static final int ERROR_PROFILE_SERVICE_NOT_BOUND = 9; // 0x9 field public static final int ERROR_UNKNOWN = 2147483647; // 0x7fffffff field public static final int FEATURE_NOT_SUPPORTED = 11; // 0xb Loading framework/java/android/bluetooth/BluetoothGatt.java +6 −13 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ import android.annotation.NonNull; import android.annotation.RequiresNoPermission; import android.annotation.RequiresPermission; import android.annotation.SuppressLint; import android.bluetooth.BluetoothGattCharacteristic.WriteType; import android.bluetooth.annotations.RequiresBluetoothConnectPermission; import android.bluetooth.annotations.RequiresLegacyBluetoothPermission; import android.compat.annotation.UnsupportedAppUsage; Loading Loading @@ -423,9 +424,6 @@ public final class BluetoothGatt implements BluetoothProfile { if (status == 0) characteristic.setValue(value); callback.onCharacteristicRead(BluetoothGatt.this, characteristic, value, status); // Keep calling deprecated callback to maintain app compatibility callback.onCharacteristicRead(BluetoothGatt.this, characteristic, status); } } }); Loading Loading @@ -526,9 +524,6 @@ public final class BluetoothGatt implements BluetoothProfile { characteristic.setValue(value); callback.onCharacteristicChanged(BluetoothGatt.this, characteristic, value); // Keep calling deprecated callback to maintain app compatibility callback.onCharacteristicChanged(BluetoothGatt.this, characteristic); } } }); Loading Loading @@ -585,8 +580,6 @@ public final class BluetoothGatt implements BluetoothProfile { if (status == 0) descriptor.setValue(value); callback.onDescriptorRead(BluetoothGatt.this, descriptor, status, value); // Keep calling deprecated callback to maintain app compatibility callback.onDescriptorRead(BluetoothGatt.this, descriptor, status); } } }); Loading Loading @@ -1305,7 +1298,6 @@ public final class BluetoothGatt implements BluetoothProfile { return true; } /** * Writes a given characteristic and its values to the associated remote device. * Loading @@ -1318,7 +1310,8 @@ public final class BluetoothGatt implements BluetoothProfile { * @throws IllegalArgumentException if characteristic or its value are null * * @deprecated Use {@link BluetoothGatt#writeCharacteristic(BluetoothGattCharacteristic, byte[], * int)} as this is not memory safe. * int)} as this is not memory safe because it relies on a {@link BluetoothGattCharacteristic} * object whose underlying fields are subject to change outside this method. */ @Deprecated @RequiresLegacyBluetoothPermission Loading @@ -1338,7 +1331,6 @@ public final class BluetoothGatt implements BluetoothProfile { @IntDef(value = { BluetoothStatusCodes.SUCCESS, BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION, BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_PRIVILEGED_PERMISSION, BluetoothStatusCodes.ERROR_DEVICE_NOT_CONNECTED, BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND, BluetoothStatusCodes.ERROR_GATT_WRITE_NOT_ALLOWED, Loading @@ -1362,7 +1354,7 @@ public final class BluetoothGatt implements BluetoothProfile { @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) @WriteOperationReturnValues public int writeCharacteristic(@NonNull BluetoothGattCharacteristic characteristic, @NonNull byte[] value, int writeType) { @NonNull byte[] value, @WriteType int writeType) { if (characteristic == null) { throw new IllegalArgumentException("characteristic must not be null"); } Loading Loading @@ -1487,7 +1479,8 @@ public final class BluetoothGatt implements BluetoothProfile { * @throws IllegalArgumentException if descriptor or its value are null * * @deprecated Use {@link BluetoothGatt#writeDescriptor(BluetoothGattDescriptor, byte[])} as * this is not memory safe. * this is not memory safe because it relies on a {@link BluetoothGattDescriptor} object * whose underlying fields are subject to change outside this method. */ @Deprecated @RequiresLegacyBluetoothPermission Loading framework/java/android/bluetooth/BluetoothGattCallback.java +3 −0 Original line number Diff line number Diff line Loading @@ -105,6 +105,7 @@ public abstract class BluetoothGattCallback { */ public void onCharacteristicRead(@NonNull BluetoothGatt gatt, @NonNull BluetoothGattCharacteristic characteristic, @NonNull byte[] value, int status) { onCharacteristicRead(gatt, characteristic, status); } /** Loading Loading @@ -155,6 +156,7 @@ public abstract class BluetoothGattCallback { */ public void onCharacteristicChanged(@NonNull BluetoothGatt gatt, @NonNull BluetoothGattCharacteristic characteristic, @NonNull byte[] value) { onCharacteristicChanged(gatt, characteristic); } /** Loading Loading @@ -184,6 +186,7 @@ public abstract class BluetoothGattCallback { */ public void onDescriptorRead(@NonNull BluetoothGatt gatt, @NonNull BluetoothGattDescriptor descriptor, int status, @NonNull byte[] value) { onDescriptorRead(gatt, descriptor, status); } /** Loading framework/java/android/bluetooth/BluetoothGattCharacteristic.java +13 −1 Original line number Diff line number Diff line Loading @@ -15,11 +15,14 @@ */ package android.bluetooth; import android.annotation.IntDef; import android.compat.annotation.UnsupportedAppUsage; import android.os.Parcel; import android.os.ParcelUuid; import android.os.Parcelable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.List; import java.util.UUID; Loading Loading @@ -115,8 +118,17 @@ public class BluetoothGattCharacteristic implements Parcelable { */ public static final int PERMISSION_WRITE_SIGNED_MITM = 0x100; /** @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef(prefix = "WRITE_TYPE_", value = { WRITE_TYPE_DEFAULT, WRITE_TYPE_NO_RESPONSE, WRITE_TYPE_SIGNED }) public @interface WriteType{} /** * Write characteristic, requesting acknoledgement by the remote device * Write characteristic, requesting acknowledgement by the remote device */ public static final int WRITE_TYPE_DEFAULT = 0x02; Loading Loading
android/app/src/com/android/bluetooth/gatt/GattService.java +63 −51 Original line number Diff line number Diff line Loading @@ -16,7 +16,7 @@ package com.android.bluetooth.gatt; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static com.android.bluetooth.Utils.enforceBluetoothPrivilegedPermission; import android.annotation.RequiresPermission; import android.annotation.SuppressLint; Loading Loading @@ -52,6 +52,7 @@ import android.content.Context; import android.content.Intent; import android.net.MacAddress; import android.os.Binder; import android.os.Build; import android.os.Handler; import android.os.IBinder; import android.os.Message; Loading Loading @@ -426,40 +427,37 @@ public class GattService extends ProfileService { sGattService = instance; } // Suppressed since we're not actually enforcing here // Suppressed because we are conditionally enforcing @SuppressLint("AndroidFrameworkRequiresPermission") private boolean permissionCheck(UUID characteristicUuid) { return !isHidCharUuid(characteristicUuid) || (checkCallingOrSelfPermission(BLUETOOTH_PRIVILEGED) == PERMISSION_GRANTED); private void permissionCheck(UUID characteristicUuid) { if (!isHidCharUuid(characteristicUuid)) { return; } enforceBluetoothPrivilegedPermission(this); } // Suppressed since we're not actually enforcing here // Suppressed because we are conditionally enforcing @SuppressLint("AndroidFrameworkRequiresPermission") private boolean permissionCheck(int connId, int handle) { Set<Integer> restrictedHandles = mRestrictedHandles.get(connId); if (restrictedHandles == null || !restrictedHandles.contains(handle)) { return true; private void permissionCheck(int connId, int handle) { if (!isHandleRestricted(connId, handle)) { return; } return (checkCallingOrSelfPermission(BLUETOOTH_PRIVILEGED) == PERMISSION_GRANTED); enforceBluetoothPrivilegedPermission(this); } // Suppressed since we're not actually enforcing here // Suppressed because we are conditionally enforcing @SuppressLint("AndroidFrameworkRequiresPermission") private boolean permissionCheck(ClientMap.App app, int connId, int handle) { Set<Integer> restrictedHandles = mRestrictedHandles.get(connId); if (restrictedHandles == null || !restrictedHandles.contains(handle)) { return true; private void permissionCheck(ClientMap.App app, int connId, int handle) { if (!isHandleRestricted(connId, handle) || app.hasBluetoothPrivilegedPermission) { return; } if (!app.hasBluetoothPrivilegedPermission && checkCallingOrSelfPermission(BLUETOOTH_PRIVILEGED)== PERMISSION_GRANTED) { enforceBluetoothPrivilegedPermission(this); app.hasBluetoothPrivilegedPermission = true; } return app.hasBluetoothPrivilegedPermission; private boolean isHandleRestricted(int connId, int handle) { Set<Integer> restrictedHandles = mRestrictedHandles.get(connId); return restrictedHandles != null && restrictedHandles.contains(handle); } @Override Loading Loading @@ -2302,7 +2300,13 @@ public class GattService extends ProfileService { ClientMap.App app = mClientMap.getByConnId(connId); if (app != null) { if (!permissionCheck(app, connId, handle)) { try { permissionCheck(connId, handle); } catch (SecurityException ex) { // Only throws on T+ as this is an older API and did not throw prior to T if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { throw ex; } Log.w(TAG, "onNotify() - permission check failed!"); return; } Loading Loading @@ -3255,7 +3259,7 @@ public class GattService extends ProfileService { this, attributionSource, "GattService getOwnAddress")) { return; } enforcePrivilegedPermission(); enforceBluetoothPrivilegedPermission(this); mAdvertiseManager.getOwnAddress(advertiserId); } Loading Loading @@ -3539,7 +3543,13 @@ public class GattService extends ProfileService { return; } if (!permissionCheck(connId, handle)) { try { permissionCheck(connId, handle); } catch (SecurityException ex) { // Only throws on T+ as this is an older API and did not throw prior to T if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { throw ex; } Log.w(TAG, "readCharacteristic() - permission check failed!"); return; } Loading @@ -3565,7 +3575,13 @@ public class GattService extends ProfileService { return; } if (!permissionCheck(uuid)) { try { permissionCheck(uuid); } catch (SecurityException ex) { // Only throws on T+ as this is an older API and did not throw prior to T if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { throw ex; } Log.w(TAG, "readUsingCharacteristicUuid() - permission check failed!"); return; } Loading Loading @@ -3595,11 +3611,7 @@ public class GattService extends ProfileService { Log.e(TAG, "writeCharacteristic() - No connection for " + address + "..."); return BluetoothStatusCodes.ERROR_DEVICE_NOT_CONNECTED; } if (!permissionCheck(connId, handle)) { Log.w(TAG, "writeCharacteristic() - permission check failed!"); return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_PRIVILEGED_PERMISSION; } permissionCheck(connId, handle); Log.d(TAG, "writeCharacteristic() - trying to acquire permit."); // Lock the thread until onCharacteristicWrite callback comes back. Loading Loading @@ -3640,7 +3652,13 @@ public class GattService extends ProfileService { return; } if (!permissionCheck(connId, handle)) { try { permissionCheck(connId, handle); } catch (SecurityException ex) { // Only throws on T+ as this is an older API and did not throw prior to T if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { throw ex; } Log.w(TAG, "readDescriptor() - permission check failed!"); return; } Loading @@ -3664,11 +3682,7 @@ public class GattService extends ProfileService { Log.e(TAG, "writeDescriptor() - No connection for " + address + "..."); return BluetoothStatusCodes.ERROR_DEVICE_NOT_CONNECTED; } if (!permissionCheck(connId, handle)) { Log.w(TAG, "writeDescriptor() - permission check failed!"); return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_PRIVILEGED_PERMISSION; } permissionCheck(connId, handle); gattClientWriteDescriptorNative(connId, handle, authReq, value); return BluetoothStatusCodes.SUCCESS; Loading Loading @@ -3724,7 +3738,13 @@ public class GattService extends ProfileService { return; } if (!permissionCheck(connId, handle)) { try { permissionCheck(connId, handle); } catch (SecurityException ex) { // Only throws on T+ as this is an older API and did not throw prior to T if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { throw ex; } Log.w(TAG, "registerForNotification() - permission check failed!"); return; } Loading Loading @@ -4449,25 +4469,17 @@ public class GattService extends ProfileService { == BluetoothDevice.ADDRESS_TYPE_PUBLIC && filter.getIrk() == null) { // Do not enforce } else { enforcePrivilegedPermission(); } enforceBluetoothPrivilegedPermission(this); } } } } // Enforce caller has BLUETOOTH_PRIVILEGED permission. A {@link SecurityException} will be // thrown if the caller app does not have BLUETOOTH_PRIVILEGED permission. @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) private void enforcePrivilegedPermission() { enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, "Need BLUETOOTH_PRIVILEGED permission"); } @SuppressLint("AndroidFrameworkRequiresPermission") private void enforcePrivilegedPermissionIfNeeded(ScanSettings settings) { if (needsPrivilegedPermissionForScan(settings)) { enforcePrivilegedPermission(); enforceBluetoothPrivilegedPermission(this); } } Loading
framework/api/current.txt +0 −1 Original line number Diff line number Diff line Loading @@ -1056,7 +1056,6 @@ package android.bluetooth { field public static final int ERROR_GATT_WRITE_NOT_ALLOWED = 200; // 0xc8 field public static final int ERROR_GATT_WRITE_REQUEST_BUSY = 201; // 0xc9 field public static final int ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION = 6; // 0x6 field public static final int ERROR_MISSING_BLUETOOTH_PRIVILEGED_PERMISSION = 8; // 0x8 field public static final int ERROR_PROFILE_SERVICE_NOT_BOUND = 9; // 0x9 field public static final int ERROR_UNKNOWN = 2147483647; // 0x7fffffff field public static final int FEATURE_NOT_SUPPORTED = 11; // 0xb Loading
framework/java/android/bluetooth/BluetoothGatt.java +6 −13 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ import android.annotation.NonNull; import android.annotation.RequiresNoPermission; import android.annotation.RequiresPermission; import android.annotation.SuppressLint; import android.bluetooth.BluetoothGattCharacteristic.WriteType; import android.bluetooth.annotations.RequiresBluetoothConnectPermission; import android.bluetooth.annotations.RequiresLegacyBluetoothPermission; import android.compat.annotation.UnsupportedAppUsage; Loading Loading @@ -423,9 +424,6 @@ public final class BluetoothGatt implements BluetoothProfile { if (status == 0) characteristic.setValue(value); callback.onCharacteristicRead(BluetoothGatt.this, characteristic, value, status); // Keep calling deprecated callback to maintain app compatibility callback.onCharacteristicRead(BluetoothGatt.this, characteristic, status); } } }); Loading Loading @@ -526,9 +524,6 @@ public final class BluetoothGatt implements BluetoothProfile { characteristic.setValue(value); callback.onCharacteristicChanged(BluetoothGatt.this, characteristic, value); // Keep calling deprecated callback to maintain app compatibility callback.onCharacteristicChanged(BluetoothGatt.this, characteristic); } } }); Loading Loading @@ -585,8 +580,6 @@ public final class BluetoothGatt implements BluetoothProfile { if (status == 0) descriptor.setValue(value); callback.onDescriptorRead(BluetoothGatt.this, descriptor, status, value); // Keep calling deprecated callback to maintain app compatibility callback.onDescriptorRead(BluetoothGatt.this, descriptor, status); } } }); Loading Loading @@ -1305,7 +1298,6 @@ public final class BluetoothGatt implements BluetoothProfile { return true; } /** * Writes a given characteristic and its values to the associated remote device. * Loading @@ -1318,7 +1310,8 @@ public final class BluetoothGatt implements BluetoothProfile { * @throws IllegalArgumentException if characteristic or its value are null * * @deprecated Use {@link BluetoothGatt#writeCharacteristic(BluetoothGattCharacteristic, byte[], * int)} as this is not memory safe. * int)} as this is not memory safe because it relies on a {@link BluetoothGattCharacteristic} * object whose underlying fields are subject to change outside this method. */ @Deprecated @RequiresLegacyBluetoothPermission Loading @@ -1338,7 +1331,6 @@ public final class BluetoothGatt implements BluetoothProfile { @IntDef(value = { BluetoothStatusCodes.SUCCESS, BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION, BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_PRIVILEGED_PERMISSION, BluetoothStatusCodes.ERROR_DEVICE_NOT_CONNECTED, BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND, BluetoothStatusCodes.ERROR_GATT_WRITE_NOT_ALLOWED, Loading @@ -1362,7 +1354,7 @@ public final class BluetoothGatt implements BluetoothProfile { @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) @WriteOperationReturnValues public int writeCharacteristic(@NonNull BluetoothGattCharacteristic characteristic, @NonNull byte[] value, int writeType) { @NonNull byte[] value, @WriteType int writeType) { if (characteristic == null) { throw new IllegalArgumentException("characteristic must not be null"); } Loading Loading @@ -1487,7 +1479,8 @@ public final class BluetoothGatt implements BluetoothProfile { * @throws IllegalArgumentException if descriptor or its value are null * * @deprecated Use {@link BluetoothGatt#writeDescriptor(BluetoothGattDescriptor, byte[])} as * this is not memory safe. * this is not memory safe because it relies on a {@link BluetoothGattDescriptor} object * whose underlying fields are subject to change outside this method. */ @Deprecated @RequiresLegacyBluetoothPermission Loading
framework/java/android/bluetooth/BluetoothGattCallback.java +3 −0 Original line number Diff line number Diff line Loading @@ -105,6 +105,7 @@ public abstract class BluetoothGattCallback { */ public void onCharacteristicRead(@NonNull BluetoothGatt gatt, @NonNull BluetoothGattCharacteristic characteristic, @NonNull byte[] value, int status) { onCharacteristicRead(gatt, characteristic, status); } /** Loading Loading @@ -155,6 +156,7 @@ public abstract class BluetoothGattCallback { */ public void onCharacteristicChanged(@NonNull BluetoothGatt gatt, @NonNull BluetoothGattCharacteristic characteristic, @NonNull byte[] value) { onCharacteristicChanged(gatt, characteristic); } /** Loading Loading @@ -184,6 +186,7 @@ public abstract class BluetoothGattCallback { */ public void onDescriptorRead(@NonNull BluetoothGatt gatt, @NonNull BluetoothGattDescriptor descriptor, int status, @NonNull byte[] value) { onDescriptorRead(gatt, descriptor, status); } /** Loading
framework/java/android/bluetooth/BluetoothGattCharacteristic.java +13 −1 Original line number Diff line number Diff line Loading @@ -15,11 +15,14 @@ */ package android.bluetooth; import android.annotation.IntDef; import android.compat.annotation.UnsupportedAppUsage; import android.os.Parcel; import android.os.ParcelUuid; import android.os.Parcelable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.List; import java.util.UUID; Loading Loading @@ -115,8 +118,17 @@ public class BluetoothGattCharacteristic implements Parcelable { */ public static final int PERMISSION_WRITE_SIGNED_MITM = 0x100; /** @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef(prefix = "WRITE_TYPE_", value = { WRITE_TYPE_DEFAULT, WRITE_TYPE_NO_RESPONSE, WRITE_TYPE_SIGNED }) public @interface WriteType{} /** * Write characteristic, requesting acknoledgement by the remote device * Write characteristic, requesting acknowledgement by the remote device */ public static final int WRITE_TYPE_DEFAULT = 0x02; Loading