Antidote port to Android
This page refers to Android 2.3 port. The port to 4.0 (Ice Cream Sandwitch) can be found at Antidote port to Android ICS page.
Antidote itself has been ported to Android quite some time ago. Android.mk files are in source tree.
This page is about the necessary components around it that need to be updated in Android. These updated components are deemed UNSTABLE. (We hope that Android 4.0 will have everything bundled so we just need to copy Android into phone and use it.)
Running Antidote in an useful way, that is, using Bluetooth HDP and serving com.signove.healthd service over D-Bus implies adding and/or upgrading some core Android components, because the current open source version (Gingerbread) is quite "old". Namely, the following components are affected:
- Updating BlueZ to >= 4.90 (for HDP support)
- Updating D-Bus to 1.4.x (for HDP API file descriptor passing)
- Adding dbus-glib (for Antidote healthd service)
- Updating GLib to >= 2.26 (for dbus-glib and the more recent BlueZ)
- Enabling compilation of GObject and GIO in GLib source tree (for dbus-glib and healthd)
- Updating kernel to >= 2.6.36 or backport the Bluetooth stack (for ERTM support, needed by HDP)
- Adding Antidote to 'external' software built along with an image.
We expect that future releases of Android have more up-to-date components so the porting effort is smaller. Also, dbus-glib has been made obsolete, the alternative is using D-Bus API included with recent GIO, so hopefully dbus-glib can be removed from requirement list, once we cease to use it in Antidote itself.
Currently, Antidote for Android can be built along with a device image. This means following these instructions: http://source.android.com/source/initializing.html and having a suitable device, whose image can be built from open source. Nexus One and Nexus S are good. (We expect to use NDK in the future, not having to build an entire device image from scratch just to add a library. But for now, that's the way it is.)
It is important to make sure that your environment is capable of generating a good phone image, BEFORE trying to add Antidote to the mix. Once you did that, get the sources below.
Currently, Antidote has been tagged for "eng" and "debug" image type. Build process was tested only for Nexus S (Crespo, the normal one, not the 4G version), always choosing an "userdebug" image in lunch configuration script.
The big tar.gz file with updated user-level components plus Antidote can be found here: File:Android-userlevel-antidote.tar.gz
This tarball includes all sources, the folders containing 'old' versions, and two stray files of the build system that needed to be changed (build/core/pathmap.mk and build/core/prelink-linux-arm.map).
It also includes a slightly changed version of init.rc that gives permission 0666 to D-Bus socket, so the health service can be run as non-root later.
Unpacking it onto environment's base folder, make clean and 'make' should be enough to generate an image with Antidote. If you want to get the latest Antidote, get patches from gingerbread branch, since master branch contains ICS files already:
cd external/bluetooth/antidote git pull origin gingerbread
Every subfolder, like external/dbus, external/bluetooth/bluez etc. is a separate Git repository. Third-party software like D-Bus, GLib and BlueZ was downloaded in tar.gz. form, added in Git with one big commit, and additional files and changes necessary to compile under Android have been stored on subsequent commits (so hopefully future updates of the same software will be much easier).
You don't need to cope with each subfolder while building an image, but version control is in place to distinguish clearly stock code from porting changes.
If it builds ok, it is not over yet! You need an updated kernel too.
You can test Antidote without having the updated Bluetooth kernel, by running the test agent and test manager. They connect to each other via TCP/IP, to they run regardless of BlueZ, Glib etc.
(in PC) $ adb shell (in phone) $ su # cd /data # mkdir test # cd /data/test # export TMPDIR=/data/test # /system/bin/ieee_manager --tcp
Open another shell and do the same, but call "ieee_agent --tcp". They should communicate. Agent exits while manager continues to run (it exits after 3 agent connections.)
It is possible to copy just the executables (/system/bin/ieee_*) to a phone (including non-Nexus) using "adb push" (no need to replace the whole image).
I have done that myself with my HTC Desire for a quick test, and programs ran normally (and my Desire ran Frodo at that time).
When you set up the image build environment, kernel tree does not come along; image gets some precooked kernel image. So you need to set up the kernel environment yourself.
Compiling custom kernel for Nexus S
Assuming that one has a full image build enviroment as described in http://source.android.com/source/initializing.html, and tested it in a Nexus S phone successfully, compiling a kernel is not incredibly difficult. The following instructions are a compilation of any number of tutorials about the subject.
git clone git://android.git.kernel.org/kernel/samsung.git cd samsung make ARCH=arm clean make ARCH=arm herring_defconfig make -j4 ARCH=arm CROSS_COMPILE=arm-eabi-
Some failure (not finding arm-eabi-gcc) means that environment is not setup with envsetup.sh/lunch. Do this as source.android.com URL describes and cross-compiliation will be ok.
Copy originally generated ramdisk from build path:
cp ../out/target/product/crespo/ramdisk.img ..
Generate new boot.img with new kernel
mkbootimg --kernel arch/arm/boot/zImage --base 0x30000000 --pagesize 4096 \ --ramdisk ../ramdisk.img --cmdline 'no_console_suspend=1 console=null' \ -o ../boot.img cd ..
NOTE: omitting the --cmdline will break Bluetooth, don't know the reason.
Test new kernel with
fastboot boot boot.img
It should boot normally, though WiFi will not work because module needs to be copied to filesystem. If it booted ok, you can copy the module into place using adb:
cd samsung/ cd drivers/net/wireless/bcm4329/ adb root adb remount adb push bcm4329.ko /system/modules
Reboot and test WiFi and BT. If everything is OK, flash the boot image definitively:
fastboot flash boot boot.img
Backporting newer Bluetooth stack
Since we want Bluetooth with ERTM, but there seems to be no kernel more recent than 2.6.35 for nexus S, I tried a backport from 184.108.40.206. It is a version where ERTM worked stable and it is 'near' 2.6.35 so no need to cope with more fundamental changes in backport.
Backport tarball: File:Kernel-samsung-backported-bt.tar.gz
I just copied the net/bluetooth/* source (including subdirs) and include/net/bluetooth/* headers from 2.6.36 to samsung tree, and repeated the recompilation/testing/flashing/copying WIFi driver procedure.
Seems to be stable. (Be warned that Bluetooth ERTM support matured (and lots of bugs have been fixed) since kernel 2.6.36. The ideal solution would be to upgrade to a real recent kernel like 2.6.38 or better.)
Running the healthd service
Finally you can run healthd and connect Bluetooth devices. (Tested with Nonin 9650 oximeter and Nexus S). Enable Bluetooth, pair the health device. Then run healthd as shown below and connect the device.
(in PC) $ adb shell (in phone) $ su # cd /data # mkdir test # cd /data/test # export TMPDIR=/data/test # /system/bin/healthd --auto
If it works, you can test whether the service run as non-root. Let's suppose that AntidoteClient application is installed (we will talk about that below), and it was assigned the user "app_34". We will use the app's folder to test non-root running:
(in PC) $ adb shell (in phone) $ su # su app_34 $ cd /data/data/com.signove.oss.antidoteclient $ export TMPDIR=$(pwd) $ /system/bin/healthd --auto
If the init.rc is right and boot.img has been flashed, it should run correctly. If it does not, you can set socket permissions manually (as root inside adb shell, of course):
# chmod 666 /dev/socket/dbus
If this permission was the problem, the service should run then. Note that this permission change only last until phone is rebooted. To make it permanent, you need to change init.rc and reflash boot.img which contains this file. (Antidote source package brings this modified file along, so there should be no problems if you flashed correctly.)
Please note that app_34 is the user in my example. It could be any other in your own phone.
End-to-end in Android
This example application starts healthd in background, and displays data from sensors.
Old version pictures
In the old version, we still needed to run healthd manually in shell, that's why there are pictures of terminal screen.
In order to show an "end-to-end" example in phone using healthd service, we have a problem: there are no D-Bus bindings to Java. Since dbus is heavily patched in Android, it is uncertain whether java-dbus would work.
In order to solve this, we have added a very simple, TCP-based protocol to healthd. It is served (instead of D-Bus service) if you run it with --tcp parameter:
(in PC) $ adb shell (in phone) $ su # cd /data # mkdir test # cd /data/test # export TMPDIR=/data/test # /system/bin/healthd --tcp
You can test that either connecting to port 9005 of phone's IP address.
Since AntidoteClient runs healthd as a child process and non-root, make sure healthd is running well as non-root in --auto mode (see earlier topic).
The "ps" command is your friend, you can see whether healthd is being run when AntidoteClient is on foreground.
You can also telnet to port 9005 when healthd is auto-loaded by AntidoteClient, at the same time AntidoteClient is shown in foreground. The TCP service in port 9005 is multi-client (it broadcasts all events to all clients).