Jan 30, 2015

Android on Zedboard

After saying "Android Shandroid" for such a long time, I finally decided to play around with Android on Zedboard.  Running modern Android on the Zedboard is apparently difficult, as Sven Anderson showed.  But maybe if I go slow, I can get lucky; I certainly will learn a lot regardless!

Android Wear

Android Accessory Development Kit 2014 runs on Arduino, so not a production quality platform.
To view all AOSP branches:

$ git clone https://android.googlesource.com/platform/manifest.git
$ cd manifest
$ git branch -r | grep w_
  origin/android-4.4w_r1
  origin/android-l-preview_r2

To get what I need, run in the source code folder:

$ repo init -u https://android.googlesource.com/platform/manifest -b android-4.4w_r1
$ repo sync #Takes 2 hours even on a fast connection

I enabled ccache:

$ export USE_CCACHE=1
$ /mnt/work/android/anroid-4.4w_r1/prebuilts/misc/linux-x86/ccache/ccache -M 50G

Choosing my build:

$ source build/envsetup.sh
$ lunch

But I don't see either the Samsung Gear Live or the LG G Watch in the list of lunch menus.  Is this even the right branch?

On the other hand, there is the aosp/lollipop-wear-release branch in the framework/native repository.  And there is the android-wear-5.1.1_r1 branch in the manifest repo.  So I switch my repository to it, like this:

$ repo init -b android-wear-5.1.1_r1


$ repo sync #Takes 30 hour even on a fast connection

After this, the Eclipse git view shows that my frameworks/native repo is on android-wear-5.1.1_r1 (00afb81), but the lunch menu STILL does not show the Samsung Gear device:

henry@w540:~/band/android$ . build/envsetup.sh 
including device/asus/deb/vendorsetup.sh
including device/asus/flo/vendorsetup.sh
including device/asus/fugu/vendorsetup.sh
including device/asus/grouper/vendorsetup.sh
including device/asus/tilapia/vendorsetup.sh
including device/generic/mini-emulator-arm64/vendorsetup.sh
including device/generic/mini-emulator-armv7-a-neon/vendorsetup.sh
including device/generic/mini-emulator-mips/vendorsetup.sh
including device/generic/mini-emulator-x86_64/vendorsetup.sh
including device/generic/mini-emulator-x86/vendorsetup.sh
including device/htc/flounder/vendorsetup.sh
including device/lge/hammerhead/vendorsetup.sh
including device/lge/mako/vendorsetup.sh
including device/moto/shamu/vendorsetup.sh
including device/samsung/manta/vendorsetup.sh
including sdk/bash_completion/adb.bash

So what makes any android-wear-* branch really a "wear" branch?

Building the Linux kernel

I downloaded the latest ADI kernel.  This might be too new for Android Wear branch of the AOSP (android-4.4w_r1 above), but we will see.

/mnt/work/android$ git clone https://github.com/analogdevicesinc/linux.git
/mnt/work/android$ cd kernel

I copied the NFS enabled kernel defconfig from my previous work on running a bare metal code, into the kernel's arch/arm/config folder, and then generated the .config file like this:

/mnt/work/android/kernel$ make ARCH=arm zynq_xcomm_adv7511_nfs_defconfig

Then I compiled the kernel, knowing that I would change the kernel config and possibly even patch the kernel for Android.

/mnt/work/android/kernel$ export CROSS_COMPILE=arm-xilinx-linux-gnueabi-
/mnt/work/android/kernel$ make ARCH=arm uImage LOADADDR=0x8000

History of HDMI Android

Can boot Android 5.0.2_r1 from sdcard and get the home screen, but the launcher crashes, as you can see below (note the Lollipop menu icons at the bottom)

When booting from NFS I get a shell over serial, but as soon as I type something (like ls), I don't get the prompt back.  BUT, the Android icon above does update VERY SLOWLY, so the kernel IS alive.  I am trying to debug the Android startup--which is taxing my debugging skill.

Update 2015 Feb 8

"nfs server not responding, still trying" is a red herring.  With wireshark, I verified that the server IS responding.

To see if I get a usable Android system, I switched over to sdcard boot, but the launcher crashed:

java.lang.RuntimeException: Unable to get provider com.android.launcher2.LauncherProvider: java.lang.NullPointerException: Attempt to invoke interface method 'void com.android.internal.appwidget.IAppWidgetService.deleteHost(java.lang.String, int)' on a null object reference

Logcat shows that I am dropping hundreds of frames.  This system is unusable without a GPU...

Update 2015 Feb 1

Tried putting /system and /data on the SD card, meaning I kept the original mount entries in the fstab.  Still have the "nfs: server not responding, still trying" error, the same binder error.  Now, I don't even get the initial Android splash screen.  I CAN get back the Android splash screen (above) when I use a sandisk SD card, but all the problems I saw when running with /system and /data over NFS.  What's common between the 2 configurations are that the root is still over NFS.  Now I realize that this may be where Sven got stuck, but the difference is that I am not getting "untracked pid" problem.  The problems on my radar at this point are:
  1. "nfs: server 192.168.1.2 not responding, still trying"
  2. Shell is responsive at first ("ls" and "logcat" works) but does not return when I type any command after seeing the above error
  3. Cannot discover ADB device
  4. Screen does not get past the splash screen
Here are the problems found in the logcat output:
  1. init: /dev/hw_random not found: you got me; I do NOT have a HW random generator
  2. failed open /proc/sys/net/ipv6/conf: did NOT go away even after I rebuilt the kernel with CONFIG_IPV6 AND confirmed with the Buildroot rootfs that the said file DOES exist!
  3. failed to create DRM screen and then:
    1. "will fall back to other EGL drivers if any"
    2. "using SW screen"
    3. gralloc finds the /dev/fd, and uses 1280x1024
    4. E/SurfaceFlinger(  977): hwcomposer module not found
    5. W/SurfaceFlinger(  977): no suitable EGLConfig found, trying a simpler query
    6. simpler query must have succeeded, because I see VMware OpenGL ES information
    7. W/EGL-GALLIUM(  977): native window format 0x43 != config format 0x1
  4. "Error opening trace file"
  5. E/CameraService(  987): Could not load camera HAL module
  6. E/AudioFlinger(  987): int android::load_audio_interface(const char*, audio_hw_device_t**) couldn't load audio hw module audio.primary (No such file or directory)
  7. W/EGL-GALLIUM( 1102): cache full: buf 0xb3bfb308, width 1280, height 1024, format 2, usage 0x933

Prep my 64-bit Ubuntu 14.04 desktop for the build

While playing around with Buildroot Linux, I've already accumulated almost all of the required utilities, so the following command is more than enough to get to what Google recommends for Ubuntu 14.04:

sudo apt-get install bison g++-multilib git gperf libxml2-utils lib32z1 curl

I added the following line to my ~/.bashrc to use ccache:

export USE_CCACHE=1

I skipped the udev rules for adb over USB cable because I can already talk to the Zedboard over Cypress USB2Serial port and can JTAG to the target over FTDI device driver (see this Google doc if you want to see how I did it), and highly doubt that I will get to the point of needing adb any time soon.

Anroid kernel

I have a Buildroot kernel I've been using, but I've told that have to patch the kernel, so I downloaded the Digilent kernel to refer to:

/mnt/work/zed$ git clone https://github.com/Digilent/linux-digilent.git digker

How is the Android 2.3 kernel different than the stock Zedboard kernel?  Let's first compare the device tree.

Device tree differences

In the ADI kernel for HDMI design, DTS are divided into 3 files: zynq.dtsi (common to Zynq CPU), which is included by zynq-zed.dtsi (Zedboard specialization), which is finally included by zynq-zed-adv7511.dts (Specialization for the HDMI HW).  But the Android 2.3 version of Digilent kernel (what I cloned above) has just 1 DTS file: arch/arm/boot/dts/digilent-zed.dts.  This DTS is the same as the DTS that comes with the Digilent HW design, except for the bootargs specifying RAM rootfs.

DifferenceDigilent DTSADI DTSImplication
root compatiblexlnx,zynq-zedxlnx,zynq-7000arch/arm/mach-zynq/ different
axi bus compatible"xlnx,ps7-axi-interconnect-1.00.a", "simple-bus""simple-bus"?
cpus/compatiblexlnx,ps7-cortexa9-1.00.aarm,cortex-a9arch/arm/mach-zynq/
cpus propertycache size specified. clock, timebase frequencyspecifiedclocks points to clkc_3. operating-points specifiedpower management?
pmunonearm,cortex-a9-pmu?
axi VDMABroken axi-dma@40420000: compatible = "xlnx,axi-dma-6.03.a", "xlnx,axi-dma-1.00.a"Proven working axivdma@43000000: compatible = "xlnx,axi-vdma"
axi_i2s_0clock frequency specifiedDMA controller handles specified clock handles specified?
i2c@41640000On PS AXI bus
xlnx,axi-iic-1.02.a IRQ: 53. Base address 0x41640000
On FPGA AXI bus
xlnx,axi-iic-1.01.b.  IRQ: 58.  Base address 0x41600000
?
ps7_afi4 instances of "xlnx,ps7-afi-1.00.a"noneWhat is AFI?
ddrccompatible = "xlnx,ps7-ddrc-1.00.a"compatible = "xlnx,ps7-ddrc-1.00.a", "xlnx,ps7-ddrc", "xlnx,zynq-ddrc-1.0"?
ps7_dev_cfg
clock handles specified?
ps7_dmacompatible = "xlnx,ps7-dma-1.00.a", "arm,pl330"compatible = "arm,primecell", "arm,pl330".  cells, channels, requests specified?
Ethernetxlnx,enet-clk-freq-hz = <0x7735940>                        xlnx,enet-reset = <0xffffffff>;xlnx,enet-clk-freq-hz = <0x17d7840>                        xlnx,enet-reset = "MIO 11"?
gpioemio-gpio-width = <60>
gpio-mask-high = <0xc0000> gpio-mask-low = <0xfe81>

?
ps7_iop_bus_config"xlnx,ps7-iop-bus-config-1.00.a"noneWhat is IOP?
qspi
Child primary_flash "st,m25p80" specifiedADI Can boot off QSPI?
gic#address-cells = < 2 >
compatible = "xlnx,ps7-scugic-1.00.a", "arm,cortex-a9-gic", "arm,gic"
compatible = "arm,cortex-a9-gic"?
watchdog?
swdt@f8005000.  IRQ 9?
watchdog"xlnx,ps7-scuwdt-1.00.a""arm,mpcore_wdt"?
slcr (system controller)"xlnx,ps7-slcr-1.00.a"compatible = "xlnx,zynq-slcr", "syscon"
clkc enumerated
?
timercompatible = "xlnx,ps7-ttc-1.00.a"
2 clocks
compatible = "cdns,ttc"
1 clock <clkc 6>
?
sdioxlnx,has-power = <0x0>
xlnx,has-wp = <0x1>
clocks explicitly specified?
ps7_uartcompatible = "xlnx,ps7-uart-1.00.a", "xlnx,xuartps"compatible = "xlnx,xuartps"?
ps7_usbxlnx,usb-reset = <0xffffffff>
?
leds
8 LED GPIO ports explicitly specified
oled"dglnt,pmodoled-gpio"
No use for small OLED
ocmc
reg = <0xf800c000 0x1000>I recently fixed this.
adv7511
Proven workingSaw penguin on an HDMI monitor
spi1
I recently proved this HWAndroid for industrial control? :-)
Just from the DTS, I can tell there is a big difference between the Digilent kernel and the ADI kernel.  Since the ADI kernel is proven to work, I will start from there.

Kernel defconfig

A kernel defconfig file captures (ideally) in a concise way a kernel's configuration.  Before building the kernel proper, you run a make command at the root of a kernel with the name of the defconfig file, to generate a .config file that has the directives from the specified defconfig.  Ever since I got both the HDMI and NFS rootfs working on the Zedboard, I have been using the defconfig that has only a few modifications from what was in the ADI's kernel git repository.  So I start by copying the known working defconfig:

/mnt/work/zed/kernel/arch/arm/configs$ cp zynq_xcomm_adv7511_nfs_defconfig zynq_xcomm_adv7511_nfs_android_defconfig

When I open this file to add Android related configs as directed here, I noticed that the kernel defconfig I've been using already has CONFIG_STAGING and many of the configs listed in the link above.  So I simply added the following at the end of the copied file:

CONFIG_EXPERIMENTAL=y
CONFIG_CGROUP_FREEZER=y
CONFIG_CGROUP_CPUACCT=y
CONFIG_RESOURCE_COUNTERS=y
CONFIG_CGROUP_SCHED=y
CONFIG_RT_GROUP_SCHED=y
CONFIG_PREEMPT=y
CONFIG_PM_AUTOSLEEP=y
CONFIG_PM_WAKELOCKS=y
CONFIG_XFRM_USER=y
CONFIG_NET_KEY=y
CONFIG_IP_ADVANCED_ROUTER=y
CONFIG_IP_MULTIPLE_TABLES=y
CONFIG_INET_ESP=y
# CONFIG_INET_LRO is not set
CONFIG_NET_SCHED=y
CONFIG_NET_SCH_HTB=y
CONFIG_FB=y
CONFIG_SYNC=y
CONFIG_USB_G_ANDROID=y
CONFIG_USB_OTG_WAKELOCK=y
CONFIG_RTC_CLASS=y
CONFIG_ANDROID=y
CONFIG_ANDROID_BINDER_IPC=y
CONFIG_ASHMEM=y
CONFIG_ANDROID_LOGGER=y
CONFIG_ANDROID_LOW_MEMORY_KILLER=y
CONFIG_ANDROID_INTF_ALARM_DEV=y

Since I have been building the kernel and the rootfs with Buildroot, it would be interesting to see if these config additions still work.  All I have to change is the Buildroot config's kernel --> defconfig name property, to point to the copied defconfig (zynq_xcomm_adv7511_nfs_android), rebuild, and boot the Zedboard with the new kernel.  The board still boots, and I can verify that the intended configs were pulled in with this command:

# zcat /proc/config.gz | grep ANDROID

The kernel log shows some new entries for the configs I just defined:

ashmem: initialized
logger: created 256K log 'log_main'
logger: created 256K log 'log_events'
logger: created 256K log 'log_radio'
logger: created 256K log 'log_system'

But I still do NOT know if I have all the code that the above configs are supposed to pull in are in the kernel.

Kernel source for Android

Thanks to the Eclipse kernel project I setup previously, it's easy to search for any symbols in the Linux kernel.  Comprehensively, above #defines fall into 4 categories: I already have the code for it, or I do not, multiplied against Digilent kernel has the code for it, or does not.  But as far as I can see, there is no difference between my existing kernel and the Digilent kernel, which is a bit strange.  Deflatingly, all that seems to have happened is that I picked up a few minor features related to Android (like the alarm and wakelock), but nothing major (e.g. there wasn't even a code code the vaunted low memory killer)?

Oddly, I see 2 additional Android related defconfigs in the cambridge hacker's version (below): CONFIG_HAS_WAKELOCK and CONFIG_ANDROID_PARANOID_NETWORK, with actual code behind the #defines.  But since I do not have such code in my kernel, I just move onto Android itself for now.

Build Android

Get AOSP

Get repo and the Android Lollipop (5.0.2) source code as packaged by siprop:

$ wget https://storage.googleapis.com/git-repo-downloads/repo
$ chmod a+x repo
$ PATH=~/work:$PATH
$ cd ~/work/zed/android/

$ git config --global user.name "Henry Choi"
$ git config --global user.email "henry.omd@gmail.com"

$ repo init -u https://android.googlesource.com/platform/manifest -b android-5.0.2_r1
$ repo sync

Actually, I did not do exactly above; originally, I checked out android-5.0.1_r1, but changed to android-5.0.2_r1 with this command:

$ repo init -b android-5.0.2_r1
$ repo sync

After letting the download finish in a couple of hours ("shutdown -h 120"), I found that it ate up 30 GB of my disk--even BEFORE building!

Get siprop's Android files

This was supposed to be easy: "repo init -u https://github.com/noritsuna/zedroid_manifests -b zedroid-5.0.2_r1" then "repo sync".  But repo init complained about invalid markup, so I just did the repo sync process manually: 

$ mkdir siprop; cd siprop

Ah, so mesa IS used for software OpenGL after all:

~/work/zed/siprop$ git clone https://github.com/noritsuna/zedroid_external_mesa3d
~/work/zed/siprop$ mv ../android/external/mesa3d .mesa3d.ORIG
~/work/zed/siprop$ mv zedroid_external_mesa3d ../android/external/mesa3d

siprop's product definition:

~/work/zed/siprop$ git clone https://github.com/noritsuna/zedroid_device_xilinx_zedboard
~/work/zed/siprop$ mv zedroid_device_xilinx_zedboard ../android/device/xilinx/zedboard

siprop's frameworks/native and frameworks/base: I do NOT think these are necessary, because diff shows these folders are apparently the same as the counterparts in AOSP's frameworks

~/work/zed/siprop$ git clone https://github.com/noritsuna/zedroid_frameworks_native
~/work/zed/siprop$ git clone https://github.com/noritsuna/zedroid_frameworks_base
~/work/zed/siprop$ git clone https://github.com/noritsuna/zedroid_system_core

Changing the siprop's zedboard build configuration for NFS rootfs

In the zedboard folder, there are a few files that describe a build target "zedboard" which will be presented to the lunch build menu.

~/work/zed/android/device/xilinx/zedboard$ ls
AndroidProducts.mk  fstab.xilinxzynqplatform    README.md           zedboard_GLES20.mk
BoardConfig.mk      init.xilinxzynqplatform.rc  swapinit.sh         zedboard.mk
device.mk           mixer_paths.xml             vendorsetup.sh
egl.cfg             overlay                     zedboard_GLES12.mk

All vendorsetup.sh in <AOSP>/device/ folder get pulled into the lunch menu.  I can add more lunch combo for each board type, but I'll live with the options presented by cambridgehacker: zedmini-userdebug and zedboard-userdebug:

~/work/zed/android$ tail device/xilinx/zedmini/vendorsetup.sh 
add_lunch_combo zedboard-userdebug
add_lunch_combo zedboard_GLES12-userdebug
add_lunch_combo zedboard_GLES20-userdebug

siprop apparently mounts the SD card, and the system.img and userdata.img on the SD card, as you can see in fstab.xilinxzynqplatform:

~/work/zed/android/device/xilinx/zedboard$ cat fstab.xilinxzynqplatform 
/dev/block/mmcblk0p1 /storage/sdcard  vfat    rw wait
#/dev/block/mmcblk0p2 /system         ext4    ro wait
#/dev/block/mmcblk0p3 /data           ext4    rw,noatime,nosuid,nodev wait

Any mounts specified above are mounted during init by init.xilinxzynqplatform.rc which has "on fs" event handler that tries to mount_all, and then mkdir folders like /data (I assume it's OK if the folder already exists).  I think the init script knows to look for a file /init.$systemname.rc.  Karim Yagmor said that this name comes from /proc/cpuinfo, and I know that my systemname is xilinxzynqplatform (apparently).

The init.rc also calls swapinit.sh, which tries to mount swap on the 4th partition of the SD card, so I know I should have 4 partitions on this SD card; the 1st partition will be the boot partition, but can also be used for general storage, and the 4th partition will be the Linux Swap filesystem as big as the Zedboard's RAM (512 MB)--the 2nd and the 3rd partitions can old the system.img and the data partitions, but I will not use them.  In GPartEd, I kept things simple: 1 GB each for the first 3 partitions, and the rest to the swap.  1 GB boot partition is unnecessarily large for my 4 MB boot.bin, but what the hell: this is the smallest SD card I have.

Of course, the question is whether the 4th partition will actually be mounted to /dev/block/mmcblk0p4 on the zedboard.

  if [ -b /dev/block/mmcblk0p4 ] ; then
    swapon /dev/block/mmcblk0p4
    echo 30 > /proc/sys/vm/swappiness
    sysctl -w vm.swappiness=30
    break
  fi

device.mk

This init, fstab, and swap init files have to get copied to the product output folder, so there is a PRODUCT_COPY_FILES at the end of device.mk:

PRODUCT_COPY_FILES += \
device/xilinx/zedboard/init.xilinxzynqplatform.rc:root/init.xilinxzynqplatform.rc \
    device/xilinx/zedboard/fstab.xilinxzynqplatform:root/fstab.xilinxzynqplatform \
    device/xilinx/zedboard/swapinit.sh:root/sbin/swapinit.sh

#PRODUCT_COPY_FILES +=    $(LOCAL_KERNEL):uImage
    
Note the colon that separates the source and destination, and space separates each src:dest pair.  Since I am NFS booting the kernel, I do NOT need to copy the kernel.  OTHERWISE, the compressed kernel image $(LOCAL_KERNEL) has to be defined to $(TARGET_PREBUILT_KERNEL), which obviously has to be defined somewhere: in BoardConfig.mk, apparently.  As Karim Yagmor talked about in section 4, Architecture of Embedded Android, BoardConfig.mk describes a board, and AndroidProducts.mk or SingleProduct.mk describes the packages I want on the board.

device.mk changes the product properties in several ways:
  • DEVICE_PACKAGE_OVERLAYS (device/xilinx/zedboard/overlay itself holding a couple of property XML files)
  • PRODUCT_CHARACTERISTICS := nosdcard
In cambridgehacker's distribution, I had a difficult time pulling in libhwui.  Maybe it's because I was missing these 2 packages?

PRODUCT_PACKAGES += \
    libGLES_android \
    libGLES_mesa

BoardConfig.mk

Defines USE_OPENGL_RENDERER, which SHOULD pull in libhwui.  Because I was having problem with dex2oat running when booting from NFS, I wanted the dex2oat to run during build, instead of the first time (as is customarily done):

WITH_DEXPREOPT := true

Without this, art (Android runtime) calls dex2oat on the 1st boot.

AndroidProducts.mk

Maybe because of the example Karim Yagmor gave in his book and he was an early advocate of Android on embedded, AndroidProducts.mk simply indirects to another makefile in the same folder;

PRODUCT_MAKEFILES := \
    $(LOCAL_DIR)/zedboard.mk \
    $(LOCAL_DIR)/zedboard_GLES12.mk \
    $(LOCAL_DIR)/zedboard_GLES20.mk

Besides the 2 versions of GLES system , zedboard.mk describes the virtual display version of the system.

zedboard_GLES12.mk

I tried to reduce the size of the product from full to generic_no_telephony.

$(call inherit-product, build/target/product/generic_no_telephony.mk)
PRODUCT_PROPERTY_OVERRIDES := \
    ro.config.use.gles12_only=true \
    ro.config.use.android_renderer=true
...
$(call inherit-product, device/xilinx/zedboard/device.mk)

At first, I went for core_minimal--which was the smallest product that Android build would take, but I found out that Android needs fonts after all, as you can see in the inheritance relationship found in build/target/product/:

Q: when I change the parent product from "full" to "core_minimal" (which should be much smaller than the full), the build time still seems to be the same?

I also changed PRODUCT_PROPERTY_OVERRIDES.  one of the workarounds for running over NFS is to prevent clearing of the IP, so I appended a property as shown below

PRODUCT_PROPERTY_OVERRIDES += ethernet.clear.ip \

Hacking the Android source for NFS hosted /data partition

In Android framework, installd (daemon) sets up applications before it can be run.  But unlike many of the core services, installd runs as the user "install", as you can see in the (edited) list of processes at the very beginning of the Android startup:

root@zedboard:/ # ps
USER     PID   PPID  VSIZE  RSS     WCHAN    PC        NAME
root      1     0     2616   480   c011d780 00022920 S /init
root      590   2     0      0     c003eafc 00000000 S binder
logd      1021  1     6988   984   ffffffff b6ee9dc4 S /system/bin/logd
root      1022  1     3688   260   c014eb00 000310b8 S /sbin/healthd
root      1023  1     4484   1164  c014eb00 b6ebac80 S /system/bin/lmkd
system    1024  1     3248   572   c0434774 b6ecf150 S /system/bin/servicemanager
root      1025  1     7700   2168  ffffffff b6f6a994 S /system/bin/vold
system    1026  1     63568  16336 ffffffff b63b2e4e R /system/bin/surfaceflinger
root      1027  1     3208   944   c0037a74 b6f33dc4 S /system/bin/sh
root      1028  1     4384   1480  00000000 b6f5c6f0 R /system/bin/netd
root      1029  1     3840   924   c04a19e8 b6f03088 S /system/bin/debuggerd
drm       1030  1     11488  4188  ffffffff b6ea4150 S /system/bin/drmserver
media     1031  1     12736  5264  00000000 b6fe5abc R /system/bin/mediaserver
install   1032  1     3200   712   c04a19e8 b6f1d088 S /system/bin/installd
keystore  1033  1     6284   2084  c0434774 b6eca150 S /system/bin/keystore
root      1035  1     24416  7292  00000000 b6f01088 R /system/bin/app_process
shell     1036  1     3644   272   ffffffff 00020db4 S /sbin/adbd
root      1092  2     0      0     c003f43c 00000000 S kworker/0:2
graphics  1114  1     14540  4812  ffffffff b6f93150 S /system/bin/bootanimation
root      1141  1028  0      0     c002684c 00000000 Z iptables

Build

Before launching the build, increase the ccache size:

henry@Zotac64:~/work/zed/android$ prebuilts/misc/linux-x86/ccache/ccache --max-size=50G
Set cache size limit to 50.0 Gbytes

I am not sure what envsetup does, but it's in the doc.

~/work/zed/android$ source build/envsetup.sh

At first, I want to start with a small distribution: zedmini-userdebug

~/work/zed/android$ lunch zedboard_GLES20-userdebug

Then I can (try to) build it.  Since there are so many warnings (expected!), pipe the output to bitbucket to see only errors.

~/work/zed/android$ make -j 2 > /dev/null

The first time build takes about 5 hours, but subsequent builds are significantly faster thanks to ccache (< 1.5 hours).

/mnt/work/zed/android/out/target/product/zedboard$ ls
android-info.txt  clean_steps.mk  installed-files.txt       ramdisk.img  system
cache             data            obj                       root         system.img
cache.img         gen             previous_build_config.mk  symbols      userdata.img

NFS boot with /system and /data on SD card

I discovered that Android has to be hacked to run with NFS hosted /data.  So this is a hybrid approach of keeping the NFS rootfs, but /system and /data on the SD card.  When the SD card is partitioned as illustrated way above (I used GPartEd), the SD card will auto mount at /media/<user>/system and /media/<user>/data.  The strategy is to copy the generated system.img and userdata.img into those partitions.

$ sudo mkdir -p /export/root/zedroid /tmp/system /tmp/userdata
~/work/zed/android/out/target/product/zedboard$ zcat ramdisk.img | sudo sh -c 'cd /export/root/zedroid && cpio -i --no-absolute-filenames'
~/work/zed/android/out/target/product/zedboard$ sudo mount system.img /tmp/system
$ sudo cp -a /tmp/system/* /media/henry/system
$ sudo umount /tmp/system
~/work/zed/android/out/target/product/zedboard$ sudo mount userdata.img /tmp/userdata
$ sudo cp -a /tmp/userdata/* /media/henry/data
$ sudo umount /tmp/userdata

This runs a lot of /system/bin/patchcoat--which is farther along the boot process than achieved in the alternative approach below.

NFS boot with /data also on NFS (does NOT work yet)

Among articles found on the web on how to NFS boot an Android target, Linaro seems to have formalized the procedure at least for the Panda board, and may be worth studying.

~/work/zed$ git clone https://android.git.linaro.org/git-ro/platform/external/linaro-android-tools.git -b linaro_android_4.4

The commands below are trying to mimic the bash function func_create_rootfs() in linaro-android-nfs-tool.sh just cloned above.

$ sudo mkdir -p /export/root/zedroid /tmp/system /tmp/userdata
~/work/zed/android/out/target/product/zedboard$ zcat ramdisk.img | sudo sh -c 'cd /export/root/zedroid && cpio -i --no-absolute-filenames'
~/work/zed/android/out/target/product/zedboard$ sudo mount system.img /tmp/system
$ sudo cp -a /tmp/system/* /export/root/zedroid/system
$ sudo umount /tmp/system
~/work/zed/android/out/target/product/zedboard$ sudo mount userdata.img /tmp/userdata
$ sudo cp -a /tmp/userdata/* /export/root/zedroid/data
$ sudo umount /tmp/userdata
$ sudo echo "hack.installd.for.nfs=1" | sudo tee -a /export/root/zedroid/system/build.prop

The explanation for the last line is from a Linaro engineer.
...when boot via nfs, we need the install usr on nfs server to have the chown permission as it does on android. but that's no easy to do with setting of nfs. so we will make the install to run as root via the
property hack.installd.for.nfs set to 1 when want to boot via nfs
When booting from a flash, /system and /data are separate partitions on the flash.  When booting over NFS, I have to stop mounting /system and /data in fstab.xilinxzynqplatform

/dev/block/mmcblk0p1 /storage/sdcard         vfat    rw wait
#/dev/block/mmcblk0p2 /system         ext4    ro wait
#/dev/block/mmcblk0p3 /data           ext4    rw,noatime,nosuid,nodev wait

This can be automated:

$ sudo sed -i'' -e "s/.*system.*/# &/" -e "s/.*data.*/# &/" /export/root/zedroid/fstab.xilinxzynqplatform

Others pointed out that init.rc remounting / as RO is a problem for NFS, so I comment out that line with sed.  If I do NOT change the file permissions with this sed commands, I get a working shell, but get the "untracked pid" problem.  This suggests that the "untracked pid" problems are due to failure to write to the RO filesystem.

$ sudo sed -i'' -e "s/mount rootfs rootfs \/ ro remount/# &/" -e "s/user shell/user root/" /export/root/zedroid/init.rc

Also, the folders that are already on the rootfs do not need to be created, although /data and /cache ownership needs to change.

$ sudo sed -i'' -e "s/mkdir \/config 0500 root root/# &/" -e "s/mkdir \/system/# &/" -e "s/mkdir \/data 0771 system system/chown system:system \/data/-e "s/mkdir \/cache 0770 system cache/chown system:cache \/cache/"  /export/root/zedroid/init.rc

I explained in previous blog entries how I NFS boot the kernel and the rootfs my zedboard, and since I want to keep using the same kernel even for Android, all I have to change in the kernel bootargs is the nfsroot.  So my bootarg changes to:

zynq-uboot> setenv bootargs 'earlyprintk maxcpus=1 console=ttyPS0,115200 ip=dhcp root=/dev/nfs nfsroot=192.168.1.2:/export/root/zedroid,nfsvers=3 rw init=/init'
zynq-uboot> saveenv

I tried to use NFS version 3 to see if the NFS not responding error will go away (it didn't) so it's not necessary.  The init argument is necessary because Android's init is NOT in one of the places the kernel checks.  With these changes, Android boots, and I get a shell, where I can get su.

...
init: cannot find '/system/bin/debuggerd64', disabling 'debuggerd64'e=vfat)=0
init: cannot find '/system/bin/install-recovery.sh', disabling 'flash_recovery'
binder: 969:969 transaction failed 29189, size 0-0
random: installd urandom read with 105 bits of entropy available
Adding 728060k swap on /dev/block/mmcblk0p4.  Priority:-1 extents:1 across:728060k SS
random: nonblocking pool is initialized
shell@zedboard:/ $ healthd: No charger supplies found
healthd: No battery devices found
nfs: server 192.168.1.2 not responding, still trying

shell@zedboard:/ $ healthd: battery none chg=

It seemed that console hangs after the boot animation starts, so I straced console service by modifying init.rc:

service console /system/xbin/strace -tt -o/data/boot.strace /system/bin/sh

This did not turn up anything that looked like a problem, so I then straced zygote.  While staring at zygote strace, I realized that the last output from art (Android runtime) is the beginning of dex2oat: "GenerateImage...", which preceeds the beginning of dex2oat starting, but there is no further message from dex2oat.  So is dex2oat running at all?  WITH_DEXPREOPT, Android will instead try to relocate the oat file from /system/framework/boot.oat to /data/dalvik-cache/arm/system@framework@boot.art.

This seems to have worked:

$ sudo ls -lh /export/root/zedroid/data/dalvik-cache/arm/
total 40M
-rw-r--r-- 1 root root   0 Feb  7 08:05 system@framework@boot.art
-rw-r--r-- 1 root root 49M Feb  7 08:47 system@framework@boot.oat



Convenience: udev rule for Zedboard's Cypress USB serial connection

By default, the /dev/ttyACMx device enumerated for the Zedboard's Cypress USB serial connection is owned by root, so I always had to run commands that access the device in sudo.  Now that I am trying to run adb, that workaround has gotten tiresome.  So I put created /etc/udev/rules.d/51-android-rules and restarted the udev:

#adb protocol on Zedboard
SUBSYSTEM=="usb", ATTR{idVendor}=="046d", ATTR{idProduct}=="c52b", MODE="0600", OWNER="henry"

I doubt the vendor and product would be different on your system, but if it is, you can just read off the numbers for Cypress from "lsusb" command after connecting the Zedboard to your PC.

APPENDIX: running Android from SD card: has problem

To mount the ramdisk.img created by Android build as initrd file, you have to run mkimage

$ sudo apt-get install u-boot-tools
~/work/zed/android/out/target/product/zedboard$ mkimage -A arm -O linux -T ramdisk -a 0x2000000 -n "Zedboard ramdisk" -d ramdisk.img ramdisk.image.gz
Image Name:   Zedboard ramdisk
Created:      Tue Feb  3 19:21:54 2015
Image Type:   ARM Linux RAMDisk Image (gzip compressed)
Data Size:    610260 Bytes = 595.96 kB = 0.58 MB
Load Address: 02000000
Entry Point:  02000000

And move that to either the SD card, or to the TFTP download folder if you are TFTP downloading the kernel and the ramdisk image.

The matching U-boot sdboot and bootargs environments are are:

u-boot> setenv sdboot 'if mmcinfo; then run uenvboot; echo Copying files over TFTP to RAM && tftpboot 0x2A00000 ${serverip}:${devicetree_image} && tftpboot 0x2000000 ${serverip}:${ramdisk_image} && tftpboot 0x3000000 ${serverip}:${kernel_image} && bootm 0x3000000 0x2000000 0x2A00000; fi'

u-boot> setenv bootargs 'earlyprintk maxcpus=1 console=ttyPS0,115200 ip=dhcp init=/init'

APPENDIX Get cambridgehackers port of Anrdoid 4.1 on Zedboard; still not working

This aosp repository of course knows nothing about Zedboard.  Sven Anderson got pretty close to booting Android 4.1 on Zedboard using the Android support package from cambridgehackers (Jamey Hicks), so I downloaded that repository to figure out what I have to do to add Zedboard target to AOSP (AOSP):

$ mkdir ~/work/zed/cambridge; cd ~/work/zed/cambridge
~/work/zed/cambridge$ repo init -u git://github.com/cambridgehackers/zynq-android4.git -b jb -m default.xml
~/work/zed/cambridge$ repo sync

It would appear that Android is a strictly monotonically increasing distribution, because this download ONLY takes up 21 GB on my disk.  Of all these files, I am only interested in device/xilinx.  Let's copy copy this whole folder to the AOSP tree, and edit as necessary.

~/work/zed/cambridge/device$ cp -r xilinx ../../android/device/
~/work/zed/android/device/xilinx$ rm -rf kernel
~/work/zed/android/device/xilinx$ find . -name .git -exec rm -rf {} \;
~/work/zed/android/device/xilinx$ ls
gralloc  hwcomposer  kernel  zedboard  zedmini

The kernel is an unnecessary folder (I have my own kernel!), so I nuked it.  zedboard and zedmini are the 2 lunch menu options for Zedboard, and gralloc and hwcomposer are shared libraries necessary for display.

Understanding the cambridgehacker build configuration

In the zedmini folder, there are 4 files that describe a build target "zedmini" which will be presented to the lunch build menu.

~/work/zed/android/device$ ls xilinx/zedmini/
AndroidProducts.mk  BoardConfig.mk  vendorsetup.sh  zedmini.mk

All vendorsetup.sh in <AOSP>/device/ folder get pulled into the lunch menu.  I can add more lunch combo for each board type, but I'll live with the options presented by cambridgehacker: zedmini-userdebug and zedboard-userdebug:

~/work/zed/android$ tail -1 device/xilinx/zedmini/vendorsetup.sh 
add_lunch_combo zedmini-userdebug

Since cambridgehacker ran the zedboard product instead of zedmini, he left out the crucial board specific init script from zedmini configuration, so I copied it from the sibling zedboard product:

~/work/zed/android/device/xilinx$ cp zedboard/init.xilinxzynqplatform.rc zedmini/

I think the init script knows to look for a file /init.$systemname.rc, but I don't know how init figures out that my systemname is xilinxzynqplatform (apparently), or where I can change this long-ass name.

This init and fstab file has to get copied to the product output folder, so I added PRODUCT_COPY_FILES at the end of zedmini.mk:

PRODUCT_COPY_FILES := \
   device/xilinx/zedmini/init.xilinxzynqplatform.rc:root/init.xilinxzynqplatform.rc \
   device/xilinx/zedmini/fstab.xilinxzynqplatform:root/fstab.xilinxzynqplatform

Since this a makefile semantics after all, the space in front of the 2 lines must be a  tab!  Note the colon that separates the source and destination, and space separates each src:dest pair.

I don't know what fstab I want for the target yet, so I will just create an empty file for now.

~work/zed/android$ touch device/xilinx/zedmini/fstab.xilinxzynqplatform

Since I want to avoid copying the system and userdata imgs to sdcard, I deleted out the mounting the loop fs imgs.  Please remember this when reading the NFS boot section below.

    #mount ext4 loop@/mnt/sdcard/system.img /system ro
    #mount ext4 loop@/mnt/sdcard/userdata.img /data rw nosuid nodev

As Karim Yagmor talked about in section 4, Architecture of Embedded Android, BoardConfig.mk describes a board, and AndroidProducts.mk or SingleProduct.mk describes the packages I want on the board.

AndroidProducts.mk

Maybe because of the example Karim Yagmor gave in his book and he was an early advocate of Android on embedded, AndroidProducts.mk simply indirects to another makefile in the same folder;

PRODUCT_MAKEFILES := $(LOCAL_DIR)/zedmini.mk

I changed zedmini.mk to pull in the smallest product I could find:

$(call inherit-product, build/target/product/core_minimal.mk)

Make complained when I tried embedded.mk and base.mk, so I went with core_minimal.mk as the smallest possible product.

To begin, I humbly use the default overlays:

DEVICE_PACKAGE_OVERLAYS := device/generic/armv7-a-neon/overlay

To display, this board needs the gralloc, and hwcomposer libraries:

PRODUCT_PACKAGES += gralloc.zynq hwcomposer.zynq

It looks like zedmini build config was not built by cambridgehackers, because I had to fix the extension from zedboard to zynq, to make it compatible with the makefile in the gralloc/ and hwcomposer/ folders.  PRODUCT_NAME will appear in the lunch menu.

PRODUCT_NAME := zedmini

PRODUCT_MODEL is stored in the device's ro.product.model global property, and appear as the "Model number" in the Settings --> "About this phone".

Karim Yagmor says that PRODUCT_BRAND is typically set to Android.

BoardConfig.mk

This makefile is full of unexplained variables.  I can guess why TARGET_NO_BOOTLOADER and TARGET_NO_KERNEL are true for this board, and roughly agree with the values for TARGET_ARCH_VARIANT (armv7-a-neon), TARGET_CPU_ABI (armeabi-v7a), TARGET_CPU_ABI2 (armeabi), TARGET_CPU_SMP (true), and ARCH_ARM_HAVE_TLS_REGISTER (true).  I probably do not want  BUILD_EMULATOR_OPENGL or USE_OPENGL_RENDERER because my Zedboard design just has framebuffer, and no OpenGL HW (a HW design including Xylon IP has it, but I would need to modify the kernel, so I am going to do away with OpenGL for now).

AOSP version 5.0 (lollipop) was complaining about TARGET_ARCH and TARGET_CPU_VARIANT not being defined, so I just added the following line into both zedmini.mk and zedboard.mk

TARGET_ARCH := arm
TARGET_CPU_VARIANT := cortex-a9

I tried putting in the following to see where the kernel and the DTB built with Buildroot (and proven to be booting with the Buildroot rootfs) windup in the Android build tree:

TARGET_PREBUILT_KERNEL := /mnt/work/zed/buildroot/output/images/uImage
DEVICE_TREE_BIN := /mnt/work/zed/buildroot/output/images/zynq-zed-adv7511-spi1.dtb

But I don't see either files in <>/out/target/prodcut/zedboard after the build (see below).  Since I've been booting the Linux kernel on my Zedboard, this is not a big deal--just a little odd.

Build

Before launching the build, increase the ccache size:

henry@Zotac64:~/work/zed/android$ prebuilts/misc/linux-x86/ccache/ccache --max-size=50G
Set cache size limit to 50.0 Gbytes

I am not sure what envsetup does, but it's in the doc.

~/work/zed/android$ source build/envsetup.sh

At first, I want to start with a small distribution: zedmini-userdebug

~/work/zed/android$ lunch zedmini-userdebug

Then I can (try to) build it.  Since there are so many warnings (expected!), pipe the output to bitbucket to see only errors.

~/work/zed/android$ make > /dev/null

Have you heard the term "confirmation bias": tendency to see and hear things that confirm your preconception?  I always felt that Android is bloated and can benefit from cleaning--especially since think that even Linux is bloated.  The Android build process and the time plays into this bias.  After 1 hour, I run into an OpenGL related (remember I don't have the OpenGL HW) error described here. I am trying the following workaround in <>/frameworks/base/core/jni/android/graphics/Paint.cpp:

 29 #include "SkBlurMask.h"
...
810    SkScalar sigma = SkBlurMask::ConvertRadiusToSigma(radius);
811 //android::uirenderer::Blur::convertRadiusToSigma(radius);

After that, the build went on for another 5 hours, and choked here:

Install: out/target/product/zedboard/system/lib/hw/gralloc.default.so
Import includes file: out/target/product/zedboard/obj/SHARED_LIBRARIES/gralloc.zynq_intermediates/import_includes
target thumb C++: gralloc.zynq <= device/xilinx/gralloc/gralloc.cpp
device/xilinx/gralloc/gralloc.cpp:34:21: fatal error: ion/ion.h: No such file or directory
 #include <ion/ion.h>

This is because the repo I picked up from cambridgehacker is Android.mk that does NOT include libion dependency that his xilinx/gralloc is calling for.  So I fixed <>/zed/android/device/xilinx/gralloc/Android.mk:

LOCAL_SHARED_LIBRARIES := liblog libcutils libion
LOCAL_ADDITIONAL_DEPENDENCIES := $(TARGET_OUT_SHARED_LIBRARIES)/libion.so

Next, I hit this error:

In file included from device/xilinx/gralloc/gralloc.cpp:40:0:
device/xilinx/gralloc/gr.h:22:23: fatal error: asm/page.h: No such file or directory
 # include <asm/page.h>

gr.h tries to pull in the Linux PAGE_SIZE if HAVE_ANDROID_OS is defined, which is the equivalent of the WIN #define on Windows (according to this discussion).  So the question is where to get this asm/page.h, which is in <kernel>/arch/arm/include in a Linux kernel.  Cambridgehacker actually included the whole kernel tree under the xilinx folder--which I want to avoid--but even then, I don't understand how he pulled in the header file.  It's doubly strange that the preprocessor is finding other files like pthread.h, stdint.h and limits.h.  I would guess those files are in bionic/libc/include, but page.h is not.  When I poke around in the <>/bionic folder, I see a comment like this "new code should use sysconf(_SC_PAGE_SIZE)", so I tried the following workaround:

 20 #ifdef HAVE_ANDROID_OS      // just want PAGE_SIZE define
 21 //can't find it # include <asm/page.h>
 22 #else
...
 39 inline size_t roundUpToPageSize(size_t x) {
 40    return (x + (sysconf(_SC_PAGE_SIZE)-1)) & ~(sysconf(_SC_PAGE_SIZE)-1);
 41 //(x + (PAGE_SIZE-1)) & ~(PAGE_SIZE-1);
 42 }

The next error is HAL_PIXEL_FORMAT_RGBA_5551 and HAL_PIXEL_FORMAT_RGBA_4444 not being declared in gralloc.cpp.  Since these 2 defines now seem to be gone from <>/system/core/include/system/graphics.h, I just commented them out (and mentally prepare to deal with consequences later):

257        case HAL_PIXEL_FORMAT_RGB_565:
258        //case HAL_PIXEL_FORMAT_RGBA_5551:
259        //case HAL_PIXEL_FORMAT_RGBA_4444:
260            bpp = 2;
261            break;

With this, I move on from gralloc, to hwcomposer.  The next error is in hwcomposer.cpp, the old hwc related types being removed in the latest code.  So I just typedef'ed them early on in the file:

typedef hwc_layer_1_t hwc_layer_t;
typedef hwc_display_contents_1_t hwc_layer_list_t;
typedef hwc_composer_device_1_t hwc_composer_device_t;

The prepare and function signatures changed too, so I modify the code minimally

 78 static int hwc_prepare(hwc_composer_device_t*, size_t nD, hwc_layer_list_t* *list) {
 79     if(nD != 1)//For HWC 1.0, numDisplays will always be one
 80      return EINVAL;
 81     if (list && list[0] && (list[0]->flags & HWC_GEOMETRY_CHANGED)) {
 82     for (size_t i=0 ; i < list[0]->numHwLayers ; i++) {
 83         dump_layer(&list[0]->hwLayers[i]);
 84         if (i > 0)
 85             list[0]->hwLayers[i].compositionType = HWC_OVERLAY;
 86     }
 87 }
...
 91 static int hwc_set(hwc_composer_device_t*, size_t nD,
 92         //hwc_display_t dpy, hwc_surface_t sur,
 93         hwc_layer_list_t* *list)
 94 {
 95     if(nD != 1)//For HWC 1.0, numDisplays will always be one
 96     return EINVAL;//and displays[0] will be non-NULL
 97     if (!eglSwapBuffers((EGLDisplay)list[0]->dpy, (EGLSurface)list[0]->sur)) {

mgrep BUILD_TINY_ANDROID (after sourcing build/envsetup.sh) shows that some makefiles do not build if this environment variable is set, so I give it a try.

$ BUILD_TINY_ANDROID=true make -j 2

But apparently, the tiny android is too tiny it causes some necessary libraries to be NOT built in order?

make: *** No rule to make target `out/target/product/zedboard/obj/SHARED_LIBRARIES/libsysutils_intermediates/export_includes', needed by `out/target/product/zedboard/obj/EXECUTABLES/logd_intermediates/import_includes'.  Stop.

So it's back to the full build.  After a successful build, I have the system, ramdisk, and data images in <>/out/target/product/zedboard/

~/work/zed/android/out/target/product/zedboard$ du -sh
18G    .
~/work/zed/android/out/target/product/zedboard$ ls -oh
total 274M
-rw-rw-r--  1 henry   14 Jan 24 16:16 android-info.txt
drwxrwxr-x  2 henry 4.0K Jan 24 16:17 cache
-rw-r--r--  1 henry 256M Jan 24 16:17 cache.img
-rw-rw-r--  1 henry  60K Jan 24 15:54 clean_steps.mk
drwxrwxr-x  3 henry 4.0K Jan 23 20:20 data
drwxrwxr-x  5 henry 4.0K Jan 24 17:11 gen
-rw-rw-r--  1 henry  35K Jan 24 16:17 installed-files.txt
drwxrwxr-x 14 henry 4.0K Jan 24 16:17 obj
-rw-rw-r--  1 henry   63 Jan 24 15:54 previous_build_config.mk
-rw-rw-r--  1 henry 594K Jan 24 16:17 ramdisk.img
drwxrwxr-x  8 henry 4.0K Jan 23 20:20 root
drwxrwxr-x  5 henry 4.0K Jan 23 20:20 symbols
drwxrwxr-x 12 henry 4.0K Jan 24 16:15 system
-rw-r--r--  1 henry 256M Jan 24 16:17 system.img
-rw-r--r--  1 henry 512M Jan 24 16:17 userdata.img

This is NOT the root; it doesn't even have the init scripts.  The root/ folder is apparently closer to the expected root file system:

~/work/zed/android/out/target/product/zedboard$ ls root/
charger       file_contexts    init.trace.rc     property_contexts  sepolicy          ueventd.rc
data          init             init.usb.rc       sbin               service_contexts
default.prop  init.environ.rc  init.zygote32.rc  seapp_contexts     sys
dev           init.rc          proc              selinux_version    system

The system/ folder above is just a mount point, while system.img is the compressed tarball of the system/ folder right next to the root/ folder shown above (data.img and cache.img look similarly).  The ramdisk.img is actually just a gzipped CPIO archive, as you can see here:

~/work/zed/android/out/target/product/zedboard$ file *.img
cache.img:    Linux rev 1.0 ext4 filesystem data, UUID=57f8f4bc-abf4-655f-bf67-946fc0f9f25b (extents) (large files)
ramdisk.img:  gzip compressed data, from Unix
system.img:   Linux rev 1.0 ext4 filesystem data, UUID=57f8f4bc-abf4-655f-bf67-946fc0f9f25b (extents) (large files)
userdata.img: Linux rev 1.0 ext4 filesystem data, UUID=57f8f4bc-abf4-655f-bf67-946fc0f9f25b (extents) (large files)

If I copy ramdisk.img to /tmp/ramdisk.cpio.gz, gunzip it, and then extract it (with cpio -i -F ramdisk.cpio), the contents are exactly the same as the root/ folder shown above.  So just think of the ramdisk image as THE rootfs the target should boot with.  When booting from SD or eMMC, the other img files are on a separate partition of the boot device, and the init process uncompresses these files to the appropriate mount points at the root file system.  During development, I want to bypass having to write the images to the flash device, and just export the rootfs that contains the full system and userdata images.

But the target exhibits the similar problem that thwarted Sven Anderson.

fs_mgr: Cannot open file /fstab.xilinxzynqplatform
shell@zedboard:/ # init: untracked pid 5875 exited with status 3
init: untracked pid 6057 killed by signal 9
...

Apparently, the "init: untracked pid" is a commonly encountered problem when something within the framework or the device driver goes wrong.  But as a silver lining, since I can read and write files into the root directory, I don't think I need the file /fstab.xilinxzynqplatform.  I tentatively conclude that the target can successfully boot from NFS, and move onto debugging the "init: untracked pid" problem.

init: untracked pid

I checked logcat for a clue to the problem.  There were many lines of "W/dex2oat ..." which is just the JIT compiler, and not of interest.  So I filtered it out:

$ sed -i'' "/^W\/dex2oat .*$/d" logcat.txt

There seems to be many problems, which I should tackle one by one--starting with the surface flinger problem, which seems to be the most serious.

Vold can't find expected files

--------- beginning of system
I/Vold    (  970): Vold 2.1 (the revenge) firing up
E/Vold    (  970): failed to open /fstab.xilinxzynqplatform
E/Vold    (  970): Error reading configuration (No such file or directory)... continuing anyways

Networking initialization


--------- beginning of main
I/Netd    (18971): Netd 1.0 starting
E/Netd    (18971): Failed to open /proc/sys/net/ipv6/conf/default/accept_ra: No such file or directory
E/InterfaceController(18971): Can't list /proc/sys/net/ipv6/conf: No such file or directory
E/Netd    (18971): Failed to open /proc/sys/net/ipv6/conf/default/accept_ra_rt_table: No such file or directory
E/InterfaceController(18971): Can't list /proc/sys/net/ipv6/conf: No such file or directory

I/iptables(18971): iptables terminated by exit(3)
E/Netd    (18971): exec() res=0, status=768 for /system/bin/iptables -t filter -N bw_INPUT


Surface flinger crash

I/SurfaceFlinger(18949): SurfaceFlinger is starting
I/SurfaceFlinger(18949): SurfaceFlinger's main thread ready to run. Initializing graphics H/W...
F/libEGL  (18949): couldn't find an OpenGL ES implementation
F/libc    (18949): Fatal signal 6 (SIGABRT), code -6 in tid 18949 (surfaceflinger)

It would appear that the root cause is that the board does not have a HW OpenGL ES implementation.  Let's explore how to work around this limitation by staring at the source code:

~/work/zed/android$ lunch source build/envsetup.sh
~/work/zed/android$ lunch zedmini-userdebug
~/work/zed/android$ cgrep "couldn't find an OpenGL ES implementation"
./frameworks/native/opengl/libs/EGL/Loader.cpp:188:    LOG_ALWAYS_FATAL_IF(!hnd, "couldn't find an OpenGL ES implementation");

I KNOW my Zedboard HW does NOT have OpenGL HW.  What I would like is to enable as much of the Android features using software OpenGL, so I started reading on the subject.  Linaro pulled it off for ICS (Android 4.0), so maybe it's still possible.

https://wiki.linaro.org/Platform/Android/ICSwithSoftwareGL


Instead of grepping my way through the vast Android framework code base, I want to debug in Eclipse, following the guidelines in this Intel post

No trace file

E/cutils-trace(20556): Error opening trace file: No such file or directory (2)

Audio flinger died, but why isn't this fatal?

I/ServiceManager(  969): service 'media.audio_flinger' died