Bluetooth Low Energy (BLE) 4.0 support with Android 4.3 on Galaxy Nexus
Preface
As of December 2012, I’ve replaced my good old Nexus S with a newer Nexus device - the Galaxy Nexus. I’ve written a little about the device in the previous post already, but in summary it was a pretty good upgrade over the aging Nexus S, who also stopped receiving Android updates and was stuck with Android 4.1.2 Jelly Bean.
When Google demonstrated Android 4.3 Jelly Bean1 at Google I/O, one of the most expected changes was inclusion of platform support for BLE
, short for Bluetooth Low Energy
standard, also known as Bluetooth Smart
2. It’s known for much better battery efficiency over the previous Bluetooth 3.0 standard and more and more devices have started supporting it. It was a missing piece to bring more accessories to the Android platform.
Galaxy Nexus did receive the Android 4.3 update, but BLE
wasn’t advertised as supported as to our suprise. Here was a point when quite some different people started researching, including myself.
Research
This time we had to also make sure the hardware in the Galaxy Nexus was actually capable of working with BLE
standard, because without that any software changes would be irrelevant. That meant the chip inside would need to support Bluetooth 4.0
.
Hardware support
A great resource for hardware research is the site called ifixit.com. They offer great high resolution photos and documentation on dissasembly of electronical devices - so called teardowns.
I’ve looked up the Galaxy Nexus teardown and started looking for the Bluetooth module vendor and model number. Here on step 12 it was describing a Samsung SWB-B42 BT 4.0 Dual Band Wlan FM Tx/Rx
module, which apparently as by Chipworks
housed a Broadcom BCM4330
die inside.
A search engine query later, I stumbled upon Broadcom
official site and a complete description of the device. It clearly stated that it supports Bluetooth 4.0+HS
, which meant the Galaxy Nexus was fine regarding hardware support. Another proof was that same hardware chip was in Google Glass, which had official support of BLE
3.
Software support
If hardware was fine, the missing piece just had to be in software. There were quite some of us in a custom ROM
forum thread by Carlos_Manuel
on xda-developers who were looking for answers and collaborating on findings and discussing different possibilities. User andQlimax
found out that Google initially supported BLE
for the Galaxy Nexus in their Android source code, but reverted the commits based on a internal bug code. Both commits can be seen here and here.
This actually was a positive find, because we started speculating that there might be a chance of reverting those commits and bringing back the BLE
support in our custom builds. There was also a problem with testing the builds, since no one had any BLE
accessories to test on.
I wrote a quick Android app to check for BLE
system support on a device. It was based on the official Android Developers suggestion how to check for support when including it in own apps. The app named BLECheck
is posted on GitHub on here. It contains a single button which runs a system command via PackageManager
and displays a Toast
with the result message.
public void onClick(View view) {
// Use this check to determine whether BLE is supported on the device. Then
// you can selectively disable BLE-related features.
Context ctx = getApplicationContext();
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
Toast.makeText(ctx, R.string.ble_not_supported, Toast.LENGTH_SHORT).show();
}
else Toast.makeText(ctx, R.string.ble_supported, Toast.LENGTH_SHORT).show();
}
This wasn’t a complete check, because it only checked for a certain permission file android.hardware.bluetooth_le.xml
, which could be manually flashed by a flashable .zip anytime. The BLECheck
would then be positive, but it still wouldn’t bring the software support of BLE
. There were various speculations where the changes could be, perhaps even in the kernel.
Then suddenly a GitHub user manuel naranjo
found that the candidate commits above were correct and also applied for the Nexus 7 tablet. He reverted the commit seen here. First change was in file bluetooth/bdroid_buildcfg.h
.
@@ -27,7 +27,5 @@
#define BTIF_HF_SERVICES (BTA_HSP_SERVICE_MASK)
#define BTIF_HF_SERVICE_NAMES { BTIF_HSAG_SERVICE_NAME }
#define PAN_NAP_DISABLED TRUE
-#define BLE_INCLUDED FALSE
-#define BTA_GATT_INCLUDED FALSE
-#define SMP_INCLUDED FALSE
+
#endif
Second change was in device-common.mk
.
@@ -58,7 +58,8 @@ PRODUCT_COPY_FILES += \
frameworks/native/data/etc/android.hardware.touchscreen.multitouch.jazzhand.xml:system/etc/permissions/android.hardware.touchscreen.multitouch.jazzhand.xml \
frameworks/native/data/etc/android.software.sip.voip.xml:system/etc/permissions/android.software.sip.voip.xml \
frameworks/native/data/etc/android.hardware.usb.host.xml:system/etc/permissions/android.hardware.usb.host.xml \
- frameworks/native/data/etc/android.hardware.usb.accessory.xml:system/etc/permissions/android.hardware.usb.accessory.xml
+ frameworks/native/data/etc/android.hardware.usb.accessory.xml:system/etc/permissions/android.hardware.usb.accessory.xml \
+ frameworks/native/data/etc/android.hardware.bluetooth_le.xml:system/etc/permissions/android.hardware.bluetooth_le.xml
PRODUCT_COPY_FILES += \
device/asus/grouper/elan-touchscreen.idc:system/usr/idc/elan-touchscreen.idc \
He also confirmed those changes working on his Nexus 7 tablet, so all that we needed to do now was adapting the changes for the Galaxy Nexus build. Carlos_Manuel
did it and built a testing version of his ROM and then after couple days of waiting for someone to try it out, user edikat
confirmed it working with a Polar H7 BLE
heart rate monitor.
While all was set with the custom ROM
, I wanted to use the same modification on a stock Google factory image as well, since this would reach far more users. It was time again to download the source code, modify and build it.
Building the modification
The steps were repeated over and over again in the previous post, only difference was now to download the Android 4.3 Jelly Bean branch.
We create a directory where we’ll download the source to, name it whatever you want.
$ mkdir WORKING_DIRECTORY
$ cd WORKING_DIRECTORY
Now we run repo init
to initialize the repository with the source code for Android 4.3 branch.
$ repo init -u https://android.googlesource.com/platform/manifest -b android-4.3_r1
After that we continue with repo sync
etc., as described in above older post. We also need to make one initial full build of the system before making any source code changes.
We need to make the changes as seen in above commits. The two files are in /device/samsung/maguro/
for Galaxy Nexus. Then we rebuild the ROM again. New rebuilt modules is ready in system/lib/hw/
, named bluetooth.default.so
. and system/lib/
with libbt-hci.so
and libbt-utils.so
. We also need the new permission file called android.hardware.bluetooth_le.xml
, which resides in system/etc/permissions/
.
Making it ready to flash
As per previous post, making a flashable .zip is the most convenient way to distribute new modifications.
Adding .apks to a .zip file like this is easily done with an archiver software like WinRAR or similar. Here’s the structure for the BLE
modification
├── system/
| ├── lib/ # folder where the .apk will be flashed to /system/framework
| ├── hw/
| ├── bluetooth.default.so # new modules with BLE support
| ├── libbt-hci.so
| ├── libbt-utils.so
| ├── permissions/
| ├── android.hardware.bluetooth_le.xml # .xml file with the added BLE permission
├── META-INF/
| ├── com/
├── google/
├── android/
├── updater-script # script where you declare how the .zip should operate
├── update-binary # update binary compatible with the signature, it's reusable
| ├── CERT.RSA # signature files which
| ├── CERT.SF # are reusable
| └── MANIFEST.MF # in every .zip
This is the the basic structure of all flashable .zip files. The main gist is in the update-script
part, which is written in Edify
and we need to modify like this:
ui_print("4.3 BLE support for tuna");
show_progress(0.500000, 0);
ui_print("Copying files");
run_program("/sbin/busybox", "mount", "/system");
package_extract_dir("system", "/system");
unmount("/system");
ui_print("Finishing Update");
show_progress(0.100000, 0);
Script simply overwrites previous files with the modified ones.
Conclusion
Quickly after the change was found, there was already a user commit for the most popular custom ROM
called CyanogenMod
which enabled the same feature for supported devices. It has shown how fast the community heard about the findings and the result was spreading out.
I’ve posted my modification for the stock Google factory image on xda-developers thread. It was also mentioned in an article, section Bluetooth 4.0
about Android 4.3 Jelly Bean on technology website Ars Technica, which was quite an exciting thing to see.
Surprisingly I got a pretty good offer to sell the Galaxy Nexus by the end of August 2013, so I wasn’t interested in continuing the modification. There were interests by user wbedard
though who quickly caught up and continued with the support.