Merge "Fix compatible errors in SDK 21" into androidx-main
diff --git a/bluetooth/bluetooth-core/src/androidTest/java/androidx/bluetooth/core/BluetoothAdapterTest.kt b/bluetooth/bluetooth-core/src/androidTest/java/androidx/bluetooth/core/BluetoothAdapterTest.kt
index 4e138e1..492753f 100644
--- a/bluetooth/bluetooth-core/src/androidTest/java/androidx/bluetooth/core/BluetoothAdapterTest.kt
+++ b/bluetooth/bluetooth-core/src/androidTest/java/androidx/bluetooth/core/BluetoothAdapterTest.kt
@@ -112,6 +112,8 @@
val fwkBluetoothAdapter =
BluetoothManager(ApplicationProvider.getApplicationContext()).getAdapter()
val bluetoothAdapter = BluetoothAdapter(fwkBluetoothAdapter)
+ assertTrue("Bluetooth is not enabled", bluetoothAdapter.isEnabled)
+
// Check correct name
val testName = "Bluetooth:Test-name_?~"
val originalName = bluetoothAdapter.name
@@ -127,12 +129,9 @@
private fun waitForAdapterNameChange(): Boolean {
try {
- Log.e("BluetoothAdapterTest", "trying")
adapterNameChangedlock.lock()
// Wait for the Adapter name to be changed
- Log.e("BluetoothAdapterTest", "waiting")
conditionAdapterNameChanged.await(5000, TimeUnit.MILLISECONDS)
- Log.e("BluetoothAdapterTest", "finish waiting")
} catch (e: InterruptedException) {
Log.e("BluetoothAdapterTest", "waitForAdapterNameChange: interrrupted")
} finally {
diff --git a/bluetooth/bluetooth-core/src/main/java/androidx/bluetooth/core/BluetoothGattCharacteristic.kt b/bluetooth/bluetooth-core/src/main/java/androidx/bluetooth/core/BluetoothGattCharacteristic.kt
index bd6c937..0422d55 100644
--- a/bluetooth/bluetooth-core/src/main/java/androidx/bluetooth/core/BluetoothGattCharacteristic.kt
+++ b/bluetooth/bluetooth-core/src/main/java/androidx/bluetooth/core/BluetoothGattCharacteristic.kt
@@ -16,9 +16,10 @@
package androidx.bluetooth.core
-import android.bluetooth.BluetoothGattCharacteristic as FwkBluetoothGattCharacteristic
import android.os.Build
import android.os.Bundle
+import android.bluetooth.BluetoothGattCharacteristic as FwkBluetoothGattCharacteristic
+import android.annotation.SuppressLint
import androidx.annotation.RequiresApi
import java.util.UUID
@@ -298,6 +299,7 @@
val CREATOR: Bundleable.Creator<BluetoothGattCharacteristic> =
object : Bundleable.Creator<BluetoothGattCharacteristic> {
+ @SuppressLint("SoonBlockedPrivateApi")
override fun fromBundle(bundle: Bundle): BluetoothGattCharacteristic {
val uuid = bundle.getString(keyForField(FIELD_FWK_CHARACTERISTIC_UUID))
?: throw IllegalArgumentException("Bundle doesn't include uuid")
@@ -324,25 +326,24 @@
throw IllegalArgumentException("Bundle doesn't include keySize")
}
- val fwkCharacteristic =
- FwkBluetoothGattCharacteristic::class.java.getConstructor(
- UUID::class.java,
- Integer.TYPE,
- Integer.TYPE,
- Integer.TYPE,
- ).newInstance(
- UUID.fromString(uuid),
- instanceId,
- properties,
- permissions,
- )
- fwkCharacteristic.writeType = writeType
+ val fwkCharacteristicWithoutPrivateField = FwkBluetoothGattCharacteristic(
+ UUID.fromString(uuid),
+ properties,
+ permissions,
+ )
- // Asserted, will always be true
- if (Build.VERSION.SDK_INT < 24) {
- fwkCharacteristic.javaClass.getDeclaredField("mKeySize")
- .setInt(fwkCharacteristic, keySize)
- }
+ val fwkCharacteristic = fwkCharacteristicWithoutPrivateField.runCatching {
+ this.writeType = writeType
+ this.javaClass.getDeclaredField("mKeySize").let {
+ it.isAccessible = true
+ it.setInt(this, keySize)
+ }
+ this.javaClass.getDeclaredField("mInstanceId").let {
+ it.isAccessible = true
+ it.setInt(this, instanceId)
+ }
+ this
+ }.getOrDefault(fwkCharacteristicWithoutPrivateField)
val gattCharacteristic = BluetoothGattCharacteristic(fwkCharacteristic)
@@ -417,10 +418,14 @@
if (Build.VERSION.SDK_INT < 24) {
bundle.putInt(
keyForField(FIELD_FWK_CHARACTERISTIC_KEY_SIZE),
- fwkCharacteristic.javaClass.getDeclaredField("mKeySize")
- .getInt(fwkCharacteristic)
+ fwkCharacteristic.javaClass.getDeclaredField("mKeySize").runCatching {
+ this.isAccessible = true
+ this.getInt(fwkCharacteristic)
+ }.getOrDefault(16) // 16 is the default value in framework
+
)
}
+
val descriptorBundles = ArrayList(descriptors.map { it.toBundle() })
bundle.putParcelableArrayList(
keyForField(FIELD_FWK_CHARACTERISTIC_DESCRIPTORS),
diff --git a/bluetooth/bluetooth-core/src/main/java/androidx/bluetooth/core/BluetoothGattDescriptor.kt b/bluetooth/bluetooth-core/src/main/java/androidx/bluetooth/core/BluetoothGattDescriptor.kt
index 612cdb0..c7800a7 100644
--- a/bluetooth/bluetooth-core/src/main/java/androidx/bluetooth/core/BluetoothGattDescriptor.kt
+++ b/bluetooth/bluetooth-core/src/main/java/androidx/bluetooth/core/BluetoothGattDescriptor.kt
@@ -16,9 +16,9 @@
package androidx.bluetooth.core
-import android.bluetooth.BluetoothGattDescriptor as FwkBluetoothGattDescriptor
import android.os.Build
import android.os.Bundle
+import android.bluetooth.BluetoothGattDescriptor as FwkBluetoothGattDescriptor
import androidx.annotation.RequiresApi
import java.util.UUID
@@ -168,15 +168,16 @@
throw IllegalArgumentException("Bundle doesn't include permission")
}
- val descriptor = FwkBluetoothGattDescriptor::class.java.getConstructor(
- UUID::class.java,
- Integer.TYPE,
- Integer.TYPE
- ).newInstance(
- UUID.fromString(uuid),
- instanceId,
- permissions
- )
+ val descriptorWithoutInstanceId =
+ FwkBluetoothGattDescriptor(UUID.fromString(uuid), permissions)
+ val descriptor: FwkBluetoothGattDescriptor = descriptorWithoutInstanceId
+ .runCatching {
+ this::class.java.getDeclaredField("mInstance").let {
+ it.isAccessible = true
+ it.setInt(this, instanceId)
+ this
+ }
+ }.getOrDefault(descriptorWithoutInstanceId)
return BluetoothGattDescriptor(descriptor)
}
@@ -193,8 +194,10 @@
val bundle = Bundle()
bundle.putString(keyForField(FIELD_FWK_DESCRIPTOR_UUID), uuid.toString())
bundle.putInt(keyForField(FIELD_FWK_DESCRIPTOR_PERMISSIONS), permissions)
- val instanceId: Int =
- fwkDescriptor.javaClass.getDeclaredField("mInstance").getInt(fwkDescriptor)
+ val instanceId = fwkDescriptor.javaClass.getDeclaredField("mInstance").runCatching {
+ this.isAccessible = true
+ this.getInt(fwkDescriptor)
+ }.getOrDefault(0) // constructor will set instanceId to 0 by default
bundle.putInt(keyForField(FIELD_FWK_DESCRIPTOR_INSTANCE), instanceId)
return bundle
}
diff --git a/bluetooth/bluetooth-core/src/main/java/androidx/bluetooth/core/BluetoothGattService.kt b/bluetooth/bluetooth-core/src/main/java/androidx/bluetooth/core/BluetoothGattService.kt
index b6b75b3..05e8963 100644
--- a/bluetooth/bluetooth-core/src/main/java/androidx/bluetooth/core/BluetoothGattService.kt
+++ b/bluetooth/bluetooth-core/src/main/java/androidx/bluetooth/core/BluetoothGattService.kt
@@ -17,6 +17,7 @@
package androidx.bluetooth.core
import android.bluetooth.BluetoothGattService as FwkBluetoothGattService
+import android.annotation.SuppressLint
import android.os.Build
import android.os.Bundle
import androidx.annotation.RequiresApi
@@ -203,6 +204,7 @@
val CREATOR: Bundleable.Creator<BluetoothGattService> =
object : Bundleable.Creator<BluetoothGattService> {
+ @SuppressLint("SoonBlockedPrivateApi")
override fun fromBundle(bundle: Bundle): BluetoothGattService {
val uuid = bundle.getString(keyForField(FIELD_FWK_SERVICE_UUID))
?: throw IllegalArgumentException("Bundle doesn't include uuid")
@@ -213,11 +215,15 @@
throw IllegalArgumentException("Bundle doesn't include service type")
}
- val fwkService = FwkBluetoothGattService::class.java.getConstructor(
- UUID::class.java,
- Integer.TYPE,
- Integer.TYPE,
- ).newInstance(UUID.fromString(uuid), instanceId, type)
+ val fwkServiceWithoutInstanceId =
+ FwkBluetoothGattService(UUID.fromString(uuid), type)
+ val fwkService = fwkServiceWithoutInstanceId.runCatching {
+ this.javaClass.getDeclaredField("mInstanceId").let {
+ it.isAccessible = true
+ it.setInt(this, instanceId)
+ }
+ this
+ }.getOrDefault(fwkServiceWithoutInstanceId)
val gattService = BluetoothGattService(fwkService)