2012年3月16日金曜日

Android_on_OMAP

Android

What is Android (not)

Android is a software stack for mobile devices that includes an operating system, middleware and key applications. See Google's What is Android? page and Benno's What is Android? and What Android isn't page for more details about Android.

Versions

From time to time Google updates their Android releases. At time of writing this article version m5-rc14 was the recent one. You should always use the latest available version. And make sure you use an Android kernel (patch) for your hardware that matches the file system version (see below).

Hardware

Goldfish

Android SDK isn't targeted for a special (ARM) SoC. Instead, they use QEMU to create a virtual ARM SoC called Goldfish. The virtual ARM SoC boots an (currently 2.6.23, m5-rc14) ARM Linux kernel with Goldfish platform support on your (x86) Windows, MacOS X or Linux host.

This virtual ARM SoC comprises:

  • ARM926ej-S CPU
  • Thumb support
  • MMC
  • RTC
  • Keyboard
  • USB Gadget
  • Framebuffer
  • TTY driver
  • NAND
  • Software compiled for ARMv5TEJ instruction set (!) with EABI
  • no TLS yet

Real hardware

Running Android on real hardware, some prerequisites should be fulfilled:

  • SoC with ARM926 or higher (e.g. ARM11) (check ARM MPCore or ARM Cortex regarding TLS issue)
  • You have already a recent (~2.6.23) Linux kernel with Thumb & MMU & EABI etc support running on your target
  • Soc/HW has and Linux kernel supports
    • Display/frame buffer (touchscreen would be good but optional). Frame buffer has to support double buffer/page flipping.
    • Keyboard
    • USB (optional)
    • RTC (optional?)
    • Serial console
    • Some storage, sufficient for ~64MB, e.g. NFS or USB stick or NAND or NOR or MMC/SDcard etc. NFS would be easiest for development
    • Sufficient main memory (SDRAM) >=32MB. While 32MB seems to be enough to start, system will be really slow then. Therefore 32MB is sufficient for proof of concept, but not for a usable system.


Known to work HW

Android internals ML, OMAP ML and Android on N810 page. Working Android port for Nokia Internet Tablets can be found here.

Known to not work HW

Compiler

Getting Android working on real hardware, you need an ARM EABI (good EABI description, ignore the Debian specific stuff) compatible development environment. I.e., your tool chain, your kernel and user space must be compatible to ARM EABI. If you don't like to create your own ARM EABI compatible compiler, linker, library etc. you should use CodeSourcery's ARM GNU/Linux tool chain.

Note: The naming in the CodeSourcery download section is slightly confusing. You need the ARM GNU/Linux named tool chain which is indeed an ARM GNU/Linux EABI tool chain with glibc. The ARM EABI named tool chain there is something normally known as arm-elf tool chain withoutany Linux support and without glibc.

Code

As mentioned above, the Android SDK contains an emulator where a virtual ARM device runs the Android SW on your host PC. The Linux kernelused in this emulator is available in source code. In contrast, the user space file system (applications) is currently only available as binary as part of the SDK.

To get Android running on real HW, currently you need both, matching SDK and kernel source. You need kernel source to extract Android specific patches to add them to your SoC specific kernel. And SDK to get Android user space file system binaries. While getting Android kernel patches is somehow straight forward, extracting user space file system with Android applications in it is a little bit tricky.

Kernel

On Android project page the source code of the kernel is available. From full kernel tree with Android modifications included you can extract patches. With this, you have to extract the Android specific patches yourself from the complete kernel tree, use already extracted patches or get kernel patches by git.

Patch extraction

See third paragraph of Benno's Android on NEO 1973 article.

  • Download matching version (e.g. m5-rc14) of Android kernel source. Besides complete kernel source this will contain Android specific changes.
  • Download matching (e.g. 2.6.23) stock Linux kernel (or use e.g. git to check out stock kernel version) and diff both kernels to get Android related changes.
  • As we want to run Android on real hardware, you can throw away all QEMU and Goldfish related changes. If you don't want to use yaffs2 file system (e.g. cause you don't have NAND or have it already in your tree), throw away yaffs2 related changes as well. If you use m5-rc14 (or higher?) you can remove OpenBinder related files (/driver/binder) as well. Result should be a generic, no ARM or OMAP specific Android patch you can apply to your (e.g. 2.6.23) kernel for your ARM based SoC.

Note: There seems to be some effort to make Android kernel patches available in a easier usable format.

Extracted patches

At some locations there are ready made patches available. The advantage of this is that you don't have to extract the patches yourself. The disadvantage is that you can't always be sure that they contain everything you need and that they match your SDK/user space file system (see below) version.

Note: Some guys on OMAP mailing list have Android patches extracted (currently from m5-rc14) and are willing to share them. Unfortunately they don't have any permanent web storage yet. If you have and like to help community with providing some web space, contact OMAP list.

Git patches

There are Android kernel patches available using Android's git repository. But have a look to Brian's notes regarding this.

File System

Getting user space file system binaries running in emulator extracted is slightly tricky. We have to extract the binaries as currently access to source code have only Google itself and eventually WindRiver.

Again, there are two ways to get user space binaries: Extracting them your self or taking already extracted ones.

Binary extraction

The user space applications compiled for ARMv5 EABI are part of the Android SDK in system.img and userdata.img in tools/lib/images directory of SDK.

  • Download SDK and unzip it
  • system.img and userdata.img are yaffs2 images. There is no way yet to mount them directly on a host to extract their content. An unyaffstool is missing, so the only way to get the content is to start the emulator and extract the contents from running emulator.

Recently there is an unyaffs available [1]

  • As file system in emulator as no cp or tar command, we use a statically linked BusyBox cross compiled for ARM and use it inside emulator (get it from Benno or build it your own with above tool chain).
  • Set path to emulator tools
export PATH=${PATH}:<path_to>/android-sdk_m5-rc14_linux-x86/tools 
  • Create an empty SDcard (image)
mksdcard -l card 100M card.img 
  • Start emulator
emulator -sdcard card.img -console -debug-kernel 
  • You should now see the SDK kernel booting and emulator starting. Wait until the emulator is ready, then send the ARM busybox from the host into the simulated environment:
adb -d 1 push busybox /data/busybox 
  • Inside emulation, set tar (and bzip2) links to busybox, tar /system and /data directories to sdcard.
  • Shutdown emulator, mount card.img
mount -o loop card.img mnt/ 

and get the images of system and user data.

  • If you look at the extracted size of the userdata image, the extracted one is bigger than the original userdata.img. So by the runtime extraction we get some temporary junk in it. For this, untar extracted userdata and remove a least some of the unnecessary stuff:
    • Remove all content of data/dalvik-cache/. It holds the decompressed files from the apk packages.
    • Remove the static busybox image. We only needed it for extraction and don't need it any more.

Note: Anybody likes to hack this unyaffs tool? Then the system.img and userdata.img extraction would be a lot easier.

Note: A user reports that he doesn't use the extracted data directory at all. He simply mounts a tempfs to /data as it seems that Android runtime creates most (all?) of the necessary files in /data itself at runtime.

Extracted binaries

At some locations there are ready made binaries available. The advantage of this is that you don't have to extract the binaries yourself. The disadvantage is that you can't always be sure that the images contain everything you need and that the images match your kernel patch (see above) version.

Note: Some guys on OMAP mailing list have Android binaries extracted (currently from m5-rc14) and are willing to share them. Unfortunately they don't have any permanent web storage yet (~30MB). If you have and like to help community with providing some web space, contact OMAP list.

Target

This section describes how to configure the software (kernel, file system) to run Android on real hardware target. Before you do this Android specific steps, you should make sure that everything works without any Android specifics. I.e. make sure that the (EABI) kernel boots, you can access all file systems (e.g. NFS or MMC or NOR or NAND etc.) and necessary drivers (e.g. keyboard, touchscreen etc.). Do this with booting into your normal (EABI) file system you always use. We later switch to Android file system then.

Kernel configuration

Make sure your kernel boots normally on your board. Then enable some Android specific configuration (needs kernel patch extracted above) and make sure that your kernel still boots (with your standard file system).

Note: Some of these settings are valid only for m5-rc14 and newer (?) (Binder config, /sys/android_power output) as it changed from older versions to m5-rc14.

EABI

CONFIG_AEABI=y # CONFIG_OABI_COMPAT is not set 

THUMB

CONFIG_ARM_THUMB=y 

Android drivers

# # Android # # CONFIG_ANDROID_GADGET is not set # CONFIG_ANDROID_RAM_CONSOLE is not set CONFIG_ANDROID_POWER=y CONFIG_ANDROID_POWER_STAT=y CONFIG_ANDROID_LOGGER=y # CONFIG_ANDROID_TIMED_GPIO is not set CONFIG_ANDROID_BINDER_IPC=y #AshMem  CONFIG_ASHMEM=y 

After you successfully booted the kernel with configuration above (and m5-rc14 kernel patch), make sure you have following /sys files:

/sys/android_power/acquire_partial_wake_lock /sys/android_power/acquire_full_wake_lock /sys/android_power/last_user_activity /sys/android_power/request_sleep /sys/android_power/acquire_full_wake_lock /sys/android_power/acquire_partial_wake_lock /sys/android_power/battery_level /sys/android_power/battery_level_low /sys/android_power/battery_level_raw /sys/android_power/battery_level_scale /sys/android_power/battery_low_level /sys/android_power/battery_shutdown_level /sys/android_power/charging_state /sys/android_power/release_wake_lock /sys/android_power/request_state /sys/android_power/state 

File system configuration

We now switch to Android file system extracted above. This should be established on a device with enough space (> ~64MB) and which is accessible on your target. Options are e.g. NFS, NOR or NAND file system, hard disk or USB storage. In a first step it is sufficient if you are able to manually mount it from your (temporary) standard root file system. In a second step it is an option to use it directly as root fs.

The Android file system we establish here on one of the the storage from above is built from four parts:

  • Content of system data image extracted above
  • Content of user data image extracted above (make sure temporary files are removed)
  • Content of Android ram disk image
  • Device file system

To create Android file system, take (empty) storage you selected and start with ram disk:

Android ram disk image can be found as ramdisk.img in tools/lib/images of Android SDK. This is a gziped cpio archive:

cp ramdisk.img ramdisk.gz gunzip ramdisk.gz cd target_fs cpio -iv < ../ramdisk 

Result of this should be an root file system tree with:

data dev etc init proc sbin sys system tmp var 

Directories data, dev and system are empty. Extract content of extracted user data image to /data and system image to /system directories. E.g.

tar xvfj ../system_m5_rc14.tar.bz2 system/ tar xvfj ../userdata_m5_rc14.tar.bz2 data/ 

Note: This depends on how you named and stored extracted user data and system image above.

Last step is to create some device nodes in /dev you need for running from this Android file system. There are several options how to establish this. One option is to extract device file system from running Android emulator as well. Second option is to use the same device file system you normally use in your standard file system. Choose the easiest way. If you did this, make sure you have Android specific device nodes with correct major/minor numbers as well.

Note: Copying device nodes the best way is to tar them at source and untar them then at target. For device nodes, cp command isn't the best option due to special device node format.

Start up

Starting Android using the file system and kernel created above, there are three ways:

  • Directly boot from Android kernel into the Android file system. I.e. let the Android kernel directly start init etc. from Android file system.
  • First boot from Android kernel into your standard file system. Then "manually" switch over to Android file system and start Android. This "manual" switch can be done using some scripts.
  • The third way is a mix of the first two ways: Boot into a standard non-Android file system, then switch over to Android but there directly execute init as it would be done by root file system.

Android root file system

There are several ways to directly start Android from (root) file system created above:

  • Directly point your kernel to /init in Android file system. Then kernel will use Android's init as init program and execute it without any manual interaction
  • Use Android's shell and give kernel /system/bin/sh as init program. Then start Android's init manually (/init&) .

Start via scripts

This section describes the second way to start Android. First boot into your normal file system and then switch to Android file system and start Android "manually", i.e. with help of some scripts. From the initial description of this method, this way is also known as the a.sh way (search for a.sh). The scripts used for this depend on your local configuration. You can take below scripts as example and adapt them for your local use.

These example scripts are used to first boot into standard root file system (e.g. JFFS2 in NOR) and then to mount (/mnt/usb) and start Android located on an ext2 formatted USB stick.

start_android.sh in standard root file system:

#!/bin/sh -x echo "Starting Android..." fsck.ext2 -pv /dev/sda1 mount /dev/sda1 /mnt/usb rm -f /mnt/usb/tmp/* umount /proc umount /sys mount -t proc proc /mnt/usb/proc mount -t sysfs sysfs /mnt/usb/sys umask 000 chroot /mnt/usb/a.sh  

a.sh to start Android at Android file system:

#!/system/bin/sh -x  export PATH=/sbin:/system/sbin:/system/bin:$PATH export LD_LIBRARY_PATH=/system/lib export ANDROID_ROOT=/system export ANDROID_ASSETS=/system/app export ANDROID_DATA=/data export EXTERNAL_STORAGE=/sdcard export DRM_CONTENT=/data/drm/content  /system/bin/app_process -Xzygote /system/bin --zygote & /system/bin/dbus-daemon --system & runtime & /system/bin/sh 

Notes:

  • fsck.ext2 -pv /dev/sda1: Make sure ext2 file system is clean. ext2 doesn't like unclean switch off while debugging Android start up ;)
  • rm -f /mnt/usb/tmp/*: Remove Android temporary files before starting Android.
  • mount proc and mount sys: This has to be done somewhere. Depending on your scripts, you can do it in a.sh as well.
  • runtime: For debugging use here /system/bin/strace -f -ff -tt -s 200 runtime&.
  • Starting runtime in background (&) and calling /system/bin/sh afterwards is optional. It gives you the option to have a shell at Android startup to e.g. observe /proc/meminfo, top or ps. Only useful if strace isn't enabled or not so noisy ;)

Start init via scripts

This third way is a mixture of the first two ways: Boot into a standard non-Android file system, then switch over to Android but there directly execute init as it would be done by root file system.

From standard non-Android file system this switch can look like:

mount /dev/sda1 /mnt/usb rm -f /mnt/usb/tmp/* umask 000 chroot /mnt/usb /init 

Debugging

  • Strace: The main debugging help currently known is strace. Again, a statically linked one is used.
strace -f -ff -tt -s 200 /system/bin/runtime

0 件のコメント:

コメントを投稿