Android-getting started

Howto build sdk and plugin - copy'n'paste version

The following commands are needed when building your own sdk and eclipse plugin.
In your homedir:

mkdir ~/repodir ~/plugindir ~/eclipse-android

cd ~/repodir

repo init -u git://android.git.kernel.org/platform/manifest.git -b cupcake

repo sync

source ./build/envsetup.sh

lunch 1

make

ECLIPSE_HOME=~/eclipse-android

./development/tools/eclipse/scripts/build_server.sh ~/plugindir

make sdk

The output files are:
~/plugindir/android-eclipse-v200903261355.zip (or whatever date it is)
~/repodir/out/host/linux-x86/sdk/android-sdk_eng.user_linux-x86.zip (replace 'user' with your username)

Not much info about what they do at the moment. Execute the commands in the specified order and it should work. If it doesn't - please comment and I will try to clarify.

 JNI hands on

In the demo setup at the seminar we hijacked the SMS application to send a LINX signal using JNI. In this post I'll describe more in detail how we implemented it.

First you need to create a Java-class that loads the C-library and declares the method (send(...))
public class NativeLib {
static {
try {
Log.i("JNI", "Trying to load libNativeLib.so");
System.loadLibrary("NativeLib");
}
catch (UnsatisfiedLinkError ule) {
Log.e("JNI", "WARNING: Could not load libNativeLib.so");
}
}
public static native long send(String number, String message);
}

Call the method somewhere appropriate from your activity:
long sum = NativeLib.send(...);

Next, you need to generate C-headers from the NativeLib Java-class:
cd <path to eclipse project dir>/bin
javah <class name>

Create a directory nativelib in the <android root>/external directory and move the header file to here.

Now, implement the C-file (and remember to include your recently generated header-file)
#include "com_android_mms_transaction_NativeSms.h"

JNIEXPORT jlong JNICALL Java_com_android_mms_transaction_NativeSms_send
(JNIEnv *env, jclass class, jstring number, jstring message)
{
//Get the native string from javaString
const char *numString;
const char *messageString;

numString = (*env)->GetStringUTFChars(env, number, 0);
messageString = (*env)->GetStringUTFChars(env, message, 0);

/*code to handle the sms info in native context goes here*/

/*release resources when done*/
(*env)->ReleaseStringUTFChars(env, number, numString); (*env)->ReleaseStringUTFChars(env, message, messageString);

return 0;
}

Next, we will construct a make-file: name it Android.mk and put it in <android root>/external/nativelib. Fill it up with the following:
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_SRC_FILES := %lt;name of C-file%gt;

LOCAL_SHARED_LIBRARIES := libcutils

LOCAL_C_INCLUDES += $(JNI_H_INCLUDE)

LOCAL_MODULE := libNativeLib

include $(BUILD_SHARED_LIBRARY)

Open file prelink-linux-arm.map in <android root>/build/core and add the row:

libNativeLib.so 0x9F400000

under comment:

# libraries for specific apps or temporary libraries

This will add your library to the prelink map. Make sure that the address is not used by anything else.
Now type make in Android root dir to build. Hopefully everything goes well and voila! You have implemented your native C-library

 A closer look at the Android project build system part I

In this two part post we will take a closer look at the structure of the build system for native functionality. The build system is based on make and resides in the build folder in the project. The first part will look at what is found in this folder while the second part discusses the Android.mk file and options.

envsetup.sh
There is one important file in build directory itself. That is the envsetup.sh file. This shell script contains a lot of functionality that is nice to have when working with Android. To invoke it type

. build/envsetup.sh

in the android root directory. This will allow you to use a number of new commands including:

m - make from the top of the tree
mm - builds all modules in the current directory
cgrep - grep in all c-files
jgrep - grep in all java-files
mgrep - grep in all makefiles
lunch - choose build target

These shell commands are very useful when working with the platform. Whether you are looking for something specific in a source file or you just want to build the current module for a test.

build/target
The target directory contains make configurations for different boards and products. The target directory is where new products can be added as needed by a hardware manufacturer. In the current release there is a generic product description, and sdk product and some other files. The available boards are the emulator, a generic board and the simulator.

The board makefiles describe the hardware platform level and can be shared among a number of products. For example you can build both the generic product and the generic_with_google product to run on in the emulator.

The makefiles for different products are listed in the file AndroidProducts.h. To add a new product put the makefile in the build/target/product folder and add the product to AndroidProduct.h. It is possible for product makefiles to inherit from each other to reduce the need for copying. The generic_with_google products inherits the generic product that inherits the core product to make up a three level product specification.

build/core
The core folder is the location of the build system files. These files are used to set up the build system and to build all the different modules as configured in the individual Android.mk files. The main.mk file is the entry point to the build system and it is this files that is included in the top level makefile in the project root directory. The build system can also be invoked by the shell command mm with at subset of the makefiles

The include order and hierarchy of the makefiles is rather complicated but an attempt of illustration can be found in this figure.


Most of the build configuration is set in the config.mk file and the definitions.mk file contains the functions to be invoked for the different source types. In the above figure the build system is invoked to build a shared library. The Android makefile uses the BUILD_SHARED_LIBRARY variable set in the config.mk file. This will set the build chain for building a shared library in a number of steps using several other files.

 A closer look at the Android project build system part II

This is the second post on the build system where we will take a closer look at the Android.mk file and what options are available. An Android.mk file describes the build for any native module that should go in the platform. We will start by looking at the makefile for the external ping facility found in external/ping.


ifneq ($(TARGET_SIMULATOR),true)

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)
LOCAL_SRC_FILES:= ping.c
LOCAL_MODULE := ping
LOCAL_STATIC_LIBRARIES := libcutils libc
include $(BUILD_EXECUTABLE)

endif # TARGET_SIMULATOR != true


The first line is just a check if we are building for the (obsolete?) simulator. The next line sets the local path to the current directory (the directory of this Android.mk file). This is handled by a function called mydir that can be found in the definitions.mk file in the build system.

The next step is to include a makefile that will clear all local variables with the line include $(CLEAR_VARS). CLEAR_VARS is set in the build configuration in config.mk and will include the clear_vars.mk file at this point. The main purpose of this include is to make sure that we do not use any local variables set by another module.

After the two initial lines that basically prepares the build system to start with this module we set the build variables. These are


LOCAL_SRC_FILES - the source files that make up this module
LOCAL_MODULE - the name of the module
LOCAL_STATIC_LIBRARIES - libraries to statically link to this module

Since ping will be an executable command placed in /system/bin in the Android file system the make file for building an executable should be used. This done with the line:

include $(BUILD_EXECUTABLE)

There are makefiles available in the build system that can be used to build a number of different types of module. To include them you may use one of the variables set in the config.mk file. A few important ones are:


BUILD_EXECUTABLE - Build an executable module
BUILD_SHARED_LIBRARY - Build a shared library
BUILD_STATIC_LIBRARY - Build a static library
BUILD_PREBUILT - Add prebuilt components


There is also a number of local variables that are recognized by the build system and that needs to be set in order to build your module.


LOCAL_C_INCLUDES - path to include files needed by your module, e.g. ($KERNEL_HEADERS)
LOCAL_CFLAGS - Any additional flags to pass to the compiler
LOCAL_LDFLAGS - Any additional flags to pass to the linker
LOCAL_SHARED_LIBRARIES - Shared libraries that the module directly links against
LOCAL_SRC_FILES - The source files to compile
LOCAL_STATIC_LIBRARIES - Static libraries to include in the module


You may use one Android.mk to build several items. It is possible to build both a library and an executable using the same makefile. To illustrate how to write a makefile for some native functionality we will look at another example. This makefile will build a shared library and an executable. It links to a couple of shared libraries in the system.



LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)
#Name of target to build
LOCAL_MODULE:= libmylibrary
#Source files to compile
LOCAL_SRC_FILES:= mysrcfile.c mysothersrcfile.c
#The shared libraries to link against
LOCAL_SHARED_LIBRARIES := libcutils
#No special headers needed
LOCAL_C_INCLUDES +=
#Prelink this library, also need to add it to the prelink map
LOCAL_PRELINK_MODULE := true
include $(BUILD_SHARED_LIBRARY)

#Clear variables and build the executable
include $(CLEAR_VARS)
LOCAL_MODULE:= myinfocmd
LOCAL_SRC_FILES:= mycmdsrcfile.c
include $(BUILD_EXECUTABLE)


The output of the build system is put in the out folder in the Android project. Build output is directed to a subfolder based on the product. A default build is for the generic product and will output everything target related to that folder. A shared library ends up in /out/target/product/generic/system/lib. In the same way an executable will end up in /out/target/product/generic/system/bin. The object files and intermediates are kept in the obj folder. The root, system, and data folders will be used to generate the file system images needed for Android in the last build step.


The Android boot process from power on

Since mobile platforms and embedded systems has some differences compared to Desktop systems in how they initially start up and boot this post will discuss the initial boot stages of an Android phone in some detail. Since we have used the Beagle Board as reference in some previous examples any specifics here are related to a similar system.

1. Power on and boot ROM code execution
At power on the CPU will be in a state where no initializations have been done. Internal clocks are not set up and the only memory available is the internal RAM. When power supplies are stable the execution will start with the Boot ROM code. This is a small piece of code that is hardwired in the CPU ASIC. For more information on boot ROM and configurations study the initalization chapter in
the Omap 3530 TRM.
  • A. The Boot ROM code will detect the boot media using a system register that maps to some physical balls on the asic. This is to determine where to find the first stage of the boot loader.
  • B. Once the boot media sequence is established the boot ROM will try to load the first stage boot loader to internal RAM. Once the boot loader is in place the boot ROM code will perform a jump and execution continues in the boot loader.
2. The boot loader
The boot loader is a special program separate from the Linux kernel that is used to set up initial memories and load the kernel to RAM. On desktop systems the boot loaders are programs like GRUB and in embedded Linux uBoot is often the boot loader of choice. Device manufacturers often use their own proprietary boot loaders. The requirements on a boot loader for Linux running on an ARM system can be found in the Booting document under /Documentation/arm in the kernel source tree.

  • A. The first boot loader stage will detect and set up external RAM.
  • B. Once external RAM is available and the system is ready the to run something more significant the first stage will load the main boot loader and place it in external RAM.
  • C. The second stage of the boot loader is the first major program that will run. This may contain code to set up file systems, additional memory, network support and other things. On a mobile phone it may also be responsible for loading code for the modem CPU and setting up low level memory protections and security options.
  • D. Once the boot loader is done with any special tasks it will look for a Linux kernel to boot. It will load this from the boot media (or some other source depending on system configuration) and place it in the RAM. It will also place some boot parameters in memory for the kernel to read when it starts up.
  • E. Once the boot loader is done it will perform a jump to the Linux kernel, usually some decompression routine, and the kernel assumes system responsibility.
3. The Linux kernel
The Linux kernel starts up in a similar way on Android as on other systems. It will set up everything that is needed for the system to run. Initialize interrupt controllers, set up memory protections, caches and scheduling.
  • A. Once the memory management units and caches have been initialized the system will be able to use virtual memory and launch user space processes.
  • B. The kernel will look in the root file system for the init process (found under system/core/init in the Android open source tree) and launch it as the initial user space process.
4. The init process
The init process is the "grandmother" of all system processes. Every other process in the system will be launched from this process or one of its descendants.

  • A. The init process in Android will look for a file called init.rc. This is a script that describes the system services, file system and other parameters that need to be set up. The init.rc script is placed in system/core/rootdir in the Android open source project.
  • B. The init process will parse the init script and launch the system service processes.
5. Zygote and Dalvik
The Zygote is launched by the init process and will basically just start executing and and initialize the Dalvik VM.
6. The system server
The system server is the first java component to run in the system. It will start all the Android services such as telephony manager and bluetooth. Start up of each service is currently written directly into the run method of the system server. The system server source can be found in the file frameworks/base/services/java/com/android/server/SystemServer.java in the open source project.


7. Boot completed
Added this part to the post on 20090831 since it is very useful and something I should not have left out from the beginning. Once the System Server is up and running and the system boot has completed there is a standard broadcast action called ACTION_BOOT_COMPLETED. To start your own service, register an alarm or otherwise make your application perform some action after boot you should register to receive this broadcast intent.

The separate boot steps and possible places to add your own functionality are covered in more detail in separate posts.

The System Server in Android

In this post I will add some more detail on the system server in Android. The system server is the core of the Android system and as described in the boot sequence post it is started as soon as Dalvik is initialized and running. The other system services will be running in the context of the System Server process. We will start by looking at the code that runs when the System Server starts. This code is found in the file frameworks/base/services/java/com/android/server/SystemServer.java (in the open source project tree) and we will start this discussion from the main entry point.

/**
* This method is called from Zygote to initialize the system. This will cause the native
* services (SurfaceFlinger, AudioFlinger, etc..) to be started. After that it will call back
* up into init2() to start the Android services.
*/
native public static void init1(String[] args);

public static void main(String[] args) {
// The system server has to run all of the time, so it needs to be
// as efficient as possible with its memory usage.
VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);

System.loadLibrary("android_servers");
init1(args);
}

public static final void init2() {
Log.i(TAG, "Entered the Android system server!");
Thread thr = new ServerThread();
thr.setName("android.server.ServerThread");
thr.start();
}

The first thing that happens is that the server will load a native library called android_servers that provides interfaces to native functionality. Source files for this lib are placed in frameworks/base/services/jni/. Then the native init method that will setup native services is called, init1(args), and executed. The name of the function that implements this is system_init() and the it resides in frameworks/base/cmds/system_server/library/system_init.cpp. After setting up the native services there is a callback:

runtime->callStatic("com/android/server/SystemServer", "init2");

to init2() above to create the server thread. This thread will start the remaining services in the system according to the necessary start order. A snippet of the initial sequence gives:

// Critical services...
try {
Log.i(TAG, "Starting Power Manager.");
power = new PowerManagerService();
ServiceManager.addService(Context.POWER_SERVICE, power);

Log.i(TAG, "Starting Activity Manager.");
context = ActivityManagerService.main(factoryTest);

Log.i(TAG, "Starting telephony registry");
ServiceManager.addService("telephony.registry", new TelephonyRegistry(context));

AttributeCache.init(context);

Log.i(TAG, "Starting Package Manager.");
pm = PackageManagerService.main(context,
factoryTest != SystemServer.FACTORY_TEST_OFF);

ActivityManagerService.setSystemProcess();

mContentResolver = context.getContentResolver();

Log.i(TAG, "Starting Content Manager.");
ContentService.main(context,
factoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL);

Log.i(TAG, "Starting System Content Providers.");
ActivityManagerService.installSystemProviders();

Log.i(TAG, "Starting Battery Service.");
BatteryService battery = new BatteryService(context);
ServiceManager.addService("battery", battery);

Log.i(TAG, "Starting Hardware Service.");
hardware = new HardwareService(context);
ServiceManager.addService("hardware", hardware);

// only initialize the power service after we have started the
// hardware service, content providers and the battery service.
power.init(context, hardware, ActivityManagerService.getDefault(), battery);

Log.i(TAG, "Starting Alarm Manager.");
AlarmManagerService alarm = new AlarmManagerService(context);
ServiceManager.addService(Context.ALARM_SERVICE, alarm);

...

We see that the power manager is started first, followed by the activity manager and the other services. There are a lot more services started after these initial and if you are interested take look in the SystemServer.java file. Each service is running in a separate Dalvik thread in the SystemServer process. To give some info on the components making up the system server we may have look at it using the DDMS tool:

We see that the main Android services such as the activity manager, package manager, alarm manager etc. are running in their separate threads but as parts of the system server process.

The init process and init.rc

In this post I will wrap up the analysis of what is going on at boot by looking at the Android init process and the init.rc file. If we start with the source you will find the code for the init process under /system/core/init in the source tree. The init process is what will set up all native services and this is similar to a regular Linux system boot. At this stage we are not executing in the actual android runtime. There is however some Android specifics going on already at this level. One example of this is that the init.rc script is written in a specific format called the Android init language. This is covered in the readme file that is kept in the same directory as the init source. Since I have not seen very much about it on the net though I will post some of the main concepts here. I will also give a small example on how to add your own native service at startup.

The Android init language
The language used by the init process has four classes of statements. These are actions, commands, services and options. Actions are associated to commands in the way that an action is a sequence of commands. An action also need something called a trigger in that the sequence of commands will be executed when the trigger event has occured. An exemple may look like:
on boot
ifup lo
hostname localhost
domainname localdomain
This action will run a command sequence to set up basic networking once it receives the boot trigger. The supported commands include export, chmod, chown and a few others. The complete list of available commands can be found in the readme file.
Services are programs that are launched by init. They are associated with options which control how they are started. The syntax for starting a service is:
service < name > < pathname > [< argument > ]*
< option >
< option >
...
There is a number of options available and a few of them are:
critical - this is a critical process and init will restart the device if it exists more than four times in four minutes
user < username > - change to this username before executing the service
group < groupname > [< groupname > ]* - change to groupname before executing the service
setenv < name > < value > - set environment variable < name > to < value > in the launched process
The init script is also the place where some important system properties are set. This is done with the setprop command and include things like the memory thresholds for applications, tcp buffer sizes etc.
The init.rc file itself is found in the root directory on a device and in the source tree it is kept under system/core/rootfs. The below example is the actual init.rc file that I have shortened significantly. The basic concepts are clearly illustrated. First there is an action on init where a long sequence of commands is run. As you can see it is accepted to use comments and they are preceded by #. A number of variables are setup during init and file systems are mounted. The next step is the boot action where networking is set up and properties assigned to the system. Then there is a list of services to be started by init.
on init
sysclktz 0
loglevel 3
# setup the global environment
export PATH /sbin:/system/sbin:/system/bin:/system/xbin
export LD_LIBRARY_PATH /system/lib
export ANDROID_BOOTLOGO 1
export ANDROID_ROOT /system
...
# mount mtd partitions
1. 
Mount /system rw first to give the filesystem a chance to save a checkpoint
mount yaffs2 mtd@system /system
mount yaffs2 mtd@system /system ro remount
2. 
We chown/chmod /data again so because mount is run as root + defaults
mount yaffs2 mtd@userdata /data nosuid nodev
chown system system /data
chmod 0771 /data
...
on boot
# basic network init
ifup lo
hostname localhost
domainname localdomain
# set RLIMIT_NICE to allow priorities from 19 to -20
setrlimit 13 40 40
# Define the oom_adj values for the classes of processes that can be
# killed by the kernel. These are used in ActivityManagerService.
setprop ro.FOREGROUND_APP_ADJ 0
setprop ro.VISIBLE_APP_ADJ 1
setprop ro.SECONDARY_SERVER_ADJ 2
setprop ro.BACKUP_APP_ADJ 2
setprop ro.HOME_APP_ADJ 4
setprop ro.HIDDEN_APP_MIN_ADJ 7
setprop ro.CONTENT_PROVIDER_ADJ 14
setprop ro.EMPTY_APP_ADJ 15
...
## Daemon processes to be run by init.
##
service console /system/bin/sh
console
# adbd is controlled by the persist.service.adb.enable system property
service adbd /sbin/adbd
disabled

Starting your own service at boot.
Normally there is not much need to do things in the init script and start services of your own. What is provided in the system goes a long way and often it may be better to add something to the Android runtime instead of using the native services. If you have a reason to add something or just what to try things out however it is relatively straight forward to add a native service to that init sequence. I have created a simple example that writes the time elapsed since it started to the log. It wakes up every three seconds. The code for exampleservice.c looks like:
#define LOG_TAG "Example Service"
#include < utils/log.h >
#include < unistd.h >
int main(int argc, char **argv)
{
    LOGI("Service started");
    int elapsed = 0;
    while(1)
    {
         sleep(3);
         elapsed += 3;
         LOGI("Service elapsed time is %d", elapsed);
    }
}
Place this somewhere in the platform build system and build as an executable. The build system will place the output in the /system/bin folder on the device. Now all that is needed is to add the following to the init.rc script:
service exampleservice /system/bin/exampleservice
user exampleservice
group exampleservice
oneshot
and your service will start on init. It is also possible to write your own file using the Android init language that enables your services and variables. Then just add a line to import the file in init.rc and you are done.
/Mattias

Back after the summer with some NDK comments

Time to pick up on the blog again after a summer where parts of the team have been on vacation and others have been hard at work in a couple of projects. In the mean time the Android platform has continued to evolve and a few things can be mentioned here:

1. The kernel has been removed from the Android manifest file and now requires a separate git pull if you are interested in it:

git clone git://android.git.kernel.org/kernel/common.git

This will save some time when syncing the repo and since the kernel was built outside the Android build system anyway it makes sense to keep it separated.

2. The NDK (Native Development Kit) was released allowing some support for native code in Android applications.
Making it possible to use native functionality in applications have been on the wish list for a long time and this is the first step in that direction. The list of supported API:s is very short though. The NDK currently supports:
  • libc (C library) headers
  • libm (math library) headers
  • JNI interface headers
  • libz (Zlib compression) headers
  • liblog (Android logging) header
  • A Minimal set of headers for C++ support
A c library combined with math and some logging capabilities provide enough for a some powerful algorithm implementations but to be of broader interest some more API:s are probably necessary. Natural candidates would be graphics support (openGL) and maybe some codecs. Currently the NDK is a good way to experiment with native functionality without going through the hoops of learning all about the platform and build system. For some applications it may also be exactly what is needed.

It looks like things will be picking up for the Android team during the fall and we aim to keep posting interesting tidbits here.

Starting an Android service after boot

After some consideration we decided that we should have a post about adding a regular Android service at boot and not just consider the cases where you have to modify the platform itself.

Simple boot service example

The key to this is the broadcast action android.intent.action.BOOT_COMPLETED that is sent out once the platform boot is complete. To perform an action on boot you need to include a broadcast receiver in your application that registers for this intent. The rest of the implementation follows the standard design for Android services and applications.
I have a small example that adds an Android service to perform a similar task as the native service that we had in the blog post about the init process. The service will start up at boot and then write something to the log at regular intervals. The first part we need is the broadcast receiver to take care of the boot intent:
package com.enea.training.bootdemo;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

/**
 * Simple receiver that will handle the boot completed intent and send the intent to 
 * launch the BootDemoService.
 * @author BMB
 *
 */
public class BootDemoReceiver extends BroadcastReceiver {
 @Override
 public void onReceive(final Context context, final Intent bootintent) {
  Intent mServiceIntent = new Intent();
mServiceIntent.setAction("com.enea.training.bootdemo.BootDemoService");
  context.startService(mServiceIntent);
 }
}
This component is basic and it will just create an intent to start our background service when it receives the boot completed intent.

The service will create a Timer task to write to the log at a preset interval. Once it is started the timer task will be registered and the service will keep running in the background.
package com.enea.training.bootdemo;

import java.util.Timer;
import java.util.TimerTask;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;

/**
 * Simple demo service that schedules a timer task to write something to 
 * the log at regular intervals.
 * @author BMB
 *
 */
public class BootDemoService extends Service {
 /**
  * Delay until first exeution of the Log task.
  */
 private final long mDelay = 0;
 /**
  * Period of the Log task.
  */
 private final long mPeriod = 500;
 /**
  * Log tag for this service.
  */ 
 private final String LOGTAG = "BootDemoService";
 /**
  * Timer to schedule the service.
  */
 private Timer mTimer;
 
 /**
  * Implementation of the timer task.
  */
 private class LogTask extends TimerTask {
  public void run() {
   Log.i(LOGTAG, "scheduled");
  }
 }
 private LogTask mLogTask; 
 
 @Override
 public IBinder onBind(final Intent intent) {
  return null;
 }
 
 @Override
 public void onCreate() {
  super.onCreate();
  Log.i(LOGTAG, "created");
  mTimer = new Timer();
  mLogTask = new LogTask();
 }
 
 @Override
 public void onStart(final Intent intent, final int startId) {
  super.onStart(intent, startId);
  Log.i(LOGTAG, "started");
  mTimer.schedule(mLogTask, mDelay, mPeriod);
 }
}
There is one more important thing to consider for this simple demo application and that is to add the correct intent-filters to the Android.xml file. We need to register for the BOOT_COMPLETED intent but also for the intent that will start the actual service.
< ?xml version="1.0" encoding="utf-8"?>
< manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.enea.oresund.training.bootdemo"
      android:versionCode="1"
      android:versionName="1.0">
      < uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
    < application android:icon="@drawable/icon" android:label="@string/app_name">
       < service android:name=".BootDemoService">
       < intent-filter>
       < action
       android:name = "com.enea.training.bootdemo.BootDemoService">
       < /action>
       < /intent-filter>
       < /service>
       < receiver android:name=".BootDemoReceiver">
       < intent-filter>
       < action
       android:name ="android.intent.action.BOOT_COMPLETED">
       < /action>
       < /intent-filter>
       < /receiver>
    < /application>
    < uses-sdk android:minSdkVersion="3" />
< /manifest> 

Summary - adding functionality at startup

With this post I think that we have covered the alternatives for adding functionality at some point during the boot process. To sum things up there is three possible places to do something like this:
  1. Modifying the init.rc script for native services
  2. Modifying the system server to include a separate thread
  3. Writing a standard Android service and register to launch it through the BOOT_COMPLETED intent
There may be other tricks you could use but they are more far-fetched. Unless you are building your own hardware or playing with the open source project for fun the third alternative is the only possible option. This is useful to register alarms or maybe an IM-client running in the background.
I would however like to add a word of caution since running services in the background will take some resources from the system. Think carefully about if you really need to automatically launch your service every time the system has booted up. It may be better to let the user choose when to start your application in order to save some system resources.

/Mattias

Examples on extending the framework

This post covers a couple of examples that are available in the Android open source project that provide a good start to exploring the framework and the JNI implementations in Android. If you are working with Android Open Source Project on hardware and want to test adding new API:s to the platform without breaking the structure these examples are really good.

The reason you may want to do this is that you are creating a device with some new features that you want to be available for some specific applications shipped with the device. It is also a good exercise to run through in order to understand the frameworks used by Android. This is the preferred way to do this and to quote Dianne Hackborn on the official mailing lists (found here):
If you are going to allow the user to keep Market on their phone, and are adding any new features, please do this the official way: include your own shared library with the features that applications use, rather than having magic hacks in the framework for them.

The example for this reside in the vendor/samples folder in the Android open source project. There are several components in this example:

  • The PlatformLibraryExample code itself which is a sample native library implementing some example platform functionality.
  • A java library that interfaces the platform library through JNI and exposes the API:s to applications.
  • A sample client application that uses this functionality

It is even possible to create an SDK add-on in order to have the added features easily available when developing applications. We will talk more about SDK add-ons in a later post.

To understand what is in this sample start out by reading the readme file in vendor/sample/frameworks/PlatformLibrary. This file describes the above components in more detail and will also tell you what you need to know in order to test the framework additions on a system.

If you are like us and like to try things out on the platform and work directly with some features that are not currently available in Android it is a good thing to follow these examples. It removes the need for making changes directly in the framework when exploring the possibilities of the platform.

/Mattias

Train Tracker - our first Android application

Even though application development has not been the main focus of the Enea Android Competence Center we decided to give it a try in order to widen our knowledge. For a couple of weeks we have been working on an application called Train Tracker. The application is mainly aimed to be used as an internal reference. The application shows real time train traffic information from Swedish train stations, some of the main features are:

  • Show all departing/arriving trains at a specific train station
  • Detect and warn for delayed trains.
  • Station search with auto complete text
  • Follow a train route (all arrival and departure times at all stations) for a specific train
  • Filter list of arrivals/departures (e.g. all departures from Lund towards Malmö)
  • Save a filter as a favourite. Favourites can be selected directly from the start page.
  • Set an alarm on train routes to get notified when the train is delayed.
  • Global search for stations and favourites integrated in Google Quick Search Box (Requires Android platform 1.6 or later and that Train Tracker is made searchable in Settings/Search/Searchable Items)

The information presented in the application is downloaded from http://banverket.se. Unfortunately Banverket was not willing to give us API access which is why our application is parsing HTML in order to get the information. This means that the application is likely to stop working if Banverket decides to change the layout of the webpage. Right now the application works quite well and if you want to try it out you can download TrainTracker.apk here, or use your favorite barcode scanner to get it:


Keep in mind that the application language is Swedish and it can only show information from Swedish trains and train stations. Here are some screenshots from Train Tracker:

Train Tracker start activity. Search for a station or select one of your saved favourites.


Train Tracker station activity. In this view you will find all arrivals/departures of a specific station.


Train Tracker filter activity. Here you can filter the list of arrivals/departures. Select “Spara Filter” to save the filter as a favourite. Select “Använd Filter” to apply the selected criteria.


Back at the station activity. This time filtered with the selected filter criteria and one of the departures has been expanded. Tapping the “Aktivera alarm” line will schedule an alarm for train 1067. Tapping The “Tåg 1067” line will take you to the train route activity for this train.


Train Tracker train route activity. At this view we display all train stops for a specific train. At the top of the screen a train delayed notification is received.


Global search in Google Quick Search Bar. Search hits from Train Tracker shows up together with ordinary search hits. Search hits gain higher priority in the search result list as they are selected.

Adding a system server to the Android framework

Following our other posts about booting and the system server, here are some more details of how to add a service to the system server.

It should be noted that extending the system server and other framework features is not recommended, as the code requires to be ported to future releases of the framework.
The most common reason for adding a system server would be for supporting proprietary hardware.

Design considerations
There are a few questions to be answered before implementing a system server, such as threads needed, application interfaces, and hardware interfaces. It's no easy task specifying your server design, but considering the following will hopefully help you out:
1. How frequently will the server run? If the server is only needed occasionaly, it might very well run within the system server context, even though the most common way is give it its own thread. A typical infrequent server is the Headset observer, which will only run when a headset is connected or removed.
2. How is the hardware accessed? Standard hardware could be accessible through device file access and file observers, but the best solution is no doubt to implement a HAL library. The HAL makes it easier to port your server to other hardware, and also makes it possible to run some functionality in native threads if needed.
3. Application interfacing? It is sometimes possible to get away with using intents and implementing your server as a receiver, but for anything but the simplest requests, you will no doubt have to use aidl.
4. Extending the framework? If you want to make your new interface visible to the applications, you will have to update the api description and build your own sdk. (That is easily done with "make update-api", followed by "make sdk".) However, if you only want the your nifty features to be accessible from your own proprietary applications, you should make use of the javadoc @hide-option for your interface.
5. Is there another way? Adding your own server adds migration work for new releases of the framework. To minimise files added, it's easy to be tempted to alter existing services instead of adding your own. That is fine to do, but keep in mind that if some functionality changes, third-party applications may not work anymore. Again, if your server will only be accessed from a proprietary application and not publicly available, consider adding the code to the application instead.

Code sample
Following is an example of a proprietary service, that knows how to set a value. For simplicity, the code is just added to the framework. For a production implementation, the code should go into the vendor directory.

Specifying the interface.
This example uses aidl, so the first step is to add an interface definition file:
frameworks/base/core/java/android/os/IEneaService.aidl
package android.os;

interface IEneaService {
  /**
  * {@hide}
  */
  void setValue(int val);
}

The interface file will need to be added to the build system:
frameworks/base/Android.mk
Add the following around line 165 (the end of the list of SRC_FILES):
core/java/android/os/IEneaService.aidl \


Implementing the server
The service spawns a worker thread that will do all the work, as part of the system server process. Since the service is created by the system server, it will need to be located somewhere where the system server can find it.
frameworks/base/services/java/com/android/server/EneaService.java
package com.android.server;

import android.content.Context;
import android.os.Handler;
import android.os.IEneaService;
import android.os.Looper;
import android.os.Message;
import android.os.Process;
import android.util.Log;

public class EneaService extends IEneaService.Stub {
  private static final String TAG = "EneaService";
  private EneaWorkerThread mWorker;
  private EneaWorkerHandler mHandler;
  private Context mContext;

  public EneaService(Context context) {
    super();
    mContext = context;
    mWorker = new EneaWorkerThread("EneaServiceWorker");
    mWorker.start();
    Log.i(TAG, "Spawned worker thread");
  }

  public void setValue(int val)
  {
    Log.i(TAG, "setValue " + val);
    Message msg = Message.obtain();
    msg.what = EneaWorkerHandler.MESSAGE_SET;
    msg.arg1 = val;
    mHandler.sendMessage(msg);
  }

  private class EneaWorkerThread extends Thread{
    public EneaWorkerThread(String name) {
      super(name);
    }

    public void run() {
      Looper.prepare();
      mHandler = new EneaWorkerHandler();
      Looper.loop();
    }
  }

  private class EneaWorkerHandler extends Handler {
    private static final int MESSAGE_SET = 0;

    @Override
    public void handleMessage(Message msg) {
      try {
        if (msg.what == MESSAGE_SET) {
          Log.i(TAG, "set message received: " + msg.arg1);
        }
      } catch (Exception e) {
        // Log, don't crash!
        Log.e(TAG, "Exception in EneaWorkerHandler.handleMessage:", e);
      }
    }
  }
}

You may want to add to the log printouts the thread id or name just to visualise which thread the code is executing in.

All that's left to do now is to type make to build the repository, and then start up the emulator. Using logcat, you will find the message saying that the thread has been spawned.


Test program
You probably want to test your service as well. For this you can create a "Hello World" activity using the project wizard. Place the project in the vendor/enea directory.

In the main activity class of your test program, add the following lines to onCreate()
IEneaService em = IEneaService.Stub.asInterface(ServiceManager.getService("EneaService"));
try {
  em.setValue(7); // Any value would do, really.
} catch (Exception e) {
  e.printStackTrace();
}

You will also need to import android.os.IEneaService and of course add an apropriate Android.mk to build your test program.

Start your test program and look in the log. You should now find the "set value"-messages.

Cheers
Robert

Howto setup a android project in Eclipse that access both Java and C/C++ code

If you follow the instructions on http://source.android.com/using-eclipse you will only have a Java project and will only see the C/C++ project files as 2:nd class citizens without any indexing. I will propose a another solution that will combine the ideas from http://lorinc.blogspot.com/2006/10/how-to-mix-java-and-c-code-in-singe.html.
1. Copy the already available Java setup
$ cd <your mydroid folder>
$ cp development/ide/eclipse/.classpath .
# You might need to make the copy writable (describe on android.com) 
$ chmod u+w .classpath 
2. From Eclipse create a new C++ project File -> New -> Other, select C/C++ -> C++ Project give it a project name and uncheck "Use default location"
and give it the path to your directory (often called the mydroid dir)
Select Project Type: "Makefile project" -> "Empty Project", let the "-- Other Toolchain" be selected and press "Finish"

3. Add in Java to the same project
Close Eclipse as you will edit a file it holds open and will overwrite otherwise Now a /.project file has been created open it in a text editor and add the following:
<buildCommand>
    <name>org.eclipse.jdt.core.javabuilder</name>
    <arguments></arguments>
</buildCommand>
and
<nature>org.eclipse.jdt.core.javanature</nature>
as described here:
<?xml version="1.0" encoding="UTF-8"?>
<projectdescription>
    <name>android zoom2</name>
    <comment></comment>
    <projects>
    </projects>
    <buildspec>
------------------------------- below is added 
        <buildCommand>
            <name>org.eclipse.jdt.core.javabuilder</name>
     <arguments>
     </arguments>
        </buildCommand>
------------------------------- end of the added stuff 
        <buildcommand>
            <name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
            <triggers>clean,full,incremental,</triggers>
...
        </buildCommand>
    </buildSpec>
    <natures>
        <nature>org.eclipse.cdt.core.cnature</nature>
 <nature>org.eclipse.cdt.core.ccnature</nature>
  <nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
 <nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
------------------------------- below is added 
 <nature>org.eclipse.jdt.core.javanature</nature>
------------------------------- end of the added stuff 
    </natures>
...
Now start eclipse again, now the Java classes are available in "Project Explorer" view and C/C++ files in "C/C++ Projects" view.

One problem remain when you build it will use "make all" and that will not work and need to be changed to "make" this can be done if you right-click on the project and select "Properties"
In the "Properties" window select "C/C++ Build" and click on the "Behaviour" tab and remove "all" from all the places where available.

I still used the java heap enlargement in eclipse.ini from the first link by changing the numbers in eclipse.ini to the numbers below:
-Xms128m
-Xmx512m
-XX:MaxPermSize=256m

The standard eclipse from Ubuntu 9.10 (installed from synaptic) uses this file /usr/lib/eclipse/eclipse.ini you need to be root to edit it e.g.

$ sudo gedit /usr/lib/eclipse/eclipse.ini

/Zingo

Working with Android on development boards

This will be the first of a set of post on a project we are doing where we will use an Android powered dev board to provide UI and user control features for an embedded system. I will get back to the setup in later posts but in brief it will consist of two boards, one running a traditional control system and one running a slightly adapted Android platform with extra API:s to interact with the control system. This part focuses on working with Android on dev boards in general and discusses a couple of boards in particular.


For platform level hacking the open source project provides a good start with the emulator and that is useful for things like working with the base applications and examining the framework. The emulator is however limited and for a lot of platform level work real hardware is the best way to go. For real hardware there are two routes, either use an existing phone or use some kind of development board. Existing phones are fun platforms for tinkering and enabling features in the way they to it at xda-developers and other forums. As a general lab environment they are limited since they often have very few hardware interfaces exposed and they are often locked down in ways that make interacting with them difficult.


Development boards on the other hand are often made especially for trying out new designs, connecting hardware and having easy debug access. These are often the best platform for working with low level stuff on Android. In fact most phone manufacturers start out with some kind of platform dev board to facilitate early development before they wrap everything in great looking metal and plastic.

So let us look at working with Android on embedded development boards. First you should decide on why you want to go this route. Dev boards are excellent for:

  • Low level work on the Android open source project, testing and debugging hardware interaction etc.
  • Hobby projects where you want to design a great Android based interface for your home-made toaster and need to hook up the android system to some outside electronics.
  • Professional projects where you are considering building an Android based product, be it a phone, a tablet, music player etc.
  • Anyone else who wants to explore the full capabilities of Android and understand the platform without the limitations of the emulator or set hardware design of a phone.

Dev boards are probably not the way to go for:

  • Getting a basic understanding of how to build and run the Android source code. The open source project and the emulator are more than sufficient for that.
  • Application development work. The SDK and existing phones are perfect for that and saves you a lot of hassle with jumpers, adb bridging and so on.


Factors to consider

Now let us say that you are still interested in working with Android on a development board. Then we get to the interesting part on deciding on which one to get. Here I would say there are a few important factors to consider:

  • Purpose - what to you plan to do with the board
  • Price
  • Performance
  • Existing Android ports for the board
  • Community
  • Debugging utilities
  • Expansion possibilities

All of these are important but do not underestimate the power of having an active community around your platform that can help you out if you run into problems. Start by looking at the above factors and note down your requirements in each aspect. And do not forget to take into account other things that I have left out in this bullet list. Once you have some idea of what you need we can start looking at what is available. And that is becoming quite a lot.


Let me start by grouping the different boards into a few categories. And here I will add in a limitation. I will mostly consider ARM-based dev boards since this is the architecture with the widest Android adoption so far and almost all commercial devices shipped so far are based on ARM. That said there is a very active community around Android on x86 and also MIPS ports. And probably a few more. The most prominent feature of any dev board is the applications processor and system on chip design that will run the actual Android system. Based on that I will use the following categories for ARM based designs:
  • State of the art - these are dev boards with high performance system on chips that are often prototypes of platforms that are not even available in commercial products yet.
  • High end, these are dev boards with an applications processor that matches the high end Android phones that are available today.
  • Mid and low end - these are either boards with performance that matches early or low end Android phones.

State of the art development boards

These platforms are based  on dual-core Arm Cortex A9, 1 GHz plus, system on chips with graphics acceleration and other features. In this category I am only aware of a couple of platforms that can be obtained as development boards for general purposes. Two are based on the TI Omap 4 system on chip and can be ordered either as the cheap panda board or as the more full featured Blaze kit which include touch screens and keyboard. If you are based in North America it is also possible to get the Tegra 250 dev kit from Nvidia with similar specs. These boards are interesting since they have more processing power available than anything else on the market but they are also fairly new designs with limited community track record. They may be perfect for experienced embedded hobbyists that want to build a HTPC setup or similar. If you have very little experience working with embedded development it may be better to start out with something with a longer track record and more information available on forums, blogs and wikis. For professionals you need to consider if you really need this kind of processing power in your design. Maybe advanced 3D graphics and full HD video is not part of your use case and then maybe these types of platforms will eat more power and cause more issues with advanced features than they provide benefits.


High end development boards.

These are ARM Cortex A8 based designs similar to what is powering most of the high end Android smarthphones that are available today. In this category we have a number of SoC and a large amount of development boards based on these SoCs. To mention a few of the families we have the Freescale i.Mx 515, evolution dev kit and android tool and the Texas Instruments OMAP3, most notable the Beagle board and the Zoom II dev kit. Since these run on the same CPU family (ARM Cortex A8) as most of the commercially available Android phones do and have been around for a while they are often well tested and relatively stable. This is especially true of the Omap based Beagle board which features a large developer community. The Omap on the Beagle board is also very similar to the Omap that powers the popular Motorola Droid phone. There are a number of derivatives from the Beagle with more peripherals and expansion possibilities.


Mid and low end development boards.

This is a more unexplored area but with some interesting products. Android this far has been a lot about performance and most community boards have been higher end boards but as interest for using Android outside the smartphone space is increasing so is the number of low cost platforms with support for the system. These boards are generally based on ARM926 or ARM11 CPUs and have a limited set of accellerators and peripherals. Many dev boards in this category have too little memory to run Android (128 MB RAM is some kind of current minimum but more is even better). There are some Samsung boards, something from Renesas and once again probably a lot of others. The board that we have worked with in this category is from Atmel, the AT91SAM9M10-EKES borad. While their Android community is relatively young compared to the Beagle board Atmel has a tradition of having a thriving community around their at91 platforms in general.


Some practical details

Now that we are finally past the overview we can get to the practical details on working with development boards. If you are considering to get a develoment board for Android I would suggest that you try to download and build whatever Android distribution is availble for that board before you get the hardware. The state of the distribution will tell you a lot about how hard it will be to get the hardware working later on. If there is no Android distribution available for your hardware make sure that you are aware what the porting effort will be and also analyze that the hardware will even be capable of running Android in terms of performance and memory available.

Another thing to investigate is how you will boot and run Android on the dev board. Does it contain a NAND flash or SD card interface. Is it possible to set up a network file system and boot Android from that? Having working adb tools are also very nice when working on a dev board. It is much more convenient to update just your shared library through an adb sync instead of having to build, generate a system image and flash it to the board every time you need to test an update.
Regardless of what board you choose prepare to spend some time understanding how to boot it up with your Android build. Often they are delivered with some other software as default configuration. Prepare to spend a few hours up to a few days just to get familiar with boot and flash options. How to set the jumpers in the correct state to be able reflash the board etc.


Our experience

These are some impressions for three of the different boards that we have worked with so far.

Beagle board:
BeagleBoard in action
Pros:
  • Very powerful board for the price tag.
  • Good community around Android and the Rowboat distribution on TI Omap
  • Well tested CPU for Android, very similar to the SoC powering the Motorola Droid and other devices
  • A lot of other Linux work happening on the Omap platform such as MeeGo
  • Decent debug support
  • Relatively easy to get started with and several boot options
Cons:
  • No ethernet support in default configuration, has to be added via USB.
  • No touch screen or other peripherals included, not even power adapter
Summary:
The Beagle board is a very powerful board for the price ($149) and if you connect to a regular monitor and keyboard it is a very capable development platform for low level work. We have run a number of projects on this platform ranging from initial demos and driver projects to advanced research stuff. The limitations made to keep the price down are a bit annoying and nowadays I would recommend getting the updated BeagleBoard xM version instead. That will add an ethernet port and more USB ports. There are also versions and derivatives that include screens etc.

Zoom II:
This is another OMAP based device but includes and the SoC is very similar to the BeagleBoard but it is packaged more like a real device with touch screen and keyboard.
Pros:
  • Much more peripherals included compared to the Beagle
  • Portable device like package, good for demos
Cons:
  • More expensive than the Beagle
Summary:
This device is very similar to the Beagle board and shares the same attributes beyond the two things mentioned here.

Atmel AT91SAM9M10-EKES:
An Atmel boad with Android up and running
Pros:
  • Includes touch screen directly on the board
  • Connection cables and power supply included
  • Good community around the at91 boards in general, emerging Android community
  • Based on relatively small and low cost ARM926 CPU
  • Good value for money for a relatively complete kit
Cons:
  • Dev tools seem a bit Windows focused, it was a little bit tricky to get started from a Linux dev machine
  • Android support is relatively new for this platform, not as well tested as the Omap distributions
Summary:
I think this is a really interesting dev kit. Especially when looking at developing things that do not have the high-end smartphone level of performance requirements. Since it includes a screen and decent amount of connections it can be used as a compact demo board. We got this relatively recently and will probably base our next demo on it. After some initial hickups with the tools it is straight forward to develop on and the support from Atmel and the community seems to be growing rapidly. We still need to do some benchmarking though and see how it handles Android compared to higher end alternatives.


I hope this article provides some insight on working with Android on development boards. With the amount of Android related news currently I am sure I have missed some capable platforms. Feel free to add whatever platform you are familiar with in the comments and I will update this post with more info. Once again I would like to remind you that I have skipped entire architectures such as x86, MIPS and PowerPC in this article.

/Mattias

Using the local_manifest.xml file in repo to customize your Android project setup

This post will discuss how to use repo and the local_manifest.xml file to keep track of projects that are not part of the default manifest for the Android open source project. This can be used to keep track of some projects that are maintained by the Android team but are not included in the default distribution. It can also be used to include other git-based projects within your android platform source tree. Adding a local manifest file is a good way to set up a personalized environment to work with Android for hacking or in a small team. Any additions to Android can be kept in separate git repositories and tracked using the local manifest. For commercial level projects it may be better to run your own repo server and edit the manifest directly to make sure that it is version controlled and that all developers see the same projects. We may get back to that topic in a separate blog post.

Now let's take a look at the practical details. The format of the local manifest file follows the standard manifest format described in the manifest-format.txt file under .repo/repo/docs in the Android Open Source project. To create a local manifest add a file with the name local_manifest.xml and place it directly in the .repo folder of your Android Open Source Project. It will be parsed by repo as part of a normal repo sync.

I keep a project on machine to track the latest development in the Android platform. It is setup to track the current master branch in the default configuration. Since I often work with hardware as well I am also interested in developments in the kernel. Currently there are a number of different kernel trees being run as part of android. None of them are part of the default manifest. In my setup I want to track the common kernel but also see what is going on with hardware support for Qualcomm (msm) and TI (omap) platforms. These are all maintained by the android team and I can use the default remote site to get them. I need however to inform repo about what branch I want to track by adding the revision tag. For each project add a tag like this:
<project path="kernel"
      name="kernel/common"
      remote="korg"
      revision="android-goldfish-2.6.29"/>

Another thing I also find myself using is Busybox and since I set it up the build config and do some adaptations when using it with Android I like to track the source for that as well within my Android tree. This can easily be achieved in the local manifest by adding a new remote site for Busybox and then adding the project itself like this:
<remote  name="busybox"
           fetch="git://git.busybox.net/"/>
<project path="busybox"
      name="busybox"
             remote="busybox"/>
To sum things up this means that each time I do a repo sync I will get the latest version of the Android Open source project and also updated repositories for the three different kernel trees that I track and an updated busybox source. All in all my local_manifest file looks like this:
<?xml version="1.0" encoding="UTF-8"?>
  <manifest>

    <remote  name="busybox"
           fetch="git://git.busybox.net/"/>

    <project path="kernel"
      name="kernel/common"
      remote="korg"
      revision="android-goldfish-2.6.29"/>
    <project path="kernel_msm"
      name="kernel/msm"
      remote="korg"
             revision="android-msm-2.6.32"/>
    <project path="kernel_omap"
      name="kernel/omap"
      remote="korg"
             revision="android-omap-2.6.32"/>
    <project path="busybox"
      name="busybox"
             remote="busybox"/> 
</manifest>

Android Open Source Project workflow

Thought I should share a couple of flowcharts showing how to do basic work with the platform source code. In this case we assume that there is a platform library that need some adaptations. It is impossible to cover all the steps in an overview like this but look at is as a basic guide if you have limited experience of the platform source. I have divided the guide into two different images. The first one shows the practical work itself (i.e. the "happy hacking") while the second one illustrates the steps needed to handle the change in an environment using repo and gerrit.

Part 1 - code changes
This part assumes you are working with the Android open source project for a device or some other project and have some changes that need to be made to a platform module. The utility commands described here all come from the envsetup script. There is a lot more to say about things like testing depending on your general setup but I hope this provides an illustration on how to go about making a small change in the Android platform and trying it out.

Part 2 - commit and review
Making a change is all good if you are just trying things out. In a real project however you are probably working with a setup using repo and gerrit for your project and would like to submit your changes. This flowchart provides additional details on the repo and git commands needed to go along with a change as described in part 1. 

Feel free to comment if you find these charts useful or if you think I should add or change things.

/Mattias B

Using Checkstyle with Android Open Source Project

This post provides a small Checkstyle template that we have been using to conform with the code style guide proposed by the Android Open Source Project. For pure formatting issues also see this question on stackoverflow.

1. Make sure that the Checkstyle plugin is installed in Eclipse. If not, follow the steps below. Note that these instructions are for Eclipse Galileo. If you are using another version, some of the installation steps might differ.
            1. Open "Help" -> "Install New Software"
            2. Paste the link: http://eclipse-cs.sf.net/update into the "Work with:" field and click "Add..."
            3. Name the site e.g. "Checkstyle"
            4. Check the box next to the latest version of the Checkstyle plugin and press "Next->"
            5. Follow the instructions to complete the installation

2. Save the contents below to a new xml file and place it on a location of your choice.
3. Open "Window" -> "Preferences" and choose Checkstyle
4. Press "New..."
5. Fill in the configuration properties
            "Type: External Configuration File"
            "Name: Android checkstyle by Enea"
            "Location:" Browse to the saved android_cs.xml file
6. Press OK twice

7. Right click on your Android project and choose Properties
8. Choose Checkstyle and check the box "Checkstyle active for this project"
9. Select "Android checkstyle by Enea" from the drop down list
10. Rebuild the project to analyze your code

Done!

Karin, Fredrik and Karl

Note: If you want to edit the checkstyle configuration open "Window" -> "Preferences" and choose Checkstyle.
Mark the Check Configuration you want to edit and press "Properties..."

Save this to an .xml file.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE module PUBLIC "-//Puppy Crawl//DTD Check Configuration 1.3//EN" "https://home.enea.com/dtds/,DanaInfo=www.puppycrawl.com,CT=dtd+configuration_1_3.dtd">

<!--
    This configuration file was written by the eclipse-cs plugin configuration editor
-->
<!--
    Checkstyle-Configuration: Android checkstyle by Enea
    Description: none
-->
<module name="Checker">
  <property name="severity" value="warning"></property>
  <module name="TreeWalker">
    <property name="tabWidth" value="4"></property>
    <module name="JavadocMethod">
      <property name="logLoadErrors" value="true"></property>
      <property name="suppressLoadErrors" value="true"></property>
    </module>
    <module name="JavadocType"></module>
    <module name="JavadocVariable"></module>
    <module name="JavadocStyle"></module>
    <module name="ConstantName"></module>
    <module name="LocalFinalVariableName"></module>
    <module name="LocalVariableName"></module>
    <module name="MemberName">
      <metadata name="net.sf.eclipsecs.core.comment" value="only public starts without m"></metadata>
      <property name="applyToProtected" value="false"></property>
      <property name="applyToPrivate" value="false"></property>
    </module>
    <module name="MethodName"></module>
    <module name="PackageName"></module>
    <module name="ParameterName"></module>
    <module name="StaticVariableName">
      <metadata name="net.sf.eclipsecs.core.comment" value="starts with 's'"></metadata>
      <property name="format" value="^[s][a-zA-Z0-9]*$"></property>
    </module>
    <module name="TypeName"></module>
    <module name="AvoidStarImport"></module>
    <module name="IllegalImport"></module>
    <module name="RedundantImport"></module>
    <module name="UnusedImports"></module>
    <module name="LineLength">
      <property name="severity" value="ignore"></property>
      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"></metadata>
    </module>
    <module name="MethodLength"></module>
    <module name="ParameterNumber"></module>
    <module name="EmptyForIteratorPad"></module>
    <module name="MethodParamPad"></module>
    <module name="NoWhitespaceAfter">
      <property name="tokens" value="BNOT,DEC,DOT,INC,LNOT,UNARY_MINUS,UNARY_PLUS"></property>
    </module>
    <module name="NoWhitespaceBefore"></module>
    <module name="OperatorWrap"></module>
    <module name="ParenPad"></module>
    <module name="TypecastParenPad"></module>
    <module name="WhitespaceAfter"></module>
    <module name="WhitespaceAround"></module>
    <module name="ModifierOrder"></module>
    <module name="RedundantModifier"></module>
    <module name="AvoidNestedBlocks"></module>
    <module name="EmptyBlock"></module>
    <module name="LeftCurly"></module>
    <module name="NeedBraces"></module>
    <module name="RightCurly"></module>
    <module name="AvoidInlineConditionals"></module>
    <module name="DoubleCheckedLocking"></module>
    <module name="EmptyStatement"></module>
    <module name="EqualsHashCode"></module>
    <module name="HiddenField"></module>
    <module name="IllegalInstantiation"></module>
    <module name="InnerAssignment"></module>
    <module name="MagicNumber"></module>
    <module name="MissingSwitchDefault"></module>
    <module name="RedundantThrows">
      <property name="logLoadErrors" value="true"></property>
      <property name="suppressLoadErrors" value="true"></property>
    </module>
    <module name="SimplifyBooleanExpression"></module>
    <module name="SimplifyBooleanReturn"></module>
    <module name="DesignForExtension">
      <property name="severity" value="ignore"></property>
      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"></metadata>
    </module>
    <module name="FinalClass"></module>
    <module name="HideUtilityClassConstructor"></module>
    <module name="InterfaceIsType"></module>
    <module name="VisibilityModifier"></module>
    <module name="ArrayTypeStyle"></module>
    <module name="FinalParameters">
      <property name="severity" value="ignore"></property>
      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"></metadata>
    </module>
    <module name="TodoComment">
      <property name="severity" value="ignore"></property>
      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"></metadata>
    </module>
    <module name="UpperEll"></module>
    <module name="MethodLength">
      <property name="max" value="40"></property>
    </module>
    <module name="MemberName">
      <metadata name="net.sf.eclipsecs.core.comment" value="non public members should start with m"></metadata>
      <property name="applyToPublic" value="false"></property>
      <property name="format" value="^[m][a-zA-Z0-9]*$"></property>
    </module>
    <module name="LineLength">
      <property name="max" value="100"></property>
    </module>
  </module>
  <module name="JavadocPackage"></module>
  <module name="NewlineAtEndOfFile">
    <property name="severity" value="ignore"></property>
    <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"></metadata>
  </module>
  <module name="Translation"></module>
  <module name="FileTabCharacter">
    <property name="severity" value="ignore"></property>
    <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"></metadata>
  </module>
  <module name="RegexpSingleline">
    <property name="severity" value="ignore"></property>
    <property name="format" value="\s+$"></property>
    <property name="message" value="Line has trailing spaces."></property>
    <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"></metadata>
  </module>
</module> 
Upplagd av Enea Android Team

Share memory using ashmem and binder in the android framework

To share memory between different processes in the android framework ashmem can be used. Ashmem is a android shared memory addon to the linux kernel.
Ashmem has reference counting so that if many processes use the same area the area will not be removed until all processes has released it, the memory is also virtual and not physically contiguous. If physically contiguous memory is needed like for hardware reasons pmem can be used, but it has no reference counting and is not part of standard Android kernel.
In this blog post we will concentrate only on ashmem.

Ashmem is allocated via ashmem_create_region() that gives you an file descriptor then you use mmap() on it to get a memory area:

int fd = ashmem_create_region("SharedRegionName", size); if(fd == 0) {
  data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
  if(data != MAP_FAILED)
  {
    /* It works do your stuff*/
  }
}

But this will not solve your problem on how to share the memory area. The first problem is that the memory pointer "data" in our example above is per process and can't be shared. The next problem is that for security reasons the name "SharedRegionName" in the example above are not shared between processes. The "other" process that want to access the same shared memory area can't use a ashmem_create_region() with the same name to get access to the same physical memory area. Instead the file descriptor (fd in the example above) needs to be used in a new mmap() in the "other" process. Here comes the third problem, the file descriptor are per process and can't be shared with the other process just like that. Bummer!

The solution is to share the file descriptor with the binder since the binder has special functions that can be used to transfer file descriptors over it's interface.
To help you with ashmem handeling and file descriptor sharing the class MemoryHeapBase can be used.

To transfer the MemoryHeapBase object you can use the asBinder() on the IMemoryHeap interface class on the server side to transfer the needed information to setup an new area on the client side mapped to the same physical memory.

sp<imemoryheap> memHeap = ...
reply->writeStrongBinder(memHeap->asBinder())

On the client side the MemoryHeapBase class will take care of all the needed stuff for you and all you need to do in your binder wrapper class is something like this:

sp<imemoryheap> memHeap;
memHeap = interface_cast<imemoryheap> (reply.readStrongBinder());


Please remember that the mmap:ed memories virtual address is not equal to the physical address even more important that the virtual address is different to each process and might be different for every call to the
getBufferMemPointer() function even if the same ashmem region is used so be careful if you have stored your pointer somewhere and still operate on it.

Here is a complete example setting up everything needed to get this working.

Interface header: IEneaBuffer.h
/*
 * IEneabuffer.h
 *  Created on: 19 mars 2010  Author: Zingo Andersen
 *  License: Public Domain (steal and use what you like)
 *
 * Buffer classes to handle the binder communication  */

#ifndef IENEABUFFER_H_
#define IENEABUFFER_H_

#include <utils/RefBase.h>
#include <binder/IInterface.h>
#include <binder/Parcel.h>
#include <binder/IMemory.h>
#include <utils/Timers.h>

namespace android {

class IEneaBuffer: public IInterface
{
public:
  DECLARE_META_INTERFACE(EneaBuffer);
  virtual sp<IMemoryHeap>           getBuffer() = 0;
};

/* --- Server side --- */

class BnEneaBuffer: public BnInterface<IEneaBuffer>
{
public:
  virtual status_t    onTransact( uint32_t code,
                                  const Parcel& data,
                                  Parcel* reply,
                                  uint32_t flags = 0);
};

}; // namespace android

#endif /* IENEABUFFER_H_ */

Interface class: IEneaBuffer.cpp
/*
 * IEneaBuffer.cpp
 *  Created on: 19 mars 2010  Author: Zingo Andersen
 *  License: Public Domain (steal and use what you like)
 *
 * Buffer classes to handle the binder communication
 */

//#define LOG_TAG "IEneaBuffer"
#include <utils/Log.h>
#include <stdint.h>
#include <sys/types.h>
#include <binder/MemoryHeapBase.h>
#include <IEneaBuffer.h>

namespace android {

enum {
    GET_BUFFER = IBinder::FIRST_CALL_TRANSACTION
};

/* --- Client side --- */
class BpEneaBuffer: public BpInterface<IEneaBuffer>
{
public:
  BpEneaBuffer(const sp<IBinder>& impl) : BpInterface<IEneaBuffer>(impl)
    {
    }

  sp<IMemoryHeap> getBuffer()
  {
    Parcel data, reply;
    sp<IMemoryHeap> memHeap = NULL;
    data.writeInterfaceToken(IEneaBuffer::getInterfaceDescriptor());
    // This will result in a call to the onTransact()
    // method on the server in it's context (from it's binder threads)
    remote()->transact(GET_BUFFER, data, &reply);
    memHeap = interface_cast<IMemoryHeap> (reply.readStrongBinder());
    return memHeap;
  }
};

IMPLEMENT_META_INTERFACE(EneaBuffer, "android.vendor.IEneaBuffer");

/* --- Server side --- */

status_t BnEneaBuffer::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
  switch (code)
  {
    case GET_BUFFER:
    {
      CHECK_INTERFACE(IEneaBuffer, data, reply);
      sp<IMemoryHeap> Data = getBuffer();
      if (Data != NULL)
      {
        reply->writeStrongBinder(Data->asBinder());
      }
      return NO_ERROR;
      break;
    }
    default:
      return BBinder::onTransact(code, data, reply, flags);
  }
}

}; // namespace android

Then use it in your server class by inherit the server class with something like this:

Server command: EneaBufferServer.cpp
/*
 * EneaBufferServer.cpp
 *  Created on: 19 mars 2010  Author: Zingo Andersen
 *  License: Public Domain (steal and use what you like)
 *
 *  The Server will create a shared area that the client will then use
 *  The server will initiate the first int in the area and print it's value every
 *  5s. If you start the client in parallell it will try to change this value
 *  (value=value+1).
 */


#include "IEneaBuffer.h"
#include <binder/MemoryHeapBase.h>
#include <binder/IServiceManager.h>
#include <binder/IPCThreadState.h>

namespace android {

#define MEMORY_SIZE 10*1024  /* 10Kb shared memory*/

class EneaBufferService : public BnEneaBuffer {
public:
  static void instantiate();
  EneaBufferService();
  virtual ~EneaBufferService();
  virtual sp<IMemoryHeap> getBuffer();
private:
  sp<MemoryHeapBase> mMemHeap;
};

sp<IMemoryHeap> EneaBufferService::getBuffer()
{
  return mMemHeap;
}

void EneaBufferService::instantiate()
{
  status_t status;
  status = defaultServiceManager()->addService(String16("vendor.enea.Buffer"), new EneaBufferService());
}

EneaBufferService::EneaBufferService()
{
  //The memory is allocated using a MemoryHeapBase, and thereby is using ashmem
  mMemHeap = new MemoryHeapBase(MEMORY_SIZE);
  unsigned int *base = (unsigned int *) mMemHeap->getBase();
  *base=0xdeadcafe; //Initiate first value in buffer
}

EneaBufferService::~EneaBufferService()
{
  mMemHeap = 0;
}


static sp<IMemoryHeap> receiverMemBase;

unsigned int * getBufferMemPointer(void)
{
  static sp<IEneaBuffer> eneaBuffer;

  /* Get the buffer service */
  if (eneaBuffer == NULL)
  {
    sp<IServiceManager> sm = defaultServiceManager();
    sp<IBinder> binder;
    binder = sm->getService(String16("vendor.enea.Buffer"));
    if (binder != 0)
    {
      eneaBuffer = IEneaBuffer::asInterface(binder);
    }
  }
  if (eneaBuffer == NULL)
  {
    LOGE("The buffer service is not published");
    return (unsigned int *)-1; /* return an errorcode... */
  }
  else
  {
    receiverMemBase = eneaBuffer->getBuffer();
    return (unsigned int *) receiverMemBase->getBase();
  }
}


}

using namespace android;

int main(int argc, char** argv)
{
 unsigned int *base;

    EneaBufferService::instantiate();

    //Create binder threads for this "server"
    ProcessState::self()->startThreadPool();
    LOGD("Server is up and running");

    base = getBufferMemPointer();


    for(;;)
    {
     LOGD("EneaBufferServer base=%p Data=0x%x", base,*base);
     sleep(5);
    }
    // wait for threads to stop
    //   IPCThreadState::self()->joinThreadPool();
    return 0;
}



You need add the following line to register the service in the file frameworks/base/cmds/servicemanager/service_manager.c

{ AID_MEDIA, "vendor.enea.Buffer" },

On the client process side you can use something like the code snippet below to get the memory pointer.
NOTE: MemoryHeapBase is based on strong pointer and will be "magical" ref counted and removed thats why the client put the object pointer in a static variable in the example below to keep it from being removed.

/*
 * EneaBufferClient.cpp
 *  Created on: 19 mars 2010  Author: Zingo Andersen
 *  License: Public Domain (steal and use what you like)
 *
 *  Get the shared memory buffer from the server and change the first int value
 *  by adding one to it. The Server should be running in parallell pleas view
 *  the logcat for the result
 */


#include "IEneaBuffer.h"
#include <binder/MemoryHeapBase.h>
#include <binder/IServiceManager.h>

namespace android {
static sp<IMemoryHeap> receiverMemBase;

unsigned int * getBufferMemPointer(void)
{
  static sp<IEneaBuffer> eneaBuffer = 0;

  /* Get the buffer service */
  if (eneaBuffer == NULL)
  {
    sp<IServiceManager> sm = defaultServiceManager();
    sp<IBinder> binder;
    binder = sm->getService(String16("vendor.enea.Buffer"));
    if (binder != 0)
    {
      eneaBuffer = IEneaBuffer::asInterface(binder);
    }
  }
  if (eneaBuffer == NULL)
  {
    LOGE("The EneaBufferServer is not published");
    return (unsigned int *)-1; /* return an errorcode... */
  }
  else
  {
    receiverMemBase = eneaBuffer->getBuffer();
    return (unsigned int *) receiverMemBase->getBase();
  }
}

}

using namespace android;

int main(int argc, char** argv)
{
 // base could be on same address as Servers base but this
 // is purely by luck do NEVER rely on this. Linux memory
 // management may put it wherever it likes.
    unsigned int *base = getBufferMemPointer();
    if(base != (unsigned int *)-1)
    {
     LOGD("EneaBufferClient base=%p Data=0x%x\n",base, *base);
       *base = (*base)+1;
       LOGD("EneaBufferClient base=%p Data=0x%x CHANGED\n",base, *base);
        receiverMemBase = 0;
    }
    else
    {
     LOGE("Error shared memory not available\n");
    }
    return 0;
}



And my Android.mk file for this:
# Ashmem shared buffer example
# Created on: 19 mars 2010  Author: Zingo Andersen # License: Public Domain (steal and use what you like)

LOCAL_PATH:= $(call my-dir)

#
# BufferServer
#

include $(CLEAR_VARS)

LOCAL_SRC_FILES:=        \
 IEneaBuffer.cpp      \
 EneaBufferServer.cpp \
   
LOCAL_SHARED_LIBRARIES:= libcutils libutils libbinder

LOCAL_MODULE:= EneaBufferServer

LOCAL_CFLAGS+=-DLOG_TAG=\"EneaBufferServer\"

LOCAL_PRELINK_MODULE:=false
include $(BUILD_EXECUTABLE)

#
# BufferClient
#

include $(CLEAR_VARS)

LOCAL_SRC_FILES:=        \
 IEneaBuffer.cpp      \
 EneaBufferClient.cpp \
   
LOCAL_SHARED_LIBRARIES:= libcutils libutils libbinder

LOCAL_MODULE:= EneaBufferClient

LOCAL_CFLAGS+=-DLOG_TAG=\"EneaBufferClient\"

LOCAL_PRELINK_MODULE:=false
include $(BUILD_EXECUTABLE) 

An example of porting existing code to a custom Android device

It is due time for another technical post here on the blog. This post will be about porting existing c-libraries to Android, something I did as part of the dev board demos we are doing here at Enea.

Platform addition or NDK

There are two ways of bringing native code to an Android device, either add it to the platform itself and integrate it with the framework, or include it with an application package. The latter method have evolved a lot and with the release of NDK version 5 even allows you to hook directly into the application lifecycle http://developer.android.com/reference/android/app/NativeActivity.html from the NDK. The NDK is useful for any application where you have need of native performance, have portable C libriaries you want to reuse or just some legacy native code that could be included in your application. The NDK integrates well with the Android SDK and is a great way to include native functionality in your application. It should be the preferred way for any application that needs to be reusable across a lot of Android devices.

The other option is to include your functionality, it may be native or Java, as an API extension for all applications to use. This will only work on devices that implement these extensions and it may be a suitable option for device builders. This is the variant that we aim for here.


Analyze the existing project
Porting native code to Android is not always straight forward, especially if we are talking about C++ code due to the fact that Android uses its own c-runtime with limited support for exceptions among other things. If you want to know more about the details of bionic there is an overview in the NDK docs.

The code I wanted to port for this project was the Enea LINX for Linux framework which is a fast IPC framework. My purpose was to be able to interact with control systems running our OSE real time operating system which also implements this kind of IPC. LINX consists of a couple of kernel driver modules, a user space library and some configuration and control utilities. It is written in C. I had created a small demo with LINX in Android before where I compiled it separately and used static linking but for this project I wanted a complete port to the Android build system. It did not have any issues with bionic compatability so the port should be straight forward.

I just want to add a short disclaimer about LINX. I use it here since it is a good example of integrating a solution into Android from kernel drivers up to the API levels. This particular piece of code does add additional IPC mechanisms to the systems which more or less messes up the security model so do not use it unless you are aware of the implications. The steps needed to port code to Android described in this post are however applicable for any type of driver/framework/library that you may want to include on your product.

Adding kernel driver modules
The first step was to add the kernel modules to the Android build. One way would have built a new kernel and include them directly but for this project I chose to keep them as separate modules. Building for the kernel is not handled by the Android build system meaning that we build them as we would do with any Linux system. The target is an Atmel based development board and in the LINX module build I provide the headers and cross compilation toolchain for that kernel and architecture.

Now for the Android specific parts. We need to add the compiled kernel modules to the platform build system in some way and create an Android.mk file that includes them in the system image when we build. Add a folder in the source tree where your project will go, device or external are suitable candidates. I created a folder called linx that will hold the entire linx port and in that I added a subfolder called modules where I place the prebuilt kernel modules. Now what we need is an Android makefile to copy them to the suitable place in the out folder for system image generation. This will look like:

LOCAL_PATH := $(my-dir)
include $(CLEAR_VARS)

LOCAL_MODULE := linx.ko

LOCAL_MODULE_CLASS := SHARED_LIBRARY

# This will copy the file in /system/lib/modules
#
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/modules

LOCAL_SRC_FILES := $(LOCAL_MODULE)

include $(BUILD_PREBUILT)

The standard location for modules on the Android system image is System/lib/modules so that is where we copy them. If we build the platform now the build system will copy our precompiled module linx.ko to the system image that we use for our device. The next step is to make sure that we have the module installed on the system when we run it. This can either be done manually via the shell or via a script that we run during init.

In this case I have created a shell script to be launched from init.rc with the following content:

#linx init
insmod /lib/modules/linx.ko
insmod /lib/modules/linx_tcp_cm.ko
netcfg eth0 up
ifconfig eth0 192.168.1.12
mktcpcon --ipaddr=192.168.1.21 ControlConn
mklink --connection=tcpcm/ControlConn control_link

This includes installing the modules and configuring the network and LINX-link. We launched this from init.rc by adding:

...
#linx init script
service linx-setup /system/etc/linx_setup.sh
oneshot
...

The setup script is added to the system image in the same way by including it as a prebuilt target.

LOCAL_PATH := $(my-dir)
include $(CLEAR_VARS)

LOCAL_MODULE := linx_setup.sh

LOCAL_MODULE_CLASS := ETC

LOCAL_MODULE_PATH := $(TARGET_OUT)/etc

LOCAL_SRC_FILES := $(LOCAL_MODULE)

include $(BUILD_PREBUILT)

Creating Android make files for the user space code
Now that we have the drivers in place the next step is to look at porting the user space libraries. The default LINX build system uses standard GNU make files but we need to create new ones adapted to the Android build system. Start out by adding the source files needed to the linx directory created in the Android source tree. This gives the following structure:

Android.mk  
include  
liblinx  
linx_basic  
linxcfg  
linx_setup.sh  
modules

I have the linx setup script and the main Android.mk file in the top directory and then we have the source files in separate folders and the include files in the include folder. To illustrate how the Android make files for each source component is created we can use liblinx as an example. The Android.mk file looks like:

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)

LOCAL_SRC_FILES := linx.c
LOCAL_C_INCLUDES += $(LOCAL_PATH)/../include
LOCAL_MODULE := liblinx
LOCAL_PRELINK_MODULE := false
include $(BUILD_SHARED_LIBRARY)

We set our sources by specifying LOCAL_SRC_FILES and the name of the library by specifying LOCAL_MODULE. We also need to supply the header files in the include directory by specifying LOCAL_C_INCLUDES. Finally this is a shared library that we are porting so use the BUILD_SHARED_LIBRARY template. This will build the library with the Android build system and add it to the system image as a shared library with the name liblinx.so.

The rest of the code is moved to the Android build system in the same way, by creating Android.mk files and specifying type and any dependencies. As another example we may look at the syntax for building the mktcpcon configuration program. This depends on the library we just created and hence the makefile looks entry looks like:

LOCAL_SRC_FILES := mktcpcon.c
LOCAL_C_INCLUDES += $(LOCAL_PATH)/../include
LOCAL_STATIC_LIBRARIES += liblinxcfg
LOCAL_SHARED_LIBRARIES += liblinx
LOCAL_MODULE := mktcpcon
include $(BUILD_EXECUTABLE)

Here we use the BUILD_EXECUTABLE template and we also need to specify static and shared libraries that we link against.

Summary
I hope that provides some insight in how you setup the build for an existing linux project to run on an Android system. The steps to follow are:
  • Build any kernel related things using the correct kernel build system and config for your device
  • Add the kernel modules (and/or kernel) to the platform build system and create Android.mk files for them using the prebuilt template.
  • Create config and intialization services for your drivers if needed and add them to init.
  • Move the rest of your code (user space) to the Android source tree and create Android.mk files for them.
  • If you encounter build errors work them out in the source code and see what incompatabilities your code have with the specifics of the Android C-runtime.

That wraps up my post for today. Having done this we are now able to use our added drivers and API:s from native programs running in the shell. The next step is to create a JNI layer and java library to allow regular Android applications to make use of our platform additions.

I have been away for half a year on paternal leave (nice Swedish benefit) but now it is full time Android hacking again and pushing the team to publish things. Hopefully you will see more activity here including a follow up on this post discussing applications APIs.

/Mattias


 
Comments