1
votes

How does Apple's proprietary technique for background GATT service advertising on iOS work?

According to Apple's documentation, when an iOS app using CoreBluetooth to implement a BLE peripheral is in the background, service UUIDs are no longer advertised, and instead are put on a special "overflow area":

Any service UUIDs contained in the value of the CBAdvertisementDataServiceUUIDsKey key that don’t fit in the allotted space go to a special “overflow” area. These services are discoverable only by an iOS device explicitly scanning for them. While your app is in the background, the local name isn’t advertised and all service UUIDs are in the overflow area. -- developer.apple.com

But what is this "overflow area"? How does it work?

I set up a bluetooth sniffer and captured the BLE data exchange, but failed to find any communication of this Service UUID. A second iOS device in the foreground was repeatedly able to successfully discover the service advertisement on the backgrounded iOS device, but the packet capture never once logged the Service UUID.

So how does this work?

If I can figure out how it works, I would like to try to program an Android device to use the same process.

1
Did you read github.com/crownstone/bluenet-ios-basic-localization/blob/…? It seems the manufacturer data contains a small fingerprint/hash of the service set, so that it can be cached. Didn't the iOS central perform a service discovery of the peripheral? And you should use nRF sniffer instead, it can easily be used with wireshark and usually catch connection requests on any channel because it switches to ch 38 when it sees an adv packet on 37, and then to ch 39 and then back.Emil
I had not seen that writeup. Fascinating! It says the proprietary manufacturer advert contains a bitmap hash where a 1 in any position indicates that any one of a subset of service UUIDS is being advertised. If true, this suggests that the advertised service uuid is never truly known or checked by iOS. A central gets a discovery callback if the bit for the desired Service UUID is set, even if the advertisement is from an iPhone advertising a different Service UUID that happens to also use that bit due to a hash collision. I will do some tests to confirm. Thanks, Emil!davidgyoung

1 Answers

4
votes

The Overflow Area is a manufacturer advertisement emitted from iOS devices when at least one iOS app is advertising a CoreBluetooth service from the background. It looks like this:

ff 4c 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80

The ff signifies a manufacturer advertisement, the 4c 00 bytes correspond to Apple’s assigned manufacturer code of 0x004C by Bluetooth SIG. The 01 identifies this as an overflow area advertisement. The last 16 bytes (128 bits) are a hashed bitmask of services advertised.

Each service UUID you advertise will cause exactly one of those 128 bits to be set to 1. There is a one-to-one mapping between a service UUID and the bit position it sets in this bitmask. This is consistent across iOS devices. Converting a service UUID to a bit position in the bitmask is some proprietary Apple hashing algorithm.

Because there are a huge number of possible 128-bit UUIDs – 2^128 (about 10^38) – multiple service UUIDs share the same bit position.

Since many service UUIDs share each bit position in the overflow area bitmask, collisions are inevitable. iOS will give a scanning callback a the colliding but different service UUID. This won’t happen often. But programmers should realize that they may scan for their service only to get a callback for detecting a backgrounded iOS device advertising a completely different service that just happens to collide in the overflow area’s bitmask.

Interestingly, the overflow area can be manipulated to enable two backgrounded iOS apps to exchanged data in the background. See my blog post for more info.