Blog

10/05/2016 - 10:36

Chris Simmonds has been working on ports of Android to the BeagleBone Black for several years, since he posted the first tutorial on running JellyBean 4.3.

Now all of that work has been consolidated into the Android4Beagle project. Android4Beagle aims to provide a vanilla Android build, based on AOSP. Currently, builds are available for KitKat, Lollipop and Marshmallow, with Nougat in the works.

10/05/2016 - 10:20

Chris Simmonds will be at the at OpenIoT Summit and Embedded Linux Conference Europe 2016. This year he will be giving two presentations:

He will be posting links to the presentations just as soon as he has finished writing them. Hope to see you there!

03/22/2016 - 11:07

Brillo (https://developers.google.com/brillo/) is Google's operating system for devices that are connected to the IoT. They communicate with each other, with the cloud and with mobile apps using a system called Weave (https://developers.google.com/weave/). Brillo and Weave are still under wraps: you have to request an invite from the two links in order to get access to documentation, sample code, and so on. However, there is enough information publicly available to build and test a device running Brillo, which is what this blog is about. I hope to cover Weave in a later post.

Brillo is actually a cut-down version of Android. Basically, all the Java components have been stripped away leaving a much simpler embedded Linux operating system. When building Brillo, some things pop out immediately, which may give a preview of future Android builds:

  • GNU make is out: the build is run by kati/ninja (same for Android N preview)
  • GCC is out: almost all C/C++ components are compiled using clang (same for Android N preview)
  • Linux kernel source is in: the AOSP tree has vendor kernels in hardware/bsp/kernel. The kernel is built using GCC, as it is not (yet) possible to build it with clang
  • DBUS is in: I have not yet found out why
  • Toybox is in: leading to a much more Linux-like command line experience

Below, I show how to build and run the Brillo emulator

Setting up the build system

This is basically the same as building Android from AOSP: the instructions are here http://source.android.com/source/initializing.html. I used a fairly old octocore AMD machine with 16 GiB RAM running Ubuntu 14.04.4 64-bit desktop. Note that although Brillo targets do not contain any Java code, the build fails at the very beginning if you don't have OpenJDK 1.7 installed.

Getting the code

The Brillo code was pushed to AOSP in November 2015. I will start by syncing the master branch:

Allow a while for that to complete because it has 34 GiB to download.

Building the emulator

The procedure is basically the same as for any AOSP build:

$ . build/envsetup.sh
$ lunch

Select brilloemulator_x86-eng (or, run lunch brilloemulator_x86-eng). Then build it using make, giving the number of CPU cores on the build machine as the -j parameter:

$ make -j8

The first thing you notice is this:

Running kati to generate build-brilloemulator_x86.ninja...

Kati is a GNU make clone which converts the many thousands of makefile snippets in an Android build into a single, huge, ninja file:

$ ls -lh out/build-brilloemulator_x86.ninja 
-rw-rw-r-- 1 chris chris 145M Mar 21 15:27 out/build-brilloemulator_x86.ninja

The main goal, apparently, is to speed-up incremental build of Android. There is some info in the README.md file at https://github.com/google/kati. To speed up incremental builds, and make them more robust, kati writes the timestamps of all the files and directories to a file, so that it only has to re-read the makefiles if something has changed:

$ ls -lh out/.kati_stamp-brilloemulator_x86 
-rw-rw-r-- 1 chris chris 12M Mar 21 15:27 out/.kati_stamp-brilloemulator_x86 

The ninja file is processed by Ninja, which is a simple build system that builds according to the rules in the input file. See https://ninja-build.org/

One nice touch is that when the build gets going, you see a nice progress indicator:

[ 44% 7550/16800] target .......................... 

Towards the end, it builds a kernel:

[ 95% 15960/16800] Building i386 4.4 kernel... 

This is a big deal. This step is optional, in that you can set up the device build files to copy a prebuilt kernel binary as with “old” AOSP builds, but the clear intention is that the kernel source is part of the archive. In hardware/bsp/kernel there are kernels for freescale, imagination, intel, marvell qcom, and rockchip. I just can't exaggerate how pleased I am about this.

Finally, you should see this message :

#### make completed successfully (34:37 (mm:ss)) #### 

The build time is quite a lot shorter than for contemporary Android builds, mostly because there is less to build, but also because of the new build system.

Running the emulator

The emulator a version of QEMU. You start it like this (assuming that you have previously sourced build/envsetup.sh and selected the target via the lunch command):

$ brilloemulator-x86

Before I go on, note that quitting the emulator is, maybe, not obvious. Remember that it is just a copy of QEMU that was started without a graphics screen (-nographic). So, to quit you type Ctrl-A X. That is, you press the Ctrl and A keys together, let go, and then press the X key, and you will see:

QEMU: Terminated 

Using Brillo at the command line feels much more Linux-y than earlier versions of Android, courtesy of Toybox (http://www.landley.net/toybox/). Toybox largely replaces the earlier command line tool called Toolbox. Now, commands such as “find”, “which”, and “uname” all work as on regular Linux. Even “ifconfig” works as it should, replacing the oddly crippled version in Toolbox. The shell is still the BSD Korn shell, but a later version. Both adb and logcat work as expected.

The basic directory layout is the same as Android: the init program and init*.rc scripts are in the root, which is an initramfs (ramdisk). The main system files are stored in the read-only system directory, which is much cut-down from Android:

# ls -p /system
bin/ build.prop etc/ lib/ usr/ xbin/

Run-time data storage is in /data, as normal. In here you find:

# ls -p /data
adb/      app-private/  data/       mediadrm/        resource-cache/
anr/      backup/       drm/        misc/            ss/
app/      bootchart/    local/      nativebenchmark/ system/
app-asec/ bugreports    lost+found/ nativetest/      tombstones/ 
app-lib/  dalvik-cache/ media/      property/        user/

There are some Dalvik related directories which I take to be atavistic vestiges from Android, but I could be missing something here, who knows?

Finally, this is the list of processes (with kernel threads removed for brevity):

# ps 
USER      PID   PPID  VSIZE  RSS   WCHAN            PC  NAME 
root      1     0     7820   1820           0 08143195 S /init 
[...]
root      981   1     3548   1476           0 0812f640 S /sbin/ueventd 
[...]
logd      1254  1     12304  2972           0 b75b1df1 S /system/bin/logd 
dbus      1257  1     6124   3204           0 b738fbd0 S /system/bin/dbus-daemon 
system    1258  1     6400   2024           0 b755bad6 S /system/bin/servicemanager 
shell     1261  1     4864   1720           0 b74bcdf1 S /system/bin/sh 
root      1262  1     7548   1024           0 0811d050 S /sbin/adbd 
keystore  1264  1     9384   4164           0 b714aad6 S /system/bin/keystore 
media     1265  1     32144  11788          0 b70d9ad6 S /system/bin/mediaserver 
system    1266  1     9104   4084           0 b730b8d5 S /system/bin/nativepowerman 
root      1267  1     9208   3860           0 b75498d5 S /system/bin/peripheralman 
root      1268  1     11280  4236           0 b7325ad6 S /system/bin/sensorservice 
wifi      1269  1     10900  4380           0 b7347c55 S /system/bin/wpa_supplicant 
audioserver 1270  1     18608  8568           0 b6af28d5 S /system/bin/brilloaudioservice 
root      1272  1     4864   2432           0 b744fc55 S /system/bin/sh 
metrics_coll 1273  1     11840  5772           0 b70ff8d5 S /system/bin/metrics_collector 
metricsd  1274  1     12804  5808           0 b74ec8d5 S /system/bin/metricsd 
root      1275  1     5408   1828           0 b74d9da1 S /system/xbin/perfprofd 
trunks    1277  1     13268  5112           0 b70938d5 S /system/bin/trunksd 
root      1278  1     15048  7852           0 b71f58d5 S /system/bin/update_engine 
webserv   1280  1     12848  6968           0 b71bf8d5 S /system/bin/webservd 
root      1300  1     13640  8760           0 b72c18d5 S /system/bin/shill 
firewall  1328  1     10524  6628           0 b73aa8d5 S /system/bin/firewalld 
dhcp      1340  1300  6208   1900           0 b75c58d5 S /system/bin/dhcpcd-6.8.2 
system    1342  1     6408   2100           0 b7353bd0 S avahi-daemon: running [linux.local] 
tlsdate   1343  1     6836   3584           0 b72b98d5 S /system/bin/tlsdated 
system    1344  1     16740  8888           0 b6e9b8d5 S /system/bin/weaved 
root      1345  1343  6708   368            0 b72bafa6 S /system/bin/tlsdated 
system    1347  1300  5172   1756           0 b7572c55 S /system/bin/dnsmasq 
root      1352  1261  4864   2476           0 b7580df1 S /system/bin/sh 
root      1370  1352  6208   2268           0 b7538fa6 R ps

Among the daemons you can see running, many are to do with network connectivity: wpa_supplicant, shill, firewalld, dhcpcd-6.8.2, avahi-daemon and dnsmasq. Then there is the Weave protocol manager, weaved, and a web server, webservd. Some components are obviously using binder to communicate: servicemanager and sensorservice, for example. And there is dbus-daemon...

Plainly there is still a lot to learn here. I will be following up with more blogs as time goes by.

02/23/2016 - 11:13

The story of how Linux grew to become a world-class embedded operating system is a fascinating tail of individual endeavour and collective cooperation. See the slides and accompanying paper from Chirs Simmonds' presentation at Embedded World 2016 for the full monty

Slides: http://2net.co.uk/slides/ew2016-embedded-linux-timeline-slides.pdf
Paper: http://2net.co.uk/slides/ew2016-embedded-linux-timeline-paper.pdf

02/23/2016 - 11:07

Writing device drivers to control new hardware can be hard work. Chris Simmonds, speaking at Embedded World 2016, explains how to take the easy road by writing userspace drivers.

Slides: http://2net.co.uk/slides/ew2016-userspace-drivers-slides.pdf
Paper: http://2net.co.uk/slides/ew2016-userspace-drivers-paper.pdf
Sample code: http://2net.co.uk/downloads/ew2016-demos.tar.gz

08/14/2015 - 17:46

One of the fundamental questions programmers ask (or at least, they should) is: how much memory is my program using? It may be a simple question, but with a virtual memory operating system like Linux the answer is quite complex. The numbers given by top and ps don't really add up. Procrank is a tool commonly used by Android platform developers to give more accurate answers, but there is no reason why it can't be more widely used in other Linux based operating systems and it is especially useful for embedded Linux.

The code

You can get the code from Github: https://github.com/csimmonds/procrank_linux.git

There are instructions about building and usage in the README

The theory

The two most common metrics for the memory usage of a process are the virtual set size, Vss, and the resident set size, Rss: you will see see these numbers in ps and top.

Vss, also called VIRT and VSZ is the total amount of virtual memory of the process has mapped, regardless of whether it has been committed to physical memory

Rss, also called RES and RSS, is the amount of physical memory being mapped

The Vss is plainly an overestimate because applications commonly allocate memory they never use. Rss is a better measure, but still an overestimate because it does not take into account pages of memory that are shared between processes. For example, there is only one copy of the C library resident in memory because it is shared between all the processes that link with it yet Rss accounts for it multiple times.

Some years ago, Matt Mackall looked at the problem and added two new metrics called the Unique Set Size, Uss, and the Proportional Set Size, Pss, and modified the kernel to expose the information needed to calculate them, which you will find in /proc/[PID]/smaps.

Uss is unique set size, which is the amount of memory that is private to the process and is not shared with any other

Pss is the proportional set size, which is the amount of memory shared with other processes, divided by the number of processes sharing each page

To over simplify slightly, the diagram below shows three processes and the pages each has mapped into its virtual address space. The pages have been marked as being of type A, B or C where:

  • A = private memory that is mapped to physical pages of RAM. This would include the parts of the stack and heap that are being actively used
  • B = shared memory that is mapped and is shared by one or more other processes, e.g. code in shared libraries
  • C = memory that has been allocated but never touched

And so for each process:

  • Vss = A + B + C
  • Rss = A + B
  • Uss = A
  • Pss = A + B/n where n is the number of processes sharing


Calculating the Pss for the three processes gives:

Pss(1) = 2 + 3/3 + 2/2 = 4
Pss(2) = 2 + 3/3 + 2/2 = 4
Pss(3) = 2 + 3/3 = 3
Sum(Pss) = 11 = total of pages in use

As you can see, Pss gives an accurate measure of the memory a process is using, taking into account sharing between processes. The total amount of memory in use by all processes is the sum or their Pss.

The Uss is also useful because it shows the pages that are unique. You can think of it as the price you would pay in memory if you forked that process to create a copy.

There is a readily available program that shows Uss and Pss called smem, developed by Matt Mackall. The only problem with it is that it requires a Python run-time environment, which is not often available on an embedded Linux device. The Android developers encountered this problem and they wrote procrank as a command-line tool written in C, using the Android BIONIC C library. I have taken that code, made a few minor changes and added a Makefile so it will compile on most GNU/Linux environments, including cross compiling for embedded use.

06/20/2015 - 22:45

At last, here is Android Lollipop for BeagleBone Black!

Screenshot of BeagleBone running 5.1 Lollipop

This is a "work in progress" so don't expect everything to go smoothly. I have tested this build on a BBB rev A (2 GiB internal eMMC) and a LCD4 cape. Here are some issues that I have found up to now (please report any other odd behaviour you find):

1. The graphics are not accelerated and the screen flickers whenever it is updated
2. The initial boot time is long, expect to wait several minutes
3. The buttons on the LCD4 cape do not work
4. The Ethernet interface is not configured
5. The Linux 3.2 kernel is unreliable if built with the gcc 4.8 toolchain that comes with AOSP 5.x

For those of you who want to build from source, the device configuration files and information about building are at https://github.com/csimmonds/bbb-android-device-files/tree/lollipop-5.1

I have also uploaded a pre-built micro SD card image, which you can get from http://2net.co.uk/downloads/bbb-android/BBB-aosp-5.1.0-sd-img-2015-06-29.zip".

To write it to microSD, plug card of at least 2 GiB capacity into your card reader: it will show up as something like /dev/mmcblk0 or /dev/sdc. Make absolutely sure that you know which it is before continuing because hard drives also show up as /dev/sd* and writing this image to your hard drive will make your computer unbootable!. Assuming that the card reader is mmcblk0, write the image using a command like this:

$ sudo sh -c "unzip -p BBB-aosp-4.4.4_r1-sd-img.zip | dd of=/dev/mmcblk0 bs=4M"

Plug it into your BeagleBone Black and boot it up.

10/05/2014 - 02:55

Once you have ported AOSP to your platform, an obvious next step is to install some apps: maybe Gmail or Angry Birds. Ideally, you would want Google Play Store so that you can select apps from the 100,000's available. But, there is a problem. Play Store, like most of the apps on Play Store, requires Google Mobile Services (GMS) to work. GMS extends the Android framework by adding the libraries, configuration files and applications required to support the extended Google APIs that most developers know simply as Google Services. Most of these components are in the system partition so either they have to be included as part of the base AOSP build or installed as root afterwards. There is also a licensing issue: the components that make up GMS and applications like Gmail, Google Maps and Google Now are proprietary to Google and require a license.

Nevertheless, you can try out GMS and get access to the Google experience. You could extract the necessary components from a running (licensed) Android handset, or from the Nexus factory images. Or you can install one of the community-maintained gapps packages. Below, I am using gapps from http://goo.im/gapps.

To install gapps on a normal handset you would install a recovery manager, such as ClockWorkMod ROM manager, boot into recovery and use it to load the zip file. There isn't a version of CWM for BeagleBone (yet) but the following method achieves the same effect by using an adb root shell to issue the commands by hand.

Installing gapps

This only works if you have my current BeagleBone Black Android 4.4 KitKat release installed in internal flash or microSD card.

Get gapps for KitKat/4.4 from http://goo.im/gapps. Then

$ adb push gapps-kk-20140105-signed.zip /sdcard/Download
$ adb remount

In an adb shell, issue these commands on the BeagleBone:

# mkdir /system/addon.d
# mount -o remount,rw /
# mkdir /tmp
# updater 1 1 /sdcard/Download/gapps-kk-20140105-signed.zip

The script takes a couple of minutes to run. You can ignore messages like

about to run program [/sbin/busybox] with 3 args
run_program: execv failed: No such file or directory
run_program: child exited with status 1

Then reboot, and you will see Google Play and Gmail apps are installed. You can use Play to install any others you need.

BeagleBone with Gapps

What is updater?

The Android updater command reads from a zip file which contains a script and the files to install. It takes three arguments

  • The updater binary API to use, 1, 2, or 3. Usually you want 1
  • A file descriptor to write commands to. Use '1' for standard output
  • The path name of the zip file

The zip file must contain the install script in

META-INF/com/google/android/updater-script

The script is written in "edify", the basic syntax of which is described in the AOSP directory bootable/recovery/edify/README

The updater command also understands install scripts written in an older format called "amend". In this case the script file must be named "update-script" (drop the 'r' from updater):

META-INF/com/google/android/update-script

09/15/2014 - 19:34

I have updated the internal eMMC flash and sdcard images for BeagleBone Black. Most changes are to make U-Boot work better with fastboot, especially to make it possible to enter fastboot without having to type "fastboot" at a U-Boot prompt and so avoid the need to have a serial cable. Also, I have increased the sizes of the system and userdata partitions so that you can install more apps. I am still using Android KitKat 4.4.4 and TI Linux 3.2 kernel with SGX accelerated graphics libraries.

Improvements to eMMc

  • Added sparse image format to U-Boot, see http://2net.co.uk/tutorial/android-sparse-image-format for a detailed description
  • Made U-Boot default to fastboot if autoboot fails
  • Turn on user LED 0 when in fastboot mode
  • Added code to Linux to make "adb reboot bootloader" work
  • Increased system partition from 256 MiB to 512 MiB
  • Increased userdata partition from 256 MiB to 1047 MiB

Improvements for SD card

  • Increased system partition from 256 MiB to 512 MiB
  • Increased userdata partition from 256 MiB to 2560 MiB

Installing Android on internal eMMC flash

You will need

  • A BeagelBone Black rev A/B/C
  • A micro SD card of any capacity since you are only going to use the first 70 MiB to write a small flasher image
  • The mini USB to USB A cable supplied with the BeagleBone
  • A 5V power supply because the current used when writing to the eMMC chip may exceed that supplied by a typical USB port. See this page for examples: http://elinux.org/Beagleboard:BeagleBone_Black_Accessories.
1. Get http://2net.co.uk/downloads/bbb-android/BBB-aosp-4.4.4_r1-emmc-2014-09-12.zip and unzip it
(If you want to build from scratch, follow the instructions in README.md at https://github.com/csimmonds/bbb-android-device-files/tree/kk4.4-fastboot)
2. Plug the microSD card into your card reader: it will show up as something like /dev/mmcblk0 or /dev/sdc. Make absolutely sure that you know which it is before continuing because hard drives also show up as /dev/sd* and writing this image to your hard drive will make your computer unbootable!. Unmount all partitions that have been automounted on the card. Next, assuming that the card reader is mmcblk0, write the image using a command like this:
$ sudo sh -c "unzip -p u-boot-bbb-fb-2014-09-12.img.zip | dd of=/dev/mmcblk0 bs=1M"

3. With no power on the BeagleBone, insert the microSD card
4. BeagleBone Black in fastboot modePress and hold the 'Boot button' on the BeagleBone, power up the board using the external 5V power connector and release the button after the fastboot LED lights up
5. Plug in the USB cable between the mini USB port on the BeagleBone and the PC. Then, using the fastboot command from the Android SDK or an AOSP build, check that the BeagleBone has been detected by typing (on the PC)
$ fastboot devices
90:59:af:5e:94:81	fastboot

6. If instead you see
$ fastboot devices
no permissions	fastboot

Add this line to /etc/udev/rules.d/51-android.rules

SUBSYSTEM =="usb", ATTRS{idVendor}=="0451", ATTRS{idProduct}=="d022" , MODE="0666"

Then unplug the mini USB cable and plug it back in again. Check that the permissions problem has gone away.

7. Use fastboot to format the eMMC chip and then flash the images
$ fastboot oem format
$ fastboot flash spl MLO
$ fastboot flash bootloader u-boot.img
$ fastboot flash boot boot.img
$ fastboot flash system system.img
$ fastboot flash userdata userdata.img
$ fastboot flash cache cache.img

8. Power off the board and remove the SD card
9. Power on again. Your BeagleBone will boot into Android!

Installing Android on sdcard

You will need

  • A BeagelBone Black rev A/B/C
  • A micro SD card of at least 4 GiB
  • The mini USB to USB A cable supplied with the BeagleBone
1. Get the pre-built image from http://2net.co.uk/downloads/bbb-android/BBB-aosp-4.4.4_r1-sd-img-2014-09-12.zip
(If you want to build from scratch, follow the instructions in README.md at https://github.com/csimmonds/bbb-android-device-files/tree/kk4.4-sdcard)
2. Plug the SD card into your card reader: it will show up as something like /dev/mmcblk0 or /dev/sdc. Make absolutely sure that you know which it is before continuing because hard drives also show up as /dev/sd* and writing this image to your hard drive will make your computer unbootable!. Assuming that the card reader is mmcblk0, write the image using a command like this:
$ sudo sh -c "unzip -p BBB-aosp-4.4.4_r1-sd-img-2014-09-12.zip | dd of=/dev/mmcblk0 bs=4M"

3. With no power on the BeagleBone, insert the microSD card
4. Press and hold the 'Boot button' while powering up by plugging in the mini USB cable. After a minute or so it should boot into Android
09/02/2014 - 14:24

Fastboot

Many Android bootloaders implement the fastboot protocol for loading and flashing images to internal memory (there is some background information about how Android boots and boot image formats in these slides: http://www.slideshare.net/chrissimmonds/android-bootslides20). Fastboot is a simple USB protocol using ASCII text strings for commands and responses. In recent versions of the AOSP you can find the specification in system/core/fastboot/fastboot_protocol.txt.

As an example, this is the interchange when using fastboot to write the recovery image using the command "fastboot flash recovery"

Host->Client "download:004ba00"
Client: "DATA004ba000"
Host: Sends 0x4ba000 (4956160) bytes of raw data
Client:"OKAY"
Host: "flash:recovery"
Client:"OKAY"

You can see this yourself using Wireshark or tcpdump to capture the USB interchange.

Note that there are two stages: first the image is downloaded to the device and then the command "flash" is sent to ask the device to program the data into internal memory. In all bootloader implementations I have seen the image data is buffered in RAM during the download stage and then written out to memory in the flash stage. This means that the image must fit into RAM, which a problem for the system, userdata and cache file system images which are often several times larger than the total amount of RAM. However, these file system images are usually not full, especially in the case of userdata.img which contains very little data initially.

Sparse image format

To make the images smaller, and to reduce transfer time, Android generates system.img, userdata.img and cache.img in sparse format. The image is split into chunks of multiples of 4096 bytes. Any chunks that contain no useful data are marked as "Don't care" and no data is sent.

The format is defined in system/core/libsparse/sparse_format.h and looks like this:

The image begins with a sparse_header of 28 bytes, which contains

magic: the number 0xed26ff3a
blk_sz: number of bytes in a block, always 4096
total_blks: number of blocks in the un-sparse file
total_chunks: number of chunks

Each chunk begins with a 12 byte chunk_header, which contains
chunk_type: see below
chunk_sz: number of blocks

There are three chunk types.
CHUNK_TYPE_RAW, followed by chunk_sz blocks of raw data
CHUNK_TYPE_DONT_CARE
CHUNK_TYPE_FILL, followed by 4 bytes of fill data

The last type, CHUNK_TYPE_FILL, fills the chunk with the 4 byte value. I have never seen it used in images produced by a normal AOSP build.

The code for all this is in system/core/libsparse, together with a tool to analyse sparse images: simg_dump.py. Here is an example:

$ system/core/libsparse/simg_dump.py -v out/target/product/manta/cache.img 
out/target/product/manta/cache.img: Total of 135168 4096-byte output blocks in 24 input chunks.
            input_bytes      output_blocks
chunk    offset     number  offset  number
   1         40       4096       0       1 Raw data
   2       4148       4096       1       1 Raw data
   3       8256     159744       2      39 Raw data
   4     168012       8192      41       2 Raw data
   5     176216    1732608      43     423 Raw data
   6    1908836    8650752     466    2112 Raw data
   7   10559600       4096    2578       1 Raw data
   8   10563708       4096    2579       1 Raw data
   9   10567816       4096    2580       1 Raw data
  10   10571924          0    2581   30187 Don't care
  11   10571936       4096   32768       1 Raw data
  12   10576044       4096   32769       1 Raw data
  13   10580152          0   32770      39 Don't care
  14   10580164       8192   32809       2 Raw data
  15   10588368          0   32811   32725 Don't care
  16   10588380       8192   65536       2 Raw data
  17   10596584          0   65538   32766 Don't care
  18   10596596       4096   98304       1 Raw data
  19   10600704       4096   98305       1 Raw data
  20   10604812          0   98306      39 Don't care
  21   10604824       8192   98345       2 Raw data
  22   10613028          0   98347   32725 Don't care
  23   10613040       8192  131072       2 Raw data
  24   10621244          0  131074    4094 Don't care
       10621244             135168         End

The sparse cache.img is 10621244 bytes (about 10 MiB), but the expanded image is 135168 blocks of 4096, which equals 553648128 bytes (528 MiB), so the sparse file is 1.9% of the size of the full image. Quite a useful saving.

You can tell the AOSP build not to create sparse images by adding this line to your BoardConfig.mk:

TARGET_USERIMAGES_SPARSE_EXT_DISABLED := true


Sparse images and Android for the BeagleBone Black

I have added support for sparse images to my U-Boot for BeagleBone Black and removed TARGET_USERIMAGES_SPARSE_EXT_DISABLED from the Android device configuration. Now it takes about 2 minutes to flash the system, userdata and cache images whereas before it used to take 5 minutes.

Want to know more about Android?

I have two training courses that will help you:
Android porting: http://www.2net.co.uk/training/android-porting
Android Internals: http://2net.co.uk/training/android-internals