Thursday, February 5, 2009

Asynchronous communication in Android

Old sins always come back to haunt. Once I wrote a blog post, shamelessly referring to a 2006 paper of mine. In that post, I praised the conformance of the Android system with regards to the requirements of the reflective middleware approach. I found that only one area was not covered appropriately, asynchronous communication. It could be then expected that when folks at Softwired ported their iBus//Mobile asynchronous communication framework to Android, they found me.

iBus//Mobile already supports a number of clients. For Java, there is J2SE, CDC and MIDP support, Android was just added to this list. Additionally, native clients like Windows CE and Symbian are also supported and all these clients are able to talk to each other using the iBus//Mobile queuing system. In Java, the access interface is the familiar JMS.

iBus//Mobile depends on a gateway on the network and each client talks to this gateway. Even if device-to-device communication is required, the data goes through the gateway. The protocol support is nicely done, the framework supports a bunch of protocols. Some are used in polling mode (e.g. HTTP), some of them, however, also work in push mode like the TCP or SMS bearers. In case of TCP, they maintain a TCP stream to the gateway, keep that stream alive with keepalive messages and push the device-bound messages over the gateway-device direction of this stream. The programmer has full control over the protocol selection. Also, there is pluggable encryption support.

Those who have not yet tried cannot even imagine, how time-consuming it can be to implement such a system. It sounds simple but when it comes to actually implement the communication between the client and the server parts, unpleasant surprises will pop up, e.g. about the differences of mobile networks with regards to timing, connection keepalive, etc.

How does iBus//Mobile compare to my dream system I envisioned in my paper? First, it is nicely componentized although not along the line of the Android component system. There is a pluggable protocol support which is a great feature, it is hard to survive without it in the mobile world. My dream system included protocol support for direct device-to-device communication (e.g. Bluetooth). This is missing in iBus//Mobile which may be due to their business requirements. I can imagine a creative usage of multiple protocols at the same time on the client side, e.g. falling back to SMS from TCP if packet data connection is not available or using SMS to trigger data push by e.g. HTTP to simulate a push bearer that can transfer large amount of data. I also find the relationship between queues and synchronization intriguing. iBus//Mobile uses a sliding window-based algorithm to ensure that there can be multiple queue items transmitted independently from each other at the same time. If off-line operation is a frequent requirement (e.g. the application puts large number of elements into the queue then connects to the server to deliver those elements), full-scale synchronization solution is more efficient.

But enough of the whining! Softwired provides a robust, field-tested solution to Android developers who need message queues. You'd better know about iBus//Mobile if you don't want to suffer in the weird world of mobile bearers, particularly in the push direction.

Tuesday, February 3, 2009

Optimized DEX files

One of the less publicized ability of the Dalvik virtual machine is that it is able to execute "optimized" DEX files (or ODEX files). "Optimizing" a DEX file speeds up its execution but also ties it to the hardware platform on which the optimization was performed. ODEX optimization relies on unsafe bytecode instructions. Unsafe instructions are much faster to execute, on the other hand, malicious use of these instructions can crash the virtual machine. Dalvik has an additional layer of security, process separation and file permissions of the underlying Linux platform so this price is not that high. It is important to note, however, that much of the security normally associated to the Java virtual machine e.g. in J2ME is now provided by the underlying Linux platform.

I remember the resistance when I proposed unsafe instruction for garbage collection performance optimization on mobile platforms. The critics argued that 1. the Java bytecode is not allowed to be modified and 2. the bytecode safety must be preserved at all costs. Seemingly, Dalvik designers have done away with both ortodoxies.

The optimization is carried out on the target platform, by the target platform's virtual machine. The command to invoke the optimizer is called dexopt. There is no point in invoking this command on the emulator as it would create an optimized DEX that can be executed only on the emulator. The most important transformations are the replacement of the method indexes with vtable indexes and the field indexes with memory offsets. So instead of invoking a method by name, it is invoked by vtable index using a set of special instructions not specified in the Dalvik instruction set.

For example:

invoke-virtual-quick {v1,v2},vtable #0x3b

(Note: if anyone reads this who is knowledgeable in the way the vtable index is computed, please, drop me a comment or mail :-))

Also, for fields:

iget-object-quick v0,v2,[obj+0x100]

The dedexer tool was updated and now provides a limited support for ODEX files. Sadly, I was not able to figure out, how to calculate method or field names out of vtable indexes and byte offsets which clearly limits the usefulness of the disassembled ODEX sources. When I was at it, I also implemented debug information processing that generates line number and local variable information like this:

.var 0 is intent Landroid/content/Intent; from l144ac to l144c8
const-class v3,com/android/vending/SubCategoryListActivity
const-string v2,"android.intent.action.VIEW"
.line 180

The Dalvik opcode list was also updated with the description of the "quick" instructions.