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

Commit 57286189 authored by Rahul Sabnis's avatar Rahul Sabnis
Browse files

Service changes to deprecate and replace BluetoothGatt callbacks and

methods that were not memory safe

Tag: #feature
Bug: 195157393
Test: Manual
Merged-In: If111e3819a88a8c3e590812beb79e850e66f6071
Change-Id: If111e3819a88a8c3e590812beb79e850e66f6071
parent 2edf12eb
Loading
Loading
Loading
Loading
+26 −6
Original line number Diff line number Diff line
@@ -302,12 +302,22 @@ void btgattc_read_characteristic_cb(int conn_id, int status,
                               conn_id, status, p_data->handle, jb.get());
}

void btgattc_write_characteristic_cb(int conn_id, int status, uint16_t handle) {
void btgattc_write_characteristic_cb(int conn_id, int status, uint16_t handle,
                                     uint16_t len, const uint8_t* value) {
  CallbackEnv sCallbackEnv(__func__);
  if (!sCallbackEnv.valid()) return;

  ScopedLocalRef<jbyteArray> jb(sCallbackEnv.get(), NULL);
  if (status == 0) {  // Success
    jb.reset(sCallbackEnv->NewByteArray(len));
    sCallbackEnv->SetByteArrayRegion(jb.get(), 0, len, (jbyte*)value);
  } else {
    uint8_t value = 0;
    jb.reset(sCallbackEnv->NewByteArray(1));
    sCallbackEnv->SetByteArrayRegion(jb.get(), 0, 1, (jbyte*)&value);
  }
  sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onWriteCharacteristic,
                               conn_id, status, handle);
                               conn_id, status, handle, jb.get());
}

void btgattc_execute_write_cb(int conn_id, int status) {
@@ -336,12 +346,22 @@ void btgattc_read_descriptor_cb(int conn_id, int status,
                               status, p_data.handle, jb.get());
}

void btgattc_write_descriptor_cb(int conn_id, int status, uint16_t handle) {
void btgattc_write_descriptor_cb(int conn_id, int status, uint16_t handle,
                                 uint16_t len, const uint8_t* value) {
  CallbackEnv sCallbackEnv(__func__);
  if (!sCallbackEnv.valid()) return;

  ScopedLocalRef<jbyteArray> jb(sCallbackEnv.get(), NULL);
  if (status == 0) {  // Success
    jb.reset(sCallbackEnv->NewByteArray(len));
    sCallbackEnv->SetByteArrayRegion(jb.get(), 0, len, (jbyte*)value);
  } else {
    uint8_t value = 0;
    jb.reset(sCallbackEnv->NewByteArray(1));
    sCallbackEnv->SetByteArrayRegion(jb.get(), 0, 1, (jbyte*)&value);
  }
  sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onWriteDescriptor, conn_id,
                               status, handle);
                               status, handle, jb.get());
}

void btgattc_remote_rssi_cb(int client_if, const RawAddress& bda, int rssi,
@@ -983,7 +1003,7 @@ static void classInitNative(JNIEnv* env, jclass clazz) {
  method_onReadCharacteristic =
      env->GetMethodID(clazz, "onReadCharacteristic", "(III[B)V");
  method_onWriteCharacteristic =
      env->GetMethodID(clazz, "onWriteCharacteristic", "(III)V");
      env->GetMethodID(clazz, "onWriteCharacteristic", "(III[B)V");
  method_onExecuteCompleted =
      env->GetMethodID(clazz, "onExecuteCompleted", "(II)V");
  method_onSearchCompleted =
@@ -991,7 +1011,7 @@ static void classInitNative(JNIEnv* env, jclass clazz) {
  method_onReadDescriptor =
      env->GetMethodID(clazz, "onReadDescriptor", "(III[B)V");
  method_onWriteDescriptor =
      env->GetMethodID(clazz, "onWriteDescriptor", "(III)V");
      env->GetMethodID(clazz, "onWriteDescriptor", "(III[B)V");
  method_onNotify =
      env->GetMethodID(clazz, "onNotify", "(ILjava/lang/String;IZ[B)V");
  method_onRegisterForNotifications =
+27 −5
Original line number Diff line number Diff line
@@ -26,16 +26,38 @@ class CallbackInfo {
    public String address;
    public int status;
    public int handle;
    public byte[] value;

    CallbackInfo(String address, int status, int handle) {
        this.address = address;
        this.status = status;
        this.handle = handle;
    static class Builder {
        private String mAddress;
        private int mStatus;
        private int mHandle;
        private byte[] mValue;

        Builder(String address, int status) {
            mAddress = address;
            mStatus = status;
        }

        Builder setHandle(int handle) {
            mHandle = handle;
            return this;
        }

    CallbackInfo(String address, int status) {
        Builder setValue(byte[] value) {
            mValue = value;
            return this;
        }

        CallbackInfo build() {
            return new CallbackInfo(mAddress, mStatus, mHandle, mValue);
        }
    }

    private CallbackInfo(String address, int status, int handle, byte[] value) {
        this.address = address;
        this.status = status;
        this.handle = handle;
    }
}
+34 −24
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothStatusCodes;
import android.bluetooth.IBluetoothGatt;
import android.bluetooth.IBluetoothGattCallback;
import android.bluetooth.IBluetoothGattServerCallback;
@@ -734,7 +735,7 @@ public class GattService extends ProfileService {
                int authReq, byte[] value, AttributionSource attributionSource) {
            GattService service = getService();
            if (service == null) {
                return BluetoothGatt.GATT_WRITE_REQUEST_FAIL;
                return BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND;
            }
            return service.writeCharacteristic(clientIf, address, handle, writeType, authReq, value,
                    attributionSource);
@@ -751,13 +752,14 @@ public class GattService extends ProfileService {
        }

        @Override
        public void writeDescriptor(int clientIf, String address, int handle, int authReq,
        public int writeDescriptor(int clientIf, String address, int handle, int authReq,
                byte[] value, AttributionSource attributionSource) {
            GattService service = getService();
            if (service == null) {
                return;
                return BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND;
            }
            service.writeDescriptor(clientIf, address, handle, authReq, value, attributionSource);
            return service.writeDescriptor(clientIf, address, handle, authReq, value,
                    attributionSource);
        }

        @Override
@@ -1694,7 +1696,8 @@ public class GattService extends ProfileService {
        }
    }

    void onWriteCharacteristic(int connId, int status, int handle) throws RemoteException {
    void onWriteCharacteristic(int connId, int status, int handle, byte[] data)
            throws RemoteException {
        String address = mClientMap.addressByConnId(connId);
        synchronized (mPermits) {
            Log.d(TAG, "onWriteCharacteristic() - increasing permit for address="
@@ -1703,7 +1706,8 @@ public class GattService extends ProfileService {
        }

        if (VDBG) {
            Log.d(TAG, "onWriteCharacteristic() - address=" + address + ", status=" + status);
            Log.d(TAG, "onWriteCharacteristic() - address=" + address + ", status=" + status
                    + ", length=" + data.length);
        }

        ClientMap.App app = mClientMap.getByConnId(connId);
@@ -1712,12 +1716,15 @@ public class GattService extends ProfileService {
        }

        if (!app.isCongested) {
            app.callback.onCharacteristicWrite(address, status, handle);
            app.callback.onCharacteristicWrite(address, status, handle, data);
        } else {
            if (status == BluetoothGatt.GATT_CONNECTION_CONGESTED) {
                status = BluetoothGatt.GATT_SUCCESS;
            }
            CallbackInfo callbackInfo = new CallbackInfo(address, status, handle);
            CallbackInfo callbackInfo = new CallbackInfo.Builder(address, status)
                    .setHandle(handle)
                    .setValue(data)
                    .build();
            app.queueCallback(callbackInfo);
        }
    }
@@ -1749,16 +1756,18 @@ public class GattService extends ProfileService {
        }
    }

    void onWriteDescriptor(int connId, int status, int handle) throws RemoteException {
    void onWriteDescriptor(int connId, int status, int handle, byte[] data)
            throws RemoteException {
        String address = mClientMap.addressByConnId(connId);

        if (VDBG) {
            Log.d(TAG, "onWriteDescriptor() - address=" + address + ", status=" + status);
            Log.d(TAG, "onWriteDescriptor() - address=" + address + ", status=" + status
                    + ", length=" + data.length);
        }

        ClientMap.App app = mClientMap.getByConnId(connId);
        if (app != null) {
            app.callback.onDescriptorWrite(address, status, handle);
            app.callback.onDescriptorWrite(address, status, handle, data);
        }
    }

@@ -2181,7 +2190,7 @@ public class GattService extends ProfileService {
                    return;
                }
                app.callback.onCharacteristicWrite(callbackInfo.address, callbackInfo.status,
                        callbackInfo.handle);
                        callbackInfo.handle, callbackInfo.value);
            }
        }
    }
@@ -2915,7 +2924,7 @@ public class GattService extends ProfileService {
            byte[] value, AttributionSource attributionSource) {
        if (!Utils.checkConnectPermissionForDataDelivery(
                this, attributionSource, "GattService writeCharacteristic")) {
            return BluetoothGatt.GATT_WRITE_REQUEST_FAIL;
            return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION;
        }

        if (VDBG) {
@@ -2929,12 +2938,12 @@ public class GattService extends ProfileService {
        Integer connId = mClientMap.connIdByAddress(clientIf, address);
        if (connId == null) {
            Log.e(TAG, "writeCharacteristic() - No connection for " + address + "...");
            return BluetoothGatt.GATT_WRITE_REQUEST_FAIL;
            return BluetoothStatusCodes.ERROR_DEVICE_NOT_CONNECTED;
        }

        if (!permissionCheck(connId, handle)) {
            Log.w(TAG, "writeCharacteristic() - permission check failed!");
            return BluetoothGatt.GATT_WRITE_REQUEST_FAIL;
            return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_PRIVILEGED_PERMISSION;
        }

        Log.d(TAG, "writeCharacteristic() - trying to acquire permit.");
@@ -2943,19 +2952,19 @@ public class GattService extends ProfileService {
            AtomicBoolean atomicBoolean = mPermits.get(address);
            if (atomicBoolean == null) {
                Log.d(TAG, "writeCharacteristic() -  atomicBoolean uninitialized!");
                return BluetoothGatt.GATT_WRITE_REQUEST_FAIL;
                return BluetoothStatusCodes.ERROR_DEVICE_NOT_CONNECTED;
            }

            boolean success = atomicBoolean.get();
            if (!success) {
                Log.d(TAG, "writeCharacteristic() - no permit available.");
                 return BluetoothGatt.GATT_WRITE_REQUEST_BUSY;
                return BluetoothStatusCodes.ERROR_GATT_WRITE_REQUEST_BUSY;
            }
            atomicBoolean.set(false);
        }

        gattClientWriteCharacteristicNative(connId, handle, writeType, authReq, value);
        return BluetoothGatt.GATT_WRITE_REQUEST_SUCCESS;
        return BluetoothStatusCodes.SUCCESS;
    }

    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
@@ -2985,11 +2994,11 @@ public class GattService extends ProfileService {
    }

    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
    void writeDescriptor(int clientIf, String address, int handle, int authReq, byte[] value,
    int writeDescriptor(int clientIf, String address, int handle, int authReq, byte[] value,
            AttributionSource attributionSource) {
        if (!Utils.checkConnectPermissionForDataDelivery(
                this, attributionSource, "GattService writeDescriptor")) {
            return;
            return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION;
        }
        if (VDBG) {
            Log.d(TAG, "writeDescriptor() - address=" + address);
@@ -2998,15 +3007,16 @@ public class GattService extends ProfileService {
        Integer connId = mClientMap.connIdByAddress(clientIf, address);
        if (connId == null) {
            Log.e(TAG, "writeDescriptor() - No connection for " + address + "...");
            return;
            return BluetoothStatusCodes.ERROR_DEVICE_NOT_CONNECTED;
        }

        if (!permissionCheck(connId, handle)) {
            Log.w(TAG, "writeDescriptor() - permission check failed!");
            return;
            return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_PRIVILEGED_PERMISSION;
        }

        gattClientWriteDescriptorNative(connId, handle, authReq, value);
        return BluetoothStatusCodes.SUCCESS;
    }

    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
@@ -3410,7 +3420,7 @@ public class GattService extends ProfileService {
            if (status == BluetoothGatt.GATT_CONNECTION_CONGESTED) {
                status = BluetoothGatt.GATT_SUCCESS;
            }
            app.queueCallback(new CallbackInfo(address, status));
            app.queueCallback(new CallbackInfo.Builder(address, status).build());
        }
    }