AOSP.dev — 2: Building your first Android image (on Ubuntu) _part-1
** This article has been ported over from my Medium blog. - Original time of writing: Oct 26, 2017 **
Note: Considering I don’t want to make the article too long in terms of time-to-read and general page-scrolling, I’m going to split this chapter into 2 parts.
Intro: Choosing a build machine
Building an Android image is not quite like building an app. When you build your Java app, you usually make use of a build tool such as Maven or Gradle, you trigger the different build steps and usually somewhere between 20 sec or 3 min (depending on project size & build machine) you can expect your build output.
Just to give a rough idea of what you’re getting into, building an Android image (from scratch) on a desktop machine can take about 1 to 3 hours depending on your machine. So make sure you have something else to do while the build commences.
Before the question arises, I will already mention that I will not discuss nor look into using macOs for building Android images. While I have done it in the passed, the additional maintenance required when switching versions (macOs / Xcode / Android version / …) is just too much of a hassle as opposed to Ubuntu in my opinion. If you would however prefer to do this on macOs, please look into the following article.
On the Android website, we can find a list of hardware requirements for Ubuntu. While the advised 250 GB of disk space does seem much (for an Android 7.1 build) I would recommend to at least have about 150 GB of dedicated disk space.
In terms of CPU, use the best you have available. And if you’re planning on building a dedicated machine for this, I can’t recommend the new Ryzen series enough. Compiling is still mostly crunching integer operations, so even the old AMD FX CPU’s perform really well in this regard. But in terms of price/quality, you can’t beat Ryzen at the moment (EDIT: This still holds true in 2020!).
Building Android 7.1.1 from scratch on an AMD Ryzen 1700 takes about 51 min. Drastically less compared to my previous i7 4790 setup which took 1:20 hours.
As for RAM, any decent modern desktop should contain at least 8GB of RAM, but try to push it up to at least 16 GB for these kind of operations. If you’re going for a Ryzen build, make sure the RAM you’re buying is compatible with your motherboard.
Preparing your build environment
I’m not going to explain how to install Ubuntu on your machine. If you’re reading this article, I’m going to assume you’re more than capable of installing it on a machine or VM yourself. I’m going to be using Ubuntu 17.04 for this tutorial, but any version from 14.04 onward should(/might?) be fine.
So let’s kick this off by downloading the Repo tool. If I had to somehow describe Repo to someone, I would do it as such:
Repo is to git repositories, what git repositories are to git submodules.
So in simple terms, Repo is just a wrapper around one or more git repositories, in the same way that a git repository could be a wrapper around one or more git submodules.
Then why not just use submodules? Well, when Google started out with AOSP development, there was no submodule functionality available in git considering this was only implemented afterward. This drove Google to create the repo tool. Git has matured quite a while since then and might even offer a superior experience as opposed to Repo, but Repo is currently still the go-to tool for AOSP maintenance due to the aforementioned legacy reasons.
Now that we got that out of the way, let’s start by downloading the Repo tool. Google recommends creating a ‘bin’ folder in your home directory, but that’s a rather messy approach in my opinion. What I usually do on my Unix based systems, is create an ‘Android’ folder in my home directory which contains all SDK’s, NDK’s & related tooling that I use. So it looks something a little like this:
Ndk & Sdk contain all versions used by Android Studio for example, along with the related tooling. Repo is still Android related, but not tied to NDK/SDK versioning so I placed it in the root.
You can of course do whatever you want, but just make sure the repo tool is available in your $PATH. So to download the repo tool and give it the permissions to run, enter the following commands:
$ curl https://storage.googleapis.com/git-repo-downloads/repo > ~/Android $ chmod a+x ~/Android/repo
Now that we got that out of the way, feel free to give it a spin. The output should look like this:
If it returns “command not found”, please make sure repo is available in your $PATH and you have reloaded your terminal session. (https://github.com/sigmadeltasoftware/APT-InIt/blob/master/env/EnvInit.sh#L10)
Downloading the AOSP
Before you continue here, please make sure you have access to a decent data connection (preferably wired & broadband/fibre) considering you’re about to download more than 20 GBs of data. Then again, looking at modern AAA-titles on Steam, this should be a breeze.
Now let’s create the directory we’re going to download the AOSP in, and cd into it:
$ mkdir ~/AOSP_DIR $ cd ~/AOSP_DIR
Once this is done, we need to choose the right AOSP branch for our target device. Using this page, you can determine which Nexus/Pixel device is supported by which branch and which Android version it correlates to:
In the screenshot above, we can see that AOSP build N4F26I, correlating to branch android-7.1.1_r10 (which is Nougat), supports the Nexus 5X, Nexus 6P and Pixel C as target devices. If you have a Pixel for example, and you download this revision of the AOSP, you won’t be able to create an image for it. So make sure you pick the right branch for your device! Considering I’m using a Nexus 6P and I want the latest branch, I’ll be going for N2G47W — android-7.1.2_r12.
Now create another directory using the branch name, cd into it to initialise your AOSP repository:
$ mkdir AOSP_ANDROID_7.1.2_r12 $ cd AOSP_ANDROID_7.1.2_r12 $ repo init -u https://android.googlesource.com/platform/manifest -b android-7.1.2_r12
After doing this, you might notice that a .repo directory appeared in your dir, similar to a .git directory. Feel free to open the file in: .repo/manifests/default.xml. This file is going to be the manifest of your AOSP. Similar how to an AndroidManifest.xml describes the composition of your app, the files within .repo/manifests will describe the composition of the AOSP project. This manifest will list all projects/repositories that are necessary for this build. I won’t go into detail about this, but feel free to dig in deeper by yourself if you want to know more.
Now trigger the download of the AOSP by executing following command:
$ repo sync -j8
‘sync’ will start the download of the AOSP onto your machine. The -jN parameter you can pass, will tell the system how many jobs it can launch in parallel. From experience, the best number to choose for N can be formulated as such:
N = number_of_cpu_threads * 2
This means if you’re using a Ryzen 1700 CPU with 8 cores and 16 threads, N will be 32. If you don’t specify a number for N in your command, it will use the default mentioned within the manifest file, which is usually 4.
Depending on your data connection, it’s possible that the sync drops out a few times resulting in an error. If this happens, just restart the sync until it completes successfully. This step might take a while so find something else to do while the downloading is taking place,
feel free to move on to part 2, to read up on the building already.