Making an Android device boot to Qt

Android Injection

Qt Enterprise Embedded provides pre-built system images for a range of popular devices, like the Nexus 7 tablets and the BeagleBone Black. With these, you can make your device "boot to Qt" and be up and running with embedded development literally within minutes. But what if you want to try a device that is not among these reference devices of Qt Enterprise Embedded? Until recently, as an evaluator, you were basically out of luck. And even with an Enterprise license, you would have to rebuild the image from scratch for your device, a process that can take some time. Now, with the recent update of Qt Enterprise Embedded, there is another option available. If your device runs a recent version of Android, it is now possible to install the Boot to Qt stack directly into the existing Android system image; in effect taking it over. We call this method Android injection. In this blog post we will show how this process works in practice. We will use a device called the ODROID-U3 as our example.

odroid-box

The Injection Steps

The installation process consists of the following:

  1. Unpacking the Boot to Qt system and data archives into the /system and /data folders of the Android system
  2. Creating a device configuration file, appcontroller.conf
  3. Changing the Android boot script (init.rc) to make the device boot to Qt instead. We provide a script to perform the necessary changes.

As you can see, this is not very complicated. However, it cannot easily be automated, since  every device has different ways of packing the file systems and boot files. So a little manual effort is required.

The ODROID-U3 Device

This device is created by Hardkernel and has a quad-core Cortex-A9 processor, Mali-400 graphics processor and HDMI display output, and Android builds are available. For the injection process, any Android 4.2 or 4.4 image should do. For this blog post, I downloaded the Android 4.4 SD card image from here, and installed is as explained here. After booting twice, the device runs Android fine:

odroid-android

1. Unpacking the Boot to Qt system and data archives

The bulk of the Boot to Qt injection stack comes in the form of two tarballs, intended to be unpacked into Androids /system and /data folders respectively. On most Android distributions, those folders have separate partitions on the storage device. We need to determine which partitions that is. One way is to log in to the device and study the /fstab file, which will show where the partitions will be mounted. Like this:

~/odroid$ adb shell cat /fstab.odroidu.sdboot
# Android fstab file.
#
# The filesystem that contains the filesystem checker binary (typically /system) cannot
# specify MF_CHECK, and must come before any filesystems that do specify MF_CHECK

/dev/block/mmcblk0p2 /system ext4 rw wait /dev/block/mmcblk0p3 /data ext4 noatime,nosuid,nodev,nomblk_io_submit,noauto_da_alloc,errors=panic wait /dev/block/mmcblk0p4 /cache ext4 noatime,nosuid,nodev,nomblk_io_submit wait /devices/platform/s3c-sdhci.2/mmc_host/mmc0 auto auto defaults voldmanaged=sdcard0:1,noemulatedsd /devices/platform/dw_mmc/mmc_host/mmc0 auto auto defaults voldmanaged=sdcard1:auto /devices/platform/s5p-ehci auto auto defaults voldmanaged=usbdisk:auto

As we see, in this case /system and /data are on partitions 2 and 3 respectively. After powering down the device, and plugging the SD card into the host PC where the Qt Enterprise Embedded SDK is installed, we are ready to do the unpacking. Here, the SD card appears as /dev/sdb, and the SDK is installed in ~/QtEE31:

~/odroid$ mkdir p2
~/odroid$ sudo mount /dev/sdb2 p2
~/odroid$ sudo tar x -C p2 -f ~/QtEE31/Boot2Qt-3.x/generic-4.4-eAndroid/images/system.tar.xz
~/odroid$ mkdir p3
~/odroid$ sudo mount /dev/sdb3 p3
~/odroid$ sudo tar x -C p3 -f ~/QtEE31/Boot2Qt-3.x/generic-4.4-eAndroid/images/data.tar.xz

# Checking that things look good so far:

~/odroid$ ls -l p2/bin/qtlauncher -rwxr-xr-x 1 root root 173420 Jul 1 21:41 p2/bin/qtlauncher ~/odroid$ ls -ld p3/user/qt drwxr-xr-x 21 root root 4096 Jul 1 21:41 p3/user/qt/

2. Creating a device configuration file

The Boot to Qt stack needs a few environment variables and other device-specific settings. These are stored in plaintext format in the file /system/bin/appcontroller.conf. (Granted, that is not the most natural place for a settings file, but for now, that is where it is). One can see examples for different reference devices in the directories in Boot2Qt-3.x/generic-4.2-eAndroid/images. For the ODROID-U3, we store the following in p2/bin/appcontroller.conf:

#env=QT_QPA_EVDEV_TOUCHSCREEN_PARAMETERS=/dev/input/event0
env=QT_QPA_EGLFS_NO_SURFACEFLINGER=0
env=QT_LOGGING_TO_CONSOLE=1
env=QML2_IMPORT_PATH=/data/user/qt/qmlplugins
env=QT_IM_MODULE=qtvirtualkeyboard
base=android
platform=odroidu

Since we do not have a touch screen connected, the line setting the touch screen device has been commented out.

3. Changing the Android boot script

This step can sometimes be a little tricky. The boot script (init.rc) is always in Android's root file system. But many Android distributions package the kernel and the root file system into a special binary boot image format, and place that in a separate partition. That partition is then not mountable and modifiable like a normal file system. Instead, special scripts must be used to unpack it and repack it after modification. One can easily search up information about the process on the net.

In other cases, the boot script is available as a plain file. That is the case for our sample device, we find the ODROID's init.rc
file in the root directory of partition 2. The modification process itself is made very simple by a script provided in the Qt Enterprise Embedded SDK:

~/odroid$ sudo cp p2/init.rc p2/init.rc.orig
~/odroid$ sudo sed -f ~/QtEE31/Boot2Qt-3.x/generic-4.4-eAndroid/images/generic/modify_init_rc.sed -i p2/init.rc

# Checking that the modification succeeded:

~/odroid$ tail -1 p2/init.rc start boot2qt

Ready to rock!

All that remains is to unmount the SD card:

~/odroid$ sudo umount p2
~/odroid$ sudo umount p3

Now, with trembling fingers take the SD card with your brand new Boot to Qt image and plug it into the device. Then apply the power supply and wait for the screen of success:

odroid-b2qt
(If your device should not start up like this, try to look for error messages in the output from adb logcat and adb shell appcontroller qtlauncher.)

At this point, it is easy to set up your linux host and Qt Creator for one-click deployment of your apps to your device. Just follow the simple instructions for "Setting up USB Access" and "Configuring a Device Kit in Qt Creator" in one of the Android device preparation pages. Then, you are all set to start Building and Running Embedded Applications!


Blog Topics:

Comments