Android Cookbook: AOSP Custom ROM Building 201

Disclaimer [2013 Dec 11]

The following sections were developed approximately a year ago on Jellybean. In that time we have had multiple versions of AOSP and the processes have likely changed. The processes (recipes) listed below are relatively close, but need to be validated / updated. That is expected to happen before the end of the calendar year. So the message is that these recipes are not complete accurate and if you use them, expect some frustration – tomwwolf

How to build a Custom Device Emulator Image

Overview

The easiest path to developing a custom ROM image is to develop a workflow that can be validated quickly, easily and often. In the world of AOSP this means doing initial development in the Android Emulator image first and then migrating it to the device. The first step in this workflow is building a custom emulator image that parallels how we would do this for a device.

In the process below we show how to build an emulator image using the AOSP device tree. The process (at a high level) is as follows:

Process

  1. Create a directory under ‘device’ with the [company]/[product] structure. For example ‘mkdir –p umlaut/alpha’.
  2. Create a file ‘Android.mk’ with the following contents:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
include $(call all-makefiles-under,$(LOCAL_PATH))
  1. Create a file ‘AndroidProducts.mk’ with the following contents:
PRODUCT_MAKEFILES := \
$(LOCAL_DIR)/alpha.mk
  1. Create a file ‘vendorsetup.sh’ with the following contents:
add_lunch_combo alpha-eng
  1. Create a file named ‘common.mk’ with the following contents:
UMLAUT_COMMON := device/umlaut/common
DEVICE_PACKAGE_OVERLAYS :=
PRODUCT_PACKAGES +=
PRODUCT_COPY_FILES +=
  1. Create a file ‘alpha.mk’ (same as directory name) with the following contents:
$(call inherit-product, device/umlaut/alpha/common.mk)
$(call inherit-product,$(SRC_TARGET_DIR)/product/sdk.mk)

PRODUCT_NAME := alpha
PRODUCT_DEVICE := alpha
PRODUCT_MODEL := alpha_model
PRODUCT_BRAND := umlaut_brand
PRODUCT_MANUFACTURER := umlaut
  1. Copy from ‘build/target/board/generic/BoardConfig.mk to the ‘device/umlaut/alpha’ directory.
  2. Change directory to the root of you AOSP build directory, and enter:
. build/envsetup.sh
lunch
  1. Select ‘alpha-eng’ from the options. If this option is not available, review the steps above.
make –j16
emulator
  1. This should launch the default android emulator with a reduced subset of applications. This is not a minimal set of applications, but the minimal configuration to create a custom emulator image.

References

How to build an Full Device Emulator Image

Overview

This process defines how to take the default image defined in the process above and add AOSP modules to the build. AOSP application packages are located in the ‘packages/apps’ directory. Some of the other directories under ‘packages’ also contain some interesting modules, but are generally do not have a user interface.

Note: Buildable modules are identified by opening the Android.mk file within each build directory and finding the tag ‘LOCAL_MODULE’. Examples include ‘external/ping’ and ‘external/ping6’ which are named to match their directories. Most other modules under external do not match the module name with the directory name.

Process

  1. Clone the minimal configuration emulator device: Assuming you already have a directory in our AOSP build named ‘device/umlaut/alpha’, enter the following from the root of your AOSP build tree.
mkdir –p device/umlaut/beta
cp device/umlaut/alpha/* device/umlaut/beta/.
cd device/umlaut/beta
mv alpha.mk beta.mk
  1. Edit ‘AndroidProducts.mk’ and change ‘alpha.mk’ to ‘beta.mk’. Save and exit.
  2. Edit ‘vendorsetup.sh’ and change ‘alpha-eng’ to ‘beta-eng’. Save and exit.
  3. Edit ‘beta.mk’ and change all references to ‘alpha’ to ‘beta’. Save and exit.
  4. These steps essentially clone the minimal configuration from the steps above.
  5. From the ‘device/umlaut/beta’ directory, edit the ‘common.mk’ file to the following:
UMLAUT_COMMON := device/umlaut/common
PRODUCT_POLICY := android.policy_mid

PRODUCT_PACKAGES += \
   Calendar \
   Contacts \
PRODUCT_COPY_FILES += /
  1. We will then build with the following:
. build/envsetup.sh
make clobber
lunch beta-eng
make –j16
emulator
  1. Confirm that the following apps are present on the emulator image:
Calendar
Contacts

References

  • none

How to build BusyBox / su / Superuser in ROM for Android

Overview

This process defines how to integrate Busybox, su, and the Superuser app into the AOSP build tree for Android.  This is going to be an end to end process, and we are going to borrow the Android packaged sources from the CyanogenMod project.

Cyanogenmod (CM) is a project based on AOSP, but with significant modifications, and a very complete and mature source tree. In order to effectively use the CM sources we will likely need to explore the repository at https://github.com/CyanogenMod  and determine some important information. In the scripts below, we are building on the AOSP 4.2 tree, and this aligns with the cm10.1 revision. However your mileage may vary, and it is important to know how to get the correct matchup.

To demonstrate, open a browser to the CM repository and search on ‘android_external_busybox’, and select the one result. Somewhere on the page there will be a drop down that lists the ‘branches’ available, and one (or more) of these will correspond to the version of AOSP you are building. The branch name on the repository and the revision name in the local_manifest.xml file are the same. In order to know which branch corresponds with the version of AOSP you are using, it will require some exploration at the CM website.

The corresponding site for the AOKP repository is https://github.com/AOKP .

Process

  1. From the source directory, navigate to the ‘.repo’ directory and create a file ‘local_manifest.xml’ with the following contents.
<?xml version="1.0" encoding="UTF-8"?>
<manifest>
<remote  name="cm"
fetch="https://github.com/CyanogenMod/"
review="review.cyanogenmod.com" />
<project path="external/busybox" name="android_external_busybox" remote="cm" revision="cm10.1" />
<project path="packages/apps/Superuser" name="android_packages_apps_Superuser" remote="cm" revision="cm10.1"/>
<project path="system/su" name="android_system_su" remote="cm" revision="cm10.1" />
</manifest>
  1. This will create repo tags for the three identified packages; busybox, SuperUser, and su. Pull the three new packages into the build tree:
repo sync
  1. Confirm that these three packages have been downloaded to the respective locations in the build tree. Check the following directories:
external/busybox
system/su
packages/apps/SuperUser
  1. This will also require that we delete the existing ‘su’ package from AOSP.
cd system/extras
 rm –rf su
  1. Next we create a shell file that links the new binaries into the OS at startup.
cd device/umlaut
 mkdir –p common/etc
 cd common/etc
vim 91-busybox_linkage.sh
<contents>
for cmd in $(busybox --list);do ln -s /system/xbin/$cmd $cmd; done; ln -s /system/xbin/su su;
<save/exit>
chmod 777 91-busybox_linkage.sh
  1.  Then we update our ‘beta’ build to include the piece parts.
  2. cd device/umlaut/beta
    vim common.mk
  3. Edit this file to look like this:
UMLAUT_COMMON := device/umlaut/common
PRODUCT_POLICY := android.policy_mid
DEVICE_PACKAGE_OVERLAYS :=
PRODUCT_PACKAGES += Superuser
PRODUCT_COPY_FILES += \
$(UMLAUT_COMMON)/etc/91-busybox_linkage.sh:system/etc/init.d/91-busybox_linkage.sh
  1. Lastly we need to get the CM certificates. For CM10.1, the certs are found at:
    1. https://github.com/CyanogenMod/android_build/blob/cm-10.1/target/product/security/superuser.x509.pem
    2. https://github.com/CyanogenMod/android_build/blob/cm-10.1/target/product/security/superuser.pk8
    3. The process is to go to each of those pages, and change the branch to match the version used in the local_manifest.xml file. Then download those two files and copy to the ‘build/target/product/security’ directory.
    4. We will then build with the following:
. build/envsetup.sh
make clobber
lunch beta-eng
make –j16
emulator
  1. Confirm that the Superuser app is in the build (and works).

References

How to build a Device Emulator Image: Deodexed [testready]

Overview

A very commonly used term in the context of AOSP ROMs is ‘deodexed’.  When an AOSP image is created, a significant amount of the OS is built from Java, and compiled into a Dalvik Executable – a form of pseudocode that runs on the Dalvik VM, identified as a ‘.dex’ file. An ‘.odex’ file is similar to a ‘.dex’ file, but is precompiled and optimized for the platform. AOSP Image files will either be ‘odexed’ or ‘deodexed’, with most factory images ‘odexed’. The distinction is that at boot time, the OS scans the installed applications, and preloads optimized Dalvik executables in the cache. If the image is ‘odexed’ the OS simply grabs that file, and if the image is ‘deodexed’ (lacking the odex files), the OS will build the odex files on the fly and populate the cache.

There are a few side effects of an ‘odexed’ image. The first is that if the cache is cleared due to user action or flashing a new image, the cache is repopulated more quickly. However this only occurs if the cache is cleared, and on any other reboot it has no effect. The second effect is that if you modify the contents of an application or the frameworks,  it may not have any effect on the system since the system is relying on the odex file. It is this second reason why most developers use deodexed images.

Interestingly, Google also recognized that there are times when each structure provides advantages. In the AOSP build process, ‘user’ builds are by default odexed, and ‘eng’ or ‘debug’ builds are deodexed. Additionally this can be forced with a few environment variables, and that is shown below.

Process

  1. Enter your AOSP directory
make clobber
. build/envsetup.sh
lunch
  1. Select your build of choice. An emulator would be a good choice for validating this method.
  2. (method 1) a deodexed build can be forced by:
export DISABLE_DEXPREOPT=true
export WITH_DEXPREOPT=false
make –j16
  1. (method 2) a deodexed build can also be forced by:
make DISABLE_DEXPREOPT=true WITH_DEXPREOPT=false –j16
emulator

Validation

  1. After the emulator is fully booted:
adb shell
cd /system/app
ls *.odex
  1. The presence or absence of ‘odex’ files indicates whether the OS is odexed or deodexed.

References

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.