Add ScanResult class
Implement a ScanResult class that represents scan result for Bluetooth
LE scan. Also add unit test for the class.
Bug: 278997201
Test: ./gradlew bluetooth:bluetooth:connectedAndroidTest
Relnote: NA
Change-Id: I35e5c906344fbb3a1d37ba884cdfaf6b61447ad4
diff --git a/bluetooth/bluetooth/api/current.txt b/bluetooth/bluetooth/api/current.txt
index d682668..cdcca53 100644
--- a/bluetooth/bluetooth/api/current.txt
+++ b/bluetooth/bluetooth/api/current.txt
@@ -71,5 +71,19 @@
public static final class ScanFilter.Companion {
}
+ public final class ScanResult {
+ method public androidx.bluetooth.BluetoothDevice getDevice();
+ method public androidx.bluetooth.BluetoothAddress getDeviceAddress();
+ method public byte[]? getManufacturerSpecificData(int manufacturerId);
+ method public byte[]? getServiceData(java.util.UUID serviceUuid);
+ method public java.util.List<java.util.UUID> getServiceUuids();
+ method public long getTimestampNanos();
+ method public boolean isConnectable();
+ property public final androidx.bluetooth.BluetoothDevice device;
+ property public final androidx.bluetooth.BluetoothAddress deviceAddress;
+ property public final java.util.List<java.util.UUID> serviceUuids;
+ property public final long timestampNanos;
+ }
+
}
diff --git a/bluetooth/bluetooth/api/restricted_current.txt b/bluetooth/bluetooth/api/restricted_current.txt
index d682668..cdcca53 100644
--- a/bluetooth/bluetooth/api/restricted_current.txt
+++ b/bluetooth/bluetooth/api/restricted_current.txt
@@ -71,5 +71,19 @@
public static final class ScanFilter.Companion {
}
+ public final class ScanResult {
+ method public androidx.bluetooth.BluetoothDevice getDevice();
+ method public androidx.bluetooth.BluetoothAddress getDeviceAddress();
+ method public byte[]? getManufacturerSpecificData(int manufacturerId);
+ method public byte[]? getServiceData(java.util.UUID serviceUuid);
+ method public java.util.List<java.util.UUID> getServiceUuids();
+ method public long getTimestampNanos();
+ method public boolean isConnectable();
+ property public final androidx.bluetooth.BluetoothDevice device;
+ property public final androidx.bluetooth.BluetoothAddress deviceAddress;
+ property public final java.util.List<java.util.UUID> serviceUuids;
+ property public final long timestampNanos;
+ }
+
}
diff --git a/bluetooth/bluetooth/src/androidTest/java/androidx/bluetooth/ScanResultTest.kt b/bluetooth/bluetooth/src/androidTest/java/androidx/bluetooth/ScanResultTest.kt
new file mode 100644
index 0000000..7f488d7
--- /dev/null
+++ b/bluetooth/bluetooth/src/androidTest/java/androidx/bluetooth/ScanResultTest.kt
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2023 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
+
+import android.bluetooth.BluetoothAdapter
+import android.bluetooth.BluetoothManager
+import android.bluetooth.le.ScanResult as FwkScanResult
+import android.content.Context
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.rule.GrantPermissionRule
+import java.util.UUID
+import junit.framework.TestCase.assertEquals
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@RunWith(JUnit4::class)
+class ScanResultTest {
+ @Rule
+ @JvmField
+ val permissionRule: GrantPermissionRule = GrantPermissionRule.grant(
+ android.Manifest.permission.BLUETOOTH_CONNECT)
+
+ private val context: Context = ApplicationProvider.getApplicationContext()
+ private val bluetoothManager: BluetoothManager =
+ context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
+ private val bluetoothAdapter: BluetoothAdapter? = bluetoothManager.adapter
+
+ @Test
+ fun constructorWithFwkInstance() {
+ val address = "00:01:02:03:04:05"
+ val fwkBluetoothDevice = bluetoothAdapter!!.getRemoteDevice(address)
+ val timeStampNanos: Long = 1
+ val serviceUuid = UUID.randomUUID()
+
+ // TODO(kihongs) Find a way to create framework ScanRecord and use in test
+ val fwkScanResult = FwkScanResult(fwkBluetoothDevice, 1, 0, 0, 0, 0, 0, 0, null,
+ timeStampNanos)
+ val scanResult = ScanResult(fwkScanResult)
+
+ assertEquals(scanResult.device.name, BluetoothDevice(fwkBluetoothDevice).name)
+ assertEquals(scanResult.device.bondState, BluetoothDevice(fwkBluetoothDevice).bondState)
+ assertEquals(scanResult.deviceAddress.address, address)
+ assertEquals(scanResult.deviceAddress.addressType, AddressType.ADDRESS_TYPE_RANDOM)
+ assertEquals(scanResult.isConnectable(), true)
+ assertEquals(scanResult.timestampNanos, timeStampNanos)
+ assertEquals(scanResult.getManufacturerSpecificData(1), null)
+ assertEquals(scanResult.serviceUuids, emptyList<UUID>())
+ assertEquals(scanResult.getServiceData(serviceUuid), null)
+ }
+}
\ No newline at end of file
diff --git a/bluetooth/bluetooth/src/main/java/androidx/bluetooth/ScanResult.kt b/bluetooth/bluetooth/src/main/java/androidx/bluetooth/ScanResult.kt
new file mode 100644
index 0000000..ac79d4a
--- /dev/null
+++ b/bluetooth/bluetooth/src/main/java/androidx/bluetooth/ScanResult.kt
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2023 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
+
+import android.bluetooth.le.ScanResult as FwkScanResult
+import android.os.ParcelUuid
+import java.util.UUID
+
+/**
+ * ScanResult for Bluetooth LE scan.
+ *
+ * The ScanResult class is used by Bluetooth LE applications to scan for and discover Bluetooth LE
+ * devices. When a Bluetooth LE application scans for devices, it will receive a list of ScanResult
+ * objects that contain information about the scanned devices. The application can then use this
+ * information to determine which devices it wants to connect to.
+ *
+ * @property device Remote device found
+ * @property deviceAddress Bluetooth address for the remote device found
+ * @property timestampNanos Device timestamp when the result was last seen
+ * @property serviceUuids A list of service UUIDs within advertisement that are used to identify the
+ * bluetooth GATT services.
+ *
+ */
+class ScanResult internal constructor(private val fwkScanResult: FwkScanResult) {
+ /** Remote Bluetooth device found. */
+ val device: BluetoothDevice
+ get() = BluetoothDevice(fwkScanResult.device)
+
+ // TODO(kihongs) Find a way to get address type from framework scan result
+ /** Bluetooth address for the remote device found. */
+ val deviceAddress: BluetoothAddress
+ get() = BluetoothAddress(fwkScanResult.device.address, AddressType.ADDRESS_TYPE_RANDOM)
+
+ /** Device timestamp when the advertisement was last seen. */
+ val timestampNanos: Long
+ get() = fwkScanResult.timestampNanos
+
+ /**
+ * Returns the manufacturer specific data associated with the manufacturer id.
+ *
+ * @param manufacturerId The manufacturer id of the scanned device
+ * @return the manufacturer specific data associated with the manufacturer id, or null if the
+ * manufacturer specific data is not present
+ */
+ fun getManufacturerSpecificData(manufacturerId: Int): ByteArray? {
+ return fwkScanResult.scanRecord?.getManufacturerSpecificData(manufacturerId)
+ }
+
+ /**
+ * A list of service UUIDs within advertisement that are used to identify the bluetooth GATT
+ * services.
+ */
+ val serviceUuids: List<UUID>
+ get() = fwkScanResult.scanRecord?.serviceUuids?.map { it.uuid }.orEmpty()
+
+ /**
+ * Returns the service data associated with the service UUID.
+ *
+ * @param serviceUuid The service UUID of the service data
+ * @return the service data associated with the specified service UUID, or null if the service
+ * UUID is not found
+ */
+ fun getServiceData(serviceUuid: UUID): ByteArray? {
+ return fwkScanResult.scanRecord?.getServiceData(ParcelUuid(serviceUuid))
+ }
+
+ /**
+ * Checks if this object represents connectable scan result.
+ *
+ * @return true if the scanned device is connectable; false otherwise
+ */
+ fun isConnectable(): Boolean {
+ return fwkScanResult.isConnectable
+ }
+}
\ No newline at end of file