Skip to content

Android 15.0.0_2.0.0 Developer Guide

Introduction

This page explains how to build and deploy Android Android 15 on the DART-MX95.

This release is based on NXP's i.MX android-15.0.0_2.0.0 release.

For additional details about this release, refer to the Release Notes.

Overview

The objective of this document is to guide DART-MX95 Android developers to obtain Android Android 15 sources, setting up host environment, compilation, and deployment.

This document contains instructions for:

  • Hardware and software requirements.
  • Setup the hardware.
  • Setup the toolchain.
  • Download & build the sources.
  • Install the binaries on the DART-MX95 SOM.

Hardware Requirements

You will need the Variscite DART-MX95 based evaluation kit.

Host (PC) setup requirements

The host development environment for Android is based on Ubuntu, please install one of the following Ubuntu versions:

If you are running Linux in a virtual machine you need at least 16GB of RAM and 32 GB of swap. The build process requires ~250GB of free storage space. Before starting a build, make sure you have adequate free space available.

Note: Do not use other Ubuntu releases other than the ones recommended above. Variscite provides Docker containers that can be used for a development environment as an alternative to using a virtual machine or a dedicated computer.

To learn more, please see Variscite's Docker Build Environment guide.

Windows with WSL/WSL2 is not supported for Android BSP

Install required packages on host PC

 $ sudo apt-get update && sudo apt-get dist-upgrade

Then, install the following packages:

 $ sudo apt-get install python3 python3-pip python3-pexpect \
 python3-git python3-jinja2 python3-subunit python3-git liblz4-tool \
 python3-jinja2 python3-subunit curl zstd

For Ubuntu 20.04 and earlier, install python2:

sudo apt-get install python python-pysqlite2

Starting in Ubuntu 22.04, python2 is no longer available. Install the following to create a symbolic link from python to python3:

sudo apt-get install python-is-python3

Ubuntu 24.04 introduced additional unprivileged user namespace restrictions. They must be disabled to avoid permission errors during Yocto fetch tasks when using Variscite's docker container.

Disable this restriction on the entire system for one boot:

sudo add-apt-repository ppa:openjdk-r/ppa

Alternatively, disable this restriction using a persistent setting by adding a new file (/etc/sysctl.d/60-apparmor-namespace.conf) with the following contents:

echo 'kernel.apparmor_restrict_unprivileged_userns=0' | sudo tee /etc/sysctl.d/60-apparmor-namespace.conf
sudo sysctl -p /etc/sysctl.d/60-apparmor-namespace.conf

Install Docker:

sudo apt update && sudo apt install docker.io qemu-user-static

Give permissions to run Docker without sudo:

sudo usermod -aG docker ${USER}
# Logout and login again for the permissions to take effect.

Configure git user and email:

git config --global user.name "Your Name"
git config --global user.email "Your Email"

Obtain source code

Variscite's Linux kernel and U-Boot are available on GitHub. NXP's Android 15.0.0_2.0.0 BSP with required Android file system patches are accessible from Variscite’s FTP server:

Get NXP's Android Release Package

mkdir ~/var_imx-android-15.0.0_2.0.0
cd ~/var_imx-android-15.0.0_2.0.0
curl -o ~/Downloads/imx-android-15.0.0_2.0.0.tar.gz https://variscite-public.nyc3.cdn.digitaloceanspaces.com/Android/Android_iMX9_1500_200/imx-android-15.0.0_2.0.0.tar.gz
tar xvf ~/Downloads/imx-android-15.0.0_2.0.0.tar.gz

Sync Android Source

mkdir -p ~/bin
curl -o ~/bin/repo https://commondatastorage.googleapis.com/git-repo-downloads/repo
chmod a+x ~/bin/repo
export PATH=~/bin:$PATH
cd ~/var_imx-android-15.0.0_2.0.0
source imx-android-15.0.0_2.0.0/imx_android_setup.sh

Note: Wait for the script to finish running. It should create the following folders.

~/var_imx-android-15.0.0_2.0.0/android_build/device/variscite/
~/var_imx-android-15.0.0_2.0.0/android_build/vendor/variscite/kernel_imx and
~/var_imx-android-15.0.0_2.0.0/android_build/vendor/variscite/uboot-imx

Apply Variscite's i.MX platforms patches

cd ~/var_imx-android-15.0.0_2.0.0/android_build/device
variscite/scripts/install.sh

Build Android Images

Start a Ubuntu Docker container:

cd ~/var_imx-android-15.0.0_2.0.0/android_build/
./var-start-container.sh

Note: After Ubuntu Docker container is started you can see the shell prompt similar to: vari@20-04-b91923e0-android-15-0-0_2-0-0$

All references to commands without this prompt should be executed in a native terminal (outside Docker). If you need to run a command using 'sudo' inside the container, the default password is ubuntu.

From the working directory, set up the build environment:

source build/envsetup.sh

Select a target using the lunch command. For example:

lunch dart_mx95-var_stable-userdebug

or

lunch dart_mx95-var_stable-user

Build variants:

  • user - Production build with debugging disabled.
  • userdebug - Production-like build with debugging and developer tools enabled.
  • eng - Engineering build for development with full debugging and minimal performance and security optimizations.

Switching from eMMC build to SD card build and vice versa

Unlike previous Android BSPs, the boot media is autodetected at boot time.

Build Android

./imx-make.sh -j4 2>&1 | tee build1-1.log
Note: By default, the supported DRAM size is 8 GB. To change the supported DRAM size during compilation, set TARGET_DRAM_SIZE_GB to the DRAM size of your machine in ~/var_imx-android-15.0.0_2.0.0/android_build/device/variscite/imx9/dart_mx95/UbootKernelBoardConfig.mk or via command line, e.g.:
TARGET_DRAM_SIZE_GB=16 ./imx-make.sh -j4 2>&1 | tee build1-1.log

Images created by the Android build

The resulted images are located in out/target/product/dart_mx95.

Image
Description
spl-imx95-var-dart-dual.bin U-Boot SPL without Trusty OS for eMMC/SD card boot.
SOM agnostics.
bootloader-imx95-var-dart-dual.img An image containing U-Boot proper ATF, OEI and SM without Trusty OS for eMMC/SD card boot.
SOM agnostics.
boot.img Android kernel image file.
SOM agnostics.
vendor_boot.img A composite image, which includes vendor RAMDisk and boot parameters.
SOM agnostics.
init_boot.img A composite image, which includes init process.
SOM agnostics.
super.img Android super image file.
SOM agnostics.
dtbo-<name>.img Depends on configuration, see below
dtbo-imx95-var-dart-dt8mcustomboard.img Device tree blob for DART-MX95 V1.2 on DT8MCustomBoard 3.x
dtbo-imx95-var-dart-sonata.img Device tree blob for DART-MX95 V1.2 on Sonata-Board
vbmeta-<name>.img Depends on configuration, see below
vbmeta-imx95-var-dart-dt8mcustomboard.img Android Verify boot metadata image for dtbo-imx95-var-dart-dt8mcustomboard.img
vbmeta-imx95-var-dart-sonata.img Android Verify boot metadata image for dtbo-imx95-var-dart-sonata.img

Boot options

Boot options of the Android:

  1. from SD card
  2. from on-SOM eMMC

Note: Flashing Android images inside Docker containers is not supported. Use a native terminal (outside Docker) to flash the Android images to your target device.

Flash and boot Android from SD card

Create a bootable SD card

Partition and format SD card, and copy all images

cd ~/var_imx-android-15.0.0_2.0.0/android_build/
sudo ./var-mksdcard.sh -f <name> /dev/sdX;sync
  • Replace with the actual desired setup name according to the second table in the "Images created by the Android build" section.
  • Replace /dev/sdX with your actual device. You can identify it with dmesg command.

Boot From SD card

  • Power-off the board.
  • Insert the SD card into the SD card slot of the carrier board (DVK)
  • Make sure the Boot Mode is set to SD card
  • Power up the board - it will boot into Android from the SD card

Flash and boot Android from eMMC

Flashing Android from Linux shell (when the primary installation android)

An example of flashing eMMC, can be found here.

Follow the instructions from above link by completing the following steps:

  1. Preparing a bootable SD card;

  2. Flash the SOM's internal storage

Flashing Android with USB Fastboot

Install tools on host PC

sudo apt-get install android-tools-adb android-tools-fastboot

Unlock device for fastboot

To use fastboot, you should first follow these steps:

  • Settings => System => About Tablet => Build number
  • Keep tapping until you see the message "You are now a developer!"
  • Settings => System => Advanced => Developer options => OEM unlocking

Connect the target device to the host PC in fastboot mode:

  1. Connect the USB OTG cable from the OTG port of the target board to the USB HOST port of your computer.
  2. Power up the board and press any key to interrupt the boot sequence at the U-Boot command prompt.
  3. Type fastboot 0 in the U-Boot command line.

Alternatively, after step 1, run the "reboot bootloader" command on your device.

  • on host PC run:
sudo `which fastboot` oem unlock
  • Wait for the unlocking process to complete
  • Proceed with flashing as following
sudo `which fastboot` flash bootloader_a out/target/product/dart_mx95/bootloader-imx95-var-dart-dual.img
sudo `which fastboot` flash bootloader_b out/target/product/dart_mx95/bootloader-imx95-var-dart-dual.img
sudo `which fastboot` flash dtbo_a out/target/product/dart_mx95/dtbo-imx95-var-dart-dt8mcustomboard.img
sudo `which fastboot` flash dtbo_b out/target/product/dart_mx95/dtbo-imx95-var-dart-dt8mcustomboard.img
sudo `which fastboot` flash boot_a out/target/product/dart_mx95/boot.img
sudo `which fastboot` flash boot_b out/target/product/dart_mx95/boot.img
sudo `which fastboot` flash init_boot_a out/target/product/dart_mx95/init_boot.img
sudo `which fastboot` flash init_boot_b out/target/product/dart_mx95/init_boot.img
sudo `which fastboot` flash vendor_boot_a out/target/product/dart_mx95/vendor_boot.img
sudo `which fastboot` flash vendor_boot_b out/target/product/dart_mx95/vendor_boot.img
sudo `which fastboot` flash super out/target/product/dart_mx95/super.img
sudo `which fastboot` flash vbmeta_a out/target/product/dart_mx95/vbmeta-imx95-var-dart-dt8mcustomboard.img
sudo `which fastboot` flash vbmeta_b out/target/product/dart_mx95/vbmeta-imx95-var-dart-dt8mcustomboard.img
sudo `which fastboot` reboot

Replace with the actual desired setup name according to the table in the "Images created by the Android build" section.

Update Android firmware

Generate OTA packages

For generating "OTA" packages, use the following commands:

cd ~/var_imx-android-15.0.0_2.0.0/android_build
source build/envsetup.sh
lunch dart_mx95-var_stable-userdebug
./imx-make.sh bootloader kernel -j4
make otapackage -j4 2>&1
Note: Before creating the OTA package, make sure that BOARD_PREBUILT_DTBOIMAGE points to the dtbo image of your machine's configuration

Install OTA package to device

  • Extract payload.bin and payload_properties.txt from OTA zip file

  • Push payload.bin and care_map.pb files to a writable location on the device (typically /data/ota_package folder)

adb root
adb push payload.bin /data/ota_package
adb push care_map.pb /data/ota_package
  • Open payload_properties.txt on an editor to copy its content, let's suppose it looks like this :
 FILE_HASH=0fSBbXonyTjaAzMpwTBgM9AVtlBeyOigpCCgkoOfHKY=
 FILE_SIZE=379074366
 METADATA_HASH=Icrs3NqoglzyppyCZouWKbo5f08IPokhlUfHDmz77WQ/de8Dgp9zFXt8Fo+Hxccp465uTOvKNsteWU=
 METADATA_SIZE=46866
  • To test the update process, enter the following command in the board's debug console:
 su
 update_engine_client --payload=file:///data/ota_package/payload.bin --update --headers="FILE_HASH=0fSBbXonyTjaAzMpwTBgM9AVtlBeyOigpCCgkoOfHKY=
 FILE_SIZE=379074366
 METADATA_HASH=Icrs3NqoglzyppyCZouWKbo5f08IPokhlUfHDmz77WQ/de8Dgp9zFXt8Fo+Hxccp465uTOvKNsteWU=
 METADATA_SIZE=46866"

Make sure that the -- header equals to the exact content of payload_properties.txt without "space" or "return" character.

After running the command, nothing appears to happen on the device, but you can monitor the progress of the operation via logcat. Once the update is successful, you can reboot into the updated version.

Refer to Chapter 7 "Over-the-Air (OTA) Update" of the NXP "Android User Guide" for further details.

Manual operations

Build boot.img

When you perform changes to the kernel, you may build boot.img solely instead of building the whole Android.

cd ~/var_imx-android-15.0.0_2.0.0/android_build
source build/envsetup.sh
lunch dart_mx95-var_stable-userdebug
make bootimage

Flashing Using NXP MFGTools - UUU (Universal Update Utility)

To flash Android OS without using a recovery SD card, UUU (MFG Tools 3.0) can be used. Please refer to Flashing Android OS using UUU - USB Boot.

Building Android with Trusty support enabled

Follow the instructions from "Build Android Images" section

Note: To enable Trusty OS support, set PRODUCT_IMX_TRUSTY to true in ~/var_imx-android-15.0.0_2.0.0/android_build/device/variscite/imx9/dart_mx95/SharedBoardConfig.mk

The image names in "Images created by the Android build" section will differ only for the bootloader:

Image
Description
spl-imx95-var-dart-trusty-dual.bin U-Boot SPL with Trusty related configurations for eMMC boot
for Android build with Trusty OS support enabled
to burn only to eMMC
bootloader-imx95-var-dart-trusty-dual.img An image containing U-Boot proper, ATF, OEI, SM and Trusty OS for eMMC boot
for Android build with Trusty OS support enabled
to burn only to eMMC

Building Android with Cortex-M support enabled

Follow the instructions from "Build Android Images" section

Note: To enable Cortex-M7 support, set PRODUCT_IMX_RPMSG to true in ~/var_imx-android-15.0.0_2.0.0/android_build/device/variscite/imx9/dart_mx95/SharedBoardConfig.mk or via command line, e.g.:

PRODUCT_IMX_RPMSG=true ./imx-make.sh -j4 2>&1 | tee build1-1.log

The image names in "Images created by the Android build" section will differ for the bootloader, dtbo and vbmeta images:

Image
Description
spl-imx95-var-dart-rpmsg-dual.bin U-Boot SPL with Cortex-M7 support without Trusty OS for eMMC/SD card boot.
SOM agnostics.
bootloader-imx95-var-dart-rpmsg-dual.img An image containing U-Boot proper ATF, OEI and SM with Cortex-M7 support without Trusty OS for eMMC/SD card boot.
SOM agnostics.
dtbo-<name>.img Depends on configuration, see below
dtbo-imx95-var-dart-dt8mcustomboard-m7.img Device tree blob for DART-MX95 V1.2 with Cortex-M7 on DT8MCustomBoard 3.x
dtbo-imx95-var-dart-sonata-m7.img Device tree blob for DART-MX95 V1.2 with Cortex-M7 on Sonata-Board
vbmeta-<name>.img Depends on configuration, see below
vbmeta-imx95-var-dart-dt8mcustomboard.img Android Verify boot metadata image for dtbo-imx95-var-dart-dt8mcustomboard-m7.img
vbmeta-imx95-var-dart-sonata.img Android Verify boot metadata image for dtbo-imx95-var-dart-sonata-m7.img

Android comes with pre-compiled demo binaries for Cortex-M7:

cm_rpmsg_lite_pingpong_rtos_linux_remote_cm7.bin.debug - TCM - RPMSG Ping-Pong FreeRTOS RTOS API Demo
cm_rpmsg_lite_str_echo_rtos_remote_cm7.bin.debug - TCM - RPMSG String Echo FreeRTOS RTOS API Demo

To flash the Android images follow one of these methods:

For machine on Sonata-Board use command list file emmc_burn_android_imx95_var_dart_sonata_m7.lst, e.g.:

sudo ./uuu emmc_burn_android_imx95_var_dart_sonata_m7.lst
For machine on DT8MCustomBoard use command list file emmc_burn_android_imx95_var_dart_dt8mcustomboard_m7.lst, e.g.:

sudo ./uuu emmc_burn_android_imx95_var_dart_dt8mcustomboard_m7.lst
By default, 'RPMSG String Echo FreeRTOS RTOS API Demo' will be burned to the mcu_os partition.

Note: Use the appropriate bootloader, dtbo and vbmeta images from the table above. Run the following additional command to burn the demo image to the mcu_os partition, e.g.:

sudo `which fastboot` flash mcu_os cm_rpmsg_lite_pingpong_rtos_linux_remote_cm7.bin.debug

e.g. for DART-MX95 on Sonata-Board:

sudo ./var-mksdcard.sh -f imx95-var-dart-sonata-m7 /dev/sdX;sync
By default, 'RPMSG Ping-Pong FreeRTOS RTOS API Demo' will be burned to the mcu_os partition

To flash a different demo image to the mcu_os partition, refer to the "Flashing Android with USB Fastboot" section, e.g.:

sudo `which fastboot` flash mcu_os cm_hello_world_cm7.bin.debug

Running a CM7 demo from Android shell

Boot Android to the shell

Increase the kernel log level while debugging:

sysctl kernel.printk=7
Check the status of CM7, it should already be attached, started by U-Boot:

cat /sys/class/remoteproc/remoteproc0/state
If the state is 'attached' or 'running', stop the CM7:

echo stop > /sys/class/remoteproc/remoteproc0/state
Load new firmware (.elf file must already exist in /vendor/firmware directory), e.g. for PMSG Ping-Pong FreeRTOS RTOS API Demo:

echo cm_rpmsg_lite_pingpong_rtos_linux_remote_cm7.elf.debug > /sys/class/remoteproc/remoteproc0/firmware
as an alternative, for RPMSG String Echo FreeRTOS RTOS API Demo:

echo cm_rpmsg_lite_str_echo_rtos_remote_cm7.elf.debug > /sys/class/remoteproc/remoteproc0/firmware
Note: Cortex-M7 demo image runs from TCM

Change the state to running:

echo start > /sys/class/remoteproc/remoteproc0/state

Load demo kernel module

The choice of the RPMSG module to load depends on the previous step.

From device shell run:

su
cd /vendor
insmod imx_rpmsg_pingpong.ko
as an alternative:

su
cd /vendor
insmod imx_rpmsg_tty.ko

Running a demo from U-Boot

Note: The bootmcu command supports demos built to run only from TCM. The U-Boot environment integrates bootmcu into the boot command when Cortex-M7 support is enabled.

Once the boot process is complete, follow the steps described in "Load demo kernel module" section. The choice of the RPMSG module to load depends on the demo image written to the mcu_os partition.

Building Android with Context Hub Runtime Environment (CHRE)

Follow the instructions from "Build Android Images" section

Note: To enable CHRE support, set ENABLE_CONTEXTHUB to true via the command line. For example:

ENABLE_CONTEXTHUB=true ./imx-make.sh -j4 2>&1 | tee build1-1.log

The resulting Android build images will be identical to those generated when Cortex-M7 support is enabled.

Android comes with pre-compiled CHRE demo binary for Cortex-M7:

rpmsg_chre_rtos_cm7.bin - MCU CHRE Demo
This demo runs with the message_world NanoApp statically built into the MCU firmware and with the hello_world preloaded NanoApp, built as a separate binary.

To flash the Android images follow one of these methods:

For machine on Sonata-Board use command list file emmc_burn_android_imx95_var_dart_sonata_m7_chre.lst, e.g.:

sudo ./uuu emmc_burn_android_imx95_var_dart_sonata_m7_chre.lst
For machine on DT8MCustomBoard use command list file emmc_burn_android_imx95_var_dart_dt8mcustomboard_m7_chre.lst, e.g.:

sudo ./uuu emmc_burn_android_imx95_var_dart_dt8mcustomboard_m7_chre.lst
By default, 'MCU CHRE Demo' will be burned to the mcu_os partition.

Note: Use the appropriate bootloader, dtbo and vbmeta images from the table in "Building Android with Cortex-M support enabled".

Run the following additional command to burn the demo image to the mcu_os partition:

sudo `which fastboot` flash mcu_os rpmsg_chre_rtos_cm7.bin

Testing the CHRE Demo

Once booted into Android, test CHRE Demo via ChreDemo UI application.

Note: pre-compiled CHRE demo does not support dynamic NanoApp loading via UI 'LOADNANOAPP' button. To use this feature, the MCU CHRE Demo should be rebuilt with a dynamic NanoApp.

To check the current state of the ContextHub Service, run the dump command:

dumpsys contexthub

The Cortex-M7 debug console can be accessed via the header pins on the carrier board. Connect a USB-to-TTL serial converter to:

  • J12.11 - J12.13 - J12.15 (Rx-Tx-GND) on the DT8MCustomBoard

  • J6.11 - J6.13 - J6.15 (Rx-Tx-GND) on the Sonata-Board

For more detailed information, please see the documentation in the system/chre/doc/ directory within AOSP source tree and the NXP guide Running CHRE on i.MX 95