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

Commit f33e7ff0 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "Create memory safe overload of BluetoothGattServer#notifyCharacteristicChanged"

parents faf1b1cf cce0326e
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -9252,7 +9252,8 @@ package android.bluetooth {
    method public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(int[]);
    method public android.bluetooth.BluetoothGattService getService(java.util.UUID);
    method public java.util.List<android.bluetooth.BluetoothGattService> getServices();
    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean notifyCharacteristicChanged(android.bluetooth.BluetoothDevice, android.bluetooth.BluetoothGattCharacteristic, boolean);
    method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean notifyCharacteristicChanged(android.bluetooth.BluetoothDevice, android.bluetooth.BluetoothGattCharacteristic, boolean);
    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int notifyCharacteristicChanged(@NonNull android.bluetooth.BluetoothDevice, @NonNull android.bluetooth.BluetoothGattCharacteristic, boolean, @NonNull byte[]);
    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void readPhy(android.bluetooth.BluetoothDevice);
    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean removeService(android.bluetooth.BluetoothGattService);
    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean sendResponse(android.bluetooth.BluetoothDevice, int, int, int, byte[]);
+67 −11
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package android.bluetooth;

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

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
@@ -709,33 +713,85 @@ public final class BluetoothGattServer implements BluetoothProfile {
     * notification
     * @return true, if the notification has been triggered successfully
     * @throws IllegalArgumentException
     *
     * @deprecated Use {@link BluetoothGattServer#notifyCharacteristicChanged(BluetoothDevice,
     * BluetoothGattCharacteristic, boolean, byte[])}  as this is not memory safe.
     */
    @Deprecated
    @RequiresLegacyBluetoothPermission
    @RequiresBluetoothConnectPermission
    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
    public boolean notifyCharacteristicChanged(BluetoothDevice device,
            BluetoothGattCharacteristic characteristic, boolean confirm) {
        return notifyCharacteristicChanged(device, characteristic, confirm,
                characteristic.getValue()) == BluetoothStatusCodes.SUCCESS;
    }

    /** @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 NotifyCharacteristicReturnValues{}

    /**
     * Send a notification or indication that a local characteristic has been
     * updated.
     *
     * <p>A notification or indication is sent to the remote device to signal
     * that the characteristic has been updated. This function should be invoked
     * for every client that requests notifications/indications by writing
     * to the "Client Configuration" descriptor for the given characteristic.
     *
     * @param device the remote device to receive the notification/indication
     * @param characteristic the local characteristic that has been updated
     * @param confirm {@code true} to request confirmation from the client (indication) or
     * {@code false} to send a notification
     * @param value the characteristic value
     * @return whether the notification has been triggered successfully
     * @throws IllegalArgumentException if the characteristic value or service is null
     */
    @RequiresLegacyBluetoothPermission
    @RequiresBluetoothConnectPermission
    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
    @NotifyCharacteristicReturnValues
    public int notifyCharacteristicChanged(@NonNull BluetoothDevice device,
            @NonNull BluetoothGattCharacteristic characteristic, boolean confirm,
            @NonNull byte[] value) {
        if (VDBG) Log.d(TAG, "notifyCharacteristicChanged() - device: " + device.getAddress());
        if (mService == null || mServerIf == 0) return false;
        if (mService == null || mServerIf == 0) {
            return BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND;
        }

        if (characteristic == null) {
            throw new IllegalArgumentException("characteristic must not be null");
        }
        if (device == null) {
            throw new IllegalArgumentException("device must not be null");
        }
        BluetoothGattService service = characteristic.getService();
        if (service == null) return false;

        if (characteristic.getValue() == null) {
            throw new IllegalArgumentException("Chracteristic value is empty. Use "
                    + "BluetoothGattCharacteristic#setvalue to update");
        if (service == null) {
            throw new IllegalArgumentException("Characteristic must have a non-null service");
        }
        if (value == null) {
            throw new IllegalArgumentException("Characteristic value must not be null");
        }

        try {
            mService.sendNotification(mServerIf, device.getAddress(),
            return mService.sendNotification(mServerIf, device.getAddress(),
                    characteristic.getInstanceId(), confirm,
                    characteristic.getValue(), mAttributionSource);
                    value, mAttributionSource);
        } catch (RemoteException e) {
            Log.e(TAG, "", e);
            return false;
            throw e.rethrowFromSystemServer();
        }

        return true;
    }

    /**