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
- Create a directory under ‘device’ with the [company]/[product] structure. For example ‘mkdir –p umlaut/alpha’.
- Create a file ‘Android.mk’ with the following contents:
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) include $(call all-makefiles-under,$(LOCAL_PATH))
- Create a file ‘AndroidProducts.mk’ with the following contents:
PRODUCT_MAKEFILES := \ $(LOCAL_DIR)/alpha.mk
- Create a file ‘vendorsetup.sh’ with the following contents:
add_lunch_combo alpha-eng
- Create a file named ‘common.mk’ with the following contents:
UMLAUT_COMMON := device/umlaut/common DEVICE_PACKAGE_OVERLAYS := PRODUCT_PACKAGES += PRODUCT_COPY_FILES +=
- 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
- Copy from ‘build/target/board/generic/BoardConfig.mk to the ‘device/umlaut/alpha’ directory.
- Change directory to the root of you AOSP build directory, and enter:
. build/envsetup.sh lunch
- Select ‘alpha-eng’ from the options. If this option is not available, review the steps above.
make –j16 emulator
- 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
- http://developer.android.com/tools/help/emulator.html
- http://www.piotrbuda.eu/2012/05/installing-google-play-on-android-emulator.html
- http://blog.apkudo.com/2012/08/08/run-google-play-on-an-emulator-and-pretend-to-be-any-device/
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
- 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
- Edit ‘AndroidProducts.mk’ and change ‘alpha.mk’ to ‘beta.mk’. Save and exit.
- Edit ‘vendorsetup.sh’ and change ‘alpha-eng’ to ‘beta-eng’. Save and exit.
- Edit ‘beta.mk’ and change all references to ‘alpha’ to ‘beta’. Save and exit.
- These steps essentially clone the minimal configuration from the steps above.
- 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 += /
- We will then build with the following:
. build/envsetup.sh make clobber lunch beta-eng make –j16 emulator
- 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
- 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>
- 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
- 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
- This will also require that we delete the existing ‘su’ package from AOSP.
cd system/extras rm –rf su
- 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
- Then we update our ‘beta’ build to include the piece parts.
- cd device/umlaut/beta
vim common.mk - 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
- Lastly we need to get the CM certificates. For CM10.1, the certs are found at:
- https://github.com/CyanogenMod/android_build/blob/cm-10.1/target/product/security/superuser.x509.pem
- https://github.com/CyanogenMod/android_build/blob/cm-10.1/target/product/security/superuser.pk8
- 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.
- We will then build with the following:
. build/envsetup.sh make clobber lunch beta-eng make –j16 emulator
- Confirm that the Superuser app is in the build (and works).
References
- http://rootzwiki.com/topic/14293-aosp-build-with-no-baseband-cdma-galaxy-nexus/
- http://www.omappedia.com/wiki/Android_Installing_Busybox_Command_Line_Tools
- http://jonrichards.net/2012/01/15/building-busybox-from-source/
- http://www.androidenea.com/2010/06/using-localmanifestxml-file-in-repo-to.html?utm_source=twitterfeed&utm_medium=twitter
- https://gerrit.googlesource.com/git-repo/+/master/docs/manifest-format.txt
- http://rootzwiki.com/topic/14293-aosp-build-with-no-baseband-cdma-galaxy-nexus/
- http://mobility.forumsee.com/a/m/s/p12-9229-054712–add-and-busybox-aosp.html
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
- Enter your AOSP directory
make clobber . build/envsetup.sh lunch
- Select your build of choice. An emulator would be a good choice for validating this method.
- (method 1) a deodexed build can be forced by:
export DISABLE_DEXPREOPT=true export WITH_DEXPREOPT=false make –j16
- (method 2) a deodexed build can also be forced by:
make DISABLE_DEXPREOPT=true WITH_DEXPREOPT=false –j16 emulator
Validation
- After the emulator is fully booted:
adb shell cd /system/app ls *.odex
- The presence or absence of ‘odex’ files indicates whether the OS is odexed or deodexed.
References
- http://www.addictivetips.com/mobile/what-is-odex-and-deodex-in-android-complete-guide/
- http://android.stackexchange.com/questions/6925/what-is-the-difference-between-odexed-and-deodexed-roms
- http://code.google.com/p/smali/wiki/DeodexInstructions
- http://stackoverflow.com/questions/8660998/compiling-a-deodexed-aosp
- http://rootzwiki.com/topic/18776-aosp-build-not-being-deodexed/