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.DISCOVERY_STARTED - delivered when the discovery process starts.
  • 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)).
  • org.bluez.intent.action.DISCOVERY_COMPLETED - delivered when the discovery process finishes.
You can download the example program from here.

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):

D/BTINTENTRECEIVER( 619): org.bluez.intent.action.DISCOVERY_STARTED
D/BTDETECT( 619): Action = org.bluez.intent.action.DISCOVERY_STARTED


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:

Anonymous said...

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.

Thanks

Reece said...

Hey,

So I tried to get your program working by File > New Android Project > Create From Source (tried both 1.1 and 1.5) but am getting numerous errors.

Errors are here: http://tinyurl.com/lv9ewa

I'm sure it's something simple like naming the app wrong or one line of code or something in the manifest.

Gabor Paller said...

Reece, this post is of historic importance. This is neither 1.1, nor 1.5 but pre-0.9 and non-published API. It would be a small miracle if it still worked today.

Stefano Sanna said...

Hi.

If you are still interested in playing with Android & Bluetooth, you may try my experimental Bluetooth API, which supports device discovery and rfcomm client. Check it out at:

http://code.google.com/p/android-bluetooth/

Rick Blake said...

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'?

Unknown said...

Hi,

just back from the telco store with a shine new HTC Hero, with intend to write an Android App for connecting to Gryphon Bluetooth Barcode Reader

After reading the above comments I'm _so_ sorry not to have hit this blog sooner :(

Will me embarking on this endeavour fail miserably even before I've started?

Any experiences, links, well just about anything are much appreciated :)

Cheers,
Walther

Rick Blake said...

Probably not. You will do fine.

1. You will probably fairly close to plenty of objects to help with reception.

2. You will probably not be too far from the phone.

3. You have plausible deniability. Bluetooth is renown for range issues. Just deny.

Jim Roal said...

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,0
11-15 15:22:50.085 I/bluetooth_ScoSocket.cpp( 1081): Connecting to socket
11-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+CHUP
11-15 15:22:51.022 I/Bluetooth AT sent( 1081): OK
11-15 15:22:51.030 I/Bluetooth AT sent( 1081): +CIEV: 2,0
11-15 15:23:55.983 I/Bluetooth AT sent( 1081): +CIEV: 5,4
11-15 15:23:56.280 D/GTalkService( 1087): [RosterMgr] roster not modified
11-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.

Dek said...

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;

Rick Blake said...

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.

drwebb said...

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?

Anonymous said...

So far the 903s still perform poorly. My Motorola adapter works well, outstanding range.

drwebb said...

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.

Alb said...

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.

Rick Blake said...

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.

Unknown said...

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.

Source: http://www.teksoftco.com/index.php?section=blueinputandroid

Unknown said...

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!

AndroidTeam

Rick Blake said...

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?

Unknown said...

@RickBlake
>> I don't see a problem
Research 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?

Unknown said...

dilly I don't understand your issue.

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?

I'm almost positive i've missed something but thought i'd ask :)

Android said...

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.

Unknown said...

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

Unknown said...

Did anyone progress on the unlimited duration of Bluetooth Discovery?
It may seem weird to need the unlimited duration, but I need to at least test it for a project of mine, so any help is welcome.

kaminomoto said...

wow,,cool have you try to hack via bluetoth?

Vishal Rajpal said...

Helllo..
Can you tell me how to communicate betn 2 androidn devices using bluetooth

Vishal Rajpal said...
This comment has been removed by the author.
Anonymous said...

I've installed Android x86 on VirtualBox, configured LAN settings and now I can use virtual machine instead of native emulator.

But still have an issue: I cannot turn on Bluetooth from menu. When I start BluetoothChat app, it just says "Turning on bluetooth..." and does nothing.

I suppose that probably I must configure VirtualBox or/and configure Android from command line, but have no idea what changes should be done.

Rick Blake said...

If you don't have a Bluetooth device in your VM, nor an emulation, what did you expect it to do?

Elephant said...

How can I create Bluetooth device in my VM?

Anonymous said...

There is program, which fixes bluetooth connection problem on android market: https://market.android.com/details?id=com.vvmaster.android.bluetoothreconnector&feature=search_result

It's free and works on my Samsung Galaxy S

Rick Blake said...

That won't fix problems where the headset doesn't receive a signal. That's the root of ky complaint.

Anonymous said...

just another crap. . . zzzz . . . boring