1 2 Previous Next

Android Community

24 posts

The Android team in ARM was lucky enough to be invited to a Linux Plumbers mini-conf to talk about AArch64, porting from 32-bit to 64-bit and our experiences in working on Binder (a key Android feature which relies upon support in the Linux kernel).


Attached to this post are the raw PDFs (no video this time).


First an introduction to the AArch64 ISA (from the lead engineer on our Javascript porting work), next a presentation of porting between AArch32 and AArch64 code (from an engineer who did a lot of work on adding AArch64 support to Skia, a key rendering library in Android). Finally a presentation on the changes to the Binder kernel driver needed to support 64-bit user space code, from the engineer who did that and a lot of the initial bionic porting to 64-bit for Android.


As an added bonus, I've attached the original slides for the 'From Zero to Boot' talk at Linaro, which are missing from the Linaro page on the talk.

Stephen Kyle

The ART of Fuzz Testing

Posted by Stephen Kyle Nov 26, 2014

In the newest version of Android, Lollipop (5.0), the virtual machine (VM) implementation has changed from Dalvik to ART. Like most VMs, ART has an interpreter for executing the bytecode of an application, but also uses an ahead-of-time (AOT) compiler to generate native code. This compilation takes place for the majority of Java methods in an app, when the app is initially installed. The old VM, Dalvik, only produced native code from bytecode as the app was executed, a process called just-in-time (JIT) compilation.


ART currently provides a single compiler for this AOT compilation, called the quick compiler. This backend is relatively simple for a compiler, using a 1:1 mapping from most bytecodes to set sequences of machine instructions, performing a few basic optimisations on top of this. More backends are in various stages of development, such as the portable backend and the optimizing backend. As the complexity of a backend increases, so too does its potential to introduce subtle bugs into the execution of bytecode. In the rest of this post, we will use the term "backend" to refer to the different ways in which code can be executed by ART, be it the interpreter, the quick compiler, or the optimizing compiler, and the term "quick compiler" and "quick backend" should be considered equivalent.


In this post we will consider how we can check that we aren't introducing new bugs as these backends are developed.


A test suite is useful, but is limited in size, and may only test for regressions of bugs the developers have found in the past. Some errors in the VM may not have been detected yet, and there are always rare cases arising from unexpected code sequences. While some bugs may just cause the compiler to crash, or create a program that produces slightly incorrect output, other bugs can be more malicious. Many of these bugs lurk at the fringes of what we would consider "normal" program behaviour, leaving open potential for exploits that use these fringe behaviours, leading to potential security issues.


How do we find these bugs? Fuzz testing (also commonly known as "fuzzing") can allow us to test a greater range of programs. Fuzz testing generally refers to random generation of input to stress test the capabilities of a program or API, particularly to see how it can handle erroneous input. In this case, we generate random programs to see how the backends of ART deal with verifying, compiling and executing them.  Before we discuss our fuzz testing strategy in more detail, let's look at how apps are executed in Android.


From Java code to execution on your Android device


Let's take a look at a simple Java method, and watch how this code is transformed into a sequence of A64 instructions.


public int doSomething(int a, int b) {
  if (a > b) {
    return (a * 2);
  return (a + b);


In Android software development, all Java source files are first compiled to Java bytecode, using the standard javac tool. The Java bytecode format (JVM bytecode) used by Java VMs is not the same as the bytecode used in ART, however. The dx tool is used to translate from JVM bytecode to the executable bytecode used by ART, which is called DEX (Dalvik EXecutable, a holdover from when the VM was called Dalvik.) The DEX code for this Java code looks like:


0000: if-le v2, v3, 0005
0002: mul-int/lit8 v0, v2, #int 2
0004: return v0
0005: add-int v0, v2, v3
0007: goto 0004


In this case, the virtual registers v2 and v3 are the method's parameters, a and b, respectively. For a good reference on DEX bytecode, you can consult this document, but essentially this code compares a to b, and if a is less-than-or-equal-to b it adds a to b and returns that result. Otherwise, it multiplies a by 2 and returns that.


When ART loads this code, it typically compiles the bytecode using the quick backend. This compilation will produce a function that roughly follows the ARM Architecture Procedure Call Standard (AAPCS) used with A64 code - it will expect to find its arguments in r2 and r3*, and will return the correct result in r0. Here is the A64 code that the quick backend will produce, with some simplifications:


  // Reminder: w2 is the 32-bit view of register r2 in A64 code!
  [-- omitted saving of registers w20-w22 to the stack --]
  mov w21, w2
  mov w22, w3
  cmp w21, w22
  b.le doAdd
  lsl w20, w21, #1  // (NB: this is w21 * 2)
  mov w0, w20
  [-- omitted loading of registers w20-w22 from the stack --]
  add w20, w21, w22
  b doLeave


*(Why not r0 and r1? Because r0 is reserved for passing the context of the method that is currently being executed. r1 is used for the implicit first argument of any non-static method - the reference to the this object.)


Before code can be compiled or executed by any backend, the bytecode must always be verified.  Verification involves checking various properties of the bytecode to ensure it is safe to execute. For example, checking that the inputs to a mul-float bytecode are actually float values, or checking that a particular method can be executed from the class we are currently executing within. Many of these properties are checked when the program is compiled from Java source to DEX bytecode, resulting in compiler errors. However, it is important to perform full bytecode verification when apps are about to be executed, to defend against security exploits that target DEX manipulation.


Once verification has taken place at run time, ART will load the arguments for the method into the correct registers, and then jump straight to the native code. Alternatively, ART could use its interpreter to interpret the input DEX bytecode as Dalvik would traditionally have done before attempting JIT compilation. Any bytecode that is executed as native code should do the exact same thing when it is executed in the interpreter. This means that methods should return the same results and produce the same side-effects. We can use these requirements to test for flaws in the various backend implementations. We expect that any code that passes the initial verification should be compilable, and some aspects of compilation will actually rely on properties of the code that verification has proven. Contracts exist between the different stages of the VM, and we would like to be assured that there are no gaps between these contracts.


Fuzz testing


We have developed a fuzz tester for ART, that uses mutation-based fuzzing to create new test cases from already written Java programs. ART comes with an extensive test suite for testing the correctness of the VM, but with a mutation-based fuzz tester, we can use these provided tests as a base from which we can investigate more corner cases of the VM.


The majority of these test programs produce some kind of console output - or at the very least, output any encountered VM errors to the console. The test suite knows exactly what output each test should produce, so it runs the test, and confirms that the output has not changed. Mutation-based fuzzing means that we take a test program, and modify it slightly - this means that the output of the program may have changed, or the program may now produce an error. Since we no longer know what output to expect, we can instead use the fact that ART has multiple backends to verify that they all execute this program the same way. Note however that this approach is not foolproof, as it may be the case that all of the backends execute the program in the same, incorrect way. To overcome this, it is also possible to test program execution on the previous VM, Dalvik, as long as some known differences between the two VMs are tolerated (e.g. the messages they use to report errors.) As we increase the number of backends to test, the likelihood that they are all wrong in the same way should decrease.




This diagram shows the fuzzing and testing process. First, the fuzzer parses the DEX file format into a form such that it can apply various mutations to the code. It randomly selects a subset of the methods of the program to mutate, and for each one, it randomly selects a number of mutations to apply. The fuzzer produces a new, mutated DEX file with the mutated code, and then executes this program using the various backends of the ART VM.


Note that all backends pass through a single verifier, and that some backends have been simplified in this diagram - the quick and optimizing backends are technically split up into compilation and execution phases, while the interpreter only has an execution phase. Ultimately, the execution of the mutated DEX file should produce some kind of output from each backend, and we compare these outputs to find bugs. In this example, the fact that the optimizing backend produces "9" instead of "7" strongly suggests there is a bug with the way the optimizing backend has handled this mutated code.


So how do we do this fuzzing? A naive approach would be to take the DEX file and flip bits randomly to produce a mutated DEX file. However, this is likely to always produce a DEX file that fails to pass verification. A large part of the verification process is checking that the structure of the DEX file format is sound, and this includes a checksum in the file's header - randomly flipping bits in the whole file will almost certainly cause this checksum to become invalid, but also likely break some part of the file's structure. A better approach is to focus applying minor mutations to the sections of the program that directly represent executable code.


Some examples of these minor mutations are as follows:



swap two bytecodesPick two bytecodes to swap with each other.
change the register used by a bytecodePick one of the registers specified by a bytecode and change the register.
change an index into the type/field listSome bytecodes may use an index into a list of methods, types or fields at the start of a DEX file. For example, new-instance v0, type@7 will create a new object with the type listed at index 7 of the type list and puts it in v0. The mutation changes which type, field or method is selected.
change the target of a branch bytecodeMake a branch bytecode point to a new target, changing control-flow.
generate a random new bytecodeGenerate a new random bytecode and insert it into a random position, with randomly generated values for all of its operands.


We limit our mutations to a few simple changes to bytecodes that individually are unlikely to break the verification of the DEX file, but in combination may lead to differences in the way the program executes. At the same time, we do not want to ensure that every mutation results in a legal bytecode state, because we wish to search for holes in the verification of the program. Often holes in verification may lead to a compiler making an incorrect assumption about the code it is compiling, which will manifest as differences in output between the compiler and the interpreter.


Example of Bugs Found


Now we present one of the bugs that we have found and fixed in the Android Open Source Project's (AOSP) code base, using this fuzz testing strategy.


When presented with a bytecode that reads an instance field of an object, such as iget v0, v1, MyClass.status (this writes into v0 the value of the "status" field of the object referred to by v1) the verifier did not confirm that v1 actually contained a reference to an object.


Here's a sequence of bytecodes that creates a new MyClass instance, and sets the status field to its initial value + 1:


const v0, 1
new-instance v1, MyClass
invoke-direct {v1} void MyClass.<init>() // calling MyClass() constructor
iget v2, v1, MyClass.status
add-int v2, v0, v2
iput v2, v1, MyClass.status


If a mutation changed the v1 on line 4 to v0, then iget would now have the constant 1 currently in v0 as an input, instead of the reference to an object that was in v1.  Previously, the verifier would not report this as an error when it should, and so the compiler (which expects the iget bytecode to have been properly verified) would expect an object reference to be in the input register for iget, and just read from the value of that reference plus the offset of the status field. If an attacker ensured that an address they wanted to read from was used as the loaded constant, they could read from any memory address in the process' address space. Java removes the ability to read memory directly (without the use of some mechanism such as JNI), to ensure that, for instance, private fields of classes cannot be accessed from within Java, but this bug allowed this to happen.


While this particular bug was present in the verifier, other bugs have been found and fixed in the quick backend of ART. For some of these bugs, we have contributed patches to the AOSP code base, while other bugs have been reported to the ART team. As a result of our fuzz testing efforts, new tests have been added to ART's test suite that are buildable directly from a description of DEX bytecode, whereas previously all tests had to be built from Java source code. This was necessary because many bugs we have found arise from specially crafted pieces of bytecode that the javac and dx tools would not generate themselves. We have aimed to submit DEX bytecode tests with any patches we submit to AOSP.




In this post we have looked at how fuzz testing can help the development of new backends for a virtual machine, specifically the ART VM that now powers Android.  From the roughly 200 test programs already present in ART's test suite, we have produced a significantly larger number of new tests using fuzzing. Each additional program used for testing increases our confidence that the implementation of ART is sound.  Most of the bugs we found affected the quick backend of ART as it was being developed in AOSP, but as new bugs could arise from complicated interactions between optimisations in the optimizing backend, the use of fuzz testing will increase our chances of finding any bugs and squashing them early.


Further Reading


The initial research into fuzzing was performed by Barton Miller at UW-Madison.


Paul Sabanal fuzzed the experimental release version of ART in Kitkat, and found a few crashes. He presented this work at HITB2014.


For more information about differential testing, various papers have been written about Csmith, a tool that performs differential testing to test C compilers.


Researchers at UC Davis recently presented work about Equivalence Modulo Inputs, where seed programs are fuzzed to produce new programs that are expected to produce the same output as the seed program for a given set of inputs. All produced programs are then compiled and executed, and divergences in output indicate miscompilations.

In this blog I will cover various methods of runtime feature detection on CPUs implementing ARMv8-A architecture. These methods include using HWCAP on Linux and Android, using NDK on Android and using /proc/cpuinfo. I will also provide sample code to detect the new optional features introduced in the ARMv8-A architecture. Before we dig deep in to the different methods, let us understand more about ARMv8-A CPU features.


ARMv8-A CPU features


ARMv7-A CPU features


The ARMv8-A architecture has made many ARMv7-A optional features mandatory, including advanced SIMD (also called NEON). This applies to both the ARMv8-A execution states namely, AArch32 (32-bit execution state, backward compatible with ARMv7-A) and AArch64 (64-bit execution state).


New features


The ARMv8-A architecture introduces a new set of optional instructions including AES. These instructions were not available in ARMv7-A architecture. These optional instructions are grouped into various categories, as listed below.


  • CRC32 instructions - CRC32B, CRC32H, CRC32W, CRC32X, CRC32CB, CRC32CH, CRC32CW, and CRC32CX
  • SHA1 instructions - SHA1C, SHA1P, SHA1M, SHA1H, SHA1SU0, and SHA1SU1
  • SHA2 instructions - SHA256H, SHA256H2, SHA256SU0, and SHA256SU1
  • AES instructions - AESE, AESD, AESMC, and AESIMC
  • PMULL instructions that operate on 64-bit data - PMULL and PMULL2


Runtime CPU feature detection scenarios


User-space programs can detect features supported by an ARMv8-A CPU at runtime, using many mechanisms including /proc/cpuinfo, HWCAP and the Android NDK CPU feature API.  I will describe them in detail below.


Detect CPU feature using /proc/cpuinfo


Parsing /proc/cpuinfo is a popular way to detect CPU features. However I strongly recommend not to use /proc/cpuinfo on ARMv8-A for cpu feature detection, as this is not a portable way of detecting CPU features. Indeed, /proc/cpuinfo reflects the characteristics of the kernel rather than the application which is being executed. This means that /proc/cpuinfo is the same for both 32-bit and 64-bit processes running on an ARMv8-A 64-bit kernel. The ARMv8-A 64-bit kernel's /proc/cpuinfo output is quite different from that of a ARMv7-A 32-bit kernel. For example, ARMv8-A 64-bit kernel uses 'asimd' for advanced SIMD support, while ARMv7-A 32-bit kernel uses 'neon'. Thus, NEON detection code that looks for the "neon" string in /proc/cpuinfo will not work on ARMv8-A 64-bit kernel. Applications using /proc/cpuinfo should migrate to either using HWCAP or the NDK API, as they are maintained and controlled interfaces unlike /proc/cpuinfo.


Detect CPU feature using HWCAP


HWCAP can be used on ARMv8-A processors to detect CPU features at runtime.


HWCAP and Auxiliary vector


First, let me give you a brief overview of HWCAP. HWCAP uses the auxiliary vector feature provided by the Linux kernel. The Linux kernel's ELF binary loader uses the auxiliary vector to pass certain OS and architecture specific information to user space programs. Each entry in the vector consists of two items: the first identifies the type of entry, the second provides the value for that type. Processes can access these auxiliary vectors through the getauxval() API call.


getauxval() is a library function available to user space programs to retrieve a value from the auxiliary vector. This function is supported by both bionic (Android's libc library) and glibc (GNU libc library).  The prototype of this function is unsigned long getauxval(unsigned long type); Given the argument type, getauxval() returns the corresponding value.


<sys/auxv.h> defines various vector types. Amongst them, AT_HWCAP and AT_HWCAP2 are of our interest. These auxiliary vector types specify processor capabilities. For these types, getauxval() returns a bit-mask with different bits indicating various processor capabilities.




Let us look at how HWCAP can be used on ARMv8-A. In ARMv8-A, the values returned by AT_HWCAP and AT_HWCAP2 depend on the execution state.  For AArch32 (32-bit processes), AT_HWCAP provides flags specific to ARMv7 and prior architectures, NEON for example.AT_HWCAP2 provides ARMv8-A related flags like AES, CRC.  In case of AArch64, AT_HWCAP provides ARMv8-A related flags like AES and AT_HWCAP2 bit-space is not used.


Benefits of HWCAP


One of the main benefits of using HWCAP over other mechanisms like /proc/cpuinfo is portability. Existing ARMv7-A programs that use HWCAP to detect features like NEON will run as is on ARMv8-A, without any change. Since the getauxval() is supported in Linux (through glibc) and Android (through bionic), the same code can run on both Android and Linux.


Sample code for AArch32 state


The sample code below shows how to detect CPU features using AT_HWCAP in the AArch32 state.


#include <stdio.h>
#include <sys/auxv.h>
#include <asm/hwcap.h>

int main()
    long hwcaps2 = getauxval(AT_HWCAP2);

    if(hwcaps2 & HWCAP2_AES){
        printf("AES instructions are available\n");
    if(hwcaps2 & HWCAP2_CRC32){
        printf("CRC32 instructions are available\n");
    if(hwcaps2 & HWCAP2_PMULL){
        printf("PMULL/PMULL2 instructions that operate on 64-bit data are available\n");
    if(hwcaps2 & HWCAP2_SHA1){
        printf("SHA1 instructions are available\n");
    if(hwcaps2 & HWCAP2_SHA2){
        printf("SHA2 instructions are available\n");
    return 0;


Sample code for AArch64 state


The code below shows how to detect ARMv8-A CPU features in AArch64 process using HWCAP


#include <stdio.h>
#include <sys/auxv.h>
#include <asm/hwcap.h>

int main()
    long hwcaps= getauxval(AT_HWCAP);

    if(hwcaps & HWCAP_AES){
        printf("AES instructions are available\n");
    if(hwcaps & HWCAP_CRC32){
        printf("CRC32 instructions are available\n");
    if(hwcaps & HWCAP_PMULL){
        printf("PMULL/PMULL2 instructions that operate on 64-bit data are available\n");
    if(hwcaps & HWCAP_SHA1){
        printf("SHA1 instructions are available\n");
    if(hwcaps & HWCAP_SHA2){
        printf("SHA2 instructions are available\n");
    return 0;


Detect CPU feature using Android NDK CPU feature API


The Android NDK provides an API to detect the CPU architecture family and the supported features at run time.


CPU feature API


There are two main functions, android_getCpuFamily() and android_getCpuFeatures().


  • android_getCpuFamily() - Returns the CPU family
  • android_getCpuFeatures() - Returns a bitmap describing a set of supported optional CPU features. The exact flags will depend on CPU family returned by android_getCpuFamily(). These flags are defined in cpu-features.h


Support for ARMv8-A optional features


The latest NDK release (version 10b, September 2014) supports ARMv8-A CPU features detection only for the AArch64 mode. However, the NDK project in AOSP supports both the AArch32 and the AArch64 CPU feature flags. The AArch32 feature flags were added to the AOSP in the change list 106360. The NDK uses HWCAP internally to detect the CPU features.


NDK Sample code to detect ARMv8-A cpu features


Detect CPU family


#include <stdio.h>
#include "cpu-features.h"

int main()
    AndroidCpuFamily family;
    family = android_getCpuFamily();
    if(family == ANDROID_CPU_FAMILY_ARM){
        printf("CPU family is ANDROID_CPU_FAMILY_ARM \n");
    } else if(family == ANDROID_CPU_FAMILY_ARM64){
        printf("CPU family is ANDROID_CPU_FAMILY_ARM64 \n");
    } else {
        printf("CPU family is %d \n", family);
    return 0;


Detect ARMv8-A CPU features


#include <stdio.h>
#include "cpu-features.h"

void printArm64Features(){
    uint64_t features;
    features = android_getCpuFeatures();
    if(features & ANDROID_CPU_ARM64_FEATURE_AES){
        printf("AES instructions are available\n");
    if(features & ANDROID_CPU_ARM64_FEATURE_PMULL){
        printf("PMULL instructions, that operate on 64-bit data, are available\n");
    if(features & ANDROID_CPU_ARM64_FEATURE_SHA1){
        printf("SHA1 instructions are available\n");
    if(features & ANDROID_CPU_ARM64_FEATURE_SHA2){
        printf("SHA2 instructions are available\n");
    if(features & ANDROID_CPU_ARM64_FEATURE_CRC32){
        printf("CRC32 instructions are available\n");

void printArmFeatures(){
    uint64_t features;
    features = android_getCpuFeatures();
    if(features & ANDROID_CPU_ARM_FEATURE_AES){
        printf("AES instructions are available\n");
        printf("PMULL instructions, that operate on 64-bit data, are available\n");
    if(features & ANDROID_CPU_ARM_FEATURE_SHA1){
        printf("SHA1 instructions are available\n");
    if(features & ANDROID_CPU_ARM_FEATURE_SHA2){
        printf("SHA2 instructions are available\n");
    if(features & ANDROID_CPU_ARM_FEATURE_CRC32){
        printf("CRC32 instructions are available\n");

int main(){
    AndroidCpuFamily family;
    family = android_getCpuFamily();
    if(family == ANDROID_CPU_FAMILY_ARM){
    if(family == ANDROID_CPU_FAMILY_ARM64){
    return 0;




The ARMv8-A architecture makes certain ARMv7-A features mandatory and introduces a new set of optional features. The popular way of detecting the features at runtime by parsing /proc/cpuinfo is not portable to ARMv8-A and existing code will not work without tricky changes. Instead, application programmers can easily use HWCAP on Linux and the NDK on Android. For detecting ARMv8-A optional features in the AArch32 mode, programmers should use HWCAP on Android as the latest NDK does not have support for it yet.

The recent Linaro Connect (lhttp://www.linaro.org/connect/lcu/lcu14/) saw several ARM and Linaro presentations about Android and about 64-bit. I think these might be interesting to anyone following Android, ARMv8, AARCH64 or 64-bit progress in mobile.


First is Serban Constantinescu presenting the journey involved in getting AOSP running first on a 64-bit kernel (in 2012) and then booting with a 64-bit userspace - all on ARM Fast Models:

LCU14 411: From zero to booting nandroid with 64bit support - YouTube


Next is Stuart Monteith the story of porting Dalvik to 64-bit - and how Dalvik and ART are related:

LCU14-100: Dalvik is Dead, Long Live Dalvik! OR Tuning ART - YouTube


Then a presentation by Ashok Bhat on some collaborative work between Linaro and ARM on creating some multimedia tests to help with porting several Android codecs to 64-bit

LCU14-502: Android User-Space Tests: Multimedia codec tests, Status and Open Discussions - YouTube


Finally a presentation by Kevin Petit on NEON ARMv8 and the use of intrinsics

LCU14-504: Taming ARMv8 NEON: from theory to benchmark results - YouTube


Hopefully, for those who prefer reading to watching, we will be able to post some blogs on the topics soon.

A few years ago(20?), I bought a programmable calculator and downloaded a program(from a "Bulletin Board" in Europe) to do symbolic Z-transform expansions for a digital signal processing test I had in college. I finished my test in a few minutes and was immediately handed my test with a "perfect!" and 0 for a grade. When I explained that I had downloaded a program to my calculator from a site in Europe - I got "right..." after a 30 second demo(and explanation of how the code worked), the zero had a 10 put in front of it and that professor became my advisor


Since then, billions of people have been downloading apps through an open source VM(I actually wrote some code for) called "Android".  A couple of years ago, I decided to start working on another open source VM - I call "rekam1" mirrowrite(rekam1);  I'll be demoing some consumer programmable projects with this at the world maker faire in NYC(check it out if you happen to be in the area) - and I'll be talking about Virtual Machines for wirelessly connected Cortex M devices at the upcoming TechCon conference in my talk: "The Consumer Programmable IOT"  If you're interested to see how the maker(and consumer developer) community could change how we all write/share code - check out my talk!


ARM TechCon Schedule Builder | Session: The Consumer Programmable IoT

Eirik Aavitsland at Digia has created a blog post about how you can easily make an ODROID-U3 or another device running a recent version of Android boot to Qt.


This blog has been written before but quite a few things have improved in the ease of use and breadth of support of Streamline use on Android in the past few years. For starters, Mac OS X is well supported. Now all three major development platforms (Linux, Windows and Mac) have the ability to run DS-5 Community Edition debugger (gdb) and Streamline with the ADT Eclipse tools from Google as an add-on or pre-packaged as DS-5 CE for Windows and Linux from ARM with ADT as an add-on. Also, and most welcome, is the new Gator driver. The component of Streamline that runs in Android to collect OS and processor counters used to require both a kernel module and a driver daemon. Compiling and flashing any module could be complicated depending on the availability of your Android platform kernel headers. That requirement has been removed and now the Gator driver will run as root on many devices. This July (7/2014), an updated version of gatord in the DS-5 CE 5.19 will be released that greatly expands the kernel versions supported (beyond the 3.12 kernel version supported in the current DS-5 5.18 release). Finally, I’ve found some erroneous and dated info in some blogs that claim to be up to date to DS-5 5.18 and even the yet to be released 5.19. I’ll try to correct that here and support this blog entry.


Streamline is a powerful system analysis tool that will help you speed up your code, reduce energy footprint and balance system resources. The free version in the Community Edition of DS-5 lets you view CPU and OS counters in a powerful graphical view; CPU and GPU activity, cache hits and misses and visibility down in to individual threads and modules. You can find code that is blocking or could be optimized by multithreading or refactoring in NEON or the GPU. Check out more features on the optimize site.



Getting Started:


As of this writing the Android SDK Manager is Revision 22.6.4 bundled in the latest SDK for Mac, adt-bundle-mac-x86_64-20140321. The SDK is available at the Android Developer Site. The Native Development Kit (NDK) is revision 9d. Download both of these for your appropriate platform. I’m downloading the Mac OS X 64-bit versions for this guide but these instructions should work for Windows and Linux just as easily.


Once you unpack these tools, you should add some executable paths to your platform if you plan on using the terminal for anything like the Android Debug tool (adb). It is now possible to use all of the tools from within Eclipse without adjusting your executable paths but for some of us old-schoolers who are wedded to the CLI, I drop my NDK folder in to the SDK folder and put that folder in my Mac’s /Applications directory. You can place them wherever you like on most platforms though. I then added these to my ~/.bashrc


export PATH=$PATH:/Applications/adt-bundle-mac-x86_64-20140321/sdk/platform-tools

export PATH=$PATH:/Applications/adt-bundle-mac-x86_64-20140321/sdk/tools

export PATH=$PATH:/Applications/adt-bundle-mac-x86_64-20140321/android-ndk-r9d


You should now be able to launch common Android tools from your command line:

> which ndk-build


> which fastboot


> which adb


> which android



You can Launch the Android SDK Manager from Eclipse in the “Window” menu or via the command line by typing:

> android


From there, you can update your current SDK, install older APIs, build-tools, platform tools and in “Extras”, the Android Support Library for compatibility with older APIs.

Pasted Graphic 4.jpeg

When you run Eclipse (ADT) for the first time or change versions, you may have to tell it where to find the SDK. The Preferences dialog box is found on Macs via the ADT->Preferences menu, sub heading Android.

Pasted Graphic 3.jpeg

Setting up a demo app to analyze (if you don’t have your own app):


You probably have your own library or application you want to perform system analysis on but just in case you’re checking out the tool, I’ll step through setting up an app that is near and dear to me, ProjectNe10. You can grab the master branch archive from GitHub. For this tool demo, I’ve created a directory /workspace and unzipped the Ne10 archive inside that folder. ProjectNe10 requires the cmake utility. Fortunately, there is a Homebrew solution to install cmake from the command line:


brew install cmake


If you don’t have brew installed, install it. You’ll use it in the future, I promise. You can also just download the binary for any platform from cmake.

Now we can build the Ne10 library from the command line:


Set these to your particular paths:


export NE10PATH=/workspace/projectNe10

export ANDROID_NDK=/Applications/adt-bundle-mac-x86_64-20140321/android-ndk-r9d




cd $NE10PATH

mkdir build && cd build

cmake -DCMAKE_TOOLCHAIN_FILE=../android/android_config.cmake ..


make install


That make install line will copy libNE10_test_demo.so to your /workspace/projectNe10/android/NE10Demo equivalent. Now you can go to the File->Import menu in Eclipse and import an existing Android code base in to your workspace.


Pasted Graphic 6.jpeg

Pasted Graphic 7.jpeg


If all goes well, you should be able to connect your ARM based Android Device (in my case, a Nexus 5 running Android 4.4.4 to match the current SDK at the time of this writing) and run this app from the Run menu as an Android app. As a sanity check, you should run adb devices from the command line to verify you can see your device. This app will iterate through every function in the ProjectNe10 library with both C and NEON implementations. One of the implementations should be faster. I’ll give you a hint. It is the NEON implementation.



Installing DS-5 Community Edition (Free Eclipse Plugin with enhanced ARM debug and system analysis):


Start Eclipse and go to the menu Help->Install New Software.... Click on “Add...”, and paste http://tools.arm.com/eclipse in the location text box, then click OK. Select ARM DS-5 Community Edition, as shown on the screenshot below, and click Next. Eclipse will compute the dependencies of the DS-5 CE plug-ins.

Pasted Graphic 8.jpeg


Click Next again. Read the license agreements and if you accept, hit Finish. After the install is complete, ADT will ask you to reload.

A license dialog should popup if this is a fresh install. Select "Install Community edition license" and click "Continue".


If there was no popup license message go to Help->Generate community edition license, and click "Finish".


Congratulations, you now have ARM DS-5 CE installed with its enhanced and easy to use debugger which you can use to debug Android NDK apps and libraries with the steps in this guide. You also have Streamline; a powerful system analysis tool which we’ll cover in the next section.


Using Streamline and gator to analyze Android apps and the entire system


Before you can gather data for system analysis, you have to install a data collecting driver (daemon) in Android. Gatord will gather processor and kernel counters on the Android device and stream them over to your host machine. It must run as root to do this. Any device with an unlocked boot loader is very simple to root, you usually just flash a custom recovery tool like TWRP and install SuperSU. If you have a locked bootloader, you’ll have to use a device exploit so I can’t recommend this or help you but your favorite search engine might… This is a minor inconvenience now as older versions required a kernel module (gator.ko) which needed to be compiled against your particular device’s kernel headers. Now that Android security terms to pass Android CTS disallow kernel modules, you’d have to compile in to the kernel and flash it. Fortunately the new gatord will expand its kernel version support significantly in July.


First, build gatord. Go to the menu Help->ARM Extras… this will open up a folder with several goodies in it.

Pasted Graphic 9.jpg


I’m going to build this from the command line so fire up your favorite terminal and cd in to this directory. The easiest way in the Mac terminal app is to type “cd ” and dragging the gator folder in to the terminal window. OS X will fill in the path, then:


cd daemon-src

tar zxf gator-daemon.tar.gz

mv gator-daemon jni

cd jni



These steps should unzip the gatord source, and build it for Android (dynamically linked) with the output in ../libs/armeabi/gatord. Copy this binary to your Android device with your favorite method, AirDroid, scp, Droid NAS or very simply:


adb push ../libs/armeabi/gatord /sdcard/gatord


This, of course, assumes you’ve enabled developer options and debugging on your device. “On Android 4.2 and newer, Developer options is hidden by default. To make it available, go to Settings > About phone and tap Build number seven times. Return to the previous screen to find Developer options. In Developer options click USB debugging. If this is a new device, you may have to approve the debug link security the first time you try to use adb. You can also do this with an ARM based Android Virtual Device (AVD) in the emulator if your physical device is too ‘locked down’ but Streamline system data won’t be as useful. You may have to use “mount -o rw,remount rootfs /“ and “chmod 777 /mnt/sdcard” in your AVD to push gatord.


Now, the tricky part, you have to move this binary to an executable location in the filesystem and set executable permissions. The most reliable method I’ve used is ES File Explorer. Go in to the menu, turn on Root Explorer and go to the Mount R/W option, set root “/“ as RW (read/writeable) rather than RO. Then copy and paste gatord in to /system/bin in your Android filesystem. You can also set the permissions to executable in ES File Browser by long pressing on the gatord file, then more->Properties->Permissions->Change. Give the owner any group Execute permission and press Ok.


Back in your host machine terminal you need to set up a pipe for gator to communicate over USB and then get a shell on the device to start it:


adb forward tcp:8080 tcp:8080

adb shell


Now you’ve got a shell on your android device, you can su to root and start gatord. Type:





The rest is pretty straight forward. Go to the Window->Show View->Other…->DS-5->ARM Streamline Data

Click on the gear button

Pasted Graphic 13.jpeg



In the address section, enter “localhost” if you’re streaming the capture data over USB using adb to forward the TCP port. In the Program Images box select the shared library that you want to profile (add ELF image from workspace).

Pasted Graphic 10.jpg




You can now use the red “Start Capture” button at any time.

Pasted Graphic 14.jpeg

Other blogs and tutorials are accurate from this point forward on the features and use of Streamline so I’ll drop a few and let you get to it!

The “CAPTURING DATA AND VIEWING THE ARM STREAMLINE REPORT” section of this blog is accurate.

Events based sampling video, analyzing CPU and GPU performance and customizing charts on YouTube.


At VIA we are aiming to provide more software support for our products. Most ARM based boards have both Linux and Android images that potential partners can try. On our product line we have two Freescale boards, the VAB-800 (single core Cortex-A8) and newer VAB-820 (quad core Cortex-A9). The latter just have a brand new Android Evaluation Package fresh up on our website, ready for testing.


The Android image is based on Jelly Bean 4.2.2 (which puts this package ahead of even our other boards). Among the available features is the CAN bus driver, resistive touch screen, HDMI video and audio output, dual display and mini PCI-E support. On the developer timeline for future releases we have ADV-7180 Capture, WatchDog/GPIO, VIA Smart ETK support for embedded solutions.


Android for Freescale is still a quite new combination with a lot of potential. We are hoping that it will make device developers lives easier both on the software and hardware side. This evaluation package is just the beginning of this conversation.


What do you think, what would make you choose an Android system over others for your next embedded solution?


The Android Evaluation Package (as well as the Linux Evaluation Package) is available on the VIA Embedded website.

There is a very active overclocking community called HWBot, with quite a few organizers here in Taiwan. For a very long time they were doing desktop (and laptop?) overclocking, challenging the hardware, and pushing the boundaries. When they were giving a presentation about their past, and future plans, they were really proud of making the desktop computer industry care more about hardware quality.


Now they want to do the same thing for smartphone hardware. Just recently released the beta version of their Android benchmarking app HWBot Prime, an started to gather data for different devices. My HTC Butterfly (running a Quad Snapdragon C4, I guess) did pretty well on that (whenever I could kill enough apps not to interfere with the benchmark).


The VIA Springboard (that I'm taking care of) is a single-board computer that can also run Android (4.0.3) besides Linux. It has a WM8950 single core 800MHz CPU, so it is not a match for the Butterfly, but the per-core-per-MHz results are better.


So far it's benchmarking only without any overclocking yet, and I'm running on the stock Android image, but it's a good baseline to start improving on the result. Cannot manage something that I cannot measure, right?


The submitted result for the Springboard is on the HWBot leaderboard. I wonder if anyone else wants to benchmark, tune, and overclock their ARM devices?


The whole experience is written up in the VIA Springboard Blog.

As a result of the rapid proliferation of Android smart phones and tablets, embedded developers worldwide are increasingly adopting the operating system for a growing number of embedded systems and connected devices that leverage its rich application framework, native multimedia capabilities, massive app ecosystem, familiar user interface, and faster time to market.


However, although the benefits of adopting Android for embedded systems and devices can be great, particularly for touch-based multimedia applications, utilizing the OS also presents a number of critical challenges, including selecting the right ARM SoC platform for the target system application, porting and customizing the operating system and applications, and ensuring tight integration between the hardware and software to deliver a compelling end-user experience.




In addition to exploring the benefits and challenges of adopting Android for embedded applications, the attached white paper provides an overview of the holistic approach that VIA Embedded has established in order to enable developers to reduce product development times and speed up time to market for innovative new embedded Android systems and devices.


Holistic Approach

VIA is committed to support the entire product development life cycle, from defining product requirements, all the way through development.

  • Best of Breed application specific ARM SoC platforms, with a comprehensive range of Freescale and VIA ARM SoCs
  • Small form factor ARM boards and systems, using VIA's expertise in creating practical form factor standards
  • Android software packages and customization services (see below)
  • Longevity, by supporting specific boards and systems up to 5 years


Android Customization


Via Embedded provides  a wide range of software solution packages and customization services to facilitate the development of Android embedded systems and devices:

  • Customized applications, including system apps
  • Kernel & Framework including security and special devices
  • System management including watchdog, remote monitoring, remote power on/off, silencing app and system upgrades
  • Embedded I/O including legacy I/O


VIA Android Smart Embedded Tool Kit (ETK)


The VIA Embedded Android Smart ETK includes a set of APIs that enable the Android application to access I/O and manageability services provided by the system hardware that are not supported in the Android framework.


APIs include:

  • Watchdog to help applications and the system to recover from failures and breakdowns
  • Scheduled power on/off, and periodic reboots
  • RTC Wake-up to auto power on at a specific time of the day, of the week, or of the month.
  • Legacy I/O Support making RS232, GPIO, I2C, and CAN bus available for apps



More details, and a case study is presented in the attached whitepaper.

We would like to share with you an Android-based application that enables Intel software on ARM-based devices. To demo you this approach we took Intel version of DOOM and run it on Android-based device. Application is freely available on Google Play:

Original DOOM - Android Apps on Google Play

This application is a mixture of virtualization and binary translation technology that translates in run-time Intel x86 code to ARM one. Along with translation this engine applies sophisticated optimization algorithms to bring high performance experience to end-users.

By the end of the day we can bring desktop applications to mobile devices at no costs. In this particular case we took original Intel x86 version of DOOM and launched it with no alterations or modifications on ARM-based Android device. In nearest future this approach could be extended to other applications.

For more details visit http://eltechs.com/exagear-mobile/



Ne10 FFT feature

Posted by yangzhang Dec 18, 2013

FFT feature in ProjectNe10

1 Introduction

Project Ne10 recently received an updated version of FFT, which is heavily NEON optimized for both ARM v7-A/v8-A AArch32 and v8-A AArch64 and is faster than almost all of the other existing open source FFT implementations such as FFTW and the FFT routine in OpenMax DL. This article will introduce this a bit.

2 Performance comparison with some other FFT’s on ARM v7-A

The following chart illustrates the benchmarking results of the complex FFT (32-bit float data type) of Ne10, FFTW and OpenMax. The test platform is ARM Cortex A9. The X-axis of the chart represents the length of FFT. The Y-axis represents the execution time of FFT. Smaller is better.

From this chart, we can find that Ne10 is better than FFTW, OpenMax DL in most of cases.

3 FFT on ARM v7-A/v8-A AArch32 and ARM v8-A AArch64

3.1 NEON usage


To utilize NEON accelerator, usually we have two choices:

  • NEON assembly
  • NEON intrinsic

The following table describes the pros and cons of using assembly/intrinsic.


NEON assembly

NEON intrinsic


Always shows the best performance for the specified platform

Depends heavily on the toolchain that is used


The different ISA (i.e. ARM v7-A/v8-A AArch32 and ARM v8-A AArch64) has different assembly implementation. Even for the same ISA, the assembly might need to be fine-tuned to achieve ideal performance between different micro architectures.

Program once and run on different ISA’s. The compiler may also grant performance fine-tuning for different micro-architectures.


Hard to read/write compared with C.

Similar to C code, it’s easy to read/write.

3.2 ARM v7-A/v8-A AArch32 and v8-A AArch64 FFT implementations

According to the aforementioned pros/cons comparison, the intrinsic is preferred for the implementation of the Ne10 library

But for FFT, we still have different versions of implementations for ARM v7-A/v8-A AArch32 and v8-A AArch64 due to the reason described as follows:

// radix 4 butterfly with twiddles

scratch[0].r = scratch_in[0].r;

scratch[0].i = scratch_in[0].i;

scratch[1].r = scratch_in[1].r * scratch_tw[0].r - scratch_in[1].i * scratch_tw[0].i;

scratch[1].i = scratch_in[1].i * scratch_tw[0].r + scratch_in[1].r * scratch_tw[0].i;

scratch[2].r = scratch_in[2].r * scratch_tw[1].r - scratch_in[2].i * scratch_tw[1].i;

scratch[2].i = scratch_in[2].i * scratch_tw[1].r + scratch_in[2].r * scratch_tw[1].i;

scratch[3].r = scratch_in[3].r * scratch_tw[2].r - scratch_in[3].i * scratch_tw[2].i;

scratch[3].i = scratch_in[3].i * scratch_tw[2].r + scratch_in[3].r * scratch_tw[2].i;

The above code snippet lists the basic element of FFT---- radix4 butterfly. From the code, we can conclude that:

  • 20 64-bit NEON registers are needed if 2 radix4 butterflies are executed in one loop.
  • 20 128-bit NEON registers are needed if 4 radix4 butterflies are executed in one loop.

And, for ARM v7-A/v8-A AArch32 and v8-A AArch64,

  • There are 32 64-bit or 16 128-bit NEON registers for ARM v7-A/v8-A AArch32.
  • There are 32 128-bit NEON registers for ARM v8-A AArch64.


Considering the above factors, in practice the implementation of Ne10 eventually has an assembly version, in which 2 radix4 butterflies are executed in one loop, for ARM v7-A/v8-A AAch32, and an intrinsic version, in which 4 radix4 butterflies are executed in one loop, for ARM v8-A AArch64.


3.3 C/NEON performance boost

The following charts show the C/NEON performance boosts in ARM v8-A AArch32 and AArch64 on the same Cortex-A53 CPU of Juno. Larger is better.

All the blue bars show the data in the AArch32 mode. The NEON code is v7-A/v8-A AArch32 assembly. The toolchain used is gcc 4.9.

All the red bars show the data in the AArch64 mode. The NEON code is intrinsic. The performance of intrinsic depends on toolchains greatly. The toolchain used here is llvm3.5.

From these charts, we can conclude that float complex FFT shows the similar or better performance boost between the AArch64 mode and the AArch32 mode. But for int32/16 complex FFT, the performance boost in the AArch32 mode is usually better than in the AArch64 mode (but this doesn’t mean the int32/16 complex FFT performs faster in the AArch32 mode than in the AArch64 mode!) 

The data from this exercise is useful to analyze the performance boost for ARM v8-A AArch64 mode but we still need more data to verify and reinforce our concept.

3.4 AArch32/AArch64 performance boost

The following charts are based on performance of the AArch32 C version and show the performance ratios of the AArch32 NEON version and the AArch64 C version, and the AArch64 NEON version on the same Cortex-A53 CPU on Juno. Larger is better.

From these charts, we can conclude that FFT in the AArch64 mode performs faster than in the AArch32 mode, no matter C or NEON.

4 Usage

4.1 APIs

The FFT still supports the following features:


Data type




2^N (N is 2, 3….)

r2c FFT


2^N (N is 3, 4….)

c2r IFFT


2^N (N is 3, 4….)

But the APIs have changed. The old users need to update to latest version v1.1.2 or master.

More API details, please check http://projectne10.github.io/Ne10/doc/group__C2C__FFT__IFFT.html.


4.2 Example

Take the float c2c FFT/IFFT as an example, current APIs are used as follows.

#include "NE10.h"



    fftSize = 2^N; //N is 2, 3, 4, 5, 6....

    in = (ne10_fft_cpx_float32_t*) NE10_MALLOC (fftSize * sizeof (ne10_fft_cpx_float32_t));

    out = (ne10_fft_cpx_float32_t*) NE10_MALLOC (fftSize * sizeof (ne10_fft_cpx_float32_t));

    ne10_fft_cfg_float32_t cfg;

    cfg = ne10_fft_alloc_c2c_float32 (fftSize);



    ne10_fft_c2c_1d_float32_neon (out, in, cfg, 0);



    ne10_fft_c2c_1d_float32_neon (out, in, cfg, 1);


    NE10_FREE (in);

NE10_FREE (out);

    NE10_FREE (cfg);


5 Conclusion

The FFT shows that you can get a significant performance boost in the ARM v8-A AArch64 mode. You may find more use cases of course. We welcome feedback and are looking to publish use cases to cross promote ProjectNe10 and the projects that use it.

For more details, please access http://projectne10.github.com/Ne10/

In the early days if multicore design, Intel claimed that Android devices did not benefit from multiple cores as the apps often lacked threading. A lot has changed and since then they have, of course, released dual-core ATOM for Android.   Today It’s hard to find a CPU in a widespread mobile device that isn’t multicore anymore because most apps need to be multi-threaded.


Most ARM partners are producing dual and quad core devices, more than what Intel produce so we maintain an advantage as Android becomes more and more multicore friendly.  So app developers need consider threading in their designs as Android becomes more intelligent about its power and thread management (i.e. ARM big.LITTLE in 64-bit SoCs)


With that in mind I teamed up with Matthew Du Puy to develop a couple of articles about Android software design and the tools ARM offers developers.  The first article, Android software design for multicore systems in Dalvik, we look at the Dalvik runtime environment so that many apps are developed in. Dalvik applications are developed using the Android SDK, usually in the GUI environment provided by the Android Development Tools (ADT) plugin for Eclipse.  In the second we take a look at Android multicore design options in C/C++ or assembly language development.


Let us know what you think.


I think the Samsung Chromebook (model XE303C12) is definitely an interesting product. It is very portable, rather inexpensive and comes with the ARM-based Samsung Exynos 5 Dual CPU. There are several posts on the web explaining how to install different linux distributions on it, but I could not find any successful attempt to port Android to it. In this blog post I give details of how I ported Android to the Samsung Chromebook model XE303C12. I try to be quite pedantic in giving details of the procedure I followed. I do this in the hope of generating documentation which can be useful in other similar ports.




  • The Samsung Chromebook model XE303C12, with the Samsung Exynos 5 Dual CPU,
  • An SD card, 8 GB in this guide,
  • A desktop PC, used to compile the kernel and the Android filesystem, with a card reader,
  • A good internet connection: the source download for Android is approximately 8.5 GB in size,
  • An USB-to-ethernet dongle (optional),


  • 64-bit Ubuntu 12.04 installed on the desktop PC. Other operating systems may work as well, but have not been tested.


Getting ready

Below I describe how to setup the Chromebook and the machine to be used for building the software. This knowledge will be useful in the following sections.


Install additional software

Install some required packages on the desktop PC with:


        desktop-pc$ sudo apt-get install \
                      u-boot-tools device-tree-compiler \
                      gcc-4.6-arm-linux-gnueabi g++-arm-linux-gnueabi


This will allow you to generate u-Boot images and use dtc to add the required Flattened Device Tree to your kernel image.


Putting the Chromebook in developer mode

There are various blogs explaining how to do this. I recommend following Daniel P. Berrangé's instructions, which are copied below for your convenience:


  1. Booting into Recovery Mode is the first thing to do. This requires holding down the Esc and Refresh keys, while pressing the Power key.
  2. It should now display a nice scary message that the installation is broken. This is of course a lie, so ignore it.
  3. Pressing Ctrl-D now will start the switch into Developer Mode.
  4. It should now display a less scary message asking if you want to turn off verification. We do indeed want to do this, so press ENTER.
  5. The ChromeBook will reboot and tell you that verification is disabled.
  6. Wait a short while, or press Ctrl-D, and it'll display another message that it is transitioning to Developer Mode.
  7. Erasing local data can take a while, so be patient here. Strangely, there’s a crude ascii art progress bar along the top of the screen here, while everything else remains pretty & graphical.


When the Chromebook is in developer mode it behaves like this: immediately after the device is turned on, it shows a white screen, with the text "OS verification is OFF/Press SPACE to re-enable". At this point you can do various things:


  • You can just ignore the message and wait: after about 30 seconds the Chromebook boots normally,
  • You can press CTRL+D and induce the Chromebook to boot normally,
  • You can press CTRL+U and induce the bootloader to boot from the SD card. The SD card, however, needs to be prepared appropriately and the system does also need to be instructed not to ignore it (I explain below how to do it),
  • You can press SPACE to leave the developer mode and return to normal (verified) mode.


Opening a root shell

Turn on the Chromebook and allow it to boot Chrome-OS. If you have just bought the device, you do not need to accept the Chrome-OS license. Wait until you get the first screen where you are asked to choose and setup the network.  Setting up the network is not required in this guide, but you can easily do it, if required: just follow the instructions on the screen and proceed until you are shown the license agreement.  You can now press CTRL+ALT+→ where is the third key starting from the left at the top of your keyboard, where the keys F1, F2, ... would normally be. The Chromebook displays a console. Login as root; there is no password. The cursor may not be visible.  A not-so-nice way of showing the cursor is starting vi. Launch vi, by typing vi + ENTER and immediately quit it typing :q! + ENTER.


Via the root console you can do things like inspect the configuration (e.g. find the modules currently loaded in the kernel with lsmod or see how the network is configured with ifconfig), which may be useful to solve issues later with Android. The machine can be rebooted with the command reboot or powered off with the command poweroff.


Installing a Linux distribution to use as a support system

In this guide I explain how to install a GNU/Linux distribution to allow testing your own compiled kernel before using it with Android.  While installing a GNU/Linux distribution is not strictly necessary to get Android running on your Chromebook, having such a system may prove useful for debugging purposes. Unlike Android, a GNU/Linux distribution comes with many useful tools for inspecting the system and interacting with it directly.


In this guide we will prepare the SD card to allow a dual boot setup with both Android and another regular GNU+Linux distribution. There are different distributions which can be used for the purpose: Fedora, Bodhi Linux, Debian, Ubuntu.

In this guide I choose Fedora, as the instructions are written down with particular clarity.


Follow the instructions given for Fedora, but do partition the SD card differently. Create four partitions: two 16 MB partitions for the kernel, followed by two ext4 partitions: one for Fedora — give it ~4 GB — and one for Android, give it the remaining ~4 GB:


  • Partition 1: 16 MB, unformatted, Fedora kernel,
  • Partition 2: 16 MB, unformatted, Android kernel,
  • Partition 3: 4 GB, ext4, Fedora file system,
  • Partition 4: 4 GB, ext4, Android file system,


At this point you should be able to boot Fedora. You should have taken the kernel and modules from Chrome-OS and Fedora should be able to use graphics, the wireless and the USB-to-ethernet dongle, if you have one. Next step is compiling the kernel ourselves and making sure Fedora can use our own kernel with our own modules.


Getting the sources and compiling the kernel

In order to run Android, you need a kernel which supports some Android specific features (e.g. the binder kernel driver). You then need to compile a kernel which has these features enabled (unlike the kernel which comes with the Chromebook). In this section we explain how to do this.


Download the Chromium Linux Kernel:


         desktop-pc$ mkdir chromebook
         desktop-pc$ cd chromebook
         desktop-pc$ git clone http://git.chromium.org/chromiumos/third_party/kernel.git \
                       -b chromeos-3.4


Where chromebook is a name for the directory where you want to download the sources. Here I use the branch chromeos-3.4.


A directory with name kernel should have been created by git. In what follows, I assume:




If you want to use exactly the same kernel which is used in this guide do as follows (I suggest to do this, unless you know what you are doing):


        desktop-pc$ cd $CHROMEOS
        desktop-pc$ git checkout 70301d5c21ee9d422e2621b76239f51f0e008362


Now, configure the Kernel:


        desktop-pc$ ./chromeos/scripts/prepareconfig chromeos-exynos5


This script creates the .config file in the kernel top directory for you. Note that there is a file /boot/config-3.4.0 in the chromebook native filesystem which contains the configuration used to build the native chromebook kernel.


Now tweak the configuration and add some features needed for Android. Make sure .config contains the following lines (uncommented):




Start compiling the configured kernel:


        desktop-pc$ make -j8 ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- uImage


Notice that you need to have the "arm-linux-gnueabi" version of gcc installed, as explained in the section Install additional software. If you do, then


        desktop-pc$ arm-linux-gnueabi-gcc --version


Shows something like:


        arm-linux-gnueabi-gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3
        Copyright (C) 2011 Free Software Foundation, Inc.
        This is free software; see the source for copying conditions.  There is NO


Let's return to the compilation of the kernel. After giving the make command, you may get messages like,


        Android RAM buffer console (ANDROID_RAM_CONSOLE) [N/y] (NEW)


Just type ENTER to all of them to use the default values.  Compilation will then take a while.


The compilation creates the files Image, zImage and uImage in the directory $CHROMEOS/arch/arm/boot. Run the command below to create the dtb files for your device in the directory $CHROMEOS/arch/arm/boot:


        desktop-pc$ make -j8 ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- dtbs


Next, create a file in $CHROMEOS/arch/kernel.its with the following content:



        / {
            description = "Chrome OS kernel image with one or more FDT blobs";
            #address-cells = <1>;
            images {
           description = "kernel";
               data = /incbin/("arm/boot/zImage");
               type = "kernel_noload";
               arch = "arm";
               os = "linux";
               compression = "none";
               load = <0>;
               entry = <0>;
               description = "exynos5250-snow.dtb";
               data = /incbin/("arm/boot/exynos5250-snow.dtb");
               type = "flat_dt";
               arch = "arm";
               compression = "none";
              algo = "sha1";
            configurations {
           default = "conf@1";
               kernel = "kernel@1";
               fdt = "fdt@1";


See also Olof Johansson's post and Siarhei Siamashka's mkimage script.


Note that the paths arm/boot/zImage and arm/boot/exynos5250-snow.dtb are pointing to files which — by now — should exist in your filesystem.  Then, do as follows:


        desktop-pc$ cd $CHROMEOS/arch
        desktop-pc$ mkimage -f kernel.its kernel.itb


A file kernel.itb is produced which contains the kernel in the right form: a FIT kernel image. It should be possible to use kernel.itb as a replacement for what — in the original device — is stored as /boot/vmlinuz-3.4.0.


Compiling the kernel modules

Do as follows:


        desktop-pc$ cd $CHROMEOS
        desktop-pc$ mkdir $CHROMEOS/../modules
        desktop-pc$ make -j8 ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- modules
        desktop-pc$ make -j8 ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- modules_install \


The directory $CHROMEOS/../modules should be populated with the kernel modules.


Using the compiled kernel and modules with Fedora

Insert the SD card on your PC. Here I assume that the partition containing the Fedora filesystem is mounted in /mnt/Fedora. I also assume that you created a user named guest in Fedora. While installing Fedora, if you have followed the instruction correctly, you will have copied the modules from Chrome-OS inside /mnt/Fedora/lib/modules/ and the firmware files inside /mnt/Fedora/lib/firmware/. Do as follows:


        desktop-pc$ mv /mnt/Fedora/lib/modules/3.4.0 /mnt/Fedora/lib/modules/original-3.4.0
        desktop-pc$ cp -a $CHROMEOS/../modules/lib/modules/3.4.0 /mnt/Fedora/lib/modules/


It is also a good idea to check the permissions for the module files: the kernel may refuse to load a module if it has loose permissions!


        desktop-pc$ cd /mnt/Fedora/lib/modules/
        desktop-pc$ find . -type f -print0 | xargs -0 chmod 0644


Copy the kernel onto the SD card:


        desktop-pc$ cp $CHROMEOS/arch/kernel.itb /mnt/Fedora/home/guest/kernel.itb


Create a file in /mnt/Fedora/home/guest/fedora-install-kernel.sh with the following content:


        echo "console=tty1 debug verbose root=/dev/mmcblk1p3 lsm.module_locking=0 rootwait rw" > /tmp/config

        vbutil_kernel \
          --pack=/tmp/outkernel \
          --keyblock=/usr/share/vboot/devkeys/kernel.keyblock \
          --version=1 \
          --signprivate=/usr/share/vboot/devkeys/kernel_data_key.vbprivk \
          --config=/tmp/config \
          --vmlinuz=/tmp/inkernel \
        dd if=/tmp/outkernel of=/dev/mmcblk1p1
        cgpt add -i 1 -S 1 -T 5 -P 10 -l kern-fedora /dev/mmcblk1
        rm /tmp/outkernel /tmp/inkernel /tmp/config


A few things to notice:


  • /dev/mmcblk1p3 is the partition in the SD card containing the Fedora filesystem. This will be the case if you followed the instructions above,
  • The kernel option lsm.module_locking=0 tells the kernel to disable the module-locking restrictions when loading the modules,
  • The kernel is installed in the first (dedicated) partition, /dev/mmcblk1p1,


Now boot the Chromebook and open a root shell, as explained in the subsection Opening a root shell.  Once you enter the root shell, insert the SD card inside the Chromebook and do as follows:


        chromebook$ cd /tmp
        chromebook$ mount /dev/mmcblk1p3 /mnt
        chromebook$ cp /mnt/home/guest/kernel.itb inkernel
        chromebook$ cp /mnt/home/guest/fedora-install-kernel.sh .
        chromebook$ bash fedora-install-kernel.sh


The script installs the kernel inside the first partition of the SD card. If you have not done it already while installing Fedora, you will have to run the command below:


        chromebook$ crossystem dev_boot_usb=1


Now reboot:


        chromebook$ reboot


When the system comes up, open a shell and try the following:


        chromebook$ dmesg | head


You should get something like:


        dmesg | head
        [    0.000000] Booting Linux on physical CPU 0
        [    0.000000] Initializing cgroup subsys cpu
        [    0.000000] Linux version 3.4.0 (username@hostname) (gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5) ) #3 SMP Fri Mar 22 14:26:00 GMT 2013
        [    0.000000] CPU: ARMv7 Processor [410fc0f4] revision 4 (ARMv7), cr=10c5387d
        [    0.000000] CPU: PIPT / VIPT nonaliasing data cache, PIPT instruction cache
        [    0.000000] Machine: SAMSUNG EXYNOS5 (Flattened Device Tree), model: Google Snow
        [    0.000000] Ramoops: 41f00000 - 41ffffff
        [    0.000000] Memory policy: ECC disabled, Data cache writealloc
        [    0.000000] CPU EXYNOS5250 (id 0x43520010)
        [    0.000000] exynos5_init_clocks: initializing clocks


Where username@hostname is replaced with your username and hostname. This proves that you are using your own kernel. Now do check that some modules are being used:


        chromebook$ lsmod
        Module                  Size  Used by
        rfcomm                 24189  4 
        uvcvideo               62616  0 
        videobuf2_vmalloc       2941  1 uvcvideo
        mcs7830                 5683  0 
        usbnet                 14225  1 mcs7830
        isl29018                7782  0 
        joydev                  8791  0 
        industrialio           15248  1 isl29018
        btmrvl_sdio             8602  0 
        mwifiex_sdio           14642  0 
        sbs_battery             7117  0 
        mwifiex               109577  1 mwifiex_sdio
        cfg80211              167815  1 mwifiex
        btmrvl                 12715  1 btmrvl_sdio
        bluetooth             178735  22 btmrvl,rfcomm,btmrvl_sdio
        lib80211                3707  1 mwifiex
        uinput                  6922  0


Note that the modules usbnet and mcs7830 are the modules loaded to handle the USB-to-ethernet dongle. It is likely that you will not see these modules if your dongle is of a different type (different vendor or model). You should then try to identify which modules are needed for your specific hardware, as this will be useful later.


Notice also that in the dmesg log you should get a number of lines like:


        [   14.840425] Chromium OS LSM: init_module old-api-locking-ignored module= pid=1 cmdline="/init"


These indicate that the kernel module loading restriction is disabled.


Downloading and patching the Android filesystem

Get familiar with the Android build mechanisms by reading instructions at http://source.android.com/source/initializing.html, which explains how to setup your desktop machine correctly.  Also, have a look at http://source.android.com/source/downloading.html, which contains instructions explaining how to retrieve the sources (e.g. how to install the repo utility and how to use it). Once you are familiar with these instructions, checkout the Android filesystem with the following:


        desktop-pc$ mkdir -p $ANDROID && cd $ANDROID
        desktop-pc$ repo init -u https://android.googlesource.com/platform/manifest -b jb-mr1.1-dev
        desktop-pc$ repo sync


Here and in what follows I assume that $ANDROID is the directory where you want to download the Android sources.


The sync will take a while. Now apply the patches listed at http://linux-arm.org/LinuxKernel/LinuxAndroidPlatform for the "Jelly Bean MR1" release. Only apply the patches. Do not decompress the tarball given in that page, but instead use the tarball given here. After decompressing this tarball inside the device directory, the new target samsung_xe303c12 is added to the Android build system.


Next, you should patch some of the files in the Android filesystem.  Details about how to do this are given in the next sections: Adjusting the screen set up, Getting wpa_supplicant to compile and Adjusting init.rc to load extra modules and use the network.


Adjusting the screen set up

You may have to modify the Android sources in order to have Android render graphics properly. The problem is that the hardware in the Samsung Chromebook expects pixels to be in the format BGR, while Android expects to use the RGB pixel format. If this is the case, logcat will report the following in the output (log.txt) of adb logcat -d -f log.txt:


        W/SurfaceFlinger(  101): no suitable EGLConfig found, trying without EGL_FRAMEBUFFER_TARGET_ANDROID
        W/SurfaceFlinger(  101): no suitable EGLConfig found, trying without EGL_RECORDABLE_ANDROID
        W/SurfaceFlinger(  101): no suitable EGLConfig found, trying with 16-bit color allowed
        E/SurfaceFlinger(  101): no suitable EGLConfig found, giving up


Android can be hacked to use a BGR format. In the file frameworks/native/opengl/libagl/egl.cpp, locate the following code:


        static configs_t const gConfigs[] = {
           { config_0_attribute_list, NELEM(config_0_attribute_list) },
           { config_1_attribute_list, NELEM(config_1_attribute_list) },
           { config_2_attribute_list, NELEM(config_2_attribute_list) },
           { config_3_attribute_list, NELEM(config_3_attribute_list) },
           { config_4_attribute_list, NELEM(config_4_attribute_list) },
           { config_5_attribute_list, NELEM(config_5_attribute_list) },
           { config_6_attribute_list, NELEM(config_6_attribute_list) },
           { config_7_attribute_list, NELEM(config_7_attribute_list) },


Add a new entry at the end of the table:


          { config_8_attribute_list, NELEM(config_8_attribute_list) },


Place the code below just before the definition of the gConfigs[] table to define the new pixel format:


          /* 32-bit BGRA */
          static config_pair_t const config_8_attribute_list[] = {
             { EGL_BUFFER_SIZE,     32 },
             { EGL_ALPHA_SIZE,       8 },
             { EGL_BLUE_SIZE,        8 },
             { EGL_GREEN_SIZE,       8 },
             { EGL_RED_SIZE,         8 },
             { EGL_DEPTH_SIZE,       0 },
             { EGL_CONFIG_ID,        2 },


This entry was basically copied from config_4_attribute_list, with the difference that GGL_PIXEL_FORMAT_RGBA_8888 is replaced with GGL_PIXEL_FORMAT_BGRA_8888 (EGL_NATIVE_VISUAL_ID attribute). With this changes, logcat should give:


        W/SurfaceFlinger(   99): no suitable EGLConfig found, trying without EGL_FRAMEBUFFER_TARGET_ANDROID
        W/SurfaceFlinger(   99): no suitable EGLConfig found, trying without EGL_RECORDABLE_ANDROID
        W/SurfaceFlinger(   99): EGL_SLOW_CONFIG selected!


This fix was inspired by http://comments.gmane.org/gmane.comp.handhelds.android.porting/521 and https://groups.google.com/forum/?fromgroups=#!topic/android-porting/rSttzZE9SBo.


Getting wpa_supplicant to compile

You should patch the file $ANDROID/external/wpa_supplicant_8/wpa_supplicant/src/drivers/driver_nl80211.c, or otherwise you may get a link error while building the Android filesystem. You should comment the line which sets the field driver_cmd, as shown below:

        //.driver_cmd = wpa_driver_nl80211_driver_cmd,


This change will disable some features of wpa_supplicant, but should not prevent the wireless from working.


Adjusting init.rc to load extra modules and use the network

The Samsung Chromebook does not have an ethernet port. If you need to connect to the internet you can use the built-in wireless. If wireless is not available, however, you may want to use an USB-to-ethernet dongle. In this section, I explain how to set this up.

Android boot can be customised through the init.rc file placed at the top of the Android filesystem. You can find information about the syntax of rc files following the link https://android.googlesource.com/platform/system/core/+/master/init/readme.txt.


The init.rc produced for PRODUCT-samsung_xe303c12-eng has been partially tailored for the Samsung Chromebook. In particular, there are a number of modules which are loaded in the kernel using the insmod command. You should add some additional lines for your USB-to-ethernet dongle. The required modules can be determined by inspecting the output of lsmod in Fedora or ChromeOS: boot without the dongle, type lsmod, connect the dongle, wait 5 seconds, retype lsmod and take note of which additional modules were loaded after the dongle was inserted.


In my case I had to add two insmod commands:


              insmod /system/lib/modules/kernel/net/ipv6/netfilter/nf_conntrack_ipv6.ko
              insmod /system/lib/modules/kernel/net/netfilter/xt_mark.ko

          # The two lines below are the ones I had to add for my dongle:
              insmod /system/lib/modules/kernel/drivers/net/usb/usbnet.ko
              insmod /system/lib/modules/kernel/drivers/net/usb/mcs7830.ko
              #wait /nonexistentfile 60


The last line is commented, but you may want to uncomment it in order to pause Android for 60 seconds while it loads the modules. This may give you a possibility of seeing if the modules are loaded correctly. Note that getting the network setup right is rather important, as it allows using adb (the Android Debugging Bridge) which — in turn — allows debugging other issues the system may have.


To enable the wired ethernet, define a service by adding the following lines to the end of init.rc:


        service wired-ethernet /system/bin/netcfg eth0 dhcp


Next, tell Android to start the service on boot by adding the following to the end of the "on boot" section:

        start wired-ethernet


This line should follow the lines:


        class_start core
        class_start main


Building the Android filesystem

Build the sources as follows:


        desktop-pc$ cd $ANDROID
        desktop-pc$ source build/envsetup.sh
        desktop-pc$ make -j8 PRODUCT-samsung_xe303c12-eng


The output of the compilation is placed inside the directory $ANDROID/out/target/product/samsung_xe303c12/.  In particular, this directory contains two directories: root and system. These contain the files which — in the Android device — will be seen at the locations / and /system respectively.


Transferring the Android filesystem to the SD card

I here assume the partition of the SD card which is going to contain the Android filesystem has been mounted in /mnt/Android. Copy the Android filesystem you obtained in the section Building the Android filesystem onto the SD card:


        desktop-pc$ cp -a $ANDROID/out/target/product/samsung_xe303c12/root/* /mnt/Android
        desktop-pc$ cp -a $ANDROID/out/target/product/samsung_xe303c12/system/* /mnt/Android/system


Copy the firmware and modules directory from the Fedora partition:


        desktop-pc$ mkdir -p /mnt/Android/system/lib/modules
        desktop-pc$ cp -a /mnt/Fedora/lib/modules/3.4.0/* /mnt/Android/system/lib/modules/
        desktop-pc$ mkdir -p /mnt/Android/system/etc/firmware/
        desktop-pc$ cp -a /mnt/Fedora/lib/firmware/* /mnt/Android/system/etc/firmware/


Remember that the firmware directory was taken directly from the Chromebook.


You may also have to change the permission of the prop and rc files so that they can be written only by the owner:


        desktop-pc$ find /mnt/Android \( -name "*.prop" -o -name "*.rc" \) -print0 | xargs -0 chmod 0644


Check that the permissions of the module files are right; they should be, if you followed the instructions. If not:


        desktop-pc$ cd /mnt/Android/system/lib/modules
        desktop-pc$ find . -type f -print0 | xargs -0 chmod 0644


Now we need to setup the SD card so that Android is booted. Similarly to what was done in section Using the compiled kernel and modules with Fedora, create a file in /mnt/Fedora/home/guest/android-install-kernel.sh with the following content:


        echo "console=tty1 debug verbose root=/dev/mmcblk1p4 lsm.module_locking=0 init=/init rootwait rw" > /tmp/config

        vbutil_kernel \
          --pack=/tmp/outkernel \
          --keyblock=/usr/share/vboot/devkeys/kernel.keyblock \
          --version=1 \
          --signprivate=/usr/share/vboot/devkeys/kernel_data_key.vbprivk \
          --config=/tmp/config \
          --vmlinuz=/tmp/inkernel \
        dd if=/tmp/outkernel of=/dev/mmcblk1p2
        cgpt add -i 2 -S 1 -T 5 -P 15 -l kern-android /dev/mmcblk1
        rm /tmp/outkernel /tmp/inkernel /tmp/config


Make sure that the file kernel.itb is present in the directory /mnt/Fedora/home/guest/; it should be the case if you followed the instructions in section Using the compiled kernel and modules with Fedora.


Notice the init=/init option which tells the kernel to pass control to the init executable at the top directory in the Android filesystem. Similarly to what done for Fedora, boot the Chromebook and open a root shell. Once you enter the root shell, insert the SD card inside the Chromebook and do as follows:


        chromebook$ cd /tmp
        chromebook$ mount /dev/mmcblk1p3 /mnt
        chromebook$ cp /mnt/home/guest/kernel.itb inkernel
        chromebook$ cp /mnt/home/guest/android-install-kernel.sh .
        chromebook$ bash android-install-kernel.sh


The script installs the kernel inside the second partition of the SD card. It gives to this kernel priority 15, which is higher than the priority currently assigned to the Fedora kernel in partition /dev/mmcblk1p3 and is hence selected by the bootloader at boot. This means that, from now on, Android is booted rather than Fedora. In section Switching back to Fedora I explain how to change the priorities so that Fedora is booted again.


Next, type reboot to reboot the system and press CTRL+U at the white boot screen to trigger boot from SD card.


        chromebook$ reboot


Android should come up. It may take several minutes.  Graphics, keyboard, touchpad and wireless should all work.


Tips and tricks

I recommend to go to "Settings" and on the left menu scroll down (you can use the down arrow) and select "{} Developer options". On the right there is a checkbox "Stay awake" that you can tick in order to stop the device to go to standby.


Keep in mind that to turn off Android you can just press the power button and keep it pressed for a couple of seconds.


The wireless can be activated by clicking on the wireless symbol on the toolbox, which also contains other buttons for bluetooth, etc.  Wait a minute and Android should automatically detect the wireless and give you the chance of setting it up. Settings should be remembered in future boots.



Debugging Android can be a nightmare when adb is not available; you cannot easily open a shell or configure the system easily. The first thing to do is then to get the network to work, so that adb can be used. If the network is not working, then you may want to add the following two lines to your init.rc file:


        service logstuff /system/bin/logcat -f /mylogstuff


You can then start the service with


        start logstuff


This line starts the Android logging service and redirects its output to the file mylogstuff at the top of the Android filesystem. You can then boot your system, turn it off, take the SD card from the Chromebook and insert it in your PC to inspect the content of the file mylogstuff.


Using lines like:


        wait /filethatdoesnotexist {number of seconds}


Can also be handy to slow down the system while loading the modules so that you can see the output of these commands. Certainly not orthodox nor beautiful, but handy...


Checking that ADB works

In order to start the Android Debug Bridge, you can use the command below:


        desktop-pc$ adb kill-server
        desktop-pc$ ADBHOST=AAA.BBB.CCC.DDD adb devices


Where AAA.BBB.CCC.DDD is the IP address of the Android device. One way of getting the IP of your device (which works well if the device is connected to the same switch/router as your desktop PC) is to do as follows:


        desktop-pc$ sudo tcpdump -n -i eth0 'tcp port 54321'


This shows on the screen of your PC all the packets arriving-to/departing-from port 54321 on your desktop PC. You can then open the browser in the Android device and use as URL the IP address of your computer. For example, if your desktop PC has IP address (try ifconfig) XXX.YYY.ZZZ.WWW then enter as URL in the Android browser "XXX.YYY.ZZZ.WWW:54321" and press ENTER. tcpdump should show a line like:


        15:42:04.188811 IP AAA.BBB.CCC.DDD.51734 > XXX.YYY.ZZZ.WWW.54321: Flags
         [S], seq 3681918437, win 14600, options [mss 1460,sackOK,TS val 290000
         ecr 0,nop,wscale 7], length 0


Where AAA.BBB.CCC.DDD is the IP address of your device. You can now use this address as a value for ADBHOSTadb devices should then find your Android device:


        desktop-pc$ ADBHOST=... adb devices
        * daemon not running. starting it now on port 5037 *
        * daemon started successfully *
        List of devices attached
        emulator-5554   device


You can now use adb. For example,


  • adb shell allows to login inside the device,
  • adb shell logcat -d allows to see the log messages,
  • adb help explains how to use adb.


Opening a root terminal in Android

Download a terminal emulator app. For example, Jack Palevich's terminal emulator app.  Install it remotely from your host using adb:


        desktop-pc$ adb install Term.apk
        desktop-pc$ adb shell # this opens a remote root shell
        adb-shell# cd /system/bin
        adb-shell# cp mksh mysh
        adb-shell# chown root:root mysh
        adb-shell# chmod 4775 mysh
        adb-shell# exit


Now open the terminal emulator app from the Chromebook and type /system/bin/mysh. You should now have root priviledges.


mysh is a copy of the default shell mksh which belongs to root, can be executed by everybody and has the setuid flag set.  The latter permission setting, in particular, means that whoever executes this executable will be treated as the root user. Remember to delete this file once you do not need it anymore, as it clearly represents a serious security hole (unauthenticated root access).


Switching back to Fedora

To switch back to Fedora you can use the cgpt utility.  From the ChromeOS shell, try cgpt show /dev/mmcblk1. This command should show a list of partitions with details about which kernel is installed in which partition, including the boot priorities.  To induce the bootloader to select the Fedora kernel, just type cgpt add -i 2 -P 5 /dev/mmcblk1. This command should reduce the priority of the Android kernel to 5, which is lower than the priority of the Fedora kernel (previously set to 10). On the next reboot, Fedora should come up.



This guide should allow you to boot Android on your Chromebook. You should be able to use it for browsing the web and run some apps. There are a number improvements that could be done to the system to provide a better user experience: audio, codecs for playing videos (e.g. YouTube), bluetooth support, tailored menus and configuration, security, etc.  All these improvements, including the release and maintainance of binary images, are outside the scope of this guide and are left to the good will of generous volunteers in the open source community.


Further reading

This content was initially posted 14 February 2013 on blogs.arm.com


Indoo.rs recently entered into a partnership with ARM, the awesome producer of processor intellectual property (IP). Why is this significant? Let me start from the beginning:


We have explained some of the technical challenges in providing real-time, accurate indoor localization in a previous post. Most good indoor localization solutions these days use a hybridized approach (WiFi fingerprinting + inertial navigation seem to be a popular option) to achieve the required accuracy and speed; and a good solution must deal with lots of entropy, but remain fast and accurate. The best way is to use any and all available sensor data, and an inertial navigation model, and then add predictive filtering while conserving device resources, such as battery power. Device manufacturers’ battery allocation for indoor location services is challengingly small.


In order to deal with all the entropy our application uses an improved variant of something called a Kalman filter, an algorithm that has been very useful over the past couple of decades in bleeding edge navigation and robotics applications (such as the Mars Rover), where a lot of noisy input is combined with a system’s dynamic models (e.g. an inertial navigation algorithm) to produce an increasingly accurate predictive model of movement and location. The Kalman filter is a set of recursive equations, and, in our case, involves a lot of tricky vector and matrix operations: a typical example has our applying a probability or confidence vector to a set of sensor inputs. This can be taxing on system resources, especially when the key requirement is real-time, accurate location using multi-sensor inputs.


This is where ARM comes to the rescue. We really like ARM’s NEON™ SIMD engine (SIMD – Single Instruction, Multiple Data - means a single instruction applied to multiple data points. Imagine a probabilistic operation applied to a large set of sensor input). We really, really like NEON. But this became full blown obsessive love when we started using ARM’s Project Ne10 library, which optimizes matrix and vector operations. Our predictions now go much faster. And our app consumes far less power. There is no trade-off (…no extra RAM requirements, nothing. I swear: we checked the fine print). It’s just amazingly wonderful. And it’s free from this Github repository!


Ne10 works like a ‘convenience wrapper’, and handles really useful things like vectorization residuals. It makes much more efficient use of CPU cycles. We see a 5x speed gain on common operations, and over the long run (we are still tuning, but initial results are awesome), we’ll see significant improvement in power consumption at the same time.


Previously, we benchmarked the performance of our indoor localization solution against competitors, (and so have Google). We were ~20% better across the board in terms of speed and accuracy before optimizing with Ne10. Now, thanks to ARM, we are significantly extending that lead.


Guest Blogger:

erikbovee.jpgErik Bovee, VP Business Development, indoo.rs, Erik has held senior operational and strategic roles since 1999 in a number of telecoms and internet companies, both startups & publicly listed companies. Erik was responsible for VeriSign Mobile Enterprise Services (VMES), a global, mobile messaging aggregation service, in addition to Enterprise Paging, a multi-protocol mediation service for wireless carriers. Prior to joining VMES, Erik was European Managing Director of eMeta Corporation, a provider of access control and digital licensing software for online publishers and financial services.