Android 10 supports dynamic partitions, a userspace partitioning system that can create, resize, and destroy partitions during over-the-air (OTA) updates.
This page describes how OTA clients resize dynamic partitions during an update for A/B devices that launched without dynamic partitions support and how OTA clients upgrade to Android 10.
Background
During an update of an A/B device to support dynamic partitions, the
GUID partition table (GPT) on the device is preserved, so there's no
super
partition on the device. Metadata is stored at
system_a
and system_b
, but this can be
customized by changing BOARD_SUPER_PARTITION_METADATA_DEVICE
.
In each of the block devices, there are two metadata slots. Only one
metadata slot in each block device is used. For example, Metadata 0 at
system_a
and Metadata 1 at system_b
correspond to partitions at the A and B slots, respectively. At
runtime, it doesn't matter which slot is being updated.
In this page, the metadata slots are called Metadata S
(source) and Metadata T (target). Similarly, partitions are referred
to as system_s
, vendor_t
, and so on.
For more information about build system configurations, see Upgrading devices.
For more information about how partitions belong to update groups, see Board configuration changes for new devices.
An example of metadata on a device is:
- Physical block device
system_a
- Metadata 0
- Group
foo_a
- Logical (dynamic) partition
system_a
- Logical (dynamic) partition
product_services_a
- Other partitions updated by Foo
- Logical (dynamic) partition
- Group
bar_a
- Logical (dynamic) partition
vendor_a
- Logical (dynamic) partition
product_a
- Other partitions updated by Bar
- Logical (dynamic) partition
- Group
- Metadata 1 (not used)
- Metadata 0
- Physical block device
system_b
- Metadata 0 (not used)
- Metadata 1
- Group foo_b
- Logical (dynamic) partition
system_b
- Logical (dynamic) partition
product_services_b
- Other partitions updated by Foo
- Logical (dynamic) partition
- Group bar_b
- Logical (dynamic) partition
vendor_b
- Logical (dynamic) partition
product_b
- Other partitions updated by Bar
- Logical (dynamic) partition
- Group foo_b
You can use the lpdump
tool under
system/extras/partition_tools
to dump the metadata on
your device. For example:
lpdump --slot 0 /dev/block/by-name/system_a
lpdump --slot 1 /dev/block/by-name/system_b
Retrofit an update
On devices running Android 9 and lower, the OTA client on the device doesn't support mapping dynamic partitions before the update. An additional set of patches is created so that mapping can be applied directly to the existing physical partitions.
The OTA generator builds the final super.img
file that
contains the content of all dynamic partitions, then splits the image
into multiple images matching the sizes of the physical block devices
corresponding to system, vendor, and so on. These images are named
super_system.img
, super_vendor.img
, and so on.
The OTA client applies these images to the physical partitions, rather
than applying the images for the logical (dynamic) partitions.
Because the OTA client doesn't know how to map dynamic partitions, all post-install steps are disabled automatically for these partitions when the update package is generated. See Configuring post-installation for more details.
The update flow is the same as in Android 9.
Before the update:
ro.boot.dynamic_partitions= ro.boot.dynamic_partitions_retrofit=
After the update:
ro.boot.dynamic_partitions=true ro.boot.dynamic_partitions_retrofit=true
Future updates after retrofit
After the retrofit update, the OTA client is updated to work with dynamic partitions. The extents for source partitions never span across target physical partitions.
Update flow using a regular update package
- Initialize the
super
partition metadata.-
Construct new metadata M from Metadata S (source metadata).
For example, if Metadata S uses [
system_s
,vendor_s
,product_s
] as block devices, then the new metadata M uses [system_t
,vendor_t
,product_t
] as block devices. All groups and partitions are discarded in M. -
Add target groups and partitions according to the
dynamic_partition_metadata
field in the update manifest. The size of each partition can be found innew_partition_info
. - Write M to Metadata T.
- Map the added partitions on the device mapper as writable.
-
Construct new metadata M from Metadata S (source metadata).
For example, if Metadata S uses [
- Apply the update on the block devices.
- If necessary, map the source partitions on the device mapper as read only. This is necessary for sideloading because the source partitions aren't mapped prior to the update.
- Apply a full or delta update to all block devices at the target slot.
- Mount the partitions to run the post-install script, and then unmount the partitions.
- Unmap the target partitions.
Update flow using a retrofit update package
If the retrofit update package is applied on a device that already
enables dynamic partitions, the OTA client applies the split
super.img
file on block devices directly. The update
flow is similar to a retrofit update. See
Retrofitting an update
for details.
For example, assume the following:
- Slot A is the active slot.
-
system_a
contains the active metadata at slot 0. -
system_a
,vendor_a
, andproduct_a
are used as block devices.
When the OTA client receives a retrofit update package, it applies
super_system.img
on physical system_b
,
super_vendor.img
on physical vendor_b
, and
super_product.img
on physical product_b
.
The physical block device system_b
contains the correct
metadata to map the logical system_b
,
vendor_b
, and product_b
at boot time.
Generate update packages
Incremental OTA
When generating incremental OTAs for retrofit devices, the updates
depend on whether or not the base build defines
PRODUCT_USE_DYNAMIC_PARTITIONS
and
PRODUCT_RETROFIT_DYNAMIC_PARTITIONS
.
-
If the base build doesn't define the variables, this is a
retrofitting update. The update package contains the split
super.img
file and disables the post-install step. - If the base build does define the variables, this is the same as a typical update with dynamic partitions. The update package contains the images for logical (dynamic) partitions. The post-install step can be enabled.
Full OTA
Two full OTA packages are generated for retrofit devices.
-
$(PRODUCT)-ota-retrofit-$(TAG).zip
always contains splitsuper.img
and disables the post-install step for retrofitting update.-
It's generated with an additional argument
--retrofit_dynamic_partitions
to theota_from_target_files
script. - It can be applied to all builds.
-
It's generated with an additional argument
-
$(PRODUCT)-ota-$(TAG).zip
contains logical images for future updates.- Apply this only to builds with dynamic partitions enabled. See details below on enforcing this.
Reject nonretrofit update on old builds
Apply the regular full OTA package only to builds with dynamic partitions enabled. If the OTA server is configured incorrectly and pushes these packages to devices running Android 9 or lower, devices fail to boot. The OTA client on Android 9 and lower can't tell the difference between a retrofit OTA package and a regular full OTA package, so the client won't reject the full package.
To prevent the device from accepting the full OTA package, you can require a post-install step to check the existing device configuration. For example:
device/device_name/dynamic_partitions/check_dynamic_partitions
#!/system/bin/sh DP_PROPERTY_NAME="ro.boot.dynamic_partitions" DP_RETROFIT_PROPERTY_NAME="ro.boot.dynamic_partitions_retrofit" DP_PROPERTY=$(getprop ${DP_PROPERTY_NAME}) DP_RETROFIT_PROPERTY=$(getprop ${DP_RETROFIT_PROPERTY_NAME}) if [ "${DP_PROPERTY}" != "true" ] || [ "${DP_RETROFIT_PROPERTY}" != "true" ] ; then echo "Error: applied non-retrofit update on build without dynamic" \ "partitions." echo "${DP_PROPERTY_NAME}=${DP_PROPERTY}" echo "${DP_RETROFIT_PROPERTY_NAME}=${DP_RETROFIT_PROPERTY}" exit 1 fi
device/device_name/dynamic_partitions/Android.mk
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE:= check_dynamic_partitions LOCAL_MODULE_TAGS := optional LOCAL_MODULE_CLASS := EXECUTABLES LOCAL_SRC_FILES := check_dynamic_partitions LOCAL_PRODUCT_MODULE := true include $(BUILD_PREBUILT)
device/device_name/device.mk
PRODUCT_PACKAGES += check_dynamic_partitions # OPTIONAL=false so that the error in check_dynamic_partitions will be # propagated to OTA client. AB_OTA_POSTINSTALL_CONFIG += \ RUN_POSTINSTALL_product=true \ POSTINSTALL_PATH_product=bin/check_dynamic_partitions \ FILESYSTEM_TYPE_product=ext4 \ POSTINSTALL_OPTIONAL_product=false \
When the regular OTA package is applied on a device without dynamic
partitions enabled, the OTA client runs
check_dynamic_partitions
as a post-install step and
rejects the update.