New issue
Advanced search Search tips

Issue 655935 link

Starred by 1 user

Issue metadata

Status: WontFix
Owner: ----
Closed: Oct 2016
Components:
EstimatedDays: ----
NextAction: ----
OS: All
Pri: 3
Type: Bug

Blocking:
issue 476735



Sign in to add a comment

bluetooth: readValue from characteristic with same UUID doesn't retrieve correct values

Project Member Reported by fbeaufort@chromium.org, Oct 14 2016

Issue description

Google Chrome	55.0.2883.7 (Official Build) dev (64-bit)
Platform	8872.6.0 (Official Build) dev-channel link

What steps will reproduce the problem?
(1) Go to https://beaufortfrancois.github.io/sandbox/web-bluetooth/get-characteristics-with-same-uuid/
(2) Make sure a Bluetooth device advertising the Battery Service is nearby and has two "Battery Level" characteristics with different returned values to identify them uniquely. 
(3) Click "Test" button
(4) Open Dev Tools

What is the expected output?
I should see "1" and "2" as Battery Level characteristics have different values.

What do you see instead?
(index):19 [BluetoothRemoteGATTCharacteristic, BluetoothRemoteGATTCharacteristic]
(index):24 1
(index):26 1


See web app source code at https://github.com/beaufortfrancois/sandbox/blob/gh-pages/web-bluetooth/get-characteristics-with-same-uuid/index.html#L20


And here's attached the nRF Server Configuration file I've used to reproduce this issue.
See inline as well:

<server-configuration name="Read">
   <service uuid="0000180f-0000-1000-8000-00805f9b34fb">
      <characteristic uuid="00002a19-0000-1000-8000-00805f9b34fb" value="01">
         <permission name="READ"/>
         <property name="READ"/>
      </characteristic>
      <characteristic uuid="00002a19-0000-1000-8000-00805f9b34fb" value="02">
         <permission name="READ"/>
         <property name="READ"/>
      </characteristic>
   </service>
</server-configuration>
 
 
nrf-connect-server-configuration.txt
469 bytes View Download
FYI, here are chrome logs:

[20684:20684:1014/102905:VERBOSE1:bluetooth_device_chooser_controller.cc(54)] requestDevice called with the following filters: 
[20684:20684:1014/102905:VERBOSE1:bluetooth_device_chooser_controller.cc(57)] Filter #1
[20684:20684:1014/102905:VERBOSE1:bluetooth_device_chooser_controller.cc(65)] Services: 
[20684:20684:1014/102905:VERBOSE1:bluetooth_device_chooser_controller.cc(66)] 	[
[20684:20684:1014/102905:VERBOSE1:bluetooth_device_chooser_controller.cc(68)] 		0000180f-0000-1000-8000-00805f9b34fb
[20684:20684:1014/102905:VERBOSE1:bluetooth_device_chooser_controller.cc(69)] 	]
[20684:20684:1014/102905:VERBOSE1:bluetooth_adapter_bluez.cc(1289)] AddDiscoverySession
[20684:20684:1014/102905:VERBOSE1:bluetooth_adapter_bluez.cc(1583)] OnSetDiscoveryFilter
[20684:20684:1014/102905:VERBOSE1:bluetooth_adapter_bluez.cc(1468)] OnStartDiscovery
[20684:20684:1014/102905:VERBOSE1:bluetooth_adapter.cc(294)] BluetoothAdapter::OnStartDiscoverySession
[20684:20684:1014/102905:VERBOSE1:bluetooth_device_chooser_controller.cc(441)] Started discovery session.
[20684:20684:1014/102906:VERBOSE1:bluetooth_adapter_bluez.cc(1022)] Discovering changed: 1
[20684:20684:1014/102907:VERBOSE1:bluetooth_discovery_session.cc(45)] Stopping device discovery session.
[20684:20684:1014/102907:VERBOSE1:bluetooth_adapter_bluez.cc(1352)] RemoveDiscoverySession
[20684:20684:1014/102907:VERBOSE1:bluetooth_allowed_devices_map.cc(28)] Adding a device to Map of Allowed Devices.
[20684:20684:1014/102907:VERBOSE1:bluetooth_allowed_devices_map.cc(46)] Id generated for device: w2rRHaKHQvPiqWx6SLac6g==
[20684:20684:1014/102907:VERBOSE1:web_bluetooth_service_impl.cc(783)] Device: Nexus 5X
[20684:20684:1014/102907:VERBOSE1:web_bluetooth_service_impl.cc(784)] UUIDs: 
[20684:20684:1014/102907:VERBOSE1:web_bluetooth_service_impl.cc(790)] 	 Allowed: 0000180f-0000-1000-8000-00805f9b34fb
[20684:20684:1014/102907:VERBOSE1:web_bluetooth_service_impl.cc(793)] 	 Not Allowed: 00001801-0000-1000-8000-00805f9b34fb
[20684:20684:1014/102907:VERBOSE1:web_bluetooth_service_impl.cc(793)] 	 Not Allowed: 00001800-0000-1000-8000-00805f9b34fb
[20684:20684:1014/102907:VERBOSE1:bluetooth_adapter_bluez.cc(1515)] OnStopDiscovery
[20684:20684:1014/102907:VERBOSE1:bluetooth_device_bluez.cc(438)] /org/bluez/hci0/dev_72_49_F1_A3_D5_DF: Connecting, 1 in progress
[20684:20684:1014/102907:VERBOSE1:bluetooth_device_bluez.cc(755)] /org/bluez/hci0/dev_72_49_F1_A3_D5_DF: Connecting
[20684:20684:1014/102907:VERBOSE1:bluetooth_adapter_bluez.cc(1022)] Discovering changed: 0
[20684:20684:1014/102908:VERBOSE1:bluetooth_device_bluez.cc(771)] /org/bluez/hci0/dev_72_49_F1_A3_D5_DF: Connected, 0 still in progress
[20684:20684:1014/102908:VERBOSE1:web_bluetooth_service_impl.cc(440)] Services not yet discovered.
[20684:20684:1014/102908:VERBOSE3:bluetooth_device_bluez.cc(693)] Updating the list of GATT services associated with device /org/bluez/hci0/dev_72_49_F1_A3_D5_DF
[20684:20684:1014/102908:VERBOSE2:bluetooth_device_bluez.cc(641)] Remote GATT service does not belong to this device.
[20684:20684:1014/102908:VERBOSE1:web_bluetooth_service_impl.cc(268)] Services discovered for device: 72:49:F1:A3:D5:DF
[20684:20684:1014/102908:VERBOSE1:web_bluetooth_service_impl.cc(158)] Looking for service: 0000180f-0000-1000-8000-00805f9b34fb
[20684:20684:1014/102908:VERBOSE1:web_bluetooth_service_impl.cc(161)] Service in cache: 0000180f-0000-1000-8000-00805f9b34fb
[20684:20684:1014/102908:VERBOSE1:web_bluetooth_service_impl.cc(161)] Service in cache: 00001801-0000-1000-8000-00805f9b34fb
[20684:20684:1014/102908:VERBOSE1:web_bluetooth_service_impl.cc(746)] Services found in device.
[20684:20684:1014/102908:VERBOSE1:web_bluetooth_service_impl.cc(139)] Looking for characteristic: 00002a19-0000-1000-8000-00805f9b34fb
[20684:20684:1014/102908:VERBOSE1:web_bluetooth_service_impl.cc(143)] Characteristic in cache: 00002a19-0000-1000-8000-00805f9b34fb
[20684:20684:1014/102908:VERBOSE1:web_bluetooth_service_impl.cc(143)] Characteristic in cache: 00002a19-0000-1000-8000-00805f9b34fb
[20684:20684:1014/102908:VERBOSE1:bluetooth_remote_gatt_characteristic_bluez.cc(278)] Sending GATT characteristic read request to characteristic: /org/bluez/hci0/dev_72_49_F1_A3_D5_DF/service0028/char0029, UUID: 00002a19-0000-1000-8000-00805f9b34fb.
[20684:20684:1014/102908:VERBOSE2:bluetooth_gatt_characteristic_client.cc(235)] Remote GATT characteristic property changed: /org/bluez/hci0/dev_72_49_F1_A3_D5_DF/service0028/char0029: Value
[20684:20684:1014/102908:VERBOSE1:bluetooth_remote_gatt_characteristic_bluez.cc(278)] Sending GATT characteristic read request to characteristic: /org/bluez/hci0/dev_72_49_F1_A3_D5_DF/service0028/char002b, UUID: 00002a19-0000-1000-8000-00805f9b34fb.
[20684:20684:1014/102908:VERBOSE2:bluetooth_gatt_characteristic_client.cc(235)] Remote GATT characteristic property changed: /org/bluez/hci0/dev_72_49_F1_A3_D5_DF/service0028/char002b: Value
Summary: bluetooth: readValue from characteristic with same UUID doesn't retrieve correct values (was: bluetooth: getCharacteristics with same UUID doesn't retrieve correct chararacteristics)
It looks like the issue is not about getCharacteristics getting wrong characteristics but readValue sending back wrong values.
The HCI trace might help to check which handles are being read, from the object path it looks like its 0x0029 and 0x002b. Btw, is the same reproducible with bluetoothctl for example?
Status: ExternalDependency (was: Available)
Oooooooooooh you're right! I can reproduce it from bluetoothctl as well.

Here's the btmon trace:

< ACL Data TX: Handle 33 flags 0x00 dlen 7                                                                                  [hci0] 8.928174
      ATT: Read Request (0x0a) len 2
        Handle: 0x002a
> HCI Event: Number of Completed Packets (0x13) plen 5                                                                      [hci0] 8.987206
        Num handles: 1
        Handle: 33
        Count: 1
> ACL Data RX: Handle 33 flags 0x02 dlen 6                                                                                  [hci0] 9.121916
      ATT: Read Response (0x0b) len 1
        Value: 01
< ACL Data TX: Handle 33 flags 0x00 dlen 7                                                                                  [hci0] 9.126153
      ATT: Read Request (0x0a) len 2
        Handle: 0x002c
> HCI Event: Number of Completed Packets (0x13) plen 5                                                                      [hci0] 9.190201
        Num handles: 1
        Handle: 33
        Count: 1
> ACL Data RX: Handle 33 flags 0x02 dlen 6                                                                                  [hci0] 9.324433
      ATT: Read Response (0x0b) len 1
        Value: 01
Note that I can reproduce this issue on macOS as well.
I've pinged nRF Connect folks to see if they're aware of a potential issue with how they deal with multiple characteristics with same UUID.
Here's the great answer I got from nRF Connect folks:


Hi Francois,
 
Here how it works in nRF Connect:
When user configures a server I open the GATT Server with defined services and characteristics.
Whenever a device is connected, connects to, or is already connected when server config was modified I create a copy of server’s services per each device. This copy contains characteristics and descriptors values, so you may modify them independently for each connected device and you will get the last written value per this device, not by any device.
[It’s not how spec says how it should be, but how I decided. Perhaps it would be better to keep only CCCD values per device and all other globally (line PC version of nRF Connect does), but at that time I decided it to be like this.] nvm.
Then, when I get a read request for characteristic, I look for its copy in the device’s corresponding copy. I just look for service index, char index and descr index in the original server services and return the characteristic or descriptor matching given indexes from device’s copy.
 
So let’s say I want to read the 2nd Battery Level characteristic from nRF Connect. I used your server configuration file on another phone.
In my readCharacteristic(..) method I have the following objects:

[IMAGE ATTACHED #1]
 
A you see the object ID 6562 matches the second characteristic in the service.
So I should be looking for the second characteristic in this service to obtain the correct value.
Now let’s look at what my server gets. This image was taken in onCharacteristicReadRequest method.

[IMAGE ATTACHED #2] 

Looks like the client wants to get the first characteristic’s value, not the second.
And nRF Connect correctly reports the requested value.
 
The problem lies in instance IDs on the server side. They are all 0, even for characteristics with the same UUID.
 
On client side it used to be that instance ids were counted from 0 and increased for each same UUID.
The Google’s BLE team in Android 7 changed the implementation of ‘getInstanceId()’ method for services and characteristics.
Now, when you connect to a device, do service discovery the instance ids are the Handle IDs. As you see on the top image the service’s instance id = 46 as I’m testing on Android 7.0 Nexus 6P.
This actually made some complications for me, as e.g. automated tests, macros and my views are counting attributes using the old way so I have to count them manually now.
 
But the gatt server services, characteristics and descriptors always have instance id = 0. You may see it on the second image, the instance id is 0 for all attributes. I tried it on Nexus 6P and HTC One M8 with Android 6.0.1 and I think it was like this since beginning.
 
So, unfortunately, the bug is on Android side. It just loses the instance id value somewhere in between and asks me always for the first instance of given UUID.
I can’t do any workaround here and count anything on my own as from the app’s point of view the client is asking for the first characteristic value and I have no way to say it’s not true.
 
*- why it may be a “feature”: otherwise, by exposing the real instance id or handle id, an app could be informed that there is another app that has the same service already defined, or how many
Services/characteristics were defined before. I don’t see any security issue with this, and in fact that could be hidden as I could be getting ‘per-app-instance-id’. It is also not said that handle numbers must be without any gaps, so each app could get a random set of handles.
 
I’m pretty sure you should not get this issue when connected to nRF5 device with 2 characteristics with the same UUID.
image-1.png
66.6 KB View Download
image-2.png
120 KB View Download

Comment 8 by ortuno@chromium.org, Oct 16 2016

Status: WontFix (was: ExternalDependency)
Closing since it seems unrelated to chrome.
According to Android folks,

Characteristic in android is described not only by UUID, but also instanceId, so if you have two characteristics with same UUID are you using ones with proper instanceId ? https://developer.android.com/reference/android/bluetooth/BluetoothGattCharacteristic.html#getInstanceId()

InstanceId on older androids is 0,1,2,3... on newer phones (android 7.0) it's value is similar(but not same as) attribute handle.



Sign in to add a comment