Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 48c007c9 authored by Rahul Sabnis's avatar Rahul Sabnis Committed by Android (Google) Code Review
Browse files

Merge "Deprecate GATT callbacks and methods that were not memory safe and...

Merge "Deprecate GATT callbacks and methods that were not memory safe and replace with memory safe versions."
parents 509c5fc4 3901dc6b
Loading
Loading
Loading
Loading
+25 −16
Original line number Original line Diff line number Diff line
@@ -9170,8 +9170,10 @@ package android.bluetooth {
    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean requestMtu(int);
    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean requestMtu(int);
    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean setCharacteristicNotification(android.bluetooth.BluetoothGattCharacteristic, boolean);
    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean setCharacteristicNotification(android.bluetooth.BluetoothGattCharacteristic, boolean);
    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void setPreferredPhy(int, int, int);
    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void setPreferredPhy(int, int, int);
    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean writeCharacteristic(android.bluetooth.BluetoothGattCharacteristic);
    method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean writeCharacteristic(android.bluetooth.BluetoothGattCharacteristic);
    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean writeDescriptor(android.bluetooth.BluetoothGattDescriptor);
    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int writeCharacteristic(@NonNull android.bluetooth.BluetoothGattCharacteristic, @NonNull byte[], int);
    method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean writeDescriptor(android.bluetooth.BluetoothGattDescriptor);
    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int writeDescriptor(@NonNull android.bluetooth.BluetoothGattDescriptor, @NonNull byte[]);
    field public static final int CONNECTION_PRIORITY_BALANCED = 0; // 0x0
    field public static final int CONNECTION_PRIORITY_BALANCED = 0; // 0x0
    field public static final int CONNECTION_PRIORITY_HIGH = 1; // 0x1
    field public static final int CONNECTION_PRIORITY_HIGH = 1; // 0x1
    field public static final int CONNECTION_PRIORITY_LOW_POWER = 2; // 0x2
    field public static final int CONNECTION_PRIORITY_LOW_POWER = 2; // 0x2
@@ -9190,11 +9192,14 @@ package android.bluetooth {
  public abstract class BluetoothGattCallback {
  public abstract class BluetoothGattCallback {
    ctor public BluetoothGattCallback();
    ctor public BluetoothGattCallback();
    method public void onCharacteristicChanged(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic);
    method @Deprecated public void onCharacteristicChanged(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic);
    method public void onCharacteristicRead(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic, int);
    method public void onCharacteristicChanged(@NonNull android.bluetooth.BluetoothGatt, @NonNull android.bluetooth.BluetoothGattCharacteristic, @NonNull byte[]);
    method @Deprecated public void onCharacteristicRead(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic, int);
    method public void onCharacteristicRead(@NonNull android.bluetooth.BluetoothGatt, @NonNull android.bluetooth.BluetoothGattCharacteristic, @NonNull byte[], int);
    method public void onCharacteristicWrite(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic, int);
    method public void onCharacteristicWrite(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic, int);
    method public void onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int);
    method public void onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int);
    method public void onDescriptorRead(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattDescriptor, int);
    method @Deprecated public void onDescriptorRead(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattDescriptor, int);
    method public void onDescriptorRead(@NonNull android.bluetooth.BluetoothGatt, @NonNull android.bluetooth.BluetoothGattDescriptor, int, @NonNull byte[]);
    method public void onDescriptorWrite(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattDescriptor, int);
    method public void onDescriptorWrite(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattDescriptor, int);
    method public void onMtuChanged(android.bluetooth.BluetoothGatt, int, int);
    method public void onMtuChanged(android.bluetooth.BluetoothGatt, int, int);
    method public void onPhyRead(android.bluetooth.BluetoothGatt, int, int, int);
    method public void onPhyRead(android.bluetooth.BluetoothGatt, int, int, int);
@@ -9211,20 +9216,20 @@ package android.bluetooth {
    method public int describeContents();
    method public int describeContents();
    method public android.bluetooth.BluetoothGattDescriptor getDescriptor(java.util.UUID);
    method public android.bluetooth.BluetoothGattDescriptor getDescriptor(java.util.UUID);
    method public java.util.List<android.bluetooth.BluetoothGattDescriptor> getDescriptors();
    method public java.util.List<android.bluetooth.BluetoothGattDescriptor> getDescriptors();
    method public Float getFloatValue(int, int);
    method @Deprecated public Float getFloatValue(int, int);
    method public int getInstanceId();
    method public int getInstanceId();
    method public Integer getIntValue(int, int);
    method @Deprecated public Integer getIntValue(int, int);
    method public int getPermissions();
    method public int getPermissions();
    method public int getProperties();
    method public int getProperties();
    method public android.bluetooth.BluetoothGattService getService();
    method public android.bluetooth.BluetoothGattService getService();
    method public String getStringValue(int);
    method @Deprecated public String getStringValue(int);
    method public java.util.UUID getUuid();
    method public java.util.UUID getUuid();
    method public byte[] getValue();
    method @Deprecated public byte[] getValue();
    method public int getWriteType();
    method public int getWriteType();
    method public boolean setValue(byte[]);
    method @Deprecated public boolean setValue(byte[]);
    method public boolean setValue(int, int, int);
    method @Deprecated public boolean setValue(int, int, int);
    method public boolean setValue(int, int, int, int);
    method @Deprecated public boolean setValue(int, int, int, int);
    method public boolean setValue(String);
    method @Deprecated public boolean setValue(String);
    method public void setWriteType(int);
    method public void setWriteType(int);
    method public void writeToParcel(android.os.Parcel, int);
    method public void writeToParcel(android.os.Parcel, int);
    field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothGattCharacteristic> CREATOR;
    field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothGattCharacteristic> CREATOR;
@@ -9264,8 +9269,8 @@ package android.bluetooth {
    method public android.bluetooth.BluetoothGattCharacteristic getCharacteristic();
    method public android.bluetooth.BluetoothGattCharacteristic getCharacteristic();
    method public int getPermissions();
    method public int getPermissions();
    method public java.util.UUID getUuid();
    method public java.util.UUID getUuid();
    method public byte[] getValue();
    method @Deprecated public byte[] getValue();
    method public boolean setValue(byte[]);
    method @Deprecated public boolean setValue(byte[]);
    method public void writeToParcel(android.os.Parcel, int);
    method public void writeToParcel(android.os.Parcel, int);
    field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothGattDescriptor> CREATOR;
    field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothGattDescriptor> CREATOR;
    field public static final byte[] DISABLE_NOTIFICATION_VALUE;
    field public static final byte[] DISABLE_NOTIFICATION_VALUE;
@@ -9553,8 +9558,12 @@ package android.bluetooth {
    field public static final int ERROR_BLUETOOTH_NOT_ALLOWED = 2; // 0x2
    field public static final int ERROR_BLUETOOTH_NOT_ALLOWED = 2; // 0x2
    field public static final int ERROR_BLUETOOTH_NOT_ENABLED = 1; // 0x1
    field public static final int ERROR_BLUETOOTH_NOT_ENABLED = 1; // 0x1
    field public static final int ERROR_DEVICE_NOT_BONDED = 3; // 0x3
    field public static final int ERROR_DEVICE_NOT_BONDED = 3; // 0x3
    field public static final int ERROR_FEATURE_NOT_SUPPORTED = 8; // 0x8
    field public static final int ERROR_FEATURE_NOT_SUPPORTED = 10; // 0xa
    field public static final int ERROR_GATT_WRITE_NOT_ALLOWED = 101; // 0x65
    field public static final int ERROR_GATT_WRITE_REQUEST_BUSY = 102; // 0x66
    field public static final int ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION = 6; // 0x6
    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 ERROR_UNKNOWN = 2147483647; // 0x7fffffff
    field public static final int SUCCESS = 0; // 0x0
    field public static final int SUCCESS = 0; // 0x0
  }
  }
+154 −65
Original line number Original line Diff line number Diff line
@@ -16,6 +16,8 @@


package android.bluetooth;
package android.bluetooth;


import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.RequiresNoPermission;
import android.annotation.RequiresNoPermission;
import android.annotation.RequiresPermission;
import android.annotation.RequiresPermission;
import android.annotation.SuppressLint;
import android.annotation.SuppressLint;
@@ -29,6 +31,8 @@ import android.os.ParcelUuid;
import android.os.RemoteException;
import android.os.RemoteException;
import android.util.Log;
import android.util.Log;


import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.ArrayList;
import java.util.List;
import java.util.List;
import java.util.UUID;
import java.util.UUID;
@@ -139,27 +143,6 @@ public final class BluetoothGatt implements BluetoothProfile {
    /** Connection parameter update - Request low power, reduced data rate connection parameters. */
    /** Connection parameter update - Request low power, reduced data rate connection parameters. */
    public static final int CONNECTION_PRIORITY_LOW_POWER = 2;
    public static final int CONNECTION_PRIORITY_LOW_POWER = 2;


    /**
     * A GATT writeCharacteristic request is started successfully.
     *
     * @hide
     */
    public static final int GATT_WRITE_REQUEST_SUCCESS = 0;

    /**
     * A GATT writeCharacteristic request failed to start.
     *
     * @hide
     */
    public static final int GATT_WRITE_REQUEST_FAIL = 1;

    /**
     * A GATT writeCharacteristic request is issued to a busy remote device.
     *
     * @hide
     */
    public static final int GATT_WRITE_REQUEST_BUSY = 2;

    /**
    /**
     * No authentication required.
     * No authentication required.
     *
     *
@@ -429,6 +412,9 @@ public final class BluetoothGatt implements BluetoothProfile {
                            final BluetoothGattCallback callback = mCallback;
                            final BluetoothGattCallback callback = mCallback;
                            if (callback != null) {
                            if (callback != null) {
                                if (status == 0) characteristic.setValue(value);
                                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,
                                callback.onCharacteristicRead(BluetoothGatt.this, characteristic,
                                        status);
                                        status);
                            }
                            }
@@ -443,7 +429,8 @@ public final class BluetoothGatt implements BluetoothProfile {
                 */
                 */
                @Override
                @Override
                @SuppressLint("AndroidFrameworkRequiresPermission")
                @SuppressLint("AndroidFrameworkRequiresPermission")
                public void onCharacteristicWrite(String address, int status, int handle) {
                public void onCharacteristicWrite(String address, int status, int handle,
                        byte[] value) {
                    if (VDBG) {
                    if (VDBG) {
                        Log.d(TAG, "onCharacteristicWrite() - Device=" + address
                        Log.d(TAG, "onCharacteristicWrite() - Device=" + address
                                + " handle=" + handle + " Status=" + status);
                                + " handle=" + handle + " Status=" + status);
@@ -467,12 +454,13 @@ public final class BluetoothGatt implements BluetoothProfile {
                        try {
                        try {
                            final int authReq = (mAuthRetryState == AUTH_RETRY_STATE_IDLE)
                            final int authReq = (mAuthRetryState == AUTH_RETRY_STATE_IDLE)
                                    ? AUTHENTICATION_NO_MITM : AUTHENTICATION_MITM;
                                    ? AUTHENTICATION_NO_MITM : AUTHENTICATION_MITM;
                            int requestStatus = GATT_WRITE_REQUEST_FAIL;
                            int requestStatus = BluetoothStatusCodes.ERROR_UNKNOWN;
                            for (int i = 0; i < WRITE_CHARACTERISTIC_MAX_RETRIES; i++) {
                            for (int i = 0; i < WRITE_CHARACTERISTIC_MAX_RETRIES; i++) {
                                requestStatus =  mService.writeCharacteristic(mClientIf, address, handle,
                                requestStatus =  mService.writeCharacteristic(mClientIf, address,
                                                  characteristic.getWriteType(), authReq,
                                                  handle, characteristic.getWriteType(), authReq,
                                                  characteristic.getValue(), mAttributionSource);
                                                  value, mAttributionSource);
                                if (requestStatus != GATT_WRITE_REQUEST_BUSY) {
                                if (requestStatus
                                        != BluetoothStatusCodes.ERROR_GATT_WRITE_REQUEST_BUSY) {
                                    break;
                                    break;
                                }
                                }
                                try {
                                try {
@@ -488,7 +476,6 @@ public final class BluetoothGatt implements BluetoothProfile {
                    }
                    }


                    mAuthRetryState = AUTH_RETRY_STATE_IDLE;
                    mAuthRetryState = AUTH_RETRY_STATE_IDLE;

                    runOrQueueCallback(new Runnable() {
                    runOrQueueCallback(new Runnable() {
                        @Override
                        @Override
                        public void run() {
                        public void run() {
@@ -524,6 +511,9 @@ public final class BluetoothGatt implements BluetoothProfile {
                            final BluetoothGattCallback callback = mCallback;
                            final BluetoothGattCallback callback = mCallback;
                            if (callback != null) {
                            if (callback != null) {
                                characteristic.setValue(value);
                                characteristic.setValue(value);
                                callback.onCharacteristicChanged(BluetoothGatt.this,
                                        characteristic, value);
                                // Keep calling deprecated callback to maintain app compatibility
                                callback.onCharacteristicChanged(BluetoothGatt.this,
                                callback.onCharacteristicChanged(BluetoothGatt.this,
                                        characteristic);
                                        characteristic);
                            }
                            }
@@ -578,6 +568,9 @@ public final class BluetoothGatt implements BluetoothProfile {
                            final BluetoothGattCallback callback = mCallback;
                            final BluetoothGattCallback callback = mCallback;
                            if (callback != null) {
                            if (callback != null) {
                                if (status == 0) descriptor.setValue(value);
                                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);
                                callback.onDescriptorRead(BluetoothGatt.this, descriptor, status);
                            }
                            }
                        }
                        }
@@ -590,7 +583,8 @@ public final class BluetoothGatt implements BluetoothProfile {
                 */
                 */
                @Override
                @Override
                @SuppressLint("AndroidFrameworkRequiresPermission")
                @SuppressLint("AndroidFrameworkRequiresPermission")
                public void onDescriptorWrite(String address, int status, int handle) {
                public void onDescriptorWrite(String address, int status, int handle,
                        byte[] value) {
                    if (VDBG) {
                    if (VDBG) {
                        Log.d(TAG,
                        Log.d(TAG,
                                "onDescriptorWrite() - Device=" + address + " handle=" + handle);
                                "onDescriptorWrite() - Device=" + address + " handle=" + handle);
@@ -614,7 +608,7 @@ public final class BluetoothGatt implements BluetoothProfile {
                            final int authReq = (mAuthRetryState == AUTH_RETRY_STATE_IDLE)
                            final int authReq = (mAuthRetryState == AUTH_RETRY_STATE_IDLE)
                                    ? AUTHENTICATION_NO_MITM : AUTHENTICATION_MITM;
                                    ? AUTHENTICATION_NO_MITM : AUTHENTICATION_MITM;
                            mService.writeDescriptor(mClientIf, address, handle,
                            mService.writeDescriptor(mClientIf, address, handle,
                                    authReq, descriptor.getValue(), mAttributionSource);
                                    authReq, value, mAttributionSource);
                            mAuthRetryState++;
                            mAuthRetryState++;
                            return;
                            return;
                        } catch (RemoteException e) {
                        } catch (RemoteException e) {
@@ -1194,8 +1188,8 @@ public final class BluetoothGatt implements BluetoothProfile {
     * Reads the requested characteristic from the associated remote device.
     * Reads the requested characteristic from the associated remote device.
     *
     *
     * <p>This is an asynchronous operation. The result of the read operation
     * <p>This is an asynchronous operation. The result of the read operation
     * is reported by the {@link BluetoothGattCallback#onCharacteristicRead}
     * is reported by the {@link BluetoothGattCallback#onCharacteristicRead(BluetoothGatt,
     * callback.
     * BluetoothGattCharacteristic, byte[], int)} callback.
     *
     *
     * @param characteristic Characteristic to read from the remote device
     * @param characteristic Characteristic to read from the remote device
     * @return true, if the read operation was initiated successfully
     * @return true, if the read operation was initiated successfully
@@ -1240,8 +1234,8 @@ public final class BluetoothGatt implements BluetoothProfile {
     * Reads the characteristic using its UUID from the associated remote device.
     * Reads the characteristic using its UUID from the associated remote device.
     *
     *
     * <p>This is an asynchronous operation. The result of the read operation
     * <p>This is an asynchronous operation. The result of the read operation
     * is reported by the {@link BluetoothGattCallback#onCharacteristicRead}
     * is reported by the {@link BluetoothGattCallback#onCharacteristicRead(BluetoothGatt,
     * callback.
     * BluetoothGattCharacteristic, byte[], int)} callback.
     *
     *
     * @param uuid UUID of characteristic to read from the remote device
     * @param uuid UUID of characteristic to read from the remote device
     * @return true, if the read operation was initiated successfully
     * @return true, if the read operation was initiated successfully
@@ -1284,40 +1278,94 @@ public final class BluetoothGatt implements BluetoothProfile {
     *
     *
     * @param characteristic Characteristic to write on the remote device
     * @param characteristic Characteristic to write on the remote device
     * @return true, if the write operation was initiated successfully
     * @return true, if the write operation was initiated successfully
     * @throws IllegalArgumentException if characteristic or its value are null
     *
     * @deprecated Use {@link BluetoothGatt#writeCharacteristic(BluetoothGattCharacteristic, byte[],
     * int)} as this is not memory safe.
     */
     */
    @Deprecated
    @RequiresLegacyBluetoothPermission
    @RequiresLegacyBluetoothPermission
    @RequiresBluetoothConnectPermission
    @RequiresBluetoothConnectPermission
    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
    public boolean writeCharacteristic(BluetoothGattCharacteristic characteristic) {
    public boolean writeCharacteristic(BluetoothGattCharacteristic characteristic) {
        if ((characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_WRITE) == 0
        try {
                && (characteristic.getProperties()
            return writeCharacteristic(characteristic, characteristic.getValue(),
                & BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE) == 0) {
                    characteristic.getWriteType()) == BluetoothStatusCodes.SUCCESS;
        } catch (Exception e) {
            return false;
            return false;
        }
        }
    }


    /** @hide */
    @Retention(RetentionPolicy.SOURCE)
    @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,
            BluetoothStatusCodes.ERROR_GATT_WRITE_REQUEST_BUSY,
            BluetoothStatusCodes.ERROR_UNKNOWN
    })
    public @interface WriteOperationReturnValues{}

    /**
     * Writes a given characteristic and its values to the associated remote device.
     *
     * <p>Once the write operation has been completed, the
     * {@link BluetoothGattCallback#onCharacteristicWrite} callback is invoked,
     * reporting the result of the operation.
     *
     * @param characteristic Characteristic to write on the remote device
     * @return whether the characteristic was successfully written to
     * @throws IllegalArgumentException if characteristic or value are null
     */
    @RequiresBluetoothConnectPermission
    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
    @WriteOperationReturnValues
    public int writeCharacteristic(@NonNull BluetoothGattCharacteristic characteristic,
            @NonNull byte[] value, int writeType) {
        if (characteristic == null) {
            throw new IllegalArgumentException("characteristic must not be null");
        }
        if (value == null) {
            throw new IllegalArgumentException("value must not be null");
        }
        if (VDBG) Log.d(TAG, "writeCharacteristic() - uuid: " + characteristic.getUuid());
        if (VDBG) Log.d(TAG, "writeCharacteristic() - uuid: " + characteristic.getUuid());
        if (mService == null || mClientIf == 0 || characteristic.getValue() == null) return false;
        if ((characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_WRITE) == 0
                && (characteristic.getProperties()
                & BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE) == 0) {
            return BluetoothStatusCodes.ERROR_GATT_WRITE_NOT_ALLOWED;
        }
        if (mService == null || mClientIf == 0) {
            return BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND;
        }


        BluetoothGattService service = characteristic.getService();
        BluetoothGattService service = characteristic.getService();
        if (service == null) return false;
        if (service == null) {
            throw new IllegalArgumentException("Characteristic must have a non-null service");
        }


        BluetoothDevice device = service.getDevice();
        BluetoothDevice device = service.getDevice();
        if (device == null) return false;
        if (device == null) {
            throw new IllegalArgumentException("Service must have a non-null device");
        }


        synchronized (mDeviceBusyLock) {
        synchronized (mDeviceBusyLock) {
            if (mDeviceBusy) {
            if (mDeviceBusy) {
                return false;
                return BluetoothStatusCodes.ERROR_GATT_WRITE_REQUEST_BUSY;
            }
            }
            mDeviceBusy = true;
            mDeviceBusy = true;
        }
        }


        int requestStatus = GATT_WRITE_REQUEST_FAIL;
        int requestStatus = BluetoothStatusCodes.ERROR_UNKNOWN;
        try {
        try {
            for (int i = 0; i < WRITE_CHARACTERISTIC_MAX_RETRIES; i++) {
            for (int i = 0; i < WRITE_CHARACTERISTIC_MAX_RETRIES; i++) {
                requestStatus = mService.writeCharacteristic(mClientIf, device.getAddress(),
                requestStatus = mService.writeCharacteristic(mClientIf, device.getAddress(),
                    characteristic.getInstanceId(), characteristic.getWriteType(),
                        characteristic.getInstanceId(), writeType, AUTHENTICATION_NONE, value,
                    AUTHENTICATION_NONE, characteristic.getValue(), mAttributionSource);
                        mAttributionSource);
                if (requestStatus != GATT_WRITE_REQUEST_BUSY) {
                if (requestStatus != BluetoothStatusCodes.ERROR_GATT_WRITE_REQUEST_BUSY) {
                    break;
                    break;
                }
                }
                try {
                try {
@@ -1330,10 +1378,10 @@ public final class BluetoothGatt implements BluetoothProfile {
            synchronized (mDeviceBusyLock) {
            synchronized (mDeviceBusyLock) {
                mDeviceBusy = false;
                mDeviceBusy = false;
            }
            }
            return false;
            throw e.rethrowFromSystemServer();
        }
        }


        return requestStatus == GATT_WRITE_REQUEST_SUCCESS;
        return requestStatus;
    }
    }


    /**
    /**
@@ -1384,45 +1432,86 @@ public final class BluetoothGatt implements BluetoothProfile {
    /**
    /**
     * Write the value of a given descriptor to the associated remote device.
     * Write the value of a given descriptor to the associated remote device.
     *
     *
     * <p>A {@link BluetoothGattCallback#onDescriptorWrite} callback is
     * <p>A {@link BluetoothGattCallback#onDescriptorWrite} callback is triggered to report the
     * triggered to report the result of the write operation.
     * result of the write operation.
     *
     *
     * @param descriptor Descriptor to write to the associated remote device
     * @param descriptor Descriptor to write to the associated remote device
     * @return true, if the write operation was initiated successfully
     * @return true, if the write operation was initiated successfully
     * @throws IllegalArgumentException if descriptor or its value are null
     *
     * @deprecated Use {@link BluetoothGatt#writeDescriptor(BluetoothGattDescriptor, byte[])} as
     * this is not memory safe.
     */
     */
    @Deprecated
    @RequiresLegacyBluetoothPermission
    @RequiresLegacyBluetoothPermission
    @RequiresBluetoothConnectPermission
    @RequiresBluetoothConnectPermission
    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
    public boolean writeDescriptor(BluetoothGattDescriptor descriptor) {
    public boolean writeDescriptor(BluetoothGattDescriptor descriptor) {
        try {
            return writeDescriptor(descriptor, descriptor.getValue())
                    == BluetoothStatusCodes.SUCCESS;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * Write the value of a given descriptor to the associated remote device.
     *
     * <p>A {@link BluetoothGattCallback#onDescriptorWrite} callback is triggered to report the
     * result of the write operation.
     *
     * @param descriptor Descriptor to write to the associated remote device
     * @return true, if the write operation was initiated successfully
     * @throws IllegalArgumentException if descriptor or value are null
     */
    @RequiresBluetoothConnectPermission
    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
    @WriteOperationReturnValues
    public int writeDescriptor(@NonNull BluetoothGattDescriptor descriptor,
            @NonNull byte[] value) {
        if (descriptor == null) {
            throw new IllegalArgumentException("descriptor must not be null");
        }
        if (value == null) {
            throw new IllegalArgumentException("value must not be null");
        }
        if (VDBG) Log.d(TAG, "writeDescriptor() - uuid: " + descriptor.getUuid());
        if (VDBG) Log.d(TAG, "writeDescriptor() - uuid: " + descriptor.getUuid());
        if (mService == null || mClientIf == 0 || descriptor.getValue() == null) return false;
        if (mService == null || mClientIf == 0) {
            return BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND;
        }


        BluetoothGattCharacteristic characteristic = descriptor.getCharacteristic();
        BluetoothGattCharacteristic characteristic = descriptor.getCharacteristic();
        if (characteristic == null) return false;
        if (characteristic == null) {
            throw new IllegalArgumentException("Descriptor must have a non-null characteristic");
        }


        BluetoothGattService service = characteristic.getService();
        BluetoothGattService service = characteristic.getService();
        if (service == null) return false;
        if (service == null) {
            throw new IllegalArgumentException("Characteristic must have a non-null service");
        }


        BluetoothDevice device = service.getDevice();
        BluetoothDevice device = service.getDevice();
        if (device == null) return false;
        if (device == null) {
            throw new IllegalArgumentException("Service must have a non-null device");
        }


        synchronized (mDeviceBusyLock) {
        synchronized (mDeviceBusyLock) {
            if (mDeviceBusy) return false;
            if (mDeviceBusy) return BluetoothStatusCodes.ERROR_GATT_WRITE_REQUEST_BUSY;
            mDeviceBusy = true;
            mDeviceBusy = true;
        }
        }


        try {
        try {
            mService.writeDescriptor(mClientIf, device.getAddress(), descriptor.getInstanceId(),
            return mService.writeDescriptor(mClientIf, device.getAddress(),
                    AUTHENTICATION_NONE, descriptor.getValue(), mAttributionSource);
                    descriptor.getInstanceId(), AUTHENTICATION_NONE, value, mAttributionSource);
        } catch (RemoteException e) {
        } catch (RemoteException e) {
            Log.e(TAG, "", e);
            Log.e(TAG, "", e);
            synchronized (mDeviceBusyLock) {
            synchronized (mDeviceBusyLock) {
                mDeviceBusy = false;
                mDeviceBusy = false;
            }
            }
            return false;
            e.rethrowFromSystemServer();
        }
        }

        return BluetoothStatusCodes.ERROR_UNKNOWN;
        return true;
    }
    }


    /**
    /**
@@ -1431,9 +1520,9 @@ public final class BluetoothGatt implements BluetoothProfile {
     * <p>Once a reliable write transaction has been initiated, all calls
     * <p>Once a reliable write transaction has been initiated, all calls
     * to {@link #writeCharacteristic} are sent to the remote device for
     * to {@link #writeCharacteristic} are sent to the remote device for
     * verification and queued up for atomic execution. The application will
     * verification and queued up for atomic execution. The application will
     * receive an {@link BluetoothGattCallback#onCharacteristicWrite} callback
     * receive a {@link BluetoothGattCallback#onCharacteristicWrite} callback in response to every
     * in response to every {@link #writeCharacteristic} call and is responsible
     * {@link #writeCharacteristic(BluetoothGattCharacteristic, byte[], int)} call and is
     * for verifying if the value has been transmitted accurately.
     * responsible for verifying if the value has been transmitted accurately.
     *
     *
     * <p>After all characteristics have been queued up and verified,
     * <p>After all characteristics have been queued up and verified,
     * {@link #executeReliableWrite} will execute all writes. If a characteristic
     * {@link #executeReliableWrite} will execute all writes. If a characteristic
@@ -1530,9 +1619,9 @@ public final class BluetoothGatt implements BluetoothProfile {
     * Enable or disable notifications/indications for a given characteristic.
     * Enable or disable notifications/indications for a given characteristic.
     *
     *
     * <p>Once notifications are enabled for a characteristic, a
     * <p>Once notifications are enabled for a characteristic, a
     * {@link BluetoothGattCallback#onCharacteristicChanged} callback will be
     * {@link BluetoothGattCallback#onCharacteristicChanged(BluetoothGatt,
     * triggered if the remote device indicates that the given characteristic
     * BluetoothGattCharacteristic, byte[])} callback will be triggered if the remote device
     * has changed.
     * indicates that the given characteristic has changed.
     *
     *
     * @param characteristic The characteristic for which to enable notifications
     * @param characteristic The characteristic for which to enable notifications
     * @param enable Set to true to enable notifications/indications
     * @param enable Set to true to enable notifications/indications
+70 −14

File changed.

Preview size limit exceeded, changes collapsed.

+33 −2

File changed.

Preview size limit exceeded, changes collapsed.

+7 −0
Original line number Original line Diff line number Diff line
@@ -260,7 +260,10 @@ public class BluetoothGattDescriptor implements Parcelable {
     * operation.
     * operation.
     *
     *
     * @return Cached value of the descriptor
     * @return Cached value of the descriptor
     *
     * @deprecated  Use {@link BluetoothGatt#readDescriptor(BluetoothGattDescriptor)} instead
     */
     */
    @Deprecated
    public byte[] getValue() {
    public byte[] getValue() {
        return mValue;
        return mValue;
    }
    }
@@ -276,7 +279,11 @@ public class BluetoothGattDescriptor implements Parcelable {
     * @param value New value for this descriptor
     * @param value New value for this descriptor
     * @return true if the locally stored value has been set, false if the requested value could not
     * @return true if the locally stored value has been set, false if the requested value could not
     * be stored locally.
     * be stored locally.
     *
     * @deprecated Pass the descriptor value directly into
     * {@link BluetoothGatt#writeDescriptor(BluetoothGattDescriptor, byte[])}
     */
     */
    @Deprecated
    public boolean setValue(byte[] value) {
    public boolean setValue(byte[] value) {
        mValue = value;
        mValue = value;
        return true;
        return true;
Loading