Comprehensive Guide to Android OTA Updates on the iMX8MP Platform

OTA Description

OTA, short for Over-the-Air Technology, refers to the process in Android systems where mobile devices download and install updates directly via wireless networks (such as WiFi, 3G/4G/5G) from remote servers, without needing to connect to a computer, simplifying the upgrade process and enhancing user experience.

Advantages of OTA

The advantages of OTA (Over-the-Air) updates in the Android ecosystem are significant and well-appreciated. The primary reason for their popularity is the convenience and speed – users can upgrade their devices without connecting to a computer, simply by being on a network, which saves a considerable amount of time and effort. Simultaneously, OTA updates efficiently and automatically detect new versions and notify users, ensuring that their devices always operate on the latest, most secure system or applications. This not only simplifies the process of manually searching for and installing updates but also reduces the security risks associated with outdated versions. Consequently, OTA updates are vital for enhancing user experience, lowering operational costs, and ensuring the security of devices.

How to implement Android OTA upgrade in imx8mp platform?

Build the OTA upgrade package

1. Build the target file

Enter the related path:

forlinx@ubuntu:~$ cd imx8mp/OK8MP-android-source/
forlinx@ubuntu:~/imx8mp/OK8MP-android-source$

Configure the environment:

forlinx@ubuntu:~/imx8mp/OK8MP-android-source$ source env.sh
forlinx@ubuntu:~/imx8mp/OK8MP-android-source$ source build/envsetup.sh
forlinx@ubuntu:~/imx8mp/OK8MP-android-source$ lunch evk_8mp-userdebug
============================================
PLATFORM_VERSION_CODENAME=REL
PLATFORM_VERSION=11
TARGET_PRODUCT=evk_8mp
TARGET_BUILD_VARIANT=userdebug
TARGET_BUILD_TYPE=release
TARGET_ARCH=arm64
TARGET_ARCH_VARIANT=armv8-a
TARGET_CPU_VARIANT=cortex-a53
TARGET_2ND_ARCH=arm
TARGET_2ND_ARCH_VARIANT=armv7-a-neon
TARGET_2ND_CPU_VARIANT=cortex-a9
HOST_ARCH=x86_64
HOST_2ND_ARCH=x86
HOST_OS=linux
HOST_OS_EXTRA=Linux-5.4.0-150-generic-x86_64-Ubuntu-18.04.4-LTS
HOST_CROSS_OS=windows
HOST_CROSS_ARCH=x86
HOST_CROSS_2ND_ARCH=x86_64
HOST_BUILD_TYPE=release
BUILD_ID=RQ1A.201205.003
OUT_DIR=out
PRODUCT_SOONG_NAMESPACES=device/generic/goldfish device/generic/goldfish-opengl external/mesa3d vendor/nxp-opensource/imx/power hardware/google/pixel vendor/partner_gms hardware/google/camera vendor/nxp-opensource/imx/camera
============================================

Start compiling:

forlinx@ubuntu:~/imx8mp/OK8MP-android-source$ ./imx-make.sh bootloader kernel -j4
make: Entering directory '/home/forlinx/imx8mp/R3_6.28/OK8MP-android-source'
/home/forlinx/imx8mp/R3_6.28/OK8MP-android-source/device/nxp/common/build/uboot.mk:74: *** shell env AARCH64_GCC_CROSS_COMPILE is not set.  Stop.
make: Leaving directory '/home/forlinx/imx8mp/R3_6.28/OK8MP-android-source'
forlinx@ubuntu:~/imx8mp/OK8MP-android-source$ make target-files-package -j4
============================================
PLATFORM_VERSION_CODENAME=REL
PLATFORM_VERSION=11
TARGET_PRODUCT=evk_8mp
TARGET_BUILD_VARIANT=userdebug
TARGET_BUILD_TYPE=release
TARGET_ARCH=arm64
TARGET_ARCH_VARIANT=armv8-a
TARGET_CPU_VARIANT=cortex-a53
TARGET_2ND_ARCH=arm
TARGET_2ND_ARCH_VARIANT=armv7-a-neon
TARGET_2ND_CPU_VARIANT=cortex-a9
HOST_ARCH=x86_64
HOST_2ND_ARCH=x86
HOST_OS=linux
HOST_OS_EXTRA=Linux-5.4.0-150-generic-x86_64-Ubuntu-18.04.4-LTS
HOST_CROSS_OS=windows
HOST_CROSS_ARCH=x86
HOST_CROSS_2ND_ARCH=x86_64
HOST_BUILD_TYPE=release
BUILD_ID=RQ1A.201205.003
OUT_DIR=out
PRODUCT_SOONG_NAMESPACES=device/generic/goldfish device/generic/goldfish-opengl external/mesa3d vendor/nxp-opensource/imx/power hardware/google/pixel vendor/partner_gms hardware/google/camera vendor/nxp-opensource/imx/camera
============================================
[……]
#### build completed successfully (13:07 (mm:ss)) ####

After the compilation is completed, it will generate "evk_8mp-/target_files-eng.forlinx.zip" under the path

"out/target/product/evk_8mp/obj/PACKAGING/target_files_intermediates/".target_files-eng.forlinx.zip" in the path "evk_8mp-eng.forlinx.zip", this is the zip package we need for OTA upgrade.

forlinx@ubuntu:~/imx8mp/OK8MP-android-source$ cd out/target/product/evk_8mp/obj/PACKAGING/target_files_intermediates/
forlinx@ubuntu:~/imx8mp/OK8MP-android-source/out/target/product/evk_8mp/obj/PACKAGING/target_files_intermediates$ ls
evk_8mp-target_files-eng.forlinx    evk_8mp-target_files-eng.forlinx.zip  
evk_8mp-target_files-eng.forlinx.zip.list

Back up "evk_8mp-target_files-eng.forlinx.zip",rename to ''target_files_v1.0.zip'':

forlinx@ubuntu:~/imx8mp/OK8MP-android-source/out/target/product/evk_8mp/obj/PACKAGING/target_files_intermediates$ cp evk_8mp-target_files-eng.forlinx.zip target_files_v1.0.zip
forlinx@ubuntu:~/imx8mp/OK8MP-android-source/out/target/product/evk_8mp/obj/PACKAGING/target_files_intermediates$ ls
evk_8mp-target_files-eng.forlinx           evk_8mp-target_files-eng.forlinx.zip  
evk_8mp-target_files-eng.forlinx.zip.list     target_files_v1.0.zip

2. Build a complete update package

Configure the environment in the same way as in step 1.

Compile command:

forlinx@ubuntu:~/imx8mp/OK8MP-android-source$ make otapackage -j4
============================================
PLATFORM_VERSION_CODENAME=REL
PLATFORM_VERSION=11
TARGET_PRODUCT=evk_8mp
TARGET_BUILD_VARIANT=userdebug
TARGET_BUILD_TYPE=release
TARGET_ARCH=arm64
TARGET_ARCH_VARIANT=armv8-a
TARGET_CPU_VARIANT=cortex-a53
TARGET_2ND_ARCH=arm
TARGET_2ND_ARCH_VARIANT=armv7-a-neon
TARGET_2ND_CPU_VARIANT=cortex-a9
HOST_ARCH=x86_64
HOST_2ND_ARCH=x86
HOST_OS=linux
HOST_OS_EXTRA=Linux-5.4.0-150-generic-x86_64-Ubuntu-18.04.4-LTS
HOST_CROSS_OS=windows
HOST_CROSS_ARCH=x86
HOST_CROSS_2ND_ARCH=x86_64
HOST_BUILD_TYPE=release
BUILD_ID=RQ1A.201205.003
OUT_DIR=out
PRODUCT_SOONG_NAMESPACES=device/generic/goldfish device/generic/goldfish-opengl external/mesa3d vendor/nxp-opensource/imx/power hardware/google/pixel vendor/partner_gms hardware/google/camera vendor/nxp-opensource/imx/camera
============================================
[……]
#### build completed successfully (13:07 (mm:ss)) ####

After compilation, "evk_8mp-ota-eng.forlinx.zip" will be generated under "out/target/product/evk_8mp/", this is the zip file we need for the OTA upgrade. This is the zip file we need for the OTA upgrade.

forlinx@ubuntu:~/imx8mp/OK8MP-android-source$ cd out/target/product/evk_8mp/
forlinx@ubuntu:~/imx8mp/OK8MP-android-source/out/target/product/evk_8mp$ ls evk*
evk_8mp-ota-eng.forlinx.zip

Back up ''evk_8mp-ota-eng.forlinx.zip'',re name to ''full-ota_v1.0.zip'':

forlinx@ubuntu:~/imx8mp/OK8MP-android-source/out/target/product/evk_8mp$ cp evk_8mp-ota-eng.forlinx.zip full-ota_v1.0.zip
forlinx@ubuntu:~/imx8mp/OK8MP-android-source/out/target/product/evk_8mp$ ls full*
full-ota_v1.0.zip

After completing steps 1 and 2, you can modify the source code according to actual needs. After the modification is completed, follow steps 1 and 2 again, at this time the new "evk_8mp-target_files-eng.forlinx.zip" is renamed "target_files_v2.0.zip";

"evk_8mp-ota-eng.forlinx.zip" is renamed "full-ota_eng.forlinx"; "evk_8mp-ota-eng.forlinx.zip" is renamed "full-ota_eng.forlinx"."; "evk_8mp-target_files-eng.forlinx.zip", renamed to "full-target_v2.0.zip".

3. Compile incremental upgrade package

The incremental update package contains only the encoding of the differences between the two files. The incremental update package can only be installed on devices using the old or source version. Before building the incremental update package, two target files need to be built.

  • Old packages that have been applied on the device, such as the target _ files _ v1.0.zip saved earlier;
  • The latest package waiting for the application on the device, such as the target _ files _ v2.0.zip saved earlier.

In the Android environment, use the following command to generate the incremental upgrade package:

forlinx@ubuntu:~/imx8mp/R3_6.28/OK8MP-android-source$ cp out/target/product/evk_8mp/obj/PACKAGING/target_files_intermediates/target_files_v* ./
forlinx@ubuntu:~/imx8mp/OK8MP-android-source$ out/host/linux-x86/bin/ota_from_target_files -i target_files_v1.0.zip target_files_v2.0.zip incremental-ota.zip

Note: Copy target_files_v1.0.zip and target_files_v2.0.zip to the OK8MP-android-source directory first, otherwise the execution command will report an error.

4. Upgrade with full package (using update system from development board storage).

Copy the compiled "full-ota_v1.0.zip" to a USB flash drive and extract it to get payload.bin and payload_properties.txt.

Insert the USB drive into the development board. The path to the USB drive is a directory under /mnt/media_rw/ with a random name; use the actual name. In this case, it is: CA35-A916.

Copy payload.bin and payload_properties.txt to the /data/ota_package directory of the development board:

evk_8mp:/ $ su
evk_8mp:/ # cd /data/ota_package/
evk_8mp:/data/ota_package # cp /mnt/media_rw/CA35-A916/full-ota_v1.0/payload* ./
evk_8mp:/data/ota_package # ls
payload.bin  payload_properties.txt

View payload_properties.txt:

evk_8mp:/ # cat payload_properties.txt
FILE_HASH=isiQeegRKyOdi9/aazwQjrZWRAIbB1Nyj1WdZ22L3Pk=
FILE_SIZE=555766395
METADATA_HASH=p0+xQATUAG7dZg/kuPaQACDdClkEOZDHoOhxx0lBEuA=
METADATA_SIZE=56853

Note: The contents in different payload _ properties. txt are inconsistent, and the actual queried values are the main ones.

Enter the following command on the debug serial port to update:

evk_8mp:/ # update_engine_client --payload=file:///data/ota_package/payload.bin --up\
date -- headers="FILE_HASH=isiQeegRKyOdi9/aazwQjrZWRAIbB1Nyj1WdZ22L3Pk=
FILE_SIZE=555766395
METADATA_HASH=p0+xQATUAG7dZg/kuPaQACDdClkEOZDHoOhxx0lBEuA=
METADATA_SIZE=56853"

Description:

  • payload specifies the upgrade file,/data/ota _ package/payload. bin is the path to the file.
  • headers is the file information of the upgrade file, which is obtained from the payload _ properties. txt.

Note: When entering commands, ensure that values enclosed within double quotes, such as FILE_HASH, are entered on a new line. The system automatically executes the command that follows after recognizing the backtick. Also, make sure that you do not add any spaces after each value, as adding spaces may cause errors in parsing.

After the input is completed, the update _ engine _ client will be automatically upgraded in the background. You can use the following command to view the progress.

evk_8mp:/ # logcat -s update_engine 
[……]
08-08 16:38:33.926   569   569 I update_engine: [INFO:update_attempter_android.cc(535)] Update successfully applied, waiting to reboot.
[……]

The above message indicates that the upgrade is complete. Restart the development board to switch to the new system.

5. Upgrade with incremental packages

Note on incremental upgrades:

An incremental upgrade is an upgrade between two target files, replacing only the parts that differ between the two targets. The same code generates different target files each time. For example, if the current code commit is A, and you have used the ''target files'' command multiple times to generate A1, A2, and A3, then after modifying the code, the code becomes B, and using the ''target files'' command generates B1. If at this point the program on the board is identical to target files A1, then the incremental package generated with A1 and B1 can be successfully upgraded. However, the incremental packages generated with A2 and A3 and B1 cannot be successfully upgraded due to a hash value verification failure in the partition.

When creating and performing an upgrade using the incremental package method, upgrade failures often occur, primarily due to the reasons mentioned above. In order for the upgrade to be successful, it is necessary to ensure that the system's internal programs are identical to the old target files used to generate the upgrade package. Flashing the system is done via image writing, so the hash values of the various partitions will differ from those of the target file we generated.

Consequently, if an incremental upgrade is to be used, the initial upgrade must be performed with a full package, and the target file corresponding to this full package must be preserved as the foundation for the subsequent incremental upgrade. Subsequently, the target file from each upgrade must be retained as the basis for the next incremental upgrade. If the hash values within the system do not match those required by the incremental package, a full package upgrade is needed to establish the correct correspondence.

So, the incremental upgrade tests were all incremental upgrade tests after a full upgrade had been completed.

The incremental upgrade steps are the same as the full package upgrade, just follow step 4.