Merge "definitions.mk: Detect bad zip files."
diff --git a/core/Makefile b/core/Makefile
index b44d1d7..24302d4 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -206,7 +206,7 @@
@mkdir -p $(dir $@)
$(hide) grep -v "$(subst $(space),\|,$(strip \
$(sdk_build_prop_remove)))" $< > $@.tmp
- $(hide) for x in $(sdk_build_prop_remove); do \
+ $(hide) for x in $(strip $(sdk_build_prop_remove)); do \
echo "$$x"generic >> $@.tmp; done
$(hide) mv $@.tmp $@
@@ -320,11 +320,11 @@
define build-image-kernel-modules-depmod
$(3)/$(DEPMOD_STAGING_SUBDIR)/modules.dep: .KATI_IMPLICIT_OUTPUTS := $(3)/$(DEPMOD_STAGING_SUBDIR)/modules.alias $(3)/$(DEPMOD_STAGING_SUBDIR)/modules.softdep $(3)/$(DEPMOD_STAGING_SUBDIR)/$(5)
$(3)/$(DEPMOD_STAGING_SUBDIR)/modules.dep: $(DEPMOD)
-$(3)/$(DEPMOD_STAGING_SUBDIR)/modules.dep: PRIVATE_MODULES := $(1)
+$(3)/$(DEPMOD_STAGING_SUBDIR)/modules.dep: PRIVATE_MODULES := $(strip $(1))
$(3)/$(DEPMOD_STAGING_SUBDIR)/modules.dep: PRIVATE_MOUNT_POINT := $(2)
$(3)/$(DEPMOD_STAGING_SUBDIR)/modules.dep: PRIVATE_MODULE_DIR := $(3)/$(DEPMOD_STAGING_SUBDIR)/$(2)/lib/modules/$(8)
$(3)/$(DEPMOD_STAGING_SUBDIR)/modules.dep: PRIVATE_STAGING_DIR := $(3)
-$(3)/$(DEPMOD_STAGING_SUBDIR)/modules.dep: PRIVATE_LOAD_MODULES := $(4)
+$(3)/$(DEPMOD_STAGING_SUBDIR)/modules.dep: PRIVATE_LOAD_MODULES := $(strip $(4))
$(3)/$(DEPMOD_STAGING_SUBDIR)/modules.dep: PRIVATE_LOAD_FILE := $(3)/$(DEPMOD_STAGING_SUBDIR)/$(5)
$(3)/$(DEPMOD_STAGING_SUBDIR)/modules.dep: PRIVATE_MODULE_ARCHIVE := $(6)
$(3)/$(DEPMOD_STAGING_SUBDIR)/modules.dep: PRIVATE_OUTPUT_DIR := $(7)
@@ -2650,6 +2650,48 @@
endif # INSTALLED_BOOTIMAGE_TARGET
endif # BOARD_BUILD_SYSTEM_ROOT_IMAGE is not true
+ifeq ($(BUILDING_VENDOR_BOOT_IMAGE),true)
+ifeq ($(BUILDING_RAMDISK_IMAGE),true)
+# -----------------------------------------------------------------
+# vendor test harness ramdisk, which is a vendor ramdisk combined with
+# a test harness ramdisk.
+
+INTERNAL_VENDOR_TEST_HARNESS_RAMDISK_TARGET := $(call intermediates-dir-for,PACKAGING,vendor_boot-test-harness)/vendor_ramdisk-test-harness.cpio$(RAMDISK_EXT)
+
+# Exclude recovery files in the default vendor ramdisk if including a standalone
+# recovery ramdisk in vendor_boot.
+ifeq (true,$(BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT))
+ifneq (true,$(BOARD_INCLUDE_RECOVERY_RAMDISK_IN_VENDOR_BOOT))
+$(INTERNAL_VENDOR_TEST_HARNESS_RAMDISK_TARGET): $(INTERNAL_RECOVERY_RAMDISK_FILES_TIMESTAMP)
+$(INTERNAL_VENDOR_TEST_HARNESS_RAMDISK_TARGET): PRIVATE_ADDITIONAL_DIR := $(TARGET_RECOVERY_ROOT_OUT)
+endif
+endif
+
+# The vendor test harness ramdisk combines vendor ramdisk and test harness ramdisk.
+$(INTERNAL_VENDOR_TEST_HARNESS_RAMDISK_TARGET): $(INTERNAL_VENDOR_RAMDISK_TARGET) $(INSTALLED_TEST_HARNESS_RAMDISK_TARGET)
+$(INTERNAL_VENDOR_TEST_HARNESS_RAMDISK_TARGET): $(MKBOOTFS) | $(COMPRESSION_COMMAND_DEPS)
+ $(MKBOOTFS) -d $(TARGET_OUT) $(TARGET_VENDOR_RAMDISK_OUT) $(TARGET_TEST_HARNESS_RAMDISK_OUT) $(PRIVATE_ADDITIONAL_DIR) | $(COMPRESSION_COMMAND) > $@
+
+# -----------------------------------------------------------------
+# vendor_boot-test-harness.img.
+INSTALLED_VENDOR_TEST_HARNESS_BOOTIMAGE_TARGET := $(PRODUCT_OUT)/vendor_boot-test-harness.img
+
+ifneq ($(BOARD_AVB_VENDOR_BOOT_KEY_PATH),)
+$(INSTALLED_VENDOR_TEST_HARNESS_BOOTIMAGE_TARGET): $(AVBTOOL) $(BOARD_AVB_VENDOR_BOOT_TEST_KEY_PATH)
+endif
+
+# Depends on vendor_boot.img and vendor_ramdisk-test-harness.cpio$(RAMDISK_EXT) to build the new vendor_boot-test-harness.img
+$(INSTALLED_VENDOR_TEST_HARNESS_BOOTIMAGE_TARGET): $(MKBOOTIMG) $(INSTALLED_VENDOR_BOOTIMAGE_TARGET)
+$(INSTALLED_VENDOR_TEST_HARNESS_BOOTIMAGE_TARGET): $(INTERNAL_VENDOR_TEST_HARNESS_RAMDISK_TARGET)
+$(INSTALLED_VENDOR_TEST_HARNESS_BOOTIMAGE_TARGET): $(INTERNAL_VENDOR_RAMDISK_FRAGMENT_TARGETS)
+ $(call pretty,"Target vendor_boot test harness image: $@")
+ $(MKBOOTIMG) $(INTERNAL_VENDOR_BOOTIMAGE_ARGS) $(BOARD_MKBOOTIMG_ARGS) --vendor_ramdisk $(INTERNAL_VENDOR_TEST_HARNESS_RAMDISK_TARGET) $(INTERNAL_VENDOR_RAMDISK_FRAGMENT_ARGS) --vendor_boot $@
+ $(call assert-max-image-size,$@,$(BOARD_VENDOR_BOOTIMAGE_PARTITION_SIZE))
+ $(if $(BOARD_AVB_VENDOR_BOOT_KEY_PATH),$(call test-key-sign-vendor-bootimage,$@))
+
+endif # BUILDING_RAMDISK_IMAGE
+endif # BUILDING_VENDOR_BOOT_IMAGE
+
# Creates a compatibility symlink between two partitions, e.g. /system/vendor to /vendor
# $1: from location (e.g $(TARGET_OUT)/vendor)
# $2: destination location (e.g. /vendor)
@@ -4621,6 +4663,12 @@
ifneq ($(BOARD_PARTIAL_OTA_UPDATE_PARTITIONS_LIST),)
$(hide) echo "partial_ota_update_partitions_list=$(BOARD_PARTIAL_OTA_UPDATE_PARTITIONS_LIST)" >> $@
endif
+ifeq ($(BUILDING_WITH_VSDK),true)
+ $(hide) echo "building_with_vsdk=true" >> $@
+endif
+ifeq ($(TARGET_FLATTEN_APEX),false)
+ $(hide) echo "target_flatten_apex=false" >> $@
+endif
.PHONY: misc_info
misc_info: $(INSTALLED_MISC_INFO_TARGET)
@@ -5142,10 +5190,10 @@
ifeq ($(AB_OTA_UPDATER),true)
@# When using the A/B updater, include the updater config files in the zip.
$(hide) cp $(TOPDIR)system/update_engine/update_engine.conf $(zip_root)/META/update_engine_config.txt
- $(hide) for part in $(AB_OTA_PARTITIONS); do \
+ $(hide) for part in $(strip $(AB_OTA_PARTITIONS)); do \
echo "$${part}" >> $(zip_root)/META/ab_partitions.txt; \
done
- $(hide) for conf in $(AB_OTA_POSTINSTALL_CONFIG); do \
+ $(hide) for conf in $(strip $(AB_OTA_POSTINSTALL_CONFIG)); do \
echo "$${conf}" >> $(zip_root)/META/postinstall_config.txt; \
done
ifdef OSRELEASED_DIRECTORY
@@ -5942,7 +5990,7 @@
$(INTERNAL_SDK_TARGET): $(deps)
@echo "Package SDK: $@"
$(hide) rm -rf $(PRIVATE_DIR) $@
- $(hide) for f in $(target_gnu_MODULES); do \
+ $(hide) for f in $(strip $(target_gnu_MODULES)); do \
if [ -f $$f ]; then \
echo SDK: $(if $(SDK_GNU_ERROR),ERROR:,warning:) \
including GNU target $$f >&2; \
diff --git a/core/android_soong_config_vars.mk b/core/android_soong_config_vars.mk
index 7cd8489..fe97047 100644
--- a/core/android_soong_config_vars.mk
+++ b/core/android_soong_config_vars.mk
@@ -54,10 +54,7 @@
else ifneq (,$(SANITIZE_TARGET)$(SANITIZE_HOST))
# Prebuilts aren't built with sanitizers either.
SOONG_CONFIG_art_module_source_build := true
-else ifneq (,$(PRODUCT_FUCHSIA))
- # Fuchsia picks out ART internal packages that aren't available in the
- # prebuilt.
- SOONG_CONFIG_art_module_source_build := true
+ MODULE_BUILD_FROM_SOURCE := true
else ifeq (,$(filter x86 x86_64,$(HOST_CROSS_ARCH)))
# We currently only provide prebuilts for x86 on host. This skips prebuilts in
# cuttlefish builds for ARM servers.
diff --git a/core/dex_preopt_config.mk b/core/dex_preopt_config.mk
index 51238a3..0c806c1 100644
--- a/core/dex_preopt_config.mk
+++ b/core/dex_preopt_config.mk
@@ -104,11 +104,11 @@
$(call add_json_bool, DisableGenerateProfile, $(filter false,$(WITH_DEX_PREOPT_GENERATE_PROFILE)))
$(call add_json_str, ProfileDir, $(PRODUCT_DEX_PREOPT_PROFILE_DIR))
$(call add_json_list, BootJars, $(PRODUCT_BOOT_JARS))
- $(call add_json_list, UpdatableBootJars, $(PRODUCT_UPDATABLE_BOOT_JARS))
+ $(call add_json_list, ApexBootJars, $(PRODUCT_APEX_BOOT_JARS))
$(call add_json_list, ArtApexJars, $(filter $(PRODUCT_BOOT_JARS),$(ART_APEX_JARS)))
$(call add_json_list, SystemServerJars, $(PRODUCT_SYSTEM_SERVER_JARS))
$(call add_json_list, SystemServerApps, $(PRODUCT_SYSTEM_SERVER_APPS))
- $(call add_json_list, UpdatableSystemServerJars, $(PRODUCT_UPDATABLE_SYSTEM_SERVER_JARS))
+ $(call add_json_list, ApexSystemServerJars, $(PRODUCT_APEX_SYSTEM_SERVER_JARS))
$(call add_json_bool, BrokenSuboptimalOrderOfSystemServerJars, $(PRODUCT_BROKEN_SUBOPTIMAL_ORDER_OF_SYSTEM_SERVER_JARS))
$(call add_json_list, SpeedApps, $(PRODUCT_DEXPREOPT_SPEED_APPS))
$(call add_json_list, PreoptFlags, $(PRODUCT_DEX_PREOPT_DEFAULT_FLAGS))
diff --git a/core/dex_preopt_odex_install.mk b/core/dex_preopt_odex_install.mk
index fcdfa82..1d16eab 100644
--- a/core/dex_preopt_odex_install.mk
+++ b/core/dex_preopt_odex_install.mk
@@ -61,7 +61,7 @@
endif
# Don't preopt system server jars that are updatable.
-ifneq (,$(filter %:$(LOCAL_MODULE), $(PRODUCT_UPDATABLE_SYSTEM_SERVER_JARS)))
+ifneq (,$(filter %:$(LOCAL_MODULE), $(PRODUCT_APEX_SYSTEM_SERVER_JARS)))
LOCAL_DEX_PREOPT :=
endif
diff --git a/core/main.mk b/core/main.mk
index 21f4387..e0fb58d 100644
--- a/core/main.mk
+++ b/core/main.mk
@@ -120,6 +120,9 @@
ifndef SKIP_BOOT_JARS_CHECK
SKIP_BOOT_JARS_CHECK := true
endif
+# Mainline modules prebuilts do not support coverage. Build them from source.
+# See b/159241638
+MODULE_BUILD_FROM_SOURCE := true
endif
ifdef TARGET_ARCH_SUITE
@@ -355,7 +358,7 @@
ADDITIONAL_PRODUCT_PROPERTIES += ro.build.characteristics=$(TARGET_AAPT_CHARACTERISTICS)
ifeq ($(AB_OTA_UPDATER),true)
-ADDITIONAL_PRODUCT_PROPERTIES += ro.product.ab_ota_partitions=$(subst $(space),$(comma),$(AB_OTA_PARTITIONS))
+ADDITIONAL_PRODUCT_PROPERTIES += ro.product.ab_ota_partitions=$(subst $(space),$(comma),$(strip $(AB_OTA_PARTITIONS)))
endif
# -----------------------------------------------------------------
@@ -1239,14 +1242,43 @@
# Name resolution for LOCAL_REQUIRED_MODULES:
# See the select-bitness-of-required-modules definition.
# $(1): product makefile
+
+# TODO(asmundak):
+# `product-installed-files` and `host-installed-files` macros below used to
+# call `get-product-var` directly to obtain per-file configuration variable
+# values (the value of variable FOO is fetched from PRODUCT.<product-makefile>.FOO).
+# Starlark-based configuration does not maintain per-file variable variable
+# values. To work around this problem, we utilize the fact that
+# `product-installed-files` and `host-installed-files` are called only in
+# two places:
+# 1. For the top-level product makefile (in this file). In this case
+# $(call get-product-var <product>, FOO) is the same as $(FOO) as the
+# product configuration has been run already. Therefore we define
+# _product-var macro to pick the values directly from product config
+# variables when using Starlark-based configuration.
+# 2. To check the path requirements (in artifact_path_requirements.mk).
+# Starlark-based configuration does not perform this check at the moment.
+# In the longer run most of the logic of this file will be moved to the
+# Starlark.
+
+ifndef RBC_PRODUCT_CONFIG
+define _product-var
+ $(call get-product-var,$(1),$(2))
+endef
+else
+define _product-var
+ $(call $(2))
+endef
+endif
+
define product-installed-files
$(eval _pif_modules := \
- $(call get-product-var,$(1),PRODUCT_PACKAGES) \
- $(if $(filter eng,$(tags_to_install)),$(call get-product-var,$(1),PRODUCT_PACKAGES_ENG)) \
- $(if $(filter debug,$(tags_to_install)),$(call get-product-var,$(1),PRODUCT_PACKAGES_DEBUG)) \
- $(if $(filter tests,$(tags_to_install)),$(call get-product-var,$(1),PRODUCT_PACKAGES_TESTS)) \
- $(if $(filter asan,$(tags_to_install)),$(call get-product-var,$(1),PRODUCT_PACKAGES_DEBUG_ASAN)) \
- $(if $(filter java_coverage,$(tags_to_install)),$(call get-product-var,$(1),PRODUCT_PACKAGES_DEBUG_JAVA_COVERAGE)) \
+ $(call _product-var,$(1),PRODUCT_PACKAGES) \
+ $(if $(filter eng,$(tags_to_install)),$(call _product-var,$(1),PRODUCT_PACKAGES_ENG)) \
+ $(if $(filter debug,$(tags_to_install)),$(call _product-var,$(1),PRODUCT_PACKAGES_DEBUG)) \
+ $(if $(filter tests,$(tags_to_install)),$(call _product-var,$(1),PRODUCT_PACKAGES_TESTS)) \
+ $(if $(filter asan,$(tags_to_install)),$(call _product-var,$(1),PRODUCT_PACKAGES_DEBUG_ASAN)) \
+ $(if $(filter java_coverage,$(tags_to_install)),$(call _product-var,$(1),PRODUCT_PACKAGES_DEBUG_JAVA_COVERAGE)) \
$(call auto-included-modules) \
) \
$(eval ### Filter out the overridden packages and executables before doing expansion) \
@@ -1257,13 +1289,13 @@
$(call expand-required-modules,_pif_modules,$(_pif_modules),$(_pif_overrides)) \
$(filter-out $(HOST_OUT_ROOT)/%,$(call module-installed-files, $(_pif_modules))) \
$(call resolve-product-relative-paths,\
- $(foreach cf,$(call get-product-var,$(1),PRODUCT_COPY_FILES),$(call word-colon,2,$(cf))))
+ $(foreach cf,$(call _product-var,$(1),PRODUCT_COPY_FILES),$(call word-colon,2,$(cf))))
endef
# Similar to product-installed-files above, but handles PRODUCT_HOST_PACKAGES instead
# This does support the :32 / :64 syntax, but does not support module overrides.
define host-installed-files
- $(eval _hif_modules := $(call get-product-var,$(1),PRODUCT_HOST_PACKAGES)) \
+ $(eval _hif_modules := $(call _product-var,$(1),PRODUCT_HOST_PACKAGES)) \
$(eval ### Split host vs host cross modules) \
$(eval _hcif_modules := $(filter host_cross_%,$(_hif_modules))) \
$(eval _hif_modules := $(filter-out host_cross_%,$(_hif_modules))) \
@@ -1348,7 +1380,7 @@
# Verify the artifact path requirements made by included products.
is_asan := $(if $(filter address,$(SANITIZE_TARGET)),true)
- ifneq (true,$(or $(is_asan),$(DISABLE_ARTIFACT_PATH_REQUIREMENTS)))
+ ifeq (,$(or $(is_asan),$(DISABLE_ARTIFACT_PATH_REQUIREMENTS),$(RBC_PRODUCT_CONFIG)))
include $(BUILD_SYSTEM)/artifact_path_requirements.mk
endif
else
@@ -1534,6 +1566,9 @@
.PHONY: vendorbootimage_debug
vendorbootimage_debug: $(INSTALLED_VENDOR_DEBUG_BOOTIMAGE_TARGET)
+.PHONY: vendorbootimage_test_harness
+vendorbootimage_test_harness: $(INSTALLED_VENDOR_TEST_HARNESS_BOOTIMAGE_TARGET)
+
.PHONY: vendorramdisk
vendorramdisk: $(INSTALLED_VENDOR_RAMDISK_TARGET)
@@ -1599,6 +1634,7 @@
$(INSTALLED_VENDORIMAGE_TARGET) \
$(INSTALLED_VENDOR_BOOTIMAGE_TARGET) \
$(INSTALLED_VENDOR_DEBUG_BOOTIMAGE_TARGET) \
+ $(INSTALLED_VENDOR_TEST_HARNESS_BOOTIMAGE_TARGET) \
$(INSTALLED_VENDOR_RAMDISK_TARGET) \
$(INSTALLED_VENDOR_DEBUG_RAMDISK_TARGET) \
$(INSTALLED_ODMIMAGE_TARGET) \
@@ -1818,6 +1854,7 @@
$(INSTALLED_TEST_HARNESS_RAMDISK_TARGET) \
$(INSTALLED_TEST_HARNESS_BOOTIMAGE_TARGET) \
$(INSTALLED_VENDOR_DEBUG_BOOTIMAGE_TARGET) \
+ $(INSTALLED_VENDOR_TEST_HARNESS_BOOTIMAGE_TARGET) \
$(INSTALLED_VENDOR_RAMDISK_TARGET) \
$(INSTALLED_VENDOR_DEBUG_RAMDISK_TARGET) \
)
diff --git a/core/product-graph.mk b/core/product-graph.mk
index 968d01b..de4e581 100644
--- a/core/product-graph.mk
+++ b/core/product-graph.mk
@@ -81,6 +81,7 @@
$(products_graph): PRIVATE_PRODUCTS_FILTER := $(products_list)
$(products_graph): $(this_makefile)
+ifeq (,$(RBC_PRODUCT_CONFIG)$(RBC_NO_PRODUCT_GRAPH))
@echo Product graph DOT: $@ for $(PRIVATE_PRODUCTS_FILTER)
$(hide) echo 'digraph {' > $@.in
$(hide) echo 'graph [ ratio=.5 ];' >> $@.in
@@ -89,6 +90,10 @@
$(foreach p,$(PRIVATE_PRODUCTS),$(call emit-product-node-props,$(p),$@.in))
$(hide) echo '}' >> $@.in
$(hide) build/make/tools/filter-product-graph.py $(PRIVATE_PRODUCTS_FILTER) < $@.in > $@
+else
+ @echo RBC_PRODUCT_CONFIG and RBC_NO_PRODUCT_GRAPH should be unset to generate product graph
+ false
+endif
# Evaluates to the name of the product file
# $(1) product file
@@ -143,6 +148,7 @@
$(hide) cat $$< | build/make/tools/product_debug.py > $$@
endef
+ifeq (,$(RBC_PRODUCT_CONFIG)$(RBC_NO_PRODUCT_GRAPH))
product_debug_files:=
$(foreach p,$(all_products), \
$(eval $(call transform-product-debug, $(p))) \
@@ -154,3 +160,8 @@
@echo Product graph .dot file: $(products_graph)
@echo Command to convert to pdf: dot -Tpdf -Nshape=box -o $(OUT_DIR)/products.pdf $(products_graph)
@echo Command to convert to svg: dot -Tsvg -Nshape=box -o $(OUT_DIR)/products.svg $(products_graph)
+else
+.PHONY: product-graph
+ @echo RBC_PRODUCT_CONFIG and RBC_NO_PRODUCT_GRAPH should be unset to generate product graph
+ false
+endif
\ No newline at end of file
diff --git a/core/product.mk b/core/product.mk
index 7e8445e..f6347e8 100644
--- a/core/product.mk
+++ b/core/product.mk
@@ -234,7 +234,7 @@
_product_list_vars += PRODUCT_SYSTEM_SERVER_APPS
_product_list_vars += PRODUCT_SYSTEM_SERVER_JARS
# List of system_server jars delivered via apex. Format = <apex name>:<jar name>.
-_product_list_vars += PRODUCT_UPDATABLE_SYSTEM_SERVER_JARS
+_product_list_vars += PRODUCT_APEX_SYSTEM_SERVER_JARS
# If true, then suboptimal order of system server jars does not cause an error.
_product_single_value_vars += PRODUCT_BROKEN_SUBOPTIMAL_ORDER_OF_SYSTEM_SERVER_JARS
@@ -374,7 +374,7 @@
# A list of <overridden-apex>:<override-apex> pairs that specifies APEX module
# overrides to be applied to the APEX names in the boot jar variables
-# (PRODUCT_BOOT_JARS, PRODUCT_UPDATABLE_BOOT_JARS etc).
+# (PRODUCT_BOOT_JARS, PRODUCT_APEX_BOOT_JARS etc).
_product_list_vars += PRODUCT_BOOT_JAR_MODULE_OVERRIDES
# Controls for whether different partitions are built for the current product.
@@ -397,7 +397,7 @@
# List of boot jars delivered via updatable APEXes, following the same format as
# PRODUCT_BOOT_JARS.
-_product_list_vars += PRODUCT_UPDATABLE_BOOT_JARS
+_product_list_vars += PRODUCT_APEX_BOOT_JARS
# If set, device uses virtual A/B.
_product_single_value_vars += PRODUCT_VIRTUAL_AB_OTA
diff --git a/core/product_config.mk b/core/product_config.mk
index 53bc9dd..403c6be 100644
--- a/core/product_config.mk
+++ b/core/product_config.mk
@@ -77,6 +77,16 @@
$(sort $(shell find $(2) -name "$(1)" -type f | $(SED_EXTENDED) "s:($(2)/?(.*)):\\1\\:$(3)/\\2:" | sed "s://:/:g"))
endef
+#
+# Convert file file to the PRODUCT_COPY_FILES/PRODUCT_SDK_ADDON_COPY_FILES
+# format: for each file F return $(F):$(PREFIX)/$(notdir $(F))
+# $(1): files list
+# $(2): prefix
+
+define copy-files
+$(foreach f,$(1),$(f):$(2)/$(notdir $(f)))
+endef
+
# ---------------------------------------------------------------
# Check for obsolete PRODUCT- and APP- goals
ifeq ($(CALLED_FROM_SETUP),true)
@@ -162,11 +172,24 @@
ifneq (1,$(words $(current_product_makefile)))
$(error Product "$(TARGET_PRODUCT)" ambiguous: matches $(current_product_makefile))
endif
+
+ifndef RBC_PRODUCT_CONFIG
$(call import-products, $(current_product_makefile))
+else
+ rbcscript=build/soong/scripts/rbc-run
+ rc := $(shell $(rbcscript) $(TARGET_PRODUCT)-$(TARGET_BUILD_VARIANT) >$(OUT_DIR)/rbctemp.mk || echo $$?)
+ ifneq (,$(rc))
+ $(error product configuration converter failed: $(rc))
+ endif
+ include $(OUT_DIR)/rbctemp.mk
+ PRODUCTS += $(current_product_makefile)
+endif
endif # Import all or just the current product makefile
+ifndef RBC_PRODUCT_CONFIG
# Quick check
$(check-all-products)
+endif
ifeq ($(SKIP_ARTIFACT_PATH_REQUIREMENT_PRODUCTS_CHECK),)
# Import all the products that have made artifact path requirements, so that we can verify
@@ -186,6 +209,7 @@
$(dump-products)
endif
+ifndef RBC_PRODUCT_CONFIG
# Convert a short name like "sooner" into the path to the product
# file defining that product.
#
@@ -198,6 +222,9 @@
############################################################################
# Strip and assign the PRODUCT_ variables.
$(call strip-product-vars)
+else
+INTERNAL_PRODUCT := $(current_product_makefile)
+endif
current_product_makefile :=
all_product_makefiles :=
@@ -252,9 +279,9 @@
# b/191127295: force core-icu4j onto boot image. It comes from a non-updatable APEX jar, but has
# historically been part of the boot image; even though APEX jars are not meant to be part of the
# boot image.
-# TODO(b/191686720): remove PRODUCT_UPDATABLE_BOOT_JARS to avoid a special handling of core-icu4j
+# TODO(b/191686720): remove PRODUCT_APEX_BOOT_JARS to avoid a special handling of core-icu4j
# in make rules.
-PRODUCT_UPDATABLE_BOOT_JARS := $(filter-out com.android.i18n:core-icu4j,$(PRODUCT_UPDATABLE_BOOT_JARS))
+PRODUCT_APEX_BOOT_JARS := $(filter-out com.android.i18n:core-icu4j,$(PRODUCT_APEX_BOOT_JARS))
# All APEX jars come after /system and /system_ext jars, so adding core-icu4j at the end of the list
PRODUCT_BOOT_JARS += com.android.i18n:core-icu4j
@@ -268,7 +295,7 @@
endef
$(call replace-boot-jar-module-overrides,PRODUCT_BOOT_JARS)
-$(call replace-boot-jar-module-overrides,PRODUCT_UPDATABLE_BOOT_JARS)
+$(call replace-boot-jar-module-overrides,PRODUCT_APEX_BOOT_JARS)
$(call replace-boot-jar-module-overrides,ART_APEX_JARS)
# The extra system server jars must be appended at the end after common system server jars.
@@ -312,10 +339,10 @@
endif
endif
-$(foreach pair,$(PRODUCT_UPDATABLE_BOOT_JARS), \
+$(foreach pair,$(PRODUCT_APEX_BOOT_JARS), \
$(eval jar := $(call word-colon,2,$(pair))) \
$(if $(findstring $(jar), $(PRODUCT_BOOT_JARS)), \
- $(error A jar in PRODUCT_UPDATABLE_BOOT_JARS must not be in PRODUCT_BOOT_JARS, but $(jar) is)))
+ $(error A jar in PRODUCT_APEX_BOOT_JARS must not be in PRODUCT_BOOT_JARS, but $(jar) is)))
ENFORCE_SYSTEM_CERTIFICATE := $(PRODUCT_ENFORCE_ARTIFACT_SYSTEM_CERTIFICATE_REQUIREMENT)
ENFORCE_SYSTEM_CERTIFICATE_ALLOW_LIST := $(PRODUCT_ARTIFACT_SYSTEM_CERTIFICATE_REQUIREMENT_ALLOW_LIST)
diff --git a/core/product_config.rbc b/core/product_config.rbc
index 8e85c4b..3714448 100644
--- a/core/product_config.rbc
+++ b/core/product_config.rbc
@@ -16,6 +16,7 @@
"""Runtime functions."""
+_soong_config_namespaces_key = "$SOONG_CONFIG_NAMESPACES"
def _global_init():
"""Returns dict created from the runtime environment."""
globals = dict()
@@ -29,6 +30,7 @@
globals[k] = getattr(rblf_cli, k)
globals.setdefault("PRODUCT_SOONG_NAMESPACES", [])
+ globals.setdefault(_soong_config_namespaces_key, {})
_envsetup_init(globals)
# Variables that should be defined.
@@ -74,7 +76,16 @@
if _options.print_globals:
print()
for attr, val in sorted(globals.items()):
- if attr not in _globals_base:
+ if attr == _soong_config_namespaces_key:
+ __print_attr("SOONG_CONFIG_NAMESPACES", val.keys())
+ for nsname, nsvars in sorted(val.items()):
+ # Define SOONG_CONFIG_<ns> for Make, othewise
+ # it cannot be added to .KATI_READONLY list
+ if _options.format == "make":
+ print("SOONG_CONFIG_" + nsname, ":=")
+ for var, val in sorted(nsvars.items()):
+ __print_attr("SOONG_CONFIG_%s_%s" % (nsname, var), val)
+ elif attr not in _globals_base:
__print_attr(attr, val)
def __printvars_rearrange_list(value_list):
@@ -268,6 +279,20 @@
"""Returns configuration item for the inherited module."""
return (pcm_name,)
+def _add_soong_config_namespace(g, nsname):
+ """Adds given namespace."""
+
+ # A value cannot be updated, so we need to create a new dictionary
+ old = g[_soong_config_namespaces_key]
+ g[_soong_config_namespaces_key] = dict([(k,v) for k,v in old.items()] + [(nsname, {})])
+
+def _add_soong_config_var_value(g, nsname, var, value):
+ """Defines a variable and adds it to the given namespace."""
+ ns = g[_soong_config_namespaces_key].get(nsname)
+ if ns == None:
+ fail("no such namespace: " + nsname)
+ ns[var] = value
+
def _addprefix(prefix, string_or_list):
"""Adds prefix and returns a list.
@@ -348,6 +373,10 @@
if type(val) == "list":
val.append(_indirect(pcm_name))
+def _copy_files(l, outdir):
+ """Generate <item>:<outdir>/item for each item."""
+ return ["%s:%s/%s" % (item, outdir, item) for item in __words(l)]
+
def _copy_if_exists(path_pair):
"""If from file exists, returns [from:to] pair."""
value = path_pair.split(":", 2)
@@ -523,8 +552,11 @@
# Settings used during debugging.
_options = __get_options()
rblf = struct(
+ add_soong_config_namespace = _add_soong_config_namespace,
+ add_soong_config_var_value = _add_soong_config_var_value,
addprefix = _addprefix,
addsuffix = _addsuffix,
+ copy_files = _copy_files,
copy_if_exists = _copy_if_exists,
cfg = __h_cfg,
enforce_product_packages_exist = _enforce_product_packages_exist,
diff --git a/core/soong_config.mk b/core/soong_config.mk
index 1d94661..d3f983c 100644
--- a/core/soong_config.mk
+++ b/core/soong_config.mk
@@ -142,7 +142,7 @@
$(call add_json_list, ModulesLoadedByPrivilegedModules, $(PRODUCT_LOADED_BY_PRIVILEGED_MODULES))
$(call add_json_list, BootJars, $(PRODUCT_BOOT_JARS))
-$(call add_json_list, UpdatableBootJars, $(PRODUCT_UPDATABLE_BOOT_JARS))
+$(call add_json_list, ApexBootJars, $(PRODUCT_APEX_BOOT_JARS))
$(call add_json_bool, VndkUseCoreVariant, $(TARGET_VNDK_USE_CORE_VARIANT))
$(call add_json_bool, VndkSnapshotBuildArtifacts, $(VNDK_SNAPSHOT_BUILD_ARTIFACTS))
diff --git a/core/sysprop.mk b/core/sysprop.mk
index be9b1f8..1d38f8c 100644
--- a/core/sysprop.mk
+++ b/core/sysprop.mk
@@ -430,7 +430,7 @@
$(eval $(call build-properties,\
odm,\
$(INSTALLED_ODM_BUILD_PROP_TARGET),\
- $(_prop_files),\
+ $(_prop_files_),\
$(_prop_vars_),\
$(empty),\
$(empty),\
diff --git a/core/tasks/OWNERS b/core/tasks/OWNERS
new file mode 100644
index 0000000..594930d
--- /dev/null
+++ b/core/tasks/OWNERS
@@ -0,0 +1 @@
+per-file art-host-tests.mk = dshi@google.com,dsrbecky@google.com,jdesprez@google.com,rpl@google.com
diff --git a/core/tasks/art-host-tests.mk b/core/tasks/art-host-tests.mk
index d771b06..b9a349d 100644
--- a/core/tasks/art-host-tests.mk
+++ b/core/tasks/art-host-tests.mk
@@ -29,6 +29,7 @@
$(art_host_tests_zip) : $(COMPATIBILITY.art-host-tests.FILES) $(my_host_shared_lib_for_art_host_tests) $(SOONG_ZIP)
echo $(sort $(COMPATIBILITY.art-host-tests.FILES)) | tr " " "\n" > $@.list
grep $(HOST_OUT_TESTCASES) $@.list > $@-host.list || true
+ $(hide) touch $@-host-libs.list
$(hide) for shared_lib in $(PRIVATE_HOST_SHARED_LIBS); do \
echo $$shared_lib >> $@-host-libs.list; \
done
diff --git a/core/version_defaults.mk b/core/version_defaults.mk
index 8e6c306..530bbff 100644
--- a/core/version_defaults.mk
+++ b/core/version_defaults.mk
@@ -94,7 +94,7 @@
# These are the current development codenames, if the build is not a final
# release build. If this is a final release build, it is simply "REL".
PLATFORM_VERSION_CODENAME.SP1A := S
-PLATFORM_VERSION_CODENAME.TP1A := T
+PLATFORM_VERSION_CODENAME.TP1A := Tiramisu
ifndef PLATFORM_VERSION_CODENAME
PLATFORM_VERSION_CODENAME := $(PLATFORM_VERSION_CODENAME.$(TARGET_PLATFORM_VERSION))
@@ -241,7 +241,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 := 2021-07-05
+ PLATFORM_SECURITY_PATCH := 2021-08-05
endif
.KATI_READONLY := PLATFORM_SECURITY_PATCH
diff --git a/target/board/BoardConfigGkiCommon.mk b/target/board/BoardConfigGkiCommon.mk
index 5173012..c0f5db9 100644
--- a/target/board/BoardConfigGkiCommon.mk
+++ b/target/board/BoardConfigGkiCommon.mk
@@ -22,6 +22,9 @@
# See b/178559811 for more details.
BOARD_GKI_SIGNING_SIGNATURE_ARGS := --prop foo:bar
+# Sets boot SPL.
+BOOT_SECURITY_PATCH = $(PLATFORM_SECURITY_PATCH)
+
# Boot image with ramdisk and kernel
BOARD_RAMDISK_USE_LZ4 := true
BOARD_BOOT_HEADER_VERSION := 4
diff --git a/target/product/default_art_config.mk b/target/product/default_art_config.mk
index 8c249b2..82f86fc 100644
--- a/target/product/default_art_config.mk
+++ b/target/product/default_art_config.mk
@@ -27,7 +27,7 @@
#
# ART APEX jars (1) are defined in ART_APEX_JARS. System, system_ext, and non updatable boot jars
# are defined below in PRODUCT_BOOT_JARS. All updatable APEX boot jars are part of
-# PRODUCT_UPDATABLE_BOOT_JARS.
+# PRODUCT_APEX_BOOT_JARS.
#
# The actual runtime ordering matching above is determined by derive_classpath service at runtime.
# See packages/modules/SdkExtensions/README.md for more details.
@@ -46,7 +46,7 @@
# APEX boot jars. Keep the list sorted by module names and then library names.
# Note: core-icu4j is moved back to PRODUCT_BOOT_JARS in product_config.mk at a later stage.
-PRODUCT_UPDATABLE_BOOT_JARS := \
+PRODUCT_APEX_BOOT_JARS := \
com.android.conscrypt:conscrypt \
com.android.i18n:core-icu4j \
com.android.ipsec:android.net.ipsec.ike \
@@ -59,7 +59,7 @@
com.android.wifi:framework-wifi
# APEX system server jars. Keep the list sorted by module names and then library names.
-PRODUCT_UPDATABLE_SYSTEM_SERVER_JARS := \
+PRODUCT_APEX_SYSTEM_SERVER_JARS := \
com.android.art:service-art \
com.android.permission:service-permission \
diff --git a/target/product/emulator_vendor.mk b/target/product/emulator_vendor.mk
index 4d46358..e6db0f8 100644
--- a/target/product/emulator_vendor.mk
+++ b/target/product/emulator_vendor.mk
@@ -37,7 +37,7 @@
#watchdog tiggers reboot because location service is not
#responding, disble it for now.
-#still keep it on internal master as it is still working
+#still keep it on internal main (master) as it is still working
#once it is fixed in aosp, remove this block of comment.
#PRODUCT_VENDOR_PROPERTIES += \
#config.disable_location=true
diff --git a/target/product/gsi/Android.mk b/target/product/gsi/Android.mk
index cb4fdcb..39848e5 100644
--- a/target/product/gsi/Android.mk
+++ b/target/product/gsi/Android.mk
@@ -237,6 +237,6 @@
LOCAL_SRC_FILES := $(LOCAL_MODULE)
LOCAL_MODULE_CLASS := ETC
LOCAL_SYSTEM_EXT_MODULE := true
-LOCAL_MODULE_RELATIVE_PATH := init
+LOCAL_MODULE_RELATIVE_PATH := gsi
include $(BUILD_PREBUILT)
diff --git a/target/product/gsi/current.txt b/target/product/gsi/current.txt
index c753e6c..6f4b7f1 100644
--- a/target/product/gsi/current.txt
+++ b/target/product/gsi/current.txt
@@ -18,8 +18,11 @@
LLNDK: libsync.so
LLNDK: libvndksupport.so
LLNDK: libvulkan.so
+VNDK-SP: android.hardware.common-V2-ndk.so
VNDK-SP: android.hardware.common-V2-ndk_platform.so
+VNDK-SP: android.hardware.common.fmq-V1-ndk.so
VNDK-SP: android.hardware.common.fmq-V1-ndk_platform.so
+VNDK-SP: android.hardware.graphics.common-V2-ndk.so
VNDK-SP: android.hardware.graphics.common-V2-ndk_platform.so
VNDK-SP: android.hardware.graphics.common@1.0.so
VNDK-SP: android.hardware.graphics.common@1.1.so
@@ -57,7 +60,9 @@
VNDK-SP: libutilscallstack.so
VNDK-SP: libz.so
VNDK-core: android.hardware.audio.common@2.0.so
+VNDK-core: android.hardware.authsecret-V1-ndk.so
VNDK-core: android.hardware.authsecret-V1-ndk_platform.so
+VNDK-core: android.hardware.automotive.occupant_awareness-V1-ndk.so
VNDK-core: android.hardware.automotive.occupant_awareness-V1-ndk_platform.so
VNDK-core: android.hardware.configstore-utils.so
VNDK-core: android.hardware.configstore@1.0.so
@@ -68,29 +73,46 @@
VNDK-core: android.hardware.graphics.allocator@4.0.so
VNDK-core: android.hardware.graphics.bufferqueue@1.0.so
VNDK-core: android.hardware.graphics.bufferqueue@2.0.so
+VNDK-core: android.hardware.health.storage-V1-ndk.so
VNDK-core: android.hardware.health.storage-V1-ndk_platform.so
+VNDK-core: android.hardware.identity-V2-ndk.so
VNDK-core: android.hardware.identity-V2-ndk_platform.so
+VNDK-core: android.hardware.keymaster-V2-ndk.so
VNDK-core: android.hardware.keymaster-V2-ndk_platform.so
+VNDK-core: android.hardware.light-V1-ndk.so
VNDK-core: android.hardware.light-V1-ndk_platform.so
VNDK-core: android.hardware.media.bufferpool@2.0.so
VNDK-core: android.hardware.media.omx@1.0.so
VNDK-core: android.hardware.media@1.0.so
+VNDK-core: android.hardware.memtrack-V1-ndk.so
VNDK-core: android.hardware.memtrack-V1-ndk_platform.so
VNDK-core: android.hardware.memtrack@1.0.so
+VNDK-core: android.hardware.oemlock-V1-ndk.so
VNDK-core: android.hardware.oemlock-V1-ndk_platform.so
+VNDK-core: android.hardware.power-V1-ndk.so
VNDK-core: android.hardware.power-V1-ndk_platform.so
+VNDK-core: android.hardware.power.stats-V1-ndk.so
VNDK-core: android.hardware.power.stats-V1-ndk_platform.so
+VNDK-core: android.hardware.rebootescrow-V1-ndk.so
VNDK-core: android.hardware.rebootescrow-V1-ndk_platform.so
+VNDK-core: android.hardware.security.keymint-V1-ndk.so
VNDK-core: android.hardware.security.keymint-V1-ndk_platform.so
+VNDK-core: android.hardware.security.secureclock-V1-ndk.so
VNDK-core: android.hardware.security.secureclock-V1-ndk_platform.so
+VNDK-core: android.hardware.security.sharedsecret-V1-ndk.so
VNDK-core: android.hardware.security.sharedsecret-V1-ndk_platform.so
VNDK-core: android.hardware.soundtrigger@2.0-core.so
VNDK-core: android.hardware.soundtrigger@2.0.so
+VNDK-core: android.hardware.vibrator-V1-ndk.so
VNDK-core: android.hardware.vibrator-V1-ndk_platform.so
+VNDK-core: android.hardware.weaver-V1-ndk.so
VNDK-core: android.hardware.weaver-V1-ndk_platform.so
VNDK-core: android.hidl.token@1.0-utils.so
VNDK-core: android.hidl.token@1.0.so
+VNDK-core: android.system.keystore2-V1-ndk.so
VNDK-core: android.system.keystore2-V1-ndk_platform.so
+VNDK-core: android.system.suspend-V1-ndk.so
+VNDK-core: android.system.suspend-V1-ndk_platform.so
VNDK-core: android.system.suspend@1.0.so
VNDK-core: libaudioroute.so
VNDK-core: libaudioutils.so
diff --git a/target/product/gsi/init.gsi.rc b/target/product/gsi/init.gsi.rc
index f482843..69c8e46 100644
--- a/target/product/gsi/init.gsi.rc
+++ b/target/product/gsi/init.gsi.rc
@@ -2,4 +2,4 @@
# Android init script for GSI required initialization
#
-import /system/system_ext/etc/init/init.vndk-${ro.vndk.version:-nodef}.rc
+import /system/system_ext/etc/gsi/init.vndk-${ro.vndk.version:-nodef}.rc
diff --git a/target/product/gsi/init.vndk-nodef.rc b/target/product/gsi/init.vndk-nodef.rc
index efeef11..1b141a0 100644
--- a/target/product/gsi/init.vndk-nodef.rc
+++ b/target/product/gsi/init.vndk-nodef.rc
@@ -1,3 +1,3 @@
on early-init
- # Must define BOARD_VNDK_VERSION
+ # Reboot if BOARD_VNDK_VERSION is not defined
exec - root -- /system/bin/reboot bootloader
diff --git a/target/product/gsi_release.mk b/target/product/gsi_release.mk
index 8591a83..d924d0b 100644
--- a/target/product/gsi_release.mk
+++ b/target/product/gsi_release.mk
@@ -71,3 +71,6 @@
PRODUCT_BUILD_VENDOR_IMAGE := false
PRODUCT_BUILD_SUPER_PARTITION := false
PRODUCT_BUILD_SUPER_EMPTY_IMAGE := false
+
+# Always build modules from source
+MODULE_BUILD_FROM_SOURCE := true
diff --git a/target/product/iorap_large_memory_config.mk b/target/product/iorap_large_memory_config.mk
index 9aa6642..0c6c89a 100644
--- a/target/product/iorap_large_memory_config.mk
+++ b/target/product/iorap_large_memory_config.mk
@@ -12,7 +12,3 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
-
-# Disable Camera pinner by default
-PRODUCT_PRODUCT_PROPERTIES += \
- pinner.pin_camera=false
diff --git a/target/product/virtual_ab_ota/compression_with_xor.mk b/target/product/virtual_ab_ota/compression_with_xor.mk
new file mode 100644
index 0000000..7d92532
--- /dev/null
+++ b/target/product/virtual_ab_ota/compression_with_xor.mk
@@ -0,0 +1,21 @@
+#
+# Copyright (C) 2021 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/compression.mk)
+
+
+PRODUCT_VENDOR_PROPERTIES += ro.virtual_ab.compression.xor.enabled=true
diff --git a/tests/device.rbc b/tests/device.rbc
index 5d4e70c..b57dbf9 100644
--- a/tests/device.rbc
+++ b/tests/device.rbc
@@ -21,7 +21,14 @@
### PRODUCT_COPY_FILES += device_from:device_to
### include $(LOCAL_PATH)/include1.mk
### PRODUCT_PACKAGES += dev_after
-### PRODUCT_COPY_FILES += $(call find-copy-subdir-files,audio_platform_info*.xml,device/google/redfin/audio,$(TARGET_COPY_OUT_VENDOR)/etc) xyz
+### PRODUCT_COPY_FILES += $(call find-copy-subdir-files,audio_platform_info*.xml,device/google/redfin/audio,$(TARGET_COPY_OUT_VENDOR)/etc) xyz:/etc/xyz
+### PRODUCT_COPY_FILES += $(call copy-files,x.xml y.xml,/etc)
+### $(call add_soong_namespace,NS1)
+### $(call add_soong_config_var_value,NS1,v1,abc)
+### $(call add_soong_config_var_value,NS1,v2,def)
+### $(call add_soong_namespace,NS2)
+### $(call add_soong_config_var_value,NS2,v3,abc)
+### $(call add_soong_config_var_value,NS2,v3,xyz)
load("//build/make/core:product_config.rbc", "rblf")
load(":part1.rbc", _part1_init = "init")
@@ -39,4 +46,12 @@
_include1_init(g, handle)
cfg["PRODUCT_PACKAGES"] += ["dev_after"]
cfg["PRODUCT_COPY_FILES"] += (rblf.find_and_copy("audio_platform_info*.xml", "device/google/redfin/audio", "||VENDOR-PATH-PH||/etc") +
- ["xyz"])
+ ["xyz:/etc/xyz"])
+ cfg["PRODUCT_COPY_FILES"] += rblf.copy_files("x.xml y.xml", "/etc")
+ rblf.add_soong_config_namespace(g, "NS1")
+ rblf.add_soong_config_var_value(g, "NS1", "v1", "abc")
+ rblf.add_soong_config_var_value(g, "NS1", "v2", "def")
+ rblf.add_soong_config_namespace(g, "NS2")
+ rblf.add_soong_config_var_value(g, "NS2", "v3", "abc")
+ rblf.add_soong_config_var_value(g, "NS2", "v3", "xyz")
+
diff --git a/tests/run.rbc b/tests/run.rbc
index 4cda180..15f6212 100644
--- a/tests/run.rbc
+++ b/tests/run.rbc
@@ -51,7 +51,9 @@
"part_from:part_to",
"device_from:device_to",
"device/google/redfin/audio/audio_platform_info_noextcodec_snd.xml:||VENDOR-PATH-PH||/etc/audio_platform_info_noextcodec_snd.xml",
- "xyz"
+ "xyz:/etc/xyz",
+ "x.xml:/etc/x.xml",
+ "y.xml:/etc/y.xml",
],
"PRODUCT_HOST_PACKAGES": ["host"],
"PRODUCT_PACKAGES": [
@@ -63,3 +65,17 @@
},
{ k:v for k, v in sorted(config.items()) }
)
+
+ns = globals["$SOONG_CONFIG_NAMESPACES"]
+assert_eq(
+ {
+ "NS1": {
+ "v1": "abc",
+ "v2": "def"
+ },
+ "NS2": {
+ "v3": "xyz"
+ }
+ },
+ {k:v for k, v in sorted(ns.items()) }
+)
diff --git a/tools/rbcrun/host.go b/tools/rbcrun/host.go
index 1e43334..b3dd499 100644
--- a/tools/rbcrun/host.go
+++ b/tools/rbcrun/host.go
@@ -118,7 +118,7 @@
if err := starlark.UnpackPositionalArgs(b.Name(), args, kwargs, 1, &path); err != nil {
return starlark.None, err
}
- if stat, err := os.Stat(path); err != nil || stat.IsDir() {
+ if _, err := os.Stat(path); err != nil {
return starlark.False, nil
}
return starlark.True, nil
diff --git a/tools/rbcrun/testdata/file_ops.star b/tools/rbcrun/testdata/file_ops.star
index e1f1ac2..31631ef 100644
--- a/tools/rbcrun/testdata/file_ops.star
+++ b/tools/rbcrun/testdata/file_ops.star
@@ -4,6 +4,7 @@
def test():
myname = "file_ops.star"
+ assert.true(rblf_file_exists("."), "./ exists ")
assert.true(rblf_file_exists(myname), "the file %s does exist" % myname)
assert.true(not rblf_file_exists("no_such_file"), "the file no_such_file does not exist")
files = rblf_wildcard("*.star")
diff --git a/tools/releasetools/OWNERS b/tools/releasetools/OWNERS
index d7fc540..9962836 100644
--- a/tools/releasetools/OWNERS
+++ b/tools/releasetools/OWNERS
@@ -1,4 +1,6 @@
elsk@google.com
nhdo@google.com
xunchang@google.com
-zhaojiac@google.com
+
+per-file merge_*.py = danielnorman@google.com
+
diff --git a/tools/releasetools/add_img_to_target_files.py b/tools/releasetools/add_img_to_target_files.py
index b8c812d..f3b58f8 100644
--- a/tools/releasetools/add_img_to_target_files.py
+++ b/tools/releasetools/add_img_to_target_files.py
@@ -1030,8 +1030,5 @@
try:
common.CloseInheritedPipes()
main(sys.argv[1:])
- except common.ExternalError:
- logger.exception("\n ERROR:\n")
- sys.exit(1)
finally:
common.Cleanup()
diff --git a/tools/releasetools/apex_utils.py b/tools/releasetools/apex_utils.py
index 893266f..51ec434 100644
--- a/tools/releasetools/apex_utils.py
+++ b/tools/releasetools/apex_utils.py
@@ -340,6 +340,8 @@
zip_items = apex_fd.namelist()
payload_info = ParseApexPayloadInfo(avbtool, payload_file)
+ if no_hashtree is None:
+ no_hashtree = payload_info.get("Tree Size", 0) == 0
SignApexPayload(
avbtool,
payload_file,
@@ -361,20 +363,16 @@
common.ZipWrite(apex_zip, payload_public_key, arcname=APEX_PUBKEY)
common.ZipClose(apex_zip)
- # 3. Align the files at page boundary (same as in apexer).
- aligned_apex = common.MakeTempFile(prefix='apex-container-', suffix='.apex')
- common.RunAndCheckOutput(['zipalign', '-f', '4096', apex_file, aligned_apex])
-
- # 4. Sign the APEX container with container_key.
+ # 3. Sign the APEX container with container_key.
signed_apex = common.MakeTempFile(prefix='apex-container-', suffix='.apex')
# Specify the 4K alignment when calling SignApk.
extra_signapk_args = OPTIONS.extra_signapk_args[:]
- extra_signapk_args.extend(['-a', '4096'])
+ extra_signapk_args.extend(['-a', '4096', '--align-file-size'])
password = container_pw.get(container_key) if container_pw else None
common.SignFile(
- aligned_apex,
+ apex_file,
signed_apex,
container_key,
password,
@@ -385,8 +383,8 @@
def SignCompressedApex(avbtool, apex_file, payload_key, container_key,
- container_pw, apk_keys, codename_to_api_level_map,
- no_hashtree, signing_args=None):
+ container_pw, apk_keys, codename_to_api_level_map,
+ no_hashtree, signing_args=None):
"""Signs the current compressed APEX with the given payload/container keys.
Args:
@@ -434,26 +432,17 @@
'--input', signed_original_apex_file,
'--output', compressed_apex_file])
- # 4. Align apex
- aligned_apex = common.MakeTempFile(prefix='apex-container-', suffix='.capex')
- common.RunAndCheckOutput(['zipalign', '-f', '4096', compressed_apex_file,
- aligned_apex])
-
- # 5. Sign the APEX container with container_key.
+ # 4. Sign the APEX container with container_key.
signed_apex = common.MakeTempFile(prefix='apex-container-', suffix='.capex')
- # Specify the 4K alignment when calling SignApk.
- extra_signapk_args = OPTIONS.extra_signapk_args[:]
- extra_signapk_args.extend(['-a', '4096'])
-
password = container_pw.get(container_key) if container_pw else None
common.SignFile(
- aligned_apex,
+ compressed_apex_file,
signed_apex,
container_key,
password,
codename_to_api_level_map=codename_to_api_level_map,
- extra_signapk_args=extra_signapk_args)
+ extra_signapk_args=OPTIONS.extra_signapk_args)
return signed_apex
@@ -516,6 +505,7 @@
raise ApexInfoError(
'Failed to get type for {}:\n{}'.format(apex_file, e))
+
def GetApexInfoFromTargetFiles(input_file, partition, compressed_only=True):
"""
Get information about system APEX stored in the input_file zip
@@ -558,7 +548,7 @@
for apex_filename in os.listdir(target_dir):
apex_filepath = os.path.join(target_dir, apex_filename)
if not os.path.isfile(apex_filepath) or \
- not zipfile.is_zipfile(apex_filepath):
+ not zipfile.is_zipfile(apex_filepath):
logger.info("Skipping %s because it's not a zipfile", apex_filepath)
continue
apex_info = ota_metadata_pb2.ApexInfo()
diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py
index 0711af5..97cfee9 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -459,6 +459,10 @@
def oem_props(self):
return self._oem_props
+ @property
+ def avb_enabled(self):
+ return self.get("avb_enable") == "true"
+
def __getitem__(self, key):
return self.info_dict[key]
@@ -2933,7 +2937,7 @@
th.join()
if p.returncode != 0:
- logger.warning("Failure running %s:\n%s\n", diff_program, "".join(err))
+ logger.warning("Failure running %s:\n%s\n", cmd, "".join(err))
self.patch = None
return None, None, None
diff = ptemp.read()
diff --git a/tools/releasetools/merge_target_files.py b/tools/releasetools/merge_target_files.py
index 7086f21..46ffdb7 100755
--- a/tools/releasetools/merge_target_files.py
+++ b/tools/releasetools/merge_target_files.py
@@ -88,11 +88,23 @@
--keep-tmp
Keep tempoary files for debugging purposes.
+
+ The following only apply when using the VSDK to perform dexopt on vendor apps:
+
+ --framework-dexpreopt-config
+ If provided, the location of framwework's dexpreopt_config.zip.
+
+ --framework-dexpreopt-tools
+ if provided, the location of framework's dexpreopt_tools.zip.
+
+ --vendor-dexpreopt-config
+ If provided, the location of vendor's dexpreopt_config.zip.
"""
from __future__ import print_function
import fnmatch
+import glob
import json
import logging
import os
@@ -140,6 +152,9 @@
OPTIONS.vendor_otatools = None
OPTIONS.rebuild_sepolicy = False
OPTIONS.keep_tmp = False
+OPTIONS.framework_dexpreopt_config = None
+OPTIONS.framework_dexpreopt_tools = None
+OPTIONS.vendor_dexpreopt_config = None
# In an item list (framework or vendor), we may see entries that select whole
# partitions. Such an entry might look like this 'SYSTEM/*' (e.g., for the
@@ -815,21 +830,23 @@
PARTITIONS_WITH_CARE_MAP, partition_image_map)
-def process_special_cases(framework_target_files_temp_dir,
- vendor_target_files_temp_dir,
+def process_special_cases(temp_dir, framework_meta, vendor_meta,
output_target_files_temp_dir,
framework_misc_info_keys, framework_partition_set,
- vendor_partition_set):
+ vendor_partition_set, framework_dexpreopt_tools,
+ framework_dexpreopt_config, vendor_dexpreopt_config):
"""Performs special-case processing for certain target files items.
Certain files in the output target files package require special-case
processing. This function performs all that special-case processing.
Args:
- framework_target_files_temp_dir: The name of a directory containing the
- special items extracted from the framework target files package.
- vendor_target_files_temp_dir: The name of a directory containing the special
- items extracted from the vendor target files package.
+ temp_dir: Location containing an 'output' directory where target files have
+ been extracted, e.g. <temp_dir>/output/SYSTEM, <temp_dir>/output/IMAGES, etc.
+ framework_meta: The name of a directory containing the special items
+ extracted from the framework target files package.
+ vendor_meta: The name of a directory containing the special items
+ extracted from the vendor target files package.
output_target_files_temp_dir: The name of a directory that will be used to
create the output target files package after all the special cases are
processed.
@@ -840,50 +857,361 @@
partitions. Used to filter apexkeys.txt and apkcerts.txt.
vendor_partition_set: Partitions that are considered vendor partitions. Used
to filter apexkeys.txt and apkcerts.txt.
+
+ The following are only used if dexpreopt is applied:
+
+ framework_dexpreopt_tools: Location of dexpreopt_tools.zip.
+ framework_dexpreopt_config: Location of framework's dexpreopt_config.zip.
+ vendor_dexpreopt_config: Location of vendor's dexpreopt_config.zip.
"""
if 'ab_update' in framework_misc_info_keys:
process_ab_partitions_txt(
- framework_target_files_temp_dir=framework_target_files_temp_dir,
- vendor_target_files_temp_dir=vendor_target_files_temp_dir,
+ framework_target_files_temp_dir=framework_meta,
+ vendor_target_files_temp_dir=vendor_meta,
output_target_files_temp_dir=output_target_files_temp_dir)
copy_file_contexts(
- framework_target_files_dir=framework_target_files_temp_dir,
- vendor_target_files_dir=vendor_target_files_temp_dir,
+ framework_target_files_dir=framework_meta,
+ vendor_target_files_dir=vendor_meta,
output_target_files_dir=output_target_files_temp_dir)
process_misc_info_txt(
- framework_target_files_temp_dir=framework_target_files_temp_dir,
- vendor_target_files_temp_dir=vendor_target_files_temp_dir,
+ framework_target_files_temp_dir=framework_meta,
+ vendor_target_files_temp_dir=vendor_meta,
output_target_files_temp_dir=output_target_files_temp_dir,
framework_misc_info_keys=framework_misc_info_keys)
process_dynamic_partitions_info_txt(
- framework_target_files_dir=framework_target_files_temp_dir,
- vendor_target_files_dir=vendor_target_files_temp_dir,
+ framework_target_files_dir=framework_meta,
+ vendor_target_files_dir=vendor_meta,
output_target_files_dir=output_target_files_temp_dir)
process_apex_keys_apk_certs_common(
- framework_target_files_dir=framework_target_files_temp_dir,
- vendor_target_files_dir=vendor_target_files_temp_dir,
+ framework_target_files_dir=framework_meta,
+ vendor_target_files_dir=vendor_meta,
output_target_files_dir=output_target_files_temp_dir,
framework_partition_set=framework_partition_set,
vendor_partition_set=vendor_partition_set,
file_name='apkcerts.txt')
process_apex_keys_apk_certs_common(
- framework_target_files_dir=framework_target_files_temp_dir,
- vendor_target_files_dir=vendor_target_files_temp_dir,
+ framework_target_files_dir=framework_meta,
+ vendor_target_files_dir=vendor_meta,
output_target_files_dir=output_target_files_temp_dir,
framework_partition_set=framework_partition_set,
vendor_partition_set=vendor_partition_set,
file_name='apexkeys.txt')
+ process_dexopt(
+ temp_dir=temp_dir,
+ framework_meta=framework_meta,
+ vendor_meta=vendor_meta,
+ output_target_files_temp_dir=output_target_files_temp_dir,
+ framework_dexpreopt_tools=framework_dexpreopt_tools,
+ framework_dexpreopt_config=framework_dexpreopt_config,
+ vendor_dexpreopt_config=vendor_dexpreopt_config)
+
+
+def process_dexopt(temp_dir, framework_meta, vendor_meta,
+ output_target_files_temp_dir,
+ framework_dexpreopt_tools, framework_dexpreopt_config,
+ vendor_dexpreopt_config):
+ """If needed, generates dexopt files for vendor apps.
+
+ Args:
+ temp_dir: Location containing an 'output' directory where target files have
+ been extracted, e.g. <temp_dir>/output/SYSTEM, <temp_dir>/output/IMAGES, etc.
+ framework_meta: The name of a directory containing the special items
+ extracted from the framework target files package.
+ vendor_meta: The name of a directory containing the special items extracted
+ from the vendor target files package.
+ output_target_files_temp_dir: The name of a directory that will be used to
+ create the output target files package after all the special cases are
+ processed.
+ framework_dexpreopt_tools: Location of dexpreopt_tools.zip.
+ framework_dexpreopt_config: Location of framework's dexpreopt_config.zip.
+ vendor_dexpreopt_config: Location of vendor's dexpreopt_config.zip.
+ """
+ # Load vendor and framework META/misc_info.txt.
+ misc_info_path = ['META', 'misc_info.txt']
+ vendor_misc_info_dict = common.LoadDictionaryFromFile(
+ os.path.join(vendor_meta, *misc_info_path))
+
+ if (vendor_misc_info_dict.get('building_with_vsdk') != 'true' or
+ framework_dexpreopt_tools is None or
+ framework_dexpreopt_config is None or
+ vendor_dexpreopt_config is None):
+ return
+
+ logger.info('applying dexpreopt')
+
+ # The directory structure to apply dexpreopt is:
+ #
+ # <temp_dir>/
+ # framework_meta/
+ # META/
+ # vendor_meta/
+ # META/
+ # output/
+ # SYSTEM/
+ # VENDOR/
+ # IMAGES/
+ # <other items extracted from system and vendor target files>
+ # tools/
+ # <contents of dexpreopt_tools.zip>
+ # system_config/
+ # <contents of system dexpreopt_config.zip>
+ # vendor_config/
+ # <contents of vendor dexpreopt_config.zip>
+ # system -> output/SYSTEM
+ # vendor -> output/VENDOR
+ # apex -> output/SYSTEM/apex (only for flattened APEX builds)
+ # apex/ (extracted updatable APEX)
+ # <apex 1>/
+ # ...
+ # <apex 2>/
+ # ...
+ # ...
+ # out/dex2oat_result/vendor/
+ # <app>
+ # oat/arm64/
+ # package.vdex
+ # package.odex
+ # <priv-app>
+ # oat/arm64/
+ # package.vdex
+ # package.odex
+ dexpreopt_tools_files_temp_dir = os.path.join(temp_dir, 'tools')
+ dexpreopt_framework_config_files_temp_dir = os.path.join(temp_dir, 'system_config')
+ dexpreopt_vendor_config_files_temp_dir = os.path.join(temp_dir, 'vendor_config')
+
+ extract_items(
+ target_files=OPTIONS.framework_dexpreopt_tools,
+ target_files_temp_dir=dexpreopt_tools_files_temp_dir,
+ extract_item_list=('*',))
+ extract_items(
+ target_files=OPTIONS.framework_dexpreopt_config,
+ target_files_temp_dir=dexpreopt_framework_config_files_temp_dir,
+ extract_item_list=('*',))
+ extract_items(
+ target_files=OPTIONS.vendor_dexpreopt_config,
+ target_files_temp_dir=dexpreopt_vendor_config_files_temp_dir,
+ extract_item_list=('*',))
+
+ os.symlink(os.path.join(output_target_files_temp_dir, "SYSTEM"),
+ os.path.join(temp_dir, "system"))
+ os.symlink(os.path.join(output_target_files_temp_dir, "VENDOR"),
+ os.path.join(temp_dir, "vendor"))
+
+ # The directory structure for flatteded APEXes is:
+ #
+ # SYSTEM
+ # apex
+ # <APEX name, e.g., com.android.wifi>
+ # apex_manifest.pb
+ # apex_pubkey
+ # etc/
+ # javalib/
+ # lib/
+ # lib64/
+ # priv-app/
+ #
+ # The directory structure for updatable APEXes is:
+ #
+ # SYSTEM
+ # apex
+ # com.android.adbd.apex
+ # com.android.appsearch.apex
+ # com.android.art.apex
+ # ...
+ apex_root = os.path.join(output_target_files_temp_dir, "SYSTEM", "apex")
+ framework_misc_info_dict = common.LoadDictionaryFromFile(
+ os.path.join(framework_meta, *misc_info_path))
+
+ # Check for flattended versus updatable APEX.
+ if framework_misc_info_dict.get('target_flatten_apex') == 'false':
+ # Extract APEX.
+ logging.info('extracting APEX')
+
+ apex_extract_root_dir = os.path.join(temp_dir, 'apex')
+ os.makedirs(apex_extract_root_dir)
+
+ for apex in (glob.glob(os.path.join(apex_root, '*.apex')) +
+ glob.glob(os.path.join(apex_root, '*.capex'))):
+ logging.info(' apex: %s', apex)
+ # deapexer is in the same directory as the merge_target_files binary extracted
+ # from otatools.zip.
+ apex_json_info = subprocess.check_output(['deapexer', 'info', apex])
+ logging.info(' info: %s', apex_json_info)
+ apex_info = json.loads(apex_json_info)
+ apex_name = apex_info['name']
+ logging.info(' name: %s', apex_name)
+
+ apex_extract_dir = os.path.join(apex_extract_root_dir, apex_name)
+ os.makedirs(apex_extract_dir)
+
+ # deapexer uses debugfs_static, which is part of otatools.zip.
+ command = [
+ 'deapexer',
+ '--debugfs_path',
+ 'debugfs_static',
+ 'extract',
+ apex,
+ apex_extract_dir,
+ ]
+ logging.info(' running %s', command)
+ subprocess.check_call(command)
+ else:
+ # Flattened APEXes don't need to be extracted since they have the necessary
+ # directory structure.
+ os.symlink(os.path.join(apex_root), os.path.join(temp_dir, 'apex'))
+
+ # Modify system config to point to the tools that have been extracted.
+ # Absolute or .. paths are not allowed by the dexpreopt_gen tool in
+ # dexpreopt_soong.config.
+ dexpreopt_framework_soon_config = os.path.join(
+ dexpreopt_framework_config_files_temp_dir, 'dexpreopt_soong.config')
+ with open(dexpreopt_framework_soon_config, 'w') as f:
+ dexpreopt_soong_config = {
+ 'Profman': 'tools/profman',
+ 'Dex2oat': 'tools/dex2oatd',
+ 'Aapt': 'tools/aapt2',
+ 'SoongZip': 'tools/soong_zip',
+ 'Zip2zip': 'tools/zip2zip',
+ 'ManifestCheck': 'tools/manifest_check',
+ 'ConstructContext': 'tools/construct_context',
+ }
+ json.dump(dexpreopt_soong_config, f)
+
+ # TODO(b/188179859): Make *dex location configurable to vendor or system_other.
+ use_system_other_odex = False
+
+ if use_system_other_odex:
+ dex_img = 'SYSTEM_OTHER'
+ else:
+ dex_img = 'VENDOR'
+ # Open vendor_filesystem_config to append the items generated by dexopt.
+ vendor_file_system_config = open(
+ os.path.join(temp_dir, 'output', 'META', 'vendor_filesystem_config.txt'),
+ 'a')
+
+ # Dexpreopt vendor apps.
+ dexpreopt_config_suffix = '_dexpreopt.config'
+ for config in glob.glob(os.path.join(
+ dexpreopt_vendor_config_files_temp_dir, '*' + dexpreopt_config_suffix)):
+ app = os.path.basename(config)[:-len(dexpreopt_config_suffix)]
+ logging.info('dexpreopt config: %s %s', config, app)
+
+ apk_dir = 'app'
+ apk_path = os.path.join(temp_dir, 'vendor', apk_dir, app, app + '.apk')
+ if not os.path.exists(apk_path):
+ apk_dir = 'priv-app'
+ apk_path = os.path.join(temp_dir, 'vendor', apk_dir, app, app + '.apk')
+ if not os.path.exists(apk_path):
+ logging.warning('skipping dexpreopt for %s, no apk found in vendor/app '
+ 'or vendor/priv-app', app)
+ continue
+
+ # Generate dexpreopting script. Note 'out_dir' is not the output directory
+ # where the script is generated, but the OUT_DIR at build time referenced
+ # in the dexpreot config files, e.g., "out/.../core-oj.jar", so the tool knows
+ # how to adjust the path.
+ command = [
+ os.path.join(dexpreopt_tools_files_temp_dir, 'dexpreopt_gen'),
+ '-global',
+ os.path.join(dexpreopt_framework_config_files_temp_dir, 'dexpreopt.config'),
+ '-global_soong',
+ os.path.join(
+ dexpreopt_framework_config_files_temp_dir, 'dexpreopt_soong.config'),
+ '-module',
+ config,
+ '-dexpreopt_script',
+ 'dexpreopt_app.sh',
+ '-out_dir',
+ 'out',
+ '-base_path',
+ '.',
+ '--uses_target_files',
+ ]
+
+ # Run the command from temp_dir so all tool paths are its descendants.
+ logging.info("running %s", command)
+ subprocess.check_call(command, cwd = temp_dir)
+
+ # Call the generated script.
+ command = ['sh', 'dexpreopt_app.sh', apk_path]
+ logging.info("running %s", command)
+ subprocess.check_call(command, cwd = temp_dir)
+
+ # Output files are in:
+ #
+ # <temp_dir>/out/dex2oat_result/vendor/priv-app/<app>/oat/arm64/package.vdex
+ # <temp_dir>/out/dex2oat_result/vendor/priv-app/<app>/oat/arm64/package.odex
+ # <temp_dir>/out/dex2oat_result/vendor/app/<app>/oat/arm64/package.vdex
+ # <temp_dir>/out/dex2oat_result/vendor/app/<app>/oat/arm64/package.odex
+ #
+ # Copy the files to their destination. The structure of system_other is:
+ #
+ # system_other/
+ # system-other-odex-marker
+ # system/
+ # app/
+ # <app>/oat/arm64/
+ # <app>.odex
+ # <app>.vdex
+ # ...
+ # priv-app/
+ # <app>/oat/arm64/
+ # <app>.odex
+ # <app>.vdex
+ # ...
+
+ # TODO(b/188179859): Support for other architectures.
+ arch = 'arm64'
+
+ dex_destination = os.path.join(temp_dir, 'output', dex_img, apk_dir, app, 'oat', arch)
+ os.makedirs(dex_destination)
+ dex2oat_path = os.path.join(
+ temp_dir, 'out', 'dex2oat_result', 'vendor', apk_dir, app, 'oat', arch)
+ shutil.copy(os.path.join(dex2oat_path, 'package.vdex'),
+ os.path.join(dex_destination, app + '.vdex'))
+ shutil.copy(os.path.join(dex2oat_path, 'package.odex'),
+ os.path.join(dex_destination, app + '.odex'))
+
+ # Append entries to vendor_file_system_config.txt, such as:
+ #
+ # vendor/app/<app>/oat 0 2000 755 selabel=u:object_r:vendor_app_file:s0 capabilities=0x0
+ # vendor/app/<app>/oat/arm64 0 2000 755 selabel=u:object_r:vendor_app_file:s0 capabilities=0x0
+ # vendor/app/<app>/oat/arm64/<app>.odex 0 0 644 selabel=u:object_r:vendor_app_file:s0 capabilities=0x0
+ # vendor/app/<app>/oat/arm64/<app>.vdex 0 0 644 selabel=u:object_r:vendor_app_file:s0 capabilities=0x0
+ if not use_system_other_odex:
+ vendor_app_prefix = 'vendor/' + apk_dir + '/' + app + '/oat'
+ selabel = 'selabel=u:object_r:vendor_app_file:s0 capabilities=0x0'
+ vendor_file_system_config.writelines([
+ vendor_app_prefix + ' 0 2000 755 ' + selabel + '\n',
+ vendor_app_prefix + '/' + arch + ' 0 2000 755 ' + selabel + '\n',
+ vendor_app_prefix + '/' + arch + '/' + app + '.odex 0 0 644 ' + selabel + '\n',
+ vendor_app_prefix + '/' + arch + '/' + app + '.vdex 0 0 644 ' + selabel + '\n',
+ ])
+
+ if not use_system_other_odex:
+ vendor_file_system_config.close()
+ # Delete vendor.img so that it will be regenerated.
+ # TODO(b/188179859): Rebuilding a vendor image in GRF mode (e.g., T(framework)
+ # and S(vendor) may require logic similar to that in
+ # rebuild_image_with_sepolicy.
+ vendor_img = os.path.join(output_target_files_temp_dir, 'IMAGES', 'vendor.img')
+ if os.path.exists(vendor_img):
+ logging.info('Deleting %s', vendor_img)
+ os.remove(vendor_img)
+
def create_merged_package(temp_dir, framework_target_files, framework_item_list,
vendor_target_files, vendor_item_list,
- framework_misc_info_keys, rebuild_recovery):
+ framework_misc_info_keys, rebuild_recovery,
+ framework_dexpreopt_tools, framework_dexpreopt_config,
+ vendor_dexpreopt_config):
"""Merges two target files packages into one target files structure.
Args:
@@ -908,6 +1236,12 @@
rebuild_recovery: If true, rebuild the recovery patch used by non-A/B
devices and write it to the system image.
+ The following are only used if dexpreopt is applied:
+
+ framework_dexpreopt_tools: Location of dexpreopt_tools.zip.
+ framework_dexpreopt_config: Location of framework's dexpreopt_config.zip.
+ vendor_dexpreopt_config: Location of vendor's dexpreopt_config.zip.
+
Returns:
Path to merged package under temp directory.
"""
@@ -928,23 +1262,27 @@
# Perform special case processing on META/* items.
# After this function completes successfully, all the files we need to create
# the output target files package are in place.
- framework_target_files_temp_dir = os.path.join(temp_dir, 'framework')
- vendor_target_files_temp_dir = os.path.join(temp_dir, 'vendor')
+ framework_meta = os.path.join(temp_dir, 'framework_meta')
+ vendor_meta = os.path.join(temp_dir, 'vendor_meta')
extract_items(
target_files=framework_target_files,
- target_files_temp_dir=framework_target_files_temp_dir,
+ target_files_temp_dir=framework_meta,
extract_item_list=('META/*',))
extract_items(
target_files=vendor_target_files,
- target_files_temp_dir=vendor_target_files_temp_dir,
+ target_files_temp_dir=vendor_meta,
extract_item_list=('META/*',))
process_special_cases(
- framework_target_files_temp_dir=framework_target_files_temp_dir,
- vendor_target_files_temp_dir=vendor_target_files_temp_dir,
+ temp_dir=temp_dir,
+ framework_meta=framework_meta,
+ vendor_meta=vendor_meta,
output_target_files_temp_dir=output_target_files_temp_dir,
framework_misc_info_keys=framework_misc_info_keys,
framework_partition_set=item_list_to_partition_set(framework_item_list),
- vendor_partition_set=item_list_to_partition_set(vendor_item_list))
+ vendor_partition_set=item_list_to_partition_set(vendor_item_list),
+ framework_dexpreopt_tools=framework_dexpreopt_tools,
+ framework_dexpreopt_config=framework_dexpreopt_config,
+ vendor_dexpreopt_config=vendor_dexpreopt_config)
return output_target_files_temp_dir
@@ -1156,7 +1494,8 @@
vendor_item_list, output_target_files, output_dir,
output_item_list, output_ota, output_img,
output_super_empty, rebuild_recovery, vendor_otatools,
- rebuild_sepolicy):
+ rebuild_sepolicy, framework_dexpreopt_tools,
+ framework_dexpreopt_config, vendor_dexpreopt_config):
"""Merges two target files packages together.
This function takes framework and vendor target files packages as input,
@@ -1195,6 +1534,12 @@
vendor_otatools: Path to an otatools zip used for recompiling vendor images.
rebuild_sepolicy: If true, rebuild odm.img (if target uses ODM) or
vendor.img using a merged precompiled_sepolicy file.
+
+ The following are only used if dexpreopt is applied:
+
+ framework_dexpreopt_tools: Location of dexpreopt_tools.zip.
+ framework_dexpreopt_config: Location of framework's dexpreopt_config.zip.
+ vendor_dexpreopt_config: Location of vendor's dexpreopt_config.zip.
"""
logger.info('starting: merge framework %s and vendor %s into output %s',
@@ -1203,7 +1548,8 @@
output_target_files_temp_dir = create_merged_package(
temp_dir, framework_target_files, framework_item_list,
vendor_target_files, vendor_item_list, framework_misc_info_keys,
- rebuild_recovery)
+ rebuild_recovery, framework_dexpreopt_tools, framework_dexpreopt_config,
+ vendor_dexpreopt_config)
if not check_target_files_vintf.CheckVintf(output_target_files_temp_dir):
raise RuntimeError('Incompatible VINTF metadata')
@@ -1377,6 +1723,12 @@
OPTIONS.rebuild_sepolicy = True
elif o == '--keep-tmp':
OPTIONS.keep_tmp = True
+ elif o == '--framework-dexpreopt-config':
+ OPTIONS.framework_dexpreopt_config = a
+ elif o == '--framework-dexpreopt-tools':
+ OPTIONS.framework_dexpreopt_tools = a
+ elif o == '--vendor-dexpreopt-config':
+ OPTIONS.vendor_dexpreopt_config = a
else:
return False
return True
@@ -1401,6 +1753,9 @@
'output-ota=',
'output-img=',
'output-super-empty=',
+ 'framework-dexpreopt-config=',
+ 'framework-dexpreopt-tools=',
+ 'vendor-dexpreopt-config=',
'rebuild_recovery',
'allow-duplicate-apkapex-keys',
'vendor-otatools=',
@@ -1460,7 +1815,10 @@
output_super_empty=OPTIONS.output_super_empty,
rebuild_recovery=OPTIONS.rebuild_recovery,
vendor_otatools=OPTIONS.vendor_otatools,
- rebuild_sepolicy=OPTIONS.rebuild_sepolicy), OPTIONS.keep_tmp)
+ rebuild_sepolicy=OPTIONS.rebuild_sepolicy,
+ framework_dexpreopt_tools=OPTIONS.framework_dexpreopt_tools,
+ framework_dexpreopt_config=OPTIONS.framework_dexpreopt_config,
+ vendor_dexpreopt_config=OPTIONS.vendor_dexpreopt_config), OPTIONS.keep_tmp)
if __name__ == '__main__':
diff --git a/tools/releasetools/ota_from_target_files.py b/tools/releasetools/ota_from_target_files.py
index 8face66..1f3022b 100755
--- a/tools/releasetools/ota_from_target_files.py
+++ b/tools/releasetools/ota_from_target_files.py
@@ -241,7 +241,7 @@
import common
import ota_utils
from ota_utils import (UNZIP_PATTERN, FinalizeMetadata, GetPackageMetadata,
- PropertyFiles, SECURITY_PATCH_LEVEL_PROP_NAME)
+ PropertyFiles, SECURITY_PATCH_LEVEL_PROP_NAME, GetZipEntryOffset)
import target_files_diff
from check_target_files_vintf import CheckVintfIfTrebleEnabled
from non_ab_ota import GenerateNonAbOtaPackage
@@ -286,6 +286,7 @@
OPTIONS.disable_vabc = False
OPTIONS.spl_downgrade = False
OPTIONS.vabc_downgrade = False
+OPTIONS.enable_vabc_xor = False
POSTINSTALL_CONFIG = 'META/postinstall_config.txt'
DYNAMIC_PARTITION_INFO = 'META/dynamic_partitions_info.txt'
@@ -602,20 +603,20 @@
payload, till the end of 'medatada_signature_message'.
"""
payload_info = input_zip.getinfo('payload.bin')
- payload_offset = payload_info.header_offset
- payload_offset += zipfile.sizeFileHeader
- payload_offset += len(payload_info.extra) + len(payload_info.filename)
- payload_size = payload_info.file_size
+ (payload_offset, payload_size) = GetZipEntryOffset(input_zip, payload_info)
- with input_zip.open('payload.bin') as payload_fp:
- header_bin = payload_fp.read(24)
+ # Read the underlying raw zipfile at specified offset
+ payload_fp = input_zip.fp
+ payload_fp.seek(payload_offset)
+ header_bin = payload_fp.read(24)
# network byte order (big-endian)
header = struct.unpack("!IQQL", header_bin)
# 'CrAU'
magic = header[0]
- assert magic == 0x43724155, "Invalid magic: {:x}".format(magic)
+ assert magic == 0x43724155, "Invalid magic: {:x}, computed offset {}" \
+ .format(magic, payload_offset)
manifest_size = header[2]
metadata_signature_size = header[3]
@@ -1132,6 +1133,8 @@
if OPTIONS.disable_vabc:
additional_args += ["--disable_vabc", "true"]
+ if OPTIONS.enable_vabc_xor:
+ additional_args += ["--enable_vabc_xor", "true"]
additional_args += ["--max_timestamp", max_timestamp]
if SupportsMainlineGkiUpdates(source_file):
@@ -1305,6 +1308,8 @@
OPTIONS.wipe_user_data = True
elif o == "--vabc_downgrade":
OPTIONS.vabc_downgrade = True
+ elif o == "--enable_vabc_xor":
+ OPTIONS.enable_vabc_xor = True
else:
return False
return True
@@ -1349,6 +1354,7 @@
"disable_vabc",
"spl_downgrade",
"vabc_downgrade",
+ "enable_vabc_xor",
], extra_option_handler=option_handler)
if len(args) != 2:
diff --git a/tools/releasetools/ota_utils.py b/tools/releasetools/ota_utils.py
index 28c246b..5737009 100644
--- a/tools/releasetools/ota_utils.py
+++ b/tools/releasetools/ota_utils.py
@@ -16,6 +16,7 @@
import itertools
import logging
import os
+import struct
import zipfile
import ota_metadata_pb2
@@ -399,6 +400,35 @@
return device_names, fingerprints
+def GetZipEntryOffset(zfp, entry_info):
+ """Get offset to a beginning of a particular zip entry
+ Args:
+ fp: zipfile.ZipFile
+ entry_info: zipfile.ZipInfo
+
+ Returns:
+ (offset, size) tuple
+ """
+ # Don't use len(entry_info.extra). Because that returns size of extra
+ # fields in central directory. We need to look at local file directory,
+ # as these two might have different sizes.
+
+ # We cannot work with zipfile.ZipFile instances, we need a |fp| for the underlying file.
+ zfp = zfp.fp
+ zfp.seek(entry_info.header_offset)
+ data = zfp.read(zipfile.sizeFileHeader)
+ fheader = struct.unpack(zipfile.structFileHeader, data)
+ # Last two fields of local file header are filename length and
+ # extra length
+ filename_len = fheader[-2]
+ extra_len = fheader[-1]
+ offset = entry_info.header_offset
+ offset += zipfile.sizeFileHeader
+ offset += filename_len + extra_len
+ size = entry_info.file_size
+ return (offset, size)
+
+
class PropertyFiles(object):
"""A class that computes the property-files string for an OTA package.
@@ -517,10 +547,7 @@
def ComputeEntryOffsetSize(name):
"""Computes the zip entry offset and size."""
info = zip_file.getinfo(name)
- offset = info.header_offset
- offset += zipfile.sizeFileHeader
- offset += len(info.extra) + len(info.filename)
- size = info.file_size
+ (offset, size) = GetZipEntryOffset(zip_file, info)
return '%s:%d:%d' % (os.path.basename(name), offset, size)
tokens = []
diff --git a/tools/releasetools/sign_target_files_apks.py b/tools/releasetools/sign_target_files_apks.py
index 2859948..0842af9 100755
--- a/tools/releasetools/sign_target_files_apks.py
+++ b/tools/releasetools/sign_target_files_apks.py
@@ -428,7 +428,7 @@
if is_compressed:
uncompressed = tempfile.NamedTemporaryFile()
with gzip.open(unsigned.name, "rb") as in_file, \
- open(uncompressed.name, "wb") as out_file:
+ open(uncompressed.name, "wb") as out_file:
shutil.copyfileobj(in_file, out_file)
# Finally, close the "unsigned" file (which is gzip compressed), and then
@@ -468,7 +468,7 @@
# Recompress the file after it has been signed.
compressed = tempfile.NamedTemporaryFile()
with open(signed.name, "rb") as in_file, \
- gzip.open(compressed.name, "wb") as out_file:
+ gzip.open(compressed.name, "wb") as out_file:
shutil.copyfileobj(in_file, out_file)
data = compressed.read()
@@ -484,21 +484,21 @@
def IsBuildPropFile(filename):
return filename in (
- "SYSTEM/etc/prop.default",
- "BOOT/RAMDISK/prop.default",
- "RECOVERY/RAMDISK/prop.default",
+ "SYSTEM/etc/prop.default",
+ "BOOT/RAMDISK/prop.default",
+ "RECOVERY/RAMDISK/prop.default",
- "VENDOR_BOOT/RAMDISK/default.prop",
- "VENDOR_BOOT/RAMDISK/prop.default",
+ "VENDOR_BOOT/RAMDISK/default.prop",
+ "VENDOR_BOOT/RAMDISK/prop.default",
- # ROOT/default.prop is a legacy path, but may still exist for upgrading
- # devices that don't support `property_overrides_split_enabled`.
- "ROOT/default.prop",
+ # ROOT/default.prop is a legacy path, but may still exist for upgrading
+ # devices that don't support `property_overrides_split_enabled`.
+ "ROOT/default.prop",
- # RECOVERY/RAMDISK/default.prop is a legacy path, but will always exist
- # as a symlink in the current code. So it's a no-op here. Keeping the
- # path here for clarity.
- "RECOVERY/RAMDISK/default.prop") or filename.endswith("build.prop")
+ # RECOVERY/RAMDISK/default.prop is a legacy path, but will always exist
+ # as a symlink in the current code. So it's a no-op here. Keeping the
+ # path here for clarity.
+ "RECOVERY/RAMDISK/default.prop") or filename.endswith("build.prop")
def ProcessTargetFiles(input_tf_zip, output_tf_zip, misc_info,
@@ -561,7 +561,7 @@
# We've asserted not having a case with only one of them PRESIGNED.
if (payload_key not in common.SPECIAL_CERT_STRINGS and
- container_key not in common.SPECIAL_CERT_STRINGS):
+ container_key not in common.SPECIAL_CERT_STRINGS):
print(" signing: %-*s container (%s)" % (
maxsize, name, container_key))
print(" : %-*s payload (%s)" % (
@@ -575,7 +575,7 @@
key_passwords,
apk_keys,
codename_to_api_level_map,
- no_hashtree=True,
+ no_hashtree=None, # Let apex_util determine if hash tree is needed
signing_args=OPTIONS.avb_extra_args.get('apex'))
common.ZipWrite(output_tf_zip, signed_apex, filename)
@@ -658,7 +658,7 @@
# Updates system_other.avbpubkey in /product/etc/.
elif filename in (
"PRODUCT/etc/security/avb/system_other.avbpubkey",
- "SYSTEM/product/etc/security/avb/system_other.avbpubkey"):
+ "SYSTEM/product/etc/security/avb/system_other.avbpubkey"):
# Only update system_other's public key, if the corresponding signing
# key is specified via --avb_system_other_key.
signing_key = OPTIONS.avb_keys.get("system_other")
@@ -671,7 +671,7 @@
# Should NOT sign boot-debug.img.
elif filename in (
"BOOT/RAMDISK/force_debuggable",
- "BOOT/RAMDISK/first_stage_ramdisk/force_debuggable"):
+ "BOOT/RAMDISK/first_stage_ramdisk/force_debuggable"):
raise common.ExternalError("debuggable boot.img cannot be signed")
# A non-APK file; copy it verbatim.
@@ -762,7 +762,8 @@
# it's only checking entries with global seinfo at the moment (i.e. ignoring
# the ones with inner packages). (Bug: 69479366)
root = ElementTree.fromstring(data)
- signatures = [signer.attrib['signature'] for signer in root.findall('signer')]
+ signatures = [signer.attrib['signature']
+ for signer in root.findall('signer')]
assert len(signatures) == len(set(signatures)), \
"Found duplicate entries after cert replacement: {}".format(data)
@@ -807,7 +808,7 @@
if line and line[0] != '#' and "=" in line:
key, value = line.split("=", 1)
if (key.startswith("ro.") and
- key.endswith((".build.fingerprint", ".build.thumbprint"))):
+ key.endswith((".build.fingerprint", ".build.thumbprint"))):
pieces = value.split("/")
pieces[-1] = EditTags(pieces[-1])
value = "/".join(pieces)
@@ -1000,7 +1001,7 @@
ReplaceAvbPartitionSigningKey(partition)
for custom_partition in misc_info.get(
- "avb_custom_images_partition_list", "").strip().split():
+ "avb_custom_images_partition_list", "").strip().split():
ReplaceAvbPartitionSigningKey(custom_partition)
@@ -1065,7 +1066,7 @@
devkeydir + "/shared": d + "/shared",
devkeydir + "/platform": d + "/platform",
devkeydir + "/networkstack": d + "/networkstack",
- })
+ })
else:
OPTIONS.key_map[s] = d
@@ -1168,8 +1169,8 @@
if container_cert == 'PRESIGNED' and container_private_key == 'PRESIGNED':
container_key = 'PRESIGNED'
elif CompareKeys(
- container_cert, OPTIONS.public_key_suffix,
- container_private_key, OPTIONS.private_key_suffix):
+ container_cert, OPTIONS.public_key_suffix,
+ container_private_key, OPTIONS.private_key_suffix):
container_key = container_cert[:-len(OPTIONS.public_key_suffix)]
else:
raise ValueError("Failed to parse container keys: \n{}".format(line))
diff --git a/tools/releasetools/test_ota_utils.py b/tools/releasetools/test_ota_utils.py
new file mode 100644
index 0000000..9a82e6f
--- /dev/null
+++ b/tools/releasetools/test_ota_utils.py
@@ -0,0 +1,56 @@
+# Copyright (C) 2021 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.
+
+
+import unittest
+import io
+import ota_utils
+import zipfile
+
+
+class TestZipEntryOffset(unittest.TestCase):
+ def test_extra_length_differ(self):
+ # This is a magic zip file such that:
+ # 1. It has 1 entry, `file.txt'`
+ # 2. The central directory entry for the entry contains an extra field of#
+ # length 24, while the local file header for the entry contains an extra#
+ # field of length 28.
+ # It is key that the entry contains extra field of different length.
+ # The sole purpose of this test case is make sure our offset computing
+ # logic works in this scenario.
+
+ # This is created by:
+ # touch file.txt
+ # zip -0 test.zip file.txt
+ # Above command may or may not work on all platforms.
+ # Some zip implementation will keep the extra field size consistent.
+ # Some don't
+ magic_zip = b'PK\x03\x04\n\x00\x00\x00\x00\x00nY\xfcR\x00\x00\x00\x00\x00\x00\x00' +\
+ b'\x00\x00\x00\x00\x00\x08\x00\x1c\x00file.txtUT\t\x00\x03' +\
+ b'\xa0s\x01a\xa0s\x01aux\x0b\x00\x01\x04\x88\xc4\t\x00\x04S_\x01\x00' +\
+ b'PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00nY\xfcR\x00\x00\x00\x00' +\
+ b'\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x18\x00\x00\x00\x00\x00' +\
+ b'\x00\x00\x00\x00\x80\x81\x00\x00\x00\x00file.txt' +\
+ b'UT\x05\x00\x03\xa0s\x01aux\x0b\x00\x01\x04\x88\xc4\t\x00\x04' +\
+ b'S_\x01\x00PK\x05\x06\x00\x00\x00\x00\x01\x00\x01\x00N\x00\x00' +\
+ b'\x00B\x00\x00\x00\x00\x00'
+ # Just making sure we concatenated the bytes correctly
+ self.assertEqual(len(magic_zip), 166)
+ fp = io.BytesIO(magic_zip)
+ with zipfile.ZipFile(fp, 'r') as zfp:
+ self.assertGreater(len(zfp.infolist()), 0)
+ zinfo = zfp.getinfo("file.txt")
+ (offset, size) = ota_utils.GetZipEntryOffset(zfp, zinfo)
+ self.assertEqual(size, zinfo.file_size)
+ self.assertEqual(offset, zipfile.sizeFileHeader+len(zinfo.filename) + 28)
diff --git a/tools/releasetools/validate_target_files.py b/tools/releasetools/validate_target_files.py
index cfe3139..622e57f 100755
--- a/tools/releasetools/validate_target_files.py
+++ b/tools/releasetools/validate_target_files.py
@@ -251,6 +251,9 @@
def ValidatePartitionFingerprints(input_tmp, info_dict):
build_info = common.BuildInfo(info_dict)
+ if not build_info.avb_enabled:
+ logging.info("AVB not enabled, skipping partition fingerprint checks")
+ return
# Expected format:
# Prop: com.android.build.vendor.fingerprint -> 'generic/aosp_cf_x86_64_phone/vsoc_x86_64:S/AOSP.MASTER/7335886:userdebug/test-keys'
# Prop: com.android.build.vendor_boot.fingerprint -> 'generic/aosp_cf_x86_64_phone/vsoc_x86_64:S/AOSP.MASTER/7335886:userdebug/test-keys'
@@ -258,6 +261,13 @@
r"Prop: com.android.build.(?P<partition>\w+).fingerprint -> '(?P<fingerprint>[\w\/:\.-]+)'")
for vbmeta_partition in ["vbmeta", "vbmeta_system"]:
image = os.path.join(input_tmp, "IMAGES", vbmeta_partition + ".img")
+ if not os.path.exists(image):
+ assert vbmeta_partition != "vbmeta",\
+ "{} is a required partition for AVB.".format(
+ vbmeta_partition)
+ logging.info("vb partition %s not present, skipping", vbmeta_partition)
+ continue
+
output = common.RunAndCheckOutput(
[info_dict["avb_avbtool"], "info_image", "--image", image])
matches = p.findall(output)
diff --git a/tools/signapk/src/com/android/signapk/SignApk.java b/tools/signapk/src/com/android/signapk/SignApk.java
index 7e5c8fc..8bf1005 100644
--- a/tools/signapk/src/com/android/signapk/SignApk.java
+++ b/tools/signapk/src/com/android/signapk/SignApk.java
@@ -1020,6 +1020,7 @@
private static void usage() {
System.err.println("Usage: signapk [-w] " +
"[-a <alignment>] " +
+ "[--align-file-size] " +
"[-providerClass <className>] " +
"[--min-sdk-version <n>] " +
"[--disable-v2] " +
@@ -1044,6 +1045,7 @@
boolean signWholeFile = false;
String providerClass = null;
int alignment = 4;
+ boolean alignFileSize = false;
Integer minSdkVersionOverride = null;
boolean signUsingApkSignatureSchemeV2 = true;
boolean signUsingApkSignatureSchemeV4 = false;
@@ -1063,6 +1065,9 @@
} else if ("-a".equals(args[argstart])) {
alignment = Integer.parseInt(args[++argstart]);
++argstart;
+ } else if ("--align-file-size".equals(args[argstart])) {
+ alignFileSize = true;
+ ++argstart;
} else if ("--min-sdk-version".equals(args[argstart])) {
String minSdkVersionString = args[++argstart];
try {
@@ -1206,12 +1211,22 @@
ByteBuffer[] outputChunks = new ByteBuffer[] {v1SignedApk};
ZipSections zipSections = findMainZipSections(v1SignedApk);
- ApkSignerEngine.OutputApkSigningBlockRequest2 addV2SignatureRequest =
- apkSigner.outputZipSections2(
- DataSources.asDataSource(zipSections.beforeCentralDir),
- DataSources.asDataSource(zipSections.centralDir),
- DataSources.asDataSource(zipSections.eocd));
- if (addV2SignatureRequest != null) {
+
+ ByteBuffer eocd = ByteBuffer.allocate(zipSections.eocd.remaining());
+ eocd.put(zipSections.eocd);
+ eocd.flip();
+ eocd.order(ByteOrder.LITTLE_ENDIAN);
+ // This loop is supposed to be iterated twice at most.
+ // The second pass is to align the file size after amending EOCD comments
+ // with assumption that re-generated signing block would be the same size.
+ while (true) {
+ ApkSignerEngine.OutputApkSigningBlockRequest2 addV2SignatureRequest =
+ apkSigner.outputZipSections2(
+ DataSources.asDataSource(zipSections.beforeCentralDir),
+ DataSources.asDataSource(zipSections.centralDir),
+ DataSources.asDataSource(eocd));
+ if (addV2SignatureRequest == null) break;
+
// Need to insert the returned APK Signing Block before ZIP Central
// Directory.
int padding = addV2SignatureRequest.getPaddingSizeBeforeApkSigningBlock();
@@ -1219,8 +1234,8 @@
// Because the APK Signing Block is inserted before the Central Directory,
// we need to adjust accordingly the offset of Central Directory inside the
// ZIP End of Central Directory (EoCD) record.
- ByteBuffer modifiedEocd = ByteBuffer.allocate(zipSections.eocd.remaining());
- modifiedEocd.put(zipSections.eocd);
+ ByteBuffer modifiedEocd = ByteBuffer.allocate(eocd.remaining());
+ modifiedEocd.put(eocd);
modifiedEocd.flip();
modifiedEocd.order(ByteOrder.LITTLE_ENDIAN);
ApkUtils.setZipEocdCentralDirectoryOffset(
@@ -1235,6 +1250,32 @@
zipSections.centralDir,
modifiedEocd};
addV2SignatureRequest.done();
+
+ // Exit the loop if we don't need to align the file size
+ if (!alignFileSize || alignment < 2) {
+ break;
+ }
+
+ // Calculate the file size
+ eocd = modifiedEocd;
+ int fileSize = 0;
+ for (ByteBuffer buf : outputChunks) {
+ fileSize += buf.remaining();
+ }
+ // Exit the loop because the file size is aligned.
+ if (fileSize % alignment == 0) {
+ break;
+ }
+ // Pad EOCD comment to align the file size.
+ int commentLen = alignment - fileSize % alignment;
+ modifiedEocd = ByteBuffer.allocate(eocd.remaining() + commentLen);
+ modifiedEocd.put(eocd);
+ modifiedEocd.rewind();
+ modifiedEocd.order(ByteOrder.LITTLE_ENDIAN);
+ ApkUtils.updateZipEocdCommentLen(modifiedEocd);
+ // Since V2 signing block should cover modified EOCD,
+ // re-iterate the loop with modified EOCD.
+ eocd = modifiedEocd;
}
// This assumes outputChunks are array-backed. To avoid this assumption, the