Skip to main content

Android OTA Update Client

The Bort SDK includes a full OTA Update Client since version 3.7.0, which uses the Memfault Android OTA service to manage the OTA update process. This supports:

  • RecoverySystem-based updates.
  • Update Engine-based updates (also known as A/B or Seamless updates).
  • Checking for updates (both regularly in the background, and manually via the system Settings menu). Check interval can be configured dynamically on the Memfault dashboard.
  • Downloading updates (and resuming interrupted downloads).
  • UI notifications of available updates, and download progress.
  • Incremental updates, referred to as Delta Releases in Memfault lingo.

In future updates, additional features will be supported:

  • Further remote configuration of update behavior (e.g. headless update behavior, force-update policy).

OTA Update Client behavior

This behavior can be customized by modifying the bort-ota application. More behavior will be remotely configurable in future releases of the OTA Update Client.

The OTA Update Client will periodically check for updates. By default, this happens every 12 hours. When an update is found, a notification is displayed.

The default behaviour is a fully user-in-the-loop update process. To download or install updates automatically without user intervention, see below.

A "Software Updates" system settings screen is added. Users can manually check for updates on this screen.

When an update is found, the notification will redirect users to the settings screen, where they can read release notes, download, and apply the update.

Update Check API

A broadcast Intent API is available, to request that the OTA update client checks for a new version (in addition to the regular scheduled checks). This can be used either over adb, or from another app on the device which holds the BORT_CONTROL_PERMISSION. Replace your.bort.ota.app.id with your Bort OTA application ID.

Using the Bort CLI:

bort_cli.py ota-check --bort-ota-app-id your.bort.ota.app.id

Using adb (by default this requires adb root to gain the com.memfault.bort.permission.CONTROL permission):

adb shell am broadcast -a com.memfault.intent.action.OTA_CHECK_FOR_UPDATES -n your.bort.ota.app.id/com.memfault.bort.ota.lib.CheckForUpdatesReceiver

From another app:

Intent("com.memfault.intent.action.OTA_CHECK_FOR_UPDATES").apply {
component = ComponentName(
"your.bort.ota.app.id", // Whatever you have chosen for the Bort OTA application ID
"com.memfault.bort.ota.lib.CheckForUpdatesReceiver"
)
}.also {
context.sendBroadcast(it)
}

OTA Update Client architecture

The OTA Update Client is included in the Bort SDK as a separate app and can be found on GitHub in the bort-ota project.

The OTA Update Client is optional, and will not be included in your system image if not required.

The bort-ota app is designed to be customizable (for example, to customize the notification UI). All customizations should be made within the bort-ota project.

The bort-ota-lib library project contains the core OTA logic, and is not intended to be customized.

The OTA Update Client requires the main Bort application to be installed and running, in order to function correctly.

Enable OTA Update Client

Ensure that the Bort OTA application ID is set (see Patch the SDK or manually update BORT_OTA_APPLICATION_ID in bort.properties).

The OTA app also needs to be configured with a keystore. See Create a keystore for the OTA Update Client app.

Once the OTA application is configured, setting the TARGET_USES_MFLT_OTA environment variable will include it in the system image. e.g.

export TARGET_USES_MFLT_OTA=1
caution

Ensure this variable is set whenever you build the Bort SDK.

After building and installing the system image, the Memfault OTA app will be active. A Release can now be activated in the Cohort containing this device.

Customizing the OTA Update Client

Applying OTA updates in the background

By default, the OTA Update Client will create a notification (see above) when an update is available - which requires user interaction before the update is installed.

From version 4.2.0, this behavior can be changed to automatically apply updates in the background, by setting the OTA_AUTO_INSTALL flag in bort.properties:

OTA_AUTO_INSTALL=true

From version 4.8.0, additional customization options are available to configure exactly when an update will be downloaded and installed in the background.

Bort's periodic check for new updates was changed in 4.8.0 to remove storage/battery/unmetered network constraints. This means that the constraints to the download/install steps can be customized using the available OTA update metadata.

Configuring background download and install behavior.

If OTA_AUTO_INSTALL flag is true, once an update has been found then Bort will use the configuration found in AutoInstallRules.kt to decide whether to download the update in the background (see canAutoDownloadOtaUpdateNow and downloadRules), then once an update has been downloaded, whether to install the update in the background (see canAutoInstallOtaUpdateNow and installRules).

To customise this logic, make changes to AutoInstallRules.kt before you compile the Bort OTA app.

Bort will schedule JobScheduler jobs for download/install based on the constraints defined in downloadRules/installrules. When these jobs run (i.e. when the constraints have been satisfied) the custom logic in canAutoDownloadOtaUpdateNow/canAutoInstallOtaUpdateNow respectively will be executed - the download or install will only take place when true is returned.

Note: overrideNetworkConstraint is null by default - this means that the dashboard configuration (Settings / Data Sources / Allow OTA downloads on Metered Networks) will take effect. Setting this to an explicit NetworkType will override the dashboard configuration.

An OTA object is passed to both of these methods - this includes metadata describing the OTA release which is available for download. This can be used in the custom logic to determine e.g. the urgency of installing an update in the background:

PropertyDescription
urlThe URL which Bort will use to download the update (provided for information only).
versionThe new version.
releaseNotesRelease notes, as added with the CLI or in the dashboard.
artifactMetadataMemfault-internal metadata describing the OTA artifact.
releaseMetadataContains any custom metadata added when uploading the artifact using the Memfault CLI using the --extra-metadata option.
isDeltaIs the update a delta/incremental update?
sizeThe size of the update image (bytes).

String translations

The strings used in the various UI elements (notifications, check for updates screen) are located in bort-ota/src/main/res/values/strings.xml. You may want to either customize, or translate these into other languages. See the Android documentation for more information.

Updating the OTA Update Client

The OTA Update Client application can (just like the main Bort application) be updated using the Android package manager. If a device has an MDM capability, then this can be used to update the OTA apk in the future, without a full OS update.

It may still be necessary to update the OS for certain new features, if they required AOSP modifications.

Testing OTA updates

It is recommended to thoroughly test the entire OTA update process after integrating the OTA Update Client. This should always include testing the ability to update from any new OS version.

Troubleshooting

Ensure that the TARGET_USES_MFLT_OTA environment variable is set in the environments where both the gradle build, and AOSP build, take place. Without this, the OTA app will not be included, or may not be correctly configured.