[GUIDE] Understanding the Android Source Code
I have been going through many guides over XDA, there were many that taught you how to compile from source, but I didn't found a single guide that could explain how Android source code works or what are so many folders, files and commands for, so here it is, a lengthy yet informative guide for aspiring devs. And yeah, I'm not a dev, just another guy who learns by exploring many things and likes to share it.
Note - I own an HTC Explorer(Pico), so many things that are written *might* be exclusive to it, or others with some changes.
Describing the Android Source Code Folders -
I'll take CM11 as an example to explain this.
Now the folders, in alphabetical order-
- This folder contains a sub folder called cpp
which actually contains many C++ files linked to many places.
repo init -u git://github.com/CyanogenMod/android.git
Yes, it's that android.git
Have a look at this
- Yeah, it is the folder that deals with the compilation of the latest android ART runtime. If you're looking into source directories of some other android versions, you won't fins it obviously.
- Bionic is mainly a port of the BSD C library to our Linux kernel with the following additions/changes:
- No support for locales.
- No support for wide chars (i.e. multi-byte characters).
- its own smallish implementation of pthreads based on Linux futexes.
- Support for x86, ARM and ARM thumb CPU instruction sets and kernel interfaces.
- Boot and startup related code. Some of it is legacy, the fastboot protocol info could be interesting since it is implemented by boot loaders in a number of devices such as the Nexus ones.
- The main entry point of the build system resides here - envsetup.sh, if you follow the instruction in source.android.com you will see that the first step before you do anything to build Android is to use the command source build/envsetup.sh
The script will check few things to make sure all the needed application available in the local machine. It also setup the devices that can be built, which is extracted from the directory device.
- the compatability tests. The test suite to ensure that a build complies with the Android specification.
- This is the folder responsible for the compilation of the Dalvik runtime for the Android devices.
*Have a look at the difference between the two(art and dalvik) folders and you'll have an idea of how things work in that case*
- This directory contains application that are not part of the deployed app in the OS. There are some useful application such as widget builder, etc
- It contains the device specific configurations for many devices.
Note - Many people ask me what, the folders like 'common' and 'generic are for, so here -
- This directory contains gps information and also a script that allows you to extract proprietary binary files from your phone to be part of the build process.(You can try to have a look at your device's device tree and then the cm.mk file, where you could find relations of these files. In my case, it shows like this:
# Include GSM stuff
$(call inherit-product, vendor/cm/config/gsm.mk)
# Inherit some common cyanogenmod stuff.
$(call inherit-product, device/common/gps/gps_eu_supl.mk)
- This directory contains the generic device configuration that is called ‘goldfish’. This is the device classification used when building the emulator.
- This directory contains the Android Accessories Kit code. It contains a demokit Android app that allows you to control the ADK board. The ADK firmware can be check out here http://code.google.com/p/microbridge/
. There is a good article about this here
- This directory contains a full example of writing your own Android platform shared library, without changing the Android framework. It also shows how to write JNI code for incorporating native code into the library, and a client application that uses the library. This example is ONLY
for people working with the open source platform to create a system image that will be delivered on a device which will include a custom library as shown here. It can not be used to create a third party shared library, which is not currently supported in Android.
- I contains an important sub-folder called source.android.com
- This directory contains source code for all external open source projects such as SQLite, Freetype, webkit and webview.
- Ah, one of the most important directories. it contains the sources for the framework. Here you will find the implementation of key services such as the System Server with the Package- and Activity managers. A lot of the mapping between the java application APIs and the native libraries is also done here.
A special note on this one - I'd recommend new users to not to play with any file/folder inside the frameworks folder, maybe your ROM doesn't boots then.
- Hardware related source code such as the Android hardware abstraction layer specification and implementation. This folder also contains the reference Radio Interface Layer(RIL - To communicate with the modem side) implementation.
- It's not a default folder in the source code, but it's a part of device configuration set-up. It contains the kernel source of your device.
- I'll explain this one with the important folders inside this, since every folder performs a different function.
- dalvik - DalvikVM runtime for Android
- dom - Java test classes for DOM
- expectations - Contains information about the test cases
- include - Some C/C++ include files that used for Array and String handling
- json - JSON based Java implementation
- luni - Contains test source code for loading .jar and .dex files
- support - Contains support class file for testing Dalvik
- xml - XML pull and push implementation
- I have no idea on this one. If someone knows, share your knowledge.
- Contains build scripts and helper files for building the NDK
(Everyone's favorite directory
) - The build output will be placed here after you run make. The folder structure is out/target/product/. In the default build for the emulator the output will be placed in out/target/product/generic. This is where you will find the images used by the emulator to start (or to be downloaded and flashed to a device if you are building for a hardware target).
- Standard Android application that are available as part of the AOSP - Camera, SMS, Dialer, Launcher, etc
- I believe that 'pdk' is the Platform Development Kit, it's basically an SDK/set of tools that Google sends to OEMs to evaluate their framework ahead of each major Android upgrade since Android 4.1.
(Thanks to @yowanvista
- Contains files that are distributed in binary form for convenience. Examples include the cross compilations toolchains for different development machines.
- This directory contains lots of apps that are not part of operating system. There are quite useful apps that developers can leverage on and can be enhanced further as part of the operating system.
- Source code files for the core Android system. That is the minimal Linux system that is started before the Dalvik VM and any java based services are enabled. This includes the source code for the init process and the default init.rc script that provide the dynamic configuration of the platform.
- Some external important tools that help in compiling. Not sure though. :/
- This directory contains vendors specific libraries. Most of the proprietary binary libraries from non-open source projects are stored here when building AOSP.
One thing - Beyond the above you also have the hidden .repo directory that contains the source for the repo utility. It also holds the manifest specifying what git repositories you want to track for this Android source project. If you have your own additions you could automatically track them by adding a local manifest here. For modifications of the platform framework there are some instructions available in the device/sample folder of the source code tree. That will show you how to add APIs to Android without having to modify the core framework.
Now, many people ask me the difference between the 'Breakfast', 'Lunch' and 'Brunch' command. So, here's what these commands are specific for:
You may not ever use this command
, but in order to explain brunch, we have to explain breakfast first. Breakfast is a function used to configure your build. It keeps track of a list of officially-supported devices to build for, and allows you to choose one.
If you do not put a device, the script will output a list of available devices to build for, and you can then choose yours. Breakfast then goes on to configure your build environment with the correct variables to create your device-specific rom.
Defined simply, brunch is equivalent to
This means that it sets up your build environment to be configured for your device, and then commences the build process. mka bacon is just CyanogenMods’s way of saying build the code for your device. It’s generally only used for officially supported devices (ones that you use can choose through the breakfast menu).
This ones also pretty simple to explain. It’s used EXACTLY like breakfast, the only difference being the choices you have to build with it. Using lunch, you can choose non-official or non-standard builds for your device. This includes special debug versions and also allows you to build CyanogenMod for use on the Android Emulator. To build after running lunch, simply issue the command mka
For other commands and help, I recommend you to read this article.
Few common Terms
Hey, do you ever find few terms on xda, related to development that go over your mind? Well, I recommend you to have a look at this
post by Recognized Contributor @TheByteSmasher
and give him the Thanks
Understanding Android Makefile (Android.mk)
Well, I bet if go through many folders of the Source Code, you might find the file named Android.mk
! Here are few important things regarding that -
These Android.mk files defines how to build that source code. There are well defined specific rules for Android.mk files. Let me summarize them.
Name: We need to define a name for our build (LOCAL_MODULE := )
Local Variables: All builds may have some local variables so to start a new build it is good to clear all local variables (include $(CLEAR_VARS))
Files: We need to write all files we want it to be build (LOCAL_SRC_FILES := main.c)
Tags: Define tags for build. (LOCAL_MODULE_TAGS := eng development)
Libraries: If build needs to be linked to other libraries, we need to define them (LOCAL_SHARED_LIBRARIES := cutils)
Template file: We can define whether our build is executable,library or something else by including template file (include $(BUILD_EXECUTABLE))
BUILD_EXECUTABLE, CLEAR_VARS, etc. variables which are the absolute address of the template files are defined in build/core/config.mk.
Now an example
The following Android.mk builds a simple APK. The codes beginning with a has(#) are the comments to tell you what the lines actually means.
LOCAL_PATH := $(call my-dir)
# Build all java files in the java subdirectory
LOCAL_SRC_FILES := $(call all-subdir-java-files)
# Name of the APK to build
LOCAL_PACKAGE_NAME := LocalPackage
# Tell it to build an APK
Last line in Android.mk file builds the APK file. Different source code types must be built differently so we can also use $(BUILD_EXECUTABLE), $(HOST_JAVA_LIBRARY), $(HOST_PREBUILT) etc. variables according to our source code. (Definitions like my-dir, all-subdir-java-files are in build/core/definitions.mk). We can add LOCAL_MODULE_TAGS variable to Android.mk file to determine that module to be installed in that source code built. Here are the some defined tags and their meanings.
>Build helper functions
A whole bunch of build helper functions are defined in the file build/core/definitions.mk
Try grep define build/core/definitions.mk for an exhaustive list.
Here are some possibly interesting functions:
- print-vars - shall all Makefile variables, for debugging
- emit-line - output a line during building, to a file
- dump-words-to-file - output a list of words to a file
- copy-one-file - copy a file from one place to another
>Add a file directly to the output area
You can copy a file directly to the output area, without building anything, using the add-prebuilt-files function.
The following line, extracted from prebuilt/android-arm/gdbserver/Android.mk copies a list of files to the EXECUTABLES directory in the output area:
$(call add-prebuilt-files, EXECUTABLES, $(prebuilt_files))
Understanding the Device Tree
Note - This is by no means complete, and there will be omissions as have explained all this top of my head and copied pasted certain bits that I have here on my own device tree.
- this will tell the build system to include and to build sources specifically for your device. I have explained a bit of it above as well.
- this is for the kernel, the build system uses that to drop the kernel image in place.
- specifies the appropriate device's make file, to use for building. i.e. device/htc/pico/pico.mk
(In my case), This is device-specific as well.
- Every device has a codename, and there is a file named as the codename of device. It specifies the properties and extras to copy over into the final output, in this case, it could be for example, pico.mk
- This is the meat of it all, this is where compiler conditional flags are set, partition layouts, boot addresses, ramdisk size, and so on.
LOCAL_PATH := $(my-dir)
include $(call all-makefiles-under,$(LOCAL_PATH))
^This is how the build will use that to build recovery, sensors, lights and camera (of course there will be more), its saying 'Yo Builder, go into each of the directories specified, and build the respective sources'
LOCAL_PATH := $(call my-dir)
ALL_PREBUILT += $(INSTALLED_KERNEL_TARGET)
# include the non-open-source counterpart to this file
^ This one is pretty simple and tells the build system to go to the vendor tree of the device and include AndroidBoardVendor.mk
PRODUCT_MAKEFILES := \
^Just specifying the makefiles of the device.
Now in this one, I'm taking a BoardConfig.mk file that I found over the internet with a suitable explanation of it. Credits to the post over stackoverflow for the valuable efforts.
LOCAL_PATH:= $(call my-dir)
TARGET_NO_BOOTLOADER := true
TARGET_PREBUILT_KERNEL := device/lg/gt540/kernel
TARGET_PREBUILT_RECOVERY_KERNEL := device/lg/gt540/recovery_kernel
# This will vary from device!
TARGET_BOARD_PLATFORM := msm7k
TARGET_ARCH_VARIANT := armv6-vfp
TARGET_CPU_ABI := armeabi
TARGET_CPU_ABI := armeabi-v6l
TARGET_CPU_ABI2 := armeabi
# OpenGL drivers config file path
BOARD_EGL_CFG := device/lg/gt540/egl.cfg
# Dependant, not to be taken literally!
BOARD_GLOBAL_CFLAGS += -DHAVE_FM_RADIO
# Dependant, not to be taken literally!
BOARD_KERNEL_BASE := 0x02600000
# this will be device specific, and by doing cat /proc/mtd will give you the correct sizes
BOARD_BOOTIMAGE_PARTITION_SIZE := 0x00480000
BOARD_RECOVERYIMAGE_PARTITION_SIZE := 0x00480000
BOARD_SYSTEMIMAGE_PARTITION_SIZE := 0x0cf80000
BOARD_USERDATAIMAGE_PARTITION_SIZE := 0x0d020000
BOARD_FLASH_BLOCK_SIZE := 131072
^That is an excerpt, notice how we specify kernel's base address, this is how the boot.img gets generated after compilation is done and yet again, gets dropped into out/target/product/lg/gt540/boot.img. Also, more importantly, we're telling the build system to use the target platform for cross-compiling the sources (*TARGET_BOARD_PLATFORM*/*TARGET_CPU_ABI*) There will be more information in there such as conditional flags to pass to the compiler, for an example. we specified the directive HAVE_FM_RADIO to tell it, when it comes to handling the source for the FM radio system, to conditionally compile parts of the source. Again, this is hardware specific and mileage will vary, also this applies to the address for boot. In a nutshell, this is saying 'Yo Builder, read the damn variables and remember them and apply them when cross-compiling those source files!'
Now that the internals of each of those Android build make-files are shown.
Now, onto the vendor/ part of it, in AOSP, simply, once again, correlation and corresponds with the device/ tree, as in continuing with this example, vendor/lg/gt540/ which gets picked up by the lunch. There's more make files in there but the general consensus is there's a directory called proprietary which contains the proprietary libs (due to close-source etc) that gets copied over. The copying over of the libraries gets specified in the file device-vendor-blobs.mk, in this case, gt540-vendor-blobs.mk.
Adding your Own Apps in the Source Code
The following part of the guide will tell you how to make your own apps to compile with the ROM and be a part of it.
1. Add the App's source code to packages/apps/name_of_app
2. Regardless of how you put the source in packages/apps/, assuming that the source for the app has an Android.mk Makefile, you can get it to automatically build and install the resulting file in your $OUT directory (and thus your .zip) by simply determining the name of the project, which is typically defined in Android.mk with this:
3. Add the project to device.mk (or whatever .mk) in the device folder.
Have a look at an example here
Compiling specific parts of a ROM
To compile an app-
Wait, there's some more things you must know for compiling a *specific app* ! Thanks to @thewisenerd
head over to this post
To compile other parts you also need to enter the folder name, here are some examples from /frameworks/base [Credits-XDA University Article]
make android.policy (the power menu and lockscreen)
make framework (the initial framework files)
make framework-res (the initial framework resources)
make services (the services.jar file)
Configuring a new Product for the AOSP.
make sdk (builds the android sdk)
make modules (builds all modules)
make installclean (removes all staging directories, such as out/target/product/boardname/system)
make clean (removes the whole /out directory)
make recoveryimage (builds the recovery from /bootable/recovery, customizable if wanted!)
Again, I'd recommend you to have a look at this great document
A detail information about BoardConfig.mk
Well, I believe that BoardConfig.mk is one of the most important files for the device tree. Now, here are few parameters of the file explained-
- TARGET_ARCH: set to arm for almost all current Android devices.
- BOARD_KERNEL_CMDLINE: not all devices pass boot parameters however if your device does this must be filled out properly in order to boot successfully.
- BOARD_KERNEL_PAGESIZE: the pagesize of the stock boot.img and must be set properly in order to boot. Typical values for this are 2048 and 4096 and this information can be extracted from the stock kernel.
- BOARD_BOOTIMAGE_PARTITION_SIZE: the number of bytes allocated to the kernel image partition.
- BOARD_RECOVERYIMAGE_PARTITION_SIZE: the number of bytes allocated to the recovery image partition.
- BOARD_SYSTEMIMAGE_PARTITION_SIZE: the number of bytes allocated to the Android system filesystem partition.
- BOARD_USERDATAIMAGE_PARTITION_SIZE: the number of bytes allocated to the Android data filesystem partition.
^The above information can be gathered by multiplying the size from /proc/partitions by the block size, typically 1024.
- BOARD_HAS_NO_SELECT_BUTTON: (optional), use this if your device needs to use its Power button to confirm selections in recovery.
- BOARD_FORCE_RAMDISK_ADDRESS / BOARD_MKBOOTIMG_ARGS: (optional), use these to force a specific address for the ramdisk. This is usually needed on larger partitions in order for the ramdisk to be loaded properly where it's expected to exist. This value can be obtained from the stock kernel. The former is deprecated as of Android 4.2.x and the latter will now be used in 4.2.x and beyond.
Few *more* external links
Few great docs that I found over the web-
>Firstly, My parents.
> @Red Devil
and my Team
for helping me with all my doubts and even answering the most supid questions that I asked them
for the idea.
> Helpful and informative posts over-
Got a query? Ask in the thread. Quote or mention me for quicker replies.
Thanks to @eagleeyetom
for featuring it on the portal