Difference between revisions of "Android"
m (→Touchscreen) |
m (Add comments) |
||
Line 50: | Line 50: | ||
===Apply the Armadeus patchset=== | ===Apply the Armadeus patchset=== | ||
Before compiling the kernel, we patch the source with the Armadeus patches. In second time, I will give the URL to retrieve Linux 2.6.29.4 patch. | Before compiling the kernel, we patch the source with the Armadeus patches. In second time, I will give the URL to retrieve Linux 2.6.29.4 patch. | ||
+ | {{Warning| Never export ARCH and CROSS_COMPILE environment variables because Android make use them too}} | ||
<pre class="host"> | <pre class="host"> | ||
− | + | $ARMADEUS/buildroot/toolchain/patch-kernel.sh $ANDROID_SOURCE/kernel $ARMADEUS/downloads patch-2.6.29.4.bz2 | |
− | + | $ARMADEUS/buildroot/toolchain/patch-kernel.sh $ANDROID_SOURCE/kernel $ARMADEUS/buildroot/target/device/armadeus/linux/kernel-patches/2.6.29.4 \*.patch{,.gz,.bz2} | |
− | + | mkdir $ANDROID_SOURCE/kernel/drivers/armadeus | |
− | + | cp -r $ARMADEUS/target/linux/modules/* $ANDROID_SOURCE/kernel/drivers/armadeus | |
</pre> | </pre> | ||
− | + | For generate the Linux kernel, we retrieve the default apf27 Linux configuration and modify it for start Android. | |
<pre class="host"> | <pre class="host"> | ||
− | + | cp $ARMADEUS/buildroot/target/device/armadeus/apf27/apf27-linux-2.6.29.config $ANDROID_SOURCE/kernel/arch/arm/configs/apf27_android_defconfig | |
− | + | cd $ANDROID_SOURCE/kernel | |
− | + | make ARCH=arm mrproper | |
− | + | make ARCH=arm apf27_android_defconfig | |
− | + | make ARCH=arm menuconfig | |
</pre> | </pre> | ||
− | + | ===Android kernel configuration=== | |
Make sure your kernel boots normally on your board. Then enable some Android specific configuration and make sure that your kernel still boots (with your standard file system). | Make sure your kernel boots normally on your board. Then enable some Android specific configuration and make sure that your kernel still boots (with your standard file system). | ||
− | *Android pmem allocator | + | * Activate the Android pmem allocator |
<pre class="config"> | <pre class="config"> | ||
Device Drivers ---> | Device Drivers ---> | ||
Line 73: | Line 74: | ||
[*] Android pmem allocator | [*] Android pmem allocator | ||
</pre> | </pre> | ||
− | * Android drivers | + | * Activate the Android drivers |
<pre class="config"> | <pre class="config"> | ||
Device Drivers ---> | Device Drivers ---> | ||
Line 88: | Line 89: | ||
[*] Android Low Memory Killer | [*] Android Low Memory Killer | ||
</pre> | </pre> | ||
− | * Anonymous Shared Memory Subsystem | + | * Activate the Anonymous Shared Memory Subsystem |
<pre class="config"> | <pre class="config"> | ||
General setup ---> | General setup ---> | ||
[*] Enable the Anonymous Shared Memory Subsystem | [*] Enable the Anonymous Shared Memory Subsystem | ||
</pre> | </pre> | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
===Touchscreen kernel configuration=== | ===Touchscreen kernel configuration=== | ||
+ | * Activate the wake lock for spi event reach to Android and include in the compiled kernel the touchscreen driver | ||
<pre class="config"> | <pre class="config"> | ||
Power management options ---> | Power management options ---> | ||
Line 131: | Line 115: | ||
===Build Android kernel=== | ===Build Android kernel=== | ||
+ | Compile the kernel and generate image kernel for U-Boot Loader | ||
<pre class="host"> | <pre class="host"> | ||
$ make ARCH=arm CROSS_COMPILE=$ANDROID_SOURCE/prebuilt/linux-x86/toolchain/arm-eabi-4.2.1/bin/arm-eabi- uImage | $ make ARCH=arm CROSS_COMPILE=$ANDROID_SOURCE/prebuilt/linux-x86/toolchain/arm-eabi-4.2.1/bin/arm-eabi- uImage | ||
Line 174: | Line 159: | ||
} | } | ||
</source> | </source> | ||
− | *Change the battery charged status as full and deterioration status as fair. | + | * Change the battery charged status as full and deterioration status as fair. |
<source lang="c"> | <source lang="c"> | ||
static void android_server_BatteryService_update(JNIEnv* env, jobject obj) | static void android_server_BatteryService_update(JNIEnv* env, jobject obj) | ||
Line 208: | Line 193: | ||
===Audio=== | ===Audio=== | ||
− | + | For activate the audio, we should retrieve Alsa android module whose not directly add in the source | |
<pre class="host"> | <pre class="host"> | ||
− | cd $ANDROID_SOURCE/external | + | cd $ANDROID_SOURCE/external |
− | git clone git://android.git.kernel.org/platform/external/ | + | git clone git://android.git.kernel.org/platform/external/alsa-lib.git |
− | git clone git://android.git.kernel.org/platform/external/ | + | git clone git://android.git.kernel.org/platform/external/alsa-utils.git |
cd $ANDROID_SOURCE/hardware | cd $ANDROID_SOURCE/hardware | ||
− | git clone git://android.git.kernel.org/platform/hardware/alsa_sound.git | + | git clone git://android.git.kernel.org/platform/hardware/alsa_sound.git |
</pre> | </pre> | ||
− | edit $ANDROID_SOURCE/build/target/board/generic/BoardConfig.mk | + | |
+ | edit '''$ANDROID_SOURCE/build/target/board/generic/BoardConfig.mk''' and modify the audio divers used by Android | ||
<pre class="config"> | <pre class="config"> | ||
# HAVE_HTC_AUDIO_DRIVER := true | # HAVE_HTC_AUDIO_DRIVER := true | ||
Line 223: | Line 209: | ||
BUILD_WITH_ALSA_UTILS := true | BUILD_WITH_ALSA_UTILS := true | ||
</pre> | </pre> | ||
− | edit $ANDROID_SOURCE/hardware/alsa_sound/AudioHardwareALSA.cpp and change bufferSize to 8192 in twice StreamDefaults structures <br> | + | |
− | edit $ANDROID_SOURCE/system/core/init/device.c | + | edit '''$ANDROID_SOURCE/hardware/alsa_sound/AudioHardwareALSA.cpp''' and change bufferSize to 8192 in twice StreamDefaults structures <br> |
+ | edit '''$ANDROID_SOURCE/system/core/init/device.c''' and add audio device in Linux devices | ||
<source lang="c"> | <source lang="c"> | ||
static struct perms_ devperms[] = { | static struct perms_ devperms[] = { | ||
Line 236: | Line 223: | ||
}; | }; | ||
</source> | </source> | ||
+ | |||
<source lang="c"> | <source lang="c"> | ||
static void handle_device_event(struct uevent *uevent) | static void handle_device_event(struct uevent *uevent) | ||
Line 243: | Line 231: | ||
int block; | int block; | ||
... | ... | ||
− | + | } else if(!strncmp(uevent->subsystem, "mtd", 3)) { | |
− | + | base = "/dev/mtd/"; | |
− | + | mkdir(base, 0755); | |
− | + | // add this conditionnal block | |
− | + | } else if(!strncmp(uevent->subsystem, "sound", 5)) { | |
− | + | base = "/dev/snd/"; | |
− | + | mkdir(base, 0755); | |
− | + | } else if(!strncmp(uevent->subsystem, "misc", 4) && | |
− | + | !strncmp(name, "log_", 4)) { | |
− | + | base = "/dev/log/"; | |
− | + | mkdir(base, 0755); | |
− | + | name += 4; | |
− | + | } else | |
− | + | base = "/dev/"; | |
− | + | } | |
− | + | ||
</source> | </source> | ||
− | + | Add audio files in Android files system | |
<pre class="host"> | <pre class="host"> | ||
− | + | mkdir $ANDROID_SOURCE/system/core/rootdir/media | |
− | + | mkdir $ANDROID_SOURCE/system/core/rootdir/media/audio | |
− | + | mkdir $ANDROID_SOURCE/system/core/rootdir/media/audio/ui | |
− | + | mkdir $ANDROID_SOURCE/system/core/rootdir/media/audio/alarms | |
− | + | mkdir $ANDROID_SOURCE/system/core/rootdir/media/audio/notifications | |
− | + | mkdir $ANDROID_SOURCE/system/core/rootdir/media/audio/ringtones | |
− | + | cp $ANDROID_SOURCE/frameworks/base/data/sounds/effects/* $ANDROID_SOURCE/system/core/rootdir/media/audio/ui/ | |
− | + | cp $ANDROID_SOURCE/frameworks/base/data/sounds/Alarm_* $ANDROID_SOURCE/system/core/rootdir/media/audio/alarms/ | |
− | + | cp $ANDROID_SOURCE/frameworks/base/data/sounds/notifications/* $ANDROID_SOURCE/system/core/rootdir/media/audio/notifications/ | |
− | + | cp $ANDROID_SOURCE/frameworks/base/data/sounds/Ring_* $ANDROID_SOURCE/system/core/rootdir/media/audio/ringtones/ | |
</pre> | </pre> | ||
===Touchscreen=== | ===Touchscreen=== | ||
− | edit $ANDROID_SOURCE/kernel/drivers/input/touchscreen/ts2102_ts.c | + | Android don't use tslib library so we should add the calibration directly in ts drivers<br> |
− | + | edit '''$ANDROID_SOURCE/kernel/drivers/input/touchscreen/ts2102_ts.c'''<br> | |
+ | Add new definitions for X and Y ranges | ||
<source lang="c"> | <source lang="c"> | ||
#define DRIVER_NAME "TSC210x Touchscreen" | #define DRIVER_NAME "TSC210x Touchscreen" | ||
Line 287: | Line 275: | ||
#define FACTOR 5000 | #define FACTOR 5000 | ||
</source> | </source> | ||
+ | Send touch event to Android when the user release the touchscreen | ||
<source lang="c"> | <source lang="c"> | ||
static void tsc210x_touch(int touching) | static void tsc210x_touch(int touching) | ||
Line 321: | Line 310: | ||
} | } | ||
</source> | </source> | ||
+ | Calibrate the touchscreen with X and Y ranges | ||
<source lang="c"> | <source lang="c"> | ||
static int tsc210x_ts_probe(struct platform_device *pdev) | static int tsc210x_ts_probe(struct platform_device *pdev) | ||
Line 367: | Line 357: | ||
===Android start up=== | ===Android start up=== | ||
− | + | Edit $ANDROID_SOURCE/system/core/rootdir/init.rc, comment the 'mount roofs' in read only mode and 'mount yaffs2' lines like this: | |
− | + | ||
<pre class="config"> | <pre class="config"> | ||
# setup the global environment | # setup the global environment | ||
Line 402: | Line 391: | ||
# mount mtd partitions | # mount mtd partitions | ||
− | # Mount | + | # Mount the SD Card partition |
− | + | ||
− | + | ||
− | + | ||
setprop EXTERNAL_STORAGE_STATE mounted | setprop EXTERNAL_STORAGE_STATE mounted | ||
mount vfat /dev/block/mmcblk0p1 /sdcard nosuid nodev | mount vfat /dev/block/mmcblk0p1 /sdcard nosuid nodev | ||
Line 415: | Line 401: | ||
# Same reason as /data above | # Same reason as /data above | ||
− | |||
chown system cache /cache | chown system cache /cache | ||
chmod 0770 /cache | chmod 0770 /cache | ||
Line 429: | Line 414: | ||
$ make | $ make | ||
</pre> | </pre> | ||
+ | |||
==Making RootFS== | ==Making RootFS== | ||
===Android Root File system=== | ===Android Root File system=== | ||
Line 439: | Line 425: | ||
Android’s root file system is generated in $ANDROID_SOURCE/out/target/product/generic. We will create a folder containing all Android files images. | Android’s root file system is generated in $ANDROID_SOURCE/out/target/product/generic. We will create a folder containing all Android files images. | ||
<pre class="host"> | <pre class="host"> | ||
− | + | sudo rm -rf $ANDROID_SOURCE/rootfs/ | |
− | + | cd $ANDROID_SOURCE/out/target/product/generic | |
− | + | mkdir $ANDROID_SOURCE/rootfs | |
− | + | cp -a root/* $ANDROID_SOURCE/rootfs/ | |
− | + | cp -a system/* $ANDROID_SOURCE/rootfs/system/ | |
− | + | cd $ANDROID_SOURCE/rootfs | |
− | + | sudo chown -R root.root . | |
− | + | sudo chmod -R a+rwX data system | |
</pre> | </pre> | ||
Line 498: | Line 484: | ||
In the U-boot prompt, make the mmc boot is on second partition of the mmc/µSD card | In the U-boot prompt, make the mmc boot is on second partition of the mmc/µSD card | ||
<pre class="apf"> | <pre class="apf"> | ||
− | + | setenv addjffsargs 'setenv bootargs ${bootargs} root=/dev/mtdblock4 rootfstype=jffs2 init=/init' | |
− | + | setenv bootcmd run mmcboot | |
− | + | saveenv | |
− | + | run update_kernel | |
− | + | run update_rootfs | |
</pre> | </pre> | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
[[Image:Apf27_android.JPG]] | [[Image:Apf27_android.JPG]] | ||
Line 521: | Line 496: | ||
Installing the [http://developer.android.com/sdk/1.6_r1/installing.html Android Development Tools (ADT)] | Installing the [http://developer.android.com/sdk/1.6_r1/installing.html Android Development Tools (ADT)] | ||
Trace with '''logcat''' with Eclipse-ADT | Trace with '''logcat''' with Eclipse-ADT | ||
− | <pre class="host"> | + | <pre class="host"> |
− | + | export ADBHOST=w.x.y.z | |
− | + | adb kill-server | |
+ | adb start-server | ||
</pre> | </pre> | ||
Line 529: | Line 505: | ||
Documentation on Android [http://developer.android.com/guide/developing/tools/emulator.html emulator] | Documentation on Android [http://developer.android.com/guide/developing/tools/emulator.html emulator] | ||
<pre class="host"> | <pre class="host"> | ||
− | + | cd $ANDROID_SOURCE/kernel | |
− | + | make ARCH=arm goldfish_defconfig | |
− | + | make ARCH=arm CROSS_COMPILE=$ANDROID_SOURCE/prebuilt/linux-x86/toolchain/arm-eabi-4.2.1/bin/arm-eabi | |
− | + | </pre> | |
− | + | Create AVD (Android Virtual Device) | |
− | + | <pre class="host"> | |
− | + | $ANDROID_SDK/tools/android create avd -n APF27-H -t 4 -s 272x480 | |
+ | $ANDROID_SDK/tools/android create avd -n APF27-L -t 4 -s 480x272 | ||
+ | $ANDROID_SOURCE/out/host/linux-x86/bin/emulator -avd APF27-H -sysdir $ANDROID_SOURCE/out/target/product/generic/ -kernel $ANDROID_SOURCE/kernel/arch/arm/boot/zImage -data $ANDROID_SOURCE/out/target/product/generic/userdata.img -ramdisk $ANDROID_SOURCE/out/target/product/generic/ramdisk.img -system $ANDROID_SOURCE/out/target/product/generic/system.img | ||
</pre> | </pre> | ||
Revision as of 10:28, 13 October 2009
This page will sumarize the efforts made to have Android running on the APF boards.
Note: Due to Android requirements (at least an ARM926 core), it is impossible to have it running on the APF9328 |
Contents
Some readings before starting
Prerequisites for Android installation
Install needed software packages
- Install these package for build the kernel image and for format the mmc/µSD card
$ sudo apt-get install uboot-mkimage mtd-utils
- The Armadeus Toolchain, only for Armadeus patches
Update the environment variables
Theses environment variables install the Android and Armadeus folder in our home directory, but of course, it can be placed anywhere!
export ANDROID_SOURCE=~/apf27droid export ANDROID_SDK=~/android-sdk-linux_x86-1.5_r3 export ARMADEUS=~/armadeus-3.1 export PATH=${PATH}:${ANDROID_SDK}/tools:${ANDROID_SOURCE}/bin
Download Android source
List of different Android branch: heads The getting Android source document describes how to set up our local work environment. Follow theses instructions until Installing Repo chapter.
$ mkdir $ANDROID_SOURCE $ cd $ANDROID_SOURCE $ mkdir bin $ curl http://android.git.kernel.org/repo >$ANDROID_SOURCE/bin/repo $ chmod a+x $ANDROID_SOURCE/bin/repo $ repo init -u git://android.git.kernel.org/platform/manifest.git -b android-sdk-1.5_r3 $ repo sync
Since android-sdk-1.5_r3 branch, the Linux kernel isn't with the Android source, We can download it in a compress archive (tar.gz) file with this android-kernel-2.6.29 (about (70Mib) or with git repository (more 300Mib)
$ mkdir $ANDROID_SOURCE/kernel $ cd $ANDROID_SOURCE/kernel $ git clone git://android.git.kernel.org/kernel/common.git android-2.6.29
Linux Kernel 2.6.29
Apply the Armadeus patchset
Before compiling the kernel, we patch the source with the Armadeus patches. In second time, I will give the URL to retrieve Linux 2.6.29.4 patch.
Warning: Never export ARCH and CROSS_COMPILE environment variables because Android make use them too |
$ARMADEUS/buildroot/toolchain/patch-kernel.sh $ANDROID_SOURCE/kernel $ARMADEUS/downloads patch-2.6.29.4.bz2 $ARMADEUS/buildroot/toolchain/patch-kernel.sh $ANDROID_SOURCE/kernel $ARMADEUS/buildroot/target/device/armadeus/linux/kernel-patches/2.6.29.4 \*.patch{,.gz,.bz2} mkdir $ANDROID_SOURCE/kernel/drivers/armadeus cp -r $ARMADEUS/target/linux/modules/* $ANDROID_SOURCE/kernel/drivers/armadeus
For generate the Linux kernel, we retrieve the default apf27 Linux configuration and modify it for start Android.
cp $ARMADEUS/buildroot/target/device/armadeus/apf27/apf27-linux-2.6.29.config $ANDROID_SOURCE/kernel/arch/arm/configs/apf27_android_defconfig cd $ANDROID_SOURCE/kernel make ARCH=arm mrproper make ARCH=arm apf27_android_defconfig make ARCH=arm menuconfig
Android kernel configuration
Make sure your kernel boots normally on your board. Then enable some Android specific configuration and make sure that your kernel still boots (with your standard file system).
- Activate the Android pmem allocator
Device Drivers ---> [*] Misc devices ---> [*] Android pmem allocator
- Activate the Android drivers
Device Drivers ---> [*] Staging drivers ---> [ ] Exclude Staging drivers from being built (NEW) ... Android ---> [*] Android Drivers [*] Android Binder IPC Driver <*> Android log driver [ ] Android RAM buffer console [*] Timed output class driver (NEW) < > Android timed gpio driver (NEW) [*] Android Low Memory Killer
- Activate the Anonymous Shared Memory Subsystem
General setup ---> [*] Enable the Anonymous Shared Memory Subsystem
Touchscreen kernel configuration
- Activate the wake lock for spi event reach to Android and include in the compiled kernel the touchscreen driver
Power management options ---> [*] Wake lock [*] Wake lock stats (NEW) [*] Userspace wake locks (NEW) [*] Early suspend (NEW) User-space screen access (Console switch on early-suspend) ---> (X) Sysfs interface ... Device Drivers ---> Input device support ---> [*] Touchscreens ---> <*> TSC 2102 based touchscreens ... <*> Hardware Monitoring support --->
Build Android kernel
Compile the kernel and generate image kernel for U-Boot Loader
$ make ARCH=arm CROSS_COMPILE=$ANDROID_SOURCE/prebuilt/linux-x86/toolchain/arm-eabi-4.2.1/bin/arm-eabi- uImage $ cp $ANDROID_SOURCE/kernel/arch/arm/boot/uImage $TFTPBOOT/apf27-linux.bin
Android
Battery patch
At the beginning, reboot happened over again even though Android logo appeared on board. Result of investigation, we found that battery power was returned with 0 when boot.. Then, we changed to notify full battery to Android by ignoring the information under /sys/class/power_supply so that to prevent the power down by low battery $ANDROID_SOURCE/frameworks/base/services/jni/com_android_server_BatteryService.cpp
- Change the battery service status as TRUE
static void setBooleanField(JNIEnv* env, jobject obj, const char* path, jfieldID fieldID)
{
const int SIZE = 16;
char buf[SIZE];
jboolean value = true; /* change false -> true */
/*!!!comment out!!!
if (readFromFile(path, buf, SIZE) > 0) {
if (buf[0] == '1') {
value = true;
}
}
*/
env->SetBooleanField(obj, fieldID, value);
}
- Change the volume, voltage and temperature of battery. Return 100%.
static void setIntField(JNIEnv* env, jobject obj, const char* path, jfieldID fieldID)
{
const int SIZE = 128;
char buf[SIZE];
jint value = 100; /* change 0 -> 100 */
/*!!!comment out!!!
if (readFromFile(path, buf, SIZE) > 0) {
value = atoi(buf);
}
*/
env->SetIntField(obj, fieldID, value);
}
- Change the battery charged status as full and deterioration status as fair.
static void android_server_BatteryService_update(JNIEnv* env, jobject obj)
{
setBooleanField(env, obj, AC_ONLINE_PATH, gFieldIds.mAcOnline);
setBooleanField(env, obj, USB_ONLINE_PATH, gFieldIds.mUsbOnline);
setBooleanField(env, obj, BATTERY_PRESENT_PATH, gFieldIds.mBatteryPresent);
setIntField(env, obj, BATTERY_CAPACITY_PATH, gFieldIds.mBatteryLevel);
setIntField(env, obj, BATTERY_VOLTAGE_PATH, gFieldIds.mBatteryVoltage);
setIntField(env, obj, BATTERY_TEMPERATURE_PATH, gFieldIds.mBatteryTemperature);
/* Change */
env->SetIntField(obj, gFieldIds.mBatteryStatus, gConstants.statusFull);
env->SetIntField(obj, gFieldIds.mBatteryHealth, gConstants.healthGood);
env->SetObjectField(obj, gFieldIds.mBatteryTechnology, env->NewStringUTF("1"));
/*!!!comment out!!!
const int SIZE = 128;
char buf[SIZE];
if (readFromFile(BATTERY_STATUS_PATH, buf, SIZE) > 0)
env->SetIntField(obj, gFieldIds.mBatteryStatus, getBatteryStatus(buf));
if (readFromFile(BATTERY_HEALTH_PATH, buf, SIZE) > 0)
env->SetIntField(obj, gFieldIds.mBatteryHealth, getBatteryHealth(buf));
if (readFromFile(BATTERY_TECHNOLOGY_PATH, buf, SIZE) > 0)
env->SetObjectField(obj, gFieldIds.mBatteryTechnology, env->NewStringUTF(buf));
*/
}
Audio
For activate the audio, we should retrieve Alsa android module whose not directly add in the source
cd $ANDROID_SOURCE/external git clone git://android.git.kernel.org/platform/external/alsa-lib.git git clone git://android.git.kernel.org/platform/external/alsa-utils.git cd $ANDROID_SOURCE/hardware git clone git://android.git.kernel.org/platform/hardware/alsa_sound.git
edit $ANDROID_SOURCE/build/target/board/generic/BoardConfig.mk and modify the audio divers used by Android
# HAVE_HTC_AUDIO_DRIVER := true # BOARD_USES_GENERIC_AUDIO := true BOARD_USES_ALSA_AUDIO := true BUILD_WITH_ALSA_UTILS := true
edit $ANDROID_SOURCE/hardware/alsa_sound/AudioHardwareALSA.cpp and change bufferSize to 8192 in twice StreamDefaults structures
edit $ANDROID_SOURCE/system/core/init/device.c and add audio device in Linux devices
static struct perms_ devperms[] = {
{ "/dev/null", 0666, AID_ROOT, AID_ROOT, 0 },
...
{ "/dev/qmi1", 0640, AID_RADIO, AID_RADIO, 0 },
{ "/dev/qmi2", 0640, AID_RADIO, AID_RADIO, 0 },
// Add this line
{ "/dev/snd/", 0664, AID_SYSTEM, AID_AUDIO, 1 },
{ NULL, 0, 0, 0, 0 },
};
static void handle_device_event(struct uevent *uevent)
{
char devpath[96];
char *base, *name;
int block;
...
} else if(!strncmp(uevent->subsystem, "mtd", 3)) {
base = "/dev/mtd/";
mkdir(base, 0755);
// add this conditionnal block
} else if(!strncmp(uevent->subsystem, "sound", 5)) {
base = "/dev/snd/";
mkdir(base, 0755);
} else if(!strncmp(uevent->subsystem, "misc", 4) &&
!strncmp(name, "log_", 4)) {
base = "/dev/log/";
mkdir(base, 0755);
name += 4;
} else
base = "/dev/";
}
Add audio files in Android files system
mkdir $ANDROID_SOURCE/system/core/rootdir/media mkdir $ANDROID_SOURCE/system/core/rootdir/media/audio mkdir $ANDROID_SOURCE/system/core/rootdir/media/audio/ui mkdir $ANDROID_SOURCE/system/core/rootdir/media/audio/alarms mkdir $ANDROID_SOURCE/system/core/rootdir/media/audio/notifications mkdir $ANDROID_SOURCE/system/core/rootdir/media/audio/ringtones cp $ANDROID_SOURCE/frameworks/base/data/sounds/effects/* $ANDROID_SOURCE/system/core/rootdir/media/audio/ui/ cp $ANDROID_SOURCE/frameworks/base/data/sounds/Alarm_* $ANDROID_SOURCE/system/core/rootdir/media/audio/alarms/ cp $ANDROID_SOURCE/frameworks/base/data/sounds/notifications/* $ANDROID_SOURCE/system/core/rootdir/media/audio/notifications/ cp $ANDROID_SOURCE/frameworks/base/data/sounds/Ring_* $ANDROID_SOURCE/system/core/rootdir/media/audio/ringtones/
Touchscreen
Android don't use tslib library so we should add the calibration directly in ts drivers
edit $ANDROID_SOURCE/kernel/drivers/input/touchscreen/ts2102_ts.c
Add new definitions for X and Y ranges
#define DRIVER_NAME "TSC210x Touchscreen"
#define X_AXIS_MAX 4000
#define X_AXIS_MIN 0
#define Y_AXIS_MAX 4200
#define Y_AXIS_MIN 100
#define PRESSURE_MIN 20
#define PRESSURE_MAX 40000
#define FACTOR 5000
Send touch event to Android when the user release the touchscreen
static void tsc210x_touch(int touching)
{
if (!touching) {
//input_report_abs(dev, ABS_X, 0);
//input_report_abs(dev, ABS_Y, 0);
input_report_key(dev, BTN_TOUCH, 0);
input_report_abs(dev, ABS_PRESSURE, 0);
input_sync(dev);
}
//input_report_key(dev, BTN_TOUCH, touching);
//do_poke_blanked_console = 1;
}
static void tsc210x_coords(int x, int y, int z1, int z2)
{
int p;
/* Calculate the touch resistance a la equation #1 */
if (z1 != 0)
p = x * (z2 - z1) / (z1 << 4) * FACTOR;
else
p = 1;
y = Y_AXIS_MAX - y;
input_report_key(dev, BTN_TOUCH, 1);
input_report_abs(dev, ABS_X, x);
input_report_abs(dev, ABS_Y, y);
input_report_abs(dev, ABS_PRESSURE, p);
input_sync(dev);
}
Calibrate the touchscreen with X and Y ranges
static int tsc210x_ts_probe(struct platform_device *pdev)
{
int status;
dev = input_allocate_device();
if (!dev)
return -ENOMEM;
status = tsc210x_touch_cb(tsc210x_touch);
if (status)
{
goto error;
}
status = tsc210x_coords_cb(tsc210x_coords);
if (status)
{
goto error;
}
dev->name = DRIVER_NAME;
dev->dev.parent = &pdev->dev;
dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
dev->keybit[BIT_WORD(BTN_TOUCH)] |= BIT_MASK(BTN_TOUCH);
dev->absbit[0] = BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) | BIT_MASK(ABS_PRESSURE);
input_set_abs_params(dev, ABS_X, X_AXIS_MIN, X_AXIS_MAX, 0, 0);
input_set_abs_params(dev, ABS_Y, Y_AXIS_MIN, Y_AXIS_MAX, 0, 0);
input_set_abs_params(dev, ABS_PRESSURE, PRESSURE_MIN, PRESSURE_MAX, 0, 0);
status = input_register_device(dev);
if (status)
{
printk(KERN_INFO "Unable to register TSC210x as input device !\n");
goto error;
}
printk(DRIVER_NAME " driver initialized\n");
return 0;
error:
input_free_device(dev);
return status;
}
Android start up
Edit $ANDROID_SOURCE/system/core/rootdir/init.rc, comment the 'mount roofs' in read only mode and 'mount yaffs2' lines like this:
# 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 export ANDROID_ASSETS /system/app export ANDROID_DATA /data export EXTERNAL_STORAGE /sdcard export BOOTCLASSPATH /system/framework/core.jar:/system/framework/ext.jar:/system/framework/framework.jar:/system/framework/android.policy.jar:/system/framework/services.jar mount rootfs rootfs / rw remount # Backward compatibility symlink /system/etc /etc # create mountpoints and mount tmpfs on sqlite_stmt_journals mkdir /sdcard 0000 system system mkdir /system mkdir /data 0771 system system mkdir /cache 0770 system cache mkdir /sqlite_stmt_journals 01777 root root mount tmpfs tmpfs /sqlite_stmt_journals size=4m mount rootfs rootfs / ro remount write /proc/sys/kernel/panic_on_oops 1 write /proc/sys/kernel/hung_task_timeout_secs 0 write /proc/cpu/alignment 4 write /proc/sys/kernel/sched_latency_ns 10000000 write /proc/sys/kernel/sched_wakeup_granularity_ns 2000000 # mount mtd partitions # Mount the SD Card partition setprop EXTERNAL_STORAGE_STATE mounted mount vfat /dev/block/mmcblk0p1 /sdcard nosuid nodev # We chown/chmod /data again so because mount is run as root + defaults mount ext2 /dev/block/mmcblk0p2 /data nosuid nodev chown system system /data chmod 0771 /data # Same reason as /data above chown system cache /cache chmod 0770 /cache # This may have been created by the recovery system with odd permissions chown system system /cache/recovery chmod 0770 /cache/recovery
Compile
$ cd $ANDROID_SOURCE $ make
Making RootFS
Android Root File system
Android emulator has 3 basic images on tools/lib/images directory.
- ramdisk.img is gziped cpio archive. ramdisk.img is a small partition image that is mounted read-only by the kernel at boot time. It only contains /init and a few config files. It is used to start init which will mount the rest of the system images properly and run the init procedure. A Ramdisk is a standard Linux feature. It is made just for the Android and do special things to start up the Android system.
- system.img is a partition image that will be mounted as / and thus contains all system binaries.
- userdata.img is a partition image that can be mounted as /data and thus contains all application-specific and user-specific data.
Create the Android root filesystem for apf27
Android’s root file system is generated in $ANDROID_SOURCE/out/target/product/generic. We will create a folder containing all Android files images.
sudo rm -rf $ANDROID_SOURCE/rootfs/ cd $ANDROID_SOURCE/out/target/product/generic mkdir $ANDROID_SOURCE/rootfs cp -a root/* $ANDROID_SOURCE/rootfs/ cp -a system/* $ANDROID_SOURCE/rootfs/system/ cd $ANDROID_SOURCE/rootfs sudo chown -R root.root . sudo chmod -R a+rwX data system
JFFS2 Root file system
Actually, Android should use a file system how support mmap function like yaffs2, ext2 or ubifs. Unfortunaly, U-Boot support only jffs2 or ext2. So we will use ext2 on a µSD for data.
Prepare the MMC/µSD card
We will create two partitions on our mmc/µSD card, The first one will use for Android memory card, the second one will use for Android file system. First connect your card reader to your workstation, with the mmc/µSD card inside. Type the dmesg command to see which device is used by your workstation. Let’s assume that this device is /dev/sdb
$ dmesg ... [ 9145.613954] sdb: sdb1 sdb2 [ 9145.615125] sd 10:0:0:0: [sdc] Attached SCSI removable disk [ 9145.615258] sd 10:0:0:0: Attached scsi generic sg3 type 0
Type the mount command to check your currently mounted partitions. If MMC/SD partitions are mounted, unmount them.
In a terminal edit partitions with fdisk:
sudo fdisk /dev/sdb
Delete any existing partition with the d command.
Now, create the boot partition:
Command (m for help): n Command action e extended p primary partition (1-4) p Partition number (1-4): 1 First cylinder (1-495, default 1): 1 Last cylinder, +cylinders or +size{K,M,G} (1-239, default 239): +1G
Change its type to FAT32:
Command (m for help): t Selected partition 1 Hex code (type L to list codes): c Changed system type of partition 1 to c (W95 FAT32 (LBA))
Using the n command again, create a second partition filling up the rest of your card (just accept default values).
Now, format the partitions in your card:
sudo mkfs.vfat -n MemoryCard -F 32 /dev/sdb1 sudo mkfs.ext2 -L data /dev/sdb2
Boot setup
$ sudo mkfs.jffs2 -n -e 0x20000 --pad=0x700000 -r $ANDROID_SOURCE/rootfs -o $TFTPBOOT/apf27-rootfs.arm.jffs2
The last thing left to do is to specify how the board boots Linux.
In the U-boot prompt, make the mmc boot is on second partition of the mmc/µSD card
setenv addjffsargs 'setenv bootargs ${bootargs} root=/dev/mtdblock4 rootfstype=jffs2 init=/init' setenv bootcmd run mmcboot saveenv run update_kernel run update_rootfs
Debug
Prerequisite
Installing the Android Development Tools (ADT) Trace with logcat with Eclipse-ADT
export ADBHOST=w.x.y.z adb kill-server adb start-server
Test with Android emulator
Documentation on Android emulator
cd $ANDROID_SOURCE/kernel make ARCH=arm goldfish_defconfig make ARCH=arm CROSS_COMPILE=$ANDROID_SOURCE/prebuilt/linux-x86/toolchain/arm-eabi-4.2.1/bin/arm-eabi
Create AVD (Android Virtual Device)
$ANDROID_SDK/tools/android create avd -n APF27-H -t 4 -s 272x480 $ANDROID_SDK/tools/android create avd -n APF27-L -t 4 -s 480x272 $ANDROID_SOURCE/out/host/linux-x86/bin/emulator -avd APF27-H -sysdir $ANDROID_SOURCE/out/target/product/generic/ -kernel $ANDROID_SOURCE/kernel/arch/arm/boot/zImage -data $ANDROID_SOURCE/out/target/product/generic/userdata.img -ramdisk $ANDROID_SOURCE/out/target/product/generic/ramdisk.img -system $ANDROID_SOURCE/out/target/product/generic/system.img
Links
- Android page on elinux.org
- Android on OpenMoko
- http://wiki.kldp.org/wiki.php/AndroidPortingOnRealTarget
Thanks
Thanks to Xavier Romanens and Fabrice Carrel form Ecole d'ingénieurs et d'architectes de Fribourg for their contributions.