Tuesday, November 5, 2013

Building Android from Source for the Galaxy Nexus

This is the first in a series of posts on building the Android firmware for Galaxy Nexus as available from Google at source.android.com. When I first tried to do this, I had to look at a lot of guides and forum posts to get everything working on my Galaxy Nexus. Although the Galaxy Nexus will be obsolete in a few months, the general principles described here are the same for any Nexus device.

Downloading the Source

This is best described at this relevant page from Google. Only gotchas are that if you decide to do this on a Linux system other than ubuntu, you will have to spend a fair bit of time in looking up the required packages and downloading it. I have built AOSP on CentOS,RHEL and OpenSuSe without much effort, so it is definitely possible to get a build up and running on any modern and well-supported Linux distribution.

Folder Structure of the Android Source

When you first run the repo init command, an empty repository is created with links to the individual Android projects in git. To see this list, open .repo/manifest.xml. In case of other Android distributions like CyanogenMod or AOKP, this manifest.xml is modified with additional entries for the specific apps in the ROM distribution.

/system - This is where all the apps are contained.
/external - This contains external libraries like OpenSSL, wpa_supplicant (for WiFi) or other third-party open-source libraries. There are typically compiled into .so object files and copied to /system/lib on the device.
/vendor - This is the folder which contains the specific files for each device. For eg. /vendor/samsung would contain all the specific files made by Samsung. ROM distros like CyanogenMod contain a /vendor/cm folder where all CM-specific packages are stored.
/out - This is where the output files are stored after a successfull build. To go to the target folder for the device you are building, type cd $OUT or cd $ANDROID_PRODUCT_OUT (This will work only after the target device has been set using lunch)
/build - This contains a bunch of Makefiles that define Android's Make-language, i.e the many keywords that are used in the .mk files scattered across the Android source. PRODUCT_IDs are VERSION_IDs are also defined in  makefiles here.
/packages - This is where the source for all the Android Apps (atleast the ones included in AOSP) resides.


Understanding the Android Build System

To start with, a bunch of makefiles in the build directory are included, which define keywords like all-files-under-dir and call-dir and other such keywords which are further used
in other makefiles, effectively creating a whole new language for use in Makefiles.

These Makefile keywords enable very useful constructs - For eg. The Galaxy Nexus (maguro) makefile inherits from the tuna Makefile, so that all the devices which use the same board as the Galaxy Nexus
(mainly the different variants of the Galaxy Nexus), can all inherit from the tuna makefile.

Special shout out to build/core/version_defaults.mk, which is the Makefile where the version info that you see in Settings->About is pulled from.

Getting the device specific drivers

To build for a device, you will need the drivers for peripherals like wireless, camera, gps, etc. which are usually not open-sourced by the individual manufacturers. For nexus devices, theses are usually provided as binary blobs from the Nexus Proprietary Binaries' page.

If you have ever wondered why your (non-nexus) Android device is not supported or is buggy running ROMs like CyanogenMod, the reason is that the appropriate binaries for the peripherals were not released for your device, so the device maintainers for the ROM needed to copy source from related devices containing same (or similar peripherals).

Download all the required binaries for the Galaxy Nexus from the above page, copy them to your vendor/ folder, and then extract them.
All the proprietary files needed for a fully functional build are contained in proprietary_files.txt. If you compare the entries in this file versus all the files from the driver packages that you just extracted, you will notice that there are a couple of files missing. These are - 
  • ducati-m3.bin
  • gps.omap4.so
  • sirfgps.conf

You can obtain these files off your devices with adb pull or you can download them from an online repository like The Muppets which contains the proprietary drivers for various devices.

Once you have obtained these files, the next step is to make appropriate entries in the Galaxy Nexus makefile, so that these binaries are copied to the system image.

Add these entries to PRODUCT_PACKAGES in vendor/samsung/maguro/device-partial.mk
sirfgps \
ducati-m3 \
gps.omap4
And then, describe the files that you have just added in vendor/samsung/maguro/proprietary/Android.mk

include $(CLEAR_VARS)
LOCAL_MODULE := sirfgps
LOCAL_MODULE_OWNER := samsung
LOCAL_SRC_FILES := sirfgps.conf
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_SUFFIX := .conf
LOCAL_MODULE_CLASS := SHARED_LIBRARIES
LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/etc
include $(BUILD_PREBUILT)

include $(CLEAR_VARS)
LOCAL_MODULE := gps.omap4
LOCAL_MODULE_OWNER := samsung
LOCAL_SRC_FILES := gps.omap4.so
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_SUFFIX := .so
LOCAL_MODULE_CLASS := SHARED_LIBRARIES
LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/lib/hw
include $(BUILD_PREBUILT)

include $(CLEAR_VARS)
LOCAL_MODULE := ducati-m3
LOCAL_MODULE_OWNER := samsung
LOCAL_SRC_FILES := ducati-m3.bin
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_SUFFIX := .bin
LOCAL_MODULE_CLASS := SHARED_LIBRARIES
LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/firmware
include $(BUILD_PREBUILT)


Now, in vendor/samsung/maguro/BoardConfigVendor.mk, change PRODUCT_RESTRICT_VENDOR_FILES to false. This will to instruct the build to pick up the proprietary drivers located in the vendor folder.

Compiling

Now that all the setup steps are taken care of, we can get down to work and start the actual compile process. To start, in the root folder, execute

source build/envsetup.sh

This pulls in some of the device specific makefiles and sets up a make target for each device.
After this is done, execute

[vineet1@vineet1-1 aosp]$ lunch

You're building on Linux

Lunch menu... pick a combo:
     1. aosp_arm-eng
     2. aosp_x86-eng
     3. aosp_mips-eng
     4. vbox_x86-eng
     5. full_maguro-userdebug
     6. aosp_manta-userdebug
     7. aosp_mako-userdebug
     8. aosp_hammerhead-userdebug
     9. aosp_grouper-userdebug
     10. aosp_deb-userdebug
     11. aosp_flo-userdebug
     12. aosp_tilapia-userdebug
     13. mini_armv7a_neon-userdebug
     14. mini_mips-userdebug
     15. mini_x86-userdebug

Which would you like? [aosp_arm-eng] 5

============================================
PLATFORM_VERSION_CODENAME=REL
PLATFORM_VERSION=4.4
TARGET_PRODUCT=full_maguro
TARGET_BUILD_VARIANT=userdebug
TARGET_BUILD_TYPE=release
TARGET_BUILD_APPS=
TARGET_ARCH=arm
TARGET_ARCH_VARIANT=armv7-a-neon
TARGET_CPU_VARIANT=cortex-a9
HOST_ARCH=x86
HOST_OS=linux
HOST_OS_EXTRA=Linux-2.6.32-358.el6.x86_64-x86_64-with-centos-6.4-Final
HOST_BUILD_TYPE=release
BUILD_ID=KRT16M
OUT_DIR=out
============================================



From the menu that is displayed, choose full_maguro-userdebug
Once that is done, run make -jn (where n = 2x the number of CPUs in your system). This will kick off the build process.

This should take a while, depending on your system. If it completes successfully, the next step is to generate a zip file which we can use to flash to your device.

make updatepackage.

This wil generate a file named like full_maguro-img-eng-<username>.zip
Flash this file onto your phone with fastboot update -w to erase the existing system on your device, and reflash your newly built system image.

Thats it! Check Setting->About phone and verify the version numbers.