Bluetooth Command Queuing for Android

Bluetooth 4 (aka BLE – Bluetooth Low Energy) on Android has some important limitations that need to be addressed in apps that need a high degree of user interactivity with a Bluetooth device. Very quickly when you set out to write such an app you’ll come to realize that you’ll need some sort of Bluetooth command queuing system.

First, a little background. Recently I had to develop a client app that would act as a control panel to a prototype hardware device using BLE. This app had to allow commands to be sent to the device on-demand from the user through a UI with a lot of “moving parts”. I’ve worked with synchronizing fitness wearables, but this was a whole different ball game! Fitness wearables tend to be a simple sync and download mechanism, but for this new device, user’s could tap around a set of controls, with each interaction issuing a command (or even a set of commands) to a device. Add to this the complexity that the app would also need to receive ad-hoc notifications at any time from the device, and would also have to send periodic timed commands in the background!

Since Android 4.3 the android.bluetooth classes support BLE, but I came to realize that they would not be enough this time to deal with the complexity alone. It’s because Android’s underlying BLE implementation is a bit quirky. The infamous google issue 58381 illustrates. Other helpful nuggets of information can be gleaned at this stack overflow post here. The critical piece of information from user OneWorld in that posting is: “Gatt always can process one command at a time. If several commands get called short after another, the first one gets cancelled due to the synchronous nature of the gatt implementation.”

I’ve come up against this problem myself. You can issue multiple BLE commands ad-hoc from a multi-threaded app, but BLE won’t respond very well. If you issue a second command before it has a chance to deal with the previous one, the BLE stack can (particularly on Android 4.3) get into a state where it won’t even respond anymore and even require a manual user restart of Bluetooth! Not ideal. You can delay before sending a second command, but to cover all possibilities in hardware and BLE conditions, this introduces an unnecessary delay into every command. Fortunately, in my app, I could assume (like most BLE applications) that the device responds to a command. So I could send the next command immediately after receiving the command response back (via a BLE notification). To create a robust, stable, experience for the user, I had to implement a queuing system layer on top of Android’s bluetooth classes so that the Android BLE stack was assured of only having to deal with one command (or event) at a time.

bluetoothqueue_screenshot
Let’s look at the details of implementing the command queue.
(The code for a sample app showing the concept is in my github.)

The first thing we need is an object to represent a command. This can be extended in subclasses to do any kind of fancy thing you want, e.g. perform multiple writes to different characteristics.
For this example, we’ll just have a simple command that reads the device’s serial number. To see the idea of the queue in action the DelayCommand will also pause briefly before doing the read, so that you can see commands backing-up in the queue.

public class DelayCommand extends BluetoothCommand {
    public void execute(BluetoothGatt gatt){
        try {
            synchronized (Thread.currentThread()) {
                Thread.currentThread().wait(500);
            }
        }catch(InterruptedException e){
            //ignore
        }

        //As an example, read from serial number characteristic
        gatt.readCharacteristic(
            gatt.getService(com.movisens.smartgattlib.Service.DEVICE_INFORMATION)
                .getCharacteristic(Characteristic.SERIAL_NUMBER_STRING));
    }
}

The main activity can create a command object and add it to the queue by calling the service’s method queueCommand, and that’s where we really see the queue in-action:

synchronized (mCommandQueue) {
            mCommandQueue.add(command);  //Add to end of stack
            //...
            ExecuteCommandRunnable runnable = new ExecuteCommandRunnable(command);
            mCommandExecutor.execute(runnable);
        }

The first thing to note is the mCommandQueue is simply a Java LinkedList, which works as a FIFO queue.

When the command is added to the queue a runnable is also created that actually executes the command. These runnables are executed on a Single Thread Executor to ensure only one is run at a time. Here’s the Runnable code that actually does the work of executing the command:

    class ExecuteCommandRunnable implements Runnable{

        BluetoothCommand mCommand;

        public ExecuteCommandRunnable(BluetoothCommand command) {
            mCommand = command;
        }

        @Override
        public void run() {
            //Acquire semaphore lock to ensure no other operations can run until this one completed
            mCommandLock.acquireUninterruptibly();
            //Tell the command to start itself.
            mCommand.execute(mBluetoothGatt);
        }
    };

You might think it’s enough to just run a queue of runnables off a single thread to implement the queue, right? Wrong. Here’s why.
When mCommand.execute is called, it starts the bluetooth read and returns immmediately. This would cause the next runnable
to run its command. Remember what I said about Android BLE not liking when you issue a new command if the first hasn’t responded yet?
So here’s the trick: we also need a lock that will prevent the next runnable from executing it’s command until the previous command
has a response. This is done in the BLE GattCallback, where the characteristic read response actually comes back to the caller:


    public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
        super.onCharacteristicRead(gatt, characteristic, status);
        if(characteristic.getUuid().equals(Characteristic.SERIAL_NUMBER_STRING)){
            //... Send string response to listener here..
            dequeueCommand();
        }
    }

    protected void dequeueCommand(){
        mCommandQueue.pop();
        //...
        mCommandLock.release();
    }

DequeueCommand releases the lock, and the next runnable then waiting to acquire the lock can run it’s own command.
The lock is just a semaphore with a limit of 1 permit:

Semaphore mCommandLock = new Semaphore(1,true);

And there you have it – the beginnings of a BLE command queue.

A more complete implementation has to allow for other important cases, such as the device failing to respond to the command at all ( – quick answer: implement a time-out to release the command lock and continue to the next command – ), but that’s for another post!

Android OpenGLES Water Caustics

I like water caustics – those sinuous reflections you get from the surface of water. I’ve always wanted a good “water pool” type animated background. The apps on the store don’t quite do what I’ve been looking for, so I wrote one.

Initially, I dipped back into 3D programming and tried to see if they could be done in real-time on the device. Water Caustics are notorious for being computationally intensive to get looking right, so I was sceptical it could be done on a mobile device, and I was right to be! Even using native c++ and the android NDK, Fast fourier transforms for smoothing the wave surface and OpenGL for sunlight ray rendering (using the fastest caustics mathematical algorithm I could find), the result is just too disappointing at 25 fps.

caustics_test

Mobile processors are good, but they are not that good yet. To get a real-time effect without jitters doesn’t give good enough detail on my HTC Desire – it just looks like a smoke filter effect. Not to mention the drain on the battery and other processes. Still, it was fun to get back to OpenGL 3D rendering again.

In the end, the best solution was to let a desktop app do the hardwork of rendering a set of tileable, loopable animation frames. I still use OpenGL and the NDK for the final live wallpaper app, but this time just to bitblit the frames onto the surface. It’s just about fast enough on my device and OS and looks pretty cool in motion. You’ll just have to believe me! (or else download it from my apps page).

caustics_wallpaper

Android HttpClient Proxy Errors

Coding HTTP interaction is a common task in mobile app development. It can be one of the trickiest if not done right. There’s a lot of edge cases to consider in the HTTP protocols –  different versions of the protocol, different server implementations, firewalls and routers to consider, etc.

Blackberry developers had been hamstrung for years by the more rudimentary net.rim.device.api.io.http package, or even plain old java URLConnection, and have had to deal with coding more of the HTTP protocol implementation themselves or else bloating the size of their apps by including a third-party HTTP library. (There’s also the issues of routing through BES/BIS and MDS to contend with!).

The Apache HttpComponents suite is a great toolset for handling all the common http interactions in Java apps, and a lot of the more specialized ones too. It can even tackle WebDAV, Authentication extensions, and HTTPS connections. Thankfully, Android had the Apache HttpComponents included in the SDK by default since day one, so there’s no need to bloat out the size of your app with extra jars if you want the convenience of HttpClient.

The classic tradeoff in using any library is that, while it may save time and cost, it can also be a ‘black box’ that obscures some of the details and makes it harder to track down and fix problems. No such problems with HttpClient though because it is well-designed (i.e. extensible) and is open source.

Here’s an example. I had an Android app interacting perfectly well with a test server, then switched it over to access Yahoo’s web server on the internet. Instant problem: HTTP 502 Proxy Error.

So why didn’t it work? In the end, the solution is simple (but finding it was a little tricky). This is where the design of the HttpComponents library really helped. HttpClient allows logging of all HTTP chatter through the standard Java logging api. Here’s an example of setting-up logging to the standard Java error console.

System.setProperty("org.apache.commons.logging.Log", "org.apache.commons.logging.impl.SimpleLog");
System.setProperty("org.apache.commons.logging.simplelog.defaultlog","trace"); 
System.setProperty("org.apache.commons.logging.simplelog.showdatetime", "true"); 
System.setProperty("org.apache.commons.logging.simplelog.log.httpclient.wire.header", "trace"); 
System.setProperty("org.apache.commons.logging.simplelog.log.org.apache.commons.httpclient", "trace");

Note: I had to do this with a java console app because commons logging won’t configure in Android via the system properties – that’s a job for another day!
Here’s the trace it produced:

[DEBUG] headers - >> REPORT /dav/user/Calendar/MyCal/ HTTP/1.1
[DEBUG] headers - >> Depth: 1
[DEBUG] headers - >> Authorization: Basic [redacted]
[DEBUG] headers - >> Content-Type: application/xml; charset="UTF-8"
[DEBUG] headers - >> Content-Length: 296
[DEBUG] headers - >> Host: caldav.calendar.yahoo.com
[DEBUG] headers - >> Connection: Keep-Alive
[DEBUG] headers - >> Expect: 100-Continue
[DEBUG] wire - >> "<C:calendar-query xmlns:D="DAV:" ...
[DEBUG] wire - << HTTP/1.1 502 Proxy Error[EOL]"

HttpClient was sending the request ok, but the server was immediately returning the 502 Proxy Error and no data. The request headers show that HttpClient was sending an Expect: 100-Continue header. (The Expect-Continue mechanism was introduced for HTTP 1.1 [RFC 2616] to make HTTP interaction more efficient).

Proxy Servers are very common on the internet. They buffer and insulate hosted environments from attack, balance loads, etc. The thing is – a proxy server uses the lowest common denominator of the HTTP protocols (HTTP 1.0) because it can never assume the client understands HTTP 1.1. Since Expect-Continue is a mechanism of the 1.1 HTTP protocol, a proxy server rejects it, even if the web server behind it can handle HTTP 1.1. It’s to do with authentication (which I won’t get into here). For this, it was enough to realise that the third-party server must have been using a proxy server.

One solution to this is to force HttpClient to use HTTP 1.0, but then you lose all the performance benefits of HTTP 1.1, which are especially important on a mobile device.

Yet again the excellent design of HttpClient comes to the rescue though. There is a configuration that you can set to prevent HttpClient from sending the Expect-Continue header over a HTTP 1.1 connection:

HttpClient httpclient = new HttpClient();
httpclient.getParams().setParameter("http.protocol.expect-continue", false);

It worked! HttpClient is great.