summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJuha Vuolle <juha.vuolle@qt.io>2023-01-13 12:08:05 +0200
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2023-02-04 13:48:53 +0000
commit8363df31ff4712f97874e9c0ea2a0aeacda47ca2 (patch)
tree6cc050b0436487c00caa730034a4db4f0d2f72bd
parent163ce3e87f1566ec820637724dfbbc12d8f90096 (diff)
downloadqtconnectivity-8363df31ff4712f97874e9c0ea2a0aeacda47ca2.tar.gz
Replace deprecated BT LE methods on Android API 33: descriptors
The overarching theme for these API deprecations is to improve memory safety. This patch replaces the descriptor related APIs. Fixes: QTBUG-107180 Change-Id: Ief098d67d2601e06a2f29fa38d9b481bbda605f9 Reviewed-by: Ivan Solovev <ivan.solovev@qt.io> (cherry picked from commit 8ae30c552ce7ae1e0ee4c6a472666a1e8ee2790a) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r--src/android/bluetooth/CMakeLists.txt1
-rw-r--r--src/android/bluetooth/src/org/qtproject/qt/android/bluetooth/QtBluetoothGattDescriptor.java39
-rw-r--r--src/android/bluetooth/src/org/qtproject/qt/android/bluetooth/QtBluetoothLE.java33
-rw-r--r--src/android/bluetooth/src/org/qtproject/qt/android/bluetooth/QtBluetoothLEServer.java14
-rw-r--r--src/bluetooth/android/jni_android_p.h2
-rw-r--r--src/bluetooth/qlowenergycontroller_android.cpp4
6 files changed, 77 insertions, 16 deletions
diff --git a/src/android/bluetooth/CMakeLists.txt b/src/android/bluetooth/CMakeLists.txt
index 7dd0c257..f8692576 100644
--- a/src/android/bluetooth/CMakeLists.txt
+++ b/src/android/bluetooth/CMakeLists.txt
@@ -8,6 +8,7 @@ set(java_sources
src/org/qtproject/qt/android/bluetooth/QtBluetoothLEServer.java
src/org/qtproject/qt/android/bluetooth/QtBluetoothSocketServer.java
src/org/qtproject/qt/android/bluetooth/QtBluetoothGattCharacteristic.java
+ src/org/qtproject/qt/android/bluetooth/QtBluetoothGattDescriptor.java
)
qt_internal_add_jar(Qt${QtConnectivity_VERSION_MAJOR}AndroidBluetooth
diff --git a/src/android/bluetooth/src/org/qtproject/qt/android/bluetooth/QtBluetoothGattDescriptor.java b/src/android/bluetooth/src/org/qtproject/qt/android/bluetooth/QtBluetoothGattDescriptor.java
new file mode 100644
index 00000000..10194ea4
--- /dev/null
+++ b/src/android/bluetooth/src/org/qtproject/qt/android/bluetooth/QtBluetoothGattDescriptor.java
@@ -0,0 +1,39 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+package org.qtproject.qt.android.bluetooth;
+
+import android.bluetooth.BluetoothGattDescriptor;
+import android.os.Build;
+
+import java.util.UUID;
+
+public class QtBluetoothGattDescriptor extends BluetoothGattDescriptor {
+ public QtBluetoothGattDescriptor(UUID uuid, int permissions) {
+ super(uuid, permissions);
+ }
+ // Starting from API 33 Android Bluetooth deprecates descriptor local value caching by
+ // deprecating the getValue() and setValue() accessors. For peripheral role we store the value
+ // locally in the descriptor as a convenience - looking up the value on the C++ side would
+ // be somewhat complicated. This should be safe as all accesses to this class are synchronized.
+ // For clarity: For API levels below 33 we still need to use the setValue() of the base class
+ // because Android internally uses getValue() with APIs below 33.
+ public boolean setLocalValue(byte[] value) {
+ if (Build.VERSION.SDK_INT >= 33) {
+ m_localValue = value;
+ return true;
+ } else {
+ return setValue(value);
+ }
+ }
+
+ public byte[] getLocalValue()
+ {
+ if (Build.VERSION.SDK_INT >= 33)
+ return m_localValue;
+ else
+ return getValue();
+ }
+
+ private byte[] m_localValue = null;
+}
diff --git a/src/android/bluetooth/src/org/qtproject/qt/android/bluetooth/QtBluetoothLE.java b/src/android/bluetooth/src/org/qtproject/qt/android/bluetooth/QtBluetoothLE.java
index 57accf3b..08527385 100644
--- a/src/android/bluetooth/src/org/qtproject/qt/android/bluetooth/QtBluetoothLE.java
+++ b/src/android/bluetooth/src/org/qtproject/qt/android/bluetooth/QtBluetoothLE.java
@@ -470,7 +470,7 @@ public class QtBluetoothLE {
private synchronized void handleOnDescriptorRead(android.bluetooth.BluetoothGatt gatt,
android.bluetooth.BluetoothGattDescriptor descriptor,
- int status)
+ int status, byte[] newValue)
{
int foundHandle = handleForDescriptor(descriptor);
if (foundHandle == -1 || foundHandle >= entries.size() ) {
@@ -504,7 +504,7 @@ public class QtBluetoothLE {
leDescriptorRead(qtObject,
descriptor.getCharacteristic().getService().getUuid().toString(),
descriptor.getCharacteristic().getUuid().toString(), foundHandle + 1,
- descriptor.getUuid().toString(), descriptor.getValue());
+ descriptor.getUuid().toString(), newValue);
} else {
if (isServiceDiscoveryRun) {
// Cannot read but still advertise the fact that we found a descriptor
@@ -516,7 +516,7 @@ public class QtBluetoothLE {
leDescriptorRead(qtObject,
descriptor.getCharacteristic().getService().getUuid().toString(),
descriptor.getCharacteristic().getUuid().toString(), foundHandle + 1,
- descriptor.getUuid().toString(), descriptor.getValue());
+ descriptor.getUuid().toString(), newValue);
} else {
// This must be in sync with QLowEnergyService::DescriptorReadError
final int descriptorReadError = 6;
@@ -539,7 +539,7 @@ public class QtBluetoothLE {
* up here.
*/
if (descriptor.getUuid().compareTo(clientCharacteristicUuid) == 0) {
- byte[] bytearray = descriptor.getValue();
+ byte[] bytearray = newValue;
final int value = (bytearray != null && bytearray.length > 0) ? bytearray[0] : 0;
// notification or indication bit set?
if ((value & 0x03) > 0) {
@@ -585,9 +585,10 @@ public class QtBluetoothLE {
errorCode = 3; break; // DescriptorWriteError
}
+ byte[] value = pendingJob.newValue;
pendingJob = null;
- leDescriptorWritten(qtObject, handle+1, descriptor.getValue(), errorCode);
+ leDescriptorWritten(qtObject, handle+1, value, errorCode);
performNextIO();
}
@@ -700,12 +701,24 @@ public class QtBluetoothLE {
handleOnCharacteristicChanged(gatt, characteristic, value);
}
+ // API < 33
public void onDescriptorRead(android.bluetooth.BluetoothGatt gatt,
android.bluetooth.BluetoothGattDescriptor descriptor,
int status)
{
super.onDescriptorRead(gatt, descriptor, status);
- handleOnDescriptorRead(gatt, descriptor, status);
+ handleOnDescriptorRead(gatt, descriptor, status, descriptor.getValue());
+ }
+
+ // API >= 33
+ public void onDescriptorRead(android.bluetooth.BluetoothGatt gatt,
+ android.bluetooth.BluetoothGattDescriptor descriptor,
+ int status,
+ byte[] value)
+ {
+ // Note: here we don't call the super implementation as it calls the old "< API 33"
+ // callback, and the callback would be handled twice
+ handleOnDescriptorRead(gatt, descriptor, status, value);
}
public void onDescriptorWrite(android.bluetooth.BluetoothGatt gatt,
@@ -1565,7 +1578,7 @@ public class QtBluetoothLE {
entry.descriptor.getCharacteristic().getService().getUuid().toString(),
entry.descriptor.getCharacteristic().getUuid().toString(),
handle + 1, entry.descriptor.getUuid().toString(),
- entry.descriptor.getValue());
+ null);
break;
case CharacteristicValue:
// for more details see scheduleServiceDetailDiscovery(int, boolean)
@@ -1676,9 +1689,15 @@ public class QtBluetoothLE {
Log.d(TAG, "Enable notifications: " + enableNotifications);
}
+ if (Build.VERSION.SDK_INT >= 33) {
+ int writeResult = mBluetoothGatt.writeDescriptor(
+ nextJob.entry.descriptor, nextJob.newValue);
+ return (writeResult != BluetoothStatusCodes.SUCCESS);
+ }
result = nextJob.entry.descriptor.setValue(nextJob.newValue);
if (!result || !mBluetoothGatt.writeDescriptor(nextJob.entry.descriptor))
return true;
+
break;
case Service:
case CharacteristicValue:
diff --git a/src/android/bluetooth/src/org/qtproject/qt/android/bluetooth/QtBluetoothLEServer.java b/src/android/bluetooth/src/org/qtproject/qt/android/bluetooth/QtBluetoothLEServer.java
index 6d4a1fa7..94601403 100644
--- a/src/android/bluetooth/src/org/qtproject/qt/android/bluetooth/QtBluetoothLEServer.java
+++ b/src/android/bluetooth/src/org/qtproject/qt/android/bluetooth/QtBluetoothLEServer.java
@@ -468,13 +468,14 @@ public class QtBluetoothLEServer {
return;
}
- byte[] dataArray = descriptor.getValue();
+ byte[] dataArray = ((QtBluetoothGattDescriptor)descriptor).getLocalValue();
+
try {
if (descriptor.getUuid().equals(CLIENT_CHARACTERISTIC_CONFIGURATION_UUID)) {
dataArray = clientCharacteristicManager.valueFor(
descriptor.getCharacteristic(), device);
if (dataArray == null)
- dataArray = descriptor.getValue();
+ dataArray = ((QtBluetoothGattDescriptor)descriptor).getLocalValue();
}
dataArray = Arrays.copyOfRange(dataArray, offset, dataArray.length);
@@ -521,8 +522,7 @@ public class QtBluetoothLEServer {
descriptor.getCharacteristic(),
device, value);
}
-
- descriptor.setValue(value);
+ ((QtBluetoothGattDescriptor)descriptor).setLocalValue(value);
leServerDescriptorWritten(qtObject, descriptor, value);
} else {
// This should not really happen as per Bluetooth spec
@@ -564,7 +564,7 @@ public class QtBluetoothLEServer {
// The target can be a descriptor or a characteristic
byte[] currentValue = (entry.target instanceof BluetoothGattCharacteristic)
? ((QtBluetoothGattCharacteristic)entry.target).getLocalValue()
- : ((BluetoothGattDescriptor)entry.target).getValue();
+ : ((QtBluetoothGattDescriptor)entry.target).getLocalValue();
// Iterate writes and apply them to the currentValue in received order
for (Pair<byte[], Integer> write : entry.writes) {
@@ -615,7 +615,7 @@ public class QtBluetoothLEServer {
leServerCharacteristicChanged(
qtObject, (BluetoothGattCharacteristic)entry.target, newValue);
} else {
- ((BluetoothGattDescriptor)entry.target).setValue(newValue);
+ ((QtBluetoothGattDescriptor)entry.target).setLocalValue(newValue);
leServerDescriptorWritten(
qtObject, (BluetoothGattDescriptor)entry.target, newValue);
}
@@ -930,7 +930,7 @@ public class QtBluetoothLEServer {
// to interpret the server's call as a change of the default value.
synchronized (this) // a value update might be in progress
{
- foundDesc.setValue(newValue);
+ ((QtBluetoothGattDescriptor)foundDesc).setLocalValue(newValue);
}
return true;
diff --git a/src/bluetooth/android/jni_android_p.h b/src/bluetooth/android/jni_android_p.h
index c51b14e7..bb3fd341 100644
--- a/src/bluetooth/android/jni_android_p.h
+++ b/src/bluetooth/android/jni_android_p.h
@@ -27,6 +27,8 @@ Q_DECLARE_JNI_CLASS(QtBtBroadcastReceiver,
"org/qtproject/qt/android/bluetooth/QtBluetoothBroadcastReceiver");
Q_DECLARE_JNI_CLASS(QtBtGattCharacteristic,
"org/qtproject/qt/android/bluetooth/QtBluetoothGattCharacteristic");
+Q_DECLARE_JNI_CLASS(QtBtGattDescriptor,
+ "org/qtproject/qt/android/bluetooth/QtBluetoothGattDescriptor");
Q_DECLARE_JNI_CLASS(QtBtInputStreamThread,
"org/qtproject/qt/android/bluetooth/QtBluetoothInputStreamThread")
Q_DECLARE_JNI_CLASS(QtBtSocketServer, "org/qtproject/qt/android/bluetooth/QtBluetoothSocketServer")
diff --git a/src/bluetooth/qlowenergycontroller_android.cpp b/src/bluetooth/qlowenergycontroller_android.cpp
index 0350b163..d01833e8 100644
--- a/src/bluetooth/qlowenergycontroller_android.cpp
+++ b/src/bluetooth/qlowenergycontroller_android.cpp
@@ -1227,13 +1227,13 @@ void QLowEnergyControllerPrivateAndroid::addToGenericAttributeList(const QLowEne
const QList<QLowEnergyDescriptorData> descriptorList = charData.descriptors();
for (const auto &descData: descriptorList) {
- QJniObject javaDesc = QJniObject::construct<QtJniTypes::BluetoothGattDescriptor>(
+ QJniObject javaDesc = QJniObject::construct<QtJniTypes::QtBtGattDescriptor>(
javaUuidfromQtUuid(descData.uuid()).object<QtJniTypes::UUID>(),
setupDescPermissions(descData));
jb = env->NewByteArray(descData.value().size());
env->SetByteArrayRegion(jb, 0, descData.value().size(), (jbyte*)descData.value().data());
- success = javaDesc.callMethod<jboolean>("setValue", jb);
+ success = javaDesc.callMethod<jboolean>("setLocalValue", jb);
if (!success) {
qCWarning(QT_BT_ANDROID) << "Cannot setup initial descriptor value for "
<< descData.uuid() << "(char" << charData.uuid()