Android on OKL4
OKL4 3.0 was originally ported to run on the HTC Dream (found here). A student, Michael Hills, developed a rudimentary Android port that removes Linux and runs natively on OKL4 3.0 for his undergraduate thesis. The supplied code demonstrates the Lunar Lander application found in the Android SDK running on the Dalvik VM on OKL4.
Getting the source
First create a base directory to contain all of the source of this project.
Then download the Android repo tool and place it into a directory that is in your environment's PATH. Then inside the project base directory, create a directory for the Android source and initialize the repo.
You may need to prepare your build environment to compile Android as specified at http://source.android.com/source/index.html.
curl http://android.git.kernel.org/repo >~/bin/repo chmod a+x ~/bin/repo mkdir android-1.5r2 cd android-1.5r2 repo init -u git://android.git.kernel.org/platform/manifest.git -b android-1.5r2
Before downloading the Android source, we need to add the project for the HTC Dream hardware. Create a local_manifest.xml file inside android-1.5r2/.repo with the contents:
<?xml version="1.0" encoding="UTF-8"?> <manifest> <project path="kernel" name="kernel/msm" revision="refs/heads/android-msm-2.6.27"/> <project path="vendor/htc/dream-open" name="platform/vendor/htc/dream-open" revision="cupcake"/> </manifest>
Then download the Android source by running the command:
All development targets the Android Developer Phone 1 (HTC Dream) and not the simulator. Therefore it is handy to tell the Android build system to default to building for the phone. To do this create a file named buildspec.mk in the android-1.5r2 directory.
The content of buildspec.mk is:
Following this, download okl4-android.tar.bz2 which contains everything else that is not Android.
Place the tarball into the base project directory and then extract it.
tar xf okl4-android.tar.bz2
Part of this tarball is a directory with diffs that will be used to patch the Android tree with the changes made during porting. A script has been provided to patch the tree with these diffs in the base directory.
./patch.py android-1.5r2 diffs
... where android-1.5r2 is the android source tree directory, and diffs is the directory containing the diffs.
Next the Android 1.5r2 SDK is required for the Android simulator which is used to optimise Java libraries (explained later). However it appears to no longer be available for download on the Android site. Instead, I have tested that using the 1.5r3 SDK works correctly. Download the SDK from http://developer.android.com/sdk/index.html and follow the instructions listed there on how to add the 1.5r3 platform to the SDK.
After extracting the tarball and patching the Android tree, the code base is now ready for building.
The gcc toolchain that is used to compile both the Android and OKL4 trees is supplied with Android. If you are using Linux add the following directory to your path:
If you are using Mac, then use:
However all development was done using Ubuntu 9.04 64-bit, and this has not been tested on a Mac.
In addition to this, the OKL4 kernel uses a different toolchain to the userland components. The kernel does not compile with the Android toolchain. Instead, use the arm-3.4.4 toolchain listed on http://ertos.nicta.com.au/software/prebuilt/binaries.pml and add the toolchain's bin/ directory to your PATH.
Building the source
Both Android and OKL4 have their own build system, and so building the source is a little more complicated than just running a single make command. Libraries and binaries that are compiled in the Android source tree must be linked to OKL4 libraries and then placed into the in-memory file system which is done using the Elfweaver tool in the OKL4 tree.
The directory layout of the source should look like the following:
./android-1.5r2/ ./okl4-android-3.0/ ./fs/
The first two directories are self-explanatory. The third directory contains files that will be placed into the in-memory file system.
The base directory contains several scripts to ease compilation.
One script will build all necessary parts of the Android tree (Java libraries, Bionic libc, Dalvik, and other misc libs), and do a full build of the OKL4 tree.
However, Dalvik uses optimised Java libraries at runtime. The optimising tool was not ported and isn't executed at runtime, so these optimised dex libraries must be produced beforehand and inserted into the in-memory file system.
The optimisation process uploads the built Java library jars to the simulator and invokes the optimisation tool on them. The optimised dex files are then downloaded back and placed into the fs/data/dalvik-cache directory where Dalvik can find them at runtime.
To start the simulator:
export ANDROID_PRODUCT_OUT=path/to/android-sdk-linux/platforms/android-1.5/images path/to/android-sdk-linux/tools/emulator
Once the simulator has finished loading, it is time to optimise the Java libraries. This is done by attempting to run a Java program with the jars you want optimised specified in the classpath.
In the project base directory run:
The argument to optimise.sh specifies the application jar that you wished to be optimised, currently only LunarLander is available. The jar file for LunarLander is located in fs/data/java, and the script automatically looks for specified jars in that location.
Now the boot image is ready to be built, this is done in the OKL4 tree.
cd okl4-android-3.0 ./make.sh dream
Calling make.sh will compile the OKL4 tree, and then build a boot image containing the files in the fs directory. Files to be placed in memory are specified in okl4-android-3.0/projects/sos/SConstruct. Make sure the latest dalvikvm binary and Java libraries are present in the file-system when compiling and booting the image onto the phone.
Once the boot image is ready, it can be loaded onto the phone using:
This script simply calls a fastboot modified for OKL4. More information about this can be found at http://ertos.nicta.com.au/software/okl4htcdream/ under "Running the code on the HTC Dream".
The LunarLander application should load, and you can use the S key to start and restart the game, Q to rotate left, W to rotate right, and Spacebar for thrust.
A Development Cycle
A standard development cycle might involve changes to code in either the Android or OKL4 trees. Rebuilding the OKL4 tree is as simple as ./make.sh dream, however the Android tree is a bit more complicated since we're using only a subset, and a complete build takes a long time.
Generally, you will need to rebuild Java or C/C++ libraries. A script has been provided to build individual libraries. For C/C++ libraries, in the base directory:
./phonelibs.sh c dvm cutils
This will build libc, libdvm, and libcutils.
For Java libraries, in the android-1.5r2/ directory:
make core framework
This will rebuild the Java core library and runtime framework library, which are both jars.
If you modify Dalvik main (dalvik/dalvikvm/Main.c), it needs to be rebuilt using:
The object file will be made, and ignore the following error messages which are a result of modifying makefiles to build static libraries.
The dalvikvm binary is statically linked with libraries from both Android and OKL4, and therefore if C/C++ libraries in either tree are modified, dalvikvm must be recompiled.
In the base directory:
make dalvik TARGET=dream
This will place a dalvikvm binary into fs/bin/.
If Java libraries are modified, they need to be re-optimised. In the base directory with the Android simulator running in the background:
... where app.jar is the Dalvik application you wish to run that has been extracted from an apk file.
Once everything is ready to go, simply build and load the boot image from the okl4-android-3.0 directory.
./make.sh dream ./run.sh dream
Bugs and Limitations
- A bug exists with the in-memory file system, and I do not know the exact cause. In the process of inserting files into the boot image, some files are occasionally corrupted and results in strange runtime behaviour. If the boot image fails to load the LunarLander application, then adding extra files to fs/data/java can make the bug go away (temporarily). The bug revealed itself early on during my thesis, but disappeared for the most of the year, only to reappear again towards the very end.
- Static linking is used because I never implemented shared libraries in my OS personality. Any library that you wish to use from the Android tree mustbe compiled statically, and some of the time Android libraries are configured to produce shared libraries only. The Android.mk file in the library's directory must be modified to build a static library, and this can be done by replacing "include $(BUILD_SHARED_LIBRARY)" with "include $(BUILD_STATIC_LIBRARY).
- C++ static initialisers are not called. This is a process which is meant to be done before calling main. Constructors of objects declared as static are meant to be executed, but they are not and this can cause strange behaviour with uninitialised objects.
- Only the LunarLander application was tested to run unmodified. It is highly likely that most programs will not work as I re-implemented the application-side libraries. This was done to get something running in the thesis to be able to benchmark the system. This is not a complete port of Android on OKL4.
If you have any questions about this project, please email Michael Hills (firstname.lastname@example.org).