0x20


A blog about mobile, maker, and embedded development.


Working With the AOSP Framework

This is a living blog post with tips and tricks for developing within the Android Open Source Project’s framework.

What is "the Android Framework"? In short; it is the layer of Android that defines APIs, services, and environments for Android applications. For a better explanation you should see AOSP’s description.

Note that this post starts with the assumption that you already have a working Android build, have sourced build/envsetup.sh and have lunched. The best place to get help with this is the AOSP Downloading and Building documentation.

Iterating Within the Java Framework

In a Nutshell

#!/usr/bin/env bash

# source this script. For example:
# > . iterate.sh

# build the framework module
mmm frameworks/base || return

# ensure adb is running as root
adb root;

# make the system partition on the device writeable
adb remount;

# synchronize files between the local system folder under
# out/target/product/<device>/system and the device's system partition
adb sync;

# restart the framework
adb shell stop;
adb shell start;

The Android framework module is built by the frameworks/base/Android.mk makefile. In AOSP mm builds the module for the current directory and mmm <dir> builds the module in <dir> (or in a list of dirs).

ProTip: elinux.org’s wiki is a good cheatsheet

You’ll need a rooted device to iterate on the framework without having to flash the entire system each time. This is because the adb sync command is copying just the parts of the framework you have rebuilt to the device’s /system partition. For the Java framework this will be out/target/product/<device name>/system/framework/framework.jar.

Alternative System Build

It’s worth mentioning that there’s an alternative way to get a system image which contains a java framework onto a device. Once you’ve run the mmm part of the build and have the build intermediates you want to get onto a device you can run

make snod

which stands for "Make System with No Dependencies". This simply packages up whatever is in the out folder into a new system image. You can then reboot fastboot and fastboot flash system to install the entire system image onto a connected device.

Careful here though, if this is the first time you are flashing a device from your local build you’ll want to do a full build/flash or your device may get into the infamous infinite app optimization and reboot. See the Android Open Source Project’s docs for full details on building AOSP and get past the point where you:

fastboot flashall

before starting to use make snod or adb sync.

Being System

The signature and signatureOrSystem protection levels become more important when developing for the Android application framework. That said, don’t define systemOrSignature permissions unless you understand the ramifications doing so has for your Android distribution (I’ll have to write a follow up post some day about this). For the signature level, the framework itself is signed using a key that establishes a signature defining what packages belong to the system and what packages are from another source (i.e. "downloaded"). Because of this your package will have to have the same signature as the framework to obtain signature level permissions defined by the system.

Under build/target/product/security you’ll see several keys that sign various parts of the system. We’re mostly concerned with the platform key when working with the application framework.

To create an application keystore with the same signature as the application framework build you’ll need to create a java keystore that contains the platform key and certificate found the build. To do this you’ll need two things: the JDK’s keytool executable and openssl. Once you have these on your path, have a working AOSP build, and an Android application development environment you can create a new debug keystore like so:

openssl pkcs8 \
        -in build/target/product/security/platform.pk8 \
        -inform DER \
        -nocrypt \
        -out platform.pem;

openssl pkcs12 -export \
        -in build/target/product/security/platform.x509.pem \
        -out platform.p12 \
        -inkey platform.pem \
        -password pass:android \
        -name androiddebugkey;

keytool -importkeystore \
        -deststorepass android \
        -destkeystore platform.jks \
        -srckeystore ./platform.p12 \
        -srcstoretype PKCS12 \
        -srcstorepass android;

You can check that this is a valid keystore using keytool:

keytool -list -keystore platform.jks

Enter keystore password:
> android

Now all you have to do is either point your app build to use this keystore or replace your randomly generated debug keystore with this one:

mv platform.jks ~/.android/debug.keystore

If you’ve already installed an application package and get an Application Installation Failed, INSTALL_FAILED_UPDATE_INCOMPATIBLE error this is because the signature has changed. Uninstall the package and you should be able to install the version with the new signature without further errors.

Free Rein

WARNING This hack disables critical security measures in Android. Don’t install any real user accounts on a development device running this hack.

Sometimes you want to test integration with apps that are production signed and limit access to certain activities by signature. If production signing your development app is too much of a burden you can just disable the signature check. In Lollipop this was found in ActivityStackSupervisor.java:1430. By commenting out the real security check and always reporting PERMISSION_GRANTED you can start any Activity you want on your hacked system regardless of signatures:

-        final int startAnyPerm = mService.checkPermission(
-                START_ANY_ACTIVITY, callingPid, callingUid);
-        final int componentPerm = mService.checkComponentPermission(aInfo.permission, callingPid,
-                callingUid, aInfo.applicationInfo.uid, aInfo.exported);
+        final int startAnyPerm = PERMISSION_GRANTED;
+        //mService.checkPermission(
+        //        START_ANY_ACTIVITY, callingPid, callingUid);
+        final int componentPerm = PERMISSION_GRANTED;
+        //mService.checkComponentPermission(aInfo.permission, callingPid,
+        //        callingUid, aInfo.applicationInfo.uid, aInfo.exported);

Tools

Here are some resources that you’ll find useful while hacking AOSP:

AndroidXREF – Online OpenGrok index of the full AOSP codebase organized by release branch. This resource is invaluable for developing AOSP and applications. Frankly the existence of this site is one of the key benefits of Android over iOS for developers. There’s no scouring docs and trying to reverse engineer strange behaviours. You just go to the source and you know exactly what the problem is. done.

AndroidXREF screenshot

App Detective – A useful app for enumerating all the activities, services, providers, permissions, etc available on a system. This can help with building rich integrations with other popular apps.

App Detective Icon