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 Smart2. 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.

Android 4.3 gives you a single, standard API for interacting with Bluetooth Smart devices (Photo Credit: developer.android.com).

Android 4.3 gives you a single, standard API for interacting with Bluetooth Smart devices (Photo Credit: developer.android.com).

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 BLE3.

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.