CoreBluetooth: central device handles services change at the peripheral incorrectly

Originator:zmicier.zaleznicenka
Number:rdar://28819540 Date Originated:18-10-2016
Status:Open Resolved:no
Product:iOS Product Version:9, 10
Classification:Bluetooth Reproducible:Yes
 
Summary:
It seems that iPhone acting as BLE Central device doesn't always respond correctly to modification of services at the peripheral side.

Some extra information from our Android engineer:

Configuration:
PersonalNavigationDevice/PND (peripheral role, GATT server) <-> iPhone (central role, GATT client), paired

Description:
The problem seems to happen because iOS does not fetch GATT services even if Service Changed indication is sent to it. So when Android BT service needs to restart, Bluedroid cleans up the existing GATT server. When this clean up happens, Bluedroid sends Service Changed indication to iOS and iOS fetches new services (which are none). It remembers that the Peripheral has no services. When BT service is started again, it sets up new GATT server and this also sends Service Changed indication to iOS. iOS ignores it and thinks there are no services available at the Peripheral.

It looks to us that iOS incorrectly handles invalidation of ATT handles caused by GATT service change on PND. Whenever a GATT service is added or removed on PND, "Service Changed" (according to BLUETOOTH SPECIFICATION Version 4.2 [Vol 3, Part G, 7.1]) is sent to iOS to indicate that it needs to re-fetch GATT services and update ATT handles. This is illustrated in the attached HCI dump under frames:

#389 - Service Changed
#396 - iOS fetching PND Primary services and following up, characteristics
#443 - iOS subscribing to Service Changed indication
We noticed that sometimes during the operation if a GATT service is removed and then again added back on PND, iOS is not fetching GATT services correctly, which leads to a situation where iOS "thinks" there are not services available on PND (due to correct handling of service removal Service Changed indication, but incorrect handling of Service Changed indication during service addition), this is illustrated in the attached HCI dump under frames:
#5643 - Service Changed triggered by GATT service removal on PND
#5648 - iOS performs Primary service search
#5651 - PND replies on Primary service search reporting no services available (apart from the required by GATT)
#5709 - (8 seconds later) Service Changed triggered by GATT service add on PND
#5736 - iOS performs characteristic search for GATT profile, but does not perform Primary service changed
Any attmept to fetch PND GATT services from an application running on iOS reports no services available.
Expected:
iOS performs Primary service search on receiving Service Changed indication. So basically, as a reaction of frame #5709 it should do what it does as a reaction of frame #389 or frame #5643.

Steps to Reproduce:
We are able to reproduce the problem in the following scenario. 

1. BLE Central (iPhone) is connected to BLE Peripheral (Android-based PND). iPhone has previously discovered two services (7BBB5350-52B1-11E3-8F96-0800200C9A66 and 8ED067D5-C74E-4D0D-B637-53280C0EB5BB) that it needs to communicate with.
2. BLE Peripheral decides to restart these services.
3. BLE Peripheral stops both services that are needed by the iPhone. Then, it starts them again.
4. iPhone app's peripheral manager receives -peripheral:didModifyServices: callback with both services being marked invalidated.
5. iPhone app decides that it cannot continue with the current peripheral connection and cancels it.
6. iPhone app starts to search for new peripherals advertising these services.
7. iPhone discovers a previously disconnected peripheral that already has both services re-initialized and available.
8. iPhone app connects to the peripheral by calling -connectPeripheral:options: method.
9. iPhone app's peripheral manager calls -discoverServices: method.
10. iPhone app's peripheral manager receives -peripheral:didDiscoverServices: callback with 0 services discovered.

At this point, iPhone won't see re-created services until its BT switch is toggled off or on, restarting the app doesn't help.

Expected Results:
After the peripheral device invalidates and recreates its advertised services, central device should be able to reconnect to it and see updated services.

Actual Results:
BLE Central device is able to reconnect after the services are invalidated by the peripheral, but the newly added services are not found.

Version:
iOS 9, 10

Notes:

Configuration:
iPhone 6, TomTom GO 6200 (Android 5.1)

Attachments:
'sysdiagnose_2016.10.10_15-34-05+0200.tar.gz' and 'hci_snoop20161010153157.cfa' were successfully uploaded.

Comments


Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!