While our guide of how to build deploy vanilla AOSP on the Wandboard has helped many to understand more about the Android and Linux build tools, it is often required for applications to have hardware graphics acceleration.
The following guide shows how to download the Wandboard AOSP source, how to compile and deploy it and how to reconfigure Android for custom purpose.
- Host Build System: Ubuntu 16.04 LTS 64 bit
- Hardware: Wandboard Quad revision C1
- Kernel Version: 3.14.52 (way behind mainline, yet this is required for the hw graphics acceleration)
- Bootloader: u-boot (imx branch) v2015.04
- Android Version: 6.0.1 from the official Wandboard website
Additional Hardware requirements:
- USB-Serial Converter and Nullmodem Cable
- Micro SD Card (Class 10 for decent I/O performance)
- 5V wall plug (make sure it is 2A+ capable)
Before starting, a couple of dependencies need to be installed in order to compile the source.
First off install the required java version, which is openjdk-7-jdk. However the package is not available in the default 16.04 Ubuntu repos, the easiest way to install the sources is from the ppa (thread on askubuntu here).
Please note that while the official AOSP documentation suggest installing openjdk-8-jdk, we have been more successful with openjdk-7-jdk on this particular build.
sudo add-apt-repository ppa:openjdk-r/ppa sudo apt-get update sudo apt-get install openjdk-7-jdk
If you have previously installed one or more versions of java it is necessary to change at least the java and javac executable to the appropriate version. On Ubuntu, “update-alternatives” is used for this purpose.
# first check your java version java -version java version "1.6.0_45" Java(TM) SE Runtime Environment (build 1.6.0_45-b06) Java HotSpot(TM) 64-Bit Server VM (build 20.45-b01, mixed mode) # In this case our java version is 1.6 oracle # We will use "update-alternatives" to change to the newly installed # java 7 openjdk sudo update-alternatives --config java There are 4 choices for the alternative java (providing /usr/bin/java). Selection Path Priority Status ------------------------------------------------------------ 0 /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java 1081 auto mode 1 /usr/lib/jvm/java-6-oracle/jre/bin/java 1072 manual mode * 2 /usr/lib/jvm/java-7-openjdk-amd64/jre/bin/java 1071 manual mode 3 /usr/lib/jvm/java-7-oracle/jre/bin/java 1073 manual mode 4 /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java 1081 manual mode # and do the same for javac sudo update-alternatives --config javac There are 4 choices for the alternative javac (providing /usr/bin/javac). Selection Path Priority Status ------------------------------------------------------------ 0 /usr/lib/jvm/java-8-openjdk-amd64/bin/javac 1081 auto mode 1 /usr/lib/jvm/java-6-oracle/bin/javac 1072 manual mode * 2 /usr/lib/jvm/java-7-openjdk-amd64/bin/javac 1071 manual mode 3 /usr/lib/jvm/java-7-oracle/bin/javac 1073 manual mode 4 /usr/lib/jvm/java-8-openjdk-amd64/bin/javac 1081 manual mode # verify the new version java -version java version "1.7.0_95" OpenJDK Runtime Environment (IcedTea 2.6.4) (7u95-2.6.4-3) OpenJDK 64-Bit Server VM (build 24.95-b01, mixed mode)
Note that the Android build system will look for an environment variable “$JAVA_HOME” and – if it is defined – use this particular java installation (disregarding any possible changes made with update-alternatives). If you have installed other java versions, it is possible that this variable is set somewhere inside /etc/profile.d/ or similar.
# check if JAVA_HOME variable is set echo $JAVA_HOME /usr/lib/jvm/java-6-oracle # In our case, JAVA_HOME is already defined # We can either unset it temporarily in our current shell before building Android unset JAVA_HOME # Or add our own JAVA_HOME export to .bashrc or .profile # Or search and remove the definitions inside /etc folders # (in that case you need to logout and login again) cd /etc grep -sr "JAVA_HOME" . profile.d/jdk.sh:export JAVA_HOME=/usr/lib/jvm/java-6-oracle profile.d/jdk.csh:setenv JAVA_HOME /usr/lib/jvm/java-6-oracle ca-certificates/update.d/jks-keystore:export JAVA_HOME=/usr/lib/jvm/$jvm ca-certificates/update.d/jks-keystore:PATH=$JAVA_HOME/bin:$PATH
There are a couple of packages that are also required and detailed at source.android.com.
sudo apt-get install git-core gnupg flex bison gperf build-essential \ zip curl zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386 \ lib32ncurses5-dev x11proto-core-dev libx11-dev lib32z-dev ccache \ libgl1-mesa-dev libxml2-utils xsltproc unzip
At this point, starting a build would result in below error:
clang: error: linker command failed with exit code 1 (use -v to see invocation) build/core/host_shared_library_internal.mk:51: recipe for target 'out/host/linux-x86/obj32/lib/libart.so' failed make: *** [out/host/linux-x86/obj32/lib/libart.so] Error 1
Thankfully this problem has been patched for newer Android releases, the patch can be found in this post.
The first couple of lines of the file
build/core/clang/HOST_x86_common.mk needs to be changed to look like this:
CLANG_CONFIG_x86_DARWIN_HOST_EXTRA_CFLAGS := \ -integrated-as CLANG_CONFIG_x86_DARWIN_HOST_EXTRA_CFLAGS += -fstack-protector-strong endif ifeq ($(HOST_OS),linux) CLANG_CONFIG_x86_LINUX_HOST_EXTRA_ASFLAGS := \ --gcc-toolchain=$($(clang_2nd_arch_prefix)HOST_TOOLCHAIN_FOR_CLANG) \ --sysroot $($(clang_2nd_arch_prefix)HOST_TOOLCHAIN_FOR_CLANG)/sysroot \ -B$($(clang_2nd_arch_prefix)HOST_TOOLCHAIN_FOR_CLANG)/x86_64-linux/bin
Adjusting AOSP configuration for deployment
Besides fixing the above issue, it is necessary to apply a few modifications to the default configuration of the android framework as well as the mounting table found in fstab.freescale.
First let’s have a look at the framework config
# change into the device folder from the top directory cd device/fsl/wandboard # edit defaults.xml of the SettingsProvider gedit overlay/frameworks/base/packages/SettingsProvider/res/values/defaults.xml
Add the below properties to the file to avoid the screen timing out:
<bool name="def_stay_on_while_plugged_in">true</bool> <integer name="def_screen_off_timeout">30000</integer>
Above properties prevent Android from going to sleep. As it turns out in this unmodified version, going to sleep will cause the system to reboot instead.
Furthermore, when changing the layout of the SD-Card partitions, a change in the fstab is required. The below changes match the partition layout further down the line.
Have a look at the mount table fstab.freescale in the device directory and adjust it to the below content:
# change into the device folder from the top directory cd device/fsl/wandboard # edit fstab.freescale gedit fstab.freescale
# Android fstab file. #<src> <mnt_point> <type> <mnt_flags and options> <fs_mgr_flags> # The filesystem that contains the filesystem checker binary (typically /system) cannot # specify MF_CHECK, and must come before any filesystems that do specify MF_CHECK /devices/soc0/soc.0/2100000.aips-bus/2190000.usdhc/mmc_host* auto auto defaults voldmanaged=sdcard:auto /devices/soc0/soc.0/2100000.aips-bus/2184200.usb/ci_hdrc.1* auto auto defaults voldmanaged=usb:auto /devices/soc0/soc.0/2200000.sata/ata1* auto auto defaults voldmanaged=sata:auto /dev/block/mmcblk2p2 /system ext4 rw,barrier=1 wait,verify /dev/block/mmcblk2p4 /data ext4 nosuid,nodev,nodiratime,noatime,nomblk_io_submit,noauto_da_alloc,errors=panic wait,check /dev/block/mmcblk2p3 /cache ext4 nosuid,nodev,nomblk_io_submit wait,check /dev/block/zram0 none swap defaults zramsize=314572800
After these changes, you are now ready to compile the Kernel, the Uboot bootloader as well as the Android OS (consisting mainly of system image and ramdisk).
There are actually two ways of how to compile Android at this stage. Under the folder /cookers you will find an environment setup that will allow you to just use the “cook” command which in turn calls make in all kernel, uboot and AOSP. While this might be a good idea for a quick build, there is added value in compiling each of the parts separately in order to gain a deeper understanding of configuring building and deploying the various parts involved.
Building with the “cook” script
These commands allow the build to be kicked off without any further understanding of the source:
# change to the root directory of the Android sources source cookers/env.bash.imx6.edm1cf-sd.wandboard.hdmi cook -j4
The cook script will select the wandboard configuration for all bootloader, kernel and AOSP. Again make sure that your JAVA_HOME path variable is unset before executing cook.
After building bootloader, and kernel, the Android build starts
============================================ PLATFORM_VERSION_CODENAME=REL PLATFORM_VERSION=6.0.1 TARGET_PRODUCT=wandboard TARGET_BUILD_VARIANT=eng TARGET_BUILD_TYPE=release TARGET_BUILD_APPS= TARGET_ARCH=arm TARGET_ARCH_VARIANT=armv7-a-neon TARGET_CPU_VARIANT=cortex-a9 TARGET_2ND_ARCH= TARGET_2ND_ARCH_VARIANT= TARGET_2ND_CPU_VARIANT= HOST_ARCH=x86_64 HOST_OS=linux HOST_OS_EXTRA=Linux-4.4.0-47-generic-x86_64-with-Ubuntu-16.04-xenial HOST_BUILD_TYPE=release BUILD_ID=1.0.0-ga-rc6 OUT_DIR=out ============================================
Alternatively the parts of the system may be built manually.
Building with the kernel, bootloader and AOSP the traditional way
In order to start the AOSP build, the u-boot bootloader and Linux kernel need to be compiled first, because the wandboard target recipe has dependencies on both u-boot and kernel binaries.
Building the Linux kernel
# change into the Android top directory (/opt/android/wand in our case) # ... and set up CROSS_COMPILE and ARCH export ARCH=arm export CROSS_COMPILE="/opt/android/wand/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin/arm-eabi-" # change into kernel directory cd kernel_imx # if you would like to clean a prior build make distclean # if you want to clean the current configuration (.config) as well make mrproper # prepare the kernel configuration make wandboard_android_defconfig # edit the config to your liking to add or remove device drivers make menuconfig # build the kernel, -j tells the make file system how many jobs to launch in parallel make -j4 zImage # the output after building the kernel successfully will look something like this ... LD arch/arm/boot/compressed/vmlinux OBJCOPY arch/arm/boot/zImage Kernel: arch/arm/boot/zImage is ready #### make completed successfully (02:43 (mm:ss)) #### # also build modules and dtbs make -j4 modules make dtbs
Building the u-boot bootloader
# change to aosp top dir # and make sure ARCH and CROSS_COMPILE are set export ARCH=arm export CROSS_COMPILE="/opt/android/wand/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin/arm-eabi-" # change into u-boot directory cd bootable/bootloader/uboot-imx # prepare the configuration make wandboard_defconfig # build the bootloader make -j4 # on success the last output lines will look like this ... LD spl/u-boot-spl OBJCOPY spl/u-boot-spl.bin CFGS arch/arm/imx-common/spl_sd.cfg.cfgtmp MKIMAGE SPL #### make completed successfully (10 seconds) ####
# change to the aosp top dir cd /opt/android/wand # init environment . build/envsetup.sh # run 'lunch' and select #  wandboard-eng # as the target product lunch # you may also directly run lunch wandboard-eng # or lunch 23 # now check the Android configuration with printconfig # ... which should look something like this ============================================ PLATFORM_VERSION_CODENAME=REL PLATFORM_VERSION=6.0.1 TARGET_PRODUCT=wandboard TARGET_BUILD_VARIANT=eng TARGET_BUILD_TYPE=release TARGET_BUILD_APPS= TARGET_ARCH=arm TARGET_ARCH_VARIANT=armv7-a-neon TARGET_CPU_VARIANT=cortex-a9 TARGET_2ND_ARCH= TARGET_2ND_ARCH_VARIANT= TARGET_2ND_CPU_VARIANT= HOST_ARCH=x86_64 HOST_OS=linux HOST_OS_EXTRA=Linux-4.4.0-47-generic-x86_64-with-Ubuntu-16.04-xenial HOST_BUILD_TYPE=release BUILD_ID=1.0.0-ga-rc6 OUT_DIR=out ============================================ # double check JAVA_HOME var echo $JAVA_HOME /usr/lib/jvm/java-7-openjdk-amd64 # JAVA_HOME must be either unset # or point to /usr/lib/jvm/java-7-openjdk-amd64 # otherwise the build might not start # start compile make -j8 # once finished the output should look something like this Creating filesystem with parameters: Size: 624152576 Block size: 4096 Blocks per group: 32768 Inodes per group: 7632 Inode size: 256 Journal blocks: 2380 Label: system Blocks: 152381 Block groups: 5 Reserved block group size: 39 Created filesystem with 1530/38160 inodes and 93182/152381 blocks build_verity_tree -A aee087a5be3b982978c923f566a94613496b417f2af592639bc80d141e34dfe7 out/target/product/wandboard/obj/PACKAGING/systemimage_intermediates/system.img /tmp/tmpx_98xE_verity_images/verity.img system/extras/verity/build_verity_metadata.py 624152576 /tmp/tmpx_98xE_verity_images/verity_metadata.img 5339aa8e5e3793d45681e7238d0cda3ee688efd07db47ab27fd942559534db50 aee087a5be3b982978c923f566a94613496b417f2af592639bc80d141e34dfe7 /dev/block/mmcblk2p5 out/host/linux-x86/bin/verity_signer build/target/product/security/verity.pk8 append2simg out/target/product/wandboard/obj/PACKAGING/systemimage_intermediates/system.img /tmp/tmpx_98xE_verity_images/verity_metadata.img append2simg out/target/product/wandboard/obj/PACKAGING/systemimage_intermediates/system.img /tmp/tmpx_98xE_verity_images/verity.img Install system fs image: out/target/product/wandboard/system.img out/target/product/wandboard/system.img+out/target/product/wandboard/obj/PACKAGING/recovery_patch_intermediates/recovery_from_boot.p maxsize=642318336 blocksize=4224 total=378917909 reserve=6488064 simg2img out/target/product/wandboard/system.img out/target/product/wandboard/system_raw.img;
After building AOSP, the ramdisk ramdisk.img as well as the system partition system.img are generated in the appropriate out folder “./out/target/product/wandboard”.
Deploying Bootloader, Kernel and Ramdisk
Deploying the produced binaries on an SD-Card will allow AOSP to be booted on the wandboard.
While the included cookers script suggest to create a total of 9 partitions, we opt to deploy the system on an SD-Card with only 4 partitions.
In order to format the SD-Card properly, we recommend to use UI based partition manager “gparted”.
# install gparted if not installed already sudo apt-get install gparted # launch gparted sudo gparted # step by step guide # select SD-Card (be careful! make sure it is the right block device, making mistakes in this step and modifying wrong block devices may cause damage to your hard drive beyond repair) # 1. create first primary partition at offset 8MiB (before comes bootloader), size 33MiB, choose fat32, label BOOT # 2. create second primary partition right after BOOT, size 1024MiB, ext4, label SYSTEM # 3. create third primary partition right after SYSTEM, size 1024MiB ext4, label CACHE # 4. create fourth primary partition right after CACHE, size is the remaining space on your SD-Card, label DATA
Below screenshot shows the partition table of the SD-Card
Once the SD-Card is formatted, it is time to mount the BOOT and SYSTEM partition and deploy the files. The data and cache partition remain empty for deployment, on first boot the data partition will be populated by Android.
Deploying Android onto an SD-Card
It is essential to understand that deployment of Android on any media is highly customisable. While most Android images found on embedded platforms follow the pattern to deploy partitions such as modem, recovery or external sdcard, none of these are mandatory.
The Android OS expects though to have a /cache and /data partition as well as a mount point for /system.
While by default a ramdisk is extracted into memory and mounted as root partition, even that behavior may be changed in favor of one root partition containing both ramdisk content as well as /system directory.
In our case we will favor to use a ramdisk and a separate /system partition.
Furthermore it is necessary to understand that while the /system partition contents have been compiled into the out/target/product/wandboard/system directory, the permissions and mods of the contents are not set appropriate for deployment. However these files are also written into the disk images out/target/product/wandboard/system.img and the raw image out/target/product/wandboard/system_raw.img. While system.img cannot be easily mounted on an Ubuntu host, system_raw.img is a plain ext4 partition image of the Android /system directory containing all the right file mods and permissions.
The system_raw.img can be recompiled using the simg2img utility which is also helpful when restoring system partitions directly from a device or rom.
Deploying the System partition
# mount system_raw.img # change to source root croot # or simply cd /opt/android/wand # create a mount point and mount the system image mkdir system_mnt sudo mount out/target/product/wandboard/system_raw.img system_mnt # check if the image has been mounted mount /android/out/target/product/wandboard/system_raw.img on /android/system_mnt type ext4 (rw,relatime,data=ordered) # copy the files over to the SD-Cards system partition cd system_mnt sudo cp -a * /mnt/$USER/SYSTEM/ sync
Copying these files and syncing may take quite a while depending on your SD-Card transfer rate.
Deploying the Boot partition
In order to set up the boot partition, bootloader, ramdisk and device tree binaries need to be copied into the BOOT partition.
# change to root dir of aosp cd /opt/android/wand # copy u-boot bootloader sudo cp bootable/bootloader/uboot-imx/u-boot.img /media/$USER/BOOT/ # copy the Linux kernel sudo cp kernel_imx/arch/arm/boot/zImage /media/$USER/BOOT/ # copy the device tree binaries for wandboard quad/dual sudo cp kernel_imx/arch/arm/boot/dts/imx6q-wandboard.dtb /media/$USER/BOOT/ sudo cp kernel_imx/arch/arm/boot/dts/imx6dl-wandboard.dtb /media/$USER/BOOT/ # convert the ramdisk to a u-boot image file named uramdisk.img # and copy it to the boot partition sudo mkimage -A arm -O linux -T ramdisk -C none -a 0x10800800 -n "Android Root Filesystem" -d ./out/target/product/wandboard/ramdisk.img ./out/target/product/wandboard/uramdisk.img sudo cp ./out/target/product/wandboard/uramdisk.img /media/$USER/BOOT/ # unmount everything sync sudo umount /media/$USER/* # flash the 1st stage bootloader # find the SD-Card block device name /dev/sdX lsblk sudo dd if=bootable/bootloader/uboot-imx/SPL of=/dev/sdX bs=1k seek=1 sync
After this procedure the SD-Card is ready to boot and will start Android. Using an USB-to-serial adapter, it is now possible to observe the system booting using your preferred serial terminal program (minicom, screen, putty, etc.).
# start and setup minicom sudo minicom -s wandboard # select 115200, 8N1, no hw flow control, no sw flow control # save and exit
Hopefully this guide has helped you getting started on working on your own AOSP build on the Wandboard. If you liked the tutorial please let us know by sharing it on G+ and throw us a +1.