[go: nahoru, domu]

Add bluetooth-core tests

Add BluetoothGattDescriptorTest, BluetoothGattCharacteristicTest
and BluetoothGattServiceTest

Test: ./gradlew bluetooth:bluetooth-core:connectAndroidTest --info --daemon
Change-Id: I6026dcbeadecf3f8adbb0208c2ef2612c72a1019
diff --git a/bluetooth/bluetooth-core/src/androidTest/java/androidx/bluetooth/core/BluetoothGattCharacteristicTest.kt b/bluetooth/bluetooth-core/src/androidTest/java/androidx/bluetooth/core/BluetoothGattCharacteristicTest.kt
new file mode 100644
index 0000000..dd93b64
--- /dev/null
+++ b/bluetooth/bluetooth-core/src/androidTest/java/androidx/bluetooth/core/BluetoothGattCharacteristicTest.kt
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.bluetooth.core
+
+import android.os.Bundle
+import java.util.UUID
+import kotlin.random.Random
+import androidx.test.filters.MediumTest
+import org.junit.Assert
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@MediumTest
+@RunWith(JUnit4::class)
+class BluetoothGattCharacteristicTest {
+    companion object {
+        fun generateUUID(): UUID {
+            return UUID.randomUUID()
+        }
+
+        fun generatePermissions(): Int {
+            // Permission are bit from 1<<0 to 1<<8, but ignoring 1<<3
+            return Random.nextBits(20) and (BluetoothGattCharacteristic.PERMISSION_READ or
+                BluetoothGattCharacteristic.PERMISSION_READ_ENCRYPTED or
+                BluetoothGattCharacteristic.PERMISSION_READ_ENCRYPTED_MITM or
+                BluetoothGattCharacteristic.PERMISSION_WRITE or
+                BluetoothGattCharacteristic.PERMISSION_WRITE_ENCRYPTED or
+                BluetoothGattCharacteristic.PERMISSION_WRITE_ENCRYPTED_MITM or
+                BluetoothGattCharacteristic.PERMISSION_WRITE_SIGNED or
+                BluetoothGattCharacteristic.PERMISSION_WRITE_SIGNED_MITM)
+        }
+
+        fun generateProperties(): Int {
+            // Permission are bit from 1<<0 to 1<<7
+            return Random.nextBits(20) and (BluetoothGattCharacteristic.PROPERTY_BROADCAST or
+                BluetoothGattCharacteristic.PROPERTY_EXTENDED_PROPS or
+                BluetoothGattCharacteristic.PROPERTY_INDICATE or
+                BluetoothGattCharacteristic.PROPERTY_NOTIFY or
+                BluetoothGattCharacteristic.PROPERTY_READ or
+                BluetoothGattCharacteristic.PROPERTY_SIGNED_WRITE or
+                BluetoothGattCharacteristic.PROPERTY_WRITE or
+                BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE)
+        }
+    }
+
+    @Test
+    fun constructorWithValues_createsInstanceCorrectly() {
+        repeat(5) {
+            val uuid = generateUUID()
+            val permissions = generatePermissions()
+            val properties = generateProperties()
+
+            val characteristic = BluetoothGattCharacteristic(uuid, properties, permissions)
+
+            Assert.assertEquals(permissions, characteristic.fwkCharacteristic.permissions)
+            Assert.assertEquals(properties, characteristic.fwkCharacteristic.properties)
+            Assert.assertEquals(uuid, characteristic.fwkCharacteristic.uuid)
+            Assert.assertEquals(permissions, characteristic.permissions)
+            Assert.assertEquals(properties, characteristic.properties)
+            Assert.assertEquals(uuid, characteristic.uuid)
+            Assert.assertEquals(null, characteristic.service)
+        }
+    }
+
+    @Test
+    fun bluetoothGattCharacteristicBundleable() {
+        repeat(5) {
+            val uuid = generateUUID()
+            val permissions = generatePermissions()
+            val properties = generateProperties()
+
+            val characteristic = BluetoothGattCharacteristic(uuid, properties, permissions)
+            characteristic.writeType = BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT
+
+            repeat(5) {
+                val descriptorUUID = BluetoothGattDescriptorTest.generateUUID()
+                val descriptorPermission = BluetoothGattDescriptorTest.generatePermissions()
+
+                val descriptor = BluetoothGattDescriptor(descriptorUUID, descriptorPermission)
+                characteristic.addDescriptor(descriptor)
+
+                Assert.assertEquals(characteristic, descriptor.characteristic)
+            }
+
+            val bundle: Bundle = characteristic.toBundle()
+            val newCharacteristic: BluetoothGattCharacteristic =
+                BluetoothGattCharacteristic.CREATOR.fromBundle(bundle)
+
+            Assert.assertEquals(newCharacteristic.permissions, characteristic.permissions)
+            Assert.assertEquals(newCharacteristic.instanceId, characteristic.instanceId)
+            Assert.assertEquals(newCharacteristic.uuid, characteristic.uuid)
+            Assert.assertEquals(newCharacteristic.properties, characteristic.properties)
+            Assert.assertEquals(newCharacteristic.writeType, characteristic.writeType)
+            Assert.assertEquals(newCharacteristic.descriptors.size, characteristic.descriptors.size)
+            newCharacteristic.descriptors.forEach {
+                val foundDescriptor = characteristic.getDescriptor(it.uuid)
+
+                Assert.assertEquals(foundDescriptor?.permissions, it.permissions)
+                Assert.assertEquals(foundDescriptor?.uuid, it.uuid)
+                Assert.assertEquals(foundDescriptor?.characteristic, characteristic)
+                Assert.assertEquals(it.characteristic, newCharacteristic)
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/bluetooth/bluetooth-core/src/androidTest/java/androidx/bluetooth/core/BluetoothGattDescriptorTest.kt b/bluetooth/bluetooth-core/src/androidTest/java/androidx/bluetooth/core/BluetoothGattDescriptorTest.kt
new file mode 100644
index 0000000..6f317dd
--- /dev/null
+++ b/bluetooth/bluetooth-core/src/androidTest/java/androidx/bluetooth/core/BluetoothGattDescriptorTest.kt
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.bluetooth.core
+
+import android.os.Bundle
+import androidx.test.filters.SmallTest
+
+import java.util.UUID
+import kotlin.random.Random
+import org.junit.Assert.assertEquals
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@SmallTest
+@RunWith(JUnit4::class)
+class BluetoothGattDescriptorTest {
+
+    companion object {
+        fun generateUUID(): UUID {
+            return UUID.randomUUID()
+        }
+
+        fun generatePermissions(): Int {
+            // Permission are bit from 1<<0 to 1<<8, but ignoring 1<<3
+            return Random.nextBits(20) and (BluetoothGattDescriptor.PERMISSION_READ or
+                BluetoothGattDescriptor.PERMISSION_READ_ENCRYPTED or
+                BluetoothGattDescriptor.PERMISSION_READ_ENCRYPTED_MITM or
+                BluetoothGattDescriptor.PERMISSION_WRITE or
+                BluetoothGattDescriptor.PERMISSION_WRITE_ENCRYPTED or
+                BluetoothGattDescriptor.PERMISSION_WRITE_ENCRYPTED_MITM or
+                BluetoothGattDescriptor.PERMISSION_WRITE_SIGNED or
+                BluetoothGattDescriptor.PERMISSION_WRITE_SIGNED_MITM)
+        }
+    }
+
+    @Test
+    fun constructorWithValues_createsInstanceCorrectly() {
+        repeat(5) {
+            val uuid = generateUUID()
+            val permissions = generatePermissions()
+
+            val descriptor = BluetoothGattDescriptor(uuid, permissions)
+
+            assertEquals(permissions, descriptor.fwkDescriptor.permissions)
+            assertEquals(uuid, descriptor.fwkDescriptor.uuid)
+            assertEquals(permissions, descriptor.permissions)
+            assertEquals(uuid, descriptor.uuid)
+            assertEquals(null, descriptor.characteristic)
+        }
+    }
+
+    @Test
+    fun bluetoothGattDescriptorBundleable() {
+        repeat(5) {
+            val uuid = generateUUID()
+            val permissions = generatePermissions()
+            val descriptor = BluetoothGattDescriptor(uuid, permissions)
+            val bundle: Bundle = descriptor.toBundle()
+            val newDescriptor: BluetoothGattDescriptor =
+                BluetoothGattDescriptor.CREATOR.fromBundle(bundle)
+
+            assertEquals(newDescriptor.permissions, descriptor.permissions)
+            assertEquals(newDescriptor.uuid, descriptor.uuid)
+        }
+    }
+}
\ No newline at end of file
diff --git a/bluetooth/bluetooth-core/src/androidTest/java/androidx/bluetooth/core/BluetoothGattServiceTest.kt b/bluetooth/bluetooth-core/src/androidTest/java/androidx/bluetooth/core/BluetoothGattServiceTest.kt
new file mode 100644
index 0000000..b7bd14c
--- /dev/null
+++ b/bluetooth/bluetooth-core/src/androidTest/java/androidx/bluetooth/core/BluetoothGattServiceTest.kt
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.bluetooth.core
+
+import android.os.Bundle
+import androidx.test.filters.MediumTest
+import java.util.UUID
+import kotlin.random.Random
+import org.junit.Assert
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@MediumTest
+@RunWith(JUnit4::class)
+class BluetoothGattServiceTest {
+    companion object {
+        fun generateUUID(): UUID {
+            return UUID.randomUUID()
+        }
+
+        fun generateType(): Int {
+            // Permission are bit from 1<<0 to 1<<8, but ignoring 1<<3
+            return Random.nextBits(1)
+        }
+    }
+
+    @Test
+    fun constructorWithValues_createsInstanceCorrectly() {
+        repeat(5) {
+            val uuid = generateUUID()
+            val type = generateType()
+
+            val service = BluetoothGattService(uuid, type)
+
+            Assert.assertEquals(uuid, service.uuid)
+            Assert.assertEquals(type, service.type)
+            Assert.assertEquals(uuid, service.fwkService.uuid)
+            Assert.assertEquals(type, service.fwkService.type)
+            Assert.assertEquals(0, service.includedServices.size)
+            Assert.assertEquals(0, service.characteristics.size)
+        }
+    }
+
+    @Test
+    fun bluetoothGattServiceBundleable() {
+        repeat(5) {
+
+            val serviceUuid = generateUUID()
+            val serviceType = generateType()
+
+            val service = BluetoothGattService(serviceUuid, serviceType)
+
+            repeat(5) {
+                val uuid = BluetoothGattCharacteristicTest.generateUUID()
+                val permissions = BluetoothGattCharacteristicTest.generatePermissions()
+                val properties = BluetoothGattCharacteristicTest.generateProperties()
+
+                val characteristic = BluetoothGattCharacteristic(uuid, properties, permissions)
+                characteristic.writeType = BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT
+
+                service.addCharacteristic(characteristic)
+
+                Assert.assertEquals(characteristic.service, service)
+            }
+
+            repeat(5) {
+                val uuid = generateUUID()
+                val type = generateType()
+
+                val includedService = BluetoothGattService(uuid, type)
+
+                service.addService(includedService)
+            }
+
+            val bundle: Bundle = service.toBundle()
+            val newService: BluetoothGattService =
+                BluetoothGattService.CREATOR.fromBundle(bundle)
+
+            Assert.assertEquals(newService.uuid, service.uuid)
+            Assert.assertEquals(newService.instanceId, service.instanceId)
+            Assert.assertEquals(newService.type, service.type)
+            Assert.assertEquals(newService.characteristics.size, service.characteristics.size)
+            Assert.assertEquals(newService.includedServices.size, service.includedServices.size)
+            newService.characteristics.forEach {
+                val foundCharacteristic = service.getCharacteristic(it.uuid)
+
+                Assert.assertEquals(foundCharacteristic?.permissions, it.permissions)
+                Assert.assertEquals(foundCharacteristic?.uuid, it.uuid)
+                Assert.assertEquals(foundCharacteristic?.instanceId, it.instanceId)
+                Assert.assertEquals(foundCharacteristic?.properties, it.properties)
+                Assert.assertEquals(foundCharacteristic?.writeType, it.writeType)
+                Assert.assertEquals(foundCharacteristic?.service, service)
+                Assert.assertEquals(it.service, newService)
+            }
+
+            newService.includedServices.forEach {
+                val foundService = service.getIncludedService(it.uuid)
+
+                Assert.assertEquals(foundService?.uuid, it.uuid)
+                Assert.assertEquals(foundService?.type, it.type)
+                Assert.assertEquals(foundService?.instanceId, it.instanceId)
+            }
+        }
+    }
+}
\ No newline at end of file
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 9cce410..a82a182 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
@@ -66,7 +66,7 @@
         const val FORMAT_UINT8 = FwkBluetoothGattCharacteristic.FORMAT_UINT8
 
         /**
-         * Characteristic proprty: Characteristic is broadcastable.
+         * Characteristic property: Characteristic is broadcastable.
          */
         const val PROPERTY_BROADCAST =
             FwkBluetoothGattCharacteristic.PROPERTY_BROADCAST
@@ -363,14 +363,6 @@
                 }
         }
 
-        init {
-            fwkCharacteristic.descriptors.forEach {
-                val descriptor = BluetoothGattDescriptor(it)
-                _descriptors.add(descriptor)
-                descriptor.characteristic = characteristic
-            }
-        }
-
         override val uuid: UUID
             get() = fwkCharacteristic.uuid
         override val properties
@@ -388,6 +380,13 @@
         override val descriptors
             get() = _descriptors.toList()
         override var service: BluetoothGattService? = null
+        init {
+            fwkCharacteristic.descriptors.forEach {
+                val descriptor = BluetoothGattDescriptor(it)
+                _descriptors.add(descriptor)
+                descriptor.characteristic = characteristic
+            }
+        }
 
         override fun addDescriptor(
             descriptor: BluetoothGattDescriptor,
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 3ebc18b..c0042c3 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
@@ -34,12 +34,12 @@
         /**
          * Primary service
          */
-        val SERVICE_TYPE_PRIMARY = FwkBluetoothGattService.SERVICE_TYPE_PRIMARY
+        const val SERVICE_TYPE_PRIMARY = FwkBluetoothGattService.SERVICE_TYPE_PRIMARY
 
         /**
          * Secondary service (included by primary services)
          */
-        val SERVICE_TYPE_SECONDARY = FwkBluetoothGattService.SERVICE_TYPE_SECONDARY
+        const val SERVICE_TYPE_SECONDARY = FwkBluetoothGattService.SERVICE_TYPE_SECONDARY
         /**
          * A companion object to create [BluetoothGattService] from bundle
          */
@@ -193,7 +193,7 @@
 
     private open class GattServiceImplApi21(
         final override val fwkService: FwkBluetoothGattService,
-        service: BluetoothGattService
+        private val service: BluetoothGattService
     ) : GattServiceImpl {
 
         companion object {
@@ -301,6 +301,7 @@
         override fun addCharacteristic(characteristic: BluetoothGattCharacteristic): Boolean {
             return if (fwkService.addCharacteristic(characteristic.fwkCharacteristic)) {
                 _characteristics.add(characteristic)
+                characteristic.service = service
                 true
             } else {
                 false
diff --git a/bluetooth/bluetooth-core/src/main/java/androidx/bluetooth/core/utils/Utils.kt b/bluetooth/bluetooth-core/src/main/java/androidx/bluetooth/core/utils/Utils.kt
index 2eb25fc..664275e 100644
--- a/bluetooth/bluetooth-core/src/main/java/androidx/bluetooth/core/utils/Utils.kt
+++ b/bluetooth/bluetooth-core/src/main/java/androidx/bluetooth/core/utils/Utils.kt
@@ -35,39 +35,33 @@
         key: String,
         clazz: Class<T>
     ): T? {
-        val parcelable: T?
         bundle.classLoader = clazz.classLoader
-        try {
+        return try {
             if (Build.VERSION.SDK_INT >= 33) {
-                parcelable = bundle.getParcelable(key, clazz)
+                bundle.getParcelable(key, clazz)
             } else {
-                parcelable = bundle.getParcelable(key)
+                bundle.getParcelable(key)
             }
         } catch (e: Exception) {
-            return null
+            null
         }
-        return parcelable
     }
-
+    @SuppressLint("ClassVerificationFailure") // bundle.getParcelable(key, clazz)
     @Suppress("DEPRECATION")
     fun <T : Parcelable> getParcelableArrayListFromBundle(
         bundle: Bundle,
         key: String,
         clazz: Class<T>
     ): List<T> {
-        bundle.classLoader = clazz.classLoader
-        if (Build.VERSION.SDK_INT >= 33) {
-            // TODO: Return framework's getParcelableArrayList when SDK 33 is available
-            // return bundle.getParcelableArrayList(key, clazz)
-            TODO()
-        } else {
-            val parcelable: List<T>
-            try {
-                parcelable = bundle.getParcelableArrayList(key) ?: emptyList()
-            } catch (e: Exception) {
-                return emptyList()
+        return try {
+            bundle.classLoader = clazz.classLoader
+            if (Build.VERSION.SDK_INT >= 33) {
+                bundle.getParcelableArrayList(key, clazz) ?: emptyList()
+            } else {
+                bundle.getParcelableArrayList(key) ?: emptyList()
             }
-            return parcelable
+        } catch (e: Exception) {
+            emptyList()
         }
     }
 }
\ No newline at end of file