This app demonstrates how to use Android system updates APIs to install OTA updates. It contains a sample client for update_engine
to install A/B (seamless) updates and a sample of applying non-A/B updates using recovery
.
A/B (seamless) update is available since Android Nougat (API 24), but this sample targets the latest android.
SystemUpdaterSample app shows list of available updates on the UI. User is allowed to select an update and apply it to the device. App shows installation progress, logs can be found in adb logcat
. User can stop or reset an update. Resetting the update requests update engine to cancel any ongoing update, and revert if the update has been applied. Stopping does not revert the applied update.
In this sample updates are defined in JSON update config files. The structure of a config file is defined in com.example.android.systemupdatersample.UpdateConfig
, example file is located at res/raw/sample.json
.
In real-life update system the config files expected to be served from a server to the app, but in this sample, the config files are stored on the device. The directory can be found in logs or on the UI. In most cases it should be located at /data/user/0/com.example.android.systemupdatersample/files/configs/
.
SystemUpdaterSample app downloads OTA package from url
. In this sample app url
is expected to point to file system, e.g. file:///data/sample-builds/ota-002.zip
.
If ab_install_type
is NON_STREAMING
then app checks if url
starts with file://
and passes url
to the update_engine
.
If ab_install_type
is STREAMING
, app downloads only the entries in need, as opposed to the entire package, to initiate a streaming update. The payload.bin
entry, which takes up the majority of the space in an OTA package, will be streamed by update_engine
directly. The ZIP entries in such a package need to be saved uncompressed (ZIP_STORED
), so that their data can be downloaded directly with the offset and length. As payload.bin
itself is already in compressed format, the size penalty is marginal.
Config files can be generated using tools/gen_update_config.py
. Running ./tools/gen_update_config.py --help
shows usage of the script.
The commands expected to be run from $ANDROID_BUILD_TOP
and for demo purpose only.
$ mmma bootable/recovery/updater_sample
.$ adb install <APK_PATH>
./data/ota_package/
to 0777
on the device.PayloadSpec
and PayloadSpecs
for working with update zip fileUpdateConfig
for working with json config filesMainActivity
UpdateEngine#applyPayload
$ mmma bootable/recovery/updater_sample/
$ adb install $OUT/system/app/SystemUpdaterSample/SystemUpdaterSample.apk
$ adb install $OUT/testcases/SystemUpdaterSampleTests/SystemUpdaterSampleTests.apk
$ adb shell am instrument -w com.example.android.systemupdatersample.tests/android.support.test.runner.AndroidJUnitRunner
$ adb shell am instrument \ -w com.example.android.systemupdatersample.tests/android.support.test.runner.AndroidJUnitRunner \ -c com.example.android.systemupdatersample.util.PayloadSpecsTest
android.os.UpdateEngine
APIandroid.os.UpdateEngine`` APIs are marked as
@SystemApi`, meaning only system apps can access them.
/data/ota_package/
Following must be included in AndroidManifest.xml
:
<uses-permission android:name="android.permission.ACCESS_CACHE_FILESYSTEM" />
Note: access to cache filesystem is granted only to system apps.
local$ adb root
local$ adb shell
android# setenforce 0
android# getenforce
SystemUpdaterSample app is released under Apache License 2.0.