The latest version of the Android system provided by Digi enables you to update the firmware of the ConnectCore 8X device from the Android system itself. See Update Android with OTA packages to learn how to perform the firmware update through the Android settings. If you prefer, you can add the firmware update functionality to an Android application using the firmware update service provided by Digi.

With the Firmware update API you can perform a firmware update of the system from an Android application, install new applications and wipe the user and data partitions. In the Digi APIx javadoc documentation you can find a complete list of the available methods in this API.

Unless noted, all Firmware update API methods require the com.digi.android.permission.FIRMWARE_UPDATE permission.

If your application does not have the com.digi.android.permission.FIRMWARE_UPDATE permission it will not have access to any Firmware update service feature.

First of all, a new FirmwareUpdateManager object must be instantiated by passing the Android Application Context.

Instantiating the FirmwareUpdateManager
import android.app.Activity;
import android.os.Bundle;

import com.digi.android.firmwareupdate.FirmwareUpdateManager;

public class FirmwareUpdateSampleActivity extends Activity {

    FirmwareUpdateManager firmwareUpdateManager;

    [...]

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Instantiate the FirmwareUpdateManager manager object.
        firmwareUpdateManager = new FirmwareUpdateManager(this);

        [...]
    }

    [...]
}

Install an application

One of the features provided by the Firmware update service is to install an Android application. Use the installApplication(String, boolean) method of the FirmwareUpdateManager with the full path of the APK to install. This method also offers the possibility of rebooting the module after the application installation.

Method Description

installApplication(String, boolean)

Installs the application represented by the given APK full path

The installApplication(String, boolean) method may fail for the following reasons:

  • The provided application path is null throwing a NullPointerException.

  • There is an error installing the application throwing an IOException.

Installing an application
import com.digi.android.firmwareupdate.FirmwareUpdateManager;

[...]

FirmwareUpdateManager firmwareUpdateManager = [...];

[...]

// Install the application located at '/storage/emulated/0/Download/MyApplication.apk'.
// Do not restart the device after application installation.
firmwareUpdateManager.installApplication("/storage/emulated/0/Download/MyApplication.apk", false);
This method will not ask for permission to install the application, as the installation process is performed by the Android Firmware update service.

Install an update package

The main purpose of this Firmware update service is to install an update package to update the Android system.

A firmware update process follows these steps when it is triggered:

  1. Check update package location. Firmware update is always performed from the cache partition of the device. If the update package is not located there, it is copied.

  2. Verification of update package. If verification is enabled, the cryptographic signature of the package is verified against the provided certificates.

  3. Update process.

  1. Device reboots into recovery mode. The kernel in the recovery partition is booted instead of the kernel in the boot partition.

  2. Recovery binary is started by init. It finds command-line arguments in /cache/recovery/command that point it to the update package.

  3. Data is pulled from the package and used to update the boot, vendor, and system partitions. One of the new files on the system partition contains the contents of the new recovery partition.

  4. Device reboots normally.

  5. The newly updated boot partition is loaded, and it mounts and starts the newly updated system partition.

  6. As part of normal startup, the system checks the contents of the recovery partition against the desired contents (previously stored as a file in /system). They are different, so the recovery partition is reprogrammed with the desired contents. On subsequent boots, the recovery partition already contains the new contents, so no reprogram is necessary.

  7. The system update is complete. The update logs can be found in /cache/recovery/last_log.#.

To generate an update package for your device, follow the steps in Create a signed OTA package.

To update your Android system using an update package, use the installUpdatePackage(String, listener, boolean, String) method with the following parameters:

  • updatePackagePath: Full path of the update package to install.

  • listener: An object implementing the IFirmwareUpdateListener interface to receive firmware update progress information, cannot be null. See Listen for firmware update events for more information.

  • verify: Boolean parameter indicating if the update package signature must be verified.

    Package signature is verified using the given certificates zip file in deviceCertsZipFile parameter. If this parameter is not provided, the default system certificates file is used.
  • deviceCertsZipFile: Full path to the zip file of certificates whose public keys will be accepted. Verification succeeds if the package is signed by the private key corresponding to any public key in this file. May be null to use the system default file, /system/etc/security/otacerts.zip. This parameter only applies if verify is true.

Method Description

installUpdatePackage(String, listener, boolean, String)

Installs the given update package

This installUpdatePackage(String, listener, boolean, String) may fail if the provided update package path or listener are null throwing a NullPointerException.

Installing an update package
import com.digi.android.firmwareupdate.FirmwareUpdateManager;

[...]

FirmwareUpdateManager firmwareUpdateManager = [...];
MyFirmwareUpdateListener myFirmwareUpdateListener = [...];

[...]

// Install the '/storage/emulated/0/Download/ota_update_package.zip' update package.
// Listen to firmware events and do not verify the package.
firmwareUpdateManager.installUpdatePackage("/storage/emulated/0/Download/ota_update_package.zip", myFirmwareUpdateListener, false, null);
The module is restarted during the firmware update process. You can get events produced during the process with the IFirmwareUpdateListener provided in the method.

Listen for firmware update events

The firmware update process generates some events that can be get and processed in your application. To make your application aware of these events, create your own Firmware update listener by implementing the IFirmwareUpdateListener interface.

Firmware update listener
import com.digi.android.firmwareupdate.IFirmwareUpdateListener;

class MyFirmwareUpdateListener implements IFirmwareUpdateListener {
    @Override
    void updatePackageCopyStarted() {
    }

    @Override
    void updatePackageCopyFinished() {
    }

    @Override
    void verifyStarted() {
    }

    @Override
    void verifyProgress(int progress) {
    }

    @Override
    void verifyFinished() {
    }

    @Override
    void updateStarted() {
    }

    @verride
    void onError(String error) {
    }
}

The IFirmwareUpdateListener interface defines the following methods to handle the events generated during a firmware update process:

Method Description

updatePackageCopyStarted()

Notifies that the update package copy operation started

updatePackageCopyFinished()

Notifies that the update package copy operation finished

verifyStarted()

Notifies that the update package verification started

verifyProgress(int)

Notifies about the update package verification progress and provides the progress percentage

verifyFinished()

Notifies that the update package verification finished

updateStarted()

Notifies that the update process started and the device is about to reboot

onError(String)

Notifies any firmware update error and provides the error message

Depending on the parameters provided in the installUpdatePackage method and the location of the update package, some events are not generated:

  1. Check update package location.

    • If the package is not in the cache partition, copy it to the cache partition.

      1. updatePackageCopyStarted() notification is fired when the copy process starts.

      2. updatePackageCopyFinished() notification is fired when the copy process ends.

    • If the package is in the cache partition, copy notifications are not fired.

  2. Verification of update package.

    • If verify parameter is set to true in the installUpdatePackage(String, listener, boolean, String), verify the update package signature.

      1. verifyStarted() notification is fired when the verification stars.

      2. verifyProgress(int) notifies about the verification progress.

      3. verifyFinished() notification is fired when the verification ends.

    • If verify parameter is set to false in the installUpdatePackage(String, listener, boolean, String), verification notifications are not fired.

  3. Update the system.

    • updateStarted() notification is fired when the update process starts.

onError(String) notification is fired if any error occurs at any stage of the firmware update process.

This listener is a mandatory parameter of the installUpdatePackage(String, listener, boolean, String) method. See Install an update package for more information.

Wipe partitions

The latest feature you can find inside the Firmware update service is functionality to wipe some of the Android system partitions. These are the data and cache partitions, where you have full access and can read and write files. Use any of the following methods to start a wipe process:

Method Description

wipeCache()

Wipes the cache (/cache) partition

wipeCache(String)

Wipes the cache (/cache) partition providing a 'reason' message

wipeUserData()

Wipes the user data (/data) and cache (/cache) partitions

wipeUserData(String)

Wipes the user data (/data) and cache (/cache) partitions providing a 'reason' message

wipeUserData(String, boolean)

Wipes the user data (/data) and cache (/cache) partitions providing a 'reason' message. It also allows for a shutdown instead of reset

These methods may fail if there is any error preparing for the wipe process throwing an IOException.

Wiping cache partition
import com.digi.android.firmwareupdate.FirmwareUpdateManager;

[...]

FirmwareUpdateManager firmwareUpdateManager = [...];

[...]

// Wipe the cache partition and provide a reason message.
firmwareUpdateManager.wipeCache("I'm sorry for your cache");
Wiping cache and data partitions
import com.digi.android.firmwareupdate.FirmwareUpdateManager;

[...]

FirmwareUpdateManager firmwareUpdateManager = [...];

[...]

// Wipe the user data and cache partitions and provide a reason message.
firmwareUpdateManager.wipeData("I'm extremely sorry for your data and cache");

The device is restarted in order to perform the wipe operation. The wipeUserData(String, boolean) method shutdowns the device, instead of rebooting it, if the shutdown parameter is true.