Android is the most frequently-installed operating system in the world. It’s available for phones, wearables, TVs and cars, among other devices.
Google leads the development of Android in the scope of the Android Open Source Project (AOSP), but the project also accepts public contributions.
While you might not have considered diving into the innards of Android before now, doing so will bring you new perspectives and help you understand common tooling and code patterns in Android app development. Being able to understand and change the behavior of the Android platform opens numerous possibilities to shape popular consumer devices.
In this tutorial, you’ll get an introduction to Android platform development. In the process, you’ll learn to:
- Set up your computer to build the AOSP.
- Get AOSP sources.
- Build the Android emulator from the sources.
- Change the AOSP code to replace the boot animation.
If you’d like more information, a great way to start learning Android app development is with our Your First Kotlin Android App tutorial. Better yet, dive in with the Android Learning Path and really sharpen your skills.
Keep in mind that Android platform development can be difficult to digest at first. You’ll find less documentation than is available for Android app development, and the size of the AOSP source tree and the mix of different technologies make learning complex.
But while understanding the different parts of the Android platform requires time and effort, it’s absolutely possible to accomplish. This tutorial will help.
Now, it’s time to start a very exciting quest and enter the depths of the Android dungeons.
Download the starter project by clicking the Download Materials button at the top or bottom of the tutorial.
You’ll find a bootanimation.zip file containing the animation for the Android version that you’re about to build. You don’t need to worry about designing your own animation — the raywenderlich.com team has you covered. The result looks like this:
You’ll now learn to download the AOSP sources and create your own build.
Setting up the Development Environment
Before starting, you should know that building the AOSP has some requirements. You’ll need a computer with at least 300 GB available (yes, 300!). Since you’ll download a lot of data, you’ll also need a reliable internet connection.
When it comes to the work environment, AOSP doesn’t currently support Windows. You could use macOS, but the most common OS for working with the AOSP is Ubuntu Linux, which this tutorial will focus on.
If you’re still interested in macOS, check out the official Google documentation for setting up a macOS build environment.
In this tutorial, you’ll rely on Docker to configure your development environment using an Ubuntu container running on a Linux host. You could use the Linux host directly, but by using Docker you can separate both environments. This is useful in case your host OS uses different versions of the libraries you’ll need here.
Configuring the Ubuntu Container
This tutorial assumes you already have Docker installed on your computer. If this isn’t the case, please refer to the official Docker documentation for installation instructions.
Once you have Docker running on your computer, hold tight because the fun starts now! :]
Open a terminal and run the following command:
docker pull ubuntu:18.04
This command will download the official Ubuntu 18.04 image from Docker Hub.
Next, run the following command to make sure that everything’s in place:
docker image ls
This lists all Docker images available on your machine. Make sure the Ubuntu image appears in the list before proceeding to the next step.
Create an empty folder called aosp in an easy-to-find location — for example, under your Desktop path: ~/Desktop/aosp. You’ll use this folder as the workspace for building the AOSP sources.
Starting the Ubuntu Container
Next, execute the following command:
docker run -v ~/Desktop/aosp:/home/aosp -it ubuntu:18.04
This will start a container based on the Ubuntu image, while at the same time sharing the folder you just created.
You share this folder with the Docker container so you can access it later from your computer — that is, directly from your system, outside the Docker container. After this, your terminal prompt will change to root, showing that you are inside the Docker container.
Make sure you have access to /home/aosp by running
ls /home/aosp. If you get a message like No such file or directory, the Docker container can’t see the folder you passed in the previous command with parameter
Repeat the steps above to validate you have access to the folder `/home/aosp` from within docker container.
Updating the Container and Installing Packages
Now, run the following command to update the Ubuntu packages in the container:
You should see the following output in your terminal:
Next, you need to install several packages you need to compile the AOSP sources during the build process. Do this by running the following command:
apt-get install -y git-core gnupg flex bison gperf build-essential zip curl zlib1g-dev gcc-multilib g++-multilib x11proto-core-dev libx11-dev libgl1-mesa-dev libxml2-utils xsltproc unzip python python3 openjdk-8-jdk rsync
Now that you’ve set up Ubuntu, you’ll get to know a tool that will help you download the Android sources more efficiently.
Using the Repo Tool
The Android codebase contains a massive amount of source code organized in different Git repositories. Repo is a tool built on top of Git to make the development workflow easier. It’s a Python script that takes care of interacting with the revision control system, helping you manage multiple Git repositories.
Repo does this using a manifest file that links to the current revision of each Git repository. If you’ve worked with Git submodules before, this is similar.
In this tutorial, you’ll use Repo to download the Android sources.
Create a new folder named bin inside /home/aosp. Then add /home/aosp/bin to the PATH environment variable:
This ensures that Repo can run from any path in your terminal.
Run the following command to download Repo to the container:
curl https://storage.googleapis.com/git-repo-downloads/repo > /home/aosp/bin/repo
curl to do an HTTP request to the given URL, then redirects the output with
> to /home/aosp/bin/repo. Basically, you download the Repo script and copy it to the bin folder.
Then, run the following command:
chmod +x /home/aosp/bin/repo
This makes Repo executable, as
To ensure everything worked, run the following command:
This shows the following output, indicating that Repo is ready to use:
Check that the output in your terminal matches that in the screenshot, to make sure everything is in place.
Great, your container is now ready to build the AOSP!
Next, you’ll focus on getting the AOSP source tree.
Getting the Sources
Before downloading the Android sources with Repo, you need to set up your user name and email address in Git. Without them, Repo will stop and won’t download anything.
Use this command to quickly check if they’re available:
git config -l
If they’re configured, you should see something like the following in your terminal:
If this isn’t the case, run the below to set up your username:
git config --global user.name "Your name"
Next, run the below to set up your email address:
git config --global user.email "email@example.com"
All set, now you will initialize a folder that will hold all the source files for AOSP and also the tracked history of those source files.
Ready to jump in? Then move to the next section!
Initializing the Source Folder
Then, in /home/aosp, create a new folder named source to hold the sources. Switch your current path to /home/aosp/source, then run the following command:
repo init -u https://android.googlesource.com/platform/manifest
init installs Repo in the current directory. It also initializes a .repo folder, which contains information about the Git repositories that the manifest points to. You pass URL information with
-u param, in this case passing in the URL for AOSP manifest file. This is how Repo gets information from the master branch.
-bargument, as in the example below:
repo init -u https://android.googlesource.com/platform/manifest -b android-10.0.0_r33
Get an overview of all the branches by visiting the Android source code tags and builds site. In this tutorial, you’ll use the master branch.
Once the previous command finishes, check that you’ve successfully set up Repo by running this command again:
This time, this command shows the following screen:
This is a list of the different commands available with Repo. Check that you get the same output in your terminal.
For more information about Repo’s different options, visit the Repo Command Reference site.
Downloading the Source
Finally, run the following command to download the AOSP source tree to the working directory. Make sure you have a reliable Internet connection and enough space on your drive. Since this process could take between one to two hours, it would be really annoying having to restart it!
While you’re waiting is a perfect time to prepare a tasty cup of tea. :]
After a successful sync, your working directory will contain the folders shown below:
Now that you have everything in place, it’s time to actually build the AOSP.
Building the AOSP
The first step to build the AOSP based on the sources you just downloaded is to set up the build environment. Run this command from /home/aosp/source:
This will make a set of useful commands — which you’ll need for the next steps — available in your terminal.
lunch in your terminal and execute it. This command shows the list of target device types that you can build.
The default option is aosp_arm-eng, which builds the Android images for a device of type phone using the ARM architecture.
You could build this, but when you run the emulator on your computer, you’ll notice that it’s very slow. A better option is to build the target aosp_x86_64-eng.
Select this target by entering the associated index from the list of options. In this case, enter 23 and press Return. The terminal will show the following output:
Running the Build
At this point, the environment is ready to trigger the build. To do so, type m and press Enter. This starts the build process, which takes between two and three hours, depending on your computer.
Are you ready for a second cup of tea? :]
Once the build process completes, you’ll find the result in /home/aosp/source/out/target/product.
To start the emulator, simply execute
emulator. This command is only available because you executed source build/envsetup.sh and then selected a build target with
lunch earlier. If you closed the terminal for any reason after the build completed, you’ll need to run those commands again.
Great job, you just built the AOSP for the first time!
However, your quest doesn’t end here. In the next section, you’ll learn how to modify the Android boot animation.
Setting up the Android Bootloader Animation
The Android OS initializes some internal services during the boot phase, just before the System UI loads. Android displays the bootloader animation, also known as the boot animation, during this time.
If you’re interested in digging into C++, the boot animation source lives in frameworks/base/cmds/bootanimation. Here’s how it works: The system tries to load an animation zip file from the following locations, in order:
- /system/media/bootanimation-encrypted.zip, which is used when data encryption is active.
If the system doesn’t find a boot animation file in those paths, it will dynamically generate a default animation.
Looking at the Boot Animation Format
bootanimation.zip follows a specific format. First of all, it’s important to note that it uses the store compression level, which means that it doesn’t compress its content. The boot animation won’t work if the ZIP file uses compression.
Open and unzip bootanimation.zip, which you downloaded with the materials for this tutorial. Inside the unzipped bootanimation folder, you’ll see a file named desc.txt and three folders named part0, part1 and part2. Inside these partX folders, you’ll find several PNG files with ordered names.
Understanding the Components
The PNGs inside bootanimation.zip represent the different frames of your animation.
They’re in three separate folders because this specific animation contains three different parts:
- part0: The animation shows the raywenderlich.com logo increasing in size.
- part1: The logo’s size increases and decreases, pulsing like a heartbeat.
- part2: The logo’s size decreases.
Note that the number of parts depends on the animation’s design.
desc.txt describes the behavior of the animation. The first line defines the general parameters. In this case, the values
30 correspond to
- width: The animation’s width in pixels.
- height: Height of the animation in pixels.
- fps: Speed of the animation in frames per second.
The remaining lines give information about each part of the animation. They follow the format
- type: Indicates the kind of animation. p means this part will play until the end of the boot interrupts it. c means it will play unconditionally until it completes. In your animation, all the parts use type c.
- count: Number of times this part will play. 0 means it loops until the boot completes.
- pause: Indicates the number of frames to delay after this part ends.
- path: Name of the directory containing the frames for this part.
There are a few more parameters you could use to tweak the boot animation. Their full description are in the following file, in the AOSP sources: frameworks/base/cmds/bootanimation/FORMAT.md.
Customizing the Boot Animation
To change the boot animation in your AOSP build, you need to use the same target you selected earlier in the
lunch menu: aosp_x86_64-eng.
Open aosp_x86_64.mk from /home/aosp/source/build/make/target/product. At the bottom of the file, add the following lines:
# Boot animation PRODUCT_COPY_FILES += \ device/generic/x86_64/bootanimation.zip:system/media/bootanimation.zip
This tells the build process to copy your animation file to system/media/bootanimation.zip. This is one of the paths where the boot loader will look for a bootanimation.zip file, as described earlier.
Then, copy bootanimation.zip into /home/aosp/source/device/generic/x86_64/.
In aosp_x86_64.mk, find the line starting with
PRODUCT_ARTIFACT_PATH_REQUIREMENT_WHITELIST, then add system/media/bootanimation.zip \ after the last \.
Without this, the build process won’t allow you to copy the ZIP file to system/media. The resulting code should look like this:
PRODUCT_ARTIFACT_PATH_REQUIREMENT_WHITELIST += \ root/init.zygote32_64.rc \ root/init.zygote64_32.rc \ system/media/bootanimation.zip \
Finally, save the file and execute the
m command to create a new build with the changes. Don’t worry, the build will take only a few minutes — no tea this time! :]
Once the build is done, open the emulator by running
emulator in your terminal. Tadaaa! Your emulator shows now your custom animation while booting.
To avoid this situation, the recommended alternative is to create your own product. Your challenge is to create the necessary configuration files and add your product as a new entry to the
Check out the Google documentation for building a product for more information.
Congratulations! You just built your very own Android version. Be proud, this is a quest not everyone has accomplished!
Where to Go From Here?
Download the final project using the Download Materials button at the top or bottom of this tutorial.
In this tutorial, you set up your development environment to build AOSP and you added a small customization by replacing the boot animation. You could now try to design your own animation and include it in your build. Surprise us with your design skills!
What you covered here is just the beginning of the AOSP adventure. There’s a lot to learn when it comes to Android platform development. Check out the official AOSP documentation for more information.
If you’re interested in navigating the AOSP source tree online, use the Android code search tool. This will help you get to know the source tree.
Hopefully, this tutorial supported you in your first steps with AOSP. If you have any questions about what you covered or if you want to show off your own Android customization, please join the discussion below!