LineageOS 15.1 for Axon 7 (A2017G): Using Docker to Build from Source

  • Go through the process of building LineageOS15.1 (an Android Oreo 8.1.x based ROM) for the Axon 7 A2017G using a docker container derived from a docker image I built to support this process.
  • Touch on topic Qualcomm Snapdragon 820 MSM8996 requirements for unlocking the bootloader and enabling Fastboot for certain firmware variants.
  • Outline the procedure for installing/flashing the build onto the physical device.

Axon 7 (A2017G) — Key Hardware Details

  • Chipset/SoC: Qualcomm Snapdragon 820 MSM8996
  • CPU: 2x Dual Core Kryo (total of 4 cores)
  • Architecture: 64 bit armv8-a
  • GPU: Qualcomm Adreno 530
  • Built in Storage Type: UFS 2.0
  • RAM: 4GB LPDDR4

Host Environment Requirements

Build and Configure Docker Image

Clone Docker Repo onto Host Machine

$ cd $HOME
$ mkdir docker_repo

$ cd $HOME/docker_repo/

$ git clone \
https://github.com/tonys-code-base/dev-docker-android.git

Edit Local Repo gitconfig Details

[user]
name = Your Name
email = me@example.com

Building the Docker Image

$ cd $HOME/docker_repo/dev-docker-android

$ docker build --build-arg userid=$(id -u) \
--build-arg groupid=$(id -g) \
--build-arg username=$(id -un) -t android-dev .

Create Host Directories for LineageOS 15.1 Build

Lineage Project Location

$ mkdir $HOME/lineage15

Ad-hoc Files Location

$ mkdir $HOME/lineage_dloads

Run Docker Container

  • We spin up a container using our image as follows:
$ sudo docker run -it --rm --privileged \
--cap-add=ALL \
-v $HOME/lineage15:/lineage15 \
-v $HOME/lineage_dloads:/lineage_dloads \
android-dev
  • This creates a container with the following host:container directory mappings:
|-------------------------------------------|
| host | container |
-----------------------|--------------------|
| $HOME/lineage15 | /lineage15 |
| $HOME/lineage_dloads | /lineage_dloads |
--------------------------------------------|

Initialise and Sync LineageOS15.1 Repo

Initialise

  • Change into our project directory. This will be the top level of our build (in Android’s official documentation, it is often referred to as $ANDROID_BUILD_TOP).
$ cd /lineage15
  • Run repo init, to initialise the repository. The value of lineage-15.1 supplied for parameter -b, ensures we are initialising for the correct Lineage source branch.
$ repo init -u https://github.com/LineageOS/android.git -b \
lineage-15.1

Sync

  • To download/sync local repo from the remote, run the following:
$ cd /lineage15
$ repo sync
  • Take a long break. There is around 65GB of code to download.

Add Axon 7 Device to the Build

Fix Device Combo Menu Choice

for combo in $(cat /lineage-build-targets.txt | sed -e 's/#.*$//' | grep lineage-15.1 | awk '{printf "lineage_%s-%s\n", $1, $2}')
do
add_lunch_combo $combo
done
  • /lineage-build-targets.txt was included as part of the docker image build and contains the the entry for our Axon-specific Lineage15.1 build.

Product/Device Specific Code

/lineage15/device
├── common
├── generic
├── google
├── lineage
├── qcom
└── sample
  • Start by activating our environment:
$ cd /lineage15
$ source build/envsetup.sh
  • The envsetup.sh imports many functions, commands and environment variables that are required for the build.
  • To choose the product we wish to build for:
$ breakfast
  • breakfast generates the following output:
including vendor/lineage/vendorsetup.sh

You're building on Linux

Lunch menu... pick a combo:
1. full-eng
2. lineage_axon7-userdebug
Which would you like? [aosp_arm-eng]
  • Choose option 2 to generate/fetch the Axon 7 specific code.
  • Once done, part of the output log from breakfast is shown below. You will notice in the output that the Axon 7 specific code is retrieved from remote repo https://github.com/LineageOS/android_device_zte_axon7, and the branch being checked out is lineage-15.1.
build/core/product_config.mk:238: *** Can not locate config makefile for product "lineage_axon7".  Stop.
Device axon7 not found. Attempting to retrieve device repository from LineageOS Github (http://github.com/LineageOS).
Found repository: android_device_zte_axon7
Default revision: lineage-15.1
Checking branch info
Checking if device/zte/axon7 is fetched from android_device_zte_axon7
...
Using default branch for android_device_zte_axon7
Syncing repository to retrieve project.
...
repo sync has finished successfully.
Repository synced!
Looking for dependencies in device/zte/axon7
Adding dependencies to manifest
Checking if device/qcom/common is fetched from android_device_qcom_common
Adding dependency: LineageOS/android_device_qcom_common -> device/qcom/common
...
  • Once complete, the final output provides a summary of the target we’re building
============================================
PLATFORM_VERSION_CODENAME=REL
PLATFORM_VERSION=8.1.0
LINEAGE_VERSION=15.1-20200629-UNOFFICIAL-axon7
TARGET_PRODUCT=lineage_axon7
TARGET_BUILD_VARIANT=userdebug
TARGET_BUILD_TYPE=release
TARGET_PLATFORM_VERSION=OPM1
TARGET_BUILD_APPS=
TARGET_ARCH=arm64
TARGET_ARCH_VARIANT=armv8-a
TARGET_CPU_VARIANT=kryo
TARGET_2ND_ARCH=arm
TARGET_2ND_ARCH_VARIANT=armv7-a-neon
TARGET_2ND_CPU_VARIANT=kryo
HOST_ARCH=x86_64
HOST_2ND_ARCH=x86
HOST_OS=linux
HOST_OS_EXTRA=Linux-5.3.0-61-generic-x86_64-with-Ubuntu-19.10-eoan
HOST_CROSS_OS=windows
HOST_CROSS_ARCH=x86
HOST_CROSS_2ND_ARCH=x86_64
HOST_BUILD_TYPE=release
BUILD_ID=OPM7.181205.001
OUT_DIR=/lineage15/out
AUX_OS_VARIANT_LIST=
============================================
  • You will also notice that path /lineage15/device/<company-name>/<device-name> has been created at:
/lineage15/device/zte
└── axon7
$ ls /lineage15/device/zte/axon7/*.mk
Android.mk BoardConfig.mk device.mk lineage.mk

Extracting Proprietary Blobs

Extracting from Axon 7 Device with LineageOS15.1 Installed

  • Exit the docker container.
  • Attach your Axon 7 to your host via USB.
  • Ensure that the ADB Debug Bridge is enabled via your device settings: Developer Options -> Debugging -> Android Debugging.
  • Run the following to bring up the docker container:
$ sudo docker run -it --rm --privileged \
--cap-add=ALL \
-v $HOME/lineage15:/lineage15 \
-v $HOME/lineage_dloads:/lineage_dloads \
android-dev
  • Once at a prompt within the container, change directory to top level project folder and activate the environment:
$ cd /lineage15
$ source build/envsetup.sh
  • Change directory so that we are in the Axon 7 device tree:
$ cd /lineage15/device/zte/axon7/
  • Execute the following script to pull the blobs from your device:
$ ./extract-files.sh

Extracting from LineageOS15.1 Flashable Zip

  • Download lineage-15.1–20200622-UNOFFICIAL-axon7.zip and save on the host at location $HOME/lineage_dloads, remembering that this host directory is mapped/mounted inside the container at /lineage_dloads.
  • From within the docker container, check to ensure this in fact is a Block-based zip by checking that the system* suffixes are dat/dat.br, the system folder is nearly empty and that system.transfer.list exists:
$ cd /lineage_dloads
$ unzip -l lineage-15.1-20200622-UNOFFICIAL-axon7.zip | \
grep -i -e system -e vendor

...
system.new.dat.br
system.transfer.list
system/build.prop
...
vendor.new.dat.br
vendor.transfer.list
...
  • We also have a similar scenario for the vendor* files, and they will also need to be included when extracting the blobs.
  • Create working directory for the extract process:
$ cd /lineage15
$ mkdir system_dump
$ cd system_dump
  • Unzip the required system* & vendor* files:
$ unzip /lineage_dloads/lineage-15.1-20200622-UNOFFICIAL-axon7.zip  system.transfer.list system.new.dat*

$ unzip /lineage_dloads/lineage-15.1-20200622-UNOFFICIAL-axon7.zip vendor.transfer.list vendor.new.dat*
  • Decompress the output files. This method uses brothli, which is already include as part of the Dockerfile:
$ brotli --decompress --output=system.new.dat system.new.dat.br
$ brotli --decompress --output=vendor.new.dat vendor.new.dat.br
  • Convert into mountable .img files:
$ python /usr/local/bin/sdat2img.py system.transfer.list system.new.dat  system.img

$ python /usr/local/bin/sdat2img.py vendor.transfer.list vendor.new.dat vendor.img
  • Note, the script used (sdat2img.py) for converting the vendor/system .new.dat files to mountable images, was originally sourced from this git repo.
  • Create mount point and mount system.img:
$ mkdir system
$ sudo mount system.img system/
  • Remove existing symbolic link on the mounted image and create mount point for our vendor.img, then mount it:
$ sudo rm system/vendor
$ sudo mkdir system/vendor
$ sudo mount vendor.img system/vendor/
  • Change to the location containing extract-files.sh and execute the script, passing in the location from which the blobs are to be extracted (system_dump/)
$ cd /lineage15/device/zte/axon7
$ sudo ./extract-files.sh /lineage15/system_dump/
  • Unmount images and remove the system_dump directory:
$ sudo umount /lineage15/system_dump/system/vendor/
$ sudo umount /lineage15/system_dump/system/
$ rm -fr /lineage15/system_dump

Build LineageOS15.1

  • Kick off the build by running:
$ cd /lineage15
$ brunch axon7
  • The build can take up to several hours and should be monitored intermittently for errors.
  • Once the build has completed successfully, the output should display the location and name of the LineageOS15.1 flashable zip produced by the build:
Package Complete: 
/lineage15/out/target/product/axon7/lineage-15.1-<YYYYMMDD>-UNOFFICIAL-axon7.zip

#### build completed successfully (04:42:23 (hh:mm:ss)) ####

Axon 7 A2017G — State Prior to Flashing LineageOS15.1

  • Android Version — Nougat 7.1.1
  • Build Number — ZTE A2017GV1.2.0B10
  • Bootloader — LOCKED
  • SanDisk 32GB SD Card for storing flash files

Unlock Bootloader & Enable Fastboot

$ adb reboot bootloader
  • If the above command worked successfully, you should see the bootloader screen appear on your phone. If so, the below command's output should list your device:
$ fastboot devices -l
...
488f9532 fastboot
  • Run the following to unlock the bootloader:
$ fastboot oem unlock
  • Your phone screen should then ask you to confirm the details, using your phone’s Volume Up/Down and Power buttons.

Unable to Boot into Bootloader/Fastboot

filename="emmc_appsboot.mbn" label="aboot" 
filename="fastboot.img" label="fbop"

Install Custom Recovery (TWRP)

  • Head over to https://twrp.me/zte/zteaxon7.html and download the latest TWRP .img recovery file for the Axon.
  • Ensure you are in fastboot mode, if you are not, then run adb reboot bootloader to reboot the device into fastboot mode.
  • Run the following to ensure your device is listed:
$ fastboot devices -l
...
488f9532 fastboot
  • Flash the TWRP recovery .img using the following (the below assumes an img file named twrp-3.3.1-0-ailsa_ii.img):
$ fastboot flash recovery twrp-3.3.1-0-ailsa_ii.img
  • Boot into TWRP recovery by using the phone’s “Volume Up/Down” to toggle between the options near the top of the phone’s screen until you see “Recovery Mode”, then press “Power” button to trigger a boot into TWRP.
  • From TWRP, perform a “Wipe--> "Advanced Wipe" and tick "Dalvik/ART Cache", "Data", "Cache" and "System". Perform a "format data", if you had encrypted storage.
  • You will need to stay in recovery mode for the next section ("Installing a Universal Bootstack")
  • If you accidentally exit recovery mode boot back into recovery as follows: a) Long pressing Power to switch off the device.
    b) Once the device has switched off, simultaneously hold down Power + Volume Up.
    c) When the ZTE logo appears, release the Power Button and continue holding the.Volume Up.
    d) Once the TWRP recovery screen appears, release the Volume Up button.

Install Universal Oreo Bootstack, Modem and LineageOS15.1

Bootstack

Modem (for A2017G)

  1. Choose install and navigate to location of the bootstack zip file (A2017x_LineageOS15.1_UniversalBootstack_v2_by_DrakenFX.zip).
  2. Untick “Reboot after installation is compete” and swipe to flash.
  3. Repeat the above steps for the A2017G_OreoModem.zip file.
  4. Now reboot into TWRP recovery again with the new bootstack/modem. TWRP has an option to select booting back into recovery. During the reboot, accept any prompt/warning relating to corrupt/unlocked bootloader by pressing the "Power" button.
  5. Once back in TWRP, you can finally flash your lineage-15.1-<YYYYMMDD>-UNOFFICIAL-axon7.zip.
  6. Perform a Wipe cache/Dalvik.
  7. Reboot the system, accept bootloader prompts regarding “unlocked/corrupt” bootloader by pressing the “Power” button.
  8. Give the initial boot a few minutes to load. If you don’t see the LineageOS splash screen after a few minutes, power off the device by long pressing Power key and let it reboot once more.
LINEAGE_VERSION=15.1-20200629-UNOFFICIAL-axon7

Final Points

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Tony Tannous

Tony Tannous

Learner. Interests include Cloud and Devops technologies.