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. The firmware update process requires two files:

  • An OTA package that contains the update files. To generate this package, follow the steps in Create a signed OTA package.

  • A JSON configuration file that describes the OTA package contents and the update process. To generate the configuration file, follow the steps described in JSON OTA configuration file.

Once you have both files, you can configure your application to trigger a firmware update using the firmware update service.

Before applying the update, Digi recommends you subscribe to the firmware update service to receive event and progress notifications for the firmware update operation. See Listen for firmware update events for more information.

To trigger the firmware update, use the applyUpdate(String) method with the following parameters:

  • otaJSONString: JSON configuration string describing the OTA update package (the contents of the JSON file).

Method Description

applyUpdate(String)

Applies the update package described in the given JSON configuration string

The applyUpdate(String) may fail throwing an IOException in the following cases:

  • If the provided JSON configuration string is invalid or malformed.

  • If an update is already running.

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

[...]

String jsonConfigurationString = [...];

FirmwareUpdateManager firmwareUpdateManager = [...];

try {
    firmwareUpdateManager.applyUpdate(jsonConfigurationString);
} catch (IOException e) {
    [...]
}

[...]

Once the update has started, you can control and manage the update with the functions described in Control the firmware update process chapter.

After a successful firmware update, you must reboot the device to boot in the update system.

Control the firmware update process

The firmware update service provides several methods to control and manage the update process once it has started:

Method Description

cancelUpdate()

Permanently cancels an in-progress update. No changes are applied.

resetUpdate()

Resets the bootable flag on the non-current partition and all internal update_engine state. This means that, if an update has been applied, it is ignored.

suspendUpdate()

Suspends an in-progress update.

resumeUpdate()

Resumes a suspended update.

Some of the methods described above may fail with an IllegalStateException:

  • The cancelUpdate() method will fail if there is not an update in progress.

  • The suspendUpdate() method will fail if there is not an update in progress.

  • The resumeUpdate() method will fail if there is not any suspended update.

Control firmware update
import com.digi.android.firmwareupdate.FirmwareUpdateManager;
[...]

FirmwareUpdateManager firmwareUpdateManager = [...];

[...]

firmwareUpdateManager.resetUpdate();

[...]

try {
    firmwareUpdateManager.cancelUpdate();
} catch (IllegalStateException e) {
    [...]
}

[...]

try {
    firmwareUpdateManager.suspendUpdate();
} catch (IllegalStateException e) {
    [...]
}

[...]

try {
    firmwareUpdateManager.resumeUpdate();
} catch (IllegalStateException e) {
    [...]
}

[...]

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 and register it using the registerFirmwareUpdateListener(listener) method passing the listener as argument.

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

[...]

class MyFirmwareUpdateListener implements IFirmwareUpdateListener {
    @Override
    void statusUpdate(FirmwareUpdaterStatus status, String details) {
      [...]
    }

    @Override
    void onProgress(int progress) {
      [...]
    }
}

[...]

FirmwareUpdateManager firmwareUpdateManager = [...];
MyFirmwareUpdateListener myFirmwareUpdateListener = new MyFirmwareUpdateListener();

firmwareUpdateManager.registerFirmwareUpdateListener(myFirmwareUpdateListener);

[...]

firmwareUpdateManager.removeFirmwareUpdateListener(myFirmwareUpdateListener);

[...]

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

Method Description

statusUpdate(FirmwareUpdaterStatus, String)

Notifies a firmware update status change.

onProgress(int)

Notifies percentage progress during the firmware update.

During the firmware update operation, the statusUpdate method is triggered several times to describe the different states of the process. This method provides the status argument which is a value of the FirmwareUpdaterStatus enumeration class and a string with detailed information of the new state. See Firmware update status for more information about the different update states.

The onProgress(int) method is fired to notify about update progress percentage (0-100).

To unsubscribe a listener from the firmware update service, call removeFirmwareUpdateListener(listener) passing the listener to remove as argument at any time.

It is convenient to subscribe to firmware update events before applying a system update. See Install an update package for more information.

Firmware update status

The firmware service allows you to retrieve the firmware update operation status at any time. You can either:

getUpdaterStatus() method returns a FirmwareUpdaterStatus enumeration value to describe the current firmware update state. The available values of the FirmwareUpdaterStatus are:

  • IDLE: The firmware update service is IDLE waiting for an update operation.

  • ERROR: The firmware update operation ended with error.

  • RUNNING: The firmware update service is applying an update.

  • PAUSED: The firmware update service has a paused update.

  • SLOT_SWITCH_REQUIRED: The firmware update operation has finished successfully and a manual slot switch is required. See Manual A/B slot switch.

  • REBOOT_REQUIRED: The firmware update operation has finished successfully and a reboot is required.

Firmware update status
import com.digi.android.firmwareupdate.FirmwareUpdateManager;
import com.digi.android.firmwareupdate.FirmwareUpdaterStatus;

[...]

FirmwareUpdateManager firmwareUpdateManager = [...];
FirmwareUpdaterStatus status = firmwareUpdateManager.getUpdaterStatus();

switch (status) {
    case IDLE:
        [...]
        break;
    case ERROR:
        [...]
        break;
    case RUNNING:
        [...]
        break;
    case PAUSED:
        [...]
        break;
    case SLOT_SWITCH_REQUIRED:
        [...]
        break;
    case REBOOT_REQUIRED:
        [...]
        break;
}

[...]

It is also possible to check if an update is already running by invoking the isUpdateRunning() method:

Firmware update running
import com.digi.android.firmwareupdate.FirmwareUpdateManager;
[...]

FirmwareUpdateManager firmwareUpdateManager = [...];

boolean updateRunning = firmwareUpdateManager.isUpdateRunning();

[...]

Manual A/B slot switch

Android can automatically change the boot slot after the update depending on the JSON file configuration. Firmware service provides a method to check whether a manual A/B slot switch is required. The method to call is isManualSwitchSlotRequired() and returns true if a manual A/B slot switch is required or false otherwise.

If a manual slot switch is required, the firmware service reports SLOT_SWITCH_REQUIRED status and you have to invoke the switchBootPartition() method. This method throws an IllegalStateException if there is not a previous update applied or if there is an update already running.

A/B slot switch
import com.digi.android.firmwareupdate.FirmwareUpdateManager;

[...]

FirmwareUpdateManager firmwareUpdateManager = [...];

if (firmwareUpdateManager.isManualSwitchSlotRequired()) {
    try {
        firmwareUpdateManager.switchBootPartition();
    } catch (IllegalStateException e) {
        [...]
    }
}

[...]

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.

Firmware update example

The Firmware Update Sample Application demonstrates the usage of the Firmware Update API to apply OTA update packages to the system. The application uses JSON configuration files that describe the OTA update package and process.

You can import the example using Digi’s Android Studio plugin. For more information, see Import a Digi sample application. To look at the application source code, go to the GitHub repository.