{{{#!html

    1. Android Updates and Recovery
      1. Android Recovery
      2. Creating an OTA image
      3. Customizing OTA
        1. Android releasetools.py
        2. Custom Recovery UI
      4. Applying an OTA
        1. Getting out of Recovery mode
        2. OTA manager - FSLOta

Android Updates and Recovery

Android has a built-in recovery and update system comprising of the following:

In general, Android can boot into 'normal' mode, or 'recovery' mode. Normal mode is used to boot Android for normal usage. Recovery mode is used to boot Android into either an automated update mode, or a minimal menu driven UI for basic recovery commands.

An 'Over The Air' (OTA) update is commonly used to distribute updates and typically they are in the form of a zip file containing a system image and an update script. Once the OTA image is downloaded to the cache partition, the system is rebooted in recovery mode which automatically detects the zip, applies it, then reboots to standard mode.

The OTA updates have an embedded digital signature (verified by android.os.RecoverySystem.verifyPackage()).

Note that the Android recovery mechanism is not without its flaws:

The Gateworks Android BSP provides the following OS OTA support:

Android Recovery

The 'reboot to recovery' mode is a bit device-specific with regards to how the device is rebooted and how it determines if it should boot into recovery mode or normal mode (specifically, the communication between the OS and the bootloader). The policy used needs to be supported in both the kernel (or Android bionic libc) as well the bootloader (or bootscript). Freescale's Android BSP uses a register in the IMX6 SoC which retains its value on a chip-level reset and checks for this in their bootloader. For the Gateworks Ventana Android BSP we changed this to use an EEPROM register in the GSC so that a full board power-cycle can still detect if the board needs to boot to recovery. Technically the bootloader could use the same mechanisms that the OS and recovery application use but that typically puts too many requirements on the capaiblities of the bootloader.

Android recovery is similar to the BOOT image in that it has a kernel, device-tree blobs, and ramdisk with Android init (using init.recovery.*.rc) and an fstab (recovery_fstab). Recovery mode boots data from a separate 'recovery' partition instead of the typical 'boot' partition.

The recovery filesystem is built in $(OUTDIR)/recovery/root which is built into a ramdisk ($(OUTDIR)/ramdisk-recovery.img) and wrapped with a U-Boot header ($(OUTDIR)/uramdisk-recovery.img). In addition, an 'Android image' is built in $(OUTDIR)/recovery.img however we don't use Android images for Ventana because they do not allow for multiple kernel device-tree's.

The Android project that builds the recovery 'application', which typically consists of a simple menu-driven interface and 'edify' script processor is in the bootable/recovery directory.

The RecoverySystem class provides the functionality of kicking off a recovery. The job of obtaining a file is outside of the scope of the Android Open Source project (AOSP), however Freescale has a simple app that can be used or modified to your needs. The RecoverySystem class will erase the log file (/cache/recovery/log), and write to the command file. For example when installPackage(Context context, File packageFile) is called, a command of '--update_package=<filename>' will be stored in /cache/recovery/command then perform a reboot via PowerManager?.reboot().

Creating an OTA image

The Android build system make dist target will create OTA images. These images will be in the form of .zip files in the $(PRODUCT_OUT) dir and are also copied to the $(DIST_DIR) directory which can be specified in the env (make dist DIST_DIR=dist_output). OTA package names will be names by the target device (ie ventana) and the BUILD_ID (from device/gateworks/ventana/build_id.mk)

The 'make dist' target will first create a 'target_files' .zip archive in the DIST_DIR directory (<target-device>-target_files-<BUILD_ID>.zip) which contains all files needed for a complete Android install (all partitions: system, boot, and recovery). You will want to keep this file for any releases you push as it may be useful later to create very small 'incremental' OTA releases from. The make dist target creates the following archives in DIR_DIR:

The ota_from_target_files tool uses this archive to create either 'full' or 'incremental' OTA update packages. The resulting OTA package is named <target-device>-ota-<BUILD_ID>.zip and will be in the PRODUCT_OUT directory (out/target/product/ventana/) as well as the DIST_DIR (which defaults to out/dist).

The OTA images are signed with a key defined by PRODUCT_DEFAULT_DEV_CERTIFICATE (which defaults to device/fsl/common/security/testkey). You can read more about Freescale's 'test key' from device/fsl/common/security/README. Once development is complete and you need to distribute a 'user' build OTA image, you need to generate a user image using your own 'private keys' as detailed in Signing builds for release. Note that the key used in OTA's must match the key used for the original system image.

An 'incremental' update contains a set of binary patches to be applied to the data already on the device which can result in considerably smaller update packages. These images can only be installed on a device that has a build where you still have the 'target_files' .zip archive to reference. If you have a previous 'target_files' .zip archive. Gateworks does not currently support the creation and installation of incremental updates.

A 'two-step' OTA will update the recovery partition first, then update the system partition. This takes place over multiple boot cycles and is necessary when the recovery requires a kernel or tool update in order to perform its duty. By default the make dist target will create an single-step OTA that only updates the system partition. In order to create a 'two-step' you must run it manually and provide the --two-step argument.

There are additional options that can be passed to the ota_from_target_files tool:

References:

Customizing OTA

An OTA image can be customized in the following ways:

See https://source.android.com/devices/tech/ota/device_code.html for more details on customization of OTA's.

Android releasetools.py

During OTA creation a target can provide a python script that extends the OTA release in a couple of ways:

Typically a custom releasetools.py is used to do very target specific things such as:

If present, the following functions can be defined that will be called allowing you to provide simple 'additions' to the existing OTA script:

The Gateworks Android BSP uses this to extend the the AOSP releasetools to add updating of the bootloader and SPL.

Sometimes the releasetools.py extensions do not offer enough customization. Gateworks has modified the ota_from_target_files script for the following:

For an example see device/gateworks/common/releasetools.py

Custom Recovery UI

A customized version of the recovery user interface can be provided by setting TARGET_RECOVERY_UI_LIB. The default implementation is to use bootable/recovery/default_device.cpp

Applying an OTA

Once an OTA image has been created you can deploy it to your devices. The Life of an OTA update is well described in on the Android OTA Updates page.

Typically a custom Android application will poll an update server for OTA updates and when one is found will download its description and present the user with a dialog asking if they wish to download and install the update. Once the update is downloaded and verified the recovery process can begin. This is done by the application copying the file to the /cache/recovery directory, creating a /cache/recovery/command file with recovery commands, and rebooting the board into recovery mode.

The 'reboot to recovery' mode is a bit device-specific with regards to how the device is rebooted and how it determines if it should boot into recovery mode or normal mode. The policy used needs to be supported in both the kernel (or Android bionic libc) as well the bootloader (or bootscript). Freescale's Android BSP uses a register in the IMX6 SoC which retains its value on a chip-level reset and checks for this in their bootloader. For the Gateworks Ventana Android BSP we changed this to use an EEPROM register in the GSC so that a full board power-cycle can still detect if the board needs to boot to recovery.

You can test an OTA manually without the need for an OTA manager by copying the OTA to the cache partition, creating a command file, and rebooting to recovery mode. For example the following via a shell prompt:

busybox wget -P /cache http://server/ota.zip
echo "--update_package=/cache/recovery/ota.zip" > /cache/command
reboot recovery

Getting out of Recovery mode

If you are stuck continually booting into recovery mode you can clear the bootmode flag with the following command in the bootloader:

i2c dev 0 && i2c mw 51 80 0xff 1

OTA manager - FSLOta

There is no Android Open Source Project (AOSP) project that provides an OTA manager, but Freescale has a simple one called FSLOta that can be used, or used for reference: FSLOta source

Android has some built-in classes that aid in the recovery process: