# Contact Tracing - Part 2

# Recap
I gave a highlight on the limitations of Google Nearby while implementing Contact Tracing service in [Part 1](https://charlesmuchene.hashnode.dev/contact-tracing-part-1-ck912ur0501uo7vs15n6sk5kh) of this series. In this part, I'll discuss another approach I took.

# Trial 2 - Bluetooth Smart - Advertising Mode

![ble.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1586958793110/pV_PJ1t5T.png)

While thinking of a solution that would advertise a token in the background on Android, I decided to give Bluetooth Smart aka Bluetooth Low Energy a try. BLE is used widely in fitness and music applications that need to stream a payload between two devices and obviously background subscription and advertisement is supported.

## Some BLE stuff
BLE is a low power technology to connect devices. This operates in the 2.4 GHz ISM (Industrial, Scientific, Medical) band alongside your cool devices such as garage door openers, baby monitors and tech like WiFi and NFC. All those years spent studying the Radio Frequency spectrum in my [Electrical and Electronics Engineering](https://www.linkedin.com/in/charlesmuchene/) class paid off here 👨🏾‍🎓. The [Bluetooth Special Interest Group](https://www.bluetooth.com/) is in charge of standardizing and evolving this technology. 
 These folks introduced BLE in version 4.0 of the Bluetooth Core Specification to target very low power applications such as those powered by a coin cell -- think Beacons etc.

Now, bear with me here. We have to go into some terminology used in BLE in order to understand how to implement our application. I'll reference, at the end, some great material I came across to help me understand this stuff.
- 
**Server**: device that has some data to expose - think of your Smart Watch (technically, receives GATT requests/commands and sends responses)
- 
**Client**: device that receives data exposed by server e.g. your dearly loved smartphone (technically, initiates GATT requests/commands and accepts responses)
- 
**Attribute**: structured data element exposed by a device
- 
**Attribute Protocol **(ATT): details how a server exposes data to a client and how the data is structured
- 
**Profile**: a set of features or services that a device has
- 
**Generic Access Profile** (GAP): defines how two devices discover and establish connections. Also acts as a basis for all other profiles
- 
**Generic Attribute Profile** (GATT): facilitates profile discovery and defines how attributes are grouped together 
- 
**Characteristic**: a single value (exposed by a server) -- contains *properties* and *descriptors*
- 
**Characteristic Properties**: determine how to use ta characteristic's value
- 
**Descriptor**: contains further information about a characteristic's value e.g. providing units of the value such as meters, nits etc
- 
**Service**: a collection of *attributes* -- contains *characteristics* and other metadata
- 
**Universally unique Identifier**: a 128-bit string used to identify BLE *attributes*

### GAP roles
BLE compliant devices can operate in one or more GAP roles at the same time:

1.  **Broadcaster**: sends advertisements, doesn't allow connections
2. **Observer**: scans and reads advertisements, doesn't initiate connections
3. **Peripheral**: sends advertisements, allows connections
4. **Central**: scans and reads advertisements, initiates connections

Again, lot's of info but check out the references at the end of the article on some great tutorials and in depth coverage of BLE.

## Android
Android provides support for BLE as from API level 18. Its API has evolved a bit from accessing the bluetooth adapter using the static `getDefaultAdapter` to having it provided from a system service: `Context.BLUETOOTH_SERVICE` -- one of the neat things I find in Android (allows apps to share cacheable system resources via a common api).

The entry point to using BLE is a system service called '**bluetooth**' -- the value for *Context.BLUETOOTH_SERVICE*. It is accessible as the `BluetoothManager` class. We then use this to get a `BluetoothAdapter` which is the representation of the our device's Bluetooth adapter -- we'll use this adapter to start device discovery and other common Bluetooth tasks. Next, we get the `BluetoothLeAdvertiser` from the adapter. This class allows us to advertise the Contact Trace token. In duality, we'll need to perform scans for devices broadcasting their token and for this enters `BluetoothLeScanner` class which we also get from the bluetooth adapter. And last but not least, we need the `BluetoothGattServer` that will enable us to create, register and serve our services. Here's my initialization listing just described:

![Screen Shot 2020-04-16 at 6.53.47 ruc-inī.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1587009762600/Bc_Fqgdi0.png)

`lazyNone` is my own sane way of writing non-synchronized property initialization since I guarantee this initialization is done on one thread. It's essentially a wrapper around, Kotlin's `lazy` generic function with `LazyThreadSafetyMode` `NONE`. Here's the declaration:

%[https://gist.github.com/charlesmuchene/b53c1724b468c5d92893e2226fe95592]

One thing to note is that bluetooth operations are asynchronous in nature and thus you have to work with callbacks. I came across an alternative [RxAndroidBle](http://polidea.github.io/RxAndroidBle/) which is an Rx wrapper around Android's Bluetooth framework. Nordic Semiconductor has an [Android BLE library](https://github.com/NordicSemiconductor/Android-BLE-Library) they claim makes working with Bluetooth LE on Android a pleasure. I didn't have time to explore these options but they all seem promising.

A couple of [permissions](https://developer.android.com/guide/topics/connectivity/bluetooth-le#permissions) are required for a BLE app:
- 
**android.Manifest.permission.BLUETOOTH** - obviously 😎
- 
**android.Manifest.permission.BLUETOOTH_ADMIN** e.g. required when advertising data
- 
**android.permission.ACCESS_FINE_LOCATION** for API level 29+ or **ACCESS_FINE_LOCATION** for <= API level 28 because... LE beacons

Advertising and Scans are possible in the background -- Finally! 🥳 I use a foreground service notifying the user that Contact Tracing is active. The user has explicit control over when to start or stop Contact Tracing.

![tracking.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1587012880393/gM2ZLnrYk.png)

## iOS
Apple added BLE a little earlier. They introduced [CoreBluetooth](https://developer.apple.com/documentation/corebluetooth) framework in [iOS 5.0](https://developer.apple.com/library/archive/releasenotes/General/WhatsNewIniOS/Articles/iOS5.html#//apple_ref/doc/uid/TP30915195-SW7). iOS uses `delegates` extensively in Cocoa. In fact, I would call it the **Delegate Framework** and *CoreBluetooth* is no different.

To encapsulate Bluetooth implementation, I created a *TraceService* singleton class -- Apple style. To have the iOS device work in the Central role, you use the `CBCentralManager`. Construction is straight forward and takes in a `CBCentralManagerDelegate` (in which my TraceService conforms via an extension), pass `nil` to use the main queue and `CBCentralManagerOptionRestoreIdentifierKey` in the options parameter (check out [Central Manager State Restoring Options](https://developer.apple.com/documentation/corebluetooth/cbcentralmanager/central_manager_state_restoration_options).)

For a peripheral role, `CBPeripheralManager` is your friend. Initialization is a breeze; provide a `CBPeripheralManagerDelegate` (my TraceService conforms to this as well), `nil` to use main dispatch queue, and `CBPeripheralManagerOptionRestoreIdentifierKey` with the restoration id for the options dictionary (check out [Peripheral Manager Initialization Options](https://developer.apple.com/documentation/corebluetooth/cbperipheralmanager/peripheral_manager_initialization_options).). This is the manager used to add services to the GATT database and advertise it.

The rest of the work in done in the respective delegates after the managers report `.poweredOn` state via the `**ManagerDidUpdateState` callback method. One key thing to note is that in iOS, advertisement is managed at the system level and shared by all applications. Remember to add the [NSBluetoothAlwaysUsageDescription](https://developer.apple.com/documentation/bundleresources/information_property_list/nsbluetoothalwaysusagedescription) in your *plist*. For my Contact Tracing app, I have the *Uses Bluetooth LE Accessories* and the *Acts as a Bluetooth LE accessory* capabilities enabled as background modes as well.

![Screen Shot 2020-04-16 at 8.57.32 ruc-inī.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1587016792038/gZL2dEYKp.png)

One iOS BLE framework wrapper I came across in my research is [BlueCap](https://github.com/troystribling/BlueCap). Again, I didn't get to work with it in this project though looks promising.

## Implementation
From the GAP roles mentioned earlier, I thought the **Broadcaster/Observer** pair looked promising. Contact Tracing didn't need to establish BLE connections -- just exchange the anonymous tokens. In both apps, I created a custom BLE profile and service, `TraceProfile` and `TraceService` respectively. *TraceProfile* defines services and characteristics and their respective UUIDs. I only needed one service for now of which I defined a custom UUID for it.
 
In BLE (at least in version I was working with), an advertiser can broadcast up to **31 bytes** of advertisement data. (*I understand Bluetooth 5.0 increases this to 255 bytes! 🤯*). 128-bits for my service UUID is 16 bytes, there are some overhead bytes per field advertised - each UUID (service uuids are grouped into one field, 2 bytes each, for each of the 16-bit, 32-bit and 128-bit uuids) and some flags such as if the advertisement is connectable adds some 3 bytes. Adding some service data to the payload easily blows beyond *31-bytes* and in Android results in `ADVERTISE_FAILED_DATA_TOO_LARGE` advertising error. With all this in mind, I chose to advertise only the service UUID and my token payload.

## Limitations
You can guess trial 2 wasn't my ideal solution. 

1. CoreBluetooth advertises data on a "best effort" basis meaning that the framework is in charge of when it does the advertisement.
2. CoreBluetooth limits what advertisement data contains -- only the *local name*, Service UUIDs or a combination of both. No other advertisement payload is allowed thus I can't have iOS working as a **broadcaster** for my use case 🤕.
3. I tried **scan response** (i.e. a scanning device requests additional advertisement data) but it too has the same limitation above. Also iOS allows only 10 bytes for it and it is usable for *local name* only -- in foreground mode only. Talk of specifications!

One task that took my time was creating a parser for UUIDs in Android. I needed the convenience of passing around 16-bit or 32-bit shorter UUIDs and have them converted to their 128-bit equivalent. The framework has `ParcelUUID` class that's a wrapper around a `UUID`. I couldn't find a public native Android way to convert a these shorter UUID strings to their 128-bit equivalent of Bluetooth's base UUID and thus had to write up some simple bit shifting code to parse such. `CBUUID` in iOS luckily provides such functionality.

# Conclusion
This article has touched on some concepts on BLE is a non-comprehensive way but simple enough to understand my take on BLE as the Contact Tracing solution. Exhaustive explanations and code samples can be found on the official Bluetooth website and respective platform documentation linked below.

With BLE, I'm closer to fulfill my requirements for Contact Tracing app -- sending anonymous tokens to nearby devices on a backgrounded app. However, the two pair roles *Broadcaster/Observer* don't fit the bill. Trial 3 could be my solution. Let's chat about it [Part 3](https://charlesmuchene.hashnode.dev/contact-tracing-part-3-ck93on13n03tv7us197iqj8d1).

> 
Special thanks to [Mohammad Afaneh](https://twitter.com/m_afaneh) for his crash course on BLE.

# References
- 
M. Afaneh's [NovelBits](https://www.novelbits.io/) has a 7 day BLE course via mail
- 
Ellisys bluetooth [video series](https://youtu.be/eZGixQzBo7Y)
- 
Bluetooth official [website](https://www.bluetooth.com/)
- 
Apple's [Core Bluetooth Framework](https://developer.apple.com/documentation/corebluetooth)
- 
Android's BLE [overview](https://developer.android.com/guide/topics/connectivity/bluetooth-le) and [more](https://source.android.com/devices/bluetooth) docs
- 
Microchip [BLE help](https://microchipdeveloper.com/wireless:ble-gap-roles)

# Update
Apple & Google have [collaborated](https://www.apple.com/covid19/contacttracing) to provide a [Contact Tracing Bluetooth specification](https://covid19-static.cdn-apple.com/applications/covid19/current/static/contact-tracing/pdf/ContactTracing-BluetoothSpecificationv1.1.pdf) support on their platforms.
