Merge "releasetools: Add signapk as required modules" into rvc-dev
diff --git a/core/Makefile b/core/Makefile
index e2d096d..ea4a745 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -587,9 +587,7 @@
@echo Target product buildinfo: $@
@mkdir -p $(dir $@)
$(hide) echo > $@
-ifdef BOARD_USES_PRODUCTIMAGE
$(hide) $(call generate-common-build-props,product,$@)
-endif # BOARD_USES_PRODUCTIMAGE
$(hide) $(foreach file,$(product_prop_files), \
if [ -f "$(file)" ]; then \
echo Target product properties from: "$(file)"; \
@@ -721,6 +719,11 @@
# Depmod requires a well-formed kernel version so 0.0 is used as a placeholder.
DEPMOD_STAGING_SUBDIR :=$= lib/modules/0.0
+define copy-and-strip-kernel-module
+$(2): $(1)
+ $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_STRIP) -o $(2) --strip-debug $(1)
+endef
+
# $(1): modules list
# $(2): output dir
# $(3): mount point
@@ -728,9 +731,15 @@
# $(5): module load list
# $(6): module load list filename
# $(7): module archive
+# $(8): staging dir for stripped modules
# Returns the a list of src:dest pairs to install the modules using copy-many-files.
define build-image-kernel-modules
- $(foreach module,$(1),$(module):$(2)/lib/modules/$(notdir $(module))) \
+ $(foreach module,$(1), \
+ $(eval _src := $(module)) \
+ $(if $(8), \
+ $(eval _src := $(8)/$(notdir $(module))) \
+ $(eval $(call copy-and-strip-kernel-module,$(module),$(_src)))) \
+ $(_src):$(2)/lib/modules/$(notdir $(module))) \
$(eval $(call build-image-kernel-modules-depmod,$(1),$(3),$(4),$(5),$(6),$(7),$(2))) \
$(4)/$(DEPMOD_STAGING_SUBDIR)/modules.dep:$(2)/lib/modules/modules.dep \
$(4)/$(DEPMOD_STAGING_SUBDIR)/modules.alias:$(2)/lib/modules/modules.alias \
@@ -784,24 +793,24 @@
endef
# $(1): staging dir
-# $(2): module load list
-# $(3): module load list filename
-# $(4): output dir
+# $(2): modules list
+# $(3): module load list
+# $(4): module load list filename
+# $(5): output dir
define module-load-list-copy-paths
- $(eval $(call build-image-module-load-list,$(1),$(2),$(3))) \
- $(1)/$(DEPMOD_STAGING_SUBDIR)/$(3):$(4)/lib/modules/$(3)
+ $(eval $(call build-image-module-load-list,$(1),$(2),$(3),$(4))) \
+ $(1)/$(DEPMOD_STAGING_SUBDIR)/$(4):$(5)/lib/modules/$(4)
endef
# $(1): staging dir
-# $(2): module load list
-# $(3): module load list filename
+# $(2): modules list
+# $(3): module load list
+# $(4): module load list filename
define build-image-module-load-list
-$(1)/$(DEPMOD_STAGING_SUBDIR)/$(3): PRIVATE_STAGING_DIR := $(1)
-$(1)/$(DEPMOD_STAGING_SUBDIR)/$(3): PRIVATE_LOAD_MODULES := $(2)
-$(1)/$(DEPMOD_STAGING_SUBDIR)/$(3): PRIVATE_LOAD_FILENAME := $(3)
-$(1)/$(DEPMOD_STAGING_SUBDIR)/$(3): $(2)
- rm -f $$@
- (for MODULE in $$(PRIVATE_LOAD_MODULES); do basename $$$$MODULE >> $$@; done)
+$(1)/$(DEPMOD_STAGING_SUBDIR)/$(4): PRIVATE_LOAD_MODULES := $(3)
+$(1)/$(DEPMOD_STAGING_SUBDIR)/$(4): $(2)
+ @echo load-list $$(@)
+ @echo '$$(strip $$(notdir $$(PRIVATE_LOAD_MODULES)))' | tr ' ' '\n' > $$(@)
endef
ifneq ($(BUILDING_VENDOR_BOOT_IMAGE),true)
@@ -827,37 +836,49 @@
ifneq ($(strip $(BOARD_RECOVERY_KERNEL_MODULES))$(strip $(BOARD_RECOVERY_KERNEL_MODULES_ARCHIVE)),)
ifeq ($(BOARD_USES_RECOVERY_AS_BOOT), true)
ifdef BOARD_GENERIC_RAMDISK_KERNEL_MODULES_LOAD
- ALL_DEFAULT_INSTALLED_MODULES += $(call copy-many-files,$(call module-load-list-copy-paths,$(call intermediates-dir-for,PACKAGING,ramdisk_modules),$(BOARD_GENERIC_RAMDISK_KERNEL_MODULES_LOAD),modules.load,$(TARGET_RECOVERY_ROOT_OUT)))
+ ALL_DEFAULT_INSTALLED_MODULES += $(call copy-many-files,$(call module-load-list-copy-paths,$(call intermediates-dir-for,PACKAGING,ramdisk_modules),$(BOARD_GENERIC_RAMDISK_KERNEL_MODULES),$(BOARD_GENERIC_RAMDISK_KERNEL_MODULES_LOAD),modules.load,$(TARGET_RECOVERY_ROOT_OUT)))
endif
endif
- ALL_DEFAULT_INSTALLED_MODULES += $(call copy-many-files,$(call build-image-kernel-modules,$(BOARD_RECOVERY_KERNEL_MODULES),$(TARGET_RECOVERY_ROOT_OUT),,$(call intermediates-dir-for,PACKAGING,depmod_recovery),$(BOARD_RECOVERY_KERNEL_MODULES_LOAD),modules.load.recovery,$(BOARD_RECOVERY_KERNEL_MODULES_ARCHIVE)))
+ ALL_DEFAULT_INSTALLED_MODULES += $(call copy-many-files,$(call build-image-kernel-modules,$(BOARD_RECOVERY_KERNEL_MODULES),$(TARGET_RECOVERY_ROOT_OUT),,$(call intermediates-dir-for,PACKAGING,depmod_recovery),$(BOARD_RECOVERY_KERNEL_MODULES_LOAD),modules.load.recovery,$(BOARD_RECOVERY_KERNEL_MODULES_ARCHIVE),))
endif
ifneq ($(strip $(BOARD_VENDOR_RAMDISK_KERNEL_MODULES))$(strip $(BOARD_VENDOR_RAMDISK_KERNEL_MODULES_ARCHIVE)),)
ifeq ($(BOARD_VENDOR_RAMDISK_KERNEL_MODULES_LOAD),)
BOARD_VENDOR_RAMDISK_KERNEL_MODULES_LOAD := $(BOARD_VENDOR_RAMDISK_KERNEL_MODULES)
endif
- ALL_DEFAULT_INSTALLED_MODULES += $(call copy-many-files,$(call build-image-kernel-modules,$(BOARD_VENDOR_RAMDISK_KERNEL_MODULES),$(TARGET_VENDOR_RAMDISK_OUT),,$(call intermediates-dir-for,PACKAGING,depmod_vendor_ramdisk),$(BOARD_VENDOR_RAMDISK_KERNEL_MODULES_LOAD),modules.load,$(BOARD_VENDOR_RAMDISK_KERNEL_MODULES_ARCHIVE)))
+ ALL_DEFAULT_INSTALLED_MODULES += $(call copy-many-files,$(call build-image-kernel-modules,$(BOARD_VENDOR_RAMDISK_KERNEL_MODULES),$(TARGET_VENDOR_RAMDISK_OUT),,$(call intermediates-dir-for,PACKAGING,depmod_vendor_ramdisk),$(BOARD_VENDOR_RAMDISK_KERNEL_MODULES_LOAD),modules.load,$(BOARD_VENDOR_RAMDISK_KERNEL_MODULES_ARCHIVE),$(call intermediates-dir-for,PACKAGING,depmod_vendor_ramdisk_stripped)))
+ ifneq (,$(BOARD_VENDOR_RAMDISK_RECOVERY_KERNEL_MODULES_LOAD))
+ # BOARD_VENDOR_RAMDISK_KERNEL_MODULES must be the full set, or super set,
+ # of copied modules represented by BOARD_VENDOR_RAMDISK_KERNEL_MODULES_LOAD
+ # and BOARD_VENDOR_RAMDISK_RECOVERY_KERNEL_MODULES_LOAD which are mined
+ # from modules.load which will contain relative paths, represent load order.
+ ALL_DEFAULT_INSTALLED_MODULES += $(call copy-many-files,$(call module-load-list-copy-paths,$(call intermediates-dir-for,PACKAGING,depmod_vendor_recovery_ramdisk),$(BOARD_VENDOR_RAMDISK_KERNEL_MODULES),$(BOARD_VENDOR_RAMDISK_RECOVERY_KERNEL_MODULES_LOAD),modules.load.recovery,$(TARGET_VENDOR_RAMDISK_OUT)))
+ endif
endif
ifneq ($(BOARD_USES_RECOVERY_AS_BOOT), true)
ifneq ($(strip $(BOARD_GENERIC_RAMDISK_KERNEL_MODULES)),)
- ALL_DEFAULT_INSTALLED_MODULES += $(call copy-many-files,$(call build-image-kernel-modules,$(BOARD_GENERIC_RAMDISK_KERNEL_MODULES),$(TARGET_RAMDISK_OUT),,$(call intermediates-dir-for,PACKAGING,depmod_ramdisk),$(BOARD_GENERIC_RAMDISK_KERNEL_MODULES_LOAD),modules.load,))
+ ALL_DEFAULT_INSTALLED_MODULES += $(call copy-many-files,$(call build-image-kernel-modules,$(BOARD_GENERIC_RAMDISK_KERNEL_MODULES),$(TARGET_RAMDISK_OUT),,$(call intermediates-dir-for,PACKAGING,depmod_ramdisk),$(BOARD_GENERIC_RAMDISK_KERNEL_MODULES_LOAD),modules.load,,))
endif
endif
+ifneq ($(BOARD_DO_NOT_STRIP_VENDOR_MODULES),true)
+ VENDOR_STRIPPED_MODULE_STAGING_DIR := $(call intermediates-dir-for,PACKAGING,depmod_vendor_stripped)
+else
+ VENDOR_STRIPPED_MODULE_STAGING_DIR :=
+endif
ifneq ($(strip $(BOARD_VENDOR_KERNEL_MODULES)$(strip $(BOARD_VENDOR_KERNEL_MODULES_ARCHIVE))),)
ifeq ($(BOARD_VENDOR_KERNEL_MODULES_LOAD),)
BOARD_VENDOR_KERNEL_MODULES_LOAD := $(BOARD_VENDOR_KERNEL_MODULES)
endif
- ALL_DEFAULT_INSTALLED_MODULES += $(call copy-many-files,$(call build-image-kernel-modules,$(BOARD_VENDOR_KERNEL_MODULES),$(TARGET_OUT_VENDOR),vendor,$(call intermediates-dir-for,PACKAGING,depmod_vendor),$(BOARD_VENDOR_KERNEL_MODULES_LOAD),modules.load,$(BOARD_VENDOR_KERNEL_MODULES_ARCHIVE)))
+ ALL_DEFAULT_INSTALLED_MODULES += $(call copy-many-files,$(call build-image-kernel-modules,$(BOARD_VENDOR_KERNEL_MODULES),$(TARGET_OUT_VENDOR),vendor,$(call intermediates-dir-for,PACKAGING,depmod_vendor),$(BOARD_VENDOR_KERNEL_MODULES_LOAD),modules.load,$(BOARD_VENDOR_KERNEL_MODULES_ARCHIVE),$(VENDOR_STRIPPED_MODULE_STAGING_DIR)))
endif
ifneq ($(strip $(BOARD_ODM_KERNEL_MODULES))$(strip $(BOARD_ODM_KERNEL_MODULES_ARCHIVE)),)
ifeq ($(BOARD_RECOVERY_KERNEL_MODULES_LOAD),)
BOARD_ODM_KERNEL_MODULES_LOAD := $(BOARD_ODM_KERNEL_MODULES)
endif
- ALL_DEFAULT_INSTALLED_MODULES += $(call copy-many-files,$(call build-image-kernel-modules,$(BOARD_ODM_KERNEL_MODULES),$(TARGET_OUT_ODM),odm,$(call intermediates-dir-for,PACKAGING,depmod_odm),$(BOARD_ODM_KERNEL_MODULES_LOAD),modules.load,$(BOARD_ODM_KERNEL_MODULES_ARCHIVE)))
+ ALL_DEFAULT_INSTALLED_MODULES += $(call copy-many-files,$(call build-image-kernel-modules,$(BOARD_ODM_KERNEL_MODULES),$(TARGET_OUT_ODM),odm,$(call intermediates-dir-for,PACKAGING,depmod_odm),$(BOARD_ODM_KERNEL_MODULES_LOAD),modules.load,$(BOARD_ODM_KERNEL_MODULES_ARCHIVE),))
endif
# -----------------------------------------------------------------
@@ -1100,16 +1121,27 @@
$(call dist-for-goals, sdk win_sdk sdk_addon, $(INSTALLED_FILES_FILE_RAMDISK))
BUILT_RAMDISK_TARGET := $(PRODUCT_OUT)/ramdisk.img
+ifeq ($(BOARD_RAMDISK_USE_LZ4),true)
+# -l enables the legacy format used by the Linux kernel
+COMPRESSION_COMMAND_DEPS := $(LZ4)
+COMPRESSION_COMMAND := $(LZ4) -l -12 --favor-decSpeed
+RAMDISK_EXT := .lz4
+else
+COMPRESSION_COMMAND_DEPS := $(MINIGZIP)
+COMPRESSION_COMMAND := $(MINIGZIP)
+RAMDISK_EXT := .gz
+endif
+
# We just build this directly to the install location.
INSTALLED_RAMDISK_TARGET := $(BUILT_RAMDISK_TARGET)
-$(INSTALLED_RAMDISK_TARGET): $(MKBOOTFS) $(INTERNAL_RAMDISK_FILES) $(INSTALLED_FILES_FILE_RAMDISK) | $(MINIGZIP)
+$(INSTALLED_RAMDISK_TARGET): $(MKBOOTFS) $(INTERNAL_RAMDISK_FILES) $(INSTALLED_FILES_FILE_RAMDISK) | $(COMPRESSION_COMMAND_DEPS)
$(call pretty,"Target ram disk: $@")
- $(hide) $(MKBOOTFS) -d $(TARGET_OUT) $(TARGET_RAMDISK_OUT) | $(MINIGZIP) > $@
+ $(hide) $(MKBOOTFS) -d $(TARGET_OUT) $(TARGET_RAMDISK_OUT) | $(COMPRESSION_COMMAND) > $@
.PHONY: ramdisk-nodeps
-ramdisk-nodeps: $(MKBOOTFS) | $(MINIGZIP)
+ramdisk-nodeps: $(MKBOOTFS) | $(COMPRESSION_COMMAND_DEPS)
@echo "make $@: ignoring dependencies"
- $(hide) $(MKBOOTFS) -d $(TARGET_OUT) $(TARGET_RAMDISK_OUT) | $(MINIGZIP) > $(INSTALLED_RAMDISK_TARGET)
+ $(hide) $(MKBOOTFS) -d $(TARGET_OUT) $(TARGET_RAMDISK_OUT) | $(COMPRESSION_COMMAND) > $(INSTALLED_RAMDISK_TARGET)
endif # BUILDING_RAMDISK_IMAGE
@@ -1124,6 +1156,15 @@
BUILT_BOOTIMAGE_TARGET := $(PRODUCT_OUT)/boot.img
endif
+ifdef BOARD_BOOTIMAGE_PARTITION_SIZE
+ BOARD_KERNEL_BOOTIMAGE_PARTITION_SIZE := $(BOARD_BOOTIMAGE_PARTITION_SIZE)
+endif
+
+# $1: boot image file name
+# $2: boot image variant (boot, boot-debug)
+define get-bootimage-partition-size
+ $(BOARD_$(call to-upper,$(subst .img,,$(subst $(2),kernel,$(notdir $(1)))))_BOOTIMAGE_PARTITION_SIZE)
+endef
ifneq ($(strip $(TARGET_NO_KERNEL)),true)
INTERNAL_BOOTIMAGE_ARGS := \
@@ -1274,8 +1315,8 @@
$(ALL_DEFAULT_INSTALLED_MODULES))
INTERNAL_VENDOR_RAMDISK_TARGET := $(call intermediates-dir-for,PACKAGING,vendor-boot)/vendor-ramdisk.cpio.gz
-$(INTERNAL_VENDOR_RAMDISK_TARGET): $(MKBOOTFS) $(INTERNAL_VENDOR_RAMDISK_FILES) | $(MINIGZIP)
- $(MKBOOTFS) -d $(TARGET_OUT) $(TARGET_VENDOR_RAMDISK_OUT) | $(MINIGZIP) > $@
+$(INTERNAL_VENDOR_RAMDISK_TARGET): $(MKBOOTFS) $(INTERNAL_VENDOR_RAMDISK_FILES) | $(COMPRESSION_COMMAND_DEPS)
+ $(MKBOOTFS) -d $(TARGET_OUT) $(TARGET_VENDOR_RAMDISK_OUT) | $(COMPRESSION_COMMAND) > $@
ifdef BOARD_INCLUDE_DTB_IN_BOOTIMG
INTERNAL_VENDOR_BOOTIMAGE_ARGS += --dtb $(INSTALLED_DTBIMAGE_TARGET)
@@ -2116,7 +2157,7 @@
BOARD_RECOVERY_MKBOOTIMG_ARGS := $(BOARD_MKBOOTIMG_ARGS)
endif
-$(recovery_ramdisk): $(MKBOOTFS) $(MINIGZIP) \
+$(recovery_ramdisk): $(MKBOOTFS) $(COMPRESSION_COMMAND_DEPS) \
$(INTERNAL_ROOT_FILES) \
$(INSTALLED_RAMDISK_TARGET) \
$(INTERNAL_RECOVERYIMAGE_FILES) \
@@ -2151,7 +2192,7 @@
cp -f $(recovery_wipe) $(TARGET_RECOVERY_ROOT_OUT)/system/etc/recovery.wipe)
ln -sf prop.default $(TARGET_RECOVERY_ROOT_OUT)/default.prop
$(BOARD_RECOVERY_IMAGE_PREPARE)
- $(MKBOOTFS) -d $(TARGET_OUT) $(TARGET_RECOVERY_ROOT_OUT) | $(MINIGZIP) > $(recovery_ramdisk)
+ $(MKBOOTFS) -d $(TARGET_OUT) $(TARGET_RECOVERY_ROOT_OUT) | $(COMPRESSION_COMMAND) > $(recovery_ramdisk)
# $(1): output file
# $(2): kernel file
@@ -2172,11 +2213,11 @@
$(if $(filter true,$(PRODUCT_SUPPORTS_VBOOT)), \
$(VBOOT_SIGNER) $(FUTILITY) $(1).unsigned $(PRODUCT_VBOOT_SIGNING_KEY).vbpubk $(PRODUCT_VBOOT_SIGNING_KEY).vbprivk $(PRODUCT_VBOOT_SIGNING_SUBKEY).vbprivk $(1).keyblock $(1))
$(if $(filter true,$(BOARD_USES_RECOVERY_AS_BOOT)), \
- $(call assert-max-image-size,$(1),$(call get-hash-image-max-size,$(BOARD_BOOTIMAGE_PARTITION_SIZE))), \
+ $(call assert-max-image-size,$(1),$(call get-hash-image-max-size,$(call get-bootimage-partition-size,$(1),boot))), \
$(call assert-max-image-size,$(1),$(call get-hash-image-max-size,$(BOARD_RECOVERYIMAGE_PARTITION_SIZE))))
$(if $(filter true,$(BOARD_AVB_ENABLE)), \
$(if $(filter true,$(BOARD_USES_RECOVERY_AS_BOOT)), \
- $(AVBTOOL) add_hash_footer --image $(1) --partition_size $(BOARD_BOOTIMAGE_PARTITION_SIZE) --partition_name boot $(INTERNAL_AVB_BOOT_SIGNING_ARGS) $(BOARD_AVB_BOOT_ADD_HASH_FOOTER_ARGS),\
+ $(AVBTOOL) add_hash_footer --image $(1) --partition_size $(call get-bootimage-partition-size,$(1),boot) --partition_name boot $(INTERNAL_AVB_BOOT_SIGNING_ARGS) $(BOARD_AVB_BOOT_ADD_HASH_FOOTER_ARGS),\
$(AVBTOOL) add_hash_footer --image $(1) --partition_size $(BOARD_RECOVERYIMAGE_PARTITION_SIZE) --partition_name recovery $(INTERNAL_AVB_RECOVERY_SIGNING_ARGS) $(BOARD_AVB_RECOVERY_ADD_HASH_FOOTER_ARGS)))
endef
@@ -2309,22 +2350,22 @@
# Depends on ramdisk.img, note that some target has ramdisk.img but no boot.img, e.g., emulator.
$(INSTALLED_DEBUG_RAMDISK_TARGET): $(INSTALLED_RAMDISK_TARGET)
endif # BOARD_USES_RECOVERY_AS_BOOT
-$(INSTALLED_DEBUG_RAMDISK_TARGET): $(MKBOOTFS) $(INTERNAL_DEBUG_RAMDISK_FILES) | $(MINIGZIP)
+$(INSTALLED_DEBUG_RAMDISK_TARGET): $(MKBOOTFS) $(INTERNAL_DEBUG_RAMDISK_FILES) | $(COMPRESSION_COMMAND_DEPS)
$(call pretty,"Target debug ram disk: $@")
mkdir -p $(TARGET_DEBUG_RAMDISK_OUT)
touch $(TARGET_DEBUG_RAMDISK_OUT)/force_debuggable
rsync -a $(DEBUG_RAMDISK_SYNC_DIR)/ $(DEBUG_RAMDISK_ROOT_DIR)
- $(MKBOOTFS) -d $(TARGET_OUT) $(DEBUG_RAMDISK_ROOT_DIR) | $(MINIGZIP) > $@
+ $(MKBOOTFS) -d $(TARGET_OUT) $(DEBUG_RAMDISK_ROOT_DIR) | $(COMPRESSION_COMMAND) > $@
.PHONY: ramdisk_debug-nodeps
ramdisk_debug-nodeps: DEBUG_RAMDISK_SYNC_DIR := $(my_debug_ramdisk_sync_dir)
ramdisk_debug-nodeps: DEBUG_RAMDISK_ROOT_DIR := $(my_debug_ramdisk_root_dir)
-ramdisk_debug-nodeps: $(MKBOOTFS) | $(MINIGZIP)
+ramdisk_debug-nodeps: $(MKBOOTFS) | $(COMPRESSION_COMMAND_DEPS)
echo "make $@: ignoring dependencies"
mkdir -p $(TARGET_DEBUG_RAMDISK_OUT)
touch $(TARGET_DEBUG_RAMDISK_OUT)/force_debuggable
rsync -a $(DEBUG_RAMDISK_SYNC_DIR)/ $(DEBUG_RAMDISK_ROOT_DIR)
- $(MKBOOTFS) -d $(TARGET_OUT) $(DEBUG_RAMDISK_ROOT_DIR) | $(MINIGZIP) > $(INSTALLED_DEBUG_RAMDISK_TARGET)
+ $(MKBOOTFS) -d $(TARGET_OUT) $(DEBUG_RAMDISK_ROOT_DIR) | $(COMPRESSION_COMMAND) > $(INSTALLED_DEBUG_RAMDISK_TARGET)
my_debug_ramdisk_sync_dir :=
my_debug_ramdisk_root_dir :=
@@ -2363,13 +2404,13 @@
INTERNAL_AVB_BOOT_TEST_SIGNING_ARGS := --algorithm SHA256_RSA2048 --key $(BOARD_AVB_BOOT_TEST_KEY_PATH)
# $(1): the bootimage to sign
define test-key-sign-bootimage
-$(call assert-max-image-size,$(1),$(call get-hash-image-max-size,$(BOARD_BOOTIMAGE_PARTITION_SIZE)))
+$(call assert-max-image-size,$(1),$(call get-hash-image-max-size,$(call get-bootimage-partition-size,$(1),boot-debug)))
$(AVBTOOL) add_hash_footer \
--image $(1) \
- --partition_size $(BOARD_BOOTIMAGE_PARTITION_SIZE) \
+ --partition_size $(call get-bootimage-partition-size,$(1),boot-debug)\
--partition_name boot $(INTERNAL_AVB_BOOT_TEST_SIGNING_ARGS) \
$(BOARD_AVB_BOOT_ADD_HASH_FOOTER_ARGS)
-$(call assert-max-image-size,$(1),$(BOARD_BOOTIMAGE_PARTITION_SIZE))
+$(call assert-max-image-size,$(1),$(call get-bootimage-partition-size,$(1),boot-debug))
endef
# $(1): output file
@@ -2396,7 +2437,7 @@
# -----------------------------------------------------------------
# vendor debug ramdisk
# Combines vendor ramdisk files and debug ramdisk files to build the vendor debug ramdisk.
-INSTALLED_VENDOR_DEBUG_RAMDISK_TARGET := $(PRODUCT_OUT)/vendor-ramdisk-debug.cpio.gz
+INSTALLED_VENDOR_DEBUG_RAMDISK_TARGET := $(PRODUCT_OUT)/vendor-ramdisk-debug.cpio$(RAMDISK_EXT)
$(INSTALLED_VENDOR_DEBUG_RAMDISK_TARGET): DEBUG_RAMDISK_FILES := $(INTERNAL_DEBUG_RAMDISK_FILES)
$(INSTALLED_VENDOR_DEBUG_RAMDISK_TARGET): VENDOR_RAMDISK_DIR := $(TARGET_VENDOR_RAMDISK_OUT)
@@ -2410,14 +2451,14 @@
# $(PRODUCT_OUT)/vendor_debug_ramdisk.
$(INSTALLED_VENDOR_DEBUG_RAMDISK_TARGET): VENDOR_DEBUG_RAMDISK_DIR := $(PRODUCT_OUT)/vendor_debug_ramdisk
$(INSTALLED_VENDOR_DEBUG_RAMDISK_TARGET): $(INTERNAL_VENDOR_RAMDISK_TARGET) $(INSTALLED_DEBUG_RAMDISK_TARGET)
-$(INSTALLED_VENDOR_DEBUG_RAMDISK_TARGET): $(MKBOOTFS) $(INTERNAL_VENDOR_DEBUG_RAMDISK_FILES) | $(MINIGZIP)
+$(INSTALLED_VENDOR_DEBUG_RAMDISK_TARGET): $(MKBOOTFS) $(INTERNAL_VENDOR_DEBUG_RAMDISK_FILES) | $(COMPRESSION_COMMAND_DEPS)
$(call pretty,"Target vendor debug ram disk: $@")
mkdir -p $(TARGET_VENDOR_DEBUG_RAMDISK_OUT)
touch $(TARGET_VENDOR_DEBUG_RAMDISK_OUT)/force_debuggable
$(foreach debug_file,$(DEBUG_RAMDISK_FILES), \
cp -f $(debug_file) $(subst $(PRODUCT_OUT)/debug_ramdisk,$(PRODUCT_OUT)/vendor_debug_ramdisk,$(debug_file)) &&) true
rsync -a $(VENDOR_RAMDISK_DIR)/ $(VENDOR_DEBUG_RAMDISK_DIR)
- $(MKBOOTFS) -d $(TARGET_OUT) $(VENDOR_DEBUG_RAMDISK_DIR) | $(MINIGZIP) > $@
+ $(MKBOOTFS) -d $(TARGET_OUT) $(VENDOR_DEBUG_RAMDISK_DIR) | $(COMPRESSION_COMMAND) > $@
INSTALLED_FILES_FILE_VENDOR_DEBUG_RAMDISK := $(PRODUCT_OUT)/installed-files-vendor-ramdisk-debug.txt
INSTALLED_FILES_JSON_VENDOR_DEBUG_RAMDISK := $(INSTALLED_FILES_FILE_VENDOR_DEBUG_RAMDISK:.txt=.json)
@@ -2495,18 +2536,18 @@
endef
$(INSTALLED_TEST_HARNESS_RAMDISK_TARGET): $(INSTALLED_DEBUG_RAMDISK_TARGET)
-$(INSTALLED_TEST_HARNESS_RAMDISK_TARGET): $(MKBOOTFS) $(INTERNAL_TEST_HARNESS_RAMDISK_FILES) | $(MINIGZIP)
+$(INSTALLED_TEST_HARNESS_RAMDISK_TARGET): $(MKBOOTFS) $(INTERNAL_TEST_HARNESS_RAMDISK_FILES) | $(COMPRESSION_COMMAND_DEPS)
$(call pretty,"Target test harness ram disk: $@")
rsync -a $(TEST_HARNESS_RAMDISK_SYNC_DIR)/ $(TEST_HARNESS_RAMDISK_ROOT_DIR)
$(call append-test-harness-props,$(ADDITIONAL_TEST_HARNESS_PROPERTIES),$(TEST_HARNESS_PROP_TARGET))
- $(MKBOOTFS) -d $(TARGET_OUT) $(TEST_HARNESS_RAMDISK_ROOT_DIR) | $(MINIGZIP) > $@
+ $(MKBOOTFS) -d $(TARGET_OUT) $(TEST_HARNESS_RAMDISK_ROOT_DIR) | $(COMPRESSION_COMMAND) > $@
.PHONY: ramdisk_test_harness-nodeps
-ramdisk_test_harness-nodeps: $(MKBOOTFS) | $(MINIGZIP)
+ramdisk_test_harness-nodeps: $(MKBOOTFS) | $(COMPRESSION_COMMAND_DEPS)
echo "make $@: ignoring dependencies"
rsync -a $(TEST_HARNESS_RAMDISK_SYNC_DIR)/ $(TEST_HARNESS_RAMDISK_ROOT_DIR)
$(call append-test-harness-props,$(ADDITIONAL_TEST_HARNESS_PROPERTIES),$(TEST_HARNESS_PROP_TARGET))
- $(MKBOOTFS) -d $(TARGET_OUT) $(TEST_HARNESS_RAMDISK_ROOT_DIR) | $(MINIGZIP) > $(INSTALLED_TEST_HARNESS_RAMDISK_TARGET)
+ $(MKBOOTFS) -d $(TARGET_OUT) $(TEST_HARNESS_RAMDISK_ROOT_DIR) | $(COMPRESSION_COMMAND) > $(INSTALLED_TEST_HARNESS_RAMDISK_TARGET)
endif # BUILDING_RAMDISK_IMAGE
@@ -3301,6 +3342,41 @@
endef
# -----------------------------------------------------------------
+# custom images
+INSTALLED_CUSTOMIMAGES_TARGET :=
+
+ifneq ($(strip $(BOARD_CUSTOMIMAGES_PARTITION_LIST)),)
+INTERNAL_AVB_CUSTOMIMAGES_SIGNING_ARGS :=
+
+# Sign custom image.
+# $(1): the prebuilt custom image.
+# $(2): the mount point of the prebuilt custom image.
+# $(3): the signed custom image target.
+define sign_custom_image
+$(3): $(1) $(INTERNAL_USERIMAGES_DEPS)
+ @echo Target custom image: $(3)
+ mkdir -p $(dir $(3))
+ cp $(1) $(3)
+ifeq ($(BOARD_AVB_ENABLE),true)
+ PATH=$(INTERNAL_USERIMAGES_BINARY_PATHS):$$$$PATH \
+ $(AVBTOOL) add_hashtree_footer \
+ --image $(3) \
+ --key $(BOARD_AVB_$(call to-upper,$(2))_KEY_PATH) \
+ --algorithm $(BOARD_AVB_$(call to-upper,$(2))_ALGORITHM) \
+ --partition_size $(BOARD_AVB_$(call to-upper,$(2))_PARTITION_SIZE) \
+ --partition_name $(2) \
+ $(INTERNAL_AVB_CUSTOMIMAGES_SIGNING_ARGS) \
+ $(BOARD_AVB_$(call to-upper,$(2))_ADD_HASHTREE_FOOTER_ARGS)
+endif
+INSTALLED_CUSTOMIMAGES_TARGET += $(3)
+endef
+
+$(foreach partition,$(BOARD_CUSTOMIMAGES_PARTITION_LIST), \
+ $(foreach image,$(BOARD_AVB_$(call to-upper,$(partition))_IMAGE_LIST), \
+ $(eval $(call sign_custom_image,$(image),$(partition),$(PRODUCT_OUT)/$(notdir $(image))))))
+endif
+
+# -----------------------------------------------------------------
# vbmeta image
ifeq ($(BOARD_AVB_ENABLE),true)
@@ -3350,10 +3426,10 @@
# When building a standalone recovery image for non-A/B devices, recovery image must be self-signed
# to be verified independently, and cannot be chained into vbmeta.img. See the link below for
# details.
-ifneq ($(AB_OTA_UPDATER),true)
+ifeq ($(TARGET_OTA_ALLOW_NON_AB),true)
ifneq ($(INSTALLED_RECOVERYIMAGE_TARGET),)
$(if $(BOARD_AVB_RECOVERY_KEY_PATH),,\
- $(error BOARD_AVB_RECOVERY_KEY_PATH must be defined for non-A/B devices. \
+ $(error BOARD_AVB_RECOVERY_KEY_PATH must be defined for if non-A/B is supported. \
See https://android.googlesource.com/platform/external/avb/+/master/README.md#booting-into-recovery))
endif
endif
@@ -3444,7 +3520,7 @@
# The recovery partition in non-A/B devices should be verified separately. Skip adding the chain
# partition descriptor for recovery partition into vbmeta.img.
-$(if $(or $(filter true,$(AB_OTA_UPDATER)),$(filter-out recovery,$(part))),\
+$(if $(or $(filter-out true,$(TARGET_OTA_ALLOW_NON_AB)),$(filter-out recovery,$(part))),\
$(eval INTERNAL_AVB_MAKE_VBMETA_IMAGE_ARGS += \
--chain_partition $(part):$($(_rollback_index_location)):$(AVB_CHAIN_KEY_DIR)/$(part).avbpubkey))
@@ -3471,13 +3547,21 @@
--include_descriptors_from_image $(call images-for-partitions,$(1)))))
endef
+# Checks and sets build variables for a custom chained partition to include it into vbmeta.img.
+# $(1): the custom partition to enable AVB chain.
+define check-and-set-custom-avb-chain-args
+$(eval part := $(1))
+$(eval PART=$(call to-upper,$(part)))
+$(eval _rollback_index_location := BOARD_AVB_$(PART)_ROLLBACK_INDEX_LOCATION)
+$(if $($(_rollback_index_location)),,$(error $(_rollback_index_location) is not defined))
+
+INTERNAL_AVB_MAKE_VBMETA_IMAGE_ARGS += \
+ --chain_partition $(part):$($(_rollback_index_location)):$(AVB_CHAIN_KEY_DIR)/$(part).avbpubkey
+endef
+
ifdef INSTALLED_BOOTIMAGE_TARGET
-# multiple hashes for an image are not yet supported, fortunately this
-# only arises for GKI where the boot descriptor can be left out
-ifeq ($(strip $(BOARD_KERNEL_BINARIES)),)
$(eval $(call check-and-set-avb-args,boot))
endif
-endif
ifdef INSTALLED_VENDOR_BOOTIMAGE_TARGET
$(eval $(call check-and-set-avb-args,vendor_boot))
@@ -3518,6 +3602,11 @@
$(eval $(call check-and-set-avb-args,vbmeta_vendor))
endif
+ifneq ($(strip $(BOARD_CUSTOMIMAGES_PARTITION_LIST)),)
+$(foreach partition,$(BOARD_CUSTOMIMAGES_PARTITION_LIST), \
+ $(eval $(call check-and-set-custom-avb-chain-args,$(partition))))
+endif
+
# Add kernel cmdline descriptor for kernel to mount system.img as root with
# dm-verity. This works when system.img is either chained or not-chained:
# - chained: The --setup_as_rootfs_from_kernel option will add dm-verity kernel
@@ -3588,6 +3677,10 @@
$(if $(BOARD_AVB_VBMETA_VENDOR_KEY_PATH),\
$(hide) $(AVBTOOL) extract_public_key --key $(BOARD_AVB_VBMETA_VENDOR_KEY_PATH) \
--output $(1)/vbmeta_vendor.avbpubkey)
+ $(if $(BOARD_CUSTOMIMAGES_PARTITION_LIST),\
+ $(hide) $(foreach partition,$(BOARD_CUSTOMIMAGES_PARTITION_LIST), \
+ $(AVBTOOL) extract_public_key --key $(BOARD_AVB_$(call to-upper,$(partition))_KEY_PATH) \
+ --output $(1)/$(partition).avbpubkey;))
endef
# Builds a chained VBMeta image. This VBMeta image will contain the descriptors for the partitions
@@ -3655,6 +3748,7 @@
$(INSTALLED_SYSTEM_EXTIMAGE_TARGET) \
$(INSTALLED_ODMIMAGE_TARGET) \
$(INSTALLED_DTBOIMAGE_TARGET) \
+ $(INSTALLED_CUSTOMIMAGES_TARGET) \
$(INSTALLED_RECOVERYIMAGE_TARGET) \
$(INSTALLED_VBMETA_SYSTEMIMAGE_TARGET) \
$(INSTALLED_VBMETA_VENDORIMAGE_TARGET) \
@@ -3976,6 +4070,7 @@
INTERNAL_OTATOOLS_MODULES := \
aapt2 \
add_img_to_target_files \
+ apksigner \
append2simg \
avbtool \
blk_alloc_to_base_fs \
@@ -4119,6 +4214,11 @@
endif
.KATI_READONLY := tool_extensions
+# $1: boot image file name
+define misc_boot_size
+$(subst .img,_size,$(1))=$(BOARD_KERNEL$(call to-upper,$(subst boot,,$(subst .img,,$(1))))_BOOTIMAGE_PARTITION_SIZE)
+endef
+
$(INSTALLED_MISC_INFO_TARGET):
rm -f $@
$(call pretty,"Target misc_info.txt: $@")
@@ -4127,8 +4227,9 @@
ifdef BOARD_FLASH_BLOCK_SIZE
$(hide) echo "blocksize=$(BOARD_FLASH_BLOCK_SIZE)" >> $@
endif
-ifdef BOARD_BOOTIMAGE_PARTITION_SIZE
- $(hide) echo "boot_size=$(BOARD_BOOTIMAGE_PARTITION_SIZE)" >> $@
+ifneq ($(strip $(BOARD_BOOTIMAGE_PARTITION_SIZE))$(strip $(BOARD_KERNEL_BINARIES)),)
+ $(foreach b,$(INSTALLED_BOOTIMAGE_TARGET),\
+ echo "$(call misc_boot_size,$(notdir $(b)))" >> $@;)
endif
ifeq ($(INSTALLED_BOOTIMAGE_TARGET),)
$(hide) echo "no_boot=true" >> $@
@@ -4207,6 +4308,16 @@
$(hide) echo "avb_recovery_algorithm=$(BOARD_AVB_RECOVERY_ALGORITHM)" >> $@
$(hide) echo "avb_recovery_rollback_index_location=$(BOARD_AVB_RECOVERY_ROLLBACK_INDEX_LOCATION)" >> $@
endif # BOARD_AVB_RECOVERY_KEY_PATH
+ifneq (,$(strip $(BOARD_CUSTOMIMAGES_PARTITION_LIST)))
+ $(hide) echo "avb_custom_images_partition_list=$(BOARD_CUSTOMIMAGES_PARTITION_LIST)" >> $@
+ $(hide) $(foreach partition,$(BOARD_CUSTOMIMAGES_PARTITION_LIST), \
+ echo "avb_$(partition)_key_path=$(BOARD_AVB_$(call to-upper,$(partition))_KEY_PATH)" >> $@; \
+ echo "avb_$(partition)_algorithm=$(BOARD_AVB_$(call to-upper,$(partition))_ALGORITHM)" >> $@; \
+ echo "avb_$(partition)_add_hashtree_footer_args=$(BOARD_AVB_$(call to-upper,$(partition))_ADD_HASHTREE_FOOTER_ARGS)" >> $@; \
+ echo "avb_$(partition)_rollback_index_location=$(BOARD_AVB_$(call to-upper,$(partition))_ROLLBACK_INDEX_LOCATION)" >> $@; \
+ echo "avb_$(partition)_partition_size=$(BOARD_AVB_$(call to-upper,$(partition))_PARTITION_SIZE)" >> $@; \
+ echo "avb_$(partition)_image_list=$(foreach image,$(BOARD_AVB_$(call to-upper,$(partition))_IMAGE_LIST),$(notdir $(image)))" >> $@;)
+endif # BOARD_CUSTOMIMAGES_PARTITION_LIST
ifneq (,$(strip $(BOARD_AVB_VBMETA_SYSTEM)))
$(hide) echo "avb_vbmeta_system=$(BOARD_AVB_VBMETA_SYSTEM)" >> $@
$(hide) echo "avb_vbmeta_system_args=$(BOARD_AVB_MAKE_VBMETA_SYSTEM_IMAGE_ARGS)" >> $@
@@ -4236,6 +4347,9 @@
$(hide) echo "build_type=$(TARGET_BUILD_VARIANT)" >> $@
$(hide) echo "ab_update=true" >> $@
endif
+ifeq ($(TARGET_OTA_ALLOW_NON_AB),true)
+ $(hide) echo "allow_non_ab=true" >> $@
+endif
ifdef BOARD_PREBUILT_DTBOIMAGE
$(hide) echo "has_dtbo=true" >> $@
ifeq ($(BOARD_AVB_ENABLE),true)
@@ -4313,10 +4427,13 @@
ifeq ($(AB_OTA_UPDATER),true)
updater_dep := system/update_engine/update_engine.conf
-else
-# Build OTA tools if not using the AB Updater.
+endif
+
+# Build OTA tools if non-A/B is allowed
+ifeq ($(TARGET_OTA_ALLOW_NON_AB),true)
updater_dep := $(built_ota_tools)
endif
+
$(BUILT_TARGET_FILES_PACKAGE): $(updater_dep)
# If we are using recovery as boot, output recovery files to BOOT/.
@@ -4434,6 +4551,7 @@
$(INSTALLED_VBMETAIMAGE_TARGET) \
$(INSTALLED_ODMIMAGE_TARGET) \
$(INSTALLED_DTBOIMAGE_TARGET) \
+ $(INSTALLED_CUSTOMIMAGES_TARGET) \
$(INTERNAL_SYSTEMOTHERIMAGE_FILES) \
$(INSTALLED_ANDROID_INFO_TXT_TARGET) \
$(INSTALLED_KERNEL_TARGET) \
@@ -4592,7 +4710,7 @@
@# Extra contents of the OTA package
$(hide) mkdir -p $(zip_root)/OTA
$(hide) cp $(INSTALLED_ANDROID_INFO_TXT_TARGET) $(zip_root)/OTA/
-ifneq ($(AB_OTA_UPDATER),true)
+ifeq ($(TARGET_OTA_ALLOW_NON_AB),true)
ifneq ($(built_ota_tools),)
$(hide) mkdir -p $(zip_root)/OTA/bin
$(hide) cp $(PRIVATE_OTA_TOOLS) $(zip_root)/OTA/bin/
@@ -4629,7 +4747,7 @@
$(hide) cp $(PRODUCT_ODM_BASE_FS_PATH) \
$(zip_root)/META/$(notdir $(PRODUCT_ODM_BASE_FS_PATH))
endif
-ifneq ($(AB_OTA_UPDATER),true)
+ifeq ($(TARGET_OTA_ALLOW_NON_AB),true)
ifneq ($(INSTALLED_RECOVERYIMAGE_TARGET),)
$(hide) PATH=$(INTERNAL_USERIMAGES_BINARY_PATHS):$$PATH MKBOOTIMG=$(MKBOOTIMG) \
$(MAKE_RECOVERY_PATCH) $(zip_root) $(zip_root)
@@ -4678,6 +4796,11 @@
$(hide) mkdir -p $(zip_root)/PREBUILT_IMAGES
$(hide) cp $(INSTALLED_DTBOIMAGE_TARGET) $(zip_root)/PREBUILT_IMAGES/
endif # BOARD_PREBUILT_DTBOIMAGE
+ifneq ($(strip $(BOARD_CUSTOMIMAGES_PARTITION_LIST)),)
+ $(hide) mkdir -p $(zip_root)/PREBUILT_IMAGES
+ $(hide) $(foreach partition,$(BOARD_CUSTOMIMAGES_PARTITION_LIST), \
+ $(foreach image,$(BOARD_AVB_$(call to-upper,$(partition))_IMAGE_LIST),cp $(image) $(zip_root)/PREBUILT_IMAGES/;))
+endif # BOARD_CUSTOMIMAGES_PARTITION_LIST
@# The radio images in BOARD_PACK_RADIOIMAGES will be additionally copied from RADIO/ into
@# IMAGES/, which then will be added into <product>-img.zip. Such images must be listed in
@# INSTALLED_RADIOIMAGE_TARGET.
diff --git a/core/board_config.mk b/core/board_config.mk
index a329cb1..86162b6 100644
--- a/core/board_config.mk
+++ b/core/board_config.mk
@@ -549,13 +549,31 @@
.KATI_READONLY := BUILDING_ODM_IMAGE
###########################################
-# Ensure that only TARGET_RECOVERY_UPDATER_LIBS *or* AB_OTA_UPDATER is set.
+# Ensure consistency among TARGET_RECOVERY_UPDATER_LIBS, AB_OTA_UPDATER, and PRODUCT_OTA_FORCE_NON_AB_PACKAGE.
TARGET_RECOVERY_UPDATER_LIBS ?=
AB_OTA_UPDATER ?=
.KATI_READONLY := TARGET_RECOVERY_UPDATER_LIBS AB_OTA_UPDATER
-ifeq ($(AB_OTA_UPDATER),true)
+
+# Ensure that if PRODUCT_OTA_FORCE_NON_AB_PACKAGE == true, then AB_OTA_UPDATER must be true
+ifeq ($(PRODUCT_OTA_FORCE_NON_AB_PACKAGE),true)
+ ifneq ($(AB_OTA_UPDATER),true)
+ $(error AB_OTA_UPDATER must be set to true when PRODUCT_OTA_FORCE_NON_AB_PACKAGE is true)
+ endif
+endif
+
+# In some configurations, A/B and non-A/B may coexist. Check TARGET_OTA_ALLOW_NON_AB
+# to see if non-A/B is supported.
+TARGET_OTA_ALLOW_NON_AB := false
+ifneq ($(AB_OTA_UPDATER),true)
+ TARGET_OTA_ALLOW_NON_AB := true
+else ifeq ($(PRODUCT_OTA_FORCE_NON_AB_PACKAGE),true)
+ TARGET_OTA_ALLOW_NON_AB := true
+endif
+.KATI_READONLY := TARGET_OTA_ALLOW_NON_AB
+
+ifneq ($(TARGET_OTA_ALLOW_NON_AB),true)
ifneq ($(strip $(TARGET_RECOVERY_UPDATER_LIBS)),)
- $(error Do not use TARGET_RECOVERY_UPDATER_LIBS when using AB_OTA_UPDATER)
+ $(error Do not use TARGET_RECOVERY_UPDATER_LIBS when using TARGET_OTA_ALLOW_NON_AB)
endif
endif
diff --git a/core/clear_vars.mk b/core/clear_vars.mk
index 0c613fa..c01912c 100644
--- a/core/clear_vars.mk
+++ b/core/clear_vars.mk
@@ -21,6 +21,7 @@
LOCAL_APIDIFF_NEWAPI:=
LOCAL_APIDIFF_OLDAPI:=
LOCAL_APK_LIBRARIES:=
+LOCAL_APK_SET_MASTER_FILE:=
LOCAL_ARM_MODE:=
LOCAL_ASFLAGS:=
LOCAL_ASSET_DIR:=
diff --git a/core/config.mk b/core/config.mk
index 699202f..0e0ff8f 100644
--- a/core/config.mk
+++ b/core/config.mk
@@ -599,6 +599,7 @@
VTSC := $(HOST_OUT_EXECUTABLES)/vtsc$(HOST_EXECUTABLE_SUFFIX)
MKBOOTFS := $(HOST_OUT_EXECUTABLES)/mkbootfs$(HOST_EXECUTABLE_SUFFIX)
MINIGZIP := $(HOST_OUT_EXECUTABLES)/minigzip$(HOST_EXECUTABLE_SUFFIX)
+LZ4 := $(HOST_OUT_EXECUTABLES)/lz4$(HOST_EXECUTABLE_SUFFIX)
ifeq (,$(strip $(BOARD_CUSTOM_MKBOOTIMG)))
MKBOOTIMG := $(HOST_OUT_EXECUTABLES)/mkbootimg$(HOST_EXECUTABLE_SUFFIX)
else
diff --git a/core/install_jni_libs_internal.mk b/core/install_jni_libs_internal.mk
index b482eb5..48c93de 100644
--- a/core/install_jni_libs_internal.mk
+++ b/core/install_jni_libs_internal.mk
@@ -124,17 +124,15 @@
my_allowed_types := $(my_allowed_ndk_types) native:platform native:product native:vendor native:vndk native:vndk_private native:platform_vndk
endif
- ifneq (,$(LOCAL_SDK_VERSION))
- ifeq ($(SOONG_ANDROID_MK),$(LOCAL_MODULE_MAKEFILE))
- # SOONG_SDK_VARIANT_MODULES isn't complete yet while parsing Soong modules, and Soong has
- # already ensured that apps link against the correct SDK variants, rewrite all JNI libraries
- # to the SDK variant.
- my_link_deps := $(addprefix SHARED_LIBRARIES:,$(addsuffix .sdk,$(LOCAL_JNI_SHARED_LIBRARIES)))
- else
- my_link_deps := $(addprefix SHARED_LIBRARIES:,$(call use_soong_sdk_libraries,$(LOCAL_JNI_SHARED_LIBRARIES)))
- endif
+ ifeq ($(SOONG_ANDROID_MK),$(LOCAL_MODULE_MAKEFILE))
+ # SOONG_SDK_VARIANT_MODULES isn't complete yet while parsing Soong modules, and Soong has
+ # already ensured that apps link against the correct SDK variants, don't check them.
else
- my_link_deps := $(addprefix SHARED_LIBRARIES:,$(LOCAL_JNI_SHARED_LIBRARIES))
+ ifneq (,$(LOCAL_SDK_VERSION))
+ my_link_deps := $(addprefix SHARED_LIBRARIES:,$(call use_soong_sdk_libraries,$(LOCAL_JNI_SHARED_LIBRARIES)))
+ else
+ my_link_deps := $(addprefix SHARED_LIBRARIES:,$(LOCAL_JNI_SHARED_LIBRARIES))
+ endif
endif
my_common :=
diff --git a/core/instrumentation_test_config_template.xml b/core/instrumentation_test_config_template.xml
index 18ea676..6ca964e 100644
--- a/core/instrumentation_test_config_template.xml
+++ b/core/instrumentation_test_config_template.xml
@@ -17,6 +17,7 @@
<configuration description="Runs {LABEL}.">
<option name="test-suite-tag" value="apct" />
<option name="test-suite-tag" value="apct-instrumentation" />
+ {EXTRA_CONFIGS}
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
<option name="test-file-name" value="{MODULE}.apk" />
diff --git a/core/product.mk b/core/product.mk
index ea9be72..0aa07ef 100644
--- a/core/product.mk
+++ b/core/product.mk
@@ -393,6 +393,13 @@
# If set, device retrofits virtual A/B.
_product_single_value_vars += PRODUCT_VIRTUAL_AB_OTA_RETROFIT
+# If set, forcefully generate a non-A/B update package.
+# Note: A device configuration should inherit from virtual_ab_ota_plus_non_ab.mk
+# instead of setting this variable directly.
+# Note: Use TARGET_OTA_ALLOW_NON_AB in the build system because
+# TARGET_OTA_ALLOW_NON_AB takes the value of AB_OTA_UPDATER into account.
+_product_single_value_vars += PRODUCT_OTA_FORCE_NON_AB_PACKAGE
+
# If set, Java module in product partition cannot use hidden APIs.
_product_single_value_vars += PRODUCT_ENFORCE_PRODUCT_PARTITION_INTERFACE
diff --git a/core/soong_android_app_set.mk b/core/soong_android_app_set.mk
new file mode 100644
index 0000000..4c27e53
--- /dev/null
+++ b/core/soong_android_app_set.mk
@@ -0,0 +1,34 @@
+# App prebuilt coming from Soong.
+# Extra inputs:
+# LOCAL_APK_SET_MASTER_FILE
+
+ifneq ($(LOCAL_MODULE_MAKEFILE),$(SOONG_ANDROID_MK))
+ $(call pretty-error,soong_apk_set.mk may only be used from Soong)
+endif
+
+LOCAL_BUILT_MODULE_STEM := $(LOCAL_APK_SET_MASTER_FILE)
+LOCAL_INSTALLED_MODULE_STEM := $(LOCAL_APK_SET_MASTER_FILE)
+
+#######################################
+include $(BUILD_SYSTEM)/base_rules.mk
+#######################################
+
+## Extract master APK from APK set into given directory
+# $(1) APK set
+# $(2) master APK entry (e.g., splits/base-master.apk
+
+define extract-master-from-apk-set
+$(LOCAL_BUILT_MODULE): $(1)
+ @echo "Extracting $$@"
+ unzip -pq $$< $(2) >$$@
+endef
+
+$(eval $(call extract-master-from-apk-set,$(LOCAL_PREBUILT_MODULE_FILE),$(LOCAL_APK_SET_MASTER_FILE)))
+# unzip returns 11 it there was nothing to extract, which is expected,
+# $(LOCAL_APK_SET_MASTER_FILE) has is already there.
+LOCAL_POST_INSTALL_CMD := unzip -qo -j -d $(dir $(LOCAL_INSTALLED_MODULE)) \
+ $(LOCAL_PREBUILT_MODULE_FILE) -x $(LOCAL_APK_SET_MASTER_FILE) || [[ $$? -eq 11 ]]
+$(LOCAL_INSTALLED_MODULE): PRIVATE_POST_INSTALL_CMD := $(LOCAL_POST_INSTALL_CMD)
+PACKAGES.$(LOCAL_MODULE).OVERRIDES := $(strip $(LOCAL_OVERRIDES_PACKAGES))
+
+SOONG_ALREADY_CONV := $(SOONG_ALREADY_CONV) $(LOCAL_MODULE)
diff --git a/core/tasks/vts-core-tests.mk b/core/tasks/vts-core-tests.mk
index 4e83de5..a3247da 100644
--- a/core/tasks/vts-core-tests.mk
+++ b/core/tasks/vts-core-tests.mk
@@ -12,15 +12,13 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+-include external/linux-kselftest/android/kselftest_test_list.mk
+-include external/ltp/android/ltp_package_list.mk
+
test_suite_name := vts
test_suite_tradefed := vts-tradefed
test_suite_readme := test/vts/tools/vts-core-tradefed/README
-# TODO(b/149249068): Clean up after all VTS tests are converted.
-vts_test_artifact_paths :=
-# Some repo may not include vts project.
--include test/vts/tools/build/tasks/framework/vts_for_core_suite.mk
-
# Copy kernel test modules to testcases directories
kernel_test_host_out := $(HOST_OUT_TESTCASES)/vts_kernel_tests
kernel_test_vts_out := $(HOST_OUT)/$(test_suite_name)/android-$(test_suite_name)/testcases/vts_kernel_tests
@@ -44,7 +42,6 @@
$(compatibility_zip): $(copy_kernel_tests)
.PHONY: vts
-$(compatibility_zip): $(vts_test_artifact_paths)
vts: $(compatibility_zip)
$(call dist-for-goals, vts, $(compatibility_zip))
diff --git a/core/version_defaults.mk b/core/version_defaults.mk
index 645c648..1b704a5 100644
--- a/core/version_defaults.mk
+++ b/core/version_defaults.mk
@@ -240,7 +240,7 @@
# It must be of the form "YYYY-MM-DD" on production devices.
# It must match one of the Android Security Patch Level strings of the Public Security Bulletins.
# If there is no $PLATFORM_SECURITY_PATCH set, keep it empty.
- PLATFORM_SECURITY_PATCH := 2020-06-05
+ PLATFORM_SECURITY_PATCH := 2020-07-05
endif
.KATI_READONLY := PLATFORM_SECURITY_PATCH
diff --git a/target/board/BoardConfigEmuCommon.mk b/target/board/BoardConfigEmuCommon.mk
index a2e5518..e9fb096 100644
--- a/target/board/BoardConfigEmuCommon.mk
+++ b/target/board/BoardConfigEmuCommon.mk
@@ -33,8 +33,6 @@
# emulator needs super.img
BOARD_BUILD_SUPER_IMAGE_BY_DEFAULT := true
- BOARD_EXT4_SHARE_DUP_BLOCKS := true
-
# 3G + header
BOARD_SUPER_PARTITION_SIZE := 3229614080
BOARD_SUPER_PARTITION_GROUPS := emulator_dynamic_partitions
diff --git a/target/board/BoardConfigGsiCommon.mk b/target/board/BoardConfigGsiCommon.mk
index c89e203..49f6edc 100644
--- a/target/board/BoardConfigGsiCommon.mk
+++ b/target/board/BoardConfigGsiCommon.mk
@@ -40,6 +40,12 @@
BOARD_AVB_SYSTEM_ROLLBACK_INDEX := $(PLATFORM_SECURITY_PATCH_TIMESTAMP)
BOARD_AVB_SYSTEM_ROLLBACK_INDEX_LOCATION := 1
+# Enable chain partition for boot, mainly for GKI images.
+BOARD_AVB_BOOT_KEY_PATH := external/avb/test/data/testkey_rsa2048.pem
+BOARD_AVB_BOOT_ALGORITHM := SHA256_RSA2048
+BOARD_AVB_BOOT_ROLLBACK_INDEX := $(PLATFORM_SECURITY_PATCH_TIMESTAMP)
+BOARD_AVB_BOOT_ROLLBACK_INDEX_LOCATION := 2
+
# GSI specific System Properties
ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT)))
TARGET_SYSTEM_EXT_PROP := build/make/target/board/gsi_system_ext.prop
diff --git a/target/board/BoardConfigMainlineCommon.mk b/target/board/BoardConfigMainlineCommon.mk
index c57968e..bf015e5 100644
--- a/target/board/BoardConfigMainlineCommon.mk
+++ b/target/board/BoardConfigMainlineCommon.mk
@@ -6,6 +6,8 @@
TARGET_NO_BOOTLOADER := true
TARGET_NO_RECOVERY := true
+BOARD_EXT4_SHARE_DUP_BLOCKS := true
+
TARGET_USERIMAGES_USE_EXT4 := true
# Mainline devices must have /system_ext, /vendor and /product partitions.
diff --git a/target/board/emulator_arm64/device.mk b/target/board/emulator_arm64/device.mk
index 6753c11..57675d0 100644
--- a/target/board/emulator_arm64/device.mk
+++ b/target/board/emulator_arm64/device.mk
@@ -14,6 +14,9 @@
# limitations under the License.
#
+PRODUCT_SOONG_NAMESPACES += device/generic/goldfish # for libwifi-hal-emu
+PRODUCT_SOONG_NAMESPACES += device/generic/goldfish-opengl # for goldfish deps.
+
# Cuttlefish has GKI kernel prebuilts, so use those for the GKI boot.img.
ifeq ($(TARGET_PREBUILT_KERNEL),)
LOCAL_KERNEL := device/google/cuttlefish_kernel/5.4-arm64/kernel
diff --git a/target/board/generic/device.mk b/target/board/generic/device.mk
index 0a32415..cfb15f0 100644
--- a/target/board/generic/device.mk
+++ b/target/board/generic/device.mk
@@ -14,6 +14,9 @@
# limitations under the License.
#
+PRODUCT_SOONG_NAMESPACES += device/generic/goldfish # for libwifi-hal-emu
+PRODUCT_SOONG_NAMESPACES += device/generic/goldfish-opengl # for goldfish deps.
+
# NFC:
# Provide default libnfc-nci.conf file for devices that does not have one in
# vendor/etc because aosp system image (of aosp_$arch products) is going to
diff --git a/target/board/generic_arm64/BoardConfig.mk b/target/board/generic_arm64/BoardConfig.mk
index d793c38..2963ee4 100644
--- a/target/board/generic_arm64/BoardConfig.mk
+++ b/target/board/generic_arm64/BoardConfig.mk
@@ -54,13 +54,13 @@
include build/make/target/board/BoardConfigGsiCommon.mk
-BOARD_EXT4_SHARE_DUP_BLOCKS := true
-
TARGET_NO_KERNEL := false
TARGET_NO_VENDOR_BOOT := true
BOARD_USES_RECOVERY_AS_BOOT := true
-BOARD_BOOTIMAGE_PARTITION_SIZE := 0x04000000
+BOARD_KERNEL-5.4_BOOTIMAGE_PARTITION_SIZE := 67108864
+BOARD_KERNEL-5.4-GZ_BOOTIMAGE_PARTITION_SIZE := 47185920
+BOARD_KERNEL-5.4-LZ4_BOOTIMAGE_PARTITION_SIZE := 53477376
BOARD_USERDATAIMAGE_PARTITION_SIZE := 576716800
BOARD_BOOT_HEADER_VERSION := 3
diff --git a/target/board/generic_x86/device.mk b/target/board/generic_x86/device.mk
index bbab2b4..2b10a3d 100644
--- a/target/board/generic_x86/device.mk
+++ b/target/board/generic_x86/device.mk
@@ -14,6 +14,9 @@
# limitations under the License.
#
+PRODUCT_SOONG_NAMESPACES += device/generic/goldfish # for libwifi-hal-emu
+PRODUCT_SOONG_NAMESPACES += device/generic/goldfish-opengl # for goldfish deps.
+
ifdef NET_ETH0_STARTONBOOT
PRODUCT_PROPERTY_OVERRIDES += net.eth0.startonboot=1
endif
diff --git a/target/board/generic_x86_64/device.mk b/target/board/generic_x86_64/device.mk
index bbab2b4..2b10a3d 100755
--- a/target/board/generic_x86_64/device.mk
+++ b/target/board/generic_x86_64/device.mk
@@ -14,6 +14,9 @@
# limitations under the License.
#
+PRODUCT_SOONG_NAMESPACES += device/generic/goldfish # for libwifi-hal-emu
+PRODUCT_SOONG_NAMESPACES += device/generic/goldfish-opengl # for goldfish deps.
+
ifdef NET_ETH0_STARTONBOOT
PRODUCT_PROPERTY_OVERRIDES += net.eth0.startonboot=1
endif
diff --git a/target/board/generic_x86_64_arm64/device.mk b/target/board/generic_x86_64_arm64/device.mk
index fa1eb67..76242c9 100755
--- a/target/board/generic_x86_64_arm64/device.mk
+++ b/target/board/generic_x86_64_arm64/device.mk
@@ -13,3 +13,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
+
+PRODUCT_SOONG_NAMESPACES += device/generic/goldfish # for libwifi-hal-emu
+PRODUCT_SOONG_NAMESPACES += device/generic/goldfish-opengl # for goldfish deps.
diff --git a/target/board/generic_x86_arm/device.mk b/target/board/generic_x86_arm/device.mk
index fa1eb67..76242c9 100644
--- a/target/board/generic_x86_arm/device.mk
+++ b/target/board/generic_x86_arm/device.mk
@@ -13,3 +13,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
+
+PRODUCT_SOONG_NAMESPACES += device/generic/goldfish # for libwifi-hal-emu
+PRODUCT_SOONG_NAMESPACES += device/generic/goldfish-opengl # for goldfish deps.
diff --git a/target/product/base_system.mk b/target/product/base_system.mk
index c346c13..c074807 100644
--- a/target/product/base_system.mk
+++ b/target/product/base_system.mk
@@ -211,7 +211,7 @@
mtpd \
ndc \
netd \
- NetworkStackNext \
+ NetworkStack \
org.apache.http.legacy \
otacerts \
PackageInstaller \
diff --git a/target/product/emulated_storage.mk b/target/product/emulated_storage.mk
index d7cc9ce..ea5d9ad 100644
--- a/target/product/emulated_storage.mk
+++ b/target/product/emulated_storage.mk
@@ -19,3 +19,5 @@
PRODUCT_FS_CASEFOLD := 1
PRODUCT_PROPERTY_OVERRIDES += external_storage.casefold.enabled=1
+
+PRODUCT_PROPERTY_OVERRIDES += external_storage.sdcardfs.enabled=0
diff --git a/target/product/generic.mk b/target/product/generic.mk
index 68130e3..a1acaab 100644
--- a/target/product/generic.mk
+++ b/target/product/generic.mk
@@ -14,6 +14,9 @@
# limitations under the License.
#
+PRODUCT_SOONG_NAMESPACES += device/generic/goldfish # for libwifi-hal-emu
+PRODUCT_SOONG_NAMESPACES += device/generic/goldfish-opengl # for goldfish deps.
+
# This is a generic phone product that isn't specialized for a specific device.
# It includes the base Android platform.
diff --git a/target/product/gsi/30.txt b/target/product/gsi/30.txt
index cc2d36d..0589517 100644
--- a/target/product/gsi/30.txt
+++ b/target/product/gsi/30.txt
@@ -150,11 +150,11 @@
VNDK-core: android.hardware.health@1.0.so
VNDK-core: android.hardware.health@2.0.so
VNDK-core: android.hardware.health@2.1.so
-VNDK-core: android.hardware.identity-V1-ndk_platform.so
+VNDK-core: android.hardware.identity-V2-ndk_platform.so
VNDK-core: android.hardware.input.classifier@1.0.so
VNDK-core: android.hardware.input.common@1.0.so
VNDK-core: android.hardware.ir@1.0.so
-VNDK-core: android.hardware.keymaster-V1-ndk_platform.so
+VNDK-core: android.hardware.keymaster-V2-ndk_platform.so
VNDK-core: android.hardware.keymaster@3.0.so
VNDK-core: android.hardware.keymaster@4.0.so
VNDK-core: android.hardware.keymaster@4.1.so
diff --git a/target/product/gsi/current.txt b/target/product/gsi/current.txt
index cc2d36d..0589517 100644
--- a/target/product/gsi/current.txt
+++ b/target/product/gsi/current.txt
@@ -150,11 +150,11 @@
VNDK-core: android.hardware.health@1.0.so
VNDK-core: android.hardware.health@2.0.so
VNDK-core: android.hardware.health@2.1.so
-VNDK-core: android.hardware.identity-V1-ndk_platform.so
+VNDK-core: android.hardware.identity-V2-ndk_platform.so
VNDK-core: android.hardware.input.classifier@1.0.so
VNDK-core: android.hardware.input.common@1.0.so
VNDK-core: android.hardware.ir@1.0.so
-VNDK-core: android.hardware.keymaster-V1-ndk_platform.so
+VNDK-core: android.hardware.keymaster-V2-ndk_platform.so
VNDK-core: android.hardware.keymaster@3.0.so
VNDK-core: android.hardware.keymaster@4.0.so
VNDK-core: android.hardware.keymaster@4.1.so
diff --git a/target/product/iorap_large_memory_config.mk b/target/product/iorap_large_memory_config.mk
new file mode 100644
index 0000000..0b74a97
--- /dev/null
+++ b/target/product/iorap_large_memory_config.mk
@@ -0,0 +1,18 @@
+# Copyright (C) 2020 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# Enable Camera pinner by default
+PRODUCT_SYSTEM_DEFAULT_PROPERTIES += \
+ pinner.pin_camera=true
diff --git a/target/product/telephony_system.mk b/target/product/telephony_system.mk
index 9c585b3..ef48719 100644
--- a/target/product/telephony_system.mk
+++ b/target/product/telephony_system.mk
@@ -22,5 +22,6 @@
CarrierDefaultApp \
CallLogBackup \
com.android.cellbroadcast \
+ CellBroadcastLegacyApp \
PRODUCT_COPY_FILES := \
diff --git a/target/product/virtual_ab_ota_plus_non_ab.mk b/target/product/virtual_ab_ota_plus_non_ab.mk
new file mode 100644
index 0000000..325d75e
--- /dev/null
+++ b/target/product/virtual_ab_ota_plus_non_ab.mk
@@ -0,0 +1,21 @@
+#
+# Copyright (C) 2020 The Android Open-Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+$(call inherit-product, $(SRC_TARGET_DIR)/product/virtual_ab_ota.mk)
+
+PRODUCT_OTA_FORCE_NON_AB_PACKAGE := true
+
+PRODUCT_PROPERTY_OVERRIDES += ro.virtual_ab.allow_non_ab=true
diff --git a/tools/auto_gen_test_config.py b/tools/auto_gen_test_config.py
index c7c5bdc..943f238 100755
--- a/tools/auto_gen_test_config.py
+++ b/tools/auto_gen_test_config.py
@@ -27,6 +27,7 @@
ATTRIBUTE_PACKAGE = 'package'
PLACEHOLDER_LABEL = '{LABEL}'
+PLACEHOLDER_EXTRA_CONFIGS = '{EXTRA_CONFIGS}'
PLACEHOLDER_MODULE = '{MODULE}'
PLACEHOLDER_PACKAGE = '{PACKAGE}'
PLACEHOLDER_RUNNER = '{RUNNER}'
@@ -41,16 +42,20 @@
Returns:
0 if no error, otherwise 1.
"""
- if len(argv) != 4:
+ if len(argv) != 4 and len(argv) != 6:
sys.stderr.write(
- 'Invalid arguements. The script requires 4 arguments for file paths: '
+ 'Invalid arguments. The script requires 4 arguments for file paths: '
'target_config android_manifest empty_config '
- 'instrumentation_test_config_template.\n')
+ 'instrumentation_test_config_template '
+ 'and 2 optional arguments for extra configs: '
+ '--extra-configs \'EXTRA_CONFIGS\'.\n')
return 1
+
target_config = argv[0]
android_manifest = argv[1]
empty_config = argv[2]
instrumentation_test_config_template = argv[3]
+ extra_configs = '\n'.join(argv[5].split('\\n')) if len(argv) == 6 else ''
manifest = parse(android_manifest)
instrumentation_elements = manifest.getElementsByTagName('instrumentation')
@@ -80,6 +85,7 @@
config = config.replace(PLACEHOLDER_MODULE, module)
config = config.replace(PLACEHOLDER_PACKAGE, package)
config = config.replace(PLACEHOLDER_TEST_TYPE, test_type)
+ config = config.replace(PLACEHOLDER_EXTRA_CONFIGS, extra_configs)
config = config.replace(PLACEHOLDER_RUNNER, runner)
with open(target_config, 'w') as config_file:
config_file.write(config)
diff --git a/tools/releasetools/add_img_to_target_files.py b/tools/releasetools/add_img_to_target_files.py
index 7db506c..490b44a 100755
--- a/tools/releasetools/add_img_to_target_files.py
+++ b/tools/releasetools/add_img_to_target_files.py
@@ -60,6 +60,7 @@
import common
import rangelib
import sparse_img
+import verity_utils
if sys.hexversion < 0x02070000:
print("Python 2.7 or newer is required.", file=sys.stderr)
@@ -312,6 +313,56 @@
img.Write()
return img.name
+def AddCustomImages(output_zip, partition_name):
+ """Adds and signs custom images in IMAGES/.
+
+ Args:
+ output_zip: The output zip file (needs to be already open), or None to
+ write images to OPTIONS.input_tmp/.
+
+ Uses the image under IMAGES/ if it already exists. Otherwise looks for the
+ image under PREBUILT_IMAGES/, signs it as needed, and returns the image name.
+
+ Raises:
+ AssertionError: If image can't be found.
+ """
+
+ partition_size = OPTIONS.info_dict.get(
+ "avb_{}_partition_size".format(partition_name))
+ key_path = OPTIONS.info_dict.get("avb_{}_key_path".format(partition_name))
+ algorithm = OPTIONS.info_dict.get("avb_{}_algorithm".format(partition_name))
+ extra_args = OPTIONS.info_dict.get(
+ "avb_{}_add_hashtree_footer_args".format(partition_name))
+ partition_size = OPTIONS.info_dict.get(
+ "avb_{}_partition_size".format(partition_name))
+
+ builder = verity_utils.CreateCustomImageBuilder(
+ OPTIONS.info_dict, partition_name, partition_size,
+ key_path, algorithm, extra_args)
+
+ for img_name in OPTIONS.info_dict.get(
+ "avb_{}_image_list".format(partition_name)).split():
+ custom_image = OutputFile(output_zip, OPTIONS.input_tmp, "IMAGES", img_name)
+ if os.path.exists(custom_image.name):
+ continue
+
+ custom_image_prebuilt_path = os.path.join(
+ OPTIONS.input_tmp, "PREBUILT_IMAGES", img_name)
+ assert os.path.exists(custom_image_prebuilt_path), \
+ "Failed to find %s at %s" % (img_name, custom_image_prebuilt_path)
+
+ shutil.copy(custom_image_prebuilt_path, custom_image.name)
+
+ if builder is not None:
+ builder.Build(custom_image.name)
+
+ custom_image.Write()
+
+ default = os.path.join(OPTIONS.input_tmp, "IMAGES", partition_name + ".img")
+ assert os.path.exists(default), \
+ "There should be one %s.img" % (partition_name)
+ return default
+
def CreateImage(input_dir, info_dict, what, output_file, block_list=None):
logger.info("creating %s.img...", what)
@@ -411,8 +462,9 @@
Args:
output_zip: The output zip file, which needs to be already open.
partitions: A dict that's keyed by partition names with image paths as
- values. Only valid partition names are accepted, as listed in
- common.AVB_PARTITIONS.
+ values. Only valid partition names are accepted, as partitions listed
+ in common.AVB_PARTITIONS and custom partitions listed in
+ OPTIONS.info_dict.get("avb_custom_images_partition_list")
name: Name of the VBMeta partition, e.g. 'vbmeta', 'vbmeta_system'.
needed_partitions: Partitions whose descriptors should be included into the
generated VBMeta image.
@@ -548,17 +600,19 @@
care_map_list += care_map
# adds fingerprint field to the care_map
- build_props = OPTIONS.info_dict.get(partition + ".build.prop", {})
+ # TODO(xunchang) revisit the fingerprint calculation for care_map.
+ partition_props = OPTIONS.info_dict.get(partition + ".build.prop")
prop_name_list = ["ro.{}.build.fingerprint".format(partition),
"ro.{}.build.thumbprint".format(partition)]
- present_props = [x for x in prop_name_list if x in build_props]
+ present_props = [x for x in prop_name_list if
+ partition_props and partition_props.GetProp(x)]
if not present_props:
logger.warning("fingerprint is not present for partition %s", partition)
property_id, fingerprint = "unknown", "unknown"
else:
property_id = present_props[0]
- fingerprint = build_props[property_id]
+ fingerprint = partition_props.GetProp(property_id)
care_map_list += [property_id, fingerprint]
if not care_map_list:
@@ -829,11 +883,20 @@
banner("dtbo")
partitions['dtbo'] = AddDtbo(output_zip)
+ # Custom images.
+ custom_partitions = OPTIONS.info_dict.get(
+ "avb_custom_images_partition_list", "").strip().split()
+ for partition_name in custom_partitions:
+ partition_name = partition_name.strip()
+ banner("custom images for " + partition_name)
+ partitions[partition_name] = AddCustomImages(output_zip, partition_name)
+
if OPTIONS.info_dict.get("avb_enable") == "true":
# vbmeta_partitions includes the partitions that should be included into
# top-level vbmeta.img, which are the ones that are not included in any
# chained VBMeta image plus the chained VBMeta images themselves.
- vbmeta_partitions = common.AVB_PARTITIONS[:]
+ # Currently custom_partitions are all chained to VBMeta image.
+ vbmeta_partitions = common.AVB_PARTITIONS[:] + tuple(custom_partitions)
vbmeta_system = OPTIONS.info_dict.get("avb_vbmeta_system", "").strip()
if vbmeta_system:
diff --git a/tools/releasetools/apex_utils.py b/tools/releasetools/apex_utils.py
index ae9b793..1c61938 100644
--- a/tools/releasetools/apex_utils.py
+++ b/tools/releasetools/apex_utils.py
@@ -169,7 +169,7 @@
def SignApexPayload(avbtool, payload_file, payload_key_path, payload_key_name,
- algorithm, salt, no_hashtree, signing_args=None):
+ algorithm, salt, hash_algorithm, no_hashtree, signing_args=None):
"""Signs a given payload_file with the payload key."""
# Add the new footer. Old footer, if any, will be replaced by avbtool.
cmd = [avbtool, 'add_hashtree_footer',
@@ -178,7 +178,8 @@
'--key', payload_key_path,
'--prop', 'apex.key:{}'.format(payload_key_name),
'--image', payload_file,
- '--salt', salt]
+ '--salt', salt,
+ '--hash_algorithm', hash_algorithm]
if no_hashtree:
cmd.append('--no_hashtree')
if signing_args:
@@ -235,11 +236,11 @@
'Failed to get APEX payload info for {}:\n{}'.format(
payload_path, e))
- # Extract the Algorithm / Salt / Prop info / Tree size from payload (i.e. an
- # image signed with avbtool). For example,
+ # Extract the Algorithm / Hash Algorithm / Salt / Prop info / Tree size from
+ # payload (i.e. an image signed with avbtool). For example,
# Algorithm: SHA256_RSA4096
PAYLOAD_INFO_PATTERN = (
- r'^\s*(?P<key>Algorithm|Salt|Prop|Tree Size)\:\s*(?P<value>.*?)$')
+ r'^\s*(?P<key>Algorithm|Hash Algorithm|Salt|Prop|Tree Size)\:\s*(?P<value>.*?)$')
payload_info_matcher = re.compile(PAYLOAD_INFO_PATTERN)
payload_info = {}
@@ -273,7 +274,7 @@
payload_info[key] = value
# Sanity check.
- for key in ('Algorithm', 'Salt', 'apex.key'):
+ for key in ('Algorithm', 'Salt', 'apex.key', 'Hash Algorithm'):
if key not in payload_info:
raise ApexInfoError(
'Failed to find {} prop in {}'.format(key, payload_path))
@@ -326,6 +327,7 @@
payload_info['apex.key'],
payload_info['Algorithm'],
payload_info['Salt'],
+ payload_info['Hash Algorithm'],
no_hashtree,
signing_args)
diff --git a/tools/releasetools/blockimgdiff.py b/tools/releasetools/blockimgdiff.py
index 72f065d..8b6a690 100644
--- a/tools/releasetools/blockimgdiff.py
+++ b/tools/releasetools/blockimgdiff.py
@@ -1558,6 +1558,7 @@
split_large_apks = []
cache_size = common.OPTIONS.cache_size
split_threshold = 0.125
+ assert cache_size is not None
max_blocks_per_transfer = int(cache_size * split_threshold /
self.tgt.blocksize)
empty = RangeSet()
diff --git a/tools/releasetools/build_image.py b/tools/releasetools/build_image.py
index 54bb857..8cf0741 100755
--- a/tools/releasetools/build_image.py
+++ b/tools/releasetools/build_image.py
@@ -509,9 +509,9 @@
d = {}
if "build.prop" in glob_dict:
- bp = glob_dict["build.prop"]
- if "ro.build.date.utc" in bp:
- d["timestamp"] = bp["ro.build.date.utc"]
+ timestamp = glob_dict["build.prop"].GetProp("ro.build.date.utc")
+ if timestamp:
+ d["timestamp"] = timestamp
def copy_prop(src_p, dest_p):
"""Copy a property from the global dictionary.
diff --git a/tools/releasetools/check_target_files_vintf.py b/tools/releasetools/check_target_files_vintf.py
index b3d491f..95d09cc 100755
--- a/tools/releasetools/check_target_files_vintf.py
+++ b/tools/releasetools/check_target_files_vintf.py
@@ -80,8 +80,9 @@
'--property', 'ro.boot.product.vendor.sku=' + vendor_sku]
for odm_sku in odm_skus for vendor_sku in vendor_skus]
+
def GetArgsForShippingApiLevel(info_dict):
- shipping_api_level = info_dict['vendor.build.prop'].get(
+ shipping_api_level = info_dict['vendor.build.prop'].GetProp(
'ro.product.first_api_level')
if not shipping_api_level:
logger.warning('Cannot determine ro.product.first_api_level')
diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py
index 2bef6de..4a91179 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -422,6 +422,14 @@
def items(self):
return self.info_dict.items()
+ def _GetRawBuildProp(self, prop, partition):
+ prop_file = '{}.build.prop'.format(
+ partition) if partition else 'build.prop'
+ partition_props = self.info_dict.get(prop_file)
+ if not partition_props:
+ return None
+ return partition_props.GetProp(prop)
+
def GetPartitionBuildProp(self, prop, partition):
"""Returns the inquired build property for the provided partition."""
# If provided a partition for this property, only look within that
@@ -430,31 +438,33 @@
prop = prop.replace("ro.product", "ro.product.{}".format(partition))
else:
prop = prop.replace("ro.", "ro.{}.".format(partition))
- try:
- return self.info_dict.get("{}.build.prop".format(partition), {})[prop]
- except KeyError:
- raise ExternalError("couldn't find %s in %s.build.prop" %
- (prop, partition))
+
+ prop_val = self._GetRawBuildProp(prop, partition)
+ if prop_val is not None:
+ return prop_val
+ raise ExternalError("couldn't find %s in %s.build.prop" %
+ (prop, partition))
def GetBuildProp(self, prop):
"""Returns the inquired build property from the standard build.prop file."""
if prop in BuildInfo._RO_PRODUCT_RESOLVE_PROPS:
return self._ResolveRoProductBuildProp(prop)
- try:
- return self.info_dict.get("build.prop", {})[prop]
- except KeyError:
- raise ExternalError("couldn't find %s in build.prop" % (prop,))
+ prop_val = self._GetRawBuildProp(prop, None)
+ if prop_val is not None:
+ return prop_val
+
+ raise ExternalError("couldn't find %s in build.prop" % (prop,))
def _ResolveRoProductBuildProp(self, prop):
"""Resolves the inquired ro.product.* build property"""
- prop_val = self.info_dict.get("build.prop", {}).get(prop)
+ prop_val = self._GetRawBuildProp(prop, None)
if prop_val:
return prop_val
default_source_order = self._GetRoProductPropsDefaultSourceOrder()
- source_order_val = self.info_dict.get("build.prop", {}).get(
- "ro.product.property_source_order")
+ source_order_val = self._GetRawBuildProp(
+ "ro.product.property_source_order", None)
if source_order_val:
source_order = source_order_val.split(",")
else:
@@ -465,11 +475,10 @@
raise ExternalError(
"Invalid ro.product.property_source_order '{}'".format(source_order))
- for source in source_order:
+ for source_partition in source_order:
source_prop = prop.replace(
- "ro.product", "ro.product.{}".format(source), 1)
- prop_val = self.info_dict.get(
- "{}.build.prop".format(source), {}).get(source_prop)
+ "ro.product", "ro.product.{}".format(source_partition), 1)
+ prop_val = self._GetRawBuildProp(source_prop, source_partition)
if prop_val:
return prop_val
@@ -478,11 +487,9 @@
def _GetRoProductPropsDefaultSourceOrder(self):
# NOTE: refer to CDDs and android.os.Build.VERSION for the definition and
# values of these properties for each Android release.
- android_codename = self.info_dict.get("build.prop", {}).get(
- "ro.build.version.codename")
+ android_codename = self._GetRawBuildProp("ro.build.version.codename", None)
if android_codename == "REL":
- android_version = self.info_dict.get("build.prop", {}).get(
- "ro.build.version.release")
+ android_version = self._GetRawBuildProp("ro.build.version.release", None)
if android_version == "10":
return BuildInfo._RO_PRODUCT_PROPS_DEFAULT_SOURCE_ORDER_ANDROID_10
# NOTE: float() conversion of android_version will have rounding error.
@@ -565,6 +572,20 @@
script.AssertOemProperty(prop, values, oem_no_mount)
+def ReadFromInputFile(input_file, fn):
+ """Reads the contents of fn from input zipfile or directory."""
+ if isinstance(input_file, zipfile.ZipFile):
+ return input_file.read(fn).decode()
+ else:
+ path = os.path.join(input_file, *fn.split("/"))
+ try:
+ with open(path) as f:
+ return f.read()
+ except IOError as e:
+ if e.errno == errno.ENOENT:
+ raise KeyError(fn)
+
+
def LoadInfoDict(input_file, repacking=False):
"""Loads the key/value pairs from the given input target_files.
@@ -602,16 +623,7 @@
"input_file must be a path str when doing repacking"
def read_helper(fn):
- if isinstance(input_file, zipfile.ZipFile):
- return input_file.read(fn).decode()
- else:
- path = os.path.join(input_file, *fn.split("/"))
- try:
- with open(path) as f:
- return f.read()
- except IOError as e:
- if e.errno == errno.ENOENT:
- raise KeyError(fn)
+ return ReadFromInputFile(input_file, fn)
try:
d = LoadDictionaryFromLines(read_helper("META/misc_info.txt").split("\n"))
@@ -664,9 +676,14 @@
makeint("userdata_size")
makeint("cache_size")
makeint("recovery_size")
- makeint("boot_size")
makeint("fstab_version")
+ boot_images = "boot.img"
+ if "boot_images" in d:
+ boot_images = d["boot_images"]
+ for b in boot_images.split():
+ makeint(b.replace(".img","_size"))
+
# Load recovery fstab if applicable.
d["fstab"] = _FindAndLoadRecoveryFstab(d, input_file, read_helper)
@@ -674,13 +691,8 @@
# system and vendor.
for partition in PARTITIONS_WITH_CARE_MAP:
partition_prop = "{}.build.prop".format(partition)
- d[partition_prop] = LoadBuildProp(
- read_helper, "{}/build.prop".format(partition.upper()))
- # Some partition might use /<partition>/etc/build.prop as the new path.
- # TODO: try new path first when majority of them switch to the new path.
- if not d[partition_prop]:
- d[partition_prop] = LoadBuildProp(
- read_helper, "{}/etc/build.prop".format(partition.upper()))
+ d[partition_prop] = PartitionBuildProps.FromInputFile(
+ input_file, partition)
d["build.prop"] = d["system.build.prop"]
# Set up the salt (based on fingerprint) that will be used when adding AVB
@@ -695,15 +707,6 @@
return d
-def LoadBuildProp(read_helper, prop_file):
- try:
- data = read_helper(prop_file)
- except KeyError:
- logger.warning("Failed to read %s", prop_file)
- data = ""
- return LoadDictionaryFromLines(data.split("\n"))
-
-
def LoadListFromFile(file_path):
with open(file_path) as f:
return f.read().splitlines()
@@ -726,15 +729,131 @@
return d
+class PartitionBuildProps(object):
+ """The class holds the build prop of a particular partition.
+
+ This class loads the build.prop and holds the build properties for a given
+ partition. It also partially recognizes the 'import' statement in the
+ build.prop; and calculates alternative values of some specific build
+ properties during runtime.
+
+ Attributes:
+ input_file: a zipped target-file or an unzipped target-file directory.
+ partition: name of the partition.
+ props_allow_override: a list of build properties to search for the
+ alternative values during runtime.
+ build_props: a dict of build properties for the given partition.
+ prop_overrides: a set of props that are overridden by import.
+ placeholder_values: A dict of runtime variables' values to replace the
+ placeholders in the build.prop file. We expect exactly one value for
+ each of the variables.
+ """
+ def __init__(self, input_file, name, placeholder_values=None):
+ self.input_file = input_file
+ self.partition = name
+ self.props_allow_override = [props.format(name) for props in [
+ 'ro.product.{}.brand', 'ro.product.{}.name', 'ro.product.{}.device']]
+ self.build_props = {}
+ self.prop_overrides = set()
+ self.placeholder_values = {}
+ if placeholder_values:
+ self.placeholder_values = copy.deepcopy(placeholder_values)
+
+ @staticmethod
+ def FromDictionary(name, build_props):
+ """Constructs an instance from a build prop dictionary."""
+
+ props = PartitionBuildProps("unknown", name)
+ props.build_props = build_props.copy()
+ return props
+
+ @staticmethod
+ def FromInputFile(input_file, name, placeholder_values=None):
+ """Loads the build.prop file and builds the attributes."""
+ data = ''
+ for prop_file in ['{}/etc/build.prop'.format(name.upper()),
+ '{}/build.prop'.format(name.upper())]:
+ try:
+ data = ReadFromInputFile(input_file, prop_file)
+ break
+ except KeyError:
+ logger.warning('Failed to read %s', prop_file)
+
+ props = PartitionBuildProps(input_file, name, placeholder_values)
+ props._LoadBuildProp(data)
+ return props
+
+ def _LoadBuildProp(self, data):
+ for line in data.split('\n'):
+ line = line.strip()
+ if not line or line.startswith("#"):
+ continue
+ if line.startswith("import"):
+ overrides = self._ImportParser(line)
+ duplicates = self.prop_overrides.intersection(overrides.keys())
+ if duplicates:
+ raise ValueError('prop {} is overridden multiple times'.format(
+ ','.join(duplicates)))
+ self.prop_overrides = self.prop_overrides.union(overrides.keys())
+ self.build_props.update(overrides)
+ elif "=" in line:
+ name, value = line.split("=", 1)
+ if name in self.prop_overrides:
+ raise ValueError('prop {} is set again after overridden by import '
+ 'statement'.format(name))
+ self.build_props[name] = value
+
+ def _ImportParser(self, line):
+ """Parses the build prop in a given import statement."""
+
+ tokens = line.split()
+ if tokens[0] != 'import' or (len(tokens) != 2 and len(tokens) != 3) :
+ raise ValueError('Unrecognized import statement {}'.format(line))
+
+ if len(tokens) == 3:
+ logger.info("Import %s from %s, skip", tokens[2], tokens[1])
+ return {}
+
+ import_path = tokens[1]
+ if not re.match(r'^/{}/.*\.prop$'.format(self.partition), import_path):
+ raise ValueError('Unrecognized import path {}'.format(line))
+
+ # We only recognize a subset of import statement that the init process
+ # supports. And we can loose the restriction based on how the dynamic
+ # fingerprint is used in practice. The placeholder format should be
+ # ${placeholder}, and its value should be provided by the caller through
+ # the placeholder_values.
+ for prop, value in self.placeholder_values.items():
+ prop_place_holder = '${{{}}}'.format(prop)
+ if prop_place_holder in import_path:
+ import_path = import_path.replace(prop_place_holder, value)
+ if '$' in import_path:
+ logger.info('Unresolved place holder in import path %s', import_path)
+ return {}
+
+ import_path = import_path.replace('/{}'.format(self.partition),
+ self.partition.upper())
+ logger.info('Parsing build props override from %s', import_path)
+
+ lines = ReadFromInputFile(self.input_file, import_path).split('\n')
+ d = LoadDictionaryFromLines(lines)
+ return {key: val for key, val in d.items()
+ if key in self.props_allow_override}
+
+ def GetProp(self, prop):
+ return self.build_props.get(prop)
+
+
def LoadRecoveryFSTab(read_helper, fstab_version, recovery_fstab_path,
system_root_image=False):
class Partition(object):
- def __init__(self, mount_point, fs_type, device, length, context):
+ def __init__(self, mount_point, fs_type, device, length, context, slotselect):
self.mount_point = mount_point
self.fs_type = fs_type
self.device = device
self.length = length
self.context = context
+ self.slotselect = slotselect
try:
data = read_helper(recovery_fstab_path)
@@ -762,10 +881,13 @@
# It's a good line, parse it.
length = 0
+ slotselect = False
options = options.split(",")
for i in options:
if i.startswith("length="):
length = int(i[7:])
+ elif i == "slotselect":
+ slotselect = True
else:
# Ignore all unknown options in the unified fstab.
continue
@@ -779,7 +901,8 @@
mount_point = pieces[1]
d[mount_point] = Partition(mount_point=mount_point, fs_type=pieces[2],
- device=pieces[0], length=length, context=context)
+ device=pieces[0], length=length, context=context,
+ slotselect=slotselect)
# / is used for the system mount point when the root directory is included in
# system. Other areas assume system is always at "/system" so point /system
@@ -794,7 +917,8 @@
"""Finds the path to recovery fstab and loads its contents."""
# recovery fstab is only meaningful when installing an update via recovery
# (i.e. non-A/B OTA). Skip loading fstab if device used A/B OTA.
- if info_dict.get('ab_update') == 'true':
+ if info_dict.get('ab_update') == 'true' and \
+ info_dict.get("allow_non_ab") != "true":
return None
# We changed recovery.fstab path in Q, from ../RAMDISK/etc/recovery.fstab to
@@ -967,8 +1091,9 @@
Args:
image_path: The output path for the new VBMeta image.
partitions: A dict that's keyed by partition names with image paths as
- values. Only valid partition names are accepted, as listed in
- common.AVB_PARTITIONS.
+ values. Only valid partition names are accepted, as partitions listed
+ in common.AVB_PARTITIONS and custom partitions listed in
+ OPTIONS.info_dict.get("avb_custom_images_partition_list")
name: Name of the VBMeta partition, e.g. 'vbmeta', 'vbmeta_system'.
needed_partitions: Partitions whose descriptors should be included into the
generated VBMeta image.
@@ -980,11 +1105,15 @@
cmd = [avbtool, "make_vbmeta_image", "--output", image_path]
AppendAVBSigningArgs(cmd, name)
+ custom_partitions = OPTIONS.info_dict.get(
+ "avb_custom_images_partition_list", "").strip().split()
+
for partition, path in partitions.items():
if partition not in needed_partitions:
continue
assert (partition in AVB_PARTITIONS or
- partition in AVB_VBMETA_PARTITIONS), \
+ partition in AVB_VBMETA_PARTITIONS or
+ partition in custom_partitions), \
'Unknown partition: {}'.format(partition)
assert os.path.exists(path), \
'Failed to find {} for {}'.format(path, partition)
@@ -1182,7 +1311,10 @@
# AVB: if enabled, calculate and add hash to boot.img or recovery.img.
if info_dict.get("avb_enable") == "true":
avbtool = info_dict["avb_avbtool"]
- part_size = info_dict[partition_name + "_size"]
+ if partition_name == "recovery":
+ part_size = info_dict["recovery_size"]
+ else:
+ part_size = info_dict[image_name.replace(".img","_size")]
cmd = [avbtool, "add_hash_footer", "--image", img.name,
"--partition_size", str(part_size), "--partition_name",
partition_name]
@@ -2518,11 +2650,12 @@
self.device = 'map_partition("%s")' % partition
else:
if OPTIONS.source_info_dict is None:
- _, device_path = GetTypeAndDevice("/" + partition, OPTIONS.info_dict)
+ _, device_expr = GetTypeAndDeviceExpr("/" + partition,
+ OPTIONS.info_dict)
else:
- _, device_path = GetTypeAndDevice("/" + partition,
- OPTIONS.source_info_dict)
- self.device = '"%s"' % device_path
+ _, device_expr = GetTypeAndDeviceExpr("/" + partition,
+ OPTIONS.source_info_dict)
+ self.device = device_expr
@property
def required_cache(self):
@@ -2754,16 +2887,51 @@
"squashfs": "EMMC"
}
-
-def GetTypeAndDevice(mount_point, info):
+def GetTypeAndDevice(mount_point, info, check_no_slot=True):
+ """
+ Use GetTypeAndDeviceExpr whenever possible. This function is kept for
+ backwards compatibility. It aborts if the fstab entry has slotselect option
+ (unless check_no_slot is explicitly set to False).
+ """
fstab = info["fstab"]
if fstab:
+ if check_no_slot:
+ assert not fstab[mount_point].slotselect, \
+ "Use GetTypeAndDeviceExpr instead"
return (PARTITION_TYPES[fstab[mount_point].fs_type],
fstab[mount_point].device)
else:
raise KeyError
+def GetTypeAndDeviceExpr(mount_point, info):
+ """
+ Return the filesystem of the partition, and an edify expression that evaluates
+ to the device at runtime.
+ """
+ fstab = info["fstab"]
+ if fstab:
+ p = fstab[mount_point]
+ device_expr = '"%s"' % fstab[mount_point].device
+ if p.slotselect:
+ device_expr = 'add_slot_suffix(%s)' % device_expr
+ return (PARTITION_TYPES[fstab[mount_point].fs_type], device_expr)
+ else:
+ raise KeyError
+
+
+def GetEntryForDevice(fstab, device):
+ """
+ Returns:
+ The first entry in fstab whose device is the given value.
+ """
+ if not fstab:
+ return None
+ for mount_point in fstab:
+ if fstab[mount_point].device == device:
+ return fstab[mount_point]
+ return None
+
def ParseCertificate(data):
"""Parses and converts a PEM-encoded certificate into DER-encoded.
@@ -2888,8 +3056,10 @@
try:
# The following GetTypeAndDevice()s need to use the path in the target
# info_dict instead of source_info_dict.
- boot_type, boot_device = GetTypeAndDevice("/boot", info_dict)
- recovery_type, recovery_device = GetTypeAndDevice("/recovery", info_dict)
+ boot_type, boot_device = GetTypeAndDevice("/boot", info_dict,
+ check_no_slot=False)
+ recovery_type, recovery_device = GetTypeAndDevice("/recovery", info_dict,
+ check_no_slot=False)
except KeyError:
return
@@ -2931,9 +3101,9 @@
'recovery_size': recovery_img.size,
'recovery_sha1': recovery_img.sha1,
'boot_type': boot_type,
- 'boot_device': boot_device,
+ 'boot_device': boot_device + '$(getprop ro.boot.slot_suffix)',
'recovery_type': recovery_type,
- 'recovery_device': recovery_device,
+ 'recovery_device': recovery_device + '$(getprop ro.boot.slot_suffix)',
'bonus_args': bonus_args}
# The install script location moved from /system/etc to /system/bin in the L
diff --git a/tools/releasetools/edify_generator.py b/tools/releasetools/edify_generator.py
index 7ed85fe..99e21f1 100644
--- a/tools/releasetools/edify_generator.py
+++ b/tools/releasetools/edify_generator.py
@@ -183,11 +183,30 @@
It checks the checksums of the given partitions. If none of them matches the
expected checksum, updater will additionally look for a backup on /cache.
"""
+ self._CheckSecondTokenNotSlotSuffixed(target, "PatchPartitionExprCheck")
+ self._CheckSecondTokenNotSlotSuffixed(source, "PatchPartitionExprCheck")
+ self.PatchPartitionExprCheck('"%s"' % target, '"%s"' % source)
+
+ def PatchPartitionExprCheck(self, target_expr, source_expr):
+ """Checks whether updater can patch the given partitions.
+
+ It checks the checksums of the given partitions. If none of them matches the
+ expected checksum, updater will additionally look for a backup on /cache.
+
+ Args:
+ target_expr: an Edify expression that serves as the target arg to
+ patch_partition. Must be evaluated to a string in the form of
+ foo:bar:baz:quux
+ source_expr: an Edify expression that serves as the source arg to
+ patch_partition. Must be evaluated to a string in the form of
+ foo:bar:baz:quux
+ """
self.script.append(self.WordWrap((
- 'patch_partition_check("{target}",\0"{source}") ||\n abort('
- '"E{code}: \\"{target}\\" or \\"{source}\\" has unexpected '
- 'contents.");').format(
- target=target, source=source,
+ 'patch_partition_check({target},\0{source}) ||\n abort('
+ 'concat("E{code}: \\"",{target},"\\" or \\"",{source},"\\" has '
+ 'unexpected contents."));').format(
+ target=target_expr,
+ source=source_expr,
code=common.ErrorCode.BAD_PATCH_FILE)))
def CacheFreeSpaceCheck(self, amount):
@@ -218,8 +237,9 @@
mount_flags = mount_dict.get(p.fs_type, "")
if p.context is not None:
mount_flags = p.context + ("," + mount_flags if mount_flags else "")
- self.script.append('mount("%s", "%s", "%s", "%s", "%s");' % (
- p.fs_type, common.PARTITION_TYPES[p.fs_type], p.device,
+ self.script.append('mount("%s", "%s", %s, "%s", "%s");' % (
+ p.fs_type, common.PARTITION_TYPES[p.fs_type],
+ self._GetSlotSuffixDeviceForEntry(p),
p.mount_point, mount_flags))
self.mounts.add(p.mount_point)
@@ -242,8 +262,9 @@
raise ValueError("Partition %s cannot be tuned\n" % (partition,))
self.script.append(
'tune2fs(' + "".join(['"%s", ' % (i,) for i in options]) +
- '"%s") || abort("E%d: Failed to tune partition %s");' % (
- p.device, common.ErrorCode.TUNE_PARTITION_FAILURE, partition))
+ '%s) || abort("E%d: Failed to tune partition %s");' % (
+ self._GetSlotSuffixDeviceForEntry(p),
+ common.ErrorCode.TUNE_PARTITION_FAILURE, partition))
def FormatPartition(self, partition):
"""Format the given partition, specified by its mount point (eg,
@@ -252,18 +273,19 @@
fstab = self.fstab
if fstab:
p = fstab[partition]
- self.script.append('format("%s", "%s", "%s", "%s", "%s");' %
+ self.script.append('format("%s", "%s", %s, "%s", "%s");' %
(p.fs_type, common.PARTITION_TYPES[p.fs_type],
- p.device, p.length, p.mount_point))
+ self._GetSlotSuffixDeviceForEntry(p),
+ p.length, p.mount_point))
def WipeBlockDevice(self, partition):
if partition not in ("/system", "/vendor"):
raise ValueError(("WipeBlockDevice doesn't work on %s\n") % (partition,))
fstab = self.fstab
size = self.info.get(partition.lstrip("/") + "_size", None)
- device = fstab[partition].device
+ device = self._GetSlotSuffixDeviceForEntry(fstab[partition])
- self.script.append('wipe_block_device("%s", %s);' % (device, size))
+ self.script.append('wipe_block_device(%s, %s);' % (device, size))
def ApplyPatch(self, srcfile, tgtfile, tgtsize, tgtsha1, *patchpairs):
"""Apply binary patches (in *patchpairs) to the given srcfile to
@@ -296,14 +318,69 @@
self.PatchPartition(target, source, patch)
def PatchPartition(self, target, source, patch):
- """Applies the patch to the source partition and writes it to target."""
+ """
+ Applies the patch to the source partition and writes it to target.
+
+ Args:
+ target: the target arg to patch_partition. Must be in the form of
+ foo:bar:baz:quux
+ source: the source arg to patch_partition. Must be in the form of
+ foo:bar:baz:quux
+ patch: the patch arg to patch_partition. Must be an unquoted string.
+ """
+ self._CheckSecondTokenNotSlotSuffixed(target, "PatchPartitionExpr")
+ self._CheckSecondTokenNotSlotSuffixed(source, "PatchPartitionExpr")
+ self.PatchPartitionExpr('"%s"' % target, '"%s"' % source, '"%s"' % patch)
+
+ def PatchPartitionExpr(self, target_expr, source_expr, patch_expr):
+ """
+ Applies the patch to the source partition and writes it to target.
+
+ Args:
+ target_expr: an Edify expression that serves as the target arg to
+ patch_partition. Must be evaluated to a string in the form of
+ foo:bar:baz:quux
+ source_expr: an Edify expression that serves as the source arg to
+ patch_partition. Must be evaluated to a string in the form of
+ foo:bar:baz:quux
+ patch_expr: an Edify expression that serves as the patch arg to
+ patch_partition. Must be evaluated to a string.
+ """
self.script.append(self.WordWrap((
- 'patch_partition("{target}",\0"{source}",\0'
- 'package_extract_file("{patch}")) ||\n'
- ' abort("E{code}: Failed to apply patch to {source}");').format(
- target=target, source=source, patch=patch,
+ 'patch_partition({target},\0{source},\0'
+ 'package_extract_file({patch})) ||\n'
+ ' abort(concat('
+ ' "E{code}: Failed to apply patch to ",{source}));').format(
+ target=target_expr,
+ source=source_expr,
+ patch=patch_expr,
code=common.ErrorCode.APPLY_PATCH_FAILURE)))
+ def _GetSlotSuffixDeviceForEntry(self, entry=None):
+ """
+ Args:
+ entry: the fstab entry of device "foo"
+ Returns:
+ An edify expression. Caller must not quote result.
+ If foo is slot suffixed, it returns
+ 'add_slot_suffix("foo")'
+ Otherwise it returns
+ '"foo"' (quoted)
+ """
+ assert entry is not None
+ if entry.slotselect:
+ return 'add_slot_suffix("%s")' % entry.device
+ return '"%s"' % entry.device
+
+ def _CheckSecondTokenNotSlotSuffixed(self, s, fn):
+ lst = s.split(':')
+ assert(len(s) == 4), "{} does not contain 4 tokens".format(s)
+ if self.fstab:
+ entry = common.GetEntryForDevice(s[1])
+ if entry is not None:
+ assert not entry.slotselect, \
+ "Use %s because %s is slot suffixed" % (fn, s[1])
+
def WriteRawImage(self, mount_point, fn, mapfn=None):
"""Write the given package file into the partition for the given
mount point."""
@@ -312,15 +389,16 @@
if fstab:
p = fstab[mount_point]
partition_type = common.PARTITION_TYPES[p.fs_type]
- args = {'device': p.device, 'fn': fn}
+ device = self._GetSlotSuffixDeviceForEntry(p)
+ args = {'device': device, 'fn': fn}
if partition_type == "EMMC":
if mapfn:
args["map"] = mapfn
self.script.append(
- 'package_extract_file("%(fn)s", "%(device)s", "%(map)s");' % args)
+ 'package_extract_file("%(fn)s", %(device)s, "%(map)s");' % args)
else:
self.script.append(
- 'package_extract_file("%(fn)s", "%(device)s");' % args)
+ 'package_extract_file("%(fn)s", %(device)s);' % args)
else:
raise ValueError(
"don't know how to write \"%s\" partitions" % p.fs_type)
diff --git a/tools/releasetools/ota_from_target_files.py b/tools/releasetools/ota_from_target_files.py
index 92a46a2..b753414 100755
--- a/tools/releasetools/ota_from_target_files.py
+++ b/tools/releasetools/ota_from_target_files.py
@@ -78,6 +78,13 @@
Write a copy of the metadata to a separate file. Therefore, users can
read the post build fingerprint without extracting the OTA package.
+ --force_non_ab
+ This flag can only be set on an A/B device that also supports non-A/B
+ updates. Implies --two_step.
+ If set, generate that non-A/B update package.
+ If not set, generates A/B package for A/B device and non-A/B package for
+ non-A/B device.
+
Non-A/B OTA specific options
-b (--binary) <file>
@@ -182,6 +189,13 @@
--payload_signer_key_size <key_size>
Deprecated. Use the '--payload_signer_maximum_signature_size' instead.
+ --boot_variable_file <path>
+ A file that contains the possible values of ro.boot.* properties. It's
+ used to calculate the possible runtime fingerprints when some
+ ro.product.* properties are overridden by the 'import' statement.
+ The file expects one property per line, and each line has the following
+ format: 'prop_name=value1,value2'. e.g. 'ro.boot.product.sku=std,pro'
+
--skip_postinstall
Skip the postinstall hooks when generating an A/B OTA package (default:
False). Note that this discards ALL the hooks, including non-optional
@@ -193,6 +207,8 @@
from __future__ import print_function
import collections
+import copy
+import itertools
import logging
import multiprocessing
import os.path
@@ -229,6 +245,7 @@
OPTIONS.no_signing = False
OPTIONS.block_based = True
OPTIONS.updater_binary = None
+OPTIONS.oem_dicts = None
OPTIONS.oem_source = None
OPTIONS.oem_no_mount = False
OPTIONS.full_radio = False
@@ -247,6 +264,8 @@
OPTIONS.skip_compatibility_check = False
OPTIONS.output_metadata_path = None
OPTIONS.disable_fec_computation = False
+OPTIONS.force_non_ab = False
+OPTIONS.boot_variable_file = None
METADATA_NAME = 'META-INF/com/android/metadata'
@@ -263,7 +282,8 @@
# 'system_other' and bootloader partitions.
SECONDARY_PAYLOAD_SKIPPED_IMAGES = [
'boot', 'dtbo', 'modem', 'odm', 'product', 'radio', 'recovery',
- 'system_ext', 'vbmeta', 'vbmeta_system', 'vbmeta_vendor', 'vendor']
+ 'system_ext', 'vbmeta', 'vbmeta_system', 'vbmeta_vendor', 'vendor',
+ 'vendor_boot']
class PayloadSigner(object):
@@ -918,17 +938,27 @@
assert isinstance(target_info, common.BuildInfo)
assert source_info is None or isinstance(source_info, common.BuildInfo)
+ separator = '|'
+
+ boot_variable_values = {}
+ if OPTIONS.boot_variable_file:
+ d = common.LoadDictionaryFromFile(OPTIONS.boot_variable_file)
+ for key, values in d.items():
+ boot_variable_values[key] = [val.strip() for val in values.split(',')]
+
+ post_build_devices, post_build_fingerprints = \
+ CalculateRuntimeDevicesAndFingerprints(target_info, boot_variable_values)
metadata = {
- 'post-build' : target_info.fingerprint,
- 'post-build-incremental' : target_info.GetBuildProp(
+ 'post-build': separator.join(sorted(post_build_fingerprints)),
+ 'post-build-incremental': target_info.GetBuildProp(
'ro.build.version.incremental'),
- 'post-sdk-level' : target_info.GetBuildProp(
+ 'post-sdk-level': target_info.GetBuildProp(
'ro.build.version.sdk'),
- 'post-security-patch-level' : target_info.GetBuildProp(
+ 'post-security-patch-level': target_info.GetBuildProp(
'ro.build.version.security_patch'),
}
- if target_info.is_ab:
+ if target_info.is_ab and not OPTIONS.force_non_ab:
metadata['ota-type'] = 'AB'
metadata['ota-required-cache'] = '0'
else:
@@ -942,12 +972,15 @@
is_incremental = source_info is not None
if is_incremental:
- metadata['pre-build'] = source_info.fingerprint
+ pre_build_devices, pre_build_fingerprints = \
+ CalculateRuntimeDevicesAndFingerprints(source_info,
+ boot_variable_values)
+ metadata['pre-build'] = separator.join(sorted(pre_build_fingerprints))
metadata['pre-build-incremental'] = source_info.GetBuildProp(
'ro.build.version.incremental')
- metadata['pre-device'] = source_info.device
+ metadata['pre-device'] = separator.join(sorted(pre_build_devices))
else:
- metadata['pre-device'] = target_info.device
+ metadata['pre-device'] = separator.join(sorted(post_build_devices))
# Use the actual post-timestamp, even for a downgrade case.
metadata['post-timestamp'] = target_info.GetBuildProp('ro.build.date.utc')
@@ -1450,7 +1483,8 @@
required_cache_sizes = [diff.required_cache for diff in
block_diff_dict.values()]
if updating_boot:
- boot_type, boot_device = common.GetTypeAndDevice("/boot", source_info)
+ boot_type, boot_device_expr = common.GetTypeAndDeviceExpr("/boot",
+ source_info)
d = common.Difference(target_boot, source_boot)
_, _, d = d.ComputePatch()
if d is None:
@@ -1465,11 +1499,11 @@
common.ZipWriteStr(output_zip, "boot.img.p", d)
- script.PatchPartitionCheck(
- "{}:{}:{}:{}".format(
- boot_type, boot_device, target_boot.size, target_boot.sha1),
- "{}:{}:{}:{}".format(
- boot_type, boot_device, source_boot.size, source_boot.sha1))
+ target_expr = 'concat("{}:",{},":{}:{}")'.format(
+ boot_type, boot_device_expr, target_boot.size, target_boot.sha1)
+ source_expr = 'concat("{}:",{},":{}:{}")'.format(
+ boot_type, boot_device_expr, source_boot.size, source_boot.sha1)
+ script.PatchPartitionExprCheck(target_expr, source_expr)
required_cache_sizes.append(target_boot.size)
@@ -1537,12 +1571,11 @@
logger.info("boot image changed; including patch.")
script.Print("Patching boot image...")
script.ShowProgress(0.1, 10)
- script.PatchPartition(
- '{}:{}:{}:{}'.format(
- boot_type, boot_device, target_boot.size, target_boot.sha1),
- '{}:{}:{}:{}'.format(
- boot_type, boot_device, source_boot.size, source_boot.sha1),
- 'boot.img.p')
+ target_expr = 'concat("{}:",{},":{}:{}")'.format(
+ boot_type, boot_device_expr, target_boot.size, target_boot.sha1)
+ source_expr = 'concat("{}:",{},":{}:{}")'.format(
+ boot_type, boot_device_expr, source_boot.size, source_boot.sha1)
+ script.PatchPartitionExpr(target_expr, source_expr, '"boot.img.p"')
else:
logger.info("boot image unchanged; skipping.")
@@ -1959,6 +1992,37 @@
output_file)
+def CalculateRuntimeDevicesAndFingerprints(build_info, boot_variable_values):
+ """Returns a tuple of sets for runtime devices and fingerprints"""
+
+ device_names = {build_info.device}
+ fingerprints = {build_info.fingerprint}
+
+ if not boot_variable_values:
+ return device_names, fingerprints
+
+ # Calculate all possible combinations of the values for the boot variables.
+ keys = boot_variable_values.keys()
+ value_list = boot_variable_values.values()
+ combinations = [dict(zip(keys, values))
+ for values in itertools.product(*value_list)]
+ for placeholder_values in combinations:
+ # Reload the info_dict as some build properties may change their values
+ # based on the value of ro.boot* properties.
+ info_dict = copy.deepcopy(build_info.info_dict)
+ for partition in common.PARTITIONS_WITH_CARE_MAP:
+ partition_prop_key = "{}.build.prop".format(partition)
+ old_props = info_dict[partition_prop_key]
+ info_dict[partition_prop_key] = common.PartitionBuildProps.FromInputFile(
+ old_props.input_file, partition, placeholder_values)
+ info_dict["build.prop"] = info_dict["system.build.prop"]
+
+ new_build_info = common.BuildInfo(info_dict, build_info.oem_dicts)
+ device_names.add(new_build_info.device)
+ fingerprints.add(new_build_info.fingerprint)
+ return device_names, fingerprints
+
+
def main(argv):
def option_handler(o, a):
@@ -2032,6 +2096,10 @@
OPTIONS.output_metadata_path = a
elif o == "--disable_fec_computation":
OPTIONS.disable_fec_computation = True
+ elif o == "--force_non_ab":
+ OPTIONS.force_non_ab = True
+ elif o == "--boot_variable_file":
+ OPTIONS.boot_variable_file = a
else:
return False
return True
@@ -2068,6 +2136,8 @@
"skip_compatibility_check",
"output_metadata_path=",
"disable_fec_computation",
+ "force_non_ab",
+ "boot_variable_file=",
], extra_option_handler=option_handler)
if len(args) != 2:
@@ -2129,11 +2199,17 @@
OPTIONS.skip_postinstall = True
ab_update = OPTIONS.info_dict.get("ab_update") == "true"
+ allow_non_ab = OPTIONS.info_dict.get("allow_non_ab") == "true"
+ if OPTIONS.force_non_ab:
+ assert allow_non_ab, "--force_non_ab only allowed on devices that supports non-A/B"
+ assert ab_update, "--force_non_ab only allowed on A/B devices"
+
+ generate_ab = not OPTIONS.force_non_ab and ab_update
# Use the default key to sign the package if not specified with package_key.
# package_keys are needed on ab_updates, so always define them if an
- # ab_update is getting created.
- if not OPTIONS.no_signing or ab_update:
+ # A/B update is getting created.
+ if not OPTIONS.no_signing or generate_ab:
if OPTIONS.package_key is None:
OPTIONS.package_key = OPTIONS.info_dict.get(
"default_system_dev_certificate",
@@ -2141,7 +2217,7 @@
# Get signing keys
OPTIONS.key_passwords = common.GetKeyPasswords([OPTIONS.package_key])
- if ab_update:
+ if generate_ab:
GenerateAbOtaPackage(
target_file=args[0],
output_file=args[1],
diff --git a/tools/releasetools/sign_target_files_apks.py b/tools/releasetools/sign_target_files_apks.py
index 52cd9a8..47360c9 100755
--- a/tools/releasetools/sign_target_files_apks.py
+++ b/tools/releasetools/sign_target_files_apks.py
@@ -112,6 +112,17 @@
(e.g. "--signing_helper /path/to/helper"). The args will be appended to
the existing ones in info dict.
+ --avb_extra_custom_image_key <partition=key>
+ --avb_extra_custom_image_algorithm <partition=algorithm>
+ Use the specified algorithm (e.g. SHA256_RSA4096) and the key to AVB-sign
+ the specified custom images mounted on the partition. Otherwise it uses
+ the existing values in info dict.
+
+ --avb_extra_custom_image_extra_args <partition=extra_args>
+ Specify any additional args that are needed to AVB-sign the custom images
+ mounted on the partition (e.g. "--signing_helper /path/to/helper"). The
+ args will be appended to the existing ones in info dict.
+
--android_jar_path <path>
Path to the android.jar to repack the apex file.
"""
@@ -956,12 +967,20 @@
if extra_args:
print('Setting extra AVB signing args for %s to "%s"' % (
partition, extra_args))
- args_key = AVB_FOOTER_ARGS_BY_PARTITION[partition]
+ if partition in AVB_FOOTER_ARGS_BY_PARTITION:
+ args_key = AVB_FOOTER_ARGS_BY_PARTITION[partition]
+ else:
+ # custom partition
+ args_key = "avb_{}_add_hashtree_footer_args".format(partition)
misc_info[args_key] = (misc_info.get(args_key, '') + ' ' + extra_args)
for partition in AVB_FOOTER_ARGS_BY_PARTITION:
ReplaceAvbPartitionSigningKey(partition)
+ for custom_partition in misc_info.get(
+ "avb_custom_images_partition_list", "").strip().split():
+ ReplaceAvbPartitionSigningKey(custom_partition)
+
def RewriteAvbProps(misc_info):
"""Rewrites the props in AVB signing args."""
@@ -1208,6 +1227,18 @@
OPTIONS.avb_extra_args['vbmeta_vendor'] = a
elif o == "--avb_apex_extra_args":
OPTIONS.avb_extra_args['apex'] = a
+ elif o == "--avb_extra_custom_image_key":
+ partition, key = a.split("=")
+ OPTIONS.avb_keys[partition] = key
+ elif o == "--avb_extra_custom_image_algorithm":
+ partition, algorithm = a.split("=")
+ OPTIONS.avb_algorithms[partition] = algorithm
+ elif o == "--avb_extra_custom_image_extra_args":
+ # Setting the maxsplit parameter to one, which will return a list with
+ # two elements. e.g., the second '=' should not be splitted for
+ # 'oem=--signing_helper_with_files=/tmp/avbsigner.sh'.
+ partition, extra_args = a.split("=", 1)
+ OPTIONS.avb_extra_args[partition] = extra_args
else:
return False
return True
@@ -1252,6 +1283,9 @@
"avb_vbmeta_vendor_algorithm=",
"avb_vbmeta_vendor_key=",
"avb_vbmeta_vendor_extra_args=",
+ "avb_extra_custom_image_key=",
+ "avb_extra_custom_image_algorithm=",
+ "avb_extra_custom_image_extra_args=",
],
extra_option_handler=option_handler)
diff --git a/tools/releasetools/test_add_img_to_target_files.py b/tools/releasetools/test_add_img_to_target_files.py
index 3d0766f..c82a40b 100644
--- a/tools/releasetools/test_add_img_to_target_files.py
+++ b/tools/releasetools/test_add_img_to_target_files.py
@@ -128,13 +128,16 @@
'vendor_image_size' : 40960,
'system_verity_block_device': '/dev/block/system',
'vendor_verity_block_device': '/dev/block/vendor',
- 'system.build.prop': {
- 'ro.system.build.fingerprint':
- 'google/sailfish/12345:user/dev-keys',
- },
- 'vendor.build.prop': {
- 'ro.vendor.build.fingerprint': 'google/sailfish/678:user/dev-keys',
- },
+ 'system.build.prop': common.PartitionBuildProps.FromDictionary(
+ 'system', {
+ 'ro.system.build.fingerprint':
+ 'google/sailfish/12345:user/dev-keys'}
+ ),
+ 'vendor.build.prop': common.PartitionBuildProps.FromDictionary(
+ 'vendor', {
+ 'ro.vendor.build.fingerprint':
+ 'google/sailfish/678:user/dev-keys'}
+ ),
}
# Prepare the META/ folder.
@@ -206,18 +209,21 @@
"""Tests the case for device using AVB."""
image_paths = self._test_AddCareMapForAbOta()
OPTIONS.info_dict = {
- 'extfs_sparse_flag' : '-s',
- 'system_image_size' : 65536,
- 'vendor_image_size' : 40960,
- 'avb_system_hashtree_enable' : 'true',
- 'avb_vendor_hashtree_enable' : 'true',
- 'system.build.prop': {
- 'ro.system.build.fingerprint':
- 'google/sailfish/12345:user/dev-keys',
- },
- 'vendor.build.prop': {
- 'ro.vendor.build.fingerprint': 'google/sailfish/678:user/dev-keys',
- }
+ 'extfs_sparse_flag': '-s',
+ 'system_image_size': 65536,
+ 'vendor_image_size': 40960,
+ 'avb_system_hashtree_enable': 'true',
+ 'avb_vendor_hashtree_enable': 'true',
+ 'system.build.prop': common.PartitionBuildProps.FromDictionary(
+ 'system', {
+ 'ro.system.build.fingerprint':
+ 'google/sailfish/12345:user/dev-keys'}
+ ),
+ 'vendor.build.prop': common.PartitionBuildProps.FromDictionary(
+ 'vendor', {
+ 'ro.vendor.build.fingerprint':
+ 'google/sailfish/678:user/dev-keys'}
+ ),
}
AddCareMapForAbOta(None, ['system', 'vendor'], image_paths)
@@ -258,17 +264,21 @@
"""Tests the case for partitions with thumbprint."""
image_paths = self._test_AddCareMapForAbOta()
OPTIONS.info_dict = {
- 'extfs_sparse_flag' : '-s',
- 'system_image_size' : 65536,
- 'vendor_image_size' : 40960,
+ 'extfs_sparse_flag': '-s',
+ 'system_image_size': 65536,
+ 'vendor_image_size': 40960,
'system_verity_block_device': '/dev/block/system',
'vendor_verity_block_device': '/dev/block/vendor',
- 'system.build.prop': {
- 'ro.system.build.thumbprint': 'google/sailfish/123:user/dev-keys',
- },
- 'vendor.build.prop' : {
- 'ro.vendor.build.thumbprint': 'google/sailfish/456:user/dev-keys',
- },
+ 'system.build.prop': common.PartitionBuildProps.FromDictionary(
+ 'system', {
+ 'ro.system.build.thumbprint':
+ 'google/sailfish/123:user/dev-keys'}
+ ),
+ 'vendor.build.prop': common.PartitionBuildProps.FromDictionary(
+ 'vendor', {
+ 'ro.vendor.build.thumbprint':
+ 'google/sailfish/456:user/dev-keys'}
+ ),
}
AddCareMapForAbOta(None, ['system', 'vendor'], image_paths)
diff --git a/tools/releasetools/test_apex_utils.py b/tools/releasetools/test_apex_utils.py
index e19bc90..7b4a4b0 100644
--- a/tools/releasetools/test_apex_utils.py
+++ b/tools/releasetools/test_apex_utils.py
@@ -50,11 +50,12 @@
payload_file = self._GetTestPayload()
apex_utils.SignApexPayload(
'avbtool', payload_file, self.payload_key, 'testkey', 'SHA256_RSA2048',
- self.SALT, no_hashtree=True)
+ self.SALT, 'sha256', no_hashtree=True)
payload_info = apex_utils.ParseApexPayloadInfo('avbtool', payload_file)
self.assertEqual('SHA256_RSA2048', payload_info['Algorithm'])
self.assertEqual(self.SALT, payload_info['Salt'])
self.assertEqual('testkey', payload_info['apex.key'])
+ self.assertEqual('sha256', payload_info['Hash Algorithm'])
self.assertEqual('0 bytes', payload_info['Tree Size'])
@test_utils.SkipIfExternalToolsUnavailable()
@@ -62,7 +63,7 @@
payload_file = self._GetTestPayload()
apex_utils.SignApexPayload(
'avbtool', payload_file, self.payload_key, 'testkey', 'SHA256_RSA2048',
- self.SALT, no_hashtree=True)
+ self.SALT, 'sha256', no_hashtree=True)
apex_utils.VerifyApexPayload(
'avbtool', payload_file, self.payload_key, True)
@@ -71,7 +72,7 @@
payload_file = self._GetTestPayload()
apex_utils.SignApexPayload(
'avbtool', payload_file, self.payload_key, 'testkey', 'SHA256_RSA2048',
- self.SALT, no_hashtree=False)
+ self.SALT, 'sha256', no_hashtree=False)
apex_utils.VerifyApexPayload('avbtool', payload_file, self.payload_key)
payload_info = apex_utils.ParseApexPayloadInfo('avbtool', payload_file)
self.assertEqual('4096 bytes', payload_info['Tree Size'])
@@ -81,7 +82,7 @@
payload_file = self._GetTestPayload()
apex_utils.SignApexPayload(
'avbtool', payload_file, self.payload_key, 'testkey', 'SHA256_RSA2048',
- self.SALT, no_hashtree=True)
+ self.SALT, 'sha256', no_hashtree=True)
apex_utils.VerifyApexPayload('avbtool', payload_file, self.payload_key,
no_hashtree=True)
payload_info = apex_utils.ParseApexPayloadInfo('avbtool', payload_file)
@@ -98,7 +99,7 @@
'avbtool',
payload_file,
self.payload_key,
- 'testkey', 'SHA256_RSA2048', self.SALT,
+ 'testkey', 'SHA256_RSA2048', self.SALT, 'sha256',
True,
payload_signer_args)
apex_utils.VerifyApexPayload(
@@ -115,6 +116,7 @@
'testkey',
'SHA256_RSA2048',
self.SALT,
+ 'sha256',
no_hashtree=True)
@test_utils.SkipIfExternalToolsUnavailable()
@@ -122,7 +124,7 @@
payload_file = self._GetTestPayload()
apex_utils.SignApexPayload(
'avbtool', payload_file, self.payload_key, 'testkey', 'SHA256_RSA2048',
- self.SALT, True)
+ self.SALT, 'sha256', True)
apex_utils.VerifyApexPayload(
'avbtool', payload_file, self.payload_key, True)
self.assertRaises(
diff --git a/tools/releasetools/test_common.py b/tools/releasetools/test_common.py
index 173ef53..e4f0812 100644
--- a/tools/releasetools/test_common.py
+++ b/tools/releasetools/test_common.py
@@ -47,109 +47,124 @@
class BuildInfoTest(test_utils.ReleaseToolsTestCase):
TEST_INFO_DICT = {
- 'build.prop' : {
- 'ro.product.device' : 'product-device',
- 'ro.product.name' : 'product-name',
- 'ro.build.fingerprint' : 'build-fingerprint',
- 'ro.build.foo' : 'build-foo',
- },
- 'system.build.prop' : {
- 'ro.product.system.brand' : 'product-brand',
- 'ro.product.system.name' : 'product-name',
- 'ro.product.system.device' : 'product-device',
- 'ro.system.build.version.release' : 'version-release',
- 'ro.system.build.id' : 'build-id',
- 'ro.system.build.version.incremental' : 'version-incremental',
- 'ro.system.build.type' : 'build-type',
- 'ro.system.build.tags' : 'build-tags',
- 'ro.system.build.foo' : 'build-foo',
- },
- 'vendor.build.prop' : {
- 'ro.product.vendor.brand' : 'vendor-product-brand',
- 'ro.product.vendor.name' : 'vendor-product-name',
- 'ro.product.vendor.device' : 'vendor-product-device',
- 'ro.vendor.build.version.release' : 'vendor-version-release',
- 'ro.vendor.build.id' : 'vendor-build-id',
- 'ro.vendor.build.version.incremental' : 'vendor-version-incremental',
- 'ro.vendor.build.type' : 'vendor-build-type',
- 'ro.vendor.build.tags' : 'vendor-build-tags',
- },
- 'property1' : 'value1',
- 'property2' : 4096,
+ 'build.prop': common.PartitionBuildProps.FromDictionary(
+ 'system', {
+ 'ro.product.device': 'product-device',
+ 'ro.product.name': 'product-name',
+ 'ro.build.fingerprint': 'build-fingerprint',
+ 'ro.build.foo': 'build-foo'}
+ ),
+ 'system.build.prop': common.PartitionBuildProps.FromDictionary(
+ 'system', {
+ 'ro.product.system.brand': 'product-brand',
+ 'ro.product.system.name': 'product-name',
+ 'ro.product.system.device': 'product-device',
+ 'ro.system.build.version.release': 'version-release',
+ 'ro.system.build.id': 'build-id',
+ 'ro.system.build.version.incremental': 'version-incremental',
+ 'ro.system.build.type': 'build-type',
+ 'ro.system.build.tags': 'build-tags',
+ 'ro.system.build.foo': 'build-foo'}
+ ),
+ 'vendor.build.prop': common.PartitionBuildProps.FromDictionary(
+ 'vendor', {
+ 'ro.product.vendor.brand': 'vendor-product-brand',
+ 'ro.product.vendor.name': 'vendor-product-name',
+ 'ro.product.vendor.device': 'vendor-product-device',
+ 'ro.vendor.build.version.release': 'vendor-version-release',
+ 'ro.vendor.build.id': 'vendor-build-id',
+ 'ro.vendor.build.version.incremental':
+ 'vendor-version-incremental',
+ 'ro.vendor.build.type': 'vendor-build-type',
+ 'ro.vendor.build.tags': 'vendor-build-tags'}
+ ),
+ 'property1': 'value1',
+ 'property2': 4096,
}
TEST_INFO_DICT_USES_OEM_PROPS = {
- 'build.prop' : {
- 'ro.product.name' : 'product-name',
- 'ro.build.thumbprint' : 'build-thumbprint',
- 'ro.build.bar' : 'build-bar',
- },
- 'vendor.build.prop' : {
- 'ro.vendor.build.fingerprint' : 'vendor-build-fingerprint',
- },
- 'property1' : 'value1',
- 'property2' : 4096,
- 'oem_fingerprint_properties' : 'ro.product.device ro.product.brand',
+ 'build.prop': common.PartitionBuildProps.FromDictionary(
+ 'system', {
+ 'ro.product.name': 'product-name',
+ 'ro.build.thumbprint': 'build-thumbprint',
+ 'ro.build.bar': 'build-bar'}
+ ),
+ 'vendor.build.prop': common.PartitionBuildProps.FromDictionary(
+ 'vendor', {
+ 'ro.vendor.build.fingerprint': 'vendor-build-fingerprint'}
+ ),
+ 'property1': 'value1',
+ 'property2': 4096,
+ 'oem_fingerprint_properties': 'ro.product.device ro.product.brand',
}
TEST_OEM_DICTS = [
{
- 'ro.product.brand' : 'brand1',
- 'ro.product.device' : 'device1',
+ 'ro.product.brand': 'brand1',
+ 'ro.product.device': 'device1',
},
{
- 'ro.product.brand' : 'brand2',
- 'ro.product.device' : 'device2',
+ 'ro.product.brand': 'brand2',
+ 'ro.product.device': 'device2',
},
{
- 'ro.product.brand' : 'brand3',
- 'ro.product.device' : 'device3',
+ 'ro.product.brand': 'brand3',
+ 'ro.product.device': 'device3',
},
]
TEST_INFO_DICT_PROPERTY_SOURCE_ORDER = {
- 'build.prop' : {
- 'ro.build.fingerprint' : 'build-fingerprint',
- 'ro.product.property_source_order' :
- 'product,odm,vendor,system_ext,system',
- },
- 'system.build.prop' : {
- 'ro.product.system.device' : 'system-product-device',
- },
- 'vendor.build.prop' : {
- 'ro.product.vendor.device' : 'vendor-product-device',
- },
+ 'build.prop': common.PartitionBuildProps.FromDictionary(
+ 'system', {
+ 'ro.build.fingerprint': 'build-fingerprint',
+ 'ro.product.property_source_order':
+ 'product,odm,vendor,system_ext,system'}
+ ),
+ 'system.build.prop': common.PartitionBuildProps.FromDictionary(
+ 'system', {
+ 'ro.product.system.device': 'system-product-device'}
+ ),
+ 'vendor.build.prop': common.PartitionBuildProps.FromDictionary(
+ 'vendor', {
+ 'ro.product.vendor.device': 'vendor-product-device'}
+ ),
}
TEST_INFO_DICT_PROPERTY_SOURCE_ORDER_ANDROID_10 = {
- 'build.prop' : {
- 'ro.build.fingerprint' : 'build-fingerprint',
- 'ro.product.property_source_order' :
- 'product,product_services,odm,vendor,system',
- 'ro.build.version.release' : '10',
- 'ro.build.version.codename' : 'REL',
- },
- 'system.build.prop' : {
- 'ro.product.system.device' : 'system-product-device',
- },
- 'vendor.build.prop' : {
- 'ro.product.vendor.device' : 'vendor-product-device',
- },
+ 'build.prop': common.PartitionBuildProps.FromDictionary(
+ 'system', {
+ 'ro.build.fingerprint': 'build-fingerprint',
+ 'ro.product.property_source_order':
+ 'product,product_services,odm,vendor,system',
+ 'ro.build.version.release': '10',
+ 'ro.build.version.codename': 'REL'}
+ ),
+ 'system.build.prop': common.PartitionBuildProps.FromDictionary(
+ 'system', {
+ 'ro.product.system.device': 'system-product-device'}
+ ),
+ 'vendor.build.prop': common.PartitionBuildProps.FromDictionary(
+ 'vendor', {
+ 'ro.product.vendor.device': 'vendor-product-device'}
+ ),
}
TEST_INFO_DICT_PROPERTY_SOURCE_ORDER_ANDROID_9 = {
- 'build.prop' : {
- 'ro.product.device' : 'product-device',
- 'ro.build.fingerprint' : 'build-fingerprint',
- 'ro.build.version.release' : '9',
- 'ro.build.version.codename' : 'REL',
- },
- 'system.build.prop' : {
- 'ro.product.system.device' : 'system-product-device',
- },
- 'vendor.build.prop' : {
- 'ro.product.vendor.device' : 'vendor-product-device',
- },
+ 'build.prop': common.PartitionBuildProps.FromDictionary(
+ 'system', {
+ 'ro.product.device': 'product-device',
+ 'ro.build.fingerprint': 'build-fingerprint',
+ 'ro.build.version.release': '9',
+ 'ro.build.version.codename': 'REL'}
+ ),
+ 'system.build.prop': common.PartitionBuildProps.FromDictionary(
+ 'system', {
+ 'ro.product.system.device': 'system-product-device'}
+ ),
+ 'vendor.build.prop': common.PartitionBuildProps.FromDictionary(
+ 'vendor', {
+ 'ro.product.vendor.device': 'vendor-product-device'}
+ ),
}
def test_init(self):
@@ -177,25 +192,27 @@
def test_init_badFingerprint(self):
info_dict = copy.deepcopy(self.TEST_INFO_DICT)
- info_dict['build.prop']['ro.build.fingerprint'] = 'bad fingerprint'
+ info_dict['build.prop'].build_props[
+ 'ro.build.fingerprint'] = 'bad fingerprint'
self.assertRaises(ValueError, common.BuildInfo, info_dict, None)
- info_dict['build.prop']['ro.build.fingerprint'] = 'bad\x80fingerprint'
+ info_dict['build.prop'].build_props[
+ 'ro.build.fingerprint'] = 'bad\x80fingerprint'
self.assertRaises(ValueError, common.BuildInfo, info_dict, None)
def test___getitem__(self):
target_info = common.BuildInfo(self.TEST_INFO_DICT, None)
self.assertEqual('value1', target_info['property1'])
self.assertEqual(4096, target_info['property2'])
- self.assertEqual('build-foo', target_info['build.prop']['ro.build.foo'])
+ self.assertEqual('build-foo',
+ target_info['build.prop'].GetProp('ro.build.foo'))
def test___getitem__with_oem_props(self):
target_info = common.BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS,
self.TEST_OEM_DICTS)
self.assertEqual('value1', target_info['property1'])
self.assertEqual(4096, target_info['property2'])
- self.assertRaises(KeyError,
- lambda: target_info['build.prop']['ro.build.foo'])
+ self.assertIsNone(target_info['build.prop'].GetProp('ro.build.foo'))
def test___setitem__(self):
target_info = common.BuildInfo(copy.deepcopy(self.TEST_INFO_DICT), None)
@@ -203,9 +220,11 @@
target_info['property1'] = 'value2'
self.assertEqual('value2', target_info['property1'])
- self.assertEqual('build-foo', target_info['build.prop']['ro.build.foo'])
- target_info['build.prop']['ro.build.foo'] = 'build-bar'
- self.assertEqual('build-bar', target_info['build.prop']['ro.build.foo'])
+ self.assertEqual('build-foo',
+ target_info['build.prop'].GetProp('ro.build.foo'))
+ target_info['build.prop'].build_props['ro.build.foo'] = 'build-bar'
+ self.assertEqual('build-bar',
+ target_info['build.prop'].GetProp('ro.build.foo'))
def test_get(self):
target_info = common.BuildInfo(self.TEST_INFO_DICT, None)
@@ -213,7 +232,8 @@
self.assertEqual(4096, target_info.get('property2'))
self.assertEqual(4096, target_info.get('property2', 1024))
self.assertEqual(1024, target_info.get('property-nonexistent', 1024))
- self.assertEqual('build-foo', target_info.get('build.prop')['ro.build.foo'])
+ self.assertEqual('build-foo',
+ target_info.get('build.prop').GetProp('ro.build.foo'))
def test_get_with_oem_props(self):
target_info = common.BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS,
@@ -222,9 +242,7 @@
self.assertEqual(4096, target_info.get('property2'))
self.assertEqual(4096, target_info.get('property2', 1024))
self.assertEqual(1024, target_info.get('property-nonexistent', 1024))
- self.assertIsNone(target_info.get('build.prop').get('ro.build.foo'))
- self.assertRaises(KeyError,
- lambda: target_info.get('build.prop')['ro.build.foo'])
+ self.assertIsNone(target_info.get('build.prop').GetProp('ro.build.foo'))
def test_items(self):
target_info = common.BuildInfo(self.TEST_INFO_DICT, None)
@@ -261,7 +279,8 @@
def test_GetPartitionFingerprint_uses_fingerprint_prop_if_available(self):
info_dict = copy.deepcopy(self.TEST_INFO_DICT)
- info_dict['vendor.build.prop']['ro.vendor.build.fingerprint'] = 'vendor:fingerprint'
+ info_dict['vendor.build.prop'].build_props[
+ 'ro.vendor.build.fingerprint'] = 'vendor:fingerprint'
target_info = common.BuildInfo(info_dict, None)
self.assertEqual(
target_info.GetPartitionFingerprint('vendor'),
@@ -302,14 +321,15 @@
def test_ResolveRoProductProperty_FromSystem(self):
info_dict = copy.deepcopy(self.TEST_INFO_DICT_PROPERTY_SOURCE_ORDER)
- del info_dict['vendor.build.prop']['ro.product.vendor.device']
+ del info_dict['vendor.build.prop'].build_props['ro.product.vendor.device']
info = common.BuildInfo(info_dict, None)
self.assertEqual('system-product-device',
info.GetBuildProp('ro.product.device'))
def test_ResolveRoProductProperty_InvalidPropertySearchOrder(self):
info_dict = copy.deepcopy(self.TEST_INFO_DICT_PROPERTY_SOURCE_ORDER)
- info_dict['build.prop']['ro.product.property_source_order'] = 'bad-source'
+ info_dict['build.prop'].build_props[
+ 'ro.product.property_source_order'] = 'bad-source'
with self.assertRaisesRegexp(common.ExternalError,
'Invalid ro.product.property_source_order'):
info = common.BuildInfo(info_dict, None)
@@ -1792,3 +1812,241 @@
lines = self.get_op_list(self.output_path)
self.assertEqual(lines, ["remove foo"])
+
+
+class PartitionBuildPropsTest(test_utils.ReleaseToolsTestCase):
+ def setUp(self):
+ self.odm_build_prop = [
+ 'ro.odm.build.date.utc=1578430045',
+ 'ro.odm.build.fingerprint='
+ 'google/coral/coral:10/RP1A.200325.001/6337676:user/dev-keys',
+ 'ro.product.odm.device=coral',
+ 'import /odm/etc/build_${ro.boot.product.device_name}.prop',
+ ]
+
+ @staticmethod
+ def _BuildZipFile(entries):
+ input_file = common.MakeTempFile(prefix='target_files-', suffix='.zip')
+ with zipfile.ZipFile(input_file, 'w') as input_zip:
+ for name, content in entries.items():
+ input_zip.writestr(name, content)
+
+ return input_file
+
+ def test_parseBuildProps_noImportStatement(self):
+ build_prop = [
+ 'ro.odm.build.date.utc=1578430045',
+ 'ro.odm.build.fingerprint='
+ 'google/coral/coral:10/RP1A.200325.001/6337676:user/dev-keys',
+ 'ro.product.odm.device=coral',
+ ]
+ input_file = self._BuildZipFile({
+ 'ODM/etc/build.prop': '\n'.join(build_prop),
+ })
+
+ with zipfile.ZipFile(input_file, 'r') as input_zip:
+ placeholder_values = {
+ 'ro.boot.product.device_name': ['std', 'pro']
+ }
+ partition_props = common.PartitionBuildProps.FromInputFile(
+ input_zip, 'odm', placeholder_values)
+
+ self.assertEqual({
+ 'ro.odm.build.date.utc': '1578430045',
+ 'ro.odm.build.fingerprint':
+ 'google/coral/coral:10/RP1A.200325.001/6337676:user/dev-keys',
+ 'ro.product.odm.device': 'coral',
+ }, partition_props.build_props)
+
+ self.assertEqual(set(), partition_props.prop_overrides)
+
+ def test_parseBuildProps_singleImportStatement(self):
+ build_std_prop = [
+ 'ro.product.odm.device=coral',
+ 'ro.product.odm.name=product1',
+ ]
+ build_pro_prop = [
+ 'ro.product.odm.device=coralpro',
+ 'ro.product.odm.name=product2',
+ ]
+
+ input_file = self._BuildZipFile({
+ 'ODM/etc/build.prop': '\n'.join(self.odm_build_prop),
+ 'ODM/etc/build_std.prop': '\n'.join(build_std_prop),
+ 'ODM/etc/build_pro.prop': '\n'.join(build_pro_prop),
+ })
+
+ with zipfile.ZipFile(input_file, 'r') as input_zip:
+ placeholder_values = {
+ 'ro.boot.product.device_name': 'std'
+ }
+ partition_props = common.PartitionBuildProps.FromInputFile(
+ input_zip, 'odm', placeholder_values)
+
+ self.assertEqual({
+ 'ro.odm.build.date.utc': '1578430045',
+ 'ro.odm.build.fingerprint':
+ 'google/coral/coral:10/RP1A.200325.001/6337676:user/dev-keys',
+ 'ro.product.odm.device': 'coral',
+ 'ro.product.odm.name': 'product1',
+ }, partition_props.build_props)
+
+ with zipfile.ZipFile(input_file, 'r') as input_zip:
+ placeholder_values = {
+ 'ro.boot.product.device_name': 'pro'
+ }
+ partition_props = common.PartitionBuildProps.FromInputFile(
+ input_zip, 'odm', placeholder_values)
+
+ self.assertEqual({
+ 'ro.odm.build.date.utc': '1578430045',
+ 'ro.odm.build.fingerprint':
+ 'google/coral/coral:10/RP1A.200325.001/6337676:user/dev-keys',
+ 'ro.product.odm.device': 'coralpro',
+ 'ro.product.odm.name': 'product2',
+ }, partition_props.build_props)
+
+ def test_parseBuildProps_noPlaceHolders(self):
+ build_prop = copy.copy(self.odm_build_prop)
+ input_file = self._BuildZipFile({
+ 'ODM/etc/build.prop': '\n'.join(build_prop),
+ })
+
+ with zipfile.ZipFile(input_file, 'r') as input_zip:
+ partition_props = common.PartitionBuildProps.FromInputFile(
+ input_zip, 'odm')
+
+ self.assertEqual({
+ 'ro.odm.build.date.utc': '1578430045',
+ 'ro.odm.build.fingerprint':
+ 'google/coral/coral:10/RP1A.200325.001/6337676:user/dev-keys',
+ 'ro.product.odm.device': 'coral',
+ }, partition_props.build_props)
+
+ self.assertEqual(set(), partition_props.prop_overrides)
+
+ def test_parseBuildProps_multipleImportStatements(self):
+ build_prop = copy.deepcopy(self.odm_build_prop)
+ build_prop.append(
+ 'import /odm/etc/build_${ro.boot.product.product_name}.prop')
+
+ build_std_prop = [
+ 'ro.product.odm.device=coral',
+ ]
+ build_pro_prop = [
+ 'ro.product.odm.device=coralpro',
+ ]
+
+ product1_prop = [
+ 'ro.product.odm.name=product1',
+ 'ro.product.not_care=not_care',
+ ]
+
+ product2_prop = [
+ 'ro.product.odm.name=product2',
+ 'ro.product.not_care=not_care',
+ ]
+
+ input_file = self._BuildZipFile({
+ 'ODM/etc/build.prop': '\n'.join(build_prop),
+ 'ODM/etc/build_std.prop': '\n'.join(build_std_prop),
+ 'ODM/etc/build_pro.prop': '\n'.join(build_pro_prop),
+ 'ODM/etc/build_product1.prop': '\n'.join(product1_prop),
+ 'ODM/etc/build_product2.prop': '\n'.join(product2_prop),
+ })
+
+ with zipfile.ZipFile(input_file, 'r') as input_zip:
+ placeholder_values = {
+ 'ro.boot.product.device_name': 'std',
+ 'ro.boot.product.product_name': 'product1',
+ 'ro.boot.product.not_care': 'not_care',
+ }
+ partition_props = common.PartitionBuildProps.FromInputFile(
+ input_zip, 'odm', placeholder_values)
+
+ self.assertEqual({
+ 'ro.odm.build.date.utc': '1578430045',
+ 'ro.odm.build.fingerprint':
+ 'google/coral/coral:10/RP1A.200325.001/6337676:user/dev-keys',
+ 'ro.product.odm.device': 'coral',
+ 'ro.product.odm.name': 'product1'
+ }, partition_props.build_props)
+
+ with zipfile.ZipFile(input_file, 'r') as input_zip:
+ placeholder_values = {
+ 'ro.boot.product.device_name': 'pro',
+ 'ro.boot.product.product_name': 'product2',
+ 'ro.boot.product.not_care': 'not_care',
+ }
+ partition_props = common.PartitionBuildProps.FromInputFile(
+ input_zip, 'odm', placeholder_values)
+
+ self.assertEqual({
+ 'ro.odm.build.date.utc': '1578430045',
+ 'ro.odm.build.fingerprint':
+ 'google/coral/coral:10/RP1A.200325.001/6337676:user/dev-keys',
+ 'ro.product.odm.device': 'coralpro',
+ 'ro.product.odm.name': 'product2'
+ }, partition_props.build_props)
+
+ def test_parseBuildProps_defineAfterOverride(self):
+ build_prop = copy.deepcopy(self.odm_build_prop)
+ build_prop.append('ro.product.odm.device=coral')
+
+ build_std_prop = [
+ 'ro.product.odm.device=coral',
+ ]
+ build_pro_prop = [
+ 'ro.product.odm.device=coralpro',
+ ]
+
+ input_file = self._BuildZipFile({
+ 'ODM/etc/build.prop': '\n'.join(build_prop),
+ 'ODM/etc/build_std.prop': '\n'.join(build_std_prop),
+ 'ODM/etc/build_pro.prop': '\n'.join(build_pro_prop),
+ })
+
+ with zipfile.ZipFile(input_file, 'r') as input_zip:
+ placeholder_values = {
+ 'ro.boot.product.device_name': 'std',
+ }
+
+ self.assertRaises(ValueError, common.PartitionBuildProps.FromInputFile,
+ input_zip, 'odm', placeholder_values)
+
+ def test_parseBuildProps_duplicateOverride(self):
+ build_prop = copy.deepcopy(self.odm_build_prop)
+ build_prop.append(
+ 'import /odm/etc/build_${ro.boot.product.product_name}.prop')
+
+ build_std_prop = [
+ 'ro.product.odm.device=coral',
+ 'ro.product.odm.name=product1',
+ ]
+ build_pro_prop = [
+ 'ro.product.odm.device=coralpro',
+ ]
+
+ product1_prop = [
+ 'ro.product.odm.name=product1',
+ ]
+
+ product2_prop = [
+ 'ro.product.odm.name=product2',
+ ]
+
+ input_file = self._BuildZipFile({
+ 'ODM/etc/build.prop': '\n'.join(build_prop),
+ 'ODM/etc/build_std.prop': '\n'.join(build_std_prop),
+ 'ODM/etc/build_pro.prop': '\n'.join(build_pro_prop),
+ 'ODM/etc/build_product1.prop': '\n'.join(product1_prop),
+ 'ODM/etc/build_product2.prop': '\n'.join(product2_prop),
+ })
+
+ with zipfile.ZipFile(input_file, 'r') as input_zip:
+ placeholder_values = {
+ 'ro.boot.product.device_name': 'std',
+ 'ro.boot.product.product_name': 'product1',
+ }
+ self.assertRaises(ValueError, common.PartitionBuildProps.FromInputFile,
+ input_zip, 'odm', placeholder_values)
diff --git a/tools/releasetools/test_ota_from_target_files.py b/tools/releasetools/test_ota_from_target_files.py
index 38faf64..7783f96 100644
--- a/tools/releasetools/test_ota_from_target_files.py
+++ b/tools/releasetools/test_ota_from_target_files.py
@@ -26,7 +26,8 @@
GetPackageMetadata, GetTargetFilesZipForSecondaryImages,
GetTargetFilesZipWithoutPostinstallConfig, NonAbOtaPropertyFiles,
Payload, PayloadSigner, POSTINSTALL_CONFIG, PropertyFiles,
- StreamingPropertyFiles, WriteFingerprintAssertion)
+ StreamingPropertyFiles, WriteFingerprintAssertion,
+ CalculateRuntimeDevicesAndFingerprints)
def construct_target_files(secondary=False):
@@ -108,55 +109,58 @@
class OtaFromTargetFilesTest(test_utils.ReleaseToolsTestCase):
-
TEST_TARGET_INFO_DICT = {
- 'build.prop' : {
- 'ro.product.device' : 'product-device',
- 'ro.build.fingerprint' : 'build-fingerprint-target',
- 'ro.build.version.incremental' : 'build-version-incremental-target',
- 'ro.build.version.sdk' : '27',
- 'ro.build.version.security_patch' : '2017-12-01',
- 'ro.build.date.utc' : '1500000000',
- },
+ 'build.prop': common.PartitionBuildProps.FromDictionary(
+ 'system', {
+ 'ro.product.device': 'product-device',
+ 'ro.build.fingerprint': 'build-fingerprint-target',
+ 'ro.build.version.incremental': 'build-version-incremental-target',
+ 'ro.build.version.sdk': '27',
+ 'ro.build.version.security_patch': '2017-12-01',
+ 'ro.build.date.utc': '1500000000'}
+ )
}
TEST_SOURCE_INFO_DICT = {
- 'build.prop' : {
- 'ro.product.device' : 'product-device',
- 'ro.build.fingerprint' : 'build-fingerprint-source',
- 'ro.build.version.incremental' : 'build-version-incremental-source',
- 'ro.build.version.sdk' : '25',
- 'ro.build.version.security_patch' : '2016-12-01',
- 'ro.build.date.utc' : '1400000000',
- },
+ 'build.prop': common.PartitionBuildProps.FromDictionary(
+ 'system', {
+ 'ro.product.device': 'product-device',
+ 'ro.build.fingerprint': 'build-fingerprint-source',
+ 'ro.build.version.incremental': 'build-version-incremental-source',
+ 'ro.build.version.sdk': '25',
+ 'ro.build.version.security_patch': '2016-12-01',
+ 'ro.build.date.utc': '1400000000'}
+ )
}
TEST_INFO_DICT_USES_OEM_PROPS = {
- 'build.prop' : {
- 'ro.product.name' : 'product-name',
- 'ro.build.thumbprint' : 'build-thumbprint',
- 'ro.build.bar' : 'build-bar',
- },
- 'vendor.build.prop' : {
- 'ro.vendor.build.fingerprint' : 'vendor-build-fingerprint',
- },
- 'property1' : 'value1',
- 'property2' : 4096,
- 'oem_fingerprint_properties' : 'ro.product.device ro.product.brand',
+ 'build.prop': common.PartitionBuildProps.FromDictionary(
+ 'system', {
+ 'ro.product.name': 'product-name',
+ 'ro.build.thumbprint': 'build-thumbprint',
+ 'ro.build.bar': 'build-bar'}
+ ),
+ 'vendor.build.prop': common.PartitionBuildProps.FromDictionary(
+ 'vendor', {
+ 'ro.vendor.build.fingerprint': 'vendor-build-fingerprint'}
+ ),
+ 'property1': 'value1',
+ 'property2': 4096,
+ 'oem_fingerprint_properties': 'ro.product.device ro.product.brand',
}
TEST_OEM_DICTS = [
{
- 'ro.product.brand' : 'brand1',
- 'ro.product.device' : 'device1',
+ 'ro.product.brand': 'brand1',
+ 'ro.product.device': 'device1',
},
{
- 'ro.product.brand' : 'brand2',
- 'ro.product.device' : 'device2',
+ 'ro.product.brand': 'brand2',
+ 'ro.product.device': 'device2',
},
{
- 'ro.product.brand' : 'brand3',
- 'ro.product.device' : 'device3',
+ 'ro.product.brand': 'brand3',
+ 'ro.product.device': 'device3',
},
]
@@ -288,10 +292,10 @@
@staticmethod
def _test_GetPackageMetadata_swapBuildTimestamps(target_info, source_info):
- (target_info['build.prop']['ro.build.date.utc'],
- source_info['build.prop']['ro.build.date.utc']) = (
- source_info['build.prop']['ro.build.date.utc'],
- target_info['build.prop']['ro.build.date.utc'])
+ (target_info['build.prop'].build_props['ro.build.date.utc'],
+ source_info['build.prop'].build_props['ro.build.date.utc']) = (
+ source_info['build.prop'].build_props['ro.build.date.utc'],
+ target_info['build.prop'].build_props['ro.build.date.utc'])
def test_GetPackageMetadata_unintentionalDowngradeDetected(self):
target_info_dict = copy.deepcopy(self.TEST_TARGET_INFO_DICT)
@@ -528,7 +532,7 @@
def test_WriteFingerprintAssertion_without_oem_props(self):
target_info = common.BuildInfo(self.TEST_TARGET_INFO_DICT, None)
source_info_dict = copy.deepcopy(self.TEST_TARGET_INFO_DICT)
- source_info_dict['build.prop']['ro.build.fingerprint'] = (
+ source_info_dict['build.prop'].build_props['ro.build.fingerprint'] = (
'source-build-fingerprint')
source_info = common.BuildInfo(source_info_dict, None)
@@ -567,7 +571,7 @@
target_info = common.BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS,
self.TEST_OEM_DICTS)
source_info_dict = copy.deepcopy(self.TEST_INFO_DICT_USES_OEM_PROPS)
- source_info_dict['build.prop']['ro.build.thumbprint'] = (
+ source_info_dict['build.prop'].build_props['ro.build.thumbprint'] = (
'source-build-thumbprint')
source_info = common.BuildInfo(source_info_dict, self.TEST_OEM_DICTS)
@@ -1315,3 +1319,239 @@
Payload.SECONDARY_PAYLOAD_PROPERTIES_TXT):
continue
self.assertEqual(zipfile.ZIP_STORED, entry_info.compress_type)
+
+
+class RuntimeFingerprintTest(test_utils.ReleaseToolsTestCase):
+ MISC_INFO = [
+ 'recovery_api_version=3',
+ 'fstab_version=2',
+ 'recovery_as_boot=true',
+ ]
+
+ BUILD_PROP = [
+ 'ro.build.version.release=version-release',
+ 'ro.build.id=build-id',
+ 'ro.build.version.incremental=version-incremental',
+ 'ro.build.type=build-type',
+ 'ro.build.tags=build-tags',
+ 'ro.build.version.sdk=30',
+ 'ro.build.version.security_patch=2020',
+ 'ro.build.date.utc=12345678'
+ ]
+
+ VENDOR_BUILD_PROP = [
+ 'ro.product.vendor.brand=vendor-product-brand',
+ 'ro.product.vendor.name=vendor-product-name',
+ 'ro.product.vendor.device=vendor-product-device'
+ ]
+
+ def setUp(self):
+ common.OPTIONS.oem_dicts = None
+ self.test_dir = common.MakeTempDir()
+ self.writeFiles({'META/misc_info.txt': '\n'.join(self.MISC_INFO)},
+ self.test_dir)
+
+ def writeFiles(self, contents_dict, out_dir):
+ for path, content in contents_dict.items():
+ abs_path = os.path.join(out_dir, path)
+ dir_name = os.path.dirname(abs_path)
+ if not os.path.exists(dir_name):
+ os.makedirs(dir_name)
+ with open(abs_path, 'w') as f:
+ f.write(content)
+
+ @staticmethod
+ def constructFingerprint(prefix):
+ return '{}:version-release/build-id/version-incremental:' \
+ 'build-type/build-tags'.format(prefix)
+
+ def test_CalculatePossibleFingerprints_no_dynamic_fingerprint(self):
+ build_prop = copy.deepcopy(self.BUILD_PROP)
+ build_prop.extend([
+ 'ro.product.brand=product-brand',
+ 'ro.product.name=product-name',
+ 'ro.product.device=product-device',
+ ])
+ self.writeFiles({
+ 'SYSTEM/build.prop': '\n'.join(build_prop),
+ 'VENDOR/build.prop': '\n'.join(self.VENDOR_BUILD_PROP),
+ }, self.test_dir)
+
+ build_info = common.BuildInfo(common.LoadInfoDict(self.test_dir))
+ expected = ({'product-device'},
+ {self.constructFingerprint(
+ 'product-brand/product-name/product-device')})
+ self.assertEqual(expected,
+ CalculateRuntimeDevicesAndFingerprints(build_info, {}))
+
+ def test_CalculatePossibleFingerprints_single_override(self):
+ vendor_build_prop = copy.deepcopy(self.VENDOR_BUILD_PROP)
+ vendor_build_prop.extend([
+ 'import /vendor/etc/build_${ro.boot.sku_name}.prop',
+ ])
+ self.writeFiles({
+ 'SYSTEM/build.prop': '\n'.join(self.BUILD_PROP),
+ 'VENDOR/build.prop': '\n'.join(vendor_build_prop),
+ 'VENDOR/etc/build_std.prop':
+ 'ro.product.vendor.name=vendor-product-std',
+ 'VENDOR/etc/build_pro.prop':
+ 'ro.product.vendor.name=vendor-product-pro',
+ }, self.test_dir)
+
+ build_info = common.BuildInfo(common.LoadInfoDict(self.test_dir))
+ boot_variable_values = {'ro.boot.sku_name': ['std', 'pro']}
+
+ expected = ({'vendor-product-device'}, {
+ self.constructFingerprint(
+ 'vendor-product-brand/vendor-product-name/vendor-product-device'),
+ self.constructFingerprint(
+ 'vendor-product-brand/vendor-product-std/vendor-product-device'),
+ self.constructFingerprint(
+ 'vendor-product-brand/vendor-product-pro/vendor-product-device'),
+ })
+ self.assertEqual(
+ expected, CalculateRuntimeDevicesAndFingerprints(
+ build_info, boot_variable_values))
+
+ def test_CalculatePossibleFingerprints_multiple_overrides(self):
+ vendor_build_prop = copy.deepcopy(self.VENDOR_BUILD_PROP)
+ vendor_build_prop.extend([
+ 'import /vendor/etc/build_${ro.boot.sku_name}.prop',
+ 'import /vendor/etc/build_${ro.boot.device_name}.prop',
+ ])
+ self.writeFiles({
+ 'SYSTEM/build.prop': '\n'.join(self.BUILD_PROP),
+ 'VENDOR/build.prop': '\n'.join(vendor_build_prop),
+ 'VENDOR/etc/build_std.prop':
+ 'ro.product.vendor.name=vendor-product-std',
+ 'VENDOR/etc/build_product1.prop':
+ 'ro.product.vendor.device=vendor-device-product1',
+ 'VENDOR/etc/build_pro.prop':
+ 'ro.product.vendor.name=vendor-product-pro',
+ 'VENDOR/etc/build_product2.prop':
+ 'ro.product.vendor.device=vendor-device-product2',
+ }, self.test_dir)
+
+ build_info = common.BuildInfo(common.LoadInfoDict(self.test_dir))
+ boot_variable_values = {
+ 'ro.boot.sku_name': ['std', 'pro'],
+ 'ro.boot.device_name': ['product1', 'product2'],
+ }
+
+ expected_devices = {'vendor-product-device', 'vendor-device-product1',
+ 'vendor-device-product2'}
+ expected_fingerprints = {
+ self.constructFingerprint(
+ 'vendor-product-brand/vendor-product-name/vendor-product-device'),
+ self.constructFingerprint(
+ 'vendor-product-brand/vendor-product-std/vendor-device-product1'),
+ self.constructFingerprint(
+ 'vendor-product-brand/vendor-product-pro/vendor-device-product1'),
+ self.constructFingerprint(
+ 'vendor-product-brand/vendor-product-std/vendor-device-product2'),
+ self.constructFingerprint(
+ 'vendor-product-brand/vendor-product-pro/vendor-device-product2')
+ }
+ self.assertEqual((expected_devices, expected_fingerprints),
+ CalculateRuntimeDevicesAndFingerprints(
+ build_info, boot_variable_values))
+
+ def test_GetPackageMetadata_full_package(self):
+ vendor_build_prop = copy.deepcopy(self.VENDOR_BUILD_PROP)
+ vendor_build_prop.extend([
+ 'import /vendor/etc/build_${ro.boot.sku_name}.prop',
+ ])
+ self.writeFiles({
+ 'SYSTEM/build.prop': '\n'.join(self.BUILD_PROP),
+ 'VENDOR/build.prop': '\n'.join(vendor_build_prop),
+ 'VENDOR/etc/build_std.prop':
+ 'ro.product.vendor.name=vendor-product-std',
+ 'VENDOR/etc/build_pro.prop':
+ 'ro.product.vendor.name=vendor-product-pro',
+ }, self.test_dir)
+
+ common.OPTIONS.boot_variable_file = common.MakeTempFile()
+ with open(common.OPTIONS.boot_variable_file, 'w') as f:
+ f.write('ro.boot.sku_name=std,pro')
+
+ build_info = common.BuildInfo(common.LoadInfoDict(self.test_dir))
+ metadata = GetPackageMetadata(build_info)
+ self.assertEqual('vendor-product-device', metadata['pre-device'])
+ fingerprints = [
+ self.constructFingerprint(
+ 'vendor-product-brand/vendor-product-name/vendor-product-device'),
+ self.constructFingerprint(
+ 'vendor-product-brand/vendor-product-pro/vendor-product-device'),
+ self.constructFingerprint(
+ 'vendor-product-brand/vendor-product-std/vendor-product-device'),
+ ]
+ self.assertEqual('|'.join(fingerprints), metadata['post-build'])
+
+ def test_GetPackageMetadata_incremental_package(self):
+ vendor_build_prop = copy.deepcopy(self.VENDOR_BUILD_PROP)
+ vendor_build_prop.extend([
+ 'import /vendor/etc/build_${ro.boot.sku_name}.prop',
+ ])
+ self.writeFiles({
+ 'SYSTEM/build.prop': '\n'.join(self.BUILD_PROP),
+ 'VENDOR/build.prop': '\n'.join(vendor_build_prop),
+ 'VENDOR/etc/build_std.prop':
+ 'ro.product.vendor.device=vendor-device-std',
+ 'VENDOR/etc/build_pro.prop':
+ 'ro.product.vendor.device=vendor-device-pro',
+ }, self.test_dir)
+
+ common.OPTIONS.boot_variable_file = common.MakeTempFile()
+ with open(common.OPTIONS.boot_variable_file, 'w') as f:
+ f.write('ro.boot.sku_name=std,pro')
+
+ source_dir = common.MakeTempDir()
+ source_build_prop = [
+ 'ro.build.version.release=source-version-release',
+ 'ro.build.id=source-build-id',
+ 'ro.build.version.incremental=source-version-incremental',
+ 'ro.build.type=build-type',
+ 'ro.build.tags=build-tags',
+ 'ro.build.version.sdk=29',
+ 'ro.build.version.security_patch=2020',
+ 'ro.build.date.utc=12340000'
+ ]
+ self.writeFiles({
+ 'META/misc_info.txt': '\n'.join(self.MISC_INFO),
+ 'SYSTEM/build.prop': '\n'.join(source_build_prop),
+ 'VENDOR/build.prop': '\n'.join(vendor_build_prop),
+ 'VENDOR/etc/build_std.prop':
+ 'ro.product.vendor.device=vendor-device-std',
+ 'VENDOR/etc/build_pro.prop':
+ 'ro.product.vendor.device=vendor-device-pro',
+ }, source_dir)
+ common.OPTIONS.incremental_source = source_dir
+
+ target_info = common.BuildInfo(common.LoadInfoDict(self.test_dir))
+ source_info = common.BuildInfo(common.LoadInfoDict(source_dir))
+
+ metadata = GetPackageMetadata(target_info, source_info)
+ self.assertEqual(
+ 'vendor-device-pro|vendor-device-std|vendor-product-device',
+ metadata['pre-device'])
+ suffix = ':source-version-release/source-build-id/' \
+ 'source-version-incremental:build-type/build-tags'
+ pre_fingerprints = [
+ 'vendor-product-brand/vendor-product-name/vendor-device-pro'
+ '{}'.format(suffix),
+ 'vendor-product-brand/vendor-product-name/vendor-device-std'
+ '{}'.format(suffix),
+ 'vendor-product-brand/vendor-product-name/vendor-product-device'
+ '{}'.format(suffix),
+ ]
+ self.assertEqual('|'.join(pre_fingerprints), metadata['pre-build'])
+
+ post_fingerprints = [
+ self.constructFingerprint(
+ 'vendor-product-brand/vendor-product-name/vendor-device-pro'),
+ self.constructFingerprint(
+ 'vendor-product-brand/vendor-product-name/vendor-device-std'),
+ self.constructFingerprint(
+ 'vendor-product-brand/vendor-product-name/vendor-product-device'),
+ ]
+ self.assertEqual('|'.join(post_fingerprints), metadata['post-build'])
diff --git a/tools/releasetools/validate_target_files.py b/tools/releasetools/validate_target_files.py
index 1b918cc..69be511 100755
--- a/tools/releasetools/validate_target_files.py
+++ b/tools/releasetools/validate_target_files.py
@@ -352,8 +352,13 @@
cmd = [info_dict['avb_avbtool'], 'verify_image', '--image', image,
'--follow_chain_partitions']
+ # Custom images.
+ custom_partitions = info_dict.get(
+ "avb_custom_images_partition_list", "").strip().split()
+
# Append the args for chained partitions if any.
- for partition in common.AVB_PARTITIONS + common.AVB_VBMETA_PARTITIONS:
+ for partition in (common.AVB_PARTITIONS + common.AVB_VBMETA_PARTITIONS +
+ tuple(custom_partitions)):
key_name = 'avb_' + partition + '_key_path'
if info_dict.get(key_name) is not None:
if info_dict.get('ab_update') != 'true' and partition == 'recovery':
diff --git a/tools/releasetools/verity_utils.py b/tools/releasetools/verity_utils.py
index e7f84f5..fc83689 100644
--- a/tools/releasetools/verity_utils.py
+++ b/tools/releasetools/verity_utils.py
@@ -695,3 +695,22 @@
raise HashtreeInfoGenerationError("Failed to reconstruct the verity tree")
return self.hashtree_info
+
+
+def CreateCustomImageBuilder(info_dict, partition_name, partition_size,
+ key_path, algorithm, signing_args):
+ builder = None
+ if info_dict.get("avb_enable") == "true":
+ builder = VerifiedBootVersion2VerityImageBuilder(
+ partition_name,
+ partition_size,
+ VerifiedBootVersion2VerityImageBuilder.AVB_HASHTREE_FOOTER,
+ info_dict.get("avb_avbtool"),
+ key_path,
+ algorithm,
+ # Salt is None because custom images have no fingerprint property to be
+ # used as the salt.
+ None,
+ signing_args)
+
+ return builder