Monday, August 29, 2011

Android and OpenGL ES profile(s) detection

There are some sample queries posted on android-porting and rowboat mailing list where Android applications fail to detect supported OpenGl ES profiles. These applications end up throwing "OpenGL ES profile unsupported" error even though those profiles are actually supported either by the hardware or software of the target platform. Most common case is that of OpenGL ES 2.0 profile as you can see in the above hyper-links.

Problem with these Android applications, as far as I can find out is that they use Android APIs instead of standard OpenGL ES APIs to query the OpenGL ES version(s) supported by the target.

These Android APIs (e.g. detectOpenGLES20() in case of OpenGL ES 2.0) query the system properties (as in /system/build.prop file) to find out if target supports OpenGL ES 2.0.

To set the system wide OpenGL ES setting we need to add the corresponding property "ro.opengles.version=xxxxxx" in /system/build.prop
For OpenGL ES 2.0, set:
ro.opengles.version=131072

For OpenGL ES 1.1, set:
ro.opengles.version=65536

For OpenGL ES 1.0, set:
ro.opengles.version=65535
This property can be directly put in /system/build.prop file as it is or can be defined in Vendor specific Board Config files (e.g. device/vendor_name/target/target.mk file) as follows:
PRODUCT_PROPERTY_OVERRIDES+=\
ro.opengles.version = 131072
I have not tested these settings myself but as confirmed in this android-porting thread it definitely works :)

Wednesday, August 24, 2011

Say hello to DroidCon London 2011

UK's largest Android conference is back. Droidcon London 2011 edition is taking place from 6-7 October 2011.


Droidcon London Oct 6-7



Conference looks very promising covering every aspect of Android ecosystem. Check Droidcon London 2011 homepage for complete schedule.

Video archive and speaker list from 2010 edition of Droidcon London is here.

How to build common Linux utils for Android without using Android.mk

Ideally one should build his/her project as a part of AOSP (Android Open Source Project) using Android standard Makefile aka Android.mk. You can find many such examples in $AOSP/external/

This guide is meant for lazy people like me who doesn't want to use the above procedure to build small Linux debug utilities/binaries like devmem2, fbset etc for Android. It assumes that we have already built AOSP sources for a TARGET_PLATFORM.

# export ANDROID_ROOT= path_to_AOSP_sources

# export TARGET_PRODUCT= target_product_name

# $ANDROID_ROOT/prebuilt/linux-x86/toolchain/arm-eabi-4.4.3/bin/arm-eabi-gcc -nostdlib -Wl,-dynamic-linker,/system/bin/linker $ANDROID_ROOT/out/target/product/$TARGET_PRODUCT/obj/lib/crtbegin_dynamic.o $ANDROID_ROOT/out/target/product/$TARGET_PRODUCT/obj/lib/crtend_android.o -L$ANDROID_ROOT/out/target/product/$TARGET_PRODUCT/obj/lib -lc -ldl -fno-short-enums -I$ANDROID_ROOT/bionic/libc/include -I$ANDROID_ROOT/bionic/libc/arch-arm/include -I$ANDROID_ROOT/bionic/libc/kernel/common -I$ANDROID_ROOT/bionic/libc/kernel/arch-arm -o devmem2 devmem2.c

Friday, August 19, 2011

Android Bootup Logo and Animation

Vanilla Android boots up with a Green Droid logo and then switch to boot animation.

Droid logo image is loaded by init process(system/core/init/init.*)
main()
--> console_init_action()
      --> load_565rle_image(INIT_IMAGE_FILE)

Where INIT_IMAGE_FILE="/initlogo.rle"
Image load processing is handled by system/core/init/logo.c

Android boot animation is triggered by SurfaceFlinger startup routine(frameworks/base/services/surfaceflinger/SurfaceFlinger.cpp)
SurfaceFlinger::readyToRun()
--> property_set("ctl.start", "bootanim")

Where bootanim service(defined in /init.rc) will start /system/bin/bootanimation
Bootanimation code can be found here frameworks/base/cmds/bootanimation/*

Now you know what you need to modify to create a custom Android bootup Logo or Animation.

Tuesday, August 16, 2011

Dual booting Android-x86 and Ubuntu

During this long weekend I finally tried out Android-x86 (v2.3.5 and "generic_x86" Target) on my Dell-XPSM1210 laptop. Most of the things (Touchpad, Audio-Out, Keyboard, WiFi, Ethernet) worked right out of the box. Others (e.g. Bluetooth, Audio-In, Mouse etc) are yet to be tested.

Clone, Build and Image-Creation.

I cloned (~3GB) and built the sources from Android-x86 Git repository as mentioned on their wiki-page. This complete process took close to 12GB of my hard-disk space. I chose to build the USB bootable image (make usb_img TARGET_PRODUCT=generic_x86 -j3).

Note:
At first attempt gingerbread-x86 manifest either did an incomplete clone or cloned a wrong branch/commit of "platform/external/elfutils" and "platform/external/elfcopy" projects. You know you need to checkout the correct one (or do a "repo sync" again) if you get errors like "libelf.h or libebl.h not found" during compilation.

After successful compilation I followed the instructions on their installation page to copy the resulting USB image (out/target/product/generic_x86/generic_x86_usb.img) to a USB drive.

First Run and Installation on hard-disk.

Once the image is ready, I restarted my machine and boot from USB disk. Grub is pre-installed on USB disk but the Root is wrongly set (at least in my case it was not correct). It was set to "hd0,1" while mine was/is "hd0,0". You may want to take care of this if you don't see Android-x86 grub menu.

I first did a Live image booting and within few seconds I reached home-screen. Everything worked perfectly. Within next few moments I knew, I was going to install it on my hard-disk which I eventually did :) but without installing Android-x86 Grub bootloader.

Dual Booting Android-x86 and Ubuntu.

I modified Ubuntu Grub2 to add Android-x86 menu entry. It was a bit tricky and took quiet a while to understand that root=(hd0,X) is not a valid root-point and you should use root='(hd0,msdosX)' instead, at-least on Ubuntu Grub2 bootloader. Here is what you need to do:

Create/Modify "/etc/grub.d/40_custom" script:

#!/bin/sh
exec tail -n +3 $0
# This file provides an easy way to add custom menu entries.
# Simply type the menu entries you want to add after this
# comment. Be careful not to change the 'exec tail' line above.

menuentry "Android-x86 2.3.5" {
    set root='(hd0,msdos2)'
    linux /android-2011-08-15/kernel quiet root=/dev/ram0 \
    androidboot_hardware=generic_x86 \
    acpi_sleep=s3_bios,s3_mode \
    video=-16 DPI=160 SRC=/android-2011-08-15
    initrd /android-2011-08-15/initrd.img
}
       
menuentry "Android-x86 2.3.5 (Debug mode)" {
    set root='(hd0,msdos2)'
    linux /android-2011-08-15/kernel root=/dev/ram0 \
    androidboot_hardware=generic_x86 \
    acpi_sleep=s3_bios,s3_mode \
    video=-16 vga=788 SRC=/android-2011-08-15 DEBUG=1
    initrd /android-2011-08-15/initrd.img
}

Once this menu-entry is created, update Grub2 by running "update-grub2" command as sudo/root user. Now you should see the corresponding entries in Grub2 menu (/boot/grub/grub.cfg) and your machine should boot into Android-x86.

Next task is to explore how to use Android Market if it is at all possible.

Wednesday, August 10, 2011

Android, Linux-ARM and TLS register emulation

TLS or Thread Local Storage

In a multi-threaded application, where all threads in a process share the same address space, there often arises the need to maintain data that is unique to a thread. Use of errno, in a C code, is a classic example of using this type of data which is local to a given thread. TLS or Thread Local Storage, as you can probably figure out from its name now, is a concept used for Threading abstraction. It is a fast and efficient way to store per-thread local data. Offset of thread's local data is accessible via the TLS register(h/w or s/w block) which points to Thread Control Block of respective thread. Check this PDF for more information.

Yesteryears High end ARM cores viz. ARM9 and even some of ARM11 cores do not have this TLS Register physically available. Operating Systems (Linux from here onwards) need to emulate it in software. New generation ARM cores viz. Cortex-Ax onwards, however, do have this TLS register available (CP15).

Why do I being an Android porting/integration guy, need to care about TLS?

Android(till Eclair? I guess) had this unique bug (or feature?) where in, it assumes that TLS register is emulated by the Kernel(Linux) and thus expect Linux to trap it. It worked well for ARM cores which were already emulating TLS register in software.

With the rise of ARM Cortex-Ax cores, people started reporting all sort of errors related to Android mounting or random Android service crashes. It turned out that the error was due to hard dependency of Android on TLS register emulation. Since Cortex-Ax devices do have TLS register available and Linux was not trapping it, that made Android really really mad.

By that time there was no known way to make Android user-space TLS register aware, developers started patching Linux to make it compatible with the emulated TLS register. Here is the relevant TLS patch for 2.6.32 and patch for 2.6.37 ARM kernel.

With Froyo i.e. v2.2, Android introduced a build config variable ARCH_ARM_HAVE_TLS_REGISTER which (you need to set/export during build time) will make Android user-space TLS register aware and you don't need to patch your Linux anymore.

So now you know what else to look for if your Android port is crashing on an unsupported Kernel version.

P.S.
I'm yet to figure out what ARCH_ARM_HAVE_TLS_REGISTER ends up doing. A quick grep of this variable in AOSP came out with results in bionic/ and frameworks/base/opengl/ projects.