TWRP Recovery’s strength makes it a worthy choice in the brush industry. For many devices, the first step is to choose a suitable TWRP and brush it. Currently, there are official adaptations for popular models from several brands, and some developers have also adapted unofficial versions of their own for models not officially covered.

However, developers can’t do everything, and there will always be some models that no single developer can fit. In such a situation, would you rather wait until someone has time to adapt, or do you want to be well-fed right away?

Do it yourself, of course!

In fact, TWRP adaptation is not as difficult as might be expected. Theoretically, you only need to do it in the Android source code, prepare the necessary files, and run the compile command to complete the adaptation. The following author will explain how to adapt TWRP Recovery step by step based on his own experience.

Configuration requirements

Building TWRP is as resource-intensive as building Android, so make sure your computer is configured properly. The operating environment must be Linux distribution 1. The following uses Ubuntu 18.04 as an example.

project requirements
The operating system 64-bit Linux distribution, Ubuntu 18.04 is recommended
Disk space At least 30 gb. Android source code eats a lot of disk space
memory At least 4GB, 8GB or more is recommended

Step 1: Prepare the build environment

(1) Install necessary software packages

TWRP compilation requires a series of software packages to support. In Ubuntu, you can install it in one go using the apt command:

Update the software source
sudo apt update
Install software packages
sudo apt install git-core gnupg flex bison gperf \
zip curl zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386 \
lib32ncurses5-dev x11proto-core-dev libx11-dev lib32z-dev ccache \
libgl1-mesa-dev libxml2-utils xsltproc unzip
# its installation
sudo apt install openjdk-8-jdk
# Install build-essential If there is an error, use the command on line 2 below
sudo apt install build-essential
sudo apt install gcc g++ make
Copy the code

(2) Configurationccache

Ccache is a caching tool that improves compilation efficiency by caching intermediate files (preprocessed code, output files *.o, etc.) that are then copied instead of regenerated the next time the same source file is compiled. The most immediate benefit is that you can recompile much faster after making clean.

The wavy line “~” is shorthand for the Home directory. We enable ccache by adding the following statement to the end of the Bash configuration file ~/.bashrc. Ccache is stored in the user directory (~/.ccache) by default. You can change the environment variable CCACHE_DIR to set it to another disk partition.

# enable ccache
export USE_CCACHE=1
Change the ccache cache path
export CCACHE_DIR=/mnt/seagate_drive/.ccache
Copy the code

Then restart the terminal, or run source ~/.bashrc, or start a new Bash session for the above statement to take effect.

Alternatively, you can set the size of the disk space occupied by the CCache cache:

ccache -M 50G
Copy the code

Step 2: Download the Android source code

TWRP cannot be compiled without Android source code because it relies on components in the Android source code. OmniROM is recommended, which has an official partnership with TWRP’s development team, TeamWin, and holds the latest source code for TWRP by OmniROM.

(1) Downloadrepo

Repo is a Google-developed software warehouse management tool, written in Python 2.7, for bulk management of source code organized by Git. Use the following command to download the repo to the /usr/bin directory contained in PATH:

sudo curl https://storage.googleapis.com/git-repo-downloads/repo > /usr/bin/repo
sudo chmod +x /usr/bin/repo
Copy the code

(two) download OmniROM source code

You first create a dedicated directory on disk for the OmniROM source code, and then use repo Init to initialize the source code repository.

mkdir omni9
cdOmni9 repo init -u git://github.com/omnirom/android.git android - 9.0 - bCopy the code

The -b parameter specifies the Android version you want. Android-6.0 is generally used to compile 3.0.x series versions, but newer versions require Android-7.0 or higher. I strongly recommend choosing only the latest TWRP version, 3.3.1-0, so use Android-8.1 or Android-9.0 instead.

Once the initialization is complete, we start downloading:

repo sync
Copy the code

Depending on network conditions and computer performance, the whole process can take several hours or more than half a day. You just need to be patient. Once the download is complete, there are many more folders in the Omni9 directory, including.repo.

(3) Tips

  • You can use the -j parameter to open more download processes to improve download efficiency.

    repo sync -j8
    Copy the code
  • If an error occurs during the download, you can add two parameters to allow the REPO to continue downloading even if it encounters an error. -f causes a network error to continue, and –force-sync causes a conflict to continue.

    repo sync -f --force-sync
    Copy the code

Minimal Manifest for TWRP

Minimal Manifest for TWRP if disk space is low, consider Minimal Manifest for TWRP, which contains only the minimum components needed to compile TWRP and also contains TWRP source code and required dependencies. The project’s address is here: github.com/minimal-man… .

Take downloading Omni 8.1’s Minimal Manifest as an example, follow the following steps to download a lean, space-saving, resource-saving code tree:

Create a folder to store the code tree
mkdir omni8_minimal
cd omni8_minimal
Initialize the source repository
You can change the branch name "twrP-8.1" after "8.1" to the android version you want to download, support 4.4~9.0Repo init -u git://github.com/minimal-manifest-twrp/platform_manifest_twrp_omni.git -b twrp-8.1 --no-clone-bundle# start sync
repo sync -f --force-sync
Copy the code

Note:

The measured TWRP-6.0 and TWRP-8.1 can be compiled normally. The latest TWRP-9.0 due to strict error detection, will lead to a variety of compiler errors, do not recommend to choose!

Step 3: Download TWRP source code

Note:

(Minimal Manifest for TWRP) (Minimal Manifest for TWRP) (Minimal Manifest for TWRP)

The twRP-8.1 branch also contains the Busybox source code, so there is no need to add a Busybox project. However, TWRP-9.0 is not included for unknown reasons and is not recommended.

Generally, the OmniROM source tree does not contain the TWRP source code, and AOSP Recovery is downloaded by default. Therefore, we need to manually download the TWRP source code and add it to the REPO’s repository configuration file (MANIFEST). TWRP is available at github.com/omnirom/and…

There are two options for changing the configuration of the OmniROM repository. (The first option is recommended for Android 9.0 to avoid unexpected problems.)

Solution 1: Change the configuration file of the local warehouse

The local warehouse configuration files are in the. Repo/local_MANIFESTS/directory of the source tree. Its original purpose is to collect all the source repository addresses involved in the official supported models of OmniROM and store them in roomService.xml so that they can be updated together later with Repo Sync. It does not change with updates to the Android official repository configuration (other XML manifest files in the.repo directory), so it is recommended to add twRP-related repository addresses to it.

Assume the source root directory is omni9. First, go to omni9/.repo and check for ** local_MANIFESTS and roomService.xml ** in that directory. If not, create one manually with the following content:


      
<! --Please do not manually edit this file-->
<manifest>
	<project name="OmniROM/android_bootable_recovery" path="bootable/recovery" remote="github" revision="android-9.0" />
	<project name="OmniROM/android_external_busybox" path="external/busybox" remote="github" revision="android-9.0" />
</manifest>
Copy the code

Then, to the default configuration file omni9 / repo/manifests/default XML to carry on the following changes, to remove AOSP Recovery corresponding manifest projects:

- 
      
+ 
      
Copy the code

Finally, go back to the omni9 directory and run the following command to download the TWRP source code:

repo sync --force-sync bootable/recovery
repo sync --force-sync external/busybox
Copy the code

Solution 2: Add TWRP related items to the default configuration file

This scheme worked in the previous Android 8.1 source code. Assume the source root directory is omni8.

First, go to the source tree and delete the downloaded AOSP Recovery:

cd omni8
rm -rf bootable/recovery
Copy the code

Then clone TWRP Recovery source code:

git clone https://github.com/omnirom/android_bootable_recovery bootable/recovery
Copy the code

Then, the MANIFEST project corresponding to AOSP Recovery is deleted. Open the omni8 /. Repo/manifests/default. XML, for the following changes:

- 
      
+ <! -- project path="bootable/recovery" name="platform/bootable/recovery" groups="pdk" /> -->
Copy the code

Add TWRP to manifest. Open omni8 / repo/manifests/omni – default. The XML, in the < manifest > section at the end of the following changes:

<project path="packages/apps/OmniSwitch" name="android_packages_apps_OmniSwitch" remote=" omniROM "revision=" Android-8.1"  /> <project path="packages/apps/OpenDelta" name="android_packages_apps_OpenDelta" remote="omnirom" Revision =" Android-8.1 "/> <project path="packages/apps/Phonograph" name="android_packages_apps_Phonograph" Remote = "omnirom" revision = "android 8.1" / >+
+ 
      
+ 
      
 </manifest>
Copy the code

So, we can compile TWRP; And next time we can update TWRP with repo Sync.

Step 4: Collect the configuration file

(1) Configuration file composition

To compile TWRP, the device configuration file is required. Device configuration files generally include the following sections. The paths mentioned below are based on the Android source root directory:

  • Device Configuration Parameters

    Device configuration parameters are located in the Device directory and define a series of basic information about the device. It consists of a series of Makefiles (*.mk) with device-specific source code.

  • The kernel source

    The kernel source code is located in the kernel directory and is compiled at the same time as Android is compiled. It is important to note that not all devices have the corresponding source code, and some devices use a prebuilt kernel, usually located in the configuration parameter directory.

  • Vendor Configuration Parameters

    Vendor configuration parameters are located in the vendor directory, which stores vendor-specific configuration information and various precompiled files (executable files, runtime, etc., usually not open source). Quite a few devices require vendor profiles only when compiling the entire Android system, not when compiling TWRP.

(b) Search GitHub for configuration files

How do I get the configuration files for your device? Go to a lot! GitHub usually has various configuration files for various devices, which can be easily searched. For example, if your mobile phone is Huawei P6 (MODEL: P6-C00), use the following keywords to search for the three configuration files on GitHub:

  • Configuration parameters:device p6ordevice huawei p6
  • Kernel source code:kernel p6orkernel huawei p6
  • Manufacturer configuration parameters:vendor p6orvendor huawei p6

It’s worth noting that a lot of devices have their own code names, and developers who post profiles on GitHub tend to refer to devices only by code names. For example, the mimax is code-named hydrogen or helium, and the Samsung Galaxy S5 dual card is code-named kltechnduo. In this case, you can’t use mimax, Galaxy S5, or G9008W to search for configuration files. To find the corresponding relationship between code name and device, you can go to moqu download page, Lineage OS download page, Resurrection Remix download page and other open source ROM websites.

Different open source ROM, the applicable configuration file is often different, the parameters supported in the configuration file are often different. Since we use OmniROM as a vehicle for compiling TWRP, it’s a good idea to find a configuration file for OmniROM — the one in the configuration parameters directory with omni_< device name >.mk. If it cannot be found, refer to the method in the next step, “Modify the Configuration File.”

(3) Save the configuration file to the corresponding directory

Once you have found a repository available on GitHub, clone git to the repository. How do I confirm “corresponding location”? It’s really simple.

The specification of the device configuration parameter directory is Device /< vendor name >/< device name >, and the kernel source code and vendor configuration parameter path are similar. For example, the huawei P6 configuration file directory is as follows:

  • Device configuration parameters:device/huawei/hwp6_u06
  • Kernel source code:kernel/huawei/hwp6_u06
  • Manufacturer configuration parameters:vendor/huawei

According to AOSP rules, each repository in the Android source directory has a fixed naming convention, which replaces the “/” with “_” in the path above, so it is easy to guess where you will find the repository. However, if you encounter a repository that is not named according to the specification, you must follow the rules above to infer which directory you should place it in.

Step 5: Modify the configuration file

Off-the-shelf configuration files are not always available out of the box. Not all of them were designed for our existing Android source code when they were born. Out-of-the-box availability was limited to a few popular models, and most of the configuration files only worked with different versions of OmniROM and even other ROMs — typically CyanogenMod. Therefore, modifying the configuration file is a required course for TWRP.

(1) Determine whether the configuration file can be directly applied

If your device is lucky enough to be officially supported by TWRP, you won’t have to work too hard to change the configuration file, just use it out of the box. You can find your model on the TWRP website.

If it’s not officially supported, don’t despair, there may be unofficial adaptations by developers. Simply check the repository of device parameters you find on GitHub to see if there is a branch corresponding to the current OmniROM version. In theory, versions suitable for Android 7.0 and above can be used directly with OmniROM 8.1.

(2) ModificationBoardConfig.mk

Boardconfig. mk is part of the device parameters file, which stores many parameters compiled with boot.img and Recovery. Setting these parameters correctly is the premise to ensure normal TWRP compilation. Recovery and boot.img are both Android boot images.

Note:

  • All directories below refer to the Android source root directory.
  • Due to typesetting limitations, the following Settings do not include description of value requirements. The value of Whether is Boolean and can be trueTrueTrue or FalseFalse. The rest are numeric values or string values without quotation marks.

1. Kernel packaging parameters

These parameters control how the kernel image files are packaged into the boot image. They are generally set up in advance by the developer and do not need to be changed. The boot image is generated by mkbootimg, and its source code is in System /core/mkbootimg.

Parameter names instructions
BOARD_KERNEL_CMDLINE Operating parameters of the kernel
BOARD_KERNEL_BASE The base address of the kernel in the boot image
BOARD_KERNEL_PAGESIZE The kernel’s page size
BOARD_MKBOOTIMG_ARGS Need to pass tomkbootimgAdditional parameters for the tool
BOARD_BOOTIMAGE_PARTITION_SIZE The size of the boot partition
BOARD_RECOVERYIMAGE_PARTITION_SIZE Recovery Partition size
BOARD_CUSTOM_MKBOOTIMG Some special equipment requires special onesmkbootimgTools to generate boot images (e.g., Rockchip). Specify the path for the tool here.
BOARD_CUSTOM_BOOTIMG_MK For some specially formatted boot images, users can write their own makefiles. Specify the path to your custom Makefile file here.

Note:

  • BOARD_CUSTOM_MKBOOTIMGThis parameter does not apply to Android 8.0 or later. If you add this parameter, an error will be reported.
  • BOARD_CUSTOM_BOOTIMG_MK It may not be supported by the Android 8.x build system and cause an error, but it is not a problem in Android 9.0 and can be used safely.

2. Kernel compilation parameters

Developers of all kinds of third-party open source ROMs recommend that you build your own kernels instead of using prebuilt kernel images from device parameter files. This is because a compiled kernel image cannot be modified, is only suitable for a particular version of the system, and will not work properly, or even boot up, on a new system. If you find a device parameter file that provides a pre-compiled kernel and you can find the kernel source, set the options below.

Parameter names instructions
TARGET_KERNEL_SOURCE Specifies the directory where the kernel source code resides
TARGET_KERNEL_CONFIG Specifies the configuration file to use to compile the kernel.

The configuration file is located in the kernel source codeArch /< system platform >/configsIn the
BOARD_KERNEL_IMAGE_NAME Specifies the kernel image name. The Android compiler uses it to find the kernel image

The compiled kernel image is located in the kernel source codeArch /< system platform >/bootIn the
KERNEL_TOOLCHAIN Specifies a cross toolchain for compiling the kernel. For some devices, the kernel compiled using the Android source code compiler cannot be started, and a dedicated or older version of the compiler must be used
TARGET_KERNEL_CROSS_COMPILE_PREFIX withKERNEL_TOOLCHAINIn conjunction, specify the prefix for the cross toolchain

However, if you really can’t find the kernel source, you can specify the following parameters to use an existing kernel (such as the kernel extracted from the boot.img and recovery.img files that work, or the kernel provided by the device parameter file provider). However, it is not guaranteed to work properly under the new version of the system!

Parameter names instructions
TARGET_PREBUILT_KERNEL Specifies the path to the precompiled kernel
TARGET_PREBUILT_RECOVERY_KERNEL Specify the precompiled kernel path for Recovery

Note:

  • Kernel source and precompiled kernel can only choose one of the two, cannot set all the parameters in the above two tables at the same time!
  • Depending on the platform,BOARD_KERNEL_IMAGE_NAMEThere will be different values. ARM platform forzImage, the x86 platform isbzImage, using u-boot platform (such as NXP, raspberry PI)uImage.

3. Recovery options

Boardconfig. mk also includes several options for setting Recovery, with the main parameters shown below. Generally, the device parameter file provider has already set the corresponding parameters.

Parameter names instructions
TARGET_RECOVERY_PIXEL_FORMAT Specify the pixel format for Recovery display. Different devices have different pixel formats, common ones areRGB_8888,RGB_565Such as, improper Settings will cause the screen, black screen and other faults.
TARGET_RECOVERY_FSTAB Specify Recovery partition table information file (fstab). This file records information about the partitions available for mounting, which users can choose to mount on the Mount page of Recovery.
BOARD_RECOVERY_SWIPE Enable the slide operation, which in non-touch Recovery allows the user to swipe up and down the screen to move highlighting options. Generally enabled.
DEVICE_RESOLUTION Specifies the resolution of the device.
RECOVERY_GRAPHICS_USE_LINELENGTH Recovery graphics display using “line spacing”. The specific effect is not clear, but if this option is set improperly, Recovery screen will be lost.
BOARD_HAS_SDCARD_INTERNAL Set whether the device has a built-in SD card. New devices at this stage all have at least 8GB of eMMC storage, and all will have built-in storage/data/media/0Chalk it up to a built-in SD card.
RECOVERY_SDCARD_ON_DATA In Recovery, determine that the SD card is locateddataThe partition. New devices at this stage will all have built-in storage/data/media/0Chalk it up to a built-in SD card. With the aboveBOARD_HAS_SDCARD_INTERNALEcho.
TARGET_RECOVERY_INITRC Self-appointedinit.rcThe path.init.rcIs an Android initializerinitThe most important script to playmain()Function. This option allows users to write their owninit.rcTo support a variety of customized equipment platform.

Note: TARGET_RECOVERY_INITRC only applies to official AOSP Recovery and older versions of Recovery prior to Android 6.0 (such as TWRP 2.x and ClockworkMod). Newer versions of TWRP (≥3.0) simply ignore this option and use only the init.rc it provides.

4. Special options for TWRP

TWRP has some exclusive options, some of which are shown below.

Parameter names instructions
TW_THEME Specifies the topic for TWRP. Different themes determine the different styles of TWRP display, including resolution, screen orientation, and so on.

The default topics available are:portrait_hdpi,portrait_mdpi,landscape_hdpi,landscape_mdpi,watch_mdpi.

This parameter must be set, otherwise TWRP compilation rules will report errors during compilation!
TW_CUSTOM_BATTERY_PATH Specify the battery path. The battery path is the kernel system directory/sysThe path where the battery device is located, which TWRP accesses to display battery power.

Example: The path of huawei P6 is/sys/devices/platform/bq_bci_battery.1/power_supply/Battery.
TW_BRIGHTNESS_PATH Specify the brightness path. The brightness path is the kernel system directory/sysThe path where the screen adjustment file is located, TWRP edits it to change the screen brightness.

Example: The path of huawei P6 is/sys/devices/platform/k3_fb.1/leds/lcd_backlight0/brightness.
TW_DEFAULT_BRIGHTNESS Specify the default brightness. Value range:
[ 0 . 255 ] [0255]
.
TW_MAX_BRIGHTNESS Specify the maximum brightness. Value range:
[ 0 . 255 ] [0255]
.
TW_FLASH_FROM_STORAGE The effect of this parameter is unknown and may only apply to2.xVersion. in3.2.3-0The version is invalid.
TW_EXTERNAL_STORAGE_PATH Specifies the mount path for external storage.
TW_EXTERNAL_STORAGE_MOUNT_POINT Specifies the mount point for external storage.
TW_DEFAULT_EXTERNAL_STORAGE Specifies whether the default storage is set to external storage. in3.2.3-0The version is invalid.
TW_EXCLUDE_SUPERSU Specifies whether SuperSU is not included. TWRP with SuperSU prompts the user Root for the phone on every reboot.
TW_INCLUDE_NTFS_3G Specifies whether to include the NTFS-3G module to support NTFS partitions.
TW_IGNORE_MISC_WIPE_DATA Specifies whether the cleanup passed from the Bootloader is ignoreddataPartition instructions. Here,miscThe partition holds the Bootloader passed to the boot image (bootorrecovery) to control the behavior of their activation.
TW_EXTRA_LANGUAGES Specifies whether to add additional languages. Additional languages include Chinese, Japanese, etc. By default TWRP will only contain English and several European languages (German, French, Russian, Danish, etc.).

5. Encryption-related options

Most of the mobile phones that can be bought today have been encrypted on the data partition. If you want to read the data partition in the system, there must be a decryption process. The initiation of official systems (including Recovery) includes the decryption process; In order for TWRP to read the data partition, the following options must be set and other components must be included for decryption.

I know of two encryption schemes: Qualcomm’s QSEECOM encryption, and Huawei’s private file system forced encryption (based on F2FS). Only the former is supported by TWRP developers, many of TWRP’s gods have added Qualcomm’s encryption components to their models. Specific to your Qualcomm processor models to increase the encryption function of the method, I will choose a day to write a tutorial. (The official TWRP for Mi Max is the developer of qualcomm decryption components, that’s me!)

Parameter names instructions
TW_INCLUDE_CRYPTO Specifies whether TWRP contains encryption components and enables encryption and decryption
TARGET_HW_DISK_ENCRYPTION Specifies whether the device includes hardware encryption. At this stage, the devices that enable encryption are generally hardware encryption
TARGET_KEYMASTER_WAIT_FOR_QSEE For Qualcomm solutions, specify whether to wait for the Qualcomm Encryption service program when Recovery startsqseecomdDecryption is complete. It must be enabled, otherwise the decryption function of TWRP is useless

6. Debug related options

TWRP supports logCAT debugging and can read logCAT logs as in Android.

Parameter names instructions
TWRP_INCLUDE_LOGCAT Specifies whether to include in TWRPlogcat
TARGET_USES_LOGD Specifies whether to enable logging in TWRPlogd

(iii) Modification of non-OmniROM configuration files

Not all devices have a configuration file for OmniROM, so you need to modify the configuration file for other ROMs. This is usually the case on slightly older devices, which often only have configuration files for older versions of ROMs such as CyanogenMod 4.x. However, the modification process is not complicated.

1. Modify device Makefile (product Makefile)

Each ROM’s device parameter file has a ROM-specific “device Makefile” **, which defines the basic information for the device and serves as a well-deserved “portal”.

Definition of the device Makefile

Let’s examine this type of Makefile. It can be divided into three parts – inheritance part, device definition part, and user – defined part. A sample device Makefile looks like this (the device is Huawei Honor 10 View, omits the beginning of the Apache 2.0 protocol) :

#
# This file is the build configuration for a full Android
# build for grouper hardware. This cleanly combines a set of
# device-specific aspects (drivers) with a device-agnostic
# product configuration (apps).
#

# Sample: This is where we'd set a backup provider if we had one
# $(call inherit-product, device/sample/products/backup_overlay.mk)
$(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk)

# Get the prebuilt list of APNs
$(call inherit-product, vendor/omni/config/gsm.mk)

# Inherit from the common Open Source product configuration
$(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_base_telephony.mk)

#treble
$(call inherit-product, $(SRC_TARGET_DIR)/product/treble_common.mk)

# must be before including omni part
TARGET_BOOTANIMATION_SIZE := 1080p

# Inherit from our custom product configuration
$(call inherit-product, vendor/omni/config/common.mk)

# Inherit from hardware-specific part of the product configuration
$(call inherit-product, device/huawei/berkeley/device.mk)PRODUCT_PROPERTY_OVERRIDES += ro.hardware.nfc_nci=nqx.default ALLOW_MISSING_DEPENDENCIES := true DEVICE_PACKAGE_OVERLAYS  += device/huawei/berkeley/overlay# Discard inherited values and use our own instead.
PRODUCT_NAME := omni_berkeley
PRODUCT_DEVICE := berkeley
PRODUCT_BRAND := Huawei
PRODUCT_MODEL := Honor View 10

TARGET_VENDOR := huawei
Copy the code
① Inheritance

Inheriting part refers to the part of the preceding source file that calls inherit-product, so that the current device configuration file inherits other configuration files. Inherited, including generic configuration files provided by ROM (located in the build/make/target directory), and device-specific configuration files (usually in the device parameter file directory, device_< device name >. Mk or device.mk).

When writing, you generally just need to move the code from other devices to use, but you need to be careful to distinguish between 32-bit and 64-bit.

(2) Equipment definition

The device definition part is the core of the device configuration file, which is the basis for the compilation system to find the device parameter file. Including the following variables, is indispensable:

The variable name instructions
PRODUCT_DEVICE The device name.Must fill in, this is the core parameter, used to compile the system for device name identification!
PRODUCT_NAME Product name, usually in the formatomni_<PRODUCT_DEVICE>

Must fill in, the build system uses this to configure the build environment for you!
PRODUCT_BRAND Brand name
PRODUCT_MODEL Device model. It is displayed under About Device in system Settings
TARGET_VENDOR Vendor name
User – defined part

Anything other than the above two types of code is user-defined code. Additional parameters can be placed.

Rename the device Makefile

Depending on the ROM, device Makefiles will have different sizes of file names. The common ones are as follows:

  • OmniROM: Omni_ < device name >.mk
  • CyanogenMod: cm.mk
  • The magic fun:mokee.mk(Old version),Mk_ < device name >.mk(9) of the Android

Despite the filename differences, they are virtually the same. Simply rename the name omni_< device name >.mk. Note Device Name in the file name is the value of PRODUCT_DEVICE in the file. Otherwise, the compilation system will report an error and abort the file.

2. Specify the call chain for the device parameter file Makefile

Call to Makefile (*.mk) with a chain relationship. The starting point for this chain of calls is to compile the system’s Makefile that manages the device configuration files — build/make/core/product_config.mk, which checks for androidProducts.mk in the device configuration file directory, And locate the “meta-makefile” of the device according to AndroidProducts.mk.

AndroidProducts.mk

Androidproducts.mk is the entry point to the device configuration file. The compiler determines that a device does have a configuration file by looking for all androidProducts.mk in the Device directory. This file is used to include the device Makefile by passing it to the PRODUCT_MAKEFILES variable. It is usually written as follows:

PRODUCT_MAKEFILES := \
    $(LOCAL_DIR)/omni_berkeley.mk
Copy the code
product_config.mk

One step in the product_config.mk working logic is to retrieve the configuration file in the device/ directory after accepting the device configuration name entered by the user. If the configuration file does not exist, an error will be reported. The code looks like this (with the original comments and additional comments from the author) :

# -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
# Include the product definitions.
# We need to do this to translate TARGET_PRODUCT into its
# underlying TARGET_DEVICE before we start defining any rules.
#
include $(BUILD_SYSTEM)/node_fns.mk
include $(BUILD_SYSTEM)/product.mk
include $(BUILD_SYSTEM)/device.mk

ifneq ($(strip $(TARGET_BUILD_APPS)).)# An unbundled app build needs only the core product makefiles.
all_product_configs := $(call get-product-makefiles,\
    $(SRC_TARGET_DIR)/product/AndroidProducts.mk)
else
# Read in all of the product definitions specified by the AndroidProducts.mk
# files in the tree.
This will search for all androidProducts.mk in the device directory and then read the PRODUCT_MAKEFILES variable in those files to get the path to the device Makefile.
All obtained device Makefile paths are stored in the all_product_configs variable.
all_product_configs := $(get-all-product-makefiles)
endif

all_named_products :=

# Find the product config makefile for the current product.
# all_product_configs consists items like:
# <product_name>:<path_to_the_product_makefile>
# or just <path_to_the_product_makefile> in case the product name is the
# same as the base filename of the product config makefile.
## [current_product_makefile is the name of the device Makefile for the configuration file selected by the user]
## the following list of foreach functions is text processing, changing the path to be relative to the source code root directory.
current_product_makefile :=
all_product_makefiles :=
$(foreach f, $(all_product_configs), \ $(eval _cpm_words := $(subst :,$(space).$(f))) \$(eval _cpm_word1 := $(word 1,$(_cpm_words))) \$(eval _cpm_word2 := $(word 2,$(_cpm_words))) \$(if $(_cpm_word2), \ $(eval all_product_makefiles += $(_cpm_word2))\
        $(eval all_named_products += $(_cpm_word1))\
        $(if $(filter $(TARGET_PRODUCT).$(_cpm_word1)), \$(eval current_product_makefile += $(_cpm_word2)), \)$(eval all_product_makefiles += $(f))\
        $(eval all_named_products += $(basename $(notdir $(f)))),$(if $(filter $(TARGET_PRODUCT), $(basename $(notdir $(f)))), \$(eval current_product_makefile += $(f)),)))
_cpm_words :=
_cpm_word1 :=
_cpm_word2 :=
## after the above processing, the value of current_product_makefile becomes the filename of the device Makefile, such as omni_berkeley.mk.
## this variable is null if not available.
current_product_makefile := $(strip $(current_product_makefile))
all_product_makefiles := $(strip $(all_product_makefiles))

load_all_product_makefiles :=
ifneq (,$(filter product-graph, $(MAKECMDGOALS)))
ifeq ($(ANDROID_PRODUCT_GRAPH),--all)
load_all_product_makefiles := true
endif
endif
ifneq (,$(filter dump-products,$(MAKECMDGOALS)))
ifeq ($(ANDROID_DUMP_PRODUCTS),all)
load_all_product_makefiles := true
endif
endif

## a device can have more than one device Makefile, but in most cases only one device Makefile will exist.
ifeq ($(load_all_product_makefiles),true)
# Import all product makefiles.
$(call import-products, $(all_product_makefiles))
else
# Import just the current product.
If you can't find the device Makefile, you can exit with an error.
ifndef current_product_makefile
$(error Can not locate config makefile for product "$(TARGET_PRODUCT)")
endif
ifneq (1,$(words $(current_product_makefile)))
$(error Product "$(TARGET_PRODUCT)" ambiguous: matches $(current_product_makefile))
endif
$(call import-products, $(current_product_makefile))
endif  # Import all or just the current product makefile
Copy the code
Total call relation

Based on the above analysis, we can easily conclude the following call relationship:

  1. build/make/core/product_config.mkRead the device parameter file directorydevice/Under all theAndroidProducts.mkTo get a list of device Makefiles.
  2. product_config.mkSearch the list for the device Makefile (for example, Huawei Honor 10 View) of the user specified device.omni_berkeley.mk).
  3. If it can be found, the device information is read from the device Makefile and the compilation environment is configured. Otherwise, an error is reported and exit.

Step 6: Start compiling

Once the configuration file is modified, we can start compiling immediately.

In the Android source root directory, first initialize the compilation environment:

source build/envsetup.sh
Copy the code

Minimal Manifest = Minimal Manifest = Minimal Manifest = Minimal Manifest = Minimal Manifest = Minimal Manifest = Minimal Manifest

export ALLOW_MISSING_DEPENDENCIES=true
Copy the code

Then, run the Lunch command and select the build target. You can also run lunch directly < one of the compilation targets in the menu below >.

$ lunch

You're building on Linux Lunch menu... pick a combo: 1. aosp_arm-eng 2. aosp_arm64-eng 3. aosp_mips-eng 4. aosp_mips64-eng 5. aosp_x86-eng 6. aosp_x86_64-eng 7. omni_berkeley-user 8. omni_berkeley-userdebug 9. omni_berkeley-eng 10. omni_hwp6_u06-userdebug 11. omni_hwp6_u06-eng 12.  omni_kenzo-userdebug 13. omni_emulator-userdebug Which would you like? [aosp_arm-eng] 10Copy the code

Finally, start compiling TWRP:

make recoveryimage
Copy the code

Out /target/product/< device name >/recovery.img

Step 7: Debug and fix the code

Adapting to TWRP is never going to be an overnight success, which means you won’t get it right the first time. Potential errors lurk in every corner of the compilation process, the running process, and even after the successful startup. What you need to do is always check for errors.

(a) compilation error

Errors during compilation are the easiest to troubleshoot. In short, “find a mistake, fix a mistake”. All errors will show up in the terminal output. You just need to observe the error output and follow its instructions. The Ninja builder, introduced in Android 7.0, will print an error command with the prefix “FAILED:” to indicate the error. Simply search for “FAILED:” to quickly locate the error.

(2) Errors before operation

After successful compilation, Recovery may not start normally, such as automatic restart and black screen. At this point, the most direct way to check the error is to get the kernel log.

1. Method of obtaining kernel logs

Generally speaking, whenever a kernel panic occurs, it will “try to” log the kernel at the time of the crash. Different platforms and kernels have different methods for obtaining kernel logs. The general combing is as follows.

  • Kernel logs are stored in/proc/last_kmsgIn the.
  • Swick (e.g. RK3188) : Same as Qualcomm.
  • Hays early chips (such as K3V2) : stored parameters in the kernelCONFIG_APANIC_PLABELIn the established zoning, it is generallysplash.

Simply read them with cat on a properly booted system (or by brushing another properly booted old Recovery into the boot partition).

2. initBad design that hinders kernel logging

Some of the startup failures that cause Panic occur during the running of the Android initializer init. However, init has the unfortunate design of restarting the Bootloader if panic is encountered in a ROM built using debug mode. The official word is “debug friendly,” but such a reboot would cause the kernel to fail to dump logs. Therefore, it is necessary to get rid of this function.

Go to system/core/init and apply the following git diff patch.

diff --git a/init/Android.bp b/init/Android.bp
index 45cf327f8.. 8a16fb2d2 100644
--- a/init/Android.bp
+++ b/init/Android.bp
@ @ - 14, 6 + 14, 9 @ @
 // limitations under the License.
 //
 
+// AnClark modify: I want to read logs. If handles panic as rebooting into bootloader, I won't get any logs!
+// Force setting DREBOOT_BOOTLOADER_ON_PANIC=0 on product_variables. 
+
 cc_defaults {
     name: "init_defaults",
     cpp_std: "experimental",
@ @ - 41, 7 + 44, 7 @ @ cc_defaults {
                 "-UALLOW_PERMISSIVE_SELINUX",
                 "-DALLOW_PERMISSIVE_SELINUX=1",
                 "-UREBOOT_BOOTLOADER_ON_PANIC",
- "-DREBOOT_BOOTLOADER_ON_PANIC=1",
+ "-DREBOOT_BOOTLOADER_ON_PANIC=0",
                 "-UWORLD_WRITABLE_KMSG",
                 "-DWORLD_WRITABLE_KMSG=1",
                 "-UDUMP_ON_UMOUNT_FAILURE",
diff --git a/init/Android.mk b/init/Android.mk
index f1fe5168b.. d28b4e489 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@ @ - 5, 10 + 5, 12 @ @ LOCAL_PATH:= $(call my-dir)
 # --
 
 ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT)))
+# AnClark modify: I want to read logs. If handles panic as rebooting into bootloader, I won't get any logs!
+# Force setting DREBOOT_BOOTLOADER_ON_PANIC=0 on product_variables. 
 init_options += \
     -DALLOW_LOCAL_PROP_OVERRIDE=1 \
     -DALLOW_PERMISSIVE_SELINUX=1 \
- -DREBOOT_BOOTLOADER_ON_PANIC=1 \
+ -DREBOOT_BOOTLOADER_ON_PANIC=0 \
     -DDUMP_ON_UMOUNT_FAILURE=1
 else
 init_options += \
diff --git a/init/util.cpp b/init/util.cpp
index fdcb22d1c.. a468082af 100644
--- a/init/util.cpp
+++ b/init/util.cpp
@ @ - 370, + 370 @ @ bool expand_props(const std::string& src, std::string* dst) {
     return true;
 }
 
+// AnClark MODIFY: Use abort() instead of rebooting into BL to trigger panic.
+ / * *
 void panic() {
     LOG(ERROR) << "panic: rebooting to bootloader";
     // Do not queue "shutdown" trigger since we want to shutdown immediately
     DoReboot(ANDROID_RB_RESTART2, "reboot", "bootloader", false);
 }
+ * * /
+
+void panic() {
+ LOG(ERROR) << "android::init::panic() invoked. Abort init to trigger kernel panic!" ;
+ abort();
+}
 
 static std::string init_android_dt_dir() {
     // Use the standard procfs-based path by default
Copy the code

** To apply the patch: ** Save the above code as system/core/init/no_reboot_into_bootloader.diff and then run the following command in the system/core/init directory:

patch -p2 < no_reboot_into_bootloader.diff
Copy the code

(iii) Functional testing and Bug repair

If you successfully pass the five passes, the long-lost TWRP startup screen appears on your device screen, then heartfelt congratulations to you! The next thing you need to do is go one step further and check the features of TWRP to catch bugs that might affect your use.

In general, in TWRP, you can do the following unit tests:

  • Check whether the mount is normal

    Go to “Mount” on the main menu and click on the options for each partition to check whether it can be mounted properly.

  • Whether decryption is normal

    For high-pass devices, the most direct way to see if decryption is working is to see if there is a hint of decryption failed in the log and if the Data partition in the Mount menu cannot be mounted.

  • Whether you can connect to ADB

    Connect the computer, run ADB Devices to check whether the device is in the Recovery state, and run ADB shell to check whether the terminal on the device can enter and have Root permission (prompt is “#”).

  • Whether MTP can be connected

    Connect the computer and check to see if an MTP device appears in the “This Computer” (Windows) or file manager sidebar (Ubuntu). If no, click Enable MTP (MTP) in Mount.

  • Whether OTG is supported

    OTG support is available on most major models starting in 2014. You can plug in an OTG data cable and run the LsusB in the TWRP terminal to see if a USB device is detected. Insert a new device and see if there is another device in the output of the LsusB. If the usb flash drive is inserted, you can also check whether the block device SDX (x is any lowercase letter) is added to /dev/block/.

  • Whether the system can be backed up/restored

    Test whether the system can back up and recover normally, and check whether the optional backup partition contains necessary partitions (system, data, Boot, and Recovery).

Matters needing attention

Build system support for shells

In principle, the Shell for the operation can only be Bash. If you use a different Shell, you will have some unexpected bugs when running commands — for example, in the Lunch menu, the Shell will select device 3 instead of device 1. The compilation system warns against using a Shell other than Bash during source build/envsetup.sh.

However, since Android 9.0, compilation systems have been able to support third-party shells other than Bash, such as Zsh. So if your Shell is Zsh (especially oh-my-zsh), feel free to use it.

Develop reading

  • TWRP Developers – XDA Developers

  1. Actually Mac OS X can do that too. ↩