diff --git a/core/Makefile b/core/Makefile index 9cf539ded..791102604 100644 --- a/core/Makefile +++ b/core/Makefile @@ -1261,19 +1261,23 @@ else recovery_wipe := endif -# Prior to A/B update, we used to have: +# Traditionally with non-A/B OTA we have: # boot.img + recovery-from-boot.p + recovery-resource.dat = recovery.img. -# recovery-resource.dat is needed only if we carry a patch of the boot and -# recovery images and invoke install-recovery.sh on the first boot post an -# OTA update. +# recovery-resource.dat is needed only if we carry an imgdiff patch of the boot and recovery images +# and invoke install-recovery.sh on the first boot post an OTA update. # # We no longer need that if one of the following conditions holds: -# a) We carry a full copy of the recovery image +# a) We carry a full copy of the recovery image - no patching needed # (BOARD_USES_FULL_RECOVERY_IMAGE = true); -# b) We build a single image that contains boot and recovery both -# (BOARD_USES_RECOVERY_AS_BOOT = true). +# b) We build a single image that contains boot and recovery both - no recovery image to install +# (BOARD_USES_RECOVERY_AS_BOOT = true); +# c) We build the root into system image - not needing the resource file as we do bsdiff +# (BOARD_BUILD_SYSTEM_ROOT_IMAGE = true). +# Note that condition b) implies condition c), because of the earlier check in this file: +# "BOARD_USES_RECOVERY_AS_BOOT = true must have BOARD_BUILD_SYSTEM_ROOT_IMAGE = true" (not vice +# versa though). -ifeq (,$(filter true, $(BOARD_USES_FULL_RECOVERY_IMAGE) $(BOARD_USES_RECOVERY_AS_BOOT))) +ifeq (,$(filter true, $(BOARD_USES_FULL_RECOVERY_IMAGE) $(BOARD_BUILD_SYSTEM_ROOT_IMAGE))) # Named '.dat' so we don't attempt to use imgdiff for patching it. RECOVERY_RESOURCE_ZIP := $(TARGET_OUT)/etc/recovery-resource.dat else @@ -1560,15 +1564,21 @@ SYSTEMIMAGE_SOURCE_DIR := $(TARGET_OUT) # image size check calculation. ifneq ($(INSTALLED_RECOVERYIMAGE_TARGET),) ifneq ($(BOARD_USES_FULL_RECOVERY_IMAGE),true) +ifeq ($(BOARD_BUILD_SYSTEM_ROOT_IMAGE),true) +diff_tool := $(HOST_OUT_EXECUTABLES)/bsdiff +else +diff_tool := $(HOST_OUT_EXECUTABLES)/imgdiff +endif intermediates := $(call intermediates-dir-for,PACKAGING,recovery_patch) RECOVERY_FROM_BOOT_PATCH := $(intermediates)/recovery_from_boot.p -$(RECOVERY_FROM_BOOT_PATCH): $(INSTALLED_RECOVERYIMAGE_TARGET) \ - $(INSTALLED_BOOTIMAGE_TARGET) \ - $(HOST_OUT_EXECUTABLES)/imgdiff \ - $(HOST_OUT_EXECUTABLES)/bsdiff +$(RECOVERY_FROM_BOOT_PATCH): PRIVATE_DIFF_TOOL := $(diff_tool) +$(RECOVERY_FROM_BOOT_PATCH): \ + $(INSTALLED_RECOVERYIMAGE_TARGET) \ + $(INSTALLED_BOOTIMAGE_TARGET) \ + $(diff_tool) @echo "Construct recovery from boot" mkdir -p $(dir $@) - PATH=$(HOST_OUT_EXECUTABLES):$$PATH $(HOST_OUT_EXECUTABLES)/imgdiff $(INSTALLED_BOOTIMAGE_TARGET) $(INSTALLED_RECOVERYIMAGE_TARGET) $@ + $(PRIVATE_DIFF_TOOL) $(INSTALLED_BOOTIMAGE_TARGET) $(INSTALLED_RECOVERYIMAGE_TARGET) $@ else # $(BOARD_USES_FULL_RECOVERY_IMAGE) == true RECOVERY_FROM_BOOT_PATCH := $(INSTALLED_RECOVERYIMAGE_TARGET) endif diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py index 743c6a057..787de9822 100644 --- a/tools/releasetools/common.py +++ b/tools/releasetools/common.py @@ -1828,35 +1828,47 @@ def ExtractPublicKey(cert): def MakeRecoveryPatch(input_dir, output_sink, recovery_img, boot_img, info_dict=None): - """Generate a binary patch that creates the recovery image starting - with the boot image. (Most of the space in these images is just the - kernel, which is identical for the two, so the resulting patch - should be efficient.) Add it to the output zip, along with a shell - script that is run from init.rc on first boot to actually do the - patching and install the new recovery image. + """Generates the recovery-from-boot patch and writes the script to output. - recovery_img and boot_img should be File objects for the - corresponding images. info should be the dictionary returned by - common.LoadInfoDict() on the input target_files. + Most of the space in the boot and recovery images is just the kernel, which is + identical for the two, so the resulting patch should be efficient. Add it to + the output zip, along with a shell script that is run from init.rc on first + boot to actually do the patching and install the new recovery image. + + Args: + input_dir: The top-level input directory of the target-files.zip. + output_sink: The callback function that writes the result. + recovery_img: File object for the recovery image. + boot_img: File objects for the boot image. + info_dict: A dict returned by common.LoadInfoDict() on the input + target_files. Will use OPTIONS.info_dict if None has been given. """ - if info_dict is None: info_dict = OPTIONS.info_dict - full_recovery_image = info_dict.get("full_recovery_image", None) == "true" + full_recovery_image = info_dict.get("full_recovery_image") == "true" if full_recovery_image: output_sink("etc/recovery.img", recovery_img.data) else: - diff_program = ["imgdiff"] + system_root_image = info_dict.get("system_root_image") == "true" path = os.path.join(input_dir, "SYSTEM", "etc", "recovery-resource.dat") - if os.path.exists(path): - diff_program.append("-b") - diff_program.append(path) - bonus_args = "-b /system/etc/recovery-resource.dat" - else: + # With system-root-image, boot and recovery images will have mismatching + # entries (only recovery has the ramdisk entry) (Bug: 72731506). Use bsdiff + # to handle such a case. + if system_root_image: + diff_program = ["bsdiff"] bonus_args = "" + assert not os.path.exists(path) + else: + diff_program = ["imgdiff"] + if os.path.exists(path): + diff_program.append("-b") + diff_program.append(path) + bonus_args = "-b /system/etc/recovery-resource.dat" + else: + bonus_args = "" d = Difference(recovery_img, boot_img, diff_program=diff_program) _, _, patch = d.ComputePatch()