In my last video tutorial on Bluetooth LE, we talked about some of the basics that came along with the introduction of this technology to the Android 4.3 APIs. With the release of Android 5.0 late last year, big changes have come to the Bluetooth LE landscape.
In this session, recorded at AnDevCon San Francisco, we see what has changed in the 5.0 release of Android.
One of the biggest complaints about the Android Bluetooth LE APIs is that they are unstable and oftentimes they don't support many of the standard communication types. What you may not realize is the underpinning reason for this started with the Android 4.2 release. You see, in early revisions of Android the entire Bluetooth stack was built upon BlueZ, the open source stack used in the Linux kernel. This stack is very mature and stable.
However, in the Android environment BlueZ came with a lot of baggage--the most notable of which is the GPL license that is attached to it. To avoid conflicts with the rest of the Apache-licensed Android stack, BlueZ was required to run in a separate process that interacted with a special daemon (bluetoothd) so it was properly isolated. In addition, BlueZ required an implementation of D-Bus (via dbus-daemon) to be in place for IPC, something Android doesn't otherwise implement. This was a lot of overhead to incur to work around a license problem.
To sidestep all this, in Android 4.2 Google replaced BlueZ in Android with Bluedroid, a completely new stack developed by Broadcom that was licensed under Apache to be more compatible with the rest of the stack. Without going into the major details of the differences between the two, I simply want to reiterate one thing…Bluedroid is a completely new stack, essentially untested in the wild. It has taken some time to bring the level of stability and maturity that Android had before.
…and all this happened just before Bluetooth LE came to the platform APIs.
Bluedroid continues to mature and stabilize; there were 565 commits to the bluedroid project alone from 4.4 -> 5.0, compared with 52 commits from 4.3 -> 4.4, and 47 commits from 4.2 -> 4.3 . This is an area of heavy activity within AOSP right now.
Along with bug fixes, Google introduced support for LE Peripheral and Broadcaster modes in applications. This comes along with new support for sending LE advertisements. Not all devices will support this new feature with the update, as Google has defined this as a HAL-enabled feature, which means manufacturer's must add a driver for it at the integration level. Developers should first check BluetoothAdapter.isMultipleAdvertisementSupported() on the device.
The APIs for scanning have also been improved. We now have proper builder classes for building scan requests (ScanSettings + ScanFilter) and analyzing scan results (ScanResult + ScanRecord)…no more parsing byte arrays manually! ScanFilter introduces a more robust filtering API which can filter on any scan parameter instead of just the advertised service UUIDs.
Along with these APIs, improvements have been made to reduce the effect of scanning on the device's battery. Scanning on Android 4.x was an operation that forced the device to stay awake (using a full wake lock), so scanning in the background was pretty much a non-starter. In Android 5.0, new low power settings for your scan allow an application to scan continuously in the background without undue battery drain.
Through use of the new filtering API, you can further reduce device wakeups by limiting the advertisements that get pushed up to the application layer. Scan results can also be batched and delivered in groups when a delay value is set on ScanSettings--again, reducing device wakeups if scanning in the background.
Some of these features (portions of filtering, and scan results batching) are also implemented at the HAL level, so some devices may not be able to take full advantage if the manufacturer didn't provide the driver support. The BluetoothAdapter.isOffloadedFilteringSupported() and BluetoothAdapter.isOffloadedScanBatchingSupported() APIs allow you to determine how power-efficient the device can be with your scan requests.
You can find the sample code demonstrated in the session video on GitHub.