Android hacking – target N900 Maemo

As an happy owner of a Nokia N900, I am really disappointed it does not support JavaME applications. Really strange from Nokia which Symbian OS is a reference for Java mobile applications.
Indeed it is a real market trend: neither Apple nor Google choose JavaME despite its great specifications, security aspects and features (3D, positioning…). I guess the main reason was the royality fees to distribute JavaME to end-users.

So to get access to Android market applications, I have looked for a way to run the Dalvik virtual machine on stock Linux and then on the N900 Maemo system.

Since Canonical announces concerning a proof of concept of a running Android on Ubuntu, no news, no how-to, no patches published ! Even from the main author of this hack. Does Google disagree seing its open source system run elsewhere than dedicated devices ?

Of course, I am not interested in running Android in the qemu-based emulator for ARM image, which is so slow I do not understand how a developer may comfortablely test its applications except on a real device. In comparison, Nokia Maemo SDK is just perfect as the system and applications run native on Linux x86 platform.

Building Android for ARM is just piece of cake on a Linux x86 (in my case in a Debian Lenny 32 bits chroot) but it is less obvious when setting target to x86.

The main difficulties to get Android native applications run on a standard Linux distribution come from its optimizations for embedded devices

  • the specific static linker, in replacement of the standard ld-linux
  • the kernel device /dev/binder for IPC calls. Here are the openbinder-x86-linux2.6.27.tar for recent Linux kernel (x86 32 bits only)
  • and the framebuffer display

Stay tuned to get details about job in progress.

19 commentaires

  1. Here are tasks in pipeline at the moment concerning developments on Maemo itself:

    • Create a userspace in-memory framebuffer device (or with a Maemo Linux kernel module). That device will be use by Android application to draw as a virtual screen.
    • Create a Maemo application (« android-ui » in Qt) to display framebuffer content as fullscreen or in a window with menu. This application will intercept mouse and keyboard events and direct them to Android processes – question to investigate: how/where Android binaries get that events.
    • Port and compile Android modules (/dev/binder and /sys/android_power) as modules for Maemo kernel or build in a power kernel for instance. Another option is to divert these interfaces usage in Android libraries (libc ?) by Maemo specific code.

    I work myself on the Android build system itself – based on google open android sources and android-x86 project.

    • Investigate to understand how « /system/bin/linker » is created/used in the compile chain to force static address mapping
    • Replace this specific linkage by standard Linux ld.so method
    • Remove useless compilation sub-trees like « adb » to speed up dev cycle
    • First step: run /system/bin/gzip compiled from Android sources on standard Linux and then ARM Maemo

    Any detailed information, proof-of-concept codes or how-to concerning any of these steps are welcome.

  2. Another step forward. After wasting time to port OpenBinder module and test suite to x86_64, I have finally succeeded in compiling binder module for Linux 2.6.27 and 2.6.33 and run test suite on it.

    To compile Android for a stock Linux and use the standard ld loader, you just have to invoke « export TARGET_SIMULATOR=true » before « make ». I still have troubles with wxWidget version, probably used for the simulator user interface.

  3. Here are some details about Dalvik VM:
    http://elinux.org/Android_Dalvik_VM
    about Android-specific Linux kernel
    http://elinux.org/Android_Kernel_Features
    Note that some supports are required for Android – as cgroup mounted in init script mount cgroup none /dev/cpuctl cpu but as designed for VServer, it is not enabled by default in distribution.
    Accord to http://fred-zone.blogspot.com/2010/08/android-is-working-on-x.html seems that ChromeOS kernel has most support required for Android processes.

  4. After a break, I get back my compiled Android in simulator mode inside a Debian x86 chroot.
    Based on http://developer.android.com/guide/tutorials/hello-world.html I have written my first Android package with a single line of code

    public static void main(String[] args) {
    Log.v("HelloAndroid", "Hello, world !");
    }

    # /system/bin/dalvikvm -Xbootclasspath:/system/framework/core.jar:/system/framework/ext.jar:/system/framework/framework.jar:/system/framework/android.policy.jar:/system/framework/services.jar -cp /data/app/HelloAndroid-debug.apk com.android.helloandroid.HelloAndroid
    W/dalvikvm(10801): No implementation found for native Landroid/util/Log;.println_native (IILjava/lang/String;Ljava/lang/String;)I
    W/dalvikvm(10801): threadid=1: thread exiting with uncaught exception (group=0xf5cc5138)
    java.lang.UnsatisfiedLinkError: println_native
    at android.util.Log.println_native(Native Method)
    at android.util.Log.v(Log.java:101)
    at com.android.helloandroid.HelloAndroid.main(HelloAndroid.java:19)
    at dalvik.system.NativeStart.main(Native Method)

    Bad luck, it seems really strange that a method lacks after a successful compilation.

    # ldd /system/bin/dalvikvm
    linux-gate.so.1 => (0xffffe000)
    libpthread.so.0 => /lib/libpthread.so.0 (0xf76cb000)
    libdvm.so => /home/mydroid/out/host/linux-x86/pr/sim/system/bin/../lib/libdvm.so (0xf75b0000)
    libssl.so => /home/mydroid/out/host/linux-x86/pr/sim/system/bin/../lib/libssl.so (0xf7573000)
    libz.so => /home/mydroid/out/host/linux-x86/pr/sim/system/bin/../lib/libz.so (0xf755e000)
    libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0xf7470000)
    libm.so.6 => /lib/libm.so.6 (0xf744a000)
    libgcc_s.so.1 => /lib/libgcc_s.so.1 (0xf743d000)
    libc.so.6 => /lib/libc.so.6 (0xf72ff000)
    /lib/ld-linux.so.2 (0xf76ec000)
    liblog.so => /home/mydroid/out/host/linux-x86/pr/sim/system/bin/../lib/../lib/liblog.so (0xf72f8000)
    libcutils.so => /home/mydroid/out/host/linux-x86/pr/sim/system/bin/../lib/../lib/libcutils.so (0xf72d9000)
    libnativehelper.so => /home/mydroid/out/host/linux-x86/pr/sim/system/bin/../lib/../lib/libnativehelper.so (0xf7290000)
    libdl.so.2 => /lib/libdl.so.2 (0xf728c000)
    librt.so.1 => /lib/librt.so.1 (0xf7283000)
    libcrypto.so => /home/mydroid/out/host/linux-x86/pr/sim/system/bin/../lib/../lib/libcrypto.so (0xf7173000)
    libexpat.so => /home/mydroid/out/host/linux-x86/pr/sim/system/bin/../lib/../lib/../lib/libexpat.so (0xf714d000)
    libutils.so => /home/mydroid/out/host/linux-x86/pr/sim/system/bin/../lib/../lib/../lib/libutils.so (0xf7111000)
    libicudata.so => /home/mydroid/out/host/linux-x86/pr/sim/system/bin/../lib/../lib/../lib/libicudata.so (0xf6f40000)
    libicuuc.so => /home/mydroid/out/host/linux-x86/pr/sim/system/bin/../lib/../lib/../lib/libicuuc.so (0xf6e0b000)
    libicui18n.so => /home/mydroid/out/host/linux-x86/pr/sim/system/bin/../lib/../lib/../lib/libicui18n.so (0xf6c9e000)
    libsqlite.so => /home/mydroid/out/host/linux-x86/pr/sim/system/bin/../lib/../lib/../lib/libsqlite.so (0xf6c1b000)

    # objdump -t /home/mydroid/out/host/linux-x86/pr/sim/system/bin/../lib/../lib/liblog.so | grep android
    00002420 l F .text 00000366 android_log_printBinaryEvent
    000029f0 g F .text 00000184 android_log_formatFromString
    00002be0 g F .text 0000020d android_log_addFilterRule
    00001c60 g F .text 0000000e android_log_setPrintFormat
    00002790 g F .text 000001e6 android_log_processBinaryLogBuffer
    00001c00 g F .text 00000054 __android_log_dev_available
    00002b80 g F .text 0000005f android_log_shouldPrintLine
    00002330 g F .text 000000eb android_log_printLogLine
    000014c0 g F .text 00000060 __android_log_btwrite
    00002980 g F .text 0000006f android_log_processLogBuffer
    000016f0 g F .text 000001cd __android_log_buf_write
    00001cc0 g F .text 00000666 android_log_formatLogLine
    00003120 g F .text 0000064b android_openEventTagMap
    00001b40 g F .text 0000005e __android_log_print
    000030d0 g F .text 00000041 android_closeEventTagMap
    00002ec0 g F .text 00000039 android_log_format_new
    00002df0 g F .text 000000cc android_log_addFilterString
    00001ae0 g F .text 00000057 __android_log_assert
    000018c0 g F .text 00000065 __android_log_buf_print
    00001ba0 g F .text 0000005e __android_log_vprint
    00001c70 g F .text 00000041 android_log_format_free
    00001470 g F .text 0000004d __android_log_bwrite
    00003060 g F .text 0000005a android_lookupEventTag
    00001930 g F .text 000001ad __android_log_write

    That native library is not called directly. Involved source is at frameworks/base/core/jni/android_util_Log.cpp

    My first impression is that JNI support is in trouble and fails to dynamically link code.
    Hope to understand and fix that quickly. Of course any help is welcome.

  5. Nice research project you have there.

    As for the framebuffer issues, I found a similar problem some months ago when I was trying to port certain other operating system’s VM that also assumed direct access to fb0, and after looking at UML, etc. I decided to implement this: http://gitorious.org/preenv/libx11fb .
    It is basically a library that should be LD_preloaded to the VM binaries, and a separate daemon that can be run under Maemo that is the X11 application showing the shared framebuffer in a window that you described. It also handles emulation of certain /dev/input/* nodes that the operating system I was « porting » required. Plus scaling and some other stuff that would probably need to be removed.

    However, since the VM you’re porting is OSS, it might be more interesting to modify it to draw to X11 instead? Either way, if you start using the above tool drop me an email and I will be happy to answer questions :) .

  6. Hi Yves,

    Let’s do this in English so that more fellows can follow :) I’m currently trying to « port » the Android’s bits so that it can be run « on » Maemo rather than on the N900 (just like the Alien Dalvik project) so Android apps could run alongside the regular Maemo ones.

    I’ve found the staging android drivers for 2.6.29 and I’m trying to merge them back into the 2.6.28 kernel tree used for the n900. With this type of drivers, the /dev/binder would come for free without having to get the « standalone » binder code.

    Do you have interest is such effort? As I understand your previous posts, you’re running everything in the simulator, but did you try to run that on the n900 itself?

    • Hello JP,

      My work on OpenBinder was based on the module from Froyo (probably 2.6.23) and I have changed system calls to match 2.6.27 API or later.
      By the way, running Dalvik alone is not supposed to depend a lot on kernel modules. OpenBinder may be required to make different applications / services communicate together.

      So my advice would be to work on OpenBinder module, and also on a Android « power » module even if it is just fake.

      Then, I do not run the qemu based « adb » emulator. I have compiled natively (x86 Linux) with TARGET_SIMULATOR=1 option.
      So binaries are linked with standard Linux glibc. But now I get troubles with JNI calls, I still have to learn from http://source.android.com/porting/dalvik.html
      So I consider I am not ready to compile for N900 inside Maemo ARMEL Scratchbox: first a Java 5 is required, so a by-pass is required, then at best, it will remain a command line process only before X11 support.

      According to a post (somewhere, I lost reference), Gingerbread build system generates a host-compiled dalvik runtime so that developers can test applications at normal speed – definitely a great improvement compared to « adb » overhead. By the way, Nokia Maemo SDK provides native execution on development workstation since years.

  7. I am just upgrading to Gingerbread. The « lunch » command from build system proposes the « simulator » choice. Really interesting. Now I am building a list of projects required for Dalvik compilation when in « simulator » mode, so that a manifest for repo can be used.

  8. Hi all,
    Thanks you Yves for sharing your valuable work. My understanding is that openbinder-x86-linux2.6.27.tar is the initial update of openbinder and you’ve reworked it again to align with 2.6.33 releases of the kernel.
    May i kindly ask you if you can share your work with us please ? Do not hesitate to contact to me please.

  9. Hi,

    Thanks for sharing your experiences with Dalvik porting for Maemo. This experiment seems like a really nice way to get into the Android / Dalvik internals.

    I would like to continue this project from where you left it. Can yo share you source/progress with me please :-)

Laisser un commentaire