Tuesday, January 29, 2008

Hacking into Android's Bluetooth support

I have been mentioning that wicked Bluetooth service for two posts but eventually something else was more interesting. Well, finding something more interesting was easy because it turned out pretty soon that the Bluetooth support in m3-rc37a version of the emulator is half-ready at best. I cannot be sure but it seems that the hcid daemon on which Android's Bluez port is based is completely missing or at least is not launched properly along with other system services.

Is there a point then to deal with Bluetooth given the current state of the emulator? IMHO, yes, because when the shiny new version of the emulator comes out, applications will be ready to run. At the present state of affairs this approach means that we have to live with a bit (lot!) of hacking.

For the moment, I was interested in the discovery process. Discovery in the present implementation does not work but that did not prevent me simulating it. By taking apart org.bluez.IBluetoothService and android.server.BluetoothService classes with the jad tool, it quickly became evident that the discovery process is based on 4 intent messages.

org.bluez.intent.action.REMOTE_DEVICE_FOUND - delivered when one device is discovered. It has 3 parameters in the Intent's Bundle: "address" (String) is the Bluetooth address of the device, "class" (Integer) is the class of the Bluetooth device and "rssi" (Short) is the Received Signal Strength Indicator.

org.bluez.intent.action.REMOTE_NAME_UPDATED - delivered when the user-friendly name of one device is discovered. This message follows an earlier REMOTE_DEVICE_FOUND message and carries the user-friendly name ("name" (String)) along with the Bluetooth address ("address" (String)).

The discovery simulator itself is an interesting piece of software because of some common Android programming tricks it employs. The discovery simulator is located in the BtDetectSimulatorService class that the main activity launches with a startService call (it is therefore the other type of service, not the one seen at the service invocation entry). Normally, the discovery would just be started with a method call on org.bluez.IBluetoothService but the implementation is not that ready. The service abuses the half-implemented Bluetooth classes (like the android.server.BluetoothService class, don't ever do what I did here!), starts the Bluetooth service and sends out intent messages. These intent messages are captured by an intent receiver (BtIntentReceiver) and are used to update the UI of the main activity.

Two small details are interesting here. The intent receiver and the main activity call each other like ordinary Java objects. The code exploits the fact that the main activity is a singleton and just connects the activity and the intent receiver instances by Java references. This is possible because these two entities are part of the same package, hence they run in the same VM instance. Here is the proof (619 is the PID of the VM process):

The other interesting bit is the way BtDetectSimulatorService delivers the events. There is a delay among the intent broadcasts (Bluetooth discovery may be a lengthy process). This delay could not be coded with the good old Thread.sleep call in onStart method because onStart would have run too long and the Android application manager would kill the process. In addition, no broadcasts would be delivered until onStart ends which means that all the broadcasts would be delivered at once. Instead, observe how an android.os.Handler instance is used to schedule Runnable tasks after a certain delay.

And at last, the fun part. The image below shows, how Android's own Phone application crashes terribly when our application stops the Bluetooth service (it was us who started it, so we stop it nicely). That characterizes pretty much the readiness of the Bluetooth support in the current emulator.

32 comments:

I searched on web and found that at present android is missing bluetooth API, is it true? is there any way for the apps to use bluetooth feature, my app needs to communicate with other android mobiles over bluetooth. if you can give me some hint or links to existing resources, that would be very helpful.

I'm interested in investigating the Bluetooth stack to diagnose problems with A2DP. My BackBeat 906 headphones perform porrly with my G1, but the audio adapter that comes with them enjoy excellent range. It's the G1, and I'm researching the Bluetooth chipset, radios, antenna, and such. Any advice, other than 'give it up'?

As you hack around, can you please fix the voice activation in Android? The new Droid is out with Android 2.0 and it does not respond to the bluetooth green button long press which sends the AT+BVRA=1. The phone gives a negative acknowledgment of it. This is a safety critical feature and people are giving the phone because because it does not work. Looking in the phone log I can see this:11-15 15:22:50.061 I/Bluetooth AT sent( 1081): +CIEV: 2,1 11-15 15:22:50.061 I/Bluetooth AT sent( 1081): +CIEV: 3,011-15 15:22:50.085 I/bluetooth_ScoSocket.cpp( 1081): Connecting to socket11-15 15:22:50.261 I/bluetooth_ScoSocket.cpp( 1081): SCO socket connected (outgoing)11-15 15:22:51.022 I/Bluetooth AT recv( 1081): AT+CHUP11-15 15:22:51.022 I/Bluetooth AT sent( 1081): OK11-15 15:22:51.030 I/Bluetooth AT sent( 1081): +CIEV: 2,011-15 15:23:55.983 I/Bluetooth AT sent( 1081): +CIEV: 5,411-15 15:23:56.280 D/GTalkService( 1087): [RosterMgr] roster not modified11-15 15:23:56.397 D/GTalkService( 1087): [OtrMgr] OTR not modified

not sure if it's related or not. That is a small portion of the log of course.

Voice dialing is disabled in the core OS. You would be unable to enable it without flashing your handset with new firmware.

I found this comment in the Android source, simply changing this flag to false should enable the voice dialer as the support is included in their implementation of the HFP

android.bluetooth.BluetoothHeadset line 112 /** The voice dialer 'works' but the user experience is poor. The voice * recognizer has trouble dealing with the 8kHz SCO signal, and it still * requires visual confirmation. Disable for cupcake. */ public static final boolean DISABLE_BT_VOICE_DIALING = true;

Yeah, I saw that. Much better to flash something more capable than rely on the lame voice dialer, tho 1.6 seems to be working tolerably. It just wants to match the contact to the voice. Doesn't always result in what I want.

Hi Rick, did you have any luck with those headphones? I have the 903's and android on a Galaxy and have seen various posts about changing the audio.conf file to maybe resolve the connection issue. Did you tey anything to resolve this yet?

Ok thanks, I've seen these ones so I may try them out: Motorola HT820 Bluetooth Stereo Headphones. I thought it was a general Bluetooth issue for android 1.5 but perhaps I should trial & error some different devices before I try and change the configuration of the phone. The issue for us Galaxy owners at present is there is no sight of an upgrade to 1.6 or even 2 (eclair) from Samsung which is obviously disappointing. Thanks again.

i m using samsung galaxy and i want to transfer files thro bluetooth. samsung galaxy is of android 1.5. can u please suggest me the way to achieve it. as i'm new to this fone and OS, i'm struggling to do these.

I'm not hearing consistent results getting the Bluetooth File Tranfer app (at http://www.androlib.com/android.application.it-medieval-blueftp-qAFE.aspx) to work. Apparently some releases and some phones don't have the various Bluetooth file protocols available (OPP and FTP I know it uses).

FWIW, if you had searched the Market for 'File Transfer', you would have gotten this app as your first hit. Probably.the help file points out some features require root, which if you have a standard release of Android, you do NOT have.

There already is a Bluetooth Keyboard Driver for Android, that works with the HID Profile. The good thing is no root required - works on any Android phone.

See:http://teksoftco.com/news/10_02_26_biandroid.jpg

[quote=Teksoft]Despite the current Bluetooth limitations in the Google Android SDK, in early 2009 we've developed a first version of our Bluetooth Keyboard driver for Android. It was an OEM Project targetting a major hardware manufacturer, and it wasn't released to end users. The initial version also required root priviledges, so it needed extra skills to be used on normal Android devices.

Almost a year after, some considerable development progress has been made and we're now announcing the Teksoft BlueInput for Android, a Bluetooth Driver that allows you to connect a Bluetooth Keyboard to your mobile device for increased typing speed, more productivity, and a new feel of comfort gained by using high tech all arround you.

BlueInput is an advanced HID driver that totally transforms your Android into the perfect Mobile office solution by offering easy Bluetooth connectivity to Bluetooth Keyboards. And it is ready and waiting for you to try it right away. [/quote]

This application is not free, but the trial version can be used as much as you want, but has a limitation on using the SPACE and ENTER keys.

Hey,I saw your blog about using Android's Bluetooth and I was wondering if you could do a new tutorial to customize the bluetooth service for the Nexus One. I hope you could find a way that doesn't require the user to keep clicking Discoverable mode on every 300 seconds... Thanks! Your blogs are very helpful!

I don't have a Nexus One, but forcing you to click Discoverable also is in the G1 Cupcake release. I don't see a problem, as everything I need to pair with finds me much faster than that. Is it possible Google saw this as a security issue, and made you keep clicking instead of leaving it out there giving up your identity continuously?

@RickBlake>> I don't see a problemResearch which examines distance between study/non-study participants - ie, medical research - needs Bluetooth to be discoverable indefinitely. Limiting it to 300 seconds - without a way of turning it back on in the background - greatly limits the type of research which can be done on this platform.

This feature/oversight greatly impedes my own research. Does anyone know of a workaround?

how is this study setup? why do you require one device to be in discoverable mode all the time for this research?Are you monitoring how random phones attach to some bluetooth service your android phone is advertising?

If not random and you have a known subset of people connecting to the phone presumably you can have them pair with the device at the beginning of the study and then there is no issue?

Wow, this seems at par with some similar iphone games. Paricularly liked the secondary features using the tilting, thats awesome. Got a doubt if there is a little bit of slowness in response for the Nexus when compared to iphone? For the touch and tile responses, seems not as smooth as the iphone..or is it just me.

I discovered an awesome laser projection keyboard that works with Android Phones. It is manufactured by Celluon and is called the CL850. The CL850 Bluetooth Keyboard driver is available on the Android Market for download just in time for the holidays. More information is available at the following URL:http://www.greatwhitesoftware.com/dnn/CL850AndroidApplication/tabid/76/Default.aspx

About the blog

This blog is a personal diary about my adventures with the Google Android platform. I write it in the hope that others may find my experiences useful but please, beware. The blog is created as I gain experience about the platform myself so errors, omissions, etc. may be found in the entries.