Custom ROM Build

Building a ROM with AGA Build Script

It is recommended to run the AGA custom ROM build as a non-root user. The build script shall be seen as a template that is to be modified for your architecture and dependencies.

The script is tested on Ubuntu 12.04 LTS 64-bit environment with the non-root user aga.

AGA Build Script and ROMs

Build environment and porting

Automotive Grade Android is a small addition to the standard Android system. It hooks in as a separate service that handles vehicle data and permissions. For this new service to start at system boot one has to add startup code to the standard Android platform.

To help out with this the AGA community provides a build script that can be modified and run to create a build for the Android version that your system uses. The shell script is located in the scripts repository on the AGA git server and named 442 in the filename refers to the Android version that the build script targeted during development. To support other Android version you probably have to make small adjustments to the script.

Shell script consists of a few stages:

  1. Main function
    To run the script one has to provide an argument stating the hardware platform for the build to target. Here you most likely want to add your own branch for the specific hardware target you are developing.
  2. Check prerequisites
    A check is made on the executing system to verify that all dependencies for the build is satisfied.
  3. Download Android source
    For development the source code when building AGA is provided by Android Open Source Community and is downloaded in this step. Most probably you have a version provided to you from the hardware supplier containing drivers and modifications to vanilla Android.
  4. Setup environment
    Configure the build environment.
  5. Explode AGA jar files
    Download the AGA sources and adds these to the Android source tree.
  6. Explode proprietary binaries
    Downloads any proprietary binaries needed for the hardware platform to fully function. Many binaries does not fall in the open source category and will be provided as pre-built binaries. You can add the needed ones in this step.
  7. Explode AGA service
    Download the AGA service and applies it to the Android service startup sequence. This is the part of the build script that is most likely to change with new versions of Android. The hooks is added using sed and you will have to verify that the grep and sed arguments is still valid for the new Android version.
  8. Add media
    During development we added an extra step where it is intended to add build specific artwork such as boot screen, launcher backgrounds or other media.
  9. Execute build
    Perform the actual build.
  10. Create image zip
    The final step will package the result into a zip file that can be deployed to hardware.

Here is an example of a modification for the explode AGA service step for patching Ice Cream Sandwich (4.0.3) that can be compared to the default implementation in the scripts repo.

explodeAgaService() {
    cd ${BUILD_DIRECTORY}/frameworks/base/core/java
    if ! ${WGET} -O "lib.jar" "$1/lib.jar" ; then
        echo "unable to download lib.jar, version $1"
        rm -f "lib.jar"
        exit 255
    ${JAR} xf "lib.jar"
    rm -f "lib.jar"

    mkdir -p ${BUILD_DIRECTORY}/frameworks/base/core/java/android/swedspot/automotive/tmp
    cd ${BUILD_DIRECTORY}/frameworks/base/core/java/android/swedspot/automotive/tmp
    if ! ${WGET} -O "lib.aar" "$1/lib.aar" ; then
        echo "unable to download lib.aar, version $1"
        rm -f "lib.aar"
        exit 255
    ${JAR} xf "lib.aar"
    cp aidl/android/swedspot/automotive/* ${BUILD_DIRECTORY}/frameworks/base/core/java/android/swedspot/automotive
    cd ..
    rm -fr tmp

    if ! grep -q AUTOMOTIVE_SERVICE ${BUILD_DIRECTORY}/frameworks/base/core/java/android/content/
        ${SED} -i 's/^.*public static final String USB_SERVICE = "usb";$/    public static final String USB_SERVICE = "usb";\n\n    public static final String AUTOMOTIVE_SERVICE = "automotive";/' ${BUILD_DIRECTORY}/frameworks/base/core/java/android/content/

    if ! grep -q AutomotiveService ${BUILD_DIRECTORY}/frameworks/base/services/java/com/android/server/
        ${SED} -i 's/^.*package;.*$/package;\n\nimport android.swedspot.automotive.AutomotiveService;\n/' ${BUILD_DIRECTORY}/frameworks/base/services/java/com/android/server/
        # Change hook from consumerIr to usbService
        ${SED} -i 's/^.*UsbService usb = null;.*$/        UsbService usb = null;\n        AutomotiveService automotiveService = null;\n/' ${BUILD_DIRECTORY}/frameworks/base/services/java/com/android/server/

        # Change hook from Consumer IR Service to Vibrator Service    
        ${SED} -i 's/^.*ServiceManager.addService("vibrator", new VibratorService(context));.*$/            ServiceManager.addService("vibrator", new VibratorService(context));\n\n            Slog.i(TAG, "Automotive Service");\n            automotiveService = new AutomotiveService(context);\n            ServiceManager.addService(Context.AUTOMOTIVE_SERVICE, automotiveService);\n            automotiveService.startAutomotiveService();\n/' ${BUILD_DIRECTORY}/frameworks/base/services/java/com/android/server/

    if ! grep -q Automotive ${BUILD_DIRECTORY}/frameworks/base/
        ${SED} -i 's/^.*core\/java\/com\/android\/internal\/widget\/IRemoteViewsAdapterConnection.aidl \\\.*$/        core\/java\/com\/android\/internal\/widget\/IRemoteViewsAdapterConnection.aidl \\\n        core\/java\/android\/swedspot\/automotive\/IAutomotiveListener.aidl \\\n        core\/java\/android\/swedspot\/automotive\/IAutomotiveService.aidl \\/' ${BUILD_DIRECTORY}/frameworks/base/

    if ! grep -q AutomotiveService ${BUILD_DIRECTORY}/frameworks/base/core/java/android/app/
        ${SED} -i 's/\(^.*package;.*$\)/\1\n\nimport android.swedspot.automotive.AutomotiveManager;\nimport android.swedspot.automotive.IAutomotiveService;\n/' ${BUILD_DIRECTORY}/frameworks/base/core/java/android/app/
        ${SED} -i 's/^.*registerService(AUDIO_SERVICE, new ServiceFetcher().*$/        registerService(AUTOMOTIVE_SERVICE, new ServiceFetcher() {\n                public Object createService(ContextImpl ctx) {\n                        IBinder b = ServiceManager.getService(AUTOMOTIVE_SERVICE);\n                        IAutomotiveService service = IAutomotiveService.Stub.asInterface(b);\n                        return new AutomotiveManager(service, ctx);\n        }}\);\n\n        registerService(AUDIO_SERVICE, new ServiceFetcher() {/' ${BUILD_DIRECTORY}/frameworks/base/core/java/android/app/

Flashing the device with a custom AGA ROM

To flash the device, put the device in boot mode with volume down + volume up + power (this applies to Nexus 10) and do:

fastboot devices
fastboot -w update
It should look like:
$ fastboot devices
R32D103PJQK     fastboot

$ fastboot -w update
Creating filesystem with parameters:
    Size: 14273216512
    Block size: 4096
    Blocks per group: 32768
    Inodes per group: 8144
    Inode size: 256
    Journal blocks: 32768
    Blocks: 3484672
    Block groups: 107
    Reserved block group size: 855
Created filesystem with 11/871408 inodes and 96018/3484672 blocks
Creating filesystem with parameters:
    Size: 553648128
    Block size: 4096
    Blocks per group: 32768
    Inodes per group: 6768
    Inode size: 256
    Journal blocks: 2112
    Blocks: 135168
    Block groups: 5
    Reserved block group size: 39
Created filesystem with 11/33840 inodes and 4363/135168 blocks
archive does not contain 'boot.sig'
archive does not contain 'recovery.sig'
archive does not contain 'system.sig'
Bootloader Version...: MANTAMF01
Baseband Version.....: no modem
Serial Number........: R32D103PJQK
checking product...
OKAY [  0.002s]
sending 'boot' (4786 KB)...
OKAY [  0.601s]
writing 'boot'...
OKAY [  0.144s]
sending 'recovery' (5336 KB)...
OKAY [  0.670s]
writing 'recovery'...
OKAY [  0.144s]
erasing 'system'...
OKAY [  0.035s]
sending 'system' (268161 KB)...
OKAY [ 33.691s]
writing 'system'...
OKAY [  8.934s]
erasing 'userdata'...
OKAY [  0.236s]
formatting 'userdata' partition...
sending 'userdata' (137478 KB)...
writing 'userdata'...
OKAY [ 21.701s]
erasing 'cache'...
OKAY [  0.042s]
formatting 'cache' partition...
sending 'cache' (10372 KB)...
writing 'cache'...
OKAY [  1.633s]

finished. total time: 67.839s

After a flash, the About should display something like: