Android 12 source was released in 2021. My test phone at the time was a Pixel 3 XL. This article keeps that hands-on record and pins the release-build example to android-12.0.0_r3. Verify version mappings in the AOSP tags/build numbers table.
Compiling the code locally offers several advantages:
- Direct Debugging: You can flash the build onto a physical device for local debugging and import the code into Android Studio.
- Userdebug Builds: These provide additional debugging capabilities. adb root/remount still depends on adbd, AVB/verity, partition layout, and build configuration. A userdebug build does not make every directory writable or replace an app’s own debugging permissions.
- Studying the System: You can enable more system debug logs, add your own, and change the code to see how it works.
Historical version note (reviewed 2026-10-14): Android 12 r3, Pixel 3 XL, and the 2021 screenshots are references for studying an old release, not recommendations for current devices or production firmware. The r3 security patch level is 2021-10-05. Some original screenshots instead show the master development branch:
Tiramisu/AOSP.MASTERdoes not prove an Android 12 r3 build. They are retained with explanations below.
For current AOSP, use the download and build guides. In a separate checkout, the documented android-latest-release branch follows current releases; it does not pin Android 12:
1 | # Current AOSP example: use a separate working directory, not the Android 12 tree. |
This is the current guide’s Cuttlefish virtual-device example, not a Pixel 3 XL flashing target. Its product-release_config-variant format differs from Android 12’s product-variant. Check availability in the actual checkout and save repo manifest -r output to identify revisions. Do not mix vendor files across releases. The USTC mirror limits concurrency to four, so do not copy the official-server -j8 setting there.
For source browsing alone, use cs.android.com. Reproducing this article requires:
- A matching Pixel 3 XL (crosshatch) whose bootloader can be unlocked. Pixel 3 is blueline and is a different target. SIM unlocking does not imply bootloader unlocking; “Pixel 3 or newer” does not mean all later models can run Android 12.
- An x86-64 Linux host with a case-sensitive filesystem and sufficient storage/RAM. The historical host screenshot shows Ubuntu 18.04.6. The old 32GB suggestion was contemporary experience, not a current guarantee; swap is not equivalent RAM. Current official requirements specify at least 400GB free storage and 64GB RAM. Old-branch resource needs still depend on target and parallelism.
1. Downloading the Code
At the time, downloading from Google’s servers in China could be painfully slow; even .repo could get stuck. That is why I used the USTC AOSP mirror as an alternative here; the official download guide remains the reference. Follow mirror protocol and concurrency rules. Its current documentation uses HTTPS, replacing the old git:// URLs in this article.
Download into the Linux filesystem you will build from. Running Git/Repo commands on WSL2 or macOS does not establish a validated Android 12 build/USB-flashing environment. Do not assume Windows-mounted or case-insensitive directories meet source-tree requirements.
1.1 Step 1: Download the Repo Tool
On Ubuntu repositories that provide the package, install the launcher using the official setup instructions:
1 | sudo apt-get update |
If your distribution lacks the package, use the official manual download/signature-verification procedure. Do not install an HTTP error page as an executable or edit the launcher’s internal REPO_URL. The launcher and downloaded Repo tool can have different versions; retain the actual repo version output.
1.2 Step 2: Configure Personal Information
If you haven’t installed Git yet, do so first. Then configure your identity:
1 | git config --global user.name "Your Name" |
1.3 Step 3: Create a Working Directory
1 | mkdir Android_12_AOSP |
1.4 Step 4: Initialize the Repository
Choose the version first. For this article, use the pinned Android 12 r3 tag in section 1.4.2. Keep current-branch experiments in a separate checkout. -b selects a manifest branch or tag; device/build-matched binaries are required regardless of whether the option appears.
1.4.1 Original Default-Branch Workflow (Historical)
The original unpinned workflow used the then-current master branch. It did not download every Android release or guarantee Android 12. Repo defaults and remote settings can change; select the version explicitly.
If access to the Repo tool’s own repository fails, the mirror documents this exported variable:
1 | export REPO_URL=https://gerrit-googlesource.proxy.ustclug.org/git-repo |
This setting is separate from the manifest’s -u URL; do not edit the launcher. Continue with the pinned tag below for this example, and run the shell setup in section 3.2 for either workflow.
1.4.2 Option B: Download a Specific Tag
Use the build numbers table to select a version for the device. This original 2021 list is a historical snapshot, not a claim that Android 12 has only two tags:

This example pins android-12.0.0_r3, mapped to SP1A.210812.016.A1, with Pixel 3 XL in its supported-device list. Selecting a tag pins the manifest; it does not automatically make a shallow clone, retain only one commit, or guarantee a smaller download.
1 | repo init -u https://mirrors.ustc.edu.cn/aosp/platform/manifest \ |
For the official server, change -u to https://android.googlesource.com/platform/manifest and retain the tag. Recheck manifest, device configuration, and binaries when changing versions; do not reuse a vendor directory from an unrelated tag.
1.5 Step 5: Sync the Code
repo init configures the Repo client and manifest; project content still needs synchronization. USTC limits concurrency to four:
1 | repo sync -c -j4 |
-c focuses on the manifest-required branch; it does not turn every repository into a shallow clone. Inspect the failing project and error before retrying. Transient network failures can be retried; insufficient disk space, missing refs, permissions, and local changes need specific fixes. Avoid indefinite three-second retries that obscure persistent failures. Proceed only after sync exits successfully.
2. Downloading Drivers (Proprietary Binaries)
Physical-device builds need matching proprietary binaries. These can include HALs, userspace libraries, vendor images, and firmware; they are not all driver source code. Match the device, source Build ID, and vendor instructions regardless of the presence of -b. These files are also distinct from Google Apps or Pixel Launcher.
2.1 Drivers for the Master Branch
Preview binaries apply only to listed device/development-build combinations, not arbitrary master/main commits. The original image’s build number 7798681 is historical and does not replace the r3 binaries:

If matching binaries are unavailable, do not infer compatibility from the Pixel model alone. Select a supported combination or a corresponding virtual-device target.
2.2 Drivers for a Specific Tag
On the Google driver binaries page, select Pixel 3 XL / Android 12.0.0 / SP1A.210812.016.A1. The r3 mapping is also confirmed by build_id.mk.

The image also includes SP1A.210812.015; select the correct row. Download both the matching Google vendor image and Qualcomm package, checking each SHA-256 against the page. Do not mix versions.

2.3 Extracting Drivers
Unpack the matching archives and run their extraction scripts from the source root. Read the license and confirm only if you accept it; do not treat typing I ACCEPT as a substitute for review. These filenames are specific to the example:
1 | ./extract-google_devices-crosshatch.sh |

1 | ./extract-qcom-crosshatch.sh |

Check the generated files under vendor/google_devices/crosshatch and vendor/qcom/crosshatch. Extraction success means files were written, not that the combination is compatible or bootable.
3. Compiling the Code
This target uses an x86-64 Linux build host. macOS platform-build support ended in 2021; browsing the source on a Mac does not establish that this Android 12 target can be built there.

3.1 Initializing the Build Environment
Install host dependencies using the official setup guide. This is its general Ubuntu package list. Older extras such as libncurses5 from the original article are not necessarily available under the same names on newer distributions.
1 | sudo apt-get update |
Android 12’s old prebuilt tools can still require older host libraries. Diagnose the failing tool and use a matching Linux environment; do not treat arbitrary old-library downloads or system-library replacement as a universal fix. Use the toolchain selected by the checked-out branch rather than applying a current Android branch’s JDK requirements.
3.2 Setting Up the Shell Environment
Every time you open a new terminal, you must run:
1 | source build/envsetup.sh |
3.3 Selecting a Target
The Android 12 r3 AndroidProducts.mk lists aosp_crosshatch-userdebug. Pixel 3 XL is crosshatch; select the name rather than a historical menu number:
1 | lunch aosp_crosshatch-userdebug |

The original menu numbered it 25; numbering can change:

The next configuration image belongs to the historical master build. It shows PLATFORM_VERSION=Tiramisu and BUILD_ID=AOSP.MASTER, not the expected r3 output. Check product, version, and Build ID, not merely the userdebug variant.

3.4 Starting the Build
The first full build means a long wait, especially if CPU or memory is limited. Run m for the selected product’s default build. -jN controls parallelism; otherwise the build system selects it. More jobs do not guarantee a faster build and can increase memory pressure.
1 | m |
Interpret helper commands using Android 12 envsetup.sh:
| Command | Scope |
|---|---|
m / m droid |
Normal selected-product build, not all products at once |
m <module> |
An existing module target; not proof that every flashable image was updated |
mma / mmma <dir> |
Modules in the current/specified directory and their dependencies |
croot |
Return to the source-tree root |
m help / hmm |
Build-target/environment-command help |
m clean |
Clear the configured output directory’s contents; check OUT_DIR first, rather than assuming the current directory’s out/ |
The branch defines what m all includes; it is not a promise to compile every Android.mk independently. Android 12 Soong’s clean implementation clears the actual output location and preserves its directory. Routine incremental builds do not need a clean each time.
This is another original master-build image with contemporary deprecation warnings, not a new r3 validation:

The recorded successful build took 03:40:47. That duration does not generalize across hardware, branches, or cache states. Confirm a successful exit and matching target artifacts for your own build before flashing.

4. Flashing the Device
Use a dedicated test device and match its Pixel 3 XL target, binaries, and artifacts. Bootloader unlocking and the -w option below erase user data; back up first. Enabling OEM unlocking is not itself unlocking. If needed, follow the official procedure: run fastboot flashing unlock in bootloader mode and confirm on the device. Do not casually relock a device running an unverified custom image.
Check adb/fastboot versions and the connected target. Keep the configured envsetup/lunch shell so ANDROID_PRODUCT_OUT points to this build’s crosshatch output. With multiple devices, select the intended serial using -s.
1 | # In the successfully built Android 12 source tree and configured shell: |
The original adb reboot fastboot enters userspace fastbootd on supported devices, unlike adb reboot bootloader. The flashing tool may change modes for dynamic partitions; see the fastbootd documentation. Do not bypass partition or compatibility checks with --force.
The Android 12 fastboot implementation reads flashall images from ANDROID_PRODUCT_OUT and normally reboots on completion. A second fastboot reboot is not mandatory. flashall is not a universal replacement for matching bootloader/radio firmware; resolve firmware mismatches using the device-specific official procedure.

The top of the old image contains an earlier command error; the later flashall shows OKAY/Finished. That is historical tool output, not current r3 device acceptance. After booting, compare ro.build.id, ro.product.device, and ro.build.type with the built artifacts, then check required USB/display/network functions. Reaching a home screen does not validate all hardware.
I found the AOSP Launcher I had just built pretty ugly and bare-bones. Without Google’s closed-source extras, it looked rather sparse. I much preferred the official Pixel Launcher. That was my reaction to those 2021 builds, not a review of their current versions.
For restoration, select the matching device in Google Factory Images and follow its version/anti-rollback instructions. Restoration can erase data and is not guaranteed to fix every flashing or hardware failure.
5. What’s Next?
This guide focused on downloading, compiling, and flashing. I will cover how to import code into an IDE, modify modules, and debug in a follow-up article.
About Me && Blog
Below are my personal details and links. I look forward to connecting and sharing knowledge with fellow developers!
- About Me: Includes my WeChat and WeChat group links.
- Blog Navigation: A guide to the content on this blog.
- Curated Android Performance Articles: A collection of must-read performance optimization articles. Self-nominations/recommendations are welcome!
- Android Performance Knowledge Planet: The paid community stopped operating in 2026 and no longer accepts new members; this link preserves its history.
“If you want to go fast, go alone. If you want to go far, go together.”
