Merge "Add build flags for legacy EROFS support."
diff --git a/Changes.md b/Changes.md
index 5edb1d8..cabbed6 100644
--- a/Changes.md
+++ b/Changes.md
@@ -26,6 +26,7 @@
cmd: "cp $(in) $(gendir)",
...
}
+```
`BUILD_BROKEN_INPUT_DIR_MODULES` can be used to allowlist specific directories
with genrules that have input directories.
diff --git a/core/Makefile b/core/Makefile
index 77b0b10..2244453 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -4,6 +4,17 @@
# intermedites-dir-for
LOCAL_PATH := $(BUILD_SYSTEM)
+SYSTEM_NOTICE_DEPS :=
+VENDOR_NOTICE_DEPS :=
+UNMOUNTED_NOTICE_DEPS :=
+ODM_NOTICE_DEPS :=
+OEM_NOTICE_DEPS :=
+PRODUCT_NOTICE_DEPS :=
+SYSTEM_EXT_NOTICE_DEPS :=
+VENDOR_DLKM_NOTICE_DEPS :=
+ODM_DLKM_NOTICE_DEPS :=
+SYSTEM_DLKM_NOTICE_DEPS :=
+
# -----------------------------------------------------------------
# Define rules to copy PRODUCT_COPY_FILES defined by the product.
# PRODUCT_COPY_FILES contains words like <source file>:<dest file>[:<owner>].
@@ -83,6 +94,8 @@
$(pcf_ignored_file):
echo "$(PRIVATE_IGNORED)" | tr " " "\n" >$@
+$(call declare-0p-target,$(pcf_ignored_file))
+
$(call dist-for-goals,droidcore-unbundled,$(pcf_ignored_file):logs/$(notdir $(pcf_ignored_file)))
pcf_ignored_file :=
@@ -157,6 +170,8 @@
echo "HTML_OUTPUT=$(ndk_doxygen_out)" \
) | doxygen -
+$(call declare-1p-target,$(ndk_doxygen_out)/index.html,)
+
# Note: Not a part of the docs target because we don't have doxygen available.
# You can run this target locally if you have doxygen installed.
ndk-docs: $(ndk_doxygen_out)/index.html
@@ -212,6 +227,8 @@
echo "$$x"generic >> $@.tmp; done
$(hide) mv $@.tmp $@
+$(call declare-0p-target,$(INSTALLED_SDK_BUILD_PROP_TARGET))
+
# -----------------------------------------------------------------
# declare recovery ramdisk files
ifeq ($(BUILDING_RECOVERY_IMAGE),true)
@@ -507,6 +524,12 @@
VENDOR_RAMDISK_STRIPPED_MODULE_STAGING_DIR :=
endif
+ifneq ($(BOARD_DO_NOT_STRIP_VENDOR_KERNEL_RAMDISK_MODULES),true)
+ VENDOR_KERNEL_RAMDISK_STRIPPED_MODULE_STAGING_DIR := $(call intermediates-dir-for,PACKAGING,depmod_vendor_kernel_ramdisk_stripped)
+else
+ VENDOR_KERNEL_RAMDISK_STRIPPED_MODULE_STAGING_DIR :=
+endif
+
BOARD_KERNEL_MODULE_DIRS += top
$(foreach kmd,$(BOARD_KERNEL_MODULE_DIRS), \
$(eval ALL_DEFAULT_INSTALLED_MODULES += $(call build-image-kernel-modules-dir,RECOVERY,$(TARGET_RECOVERY_ROOT_OUT),,modules.load.recovery,$(RECOVERY_STRIPPED_MODULE_STAGING_DIR),$(kmd))) \
@@ -518,6 +541,7 @@
$(eval output_dir := $(TARGET_VENDOR_RAMDISK_OUT)) \
$(eval result_var := ALL_DEFAULT_INSTALLED_MODULES)) \
$(eval $(result_var) += $(call build-image-kernel-modules-dir,VENDOR_RAMDISK,$(output_dir),,modules.load,$(VENDOR_RAMDISK_STRIPPED_MODULE_STAGING_DIR),$(kmd))) \
+ $(eval ALL_DEFAULT_INSTALLED_MODULES += $(call build-image-kernel-modules-dir,VENDOR_KERNEL_RAMDISK,$(TARGET_VENDOR_KERNEL_RAMDISK_OUT),,modules.load,$(VENDOR_KERNEL_RAMDISK_STRIPPED_MODULE_STAGING_DIR),$(kmd))) \
$(eval ALL_DEFAULT_INSTALLED_MODULES += $(call build-vendor-ramdisk-recovery-load,$(kmd))) \
$(eval ALL_DEFAULT_INSTALLED_MODULES += $(call build-image-kernel-modules-dir,VENDOR,$(if $(filter true,$(BOARD_USES_VENDOR_DLKMIMAGE)),$(TARGET_OUT_VENDOR_DLKM),$(TARGET_OUT_VENDOR)),vendor,modules.load,$(VENDOR_STRIPPED_MODULE_STAGING_DIR),$(kmd))) \
$(eval ALL_DEFAULT_INSTALLED_MODULES += $(call build-vendor-charger-load,$(kmd))) \
@@ -580,6 +604,8 @@
# In case value of PACKAGES is empty.
$(hide) touch $@
+$(call declare-0p-target,$(APKCERTS_FILE))
+
.PHONY: apkcerts-list
apkcerts-list: $(APKCERTS_FILE)
@@ -596,6 +622,7 @@
@rm -f $@
@$(foreach s,$(STATS.MODULE_TYPE),echo "modules_type_make,$(s),$(words $(STATS.MODULE_TYPE.$(s)))" >>$@;)
@$(foreach s,$(STATS.SOONG_MODULE_TYPE),echo "modules_type_soong,$(s),$(STATS.SOONG_MODULE_TYPE.$(s))" >>$@;)
+$(call declare-1p-target,$(BUILD_SYSTEM_STATS),build)
$(call dist-for-goals,droidcore-unbundled,$(BUILD_SYSTEM_STATS))
# -----------------------------------------------------------------
@@ -616,35 +643,48 @@
@rm -f $@
@$(foreach s,$(SOONG_CONV),echo "$(s),$(SOONG_CONV.$(s).TYPE),$(sort $(SOONG_CONV.$(s).PROBLEMS)),$(sort $(filter-out $(SOONG_ALREADY_CONV),$(SOONG_CONV.$(s).DEPS))),$(sort $(SOONG_CONV.$(s).MAKEFILES)),$(sort $(SOONG_CONV.$(s).INSTALLED))" >>$@;)
+$(call declare-1p-target,$(SOONG_CONV_DATA),build)
+
SOONG_TO_CONVERT_SCRIPT := build/make/tools/soong_to_convert.py
SOONG_TO_CONVERT := $(PRODUCT_OUT)/soong_to_convert.txt
$(SOONG_TO_CONVERT): $(SOONG_CONV_DATA) $(SOONG_TO_CONVERT_SCRIPT)
@rm -f $@
$(hide) $(SOONG_TO_CONVERT_SCRIPT) $< >$@
+$(call declare-1p-target,$(SOONG_TO_CONVERT),build)
$(call dist-for-goals,droidcore-unbundled,$(SOONG_TO_CONVERT))
+$(PRODUCT_OUT)/product_packages.txt:
+ @rm -f $@
+ echo "" > $@
+ $(foreach x,$(PRODUCT_PACKAGES),echo $(x) >> $@$(newline))
+
MK2BP_CATALOG_SCRIPT := build/make/tools/mk2bp_catalog.py
+PRODUCT_PACKAGES_TXT := $(PRODUCT_OUT)/product_packages.txt
MK2BP_REMAINING_HTML := $(PRODUCT_OUT)/mk2bp_remaining.html
$(MK2BP_REMAINING_HTML): PRIVATE_CODE_SEARCH_BASE_URL := "https://cs.android.com/android/platform/superproject/+/master:"
-$(MK2BP_REMAINING_HTML): $(SOONG_CONV_DATA) $(MK2BP_CATALOG_SCRIPT)
+$(MK2BP_REMAINING_HTML): $(SOONG_CONV_DATA) $(MK2BP_CATALOG_SCRIPT) $(PRODUCT_PACKAGES_TXT)
@rm -f $@
$(hide) $(MK2BP_CATALOG_SCRIPT) \
--device=$(TARGET_DEVICE) \
+ --product-packages=$(PRODUCT_PACKAGES_TXT) \
--title="Remaining Android.mk files for $(TARGET_DEVICE)-$(TARGET_BUILD_VARIANT)" \
--codesearch=$(PRIVATE_CODE_SEARCH_BASE_URL) \
- --out_dir="$(OUT_DIR)" \
+ --out-dir="$(OUT_DIR)" \
--mode=html \
> $@
+$(call declare-1p-target,$(MK2BP_REMAINING_HTML),build)
$(call dist-for-goals,droidcore-unbundled,$(MK2BP_REMAINING_HTML))
MK2BP_REMAINING_CSV := $(PRODUCT_OUT)/mk2bp_remaining.csv
-$(MK2BP_REMAINING_CSV): $(SOONG_CONV_DATA) $(MK2BP_CATALOG_SCRIPT)
+$(MK2BP_REMAINING_CSV): $(SOONG_CONV_DATA) $(MK2BP_CATALOG_SCRIPT) $(PRODUCT_PACKAGES_TXT)
@rm -f $@
$(hide) $(MK2BP_CATALOG_SCRIPT) \
--device=$(TARGET_DEVICE) \
- --out_dir="$(OUT_DIR)" \
+ --product-packages=$(PRODUCT_PACKAGES_TXT) \
+ --out-dir="$(OUT_DIR)" \
--mode=csv \
> $@
+$(call declare-1p-target,$(MK2BP_REMAINING_CSV))
$(call dist-for-goals,droidcore-unbundled,$(MK2BP_REMAINING_CSV))
# -----------------------------------------------------------------
@@ -657,12 +697,16 @@
echo "# Modules added default -Wall" >> $@
for m in $(sort $(SOONG_MODULES_ADDED_WALL) $(MODULES_ADDED_WALL)); do echo $$m >> $@; done
+$(call declare-0p-target,$(WALL_WERROR))
+
$(call dist-for-goals,droidcore-unbundled,$(WALL_WERROR))
# -----------------------------------------------------------------
# C/C++ flag information for modules
$(call dist-for-goals,droidcore-unbundled,$(SOONG_MODULES_CFLAG_ARTIFACTS))
+$(foreach a,$(SOONG_MODULES_CFLAG_ARTIFACTS),$(call declare-0p-target,$(call word-colon,1,$(a))))
+
# -----------------------------------------------------------------
# Modules missing profile files
PGO_PROFILE_MISSING := $(PRODUCT_OUT)/pgo_profile_file_missing.txt
@@ -671,12 +715,15 @@
echo "# Modules missing PGO profile files" >> $@
for m in $(SOONG_MODULES_MISSING_PGO_PROFILE_FILE); do echo $$m >> $@; done
+$(call declare-0p-target,$(PGO_PROFILE_MISSING))
+
$(call dist-for-goals,droidcore,$(PGO_PROFILE_MISSING))
CERTIFICATE_VIOLATION_MODULES_FILENAME := $(PRODUCT_OUT)/certificate_violation_modules.txt
$(CERTIFICATE_VIOLATION_MODULES_FILENAME):
rm -f $@
$(foreach m,$(sort $(CERTIFICATE_VIOLATION_MODULES)), echo $(m) >> $@;)
+$(call declare-0p-target,$(CERTIFICATE_VIOLATION_MODULES_FILENAME))
$(call dist-for-goals,droidcore,$(CERTIFICATE_VIOLATION_MODULES_FILENAME))
# -----------------------------------------------------------------
@@ -713,6 +760,8 @@
$(hide) mkdir -p $(dir $@)
$(hide) $(MERGETAGS) -o $@ $(PRIVATE_SRC_FILES)
+$(call declare-0p-target,$(all_event_log_tags_file))
+
# Include tags from all packages included in this product, plus all
# tags that are part of the system (ie, not in a vendor/ or device/
# directory).
@@ -729,10 +778,19 @@
$(hide) mkdir -p $(dir $@)
$(hide) $(MERGETAGS) -o $@ -m $(PRIVATE_MERGED_FILE) $(PRIVATE_SRC_FILES)
+$(eval $(call declare-0p-target,$(event_log_tags_file)))
+
event-log-tags: $(event_log_tags_file)
ALL_DEFAULT_INSTALLED_MODULES += $(event_log_tags_file)
+# Initialize INSTALLED_FILES_OUTSIDE_IMAGES with the list of all device files,
+# files installed in images will be filtered out later.
+INSTALLED_FILES_OUTSIDE_IMAGES := $(filter-out \
+ $(PRODUCT_OUT)/apex/% \
+ $(PRODUCT_OUT)/fake_packages/% \
+ $(PRODUCT_OUT)/testcases/%, \
+ $(filter $(PRODUCT_OUT)/%,$(ALL_DEFAULT_INSTALLED_MODULES)))
# #################################################################
# Targets for boot/OS images
@@ -765,10 +823,11 @@
# -----------------------------------------------------------------
# the root dir
+INSTALLED_FILES_OUTSIDE_IMAGES := $(filter-out $(TARGET_ROOT_OUT)/%, $(INSTALLED_FILES_OUTSIDE_IMAGES))
INTERNAL_ROOT_FILES := $(filter $(TARGET_ROOT_OUT)/%, \
- $(ALL_GENERATED_SOURCES) \
$(ALL_DEFAULT_INSTALLED_MODULES))
+
INSTALLED_FILES_FILE_ROOT := $(PRODUCT_OUT)/installed-files-root.txt
INSTALLED_FILES_JSON_ROOT := $(INSTALLED_FILES_FILE_ROOT:.txt=.json)
$(INSTALLED_FILES_FILE_ROOT): .KATI_IMPLICIT_OUTPUTS := $(INSTALLED_FILES_JSON_ROOT)
@@ -780,6 +839,9 @@
$(FILESLIST) $(TARGET_ROOT_OUT) > $(@:.txt=.json)
$(FILESLIST_UTIL) -c $(@:.txt=.json) > $@
+$(call declare-0p-target,$(INSTALLED_FILES_FILE_ROOT))
+$(call declare-0p-target,$(INSTALLED_FILES_JSON_ROOT))
+
ifeq ($(HOST_OS),linux)
$(call dist-for-goals, sdk sdk_addon, $(INSTALLED_FILES_FILE_ROOT))
endif
@@ -796,9 +858,9 @@
# -----------------------------------------------------------------
# the ramdisk
+INSTALLED_FILES_OUTSIDE_IMAGES := $(filter-out $(TARGET_RAMDISK_OUT)/%, $(INSTALLED_FILES_OUTSIDE_IMAGES))
ifdef BUILDING_RAMDISK_IMAGE
INTERNAL_RAMDISK_FILES := $(filter $(TARGET_RAMDISK_OUT)/%, \
- $(ALL_GENERATED_SOURCES) \
$(ALL_DEFAULT_INSTALLED_MODULES))
INSTALLED_FILES_FILE_RAMDISK := $(PRODUCT_OUT)/installed-files-ramdisk.txt
@@ -812,6 +874,9 @@
$(FILESLIST) $(TARGET_RAMDISK_OUT) > $(@:.txt=.json)
$(FILESLIST_UTIL) -c $(@:.txt=.json) > $@
+$(eval $(call declare-0p-target,$(INSTALLED_FILES_FILE_RAMDISK)))
+$(eval $(call declare-0p-target,$(INSTALLED_FILES_JSON_RAMDISK)))
+
ifeq ($(HOST_OS),linux)
$(call dist-for-goals, sdk sdk_addon, $(INSTALLED_FILES_FILE_RAMDISK))
endif
@@ -839,6 +904,11 @@
endif
$(hide) $(MKBOOTFS) -d $(TARGET_OUT) $(TARGET_RAMDISK_OUT) | $(COMPRESSION_COMMAND) > $@
+$(call declare-1p-container,$(INSTALLED_RAMDISK_TARGET),)
+$(call declare-container-license-deps,$(INSTALLED_RAMDISK_TARGET),$(INTERNAL_RAMDISK_FILE),$(PRODUCT_OUT)/:/)
+
+UNMOUNTED_NOTICE_DEPS += $(INSTALLED_RAMDISK_TARGET)
+
.PHONY: ramdisk-nodeps
ramdisk-nodeps: $(MKBOOTFS) | $(COMPRESSION_COMMAND_DEPS)
@echo "make $@: ignoring dependencies"
@@ -953,9 +1023,15 @@
endif
endif # BUILDING_VENDOR_BOOT_IMAGE == "" && BOARD_USES_GENERIC_KERNEL_IMAGE != true
-INTERNAL_MKBOOTIMG_VERSION_ARGS := \
+ifdef BOARD_GKI_SIGNING_KEY_PATH
+ # GKI boot images will not set system version & SPL value in the header.
+ # They can be set by the device manufacturer in the AVB properties instead.
+ INTERNAL_MKBOOTIMG_VERSION_ARGS :=
+else
+ INTERNAL_MKBOOTIMG_VERSION_ARGS := \
--os_version $(PLATFORM_VERSION_LAST_STABLE) \
--os_patch_level $(PLATFORM_SECURITY_PATCH)
+endif # BOARD_GKI_SIGNING_KEY_PATH
# $(1): image target to certify
# $(2): out certificate target
@@ -1030,6 +1106,11 @@
$(call pretty,"Target boot image: $@")
$(call build_boot_board_avb_enabled,$@)
+$(call declare-1p-container,$(INSTALLED_BOOTIMAGE_TARGET),)
+$(call declare-container-license-deps,$(INSTALLED_BOOTIMAGE_TARGET),$(INTERNAL_BOOTIMAGE_FILES) $(INTERNAL_GKI_CERTIFICATE_DEPS),$(PRODUCT_OUT)/:/)
+
+UNMOUNTED_NOTICE_DEPS += $(INSTALLED_BOOTIMAGE_TARGET)
+
.PHONY: bootimage-nodeps
bootimage-nodeps: $(MKBOOTIMG) $(AVBTOOL) $(BOARD_AVB_BOOT_KEY_PATH) $(INTERNAL_GKI_CERTIFICATE_DEPS)
@echo "make $@: ignoring dependencies"
@@ -1048,6 +1129,11 @@
$(call pretty,"Target boot image: $@")
$(call build_boot_supports_boot_signer,$@)
+$(call declare-1p-container,$(INSTALLED_BOOTIMAGE_TARGET),)
+$(call declare-container-license-deps,$(INSTALLED_BOOTIMAGE_TARGET),$(INTERNAL_BOOTIMAGE_FILES),$(PRODUCT_OUT)/:/)
+
+UNMOUNTED_NOTICE_DEPS += $(INSTALLED_BOOTIMAGE_TARGET)
+
.PHONY: bootimage-nodeps
bootimage-nodeps: $(MKBOOTIMG) $(BOOT_SIGNER)
@echo "make $@: ignoring dependencies"
@@ -1066,6 +1152,11 @@
$(call pretty,"Target boot image: $@")
$(call build_boot_supports_vboot,$@)
+$(call declare-1p-container,$(INSTALLED_BOOTIMAGE_TARGET),)
+$(call declare-container-license-deps,$(INSTALLED_BOOTIMAGE_TARGET),$(INTERNAL_BOOTIMAGE_FILES),$(PRODUCT_OUT)/:/)
+
+UNMOUNTED_NOTICE_DEPS += $(INSTALLED_BOOTIMAGE_TARGET)
+
.PHONY: bootimage-nodeps
bootimage-nodeps: $(MKBOOTIMG) $(VBOOT_SIGNER) $(FUTILITY)
@echo "make $@: ignoring dependencies"
@@ -1083,6 +1174,11 @@
$(call pretty,"Target boot image: $@")
$(call build_boot_novboot,$@)
+$(call declare-1p-container,$(INSTALLED_BOOTIMAGE_TARGET),)
+$(call declare-container-license-deps,$(INSTALLED_BOOTIMAGE_TARGET),$(INTERNAL_BOOTIMAGE_FILES),$(PRODUCT_OUT)/:/)
+
+UNMOUNTED_NOTICE_DEPS += $(INSTALLED_BOOTIMAGE_TARGET)
+
.PHONY: bootimage-nodeps
bootimage-nodeps: $(MKBOOTIMG)
@echo "make $@: ignoring dependencies"
@@ -1104,6 +1200,11 @@
$(call get-partition-size-argument,$(BOARD_BOOTIMAGE_PARTITION_SIZE)) \
--partition_name boot $(INTERNAL_AVB_BOOT_SIGNING_ARGS) \
$(BOARD_AVB_BOOT_ADD_HASH_FOOTER_ARGS)
+
+$(call declare-1p-container,$(INSTALLED_BOOTIMAGE_TARGET),)
+$(call declare-container-license-deps,$(INSTALLED_BOOTIMAGE_TARGET),$(INTERNAL_PREBUILT_BOOTIMAGE),$(PRODUCT_OUT)/:/)
+
+UNMOUNTED_NOTICE_DEPS += $(INSTALLED_BOOTIMAGE_TARGET)
else
$(INSTALLED_BOOTIMAGE_TARGET): $(INTERNAL_PREBUILT_BOOTIMAGE)
cp $(INTERNAL_PREBUILT_BOOTIMAGE) $@
@@ -1139,13 +1240,20 @@
$(call get-partition-size-argument,$(BOARD_INIT_BOOT_IMAGE_PARTITION_SIZE)) \
--partition_name init_boot $(INTERNAL_AVB_INIT_BOOT_SIGNING_ARGS) \
$(BOARD_AVB_INIT_BOOT_ADD_HASH_FOOTER_ARGS)
+
+$(call declare-1p-container,$(INSTALLED_INIT_BOOT_IMAGE_TARGET),)
+$(call declare-container-license-deps,$(INSTALLED_INIT_BOOT_IMAGE_TARGET),$(INTERNAL_GENERIC_RAMDISK_BOOT_SIGNATURE),$(PRODUCT_OUT)/:/)
else
$(INSTALLED_INIT_BOOT_IMAGE_TARGET):
$(call pretty,"Target init_boot image: $@")
$(MKBOOTIMG) $(INTERNAL_INIT_BOOT_IMAGE_ARGS) $(INTERNAL_MKBOOTIMG_VERSION_ARGS) $(BOARD_MKBOOTIMG_INIT_ARGS) --output $@
$(call assert-max-image-size,$@,$(BOARD_INIT_BOOT_IMAGE_PARTITION_SIZE))
+
+$(call declare-1p-target,$(INSTALLED_INIT_BOOT_IMAGE_TARGET),)
endif
+UNMOUNTED_NOTICE_DEPS += $(INSTALLED_INIT_BOOT_IMAGE_TARGET)
+
else # BUILDING_INIT_BOOT_IMAGE is not true
ifdef BOARD_PREBUILT_INIT_BOOT_IMAGE
@@ -1160,11 +1268,18 @@
$(call get-partition-size-argument,$(BOARD_INIT_BOOT_IMAGE_PARTITION_SIZE)) \
--partition_name boot $(INTERNAL_AVB_INIT_BOOT_SIGNING_ARGS) \
$(BOARD_AVB_INIT_BOOT_ADD_HASH_FOOTER_ARGS)
+
+$(call declare-1p-container,$(INSTALLED_INIT_BOOT_IMAGE_TARGET),)
+$(call declare-container-license-deps,$(INSTALLED_INIT_BOOT_IMAGE_TARGET),$(INTERNAL_PREBUILT_INIT_BOOT_IMAGE),$(PRODUCT_OUT)/:/)
else
$(INSTALLED_INIT_BOOT_IMAGE_TARGET): $(INTERNAL_PREBUILT_INIT_BOOT_IMAGE)
cp $(INTERNAL_PREBUILT_INIT_BOOT_IMAGE) $@
+
+$(call declare-1p-target,$(INSTALLED_INIT_BOOT_IMAGE_TARGET),)
endif # BOARD_AVB_ENABLE
+UNMOUNTED_NOTICE_DEPS += $(INSTALLED_INIT_BOOT_IMAGE_TARGET)
+
else # BOARD_PREBUILT_INIT_BOOT_IMAGE not defined
INSTALLED_INIT_BOOT_IMAGE_TARGET :=
endif # BOARD_PREBUILT_INIT_BOOT_IMAGE
@@ -1173,6 +1288,7 @@
# -----------------------------------------------------------------
# vendor boot image
+INSTALLED_FILES_OUTSIDE_IMAGES := $(filter-out $(TARGET_VENDOR_RAMDISK_OUT)/%, $(INSTALLED_FILES_OUTSIDE_IMAGES))
ifeq ($(BUILDING_VENDOR_BOOT_IMAGE),true)
ifeq ($(PRODUCT_SUPPORTS_VERITY),true)
@@ -1180,7 +1296,6 @@
endif
INTERNAL_VENDOR_RAMDISK_FILES := $(filter $(TARGET_VENDOR_RAMDISK_OUT)/%, \
- $(ALL_GENERATED_SOURCES) \
$(ALL_DEFAULT_INSTALLED_MODULES))
INTERNAL_VENDOR_RAMDISK_TARGET := $(call intermediates-dir-for,PACKAGING,vendor_boot)/vendor_ramdisk.cpio$(RAMDISK_EXT)
@@ -1202,6 +1317,11 @@
@echo "Target vendor ramdisk: $@"
$(copy-file-to-target)
+$(call declare-1p-container,$(INSTALLED_VENDOR_RAMDISK_TARGET),)
+$(call declare-container-license-deps,$(INSTALLED_VENDOR_RAMDISK_TARGET),$(INTERNAL_VENDOR_RAMDISK_TARGET),$(PRODUCT_OUT)/:/)
+
+VENDOR_NOTICE_DEPS += $(INSTALLED_VENDOR_RAMDISK_TARGET)
+
INSTALLED_FILES_FILE_VENDOR_RAMDISK := $(PRODUCT_OUT)/installed-files-vendor-ramdisk.txt
INSTALLED_FILES_JSON_VENDOR_RAMDISK := $(INSTALLED_FILES_FILE_VENDOR_RAMDISK:.txt=.json)
$(INSTALLED_FILES_FILE_VENDOR_RAMDISK): .KATI_IMPLICIT_OUTPUTS := $(INSTALLED_FILES_JSON_VENDOR_RAMDISK)
@@ -1213,8 +1333,15 @@
$(FILESLIST) $(TARGET_VENDOR_RAMDISK_OUT) > $(@:.txt=.json)
$(FILESLIST_UTIL) -c $(@:.txt=.json) > $@
+$(eval $(call declare-0p-target,$(INSTALLED_FILES_FILE_VENDOR_RAMDISK)))
+$(eval $(call declare-0p-target,$(INSTALLED_FILES_JSON_VENDOR_RAMDISK)))
+
ifdef BOARD_INCLUDE_DTB_IN_BOOTIMG
- INTERNAL_VENDOR_BOOTIMAGE_ARGS += --dtb $(INSTALLED_DTBIMAGE_TARGET)
+ ifneq ($(BUILDING_VENDOR_KERNEL_BOOT_IMAGE),true)
+ # If we have vendor_kernel_boot partition, we migrate dtb image to that image
+ # and allow dtb in vendor_boot to be empty.
+ INTERNAL_VENDOR_BOOTIMAGE_ARGS += --dtb $(INSTALLED_DTBIMAGE_TARGET)
+ endif
endif
ifdef BOARD_KERNEL_BASE
INTERNAL_VENDOR_BOOTIMAGE_ARGS += --base $(BOARD_KERNEL_BASE)
@@ -1294,9 +1421,83 @@
$(MKBOOTIMG) $(INTERNAL_VENDOR_BOOTIMAGE_ARGS) $(BOARD_MKBOOTIMG_ARGS) --vendor_ramdisk $(INTERNAL_VENDOR_RAMDISK_TARGET) $(INTERNAL_VENDOR_RAMDISK_FRAGMENT_ARGS) --vendor_boot $@
$(call assert-max-image-size,$@,$(BOARD_VENDOR_BOOTIMAGE_PARTITION_SIZE))
endif
+
+$(call declare-1p-container,$(INSTALLED_VENDOR_BOOTIMAGE_TARGET),)
+$(call declare-container-license-deps,$(INSTALLED_VENDOR_BOOTIMAGE_TARGET),$(INTERNAL_VENDOR_RAMDISK_TARGET) $(INSTALLED_DTB_IMAGE_TARGET) $(INTERNAL_VENDOR_RAMDISK_FRAGMENT_TARGETS) $(INTERNAL_VENDOR_BOOTCONDIG_TARGET),$(PRODUCT_OUT)/:/)
+VENDOR_NOTICE_DEPS += $(INSTALLED_VENDOR_BOOTIMAGE_TARGET)
endif # BUILDING_VENDOR_BOOT_IMAGE
# -----------------------------------------------------------------
+# vendor kernel boot image
+ifeq ($(BUILDING_VENDOR_KERNEL_BOOT_IMAGE),true)
+
+INTERNAL_VENDOR_KERNEL_RAMDISK_FILES := $(filter $(TARGET_VENDOR_KERNEL_RAMDISK_OUT)/%, \
+ $(ALL_DEFAULT_INSTALLED_MODULES))
+
+INTERNAL_VENDOR_KERNEL_RAMDISK_TARGET := $(call intermediates-dir-for,PACKAGING,vendor_kernel_boot)/vendor_kernel_ramdisk.cpio$(RAMDISK_EXT)
+
+$(INTERNAL_VENDOR_KERNEL_RAMDISK_TARGET): $(MKBOOTFS) $(INTERNAL_VENDOR_KERNEL_RAMDISK_FILES) | $(COMPRESSION_COMMAND_DEPS)
+ $(MKBOOTFS) -d $(TARGET_OUT) $(TARGET_VENDOR_KERNEL_RAMDISK_OUT) | $(COMPRESSION_COMMAND) > $@
+
+INSTALLED_VENDOR_KERNEL_RAMDISK_TARGET := $(PRODUCT_OUT)/vendor_kernel_ramdisk.img
+$(INSTALLED_VENDOR_KERNEL_RAMDISK_TARGET): $(INTERNAL_VENDOR_KERNEL_RAMDISK_TARGET)
+ @echo "Target vendor kernel ramdisk: $@"
+ $(copy-file-to-target)
+
+INSTALLED_FILES_FILE_VENDOR_KERNEL_RAMDISK := $(PRODUCT_OUT)/installed-files-vendor-kernel-ramdisk.txt
+INSTALLED_FILES_JSON_VENDOR_KERNEL_RAMDISK := $(INSTALLED_FILES_FILE_VENDOR_KERNEL_RAMDISK:.txt=.json)
+$(INSTALLED_FILES_FILE_VENDOR_KERNEL_RAMDISK): .KATI_IMPLICIT_OUTPUTS := $(INSTALLED_FILES_JSON_VENDOR_KERNEL_RAMDISK)
+$(INSTALLED_FILES_FILE_VENDOR_KERNEL_RAMDISK): $(INTERNAL_VENDOR_KERNEL_RAMDISK_TARGET)
+$(INSTALLED_FILES_FILE_VENDOR_KERNEL_RAMDISK): $(INTERNAL_VENDOR_KERNEL_RAMDISK_FILES) $(FILESLIST) $(FILESLIST_UTIL)
+ @echo Installed file list: $@
+ mkdir -p $(dir $@)
+ rm -f $@
+ $(FILESLIST) $(TARGET_VENDOR_KERNEL_RAMDISK_OUT) > $(@:.txt=.json)
+ $(FILESLIST_UTIL) -c $(@:.txt=.json) > $@
+
+$(call declare-0p-target,$(INSTALLED_FILES_FILE_VENDOR_KERNEL_RAMDISK))
+$(call declare-0p-target,$(INSTALLED_FILES_JSON_VENDOR_KERNEL_RAMDISK))
+
+INTERNAL_VENDOR_KERNEL_BOOTIMAGE_ARGS := --vendor_ramdisk $(INTERNAL_VENDOR_KERNEL_RAMDISK_TARGET)
+INSTALLED_VENDOR_KERNEL_BOOTIMAGE_TARGET := $(PRODUCT_OUT)/vendor_kernel_boot.img
+$(INSTALLED_VENDOR_KERNEL_BOOTIMAGE_TARGET): $(MKBOOTIMG) $(INTERNAL_VENDOR_KERNEL_RAMDISK_TARGET)
+
+ifdef BOARD_INCLUDE_DTB_IN_BOOTIMG
+ INTERNAL_VENDOR_KERNEL_BOOTIMAGE_ARGS += --dtb $(INSTALLED_DTBIMAGE_TARGET)
+ $(INSTALLED_VENDOR_KERNEL_BOOTIMAGE_TARGET): $(INSTALLED_DTBIMAGE_TARGET)
+endif
+ifdef BOARD_KERNEL_PAGESIZE
+ INTERNAL_VENDOR_KERNEL_BOOTIMAGE_ARGS += --pagesize $(BOARD_KERNEL_PAGESIZE)
+endif
+
+
+ifeq ($(BOARD_AVB_ENABLE),true)
+$(INSTALLED_VENDOR_KERNEL_BOOTIMAGE_TARGET): $(AVBTOOL) $(BOARD_AVB_VENDOR_KERNEL_BOOTIMAGE_KEY_PATH)
+ $(call pretty,"Target vendor_kernel_boot image: $@")
+ $(MKBOOTIMG) $(INTERNAL_VENDOR_KERNEL_BOOTIMAGE_ARGS) $(BOARD_MKBOOTIMG_ARGS) --vendor_boot $@
+ $(call assert-max-image-size,$@,$(BOARD_VENDOR_KERNEL_BOOTIMAGE_PARTITION_SIZE))
+ $(AVBTOOL) add_hash_footer \
+ --image $@ \
+ $(call get-partition-size-argument,$(BOARD_VENDOR_KERNEL_BOOTIMAGE_PARTITION_SIZE)) \
+ --partition_name vendor_kernel_boot $(INTERNAL_AVB_VENDOR_KERNEL_BOOT_SIGNING_ARGS) \
+ $(BOARD_AVB_VENDOR_KERNEL_BOOT_ADD_HASH_FOOTER_ARGS)
+else
+$(INSTALLED_VENDOR_KERNEL_BOOTIMAGE_TARGET):
+ $(call pretty,"Target vendor_kernel_boot image: $@")
+ $(MKBOOTIMG) $(INTERNAL_VENDOR_KERNEL_BOOTIMAGE_ARGS) $(BOARD_MKBOOTIMG_ARGS) --vendor_boot $@
+ $(call assert-max-image-size,$@,$(BOARD_VENDOR_KERNEL_BOOTIMAGE_PARTITION_SIZE))
+endif
+$(call declare-1p-container,$(INSTALLED_VENDOR_KERNEL_BOOTIMAGE_TARGET),)
+ifdef BOARD_INCLUDE_DTB_IN_BOOTIMG
+$(call declare-container-license-deps,$(INSTALLED_VENDOR_KERNEL_BOOTIMAGE_TARGET),\
+ $(INTERNAL_VENDOR_KERNEL_RAMDISK_TARGET) $(INSTALLED_DTBIMAGE_TARGET),\
+ $(INSTALLED_VENDOR_KERNEL_BOOTIMAGE_TARGET):)
+else
+$(call declare-container-license-deps,$(INSTALLED_VENDOR_KERNEL_BOOTIMAGE_TARGET),$(INTERNAL_VENDOR_KERNEL_RAMDISK_TARGET),$(INSTALLED_VENDOR_KERNEL_BOOTIMAGE_TARGET):)
+endif
+endif # BUILDING_VENDOR_KERNEL_BOOT_IMAGE
+
+# -----------------------------------------------------------------
# NOTICE files
#
# We are required to publish the licenses for all code under BSD, GPL and
@@ -1310,49 +1511,57 @@
.PHONY: notice_files
-# Create the rule to combine the files into text and html/xml forms
-# $(1) - xml_excluded_system_product_odm_vendor_dlkm_odm_dlkm|
-# xml_excluded_vendor_product_odm_vendor_dlkm_odm_dlkm|
-# xml_product|xml_odm|xml_system_ext|xml_system|xml_vendor_dlkm|
-# xml_odm_dlkm|html
-# $(2) - Plain text output file
-# $(3) - HTML/XML output file
-# $(4) - File title
-# $(5) - Directory to use. Notice files are all $(5)/src. Other
-# directories in there will be used for scratch
-# $(6) - Dependencies for the output files
-# $(7) - Directories to exclude
+# Convert license metadata into xml notice file.
+# $(1) - Output target notice filename
+# $(2) - Product name
+# $(3) - File title
+# $(4) - License metadata file roots
+# $(5) - Prefixes to strip
#
-# The algorithm here is that we go collect a hash for each of the notice
-# files and write the names of the files that match that hash. Then
-# to generate the real files, we go print out all of the files and their
-# hashes.
-#
-# These rules are fairly complex, so they depend on this makefile so if
-# it changes, they'll run again.
-#
-# TODO: We could clean this up so that we just record the locations of the
-# original notice files instead of making rules to copy them somwehere.
-# Then we could traverse that without quite as much bash drama.
-define combine-notice-files
-$(2): PRIVATE_MESSAGE := $(4)
-$(2): PRIVATE_DIR := $(5)
-$(2): .KATI_IMPLICIT_OUTPUTS := $(3)
-$(2): $(6) $(BUILD_SYSTEM)/Makefile build/make/tools/generate-notice-files.py
- build/make/tools/generate-notice-files.py --text-output $(2) $(foreach xdir, $(7), -e $(xdir) )\
- $(if $(filter $(1),xml_excluded_vendor_product_odm_vendor_dlkm_odm_dlkm),-e vendor -e product -e system_ext -e odm -e vendor_dlkm -e odm_dlkm --xml-output, \
- $(if $(filter $(1),xml_excluded_system_product_odm_vendor_dlkm_odm_dlkm),-e system -e product -e system_ext -e odm -e vendor_dlkm -e odm_dlkm --xml-output, \
- $(if $(filter $(1),xml_product),-i product --xml-output, \
- $(if $(filter $(1),xml_system_ext),-i system_ext --xml-output, \
- $(if $(filter $(1),xml_system),-i system --xml-output, \
- $(if $(filter $(1),xml_odm),-i odm --xml-output, \
- $(if $(filter $(1),xml_vendor_dlkm),-i vendor_dlkm --xml-output, \
- $(if $(filter $(1),xml_odm_dlkm),-i odm_dlkm --xml-output, \
- --html-output)))))))) $(3) \
- -t $$(PRIVATE_MESSAGE) $$(foreach dir,$$(sort $$(PRIVATE_DIR)), -s $$(dir)/src)
-notice_files: $(2) $(3)
+define xml-notice-rule
+$(1): PRIVATE_PRODUCT := $(2)
+$(1): PRIVATE_MESSAGE := $(3)
+$(1): PRIVATE_DEPS := $(call corresponding-license-metadata,$(4))
+$(1): $(call corresponding-license-metadata,$(4)) $(XMLNOTICE) $(BUILD_SYSTEM)/Makefile
+ OUT_DIR=$(OUT_DIR) $(XMLNOTICE) -o $$@ -product=$$(PRIVATE_PRODUCT) -title=$$(PRIVATE_MESSAGE) $(foreach prefix, $(5), -strip_prefix=$(prefix)) $$(PRIVATE_DEPS)
+
+notice_files: $(1)
endef
+# Convert license metadata into text notice file.
+# $(1) - Output target notice filename
+# $(2) - Product name
+# $(3) - File title
+# $(4) - License metadata file roots
+# $(5) - Prefixes to strip
+#
+define text-notice-rule
+$(1): PRIVATE_PRODUCT := $(2)
+$(1): PRIVATE_MESSAGE := $(3)
+$(1): $(call corresponding-license-metadata,$(4)) $(TEXTNOTICE) $(BUILD_SYSTEM)/Makefile
+ OUT_DIR=$(OUT_DIR) $(TEXTNOTICE) -o $$@ -product=$$(PRIVATE_PRODUCT) -title=$$(PRIVATE_MESSAGE) $(foreach prefix, $(5), -strip_prefix=$(prefix)) $(call corresponding-license-metadata,$(4))
+
+notice_files: $(1)
+endef
+
+# Conversion license metadata into html notice file.
+# $(1) - Output target notice filename
+# $(2) - Product name
+# $(3) - File title
+# $(4) - License metadata file roots
+# $(5) - Prefixes to strip
+#
+define html-notice-rule
+$(1): PRIVATE_PRODUCT := $(2)
+$(1): PRIVATE_MESSAGE := $(3)
+$(1): $(call corresponding-license-metadata,$(4)) $(HTMLNOTICE) $(BUILD_SYSTEM)/Makefile
+ OUT_DIR=$(OUT_DIR) $(HTMLNOTICE) -o $$@ -product=$$(PRIVATE_PRODUCT) -title=$$(PRIVATE_MESSAGE) $(foreach prefix, $(5), -strip_prefix=$(prefix)) $(call corresponding-license-metadata,$(4))
+
+notice_files: $(1)
+endef
+
+$(KATI_obsolete_var combine-notice-files, To create notice files use xml-notice-rule, html-notice-rule, or text-notice-rule.)
+
# Notice file logic isn't relevant for TARGET_BUILD_APPS
ifndef TARGET_BUILD_APPS
@@ -1370,60 +1579,42 @@
# TODO(b/69865032): Make PRODUCT_NOTICE_SPLIT the default behavior.
ifneq ($(PRODUCT_NOTICE_SPLIT),true)
-target_notice_file_html := $(TARGET_OUT_INTERMEDIATES)/NOTICE.html
+#target_notice_file_html := $(TARGET_OUT_INTERMEDIATES)/NOTICE.html
target_notice_file_html_gz := $(TARGET_OUT_INTERMEDIATES)/NOTICE.html.gz
installed_notice_html_or_xml_gz := $(TARGET_OUT)/etc/NOTICE.html.gz
-$(eval $(call combine-notice-files, html, \
- $(target_notice_file_txt), \
- $(target_notice_file_html), \
- "Notices for files contained in the filesystem images in this directory:", \
- $(TARGET_OUT_NOTICE_FILES), \
- $(ALL_DEFAULT_INSTALLED_MODULES) $(kernel_notice_file), \
- $(exclude_target_dirs)))
-$(target_notice_file_html_gz): $(target_notice_file_html) | $(MINIGZIP)
- $(hide) $(MINIGZIP) -9 < $< > $@
-$(installed_notice_html_or_xml_gz): $(target_notice_file_html_gz)
- $(copy-file-to-target)
$(call declare-0p-target,$(target_notice_file_html_gz))
$(call declare-0p-target,$(installed_notice_html_or_xml_gz))
else
-target_notice_file_xml := $(TARGET_OUT_INTERMEDIATES)/NOTICE.xml
+# target_notice_file_xml := $(TARGET_OUT_INTERMEDIATES)/NOTICE.xml
target_notice_file_xml_gz := $(TARGET_OUT_INTERMEDIATES)/NOTICE.xml.gz
installed_notice_html_or_xml_gz := $(TARGET_OUT)/etc/NOTICE.xml.gz
target_vendor_notice_file_txt := $(TARGET_OUT_INTERMEDIATES)/NOTICE_VENDOR.txt
-target_vendor_notice_file_xml := $(TARGET_OUT_INTERMEDIATES)/NOTICE_VENDOR.xml
target_vendor_notice_file_xml_gz := $(TARGET_OUT_INTERMEDIATES)/NOTICE_VENDOR.xml.gz
installed_vendor_notice_xml_gz := $(TARGET_OUT_VENDOR)/etc/NOTICE.xml.gz
target_product_notice_file_txt := $(TARGET_OUT_INTERMEDIATES)/NOTICE_PRODUCT.txt
-target_product_notice_file_xml := $(TARGET_OUT_INTERMEDIATES)/NOTICE_PRODUCT.xml
target_product_notice_file_xml_gz := $(TARGET_OUT_INTERMEDIATES)/NOTICE_PRODUCT.xml.gz
installed_product_notice_xml_gz := $(TARGET_OUT_PRODUCT)/etc/NOTICE.xml.gz
target_system_ext_notice_file_txt := $(TARGET_OUT_INTERMEDIATES)/NOTICE_SYSTEM_EXT.txt
-target_system_ext_notice_file_xml := $(TARGET_OUT_INTERMEDIATES)/NOTICE_SYSTEM_EXT.xml
target_system_ext_notice_file_xml_gz := $(TARGET_OUT_INTERMEDIATES)/NOTICE_SYSTEM_EXT.xml.gz
installed_system_ext_notice_xml_gz := $(TARGET_OUT_SYSTEM_EXT)/etc/NOTICE.xml.gz
target_odm_notice_file_txt := $(TARGET_OUT_INTERMEDIATES)/NOTICE_ODM.txt
-target_odm_notice_file_xml := $(TARGET_OUT_INTERMEDIATES)/NOTICE_ODM.xml
target_odm_notice_file_xml_gz := $(TARGET_OUT_INTERMEDIATES)/NOTICE_ODM.xml.gz
installed_odm_notice_xml_gz := $(TARGET_OUT_ODM)/etc/NOTICE.xml.gz
target_vendor_dlkm_notice_file_txt := $(TARGET_OUT_INTERMEDIATES)/NOTICE_VENDOR_DLKM.txt
-target_vendor_dlkm_notice_file_xml := $(TARGET_OUT_INTERMEDIATES)/NOTICE_VENDOR_DLKM.xml
target_vendor_dlkm_notice_file_xml_gz := $(TARGET_OUT_INTERMEDIATES)/NOTICE_VENDOR_DLKM.xml.gz
installed_vendor_dlkm_notice_xml_gz := $(TARGET_OUT_VENDOR_DLKM)/etc/NOTICE.xml.gz
target_odm_dlkm_notice_file_txt := $(TARGET_OUT_INTERMEDIATES)/NOTICE_ODM_DLKM.txt
-target_odm_dlkm_notice_file_xml := $(TARGET_OUT_INTERMEDIATES)/NOTICE_ODM_DLKM.xml
target_odm_dlkm_notice_file_xml_gz := $(TARGET_OUT_INTERMEDIATES)/NOTICE_ODM_DLKM.xml.gz
installed_odm_dlkm_notice_xml_gz := $(TARGET_OUT_ODM_DLKM)/etc/NOTICE.xml.gz
target_system_dlkm_notice_file_txt := $(TARGET_OUT_INTERMEDIATES)/NOTICE_SYSTEM_DLKM.txt
-target_system_dlkm_notice_file_xml := $(TARGET_OUT_INTERMEDIATES)/NOTICE_SYSTEM_DLKM.xml
target_system_dlkm_notice_file_xml_gz := $(TARGET_OUT_INTERMEDIATES)/NOTICE_SYSTEM_DLKM.xml.gz
installed_system_dlkm_notice_xml_gz := $(TARGET_OUT_SYSTEM_DLKM)/etc/NOTICE.xml.gz
@@ -1498,129 +1689,6 @@
system_notice_file_message := "Notices for files contained in the system filesystem image in this directory:"
endif
-$(eval $(call combine-notice-files, $(system_xml_directories), \
- $(target_notice_file_txt), \
- $(target_notice_file_xml), \
- $(system_notice_file_message), \
- $(TARGET_OUT_NOTICE_FILES), \
- $(license_modules_system), \
- $(exclude_target_dirs)))
-$(eval $(call combine-notice-files, xml_excluded_system_product_odm_vendor_dlkm_odm_dlkm, \
- $(target_vendor_notice_file_txt), \
- $(target_vendor_notice_file_xml), \
- "Notices for files contained in all filesystem images except system/system_ext/product/odm/vendor_dlkm/odm_dlkm in this directory:", \
- $(TARGET_OUT_NOTICE_FILES), \
- $(license_modules_vendor), \
- $(exclude_target_dirs)))
-$(eval $(call combine-notice-files, xml_product, \
- $(target_product_notice_file_txt), \
- $(target_product_notice_file_xml), \
- "Notices for files contained in the product filesystem image in this directory:", \
- $(TARGET_OUT_NOTICE_FILES), \
- $(license_modules_product), \
- $(exclude_target_dirs)))
-$(eval $(call combine-notice-files, xml_system_ext, \
- $(target_system_ext_notice_file_txt), \
- $(target_system_ext_notice_file_xml), \
- "Notices for files contained in the system_ext filesystem image in this directory:", \
- $(TARGET_OUT_NOTICE_FILES), \
- $(license_modules_system_ext), \
- $(exclude_target_dirs)))
-$(eval $(call combine-notice-files, xml_odm, \
- $(target_odm_notice_file_txt), \
- $(target_odm_notice_file_xml), \
- "Notices for files contained in the odm filesystem image in this directory:", \
- $(TARGET_OUT_NOTICE_FILES), \
- $(license_modules_odm), \
- $(exclude_target_dirs)))
-$(eval $(call combine-notice-files, xml_vendor_dlkm, \
- $(target_vendor_dlkm_notice_file_txt), \
- $(target_vendor_dlkm_notice_file_xml), \
- "Notices for files contained in the vendor_dlkm filesystem image in this directory:", \
- $(TARGET_OUT_NOTICE_FILES), \
- $(license_modules_vendor_dlkm), \
- $(exclude_target_dirs)))
-$(eval $(call combine-notice-files, xml_odm_dlkm, \
- $(target_odm_dlkm_notice_file_txt), \
- $(target_odm_dlkm_notice_file_xml), \
- "Notices for files contained in the odm_dlkm filesystem image in this directory:", \
- $(TARGET_OUT_NOTICE_FILES), \
- $(license_modules_odm_dlkm), \
- $(exclude_target_dirs)))
-$(eval $(call combine-notice-files, xml_system_dlkm, \
- $(target_system_dlkm_notice_file_txt), \
- $(target_system_dlkm_notice_file_xml), \
- "Notices for files contained in the system_dlkm filesystem image in this directory:", \
- $(TARGET_OUT_NOTICE_FILES), \
- $(license_modules_system_dlkm), \
- $(exclude_target_dirs)))
-
-$(target_notice_file_xml_gz): $(target_notice_file_xml) | $(MINIGZIP)
- $(hide) $(MINIGZIP) -9 < $< > $@
-$(target_vendor_notice_file_xml_gz): $(target_vendor_notice_file_xml) | $(MINIGZIP)
- $(hide) $(MINIGZIP) -9 < $< > $@
-$(target_product_notice_file_xml_gz): $(target_product_notice_file_xml) | $(MINIGZIP)
- $(hide) $(MINIGZIP) -9 < $< > $@
-$(target_system_ext_notice_file_xml_gz): $(target_system_ext_notice_file_xml) | $(MINIGZIP)
- $(hide) $(MINIGZIP) -9 < $< > $@
-$(target_odm_notice_file_xml_gz): $(target_odm_notice_file_xml) | $(MINIGZIP)
- $(hide) $(MINIGZIP) -9 < $< > $@
-$(target_vendor_dlkm_notice_file_xml_gz): $(target_vendor_dlkm_notice_file_xml) | $(MINIGZIP)
- $(hide) $(MINIGZIP) -9 < $< > $@
-$(target_odm_dlkm_notice_file_xml_gz): $(target_odm_dlkm_notice_file_xml) | $(MINIGZIP)
- $(hide) $(MINIGZIP) -9 < $< > $@
-$(target_system_dlkm_notice_file_xml_gz): $(target_system_dlkm_notice_file_xml) | $(MINIGZIP)
- $(hide) $(MINIGZIP) -9 < $< > $@
-$(installed_notice_html_or_xml_gz): $(target_notice_file_xml_gz)
- $(copy-file-to-target)
-$(installed_vendor_notice_xml_gz): $(target_vendor_notice_file_xml_gz)
- $(copy-file-to-target)
-$(installed_product_notice_xml_gz): $(target_product_notice_file_xml_gz)
- $(copy-file-to-target)
-$(installed_system_ext_notice_xml_gz): $(target_system_ext_notice_file_xml_gz)
- $(copy-file-to-target)
-$(installed_odm_notice_xml_gz): $(target_odm_notice_file_xml_gz)
- $(copy-file-to-target)
-$(installed_vendor_dlkm_notice_xml_gz): $(target_vendor_dlkm_notice_file_xml_gz)
- $(copy-file-to-target)
-$(installed_odm_dlkm_notice_xml_gz): $(target_odm_dlkm_notice_file_xml_gz)
- $(copy-file-to-target)
-$(installed_system_dlkm_notice_xml_gz): $(target_system_dlkm_notice_file_xml_gz)
- $(copy-file-to-target)
-
-$(call declare-0p-target,$(target_notice_file_xml))
-$(call declare-0p-target,$(target_notice_file_xml_gz))
-$(call declare-0p-target,$(target_vendor_notice_file_xml))
-$(call declare-0p-target,$(target_vendor_notice_file_xml_gz))
-$(call declare-0p-target,$(target_product_notice_file_xml))
-$(call declare-0p-target,$(target_product_notice_file_xml_gz))
-$(call declare-0p-target,$(target_system_ext_notice_file_xml))
-$(call declare-0p-target,$(target_system_ext_notice_file_xml_gz))
-$(call declare-0p-target,$(target_odm_notice_file_xml))
-$(call declare-0p-target,$(target_odm_notice_file_xml_gz))
-$(call declare-0p-target,$(target_vendor_dlkm_notice_file_xml))
-$(call declare-0p-target,$(target_vendor_dlkm_notice_file_xml_gz))
-$(call declare-0p-target,$(target_odm_dlkm_notice_file_xml))
-$(call declare-0p-target,$(target_odm_dlkm_notice_file_xml_gz))
-$(call declare-0p-target,$(target_system_dlkm_notice_file_xml))
-$(call declare-0p-target,$(target_system_dlkm_notice_file_xml_gz))
-$(call declare-0p-target,$(installed_notice_html_or_xml_gz))
-$(call declare-0p-target,$(installed_vendor_notice_xml_gz))
-$(call declare-0p-target,$(installed_product_notice_xml_gz))
-$(call declare-0p-target,$(installed_system_ext_notice_xml_gz))
-$(call declare-0p-target,$(installed_odm_notice_xml_gz))
-$(call declare-0p-target,$(installed_vendor_dlkm_notice_xml_gz))
-$(call declare-0p-target,$(installed_odm_dlkm_notice_xml_gz))
-$(call declare-0p-target,$(installed_sysetm_dlkm_notice_xml_gz))
-
-ALL_DEFAULT_INSTALLED_MODULES += $(installed_notice_html_or_xml_gz)
-ALL_DEFAULT_INSTALLED_MODULES += $(installed_vendor_notice_xml_gz)
-ALL_DEFAULT_INSTALLED_MODULES += $(installed_product_notice_xml_gz)
-ALL_DEFAULT_INSTALLED_MODULES += $(installed_system_ext_notice_xml_gz)
-ALL_DEFAULT_INSTALLED_MODULES += $(installed_odm_notice_xml_gz)
-ALL_DEFAULT_INSTALLED_MODULES += $(installed_vendor_dlkm_notice_xml_gz)
-ALL_DEFAULT_INSTALLED_MODULES += $(installed_odm_dlkm_notice_xml_gz)
-ALL_DEFAULT_INSTALLED_MODULES += $(installed_system_dlkm_notice_xml_gz)
endif # PRODUCT_NOTICE_SPLIT
ALL_DEFAULT_INSTALLED_MODULES += $(installed_notice_html_or_xml_gz)
@@ -1632,6 +1700,9 @@
# then be in the right directory for the find in combine-notice-files to work.
$(eval $(call copy-one-file,$(BUILD_SYSTEM)/LINUX_KERNEL_COPYING,$(kernel_notice_file)))
+# No matter where it gets copied from, a copied linux kernel is licensed under "GPL 2.0 only"
+$(eval $(call declare-copy-files-license-metadata,,:kernel,SPDX-license-identifier-GPL-2.0-only,notice,$(BUILD_SYSTEM)/LINUX_KERNEL_COPYING,))
+
$(eval $(call copy-one-file,$(BUILD_SYSTEM)/WINPTHREADS_COPYING,$(winpthreads_notice_file)))
@@ -1677,6 +1748,8 @@
$(MKE2FS_CONF) \
$(MKEXTUSERIMG)
+$(call declare-1p-target,$(MKE2FS_CONF),system/extras)
+
ifeq ($(TARGET_USERIMAGES_USE_F2FS),true)
INTERNAL_USERIMAGES_DEPS += $(MKF2FSUSERIMG)
endif
@@ -1992,6 +2065,7 @@
# Recovery image
# Recovery image exists if we are building recovery, or building recovery as boot.
+INSTALLED_FILES_OUTSIDE_IMAGES := $(filter-out $(TARGET_RECOVERY_OUT)/%, $(INSTALLED_FILES_OUTSIDE_IMAGES))
ifdef BUILDING_RECOVERY_IMAGE
INTERNAL_RECOVERYIMAGE_FILES := $(filter $(TARGET_RECOVERY_OUT)/%, \
@@ -2018,6 +2092,9 @@
$(FILESLIST) $(TARGET_RECOVERY_ROOT_OUT) > $(@:.txt=.json)
$(FILESLIST_UTIL) -c $(@:.txt=.json) > $@
+$(eval $(call declare-0p-target,$(INSTALLED_FILES_FILE_RECOVERY)))
+$(eval $(call declare-0p-target,$(INSTALLED_FILES_JSON_RECOVERY)))
+
recovery_sepolicy := \
$(TARGET_RECOVERY_ROOT_OUT)/sepolicy \
$(TARGET_RECOVERY_ROOT_OUT)/plat_file_contexts \
@@ -2273,6 +2350,11 @@
$(hide) cat $(INSTALLED_SYSTEM_EXT_BUILD_PROP_TARGET) >> $@
$(call append-recovery-ui-properties,$(PRIVATE_RECOVERY_UI_PROPERTIES),$@)
+$(call declare-1p-target,$(INSTALLED_RECOVERY_BUILD_PROP_TARGET),build)
+$(call declare-license-deps,$(INSTALLED_RECOVERY_BUILD_PROP_TARGET),\
+ $(INSTALLED_BUILD_PROP_TARGET) $(INSTALLED_VENDOR_BUILD_PROP_TARGET) $(INSTALLED_ODM_BUILD_PROP_TARGET) \
+ $(INSTALLED_PRODUCT_BUILD_PROP_TARGET) $(INSTALLED_SYSTEM_EXT_BUILD_PROP_TARGET))
+
# Only install boot/etc/build.prop to recovery image on recovery_as_boot.
# On device with dedicated recovery partition, the file should come from the boot
# ramdisk.
@@ -2280,6 +2362,9 @@
INSTALLED_RECOVERY_RAMDISK_BUILD_PROP_TARGET := $(TARGET_RECOVERY_ROOT_OUT)/$(RAMDISK_BUILD_PROP_REL_PATH)
$(INSTALLED_RECOVERY_RAMDISK_BUILD_PROP_TARGET): $(INSTALLED_RAMDISK_BUILD_PROP_TARGET)
$(copy-file-to-target)
+
+$(call declare-1p-target,$(INSTALLED_RECOVERY_RAMDISK_BUILD_PROP_TARGET),build)
+$(call declare-license-deps,$(INSTALLED_RECOVERY_RAMDISK_BUILD_PROP_TARGET),$(INSTALLED_RAMDISK_BUILD_PROP_TARGET))
endif
INTERNAL_RECOVERYIMAGE_ARGS := --ramdisk $(recovery_ramdisk)
@@ -2413,6 +2498,11 @@
$(INSTALLED_BOOTIMAGE_TARGET): $(recoveryimage-deps)
$(call pretty,"Target boot image from recovery: $@")
$(call build-recoveryimage-target, $@, $(PRODUCT_OUT)/$(subst .img,,$(subst boot,kernel,$(notdir $@))))
+
+$(call declare-1p-container,$(INSTALLED_BOOTIMAGE_TARGET),)
+$(call declare-container-license-deps,$(INSTALLED_BOOTIMAGE_TARGET),$(recoveryimage-deps),$(PRODUCT_OUT)/:/)
+
+UNMOUNTED_NOTICE_DEPS += $(INSTALLED_BOOTIMAGE_TARGET)
endif # BOARD_USES_RECOVERY_AS_BOOT
$(INSTALLED_RECOVERYIMAGE_TARGET): $(recoveryimage-deps)
@@ -2426,6 +2516,12 @@
$(remove-timestamps-from-package)
endif
+
+$(call declare-1p-container,$(INSTALLED_RECOVERYIMAGE_TARGET),)
+$(call declare-container-license-deps,$(INSTALLED_RECOVERYIMAGE_TARGET),$(recoveryimage-deps),$(PRODUCT_OUT)/:/)
+
+UNMOUNTED_NOTICE_DEPS += $(INSTALLED_RECOVERYIMAGE_TARGET)
+
.PHONY: recoveryimage-nodeps
recoveryimage-nodeps:
@echo "make $@: ignoring dependencies"
@@ -2450,10 +2546,10 @@
# -----------------------------------------------------------------
# Build debug ramdisk and debug boot image.
+INSTALLED_FILES_OUTSIDE_IMAGES := $(filter-out $(TARGET_DEBUG_RAMDISK_OUT)/%, $(INSTALLED_FILES_OUTSIDE_IMAGES))
ifneq ($(BUILDING_DEBUG_BOOT_IMAGE)$(BUILDING_DEBUG_VENDOR_BOOT_IMAGE),)
INTERNAL_DEBUG_RAMDISK_FILES := $(filter $(TARGET_DEBUG_RAMDISK_OUT)/%, \
- $(ALL_GENERATED_SOURCES) \
$(ALL_DEFAULT_INSTALLED_MODULES))
# Directories to be picked into the debug ramdisk.
@@ -2488,6 +2584,9 @@
$(FILESLIST) $(INTERNAL_DEBUG_RAMDISK_SRC_DIRS) > $(@:.txt=.json)
$(FILESLIST_UTIL) -c $(@:.txt=.json) > $@
+$(eval $(call declare-0p-target,$(INSTALLED_FILES_FILE_DEBUG_RAMDISK)))
+$(eval $(call declare-0p-target,$(INSTALLED_FILES_JSON_DEBUG_RAMDISK)))
+
ifdef BUILDING_DEBUG_BOOT_IMAGE
# -----------------------------------------------------------------
@@ -2504,6 +2603,11 @@
$(hide) mkdir -p $(dir $@)
$(MKBOOTFS) -d $(TARGET_OUT) $(INTERNAL_DEBUG_RAMDISK_SRC_DIRS) | $(COMPRESSION_COMMAND) > $@
+$(call declare-1p-container,$(INSTALLED_DEBUG_RAMDISK_TARGET),)
+$(call declare-container-license-deps,$(INSTALLED_DEBUG_RAMDISK_TARGET),$(INSTALLED_RAMDISK_TARGET),$(PRODUCT_OUT)/:/)
+
+UNMOUNTED_NOTICE_DEPS += $(INSTALLED_DEBUG_RAMDISK_TARGET)
+
.PHONY: ramdisk_debug-nodeps
ramdisk_debug-nodeps: $(MKBOOTFS) | $(COMPRESSION_COMMAND_DEPS)
@echo "make $@: ignoring dependencies"
@@ -2566,6 +2670,11 @@
$(call pretty,"Target boot debug image: $@")
$(call build-debug-bootimage-target, $@)
+$(call declare-1p-container,$(INSTALLED_DEBUG_BOOTIMAGE_TARGET),)
+$(call declare-container-license-deps,$(INSTALLED_DEBUG_BOOTIMAGE_TARGET),$(INSTALLED_BOOTIMAGE_TARGET),$(PRODUCT_OUT)/:/)
+
+UNMOUNTED_NOTICE_DEPS += $(INSTALLED_DEBUG_BOOTIMAGE_TARGET)
+
.PHONY: bootimage_debug-nodeps
bootimage_debug-nodeps: $(MKBOOTIMG) $(AVBTOOL)
echo "make $@: ignoring dependencies"
@@ -2576,10 +2685,10 @@
# -----------------------------------------------------------------
# vendor debug ramdisk
# Combines vendor ramdisk files and debug ramdisk files to build the vendor debug ramdisk.
+INSTALLED_FILES_OUTSIDE_IMAGES := $(filter-out $(TARGET_VENDOR_DEBUG_RAMDISK_OUT)/%, $(INSTALLED_FILES_OUTSIDE_IMAGES))
ifdef BUILDING_DEBUG_VENDOR_BOOT_IMAGE
INTERNAL_VENDOR_DEBUG_RAMDISK_FILES := $(filter $(TARGET_VENDOR_DEBUG_RAMDISK_OUT)/%, \
- $(ALL_GENERATED_SOURCES) \
$(ALL_DEFAULT_INSTALLED_MODULES))
# The debug vendor ramdisk combines vendor ramdisk and debug ramdisk.
@@ -2610,6 +2719,9 @@
$(FILESLIST) $(INTERNAL_DEBUG_VENDOR_RAMDISK_SRC_DIRS) > $(@:.txt=.json)
$(FILESLIST_UTIL) -c $(@:.txt=.json) > $@
+$(call declare-0p-target,$(INSTALLED_FILES_FILE_VENDOR_DEBUG_RAMDISK))
+$(call declare-0p-target,$(INSTALLED_FILES_JSON_VENDOR_DEBUG_RAMDISK))
+
INTERNAL_VENDOR_DEBUG_RAMDISK_TARGET := $(call intermediates-dir-for,PACKAGING,vendor_boot-debug)/vendor_ramdisk-debug.cpio$(RAMDISK_EXT)
$(INTERNAL_VENDOR_DEBUG_RAMDISK_TARGET): $(INSTALLED_FILES_FILE_VENDOR_DEBUG_RAMDISK)
@@ -2623,6 +2735,11 @@
@echo "Target debug vendor ramdisk: $@"
$(copy-file-to-target)
+$(call declare-1p-container,$(INSTALLED_VENDOR_DEBUG_RAMDISK_TARGET),)
+$(call declare-container-license-deps,$(INSTALLED_VENDOR_DEBUG_RAMDISK_TARGET),$(INTERNAL_VENDOR_DEBUG_RAMDISK_TARGET),$(PRODUCT_OUT)/:/)
+
+VENDOR_NOTICE_DEPS += $(INSTALLED_VENDOR_DEBUG_RAMDISK_TARGET)
+
# -----------------------------------------------------------------
# vendor_boot-debug.img.
INSTALLED_VENDOR_DEBUG_BOOTIMAGE_TARGET := $(PRODUCT_OUT)/vendor_boot-debug.img
@@ -2653,6 +2770,11 @@
$(call assert-max-image-size,$@,$(BOARD_VENDOR_BOOTIMAGE_PARTITION_SIZE))
$(if $(BOARD_AVB_VENDOR_BOOT_KEY_PATH),$(call test-key-sign-vendor-bootimage,$@))
+$(call declare-1p-container,$(INSTALLED_VENDOR_DEBUG_BOOTIMAGE_TARGET),)
+$(call declare-container-license-deps,$(INSTALLED_VENDOR_DEBUG_BOOTIMAGE_TARGET),$(INTERNAL_VENDOR_DEBUG_RAMDISK_TARGET),$(PRODUCT_OUT)/:/)
+
+VENDOR_NOTICE_DEPS += $(INSTALLED_VENDOR_DEBUG_BOOTIMAGE_TARGET)
+
endif # BUILDING_DEBUG_VENDOR_BOOT_IMAGE
# Appends a few test harness specific properties into the adb_debug.prop.
@@ -2674,9 +2796,11 @@
$(hide) $(foreach line,$(ADDITIONAL_TEST_HARNESS_PROPERTIES), \
echo "$(line)" >> $@;)
+$(call declare-1p-target,$(INTERNAL_TEST_HARNESS_RAMDISK_ADB_DEBUG_PROP_TARGET))
+
+INSTALLED_FILES_OUTSIDE_IMAGES := $(filter-out $(TARGET_TEST_HARNESS_RAMDISK_OUT)/%, $(INSTALLED_FILES_OUTSIDE_IMAGES))
INTERNAL_TEST_HARNESS_RAMDISK_FILES := $(filter $(TARGET_TEST_HARNESS_RAMDISK_OUT)/%, \
$(INTERNAL_TEST_HARNESS_RAMDISK_ADB_DEBUG_PROP_TARGET) \
- $(ALL_GENERATED_SOURCES) \
$(ALL_DEFAULT_INSTALLED_MODULES))
# The order is important here. The test harness ramdisk staging directory has to
@@ -2699,6 +2823,11 @@
$(hide) mkdir -p $(dir $@)
$(MKBOOTFS) -d $(TARGET_OUT) $(INTERNAL_TEST_HARNESS_RAMDISK_SRC_DIRS) | $(COMPRESSION_COMMAND) > $@
+$(call declare-1p-container,$(INSTALLED_TEST_HARNESS_RAMDISK_TARGET),)
+$(call declare-container-license-deps,$(INSTALLED_TEST_HARNESS_RAMDISK_TARGET),$(INTERNAL_TEST_HARNESS_RAMDISK_SRC_DEPS),$(PRODUCT_OUT)/:/)
+
+UNMOUNTED_NOTICE_DEPS += $(INSTALLED_TEST_HARNESS_RAMDISK_TARGET)
+
.PHONY: ramdisk_test_harness-nodeps
ramdisk_test_harness-nodeps: $(MKBOOTFS) | $(COMPRESSION_COMMAND_DEPS)
@echo "make $@: ignoring dependencies"
@@ -2743,6 +2872,11 @@
$(call pretty,"Target boot test harness image: $@")
$(call build-boot-test-harness-target,$@)
+$(call declare-1p-container,$(INSTALLED_TEST_HARNESS_BOOTIMAGE_TARGET),)
+$(call declare-container-license-deps,$(INSTALLED_TEST_HARNESS_BOOTIMAGE_TARGET),$(INSTALLED_DEBUG_BOOTIMAGE_TARGET),$(PRODUCT_OUT)/:/)
+
+UNMOUNTED_NOTICE_DEPS += $(INSTALLED_TEST_HARNESS_BOOTIMAGE_TARGET)
+
.PHONY: bootimage_test_harness-nodeps
bootimage_test_harness-nodeps: $(MKBOOTIMG) $(AVBTOOL)
echo "make $@: ignoring dependencies"
@@ -2774,6 +2908,11 @@
@echo "Target test harness vendor ramdisk: $@"
$(copy-file-to-target)
+$(call declare-1p-container,$(INSTALLED_VENDOR_TEST_HARNESS_RAMDISK_TARGET),)
+$(call declare-container-license-deps,$(INSTALLED_VENDOR_TEST_HARNESS_RAMDISK_TARGET),$(INTERNAL_VENDOR_TEST_HARNESS_RAMDISK_TARGET),$(PRODUCT_OUT)/:/)
+
+VENDOR_NOTICE_DEPS += $(INSTALLED_VENDOR_TEST_HARNESS_RAMDISK_TARGET)
+
# -----------------------------------------------------------------
# vendor_boot-test-harness.img.
INSTALLED_VENDOR_TEST_HARNESS_BOOTIMAGE_TARGET := $(PRODUCT_OUT)/vendor_boot-test-harness.img
@@ -2791,6 +2930,11 @@
$(call assert-max-image-size,$@,$(BOARD_VENDOR_BOOTIMAGE_PARTITION_SIZE))
$(if $(BOARD_AVB_VENDOR_BOOT_KEY_PATH),$(call test-key-sign-vendor-bootimage,$@))
+$(call declare-1p-container,$(INSTALLED_VENDOR_TEST_HARNESS_BOOTIMAGE_TARGET),)
+$(call declare-container-license-deps,$(INSTALLED_VENDOR_TEST_HARNESS_BOOTIMAGE_TARGET),$(INTERNAL_VENDOR_TEST_HARNESS_RAMDISK_TARGET),$(PRODUCT_OUT)/:/)
+
+VENDOR_NOTICE_DEPS += $(INSTALLED_VENDOR_TEST_HARNESS_BOOTIMAGE_TARGET)
+
endif # BUILDING_DEBUG_VENDOR_BOOT_IMAGE
endif # BUILDING_DEBUG_BOOT_IMAGE || BUILDING_DEBUG_VENDOR_BOOT_IMAGE
@@ -2830,8 +2974,9 @@
$(TARGET_OUT)/framework/% \
$(TARGET_OUT)/etc/boot-image.prof \
$(TARGET_OUT)/etc/dirty-image-objects \
+ $(TARGET_OUT)/etc/preloaded-classes \
$(TARGET_OUT)/etc/classpaths/%.pb, \
- $(ALL_GENERATED_SOURCES) $(ALL_DEFAULT_INSTALLED_MODULES)))
+ $(ALL_DEFAULT_INSTALLED_MODULES)))
define fsverity-generate-metadata
$(1).fsv_meta: PRIVATE_SRC := $(1)
@@ -2877,8 +3022,8 @@
endif # PRODUCT_SYSTEM_FSVERITY_GENERATE_METADATA
+INSTALLED_FILES_OUTSIDE_IMAGES := $(filter-out $(TARGET_OUT)/%, $(INSTALLED_FILES_OUTSIDE_IMAGES))
INTERNAL_SYSTEMIMAGE_FILES := $(sort $(filter $(TARGET_OUT)/%, \
- $(ALL_GENERATED_SOURCES) \
$(ALL_DEFAULT_INSTALLED_MODULES)))
# Create symlink /system/vendor to /vendor if necessary.
@@ -2927,10 +3072,15 @@
# Install system linker configuration
# Collect all available stub libraries installed in system and install with predefined linker configuration
SYSTEM_LINKER_CONFIG := $(TARGET_OUT)/etc/linker.config.pb
-$(SYSTEM_LINKER_CONFIG) : $(INTERNAL_SYSTEMIMAGE_FILES) $(LINKER_CONFIG_PATH_system_linker_config) | conv_linker_config
- $(HOST_OUT_EXECUTABLES)/conv_linker_config systemprovide --source $(LINKER_CONFIG_PATH_system_linker_config)\
+SYSTEM_LINKER_CONFIG_SOURCE := $(call intermediates-dir-for,ETC,system_linker_config)/system_linker_config
+$(SYSTEM_LINKER_CONFIG): PRIVATE_SYSTEM_LINKER_CONFIG_SOURCE := $(SYSTEM_LINKER_CONFIG_SOURCE)
+$(SYSTEM_LINKER_CONFIG) : $(INTERNAL_SYSTEMIMAGE_FILES) $(SYSTEM_LINKER_CONFIG_SOURCE) | conv_linker_config
+ $(HOST_OUT_EXECUTABLES)/conv_linker_config systemprovide --source $(PRIVATE_SYSTEM_LINKER_CONFIG_SOURCE) \
--output $@ --value "$(STUB_LIBRARIES)" --system "$(TARGET_OUT)"
+$(call declare-1p-target,$(SYSTEM_LINKER_CONFIG),)
+$(call declare-license-deps,$(SYSTEM_LINKER_CONFIG),$(INTERNAL_SYSTEMIMAGE_FILES) $(SYSTEM_LINKER_CONFIG_SOURCE))
+
FULL_SYSTEMIMAGE_DEPS += $(SYSTEM_LINKER_CONFIG)
# installed file list
@@ -2948,6 +3098,9 @@
$(FILESLIST) $(TARGET_OUT) > $(@:.txt=.json)
$(FILESLIST_UTIL) -c $(@:.txt=.json) > $@
+$(eval $(call declare-0p-target,$(INSTALLED_FILES_FILE)))
+$(eval $(call declare-0p-target,$(INSTALLED_FILES_JSON)))
+
.PHONY: installed-file-list
installed-file-list: $(INSTALLED_FILES_FILE)
@@ -2980,7 +3133,7 @@
$(call build-systemimage-target,$@)
$(call declare-1p-container,$(BUILT_SYSTEMIMAGE),system/extras)
-$(call declare-container-license-deps,$(BUILT_SYSTEMIMAGE),$(FULL_SYSTEMIMAGE_DEPS),$(PRODUCT_OUT)/:)
+$(call declare-container-license-deps,$(BUILT_SYSTEMIMAGE),$(FULL_SYSTEMIMAGE_DEPS),$(PRODUCT_OUT)/:/)
INSTALLED_SYSTEMIMAGE_TARGET := $(PRODUCT_OUT)/system.img
SYSTEMIMAGE_SOURCE_DIR := $(TARGET_OUT)
@@ -3028,8 +3181,7 @@
systemimage: $(INSTALLED_SYSTEMIMAGE_TARGET)
-.PHONY: systemlicense
-systemlicense: $(call license-metadata-dir)/$(INSTALLED_SYSTEMIMAGE_TARGET).meta_lic reportmissinglicenses
+SYSTEM_NOTICE_DEPS += $(INSTALLED_SYSTEMIMAGE_TARGET)
.PHONY: systemimage-nodeps snod
systemimage-nodeps snod: $(filter-out systemimage-nodeps snod,$(MAKECMDGOALS)) \
@@ -3058,6 +3210,7 @@
# -----------------------------------------------------------------
# data partition image
+INSTALLED_FILES_OUTSIDE_IMAGES := $(filter-out $(TARGET_OUT_DATA)/%, $(INSTALLED_FILES_OUTSIDE_IMAGES))
INTERNAL_USERDATAIMAGE_FILES := \
$(filter $(TARGET_OUT_DATA)/%,$(ALL_DEFAULT_INSTALLED_MODULES))
@@ -3086,6 +3239,11 @@
$(INSTALLED_USERDATAIMAGE_TARGET): $(INSTALLED_USERDATAIMAGE_TARGET_DEPS)
$(build-userdataimage-target)
+$(call declare-1p-container,$(INSTALLED_USERDATAIMAGE_TARGET),)
+$(call declare-container-license-deps,$(INSTALLED_USERDATAIMAGE_TARGET),$(INSTALLED_USERDATAIMAGE_TARGET_DEPS),$(PRODUCT_OUT)/:/)
+
+UNMOUNTED_NOTICE_DEPS += $(INSTALLED_USERDATAIMAGE_TARGET)
+
.PHONY: userdataimage-nodeps
userdataimage-nodeps: | $(INTERNAL_USERIMAGES_DEPS)
$(build-userdataimage-target)
@@ -3133,6 +3291,11 @@
$(INSTALLED_BPTIMAGE_TARGET): $(BPTTOOL) $(BOARD_BPT_INPUT_FILES)
$(build-bptimage-target)
+$(call declare-1p-container,$(INSTALLED_BPTIMAGE_TARGET),)
+$(call declare-container-license-deps,$(INSTALLED_BPTIMAGE_TARGET),$(BOARD_BPT_INPUT_FILES),$(PRODUCT_OUT)/:/)
+
+UNMOUNTED_NOTICE_DEPS += $(INSTALLED_BPTIMAGE_TARGET)
+
.PHONY: bptimage-nodeps
bptimage-nodeps:
$(build-bptimage-target)
@@ -3141,6 +3304,7 @@
# -----------------------------------------------------------------
# cache partition image
+INSTALLED_FILES_OUTSIDE_IMAGES := $(filter-out $(TARGET_OUT_CACHE)/%, $(INSTALLED_FILES_OUTSIDE_IMAGES))
ifdef BUILDING_CACHE_IMAGE
INTERNAL_CACHEIMAGE_FILES := \
$(filter $(TARGET_OUT_CACHE)/%,$(ALL_DEFAULT_INSTALLED_MODULES))
@@ -3166,6 +3330,11 @@
$(INSTALLED_CACHEIMAGE_TARGET): $(INTERNAL_USERIMAGES_DEPS) $(INTERNAL_CACHEIMAGE_FILES)
$(build-cacheimage-target)
+$(call declare-1p-container,$(INSTALLED_CACHEIMAGE_TARGET),)
+$(call declare-container-license-deps,$(INSTALLED_CACHEIMAGE_TARGET),$(INTERNAL_USERIMAGES_DEPS) $(INTERNAL_CACHEIMAGE_FILES),$(PRODUCT_OUT)/:/)
+
+UNMOUNTED_NOTICE_DEPS += $(INSTALLED_CACHEIMAGE_TARGET)
+
.PHONY: cacheimage-nodeps
cacheimage-nodeps: | $(INTERNAL_USERIMAGES_DEPS)
$(build-cacheimage-target)
@@ -3177,6 +3346,7 @@
# -----------------------------------------------------------------
# system_other partition image
+INSTALLED_FILES_OUTSIDE_IMAGES := $(filter-out $(TARGET_OUT_SYSTEM_OTHER)/%, $(INSTALLED_FILES_OUTSIDE_IMAGES))
ifdef BUILDING_SYSTEM_OTHER_IMAGE
ifeq ($(BOARD_USES_SYSTEM_OTHER_ODEX),true)
# Marker file to identify that odex files are installed
@@ -3184,6 +3354,8 @@
ALL_DEFAULT_INSTALLED_MODULES += $(INSTALLED_SYSTEM_OTHER_ODEX_MARKER)
$(INSTALLED_SYSTEM_OTHER_ODEX_MARKER):
$(hide) touch $@
+
+$(call declare-0p-target,$(INSTALLED_SYSTEM_OTHER_ODEX_MARKER))
endif
INTERNAL_SYSTEMOTHERIMAGE_FILES := \
@@ -3203,6 +3375,9 @@
$(FILESLIST) $(TARGET_OUT_SYSTEM_OTHER) > $(@:.txt=.json)
$(FILESLIST_UTIL) -c $(@:.txt=.json) > $@
+$(eval $(call declare-0p-target,$(INSTALLED_FILES_FILE_SYSTEMOTHER)))
+$(eval $(call declare-0p-target,$(INSTALLED_FILES_JSON_SYSTEMOTHER)))
+
# Determines partition size for system_other.img.
ifeq ($(PRODUCT_RETROFIT_DYNAMIC_PARTITIONS),true)
ifneq ($(filter system,$(BOARD_SUPER_PARTITION_BLOCK_DEVICES)),)
@@ -3237,6 +3412,11 @@
# Only create system_other when not building the second stage of a SANITIZE_LITE build.
$(INSTALLED_SYSTEMOTHERIMAGE_TARGET): $(INTERNAL_USERIMAGES_DEPS) $(INTERNAL_SYSTEMOTHERIMAGE_FILES) $(INSTALLED_FILES_FILE_SYSTEMOTHER)
$(build-systemotherimage-target)
+
+$(call declare-1p-container,$(INSTALLED_SYSTEMOTHERIMAGE_TARGET),)
+$(call declare-container-license-deps,$(INSTALLED_SYSTEMOTHERIMAGE_TARGET),$(INTERNAL_USERIMAGES_DEPS) $(INTERNAL_SYSTEMOTHERIMAGE_FILES),$(PRODUCT_OUT)/:/)
+
+UNMOUNTED_NOTICE_DEPS += $(INSTALLED_SYSTEMOTHERIMAGE_TARGET)
endif
.PHONY: systemotherimage-nodeps
@@ -3248,6 +3428,7 @@
# -----------------------------------------------------------------
# vendor partition image
+INSTALLED_FILES_OUTSIDE_IMAGES := $(filter-out $(TARGET_OUT_VENDOR)/%, $(INSTALLED_FILES_OUTSIDE_IMAGES))
ifdef BUILDING_VENDOR_IMAGE
INTERNAL_VENDORIMAGE_FILES := \
$(filter $(TARGET_OUT_VENDOR)/%,\
@@ -3287,6 +3468,9 @@
$(FILESLIST) $(TARGET_OUT_VENDOR) > $(@:.txt=.json)
$(FILESLIST_UTIL) -c $(@:.txt=.json) > $@
+$(call declare-0p-target,$(INSTALLED_FILES_FILE_VENDOR))
+$(call declare-0p-target,$(INSTALLED_FILES_JSON_VENDOR))
+
vendorimage_intermediates := \
$(call intermediates-dir-for,PACKAGING,vendor)
BUILT_VENDORIMAGE_TARGET := $(PRODUCT_OUT)/vendor.img
@@ -3311,6 +3495,11 @@
$(RECOVERY_FROM_BOOT_PATCH)
$(build-vendorimage-target)
+VENDOR_NOTICE_DEPS += $(INSTALLED_VENDORIMAGE_TARGET)
+
+$(call declare-container-license-metadata,$(INSTALLED_VENDORIMAGE_TARGET),legacy_proprietary,proprietary,,"Vendor Image",vendor)
+$(call declare-container-license-deps,$(INSTALLED_VENDORIMAGE_TARGET),$(INTERNAL_USERIMAGES_DEPS) $(INTERNAL_VENDORIMAGE_FILES) $(RECOVERY_FROM_BOOT_PATH),$(PRODUCT_OUT)/:/)
+
.PHONY: vendorimage-nodeps vnod
vendorimage-nodeps vnod: | $(INTERNAL_USERIMAGES_DEPS)
$(build-vendorimage-target)
@@ -3320,10 +3509,15 @@
else ifdef BOARD_PREBUILT_VENDORIMAGE
INSTALLED_VENDORIMAGE_TARGET := $(PRODUCT_OUT)/vendor.img
$(eval $(call copy-one-file,$(BOARD_PREBUILT_VENDORIMAGE),$(INSTALLED_VENDORIMAGE_TARGET)))
+$(if $(strip $(ALL_TARGETS.$(INSTALLED_VENDORIMAGE_TARGET).META_LIC)),,\
+ $(if $(strip $(ALL_TARGETS.$(BOARD_PREBUILT_VENDORIMAGE).META_LIC)),\
+ $(eval ALL_TARGETS.$(INSTALLED_VENDORIMAGE_TARGET).META_LIC:=$(ALL_TARGETS.$(BOARD_PREBUILT_VENDORIMAGE).META_LIC)),\
+ $(call declare-license-metadata,$(INSTALLED_VENDORIMAGE_TARGET),legacy_proprietary,proprietary,,"Vendor Image",vendor)))
endif
# -----------------------------------------------------------------
# product partition image
+INSTALLED_FILES_OUTSIDE_IMAGES := $(filter-out $(TARGET_OUT_PRODUCT)/%, $(INSTALLED_FILES_OUTSIDE_IMAGES))
ifdef BUILDING_PRODUCT_IMAGE
INTERNAL_PRODUCTIMAGE_FILES := \
$(filter $(TARGET_OUT_PRODUCT)/%,\
@@ -3339,6 +3533,9 @@
$(FILESLIST) $(TARGET_OUT_PRODUCT) > $(@:.txt=.json)
$(FILESLIST_UTIL) -c $(@:.txt=.json) > $@
+$(call declare-0p-target,$(INSTALLED_FILES_FILE_PRODUCT))
+$(call declare-0p-target,$(INSTALLED_FILES_JSON_PRODUCT))
+
productimage_intermediates := \
$(call intermediates-dir-for,PACKAGING,product)
BUILT_PRODUCTIMAGE_TARGET := $(PRODUCT_OUT)/product.img
@@ -3362,6 +3559,11 @@
$(INSTALLED_FILES_FILE_PRODUCT)
$(build-productimage-target)
+PRODUCT_NOTICE_DEPS += $(INSTALLED_PRODUCTIMAGE_TARGET)
+
+$(call declare-1p-container,$(INSTALLED_PRODUCTIMAGE_TARGET),)
+$(call declare-container-license-deps,$(INSTALLED_PRODUCTIMAGE_TARGET),$(INTERNAL_USERIMAGES_DEPS) $(INTERNAL_PRODUCTIMAGE_FILES) $(INSTALLED_FILES_FILE_PRODUCT),$(PRODUCT_OUT)/:/)
+
.PHONY: productimage-nodeps pnod
productimage-nodeps pnod: | $(INTERNAL_USERIMAGES_DEPS)
$(build-productimage-target)
@@ -3375,6 +3577,7 @@
# -----------------------------------------------------------------
# system_ext partition image
+INSTALLED_FILES_OUTSIDE_IMAGES := $(filter-out $(TARGET_OUT_SYSTEM_EXT)/%, $(INSTALLED_FILES_OUTSIDE_IMAGES))
ifdef BUILDING_SYSTEM_EXT_IMAGE
INTERNAL_SYSTEM_EXTIMAGE_FILES := \
$(filter $(TARGET_OUT_SYSTEM_EXT)/%,\
@@ -3390,6 +3593,9 @@
$(FILESLIST) $(TARGET_OUT_SYSTEM_EXT) > $(@:.txt=.json)
$(FILESLIST_UTIL) -c $(@:.txt=.json) > $@
+$(call declare-0p-target,$(INSTALLED_FILES_FILE_SYSTEM_EXT))
+$(call declare-0p-target,$(INSTALLED_FILES_JSON_SYSTEM_EXT))
+
system_extimage_intermediates := \
$(call intermediates-dir-for,PACKAGING,system_ext)
BUILT_SYSTEM_EXTIMAGE_TARGET := $(PRODUCT_OUT)/system_ext.img
@@ -3415,6 +3621,11 @@
$(INSTALLED_FILES_FILE_SYSTEM_EXT)
$(build-system_extimage-target)
+SYSTEM_EXT_NOTICE_DEPS += $(INSTALLED_SYSTEM_EXTIMAGE_TARGET)
+
+$(call declare-1p-container,$(INSTALLED_SYSTEM_EXTIMAGE_TARGET),)
+$(call declare-container-license-deps,$(INSTALLED_SYSTEM_EXTIMAGE_TARGET),$(INTERNAL_USERIMAGES_DEPS) $(INTERNAL_SYSTEM_EXTIMAGE_FILES) $(INSTALLED_FILES_FILE_SYSTEM_EXT),$(PRODUCT_OUT)/:/)
+
.PHONY: systemextimage-nodeps senod
systemextimage-nodeps senod: | $(INTERNAL_USERIMAGES_DEPS)
$(build-system_extimage-target)
@@ -3428,6 +3639,7 @@
# -----------------------------------------------------------------
# odm partition image
+INSTALLED_FILES_OUTSIDE_IMAGES := $(filter-out $(TARGET_OUT_ODM)/%, $(INSTALLED_FILES_OUTSIDE_IMAGES))
ifdef BUILDING_ODM_IMAGE
INTERNAL_ODMIMAGE_FILES := \
$(filter $(TARGET_OUT_ODM)/%,\
@@ -3461,6 +3673,9 @@
$(FILESLIST) $(TARGET_OUT_ODM) > $(@:.txt=.json)
$(FILESLIST_UTIL) -c $(@:.txt=.json) > $@
+$(call declare-0p-target,$(INSTALLED_FILES_FILE_ODM))
+$(call declare-0p-target,$(INSTALLED_FILES_JSON_ODM))
+
odmimage_intermediates := \
$(call intermediates-dir-for,PACKAGING,odm)
BUILT_ODMIMAGE_TARGET := $(PRODUCT_OUT)/odm.img
@@ -3485,6 +3700,11 @@
$(INSTALLED_FILES_FILE_ODM)
$(build-odmimage-target)
+ODM_NOTICE_DEPS += $(INSTALLED_ODMIMAGE_TARGET)
+
+$(call declare-1p-container,$(INSTALLED_ODMIMAGE_TARGET),)
+$(call declare-container-license-deps,$(INSTALLED_ODMIMAGE_TARGET),$(INTERNAL_USERIMAGES_DEPS) $(INTERNAL_ODMIMAGE_FILES) $(INSTALLED_FILES_FILE_ODM),$(PRODUCT_OUT)/:/)
+
.PHONY: odmimage-nodeps onod
odmimage-nodeps onod: | $(INTERNAL_USERIMAGES_DEPS)
$(build-odmimage-target)
@@ -3498,6 +3718,7 @@
# -----------------------------------------------------------------
# vendor_dlkm partition image
+INSTALLED_FILES_OUTSIDE_IMAGES := $(filter-out $(TARGET_OUT_VENDOR_DLKM)/%, $(INSTALLED_FILES_OUTSIDE_IMAGES))
ifdef BUILDING_VENDOR_DLKM_IMAGE
INTERNAL_VENDOR_DLKMIMAGE_FILES := \
$(filter $(TARGET_OUT_VENDOR_DLKM)/%,\
@@ -3513,6 +3734,9 @@
$(FILESLIST) $(TARGET_OUT_VENDOR_DLKM) > $(@:.txt=.json)
$(FILESLIST_UTIL) -c $(@:.txt=.json) > $@
+$(call declare-0p-target,$(INSTALLED_FILES_FILE_VENDOR_DLKM))
+$(call declare-0p-target,$(INSTALLED_FILES_JSON_VENDOR_DLKM))
+
vendor_dlkmimage_intermediates := \
$(call intermediates-dir-for,PACKAGING,vendor_dlkm)
BUILT_VENDOR_DLKMIMAGE_TARGET := $(PRODUCT_OUT)/vendor_dlkm.img
@@ -3537,6 +3761,11 @@
$(INSTALLED_FILES_FILE_VENDOR_DLKM)
$(build-vendor_dlkmimage-target)
+VENDOR_DLKM_NOTICE_DEPS += $(INSTALLED_VENDOR_DLKMIMAGE_TARGET)
+
+$(call declare-1p-container,$(INSTALLED_VENDOR_DLKMIMAGE_TARGET),)
+$(call declare-container-license-deps,$(INSTALLED_VENDOR_DLKMIMAGE_TARGET),$(INTERNAL_USERIMAGES_DEPS) $(INTERNAL_VENDOR_DLKMIMAGE_FILES) $(INSTALLED_FILES_FILE_VENDOR_DLKM),$(PRODUCT_OUT)/:/)
+
.PHONY: vendor_dlkmimage-nodeps vdnod
vendor_dlkmimage-nodeps vdnod: | $(INTERNAL_USERIMAGES_DEPS)
$(build-vendor_dlkmimage-target)
@@ -3550,6 +3779,7 @@
# -----------------------------------------------------------------
# odm_dlkm partition image
+INSTALLED_FILES_OUTSIDE_IMAGES := $(filter-out $(TARGET_OUT_ODM_DLKM)/%, $(INSTALLED_FILES_OUTSIDE_IMAGES))
ifdef BUILDING_ODM_DLKM_IMAGE
INTERNAL_ODM_DLKMIMAGE_FILES := \
$(filter $(TARGET_OUT_ODM_DLKM)/%,\
@@ -3565,6 +3795,9 @@
$(FILESLIST) $(TARGET_OUT_ODM_DLKM) > $(@:.txt=.json)
$(FILESLIST_UTIL) -c $(@:.txt=.json) > $@
+$(call declare-0p-target,$(INSTALLED_FILES_FILE_ODM_DLKM))
+$(call declare-0p-target,$(INSTALLED_FILES_JSON_ODM_DLKM))
+
odm_dlkmimage_intermediates := \
$(call intermediates-dir-for,PACKAGING,odm_dlkm)
BUILT_ODM_DLKMIMAGE_TARGET := $(PRODUCT_OUT)/odm_dlkm.img
@@ -3589,6 +3822,11 @@
$(INSTALLED_FILES_FILE_ODM_DLKM)
$(build-odm_dlkmimage-target)
+ODM_DLKM_NOTICE_DEPS += $(INSTALLED_ODM_DLKMIMAGE_TARGET)
+
+$(call declare-1p-container,$(INSTALLED_ODM_DLKMIMAGE_TARGET),)
+$(call declare-container-license-deps,$(INSTALLED_ODM_DLKMIMAGE_TARGET),$(INTERNAL_USERIMAGES_DEPS) $(INTERNAL_ODM_DLKMIMAGE_FILES) $(INSTALLED_FILES_FILE_ODM_DLKM),$(PRODUCT_OUT)/:/)
+
.PHONY: odm_dlkmimage-nodeps odnod
odm_dlkmimage-nodeps odnod: | $(INTERNAL_USERIMAGES_DEPS)
$(build-odm_dlkmimage-target)
@@ -3603,6 +3841,7 @@
# -----------------------------------------------------------------
# system_dlkm partition image
+INSTALLED_FILES_OUTSIDE_IMAGES := $(filter-out $(TARGET_OUT_SYSTEM_DLKM)/%, $(INSTALLED_FILES_OUTSIDE_IMAGES))
ifdef BUILDING_SYSTEM_DLKM_IMAGE
INTERNAL_SYSTEM_DLKMIMAGE_FILES := \
@@ -3620,6 +3859,9 @@
$(FILESLIST) $(TARGET_OUT_SYSTEM_DLKM) > $(@:.txt=.json)
$(FILESLIST_UTIL) -c $(@:.txt=.json) > $@
+$(call declare-0p-target,$(INSTALLED_FILES_FILE_SYSTEM_DLKM))
+$(call declare-0p-target,$(INSTALLED_FILES_JSON_SYSTEM_DLKM))
+
system_dlkmimage_intermediates := \
$(call intermediates-dir-for,PACKAGING,system_dlkm)
BUILT_SYSTEM_DLKMIMAGE_TARGET := $(PRODUCT_OUT)/system_dlkm.img
@@ -3668,6 +3910,11 @@
$(call get-partition-size-argument,$(BOARD_DTBOIMG_PARTITION_SIZE)) \
--partition_name dtbo $(INTERNAL_AVB_DTBO_SIGNING_ARGS) \
$(BOARD_AVB_DTBO_ADD_HASH_FOOTER_ARGS)
+
+$(call declare-1p-container,$(INSTALLED_DTBOIMAGE_TARGET),)
+$(call declare-container-license-deps,$(INSTALLED_DTBOIMAGE_TARGET),$(BOARD_PREBUILT_DTBOIMAGE),$(PRODUCT_OUT)/:/)
+
+UNMOUNTED_NOTICE_DEPS += $(INSTALLED_DTBOIMAGE_TARGET)
else
$(INSTALLED_DTBOIMAGE_TARGET): $(BOARD_PREBUILT_DTBOIMAGE)
cp $(BOARD_PREBUILT_DTBOIMAGE) $@
@@ -3697,6 +3944,11 @@
$(call get-partition-size-argument,$(BOARD_PVMFWIMAGE_PARTITION_SIZE)) \
--partition_name pvmfw $(INTERNAL_AVB_PVMFW_SIGNING_ARGS) \
$(BOARD_AVB_PVMFW_ADD_HASH_FOOTER_ARGS)
+
+$(call declare-1p-container,$(INSTALLED_PVMFWIMAGE_TARGET),)
+$(call declare-container-license-deps,$(INSTALLED_PVMFWIMAGE_TARGET),$(PREBUILT_PVMFWIMAGE_TARGET),$(PRODUCT_OUT)/:/)
+
+UNMOUNTED_NOTICE_DEPS += $(INSTALLED_PVMFWIMAGE_TARGET)
else
$(eval $(call copy-one-file,$(PREBUILT_PVMFWIMAGE_TARGET),$(INSTALLED_PVMFWIMAGE_TARGET)))
endif
@@ -3784,6 +4036,8 @@
@mkdir -p $(dir $@)
$(AVBTOOL) extract_public_key --key $(BOARD_AVB_SYSTEM_OTHER_KEY_PATH) --output $@
+$(eval $(call declare-0p-target,$(INSTALLED_PRODUCT_SYSTEM_OTHER_AVBKEY_TARGET),))
+
ifndef BOARD_AVB_SYSTEM_OTHER_ROLLBACK_INDEX
BOARD_AVB_SYSTEM_OTHER_ROLLBACK_INDEX := $(PLATFORM_SECURITY_PATCH_TIMESTAMP)
endif
@@ -3811,55 +4065,89 @@
endif
endif
-# Appends os version and security patch level as a AVB property descriptor
+# Appends os version as a AVB property descriptor.
+SYSTEM_OS_VERSION ?= $(PLATFORM_VERSION_LAST_STABLE)
+BOARD_AVB_SYSTEM_ADD_HASHTREE_FOOTER_ARGS += \
+ --prop com.android.build.system.os_version:$(SYSTEM_OS_VERSION)
+PRODUCT_OS_VERSION ?= $(PLATFORM_VERSION_LAST_STABLE)
+BOARD_AVB_PRODUCT_ADD_HASHTREE_FOOTER_ARGS += \
+ --prop com.android.build.product.os_version:$(PRODUCT_OS_VERSION)
+
+SYSTEM_EXT_OS_VERSION ?= $(PLATFORM_VERSION_LAST_STABLE)
+BOARD_AVB_SYSTEM_EXT_ADD_HASHTREE_FOOTER_ARGS += \
+ --prop com.android.build.system_ext.os_version:$(SYSTEM_EXT_OS_VERSION)
+
+INIT_BOOT_OS_VERSION ?= $(PLATFORM_VERSION_LAST_STABLE)
+BOARD_AVB_INIT_BOOT_ADD_HASH_FOOTER_ARGS += \
+ --prop com.android.build.init_boot.os_version:$(INIT_BOOT_OS_VERSION)
+
+BOOT_OS_VERSION ?= $(PLATFORM_VERSION_LAST_STABLE)
+BOARD_AVB_BOOT_ADD_HASH_FOOTER_ARGS += \
+ --prop com.android.build.boot.os_version:$(BOOT_OS_VERSION)
+
+VENDOR_OS_VERSION ?= $(PLATFORM_VERSION_LAST_STABLE)
+BOARD_AVB_VENDOR_ADD_HASHTREE_FOOTER_ARGS += \
+ --prop com.android.build.vendor.os_version:$(VENDOR_OS_VERSION)
+
+ODM_OS_VERSION ?= $(PLATFORM_VERSION_LAST_STABLE)
+BOARD_AVB_ODM_ADD_HASHTREE_FOOTER_ARGS += \
+ --prop com.android.build.odm.os_version:$(ODM_OS_VERSION)
+
+VENDOR_DLKM_OS_VERSION ?= $(PLATFORM_VERSION_LAST_STABLE)
+BOARD_AVB_VENDOR_DLKM_ADD_HASHTREE_FOOTER_ARGS += \
+ --prop com.android.build.vendor_dlkm.os_version:$(VENDOR_DLKM_OS_VERSION)
+
+ODM_DLKM_OS_VERSION ?= $(PLATFORM_VERSION_LAST_STABLE)
+BOARD_AVB_ODM_DLKM_ADD_HASHTREE_FOOTER_ARGS += \
+ --prop com.android.build.odm_dlkm.os_version:$(ODM_DLKM_OS_VERSION)
+
+SYSTEM_DLKM_OS_VERSION ?= $(PLATFORM_VERSION_LAST_STABLE)
+BOARD_AVB_SYSTEM_DLKM_ADD_HASHTREE_FOOTER_ARGS += \
+ --prop com.android.build.system_dlkm.os_version:$(SYSTEM_DLKM_OS_VERSION)
+
+# Appends fingerprint and security patch level as a AVB property descriptor.
BOARD_AVB_SYSTEM_ADD_HASHTREE_FOOTER_ARGS += \
--prop com.android.build.system.fingerprint:$(BUILD_FINGERPRINT_FROM_FILE) \
- --prop com.android.build.system.os_version:$(PLATFORM_VERSION_LAST_STABLE) \
--prop com.android.build.system.security_patch:$(PLATFORM_SECURITY_PATCH)
BOARD_AVB_PRODUCT_ADD_HASHTREE_FOOTER_ARGS += \
--prop com.android.build.product.fingerprint:$(BUILD_FINGERPRINT_FROM_FILE) \
- --prop com.android.build.product.os_version:$(PLATFORM_VERSION_LAST_STABLE) \
--prop com.android.build.product.security_patch:$(PLATFORM_SECURITY_PATCH)
BOARD_AVB_SYSTEM_EXT_ADD_HASHTREE_FOOTER_ARGS += \
--prop com.android.build.system_ext.fingerprint:$(BUILD_FINGERPRINT_FROM_FILE) \
- --prop com.android.build.system_ext.os_version:$(PLATFORM_VERSION_LAST_STABLE) \
--prop com.android.build.system_ext.security_patch:$(PLATFORM_SECURITY_PATCH)
BOARD_AVB_BOOT_ADD_HASH_FOOTER_ARGS += \
--prop com.android.build.boot.fingerprint:$(BUILD_FINGERPRINT_FROM_FILE)
BOARD_AVB_INIT_BOOT_ADD_HASH_FOOTER_ARGS += \
- --prop com.android.build.init_boot.fingerprint:$(BUILD_FINGERPRINT_FROM_FILE) \
- --prop com.android.build.init_boot.os_version:$(PLATFORM_VERSION_LAST_STABLE)
+ --prop com.android.build.init_boot.fingerprint:$(BUILD_FINGERPRINT_FROM_FILE)
BOARD_AVB_VENDOR_BOOT_ADD_HASH_FOOTER_ARGS += \
--prop com.android.build.vendor_boot.fingerprint:$(BUILD_FINGERPRINT_FROM_FILE) \
+BOARD_AVB_VENDOR_KERNEL_BOOT_ADD_HASH_FOOTER_ARGS += \
+ --prop com.android.build.vendor_kernel_boot.fingerprint:$(BUILD_FINGERPRINT_FROM_FILE) \
+
BOARD_AVB_RECOVERY_ADD_HASH_FOOTER_ARGS += \
--prop com.android.build.recovery.fingerprint:$(BUILD_FINGERPRINT_FROM_FILE)
BOARD_AVB_VENDOR_ADD_HASHTREE_FOOTER_ARGS += \
- --prop com.android.build.vendor.fingerprint:$(BUILD_FINGERPRINT_FROM_FILE) \
- --prop com.android.build.vendor.os_version:$(PLATFORM_VERSION_LAST_STABLE)
+ --prop com.android.build.vendor.fingerprint:$(BUILD_FINGERPRINT_FROM_FILE)
BOARD_AVB_ODM_ADD_HASHTREE_FOOTER_ARGS += \
- --prop com.android.build.odm.fingerprint:$(BUILD_FINGERPRINT_FROM_FILE) \
- --prop com.android.build.odm.os_version:$(PLATFORM_VERSION_LAST_STABLE)
+ --prop com.android.build.odm.fingerprint:$(BUILD_FINGERPRINT_FROM_FILE)
BOARD_AVB_VENDOR_DLKM_ADD_HASHTREE_FOOTER_ARGS += \
- --prop com.android.build.vendor_dlkm.fingerprint:$(BUILD_FINGERPRINT_FROM_FILE) \
- --prop com.android.build.vendor_dlkm.os_version:$(PLATFORM_VERSION_LAST_STABLE)
+ --prop com.android.build.vendor_dlkm.fingerprint:$(BUILD_FINGERPRINT_FROM_FILE)
BOARD_AVB_ODM_DLKM_ADD_HASHTREE_FOOTER_ARGS += \
- --prop com.android.build.odm_dlkm.fingerprint:$(BUILD_FINGERPRINT_FROM_FILE) \
- --prop com.android.build.odm_dlkm.os_version:$(PLATFORM_VERSION_LAST_STABLE)
+ --prop com.android.build.odm_dlkm.fingerprint:$(BUILD_FINGERPRINT_FROM_FILE)
BOARD_AVB_SYSTEM_DLKM_ADD_HASHTREE_FOOTER_ARGS += \
- --prop com.android.build.system_dlkm.fingerprint:$(BUILD_FINGERPRINT_FROM_FILE) \
- --prop com.android.build.system_dlkm.os_version:$(PLATFORM_VERSION_LAST_STABLE)
+ --prop com.android.build.system_dlkm.fingerprint:$(BUILD_FINGERPRINT_FROM_FILE)
BOARD_AVB_DTBO_ADD_HASH_FOOTER_ARGS += \
--prop com.android.build.dtbo.fingerprint:$(BUILD_FINGERPRINT_FROM_FILE)
@@ -3870,14 +4158,6 @@
# The following vendor- and odm-specific images needs explicit SPL set per board.
# TODO(b/210875415) Is this security_patch property used? Should it be removed from
# boot.img when there is no platform ramdisk included in it?
-ifdef BOOT_OS_VERSION
-BOARD_AVB_BOOT_ADD_HASH_FOOTER_ARGS += \
- --prop com.android.build.boot.os_version:$(BOOT_OS_VERSION)
-else
-BOARD_AVB_BOOT_ADD_HASH_FOOTER_ARGS += \
- --prop com.android.build.boot.os_version:$(PLATFORM_VERSION_LAST_STABLE)
-endif
-
ifdef BOOT_SECURITY_PATCH
BOARD_AVB_BOOT_ADD_HASH_FOOTER_ARGS += \
--prop com.android.build.boot.security_patch:$(BOOT_SECURITY_PATCH)
@@ -3924,6 +4204,7 @@
BOOT_FOOTER_ARGS := BOARD_AVB_BOOT_ADD_HASH_FOOTER_ARGS
INIT_BOOT_FOOTER_ARGS := BOARD_AVB_INIT_BOOT_ADD_HASH_FOOTER_ARGS
VENDOR_BOOT_FOOTER_ARGS := BOARD_AVB_VENDOR_BOOT_ADD_HASH_FOOTER_ARGS
+VENDOR_KERNEL_BOOT_FOOTER_ARGS := BOARD_AVB_VENDOR_KERNEL_BOOT_ADD_HASH_FOOTER_ARGS
DTBO_FOOTER_ARGS := BOARD_AVB_DTBO_ADD_HASH_FOOTER_ARGS
PVMFW_FOOTER_ARGS := BOARD_AVB_PVMFW_ADD_HASH_FOOTER_ARGS
SYSTEM_FOOTER_ARGS := BOARD_AVB_SYSTEM_ADD_HASHTREE_FOOTER_ARGS
@@ -4015,6 +4296,10 @@
$(eval $(call check-and-set-avb-args,vendor_boot))
endif
+ifdef INSTALLED_VENDOR_KERNEL_BOOTIMAGE_TARGET
+$(eval $(call check-and-set-avb-args,vendor_kernel_boot))
+endif
+
ifdef INSTALLED_SYSTEMIMAGE_TARGET
$(eval $(call check-and-set-avb-args,system))
endif
@@ -4119,6 +4404,9 @@
$(if $(BOARD_AVB_VENDOR_BOOT_KEY_PATH),\
$(AVBTOOL) extract_public_key --key $(BOARD_AVB_VENDOR_BOOT_KEY_PATH) \
--output $(1)/vendor_boot.avbpubkey)
+ $(if $(BOARD_AVB_VENDOR_KERNEL_BOOT_KEY_PATH),\
+ $(AVBTOOL) extract_public_key --key $(BOARD_AVB_VENDOR_KERNEL_BOOT_KEY_PATH) \
+ --output $(1)/vendor_kernel_boot.avbpubkey)
$(if $(BOARD_AVB_SYSTEM_KEY_PATH),\
$(hide) $(AVBTOOL) extract_public_key --key $(BOARD_AVB_SYSTEM_KEY_PATH) \
--output $(1)/system.avbpubkey)
@@ -4190,6 +4478,10 @@
$(call images-for-partitions,$(BOARD_AVB_VBMETA_SYSTEM)) \
$(BOARD_AVB_VBMETA_SYSTEM_KEY_PATH)
$(call build-chained-vbmeta-image,vbmeta_system)
+
+$(call declare-1p-container,$(INSTALLED_VBMETA_SYSTEMIMAGE_TARGET),)
+
+SYSTEM_NOTICE_DEPS += $(INSTALLED_VBMETA_SYSTEMIMAGE_TARGET)
endif
endif # BUILDING_SYSTEM_IMAGE
@@ -4200,6 +4492,10 @@
$(call images-for-partitions,$(BOARD_AVB_VBMETA_VENDOR)) \
$(BOARD_AVB_VBMETA_VENDOR_KEY_PATH)
$(call build-chained-vbmeta-image,vbmeta_vendor)
+
+$(call declare-1p-container,$(INSTALLED_VBMETA_VENDORIMAGE_TARGET),)
+
+UNMOUNTED_NOTICE_DEPS += $(INSTALLED_VBMETA_VENDORIMAGE_TARGET)
endif
define build-vbmetaimage-target
@@ -4224,6 +4520,7 @@
$(INSTALLED_BOOTIMAGE_TARGET) \
$(INSTALLED_INIT_BOOT_IMAGE_TARGET) \
$(INSTALLED_VENDOR_BOOTIMAGE_TARGET) \
+ $(INSTALLED_VENDOR_KERNEL_BOOTIMAGE_TARGET) \
$(INSTALLED_SYSTEMIMAGE_TARGET) \
$(INSTALLED_VENDORIMAGE_TARGET) \
$(INSTALLED_PRODUCTIMAGE_TARGET) \
@@ -4243,6 +4540,10 @@
$(BOARD_AVB_KEY_PATH)
$(build-vbmetaimage-target)
+$(call declare-1p-container,$(INSTALLED_VBMETAIMAGE_TARGET),)
+
+UNMOUNTED_NOTICE_DEPS += $(INSTALLED_VBMETAIMAGE_TARGET)
+
.PHONY: vbmetaimage-nodeps
vbmetaimage-nodeps: PRIVATE_AVB_VBMETA_SIGNING_ARGS := \
--algorithm $(BOARD_AVB_ALGORITHM) --key $(BOARD_AVB_KEY_PATH)
@@ -4305,6 +4606,7 @@
check_vintf_all_deps += $(check_vintf_system_log)
$(check_vintf_system_log): $(HOST_OUT_EXECUTABLES)/checkvintf $(check_vintf_system_deps)
@( $< --check-one --dirmap /system:$(TARGET_OUT) > $@ 2>&1 ) || ( cat $@ && exit 1 )
+$(call declare-0p-target,$(check_vintf_system_log))
check_vintf_system_log :=
vintffm_log := $(intermediates)/vintffm.log
@@ -4313,6 +4615,8 @@
@( $< --check --dirmap /system:$(TARGET_OUT) \
$(VINTF_FRAMEWORK_MANIFEST_FROZEN_DIR) > $@ 2>&1 ) || ( cat $@ && exit 1 )
+$(call declare-0p-target,$(vintffm_log))
+
endif # check_vintf_system_deps
check_vintf_system_deps :=
@@ -4334,6 +4638,7 @@
( $< --check-one --dirmap /vendor:$(TARGET_OUT_VENDOR) \
--property ro.boot.product.vendor.sku=$(filter-out EMPTY_VENDOR_SKU_PLACEHOLDER,$(vendor_sku)) \
> $@ 2>&1 ) || ( cat $@ && exit 1 ); )
+$(call declare-0p-target,$(check_vintf_vendor_log))
check_vintf_vendor_log :=
endif # check_vintf_vendor_deps
check_vintf_vendor_deps :=
@@ -4355,6 +4660,9 @@
$(BUILT_KERNEL_VERSION_FILE):
echo $(BOARD_KERNEL_VERSION) > $@
+$(call declare-0p-target,$(BUILT_KERNEL_CONFIGS_FILE))
+$(call declare-0p-target,$(BUILT_KERNEL_VERSION_FILE))
+
my_board_extracted_kernel := true
endif # BOARD_KERNEL_VERSION
endif # BOARD_KERNEL_CONFIG_FILE
@@ -4378,6 +4686,8 @@
--output-configs $@ \
--output-release $(BUILT_KERNEL_VERSION_FILE)
+$(call declare-0p-target,$(BUILT_KERNEL_CONFIGS_FILE))
+
my_board_extracted_kernel := true
endif # INSTALLED_KERNEL_TARGET
endif # my_board_extracted_kernel
@@ -4397,6 +4707,8 @@
--output-configs $@ \
--output-release $(BUILT_KERNEL_VERSION_FILE)
+$(call declare-0p-target,$(BUILT_KERNEL_CONFIGS_FILE))
+
my_board_extracted_kernel := true
endif # INSTALLED_BOOTIMAGE_TARGET
endif # my_board_extracted_kernel
@@ -4486,6 +4798,8 @@
--property ro.boot.product.vendor.sku=$(filter-out EMPTY_VENDOR_SKU_PLACEHOLDER,$(vendor_sku)) \
>> $@ 2>&1 ) || (cat $@ && exit 1); ))
+$(call declare-0p-target,$(check_vintf_compatible_log))
+
check_vintf_compatible_log :=
check_vintf_compatible_args :=
check_vintf_compatible_deps :=
@@ -4549,6 +4863,8 @@
$(call intermediates-dir-for,PACKAGING,check-all-partition-sizes)/misc_info.txt, \
$@)
+$(call declare-0p-target,$(check_all_partition_sizes_log))
+
.PHONY: check-all-partition-sizes
check-all-partition-sizes: $(check_all_partition_sizes_log)
@@ -4640,6 +4956,7 @@
e2fsdroid \
fc_sort \
fec \
+ fsck.erofs \
fsck.f2fs \
fs_config \
generate_gki_certificate \
@@ -4666,6 +4983,7 @@
mksquashfs \
mksquashfsimage.sh \
mkuserimg_mke2fs \
+ ota_extractor \
ota_from_target_files \
repack_bootimg \
secilc \
@@ -4756,6 +5074,9 @@
cp $(SOONG_ZIP) $(ZIP2ZIP) $(MERGE_ZIPS) $(PRIVATE_ZIP_ROOT)/bin/
$(SOONG_ZIP) -o $@ -C $(PRIVATE_ZIP_ROOT) -D $(PRIVATE_ZIP_ROOT)
+$(call declare-1p-container,$(BUILT_OTATOOLS_PACKAGE),build)
+$(call declare-container-license-deps,$(INTERNAL_OTATOOLS_PACKAGE_FILES) $(INTERNAL_OTATOOLS_RELEASETOOLS),$(BUILT_OTATOOLS_PACKAGE):)
+
.PHONY: otatools-package
otatools-package: $(BUILT_OTATOOLS_PACKAGE)
@@ -4807,6 +5128,10 @@
echo "vendor_boot=true" >> $@
echo "vendor_boot_size=$(BOARD_VENDOR_BOOTIMAGE_PARTITION_SIZE)" >> $@
endif
+ifneq ($(INSTALLED_VENDOR_KERNEL_BOOTIMAGE_TARGET),)
+ echo "vendor_kernel_boot=true" >> $@
+ echo "vendor_kernel_boot_size=$(BOARD_VENDOR_KERNEL_BOOTIMAGE_PARTITION_SIZE)" >> $@
+endif
ifeq ($(INSTALLED_RECOVERYIMAGE_TARGET),)
$(hide) echo "no_recovery=true" >> $@
endif
@@ -4887,6 +5212,12 @@
echo "avb_vendor_boot_algorithm=$(BOARD_AVB_VENDOR_BOOT_ALGORITHM)" >> $@
echo "avb_vendor_boot_rollback_index_location=$(BOARD_AVB_VENDOR_BOOT_ROLLBACK_INDEX_LOCATION)" >> $@
endif # BOARD_AVB_VENDOR_BOOT_KEY_PATH
+ echo "avb_vendor_kernel_boot_add_hash_footer_args=$(BOARD_AVB_VENDOR_KERNEL_BOOT_ADD_HASH_FOOTER_ARGS)" >> $@
+ifdef BOARD_AVB_VENDOR_KERNEL_BOOT_KEY_PATH
+ echo "avb_vendor_kernel_boot_key_path=$(BOARD_AVB_VENDOR_KERNEL_BOOT_KEY_PATH)" >> $@
+ echo "avb_vendor_kernel_boot_algorithm=$(BOARD_AVB_VENDOR_KERNEL_BOOT_ALGORITHM)" >> $@
+ echo "avb_vendor_kernel_boot_rollback_index_location=$(BOARD_AVB_VENDOR_KERNEL_BOOT_ROLLBACK_INDEX_LOCATION)" >> $@
+endif # BOARD_AVB_VENDOR_KERNEL_BOOT_KEY_PATH
$(hide) echo "avb_recovery_add_hash_footer_args=$(BOARD_AVB_RECOVERY_ADD_HASH_FOOTER_ARGS)" >> $@
ifdef BOARD_AVB_RECOVERY_KEY_PATH
$(hide) echo "avb_recovery_key_path=$(BOARD_AVB_RECOVERY_KEY_PATH)" >> $@
@@ -4992,6 +5323,8 @@
$(hide) echo "target_flatten_apex=false" >> $@
endif
+$(call declare-0p-target,$(INSTALLED_MISC_INFO_TARGET))
+
.PHONY: misc_info
misc_info: $(INSTALLED_MISC_INFO_TARGET)
@@ -5040,7 +5373,9 @@
updaer_dep :=
ifeq ($(AB_OTA_UPDATER),true)
updater_dep += system/update_engine/update_engine.conf
+$(call declare-1p-target,system/update_engine/update_engine.conf,system/update_engine)
updater_dep += external/zucchini/version_info.h
+$(call declare-license-metadata,external/zucchini/version_info.h,legacy_notice,notice,external/zucchini/LICENSE,external/zucchini)
updater_dep += $(HOST_OUT_SHARED_LIBRARIES)/liblz4.so
endif
@@ -5402,8 +5737,10 @@
$(call package_files-copy-root, \
$(TARGET_VENDOR_RAMDISK_OUT),$(zip_root)/VENDOR_BOOT/RAMDISK)
ifdef INSTALLED_DTBIMAGE_TARGET
+ifneq ($(BUILDING_VENDOR_KERNEL_BOOT_IMAGE),true)
cp $(INSTALLED_DTBIMAGE_TARGET) $(zip_root)/VENDOR_BOOT/dtb
endif
+endif # end of INSTALLED_DTBIMAGE_TARGET
ifdef INTERNAL_VENDOR_BOOTCONFIG_TARGET
cp $(INTERNAL_VENDOR_BOOTCONFIG_TARGET) $(zip_root)/VENDOR_BOOT/vendor_bootconfig
endif
@@ -5428,6 +5765,17 @@
))
endif # INTERNAL_VENDOR_RAMDISK_FRAGMENTS != ""
endif # INSTALLED_VENDOR_BOOTIMAGE_TARGET
+ifdef INSTALLED_VENDOR_KERNEL_BOOTIMAGE_TARGET
+ mkdir -p $(zip_root)/VENDOR_KERNEL_BOOT
+ $(call package_files-copy-root, \
+ $(TARGET_VENDOR_KERNEL_RAMDISK_OUT),$(zip_root)/VENDOR_KERNEL_BOOT/RAMDISK)
+ifdef INSTALLED_DTBIMAGE_TARGET
+ cp $(INSTALLED_DTBIMAGE_TARGET) $(zip_root)/VENDOR_KERNEL_BOOT/dtb
+endif
+ifdef BOARD_KERNEL_PAGESIZE
+ echo "$(BOARD_KERNEL_PAGESIZE)" > $(zip_root)/VENDOR_KERNEL_BOOT/pagesize
+endif
+endif # INSTALLED_VENDOR_BOOTIMAGE_TARGET
ifdef BUILDING_SYSTEM_IMAGE
@# Contents of the system image
$(hide) $(call package_files-copy-root, \
@@ -5715,6 +6063,41 @@
.PHONY: target-files-package
target-files-package: $(BUILT_TARGET_FILES_PACKAGE)
+$(call declare-1p-container,$(BUILT_TARGET_FILES_PACKAGE),)
+$(call declare-container-license-deps,$(BUILT_TARGET_FILES_PACKAGE), $(INSTALLED_RADIOIMAGE_TARGET) \
+ $(INSTALLED_RECOVERYIMAGE_TARGET) \
+ $(INSTALLED_CACHEIMAGE_TARGET) \
+ $(INSTALLED_DTBOIMAGE_TARGET) \
+ $(INSTALLED_PVMFWIMAGE_TARGET) \
+ $(INSTALLED_PVMFW_EMBEDDED_AVBKEY_TARGET) \
+ $(INSTALLED_CUSTOMIMAGES_TARGET) \
+ $(INSTALLED_ANDROID_INFO_TXT_TARGET) \
+ $(INSTALLED_KERNEL_TARGET) \
+ $(INSTALLED_RAMDISK_TARGET) \
+ $(INSTALLED_DTBIMAGE_TARGET) \
+ $(INSTALLED_2NDBOOTLOADER_TARGET) \
+ $(BOARD_PREBUILT_DTBOIMAGE) \
+ $(BOARD_PREBUILT_RECOVERY_DTBOIMAGE) \
+ $(BOARD_RECOVERY_ACPIO) \
+ $(PRODUCT_SYSTEM_BASE_FS_PATH) \
+ $(PRODUCT_VENDOR_BASE_FS_PATH) \
+ $(PRODUCT_PRODUCT_BASE_FS_PATH) \
+ $(PRODUCT_SYSTEM_EXT_BASE_FS_PATH) \
+ $(PRODUCT_ODM_BASE_FS_PATH) \
+ $(PRODUCT_VENDOR_DLKM_BASE_FS_PATH) \
+ $(PRODUCT_ODM_DLKM_BASE_FS_PATH) \
+ $(PRODUCT_SYSTEM_DLKM_BASE_FS_PATH) \
+ $(LPMAKE) \
+ $(SELINUX_FC) \
+ $(INSTALLED_MISC_INFO_TARGET) \
+ $(APKCERTS_FILE) \
+ $(SOONG_APEX_KEYS_FILE) \
+ $(HOST_OUT_EXECUTABLES)/fs_config \
+ $(ADD_IMG_TO_TARGET_FILES) \
+ $(MAKE_RECOVERY_PATCH) \
+ $(BUILT_KERNEL_CONFIGS_FILE) \
+ $(BUILT_KERNEL_VERSION_FILE),$(BUILT_TARGET_FILES_PACKAGE):)
+
$(call dist-for-goals, target-files-package, $(BUILT_TARGET_FILES_PACKAGE))
# -----------------------------------------------------------------
@@ -5754,12 +6137,17 @@
INTERNAL_OTA_PACKAGE_TARGET := $(PRODUCT_OUT)/$(name).zip
INTERNAL_OTA_METADATA := $(PRODUCT_OUT)/ota_metadata
+$(call declare-0p-target,$(INTERNAL_OTA_METADATA))
+
$(INTERNAL_OTA_PACKAGE_TARGET): KEY_CERT_PAIR := $(DEFAULT_KEY_CERT_PAIR)
$(INTERNAL_OTA_PACKAGE_TARGET): .KATI_IMPLICIT_OUTPUTS := $(INTERNAL_OTA_METADATA)
$(INTERNAL_OTA_PACKAGE_TARGET): $(BUILT_TARGET_FILES_PACKAGE) $(OTA_FROM_TARGET_FILES) $(INTERNAL_OTATOOLS_FILES)
@echo "Package OTA: $@"
$(call build-ota-package-target,$@,-k $(KEY_CERT_PAIR) --output_metadata_path $(INTERNAL_OTA_METADATA))
+$(call declare-1p-container,$(INTERNAL_OTA_PACKAGE_TARGET),)
+$(call declare-container-license-deps,$(INTERNAL_OTA_PACKAGE_TARGET),$(BUILT_TARGET_FILES_PACKAGE) $(OTA_FROM_TARGET_FILES) $(INTERNAL_OTATOOLS_FILES),$(PRODUCT_OUT)/:/)
+
.PHONY: otapackage
otapackage: $(INTERNAL_OTA_PACKAGE_TARGET)
@@ -5775,6 +6163,9 @@
@echo "Package OTA (retrofit dynamic partitions): $@"
$(call build-ota-package-target,$@,-k $(KEY_CERT_PAIR) --retrofit_dynamic_partitions)
+$(call declare-1p-container,$(INTERNAL_OTA_RETROFIT_DYNAMIC_PARTITIONS_PACKAGE_TARGET),)
+$(call declare-container-license-deps,$(INTERNAL_OTA_RETROFIT_DYNAMIC_PARTITIONS_PACKAGE_TARGET),$(BUILT_TARGET_FILES_PACKAGE) $(OTA_FROM_TARGET_FILES) $(INTERNAL_OTATOOLS_FILES),$(PRODUCT_OUT)/:/)
+
.PHONY: otardppackage
otapackage otardppackage: $(INTERNAL_OTA_RETROFIT_DYNAMIC_PARTITIONS_PACKAGE_TARGET)
@@ -5790,6 +6181,10 @@
@echo "Package partial OTA: $@"
$(call build-ota-package-target,$@,-k $(KEY_CERT_PAIR) --partial "$(BOARD_PARTIAL_OTA_UPDATE_PARTITIONS_LIST)")
+$(call declare-1p-container,$(INTERNAL_OTA_PARTIAL_PACKAGE_TARGET),)
+$(call declare-container-license-deps,$(INTERNAL_OTA_PARTIAL_PACKAGE_TARGET),$(BUILT_TARGET_FILES_PACKAGE) $(OTA_FROM_TARGET_FILES) $(INTERNAL_OTATOOLS_FILES),$(PRODUCT_OUT)/:/)
+
+
.PHONY: partialotapackage
partialotapackage: $(INTERNAL_OTA_PARTIAL_PACKAGE_TARGET)
@@ -5829,6 +6224,7 @@
$(DEXPREOPT_TOOLS_ZIP): $(SOONG_ZIP)
$(hide) mkdir -p $(dir $@)
$(hide) $(SOONG_ZIP) -d -o $@ -j $(addprefix -f ,$(PRIVATE_DEXPREOPT_TOOLS_DEPS)) -f $$(realpath $(DEX2OAT))
+$(call declare-1p-target,$(DEXPREOPT_TOOLS_ZIP),)
endif # DEX2OAT is set
endif # BUILD_OS == linux
@@ -5861,28 +6257,49 @@
.PHONY: dexpreopt_config_zip
dexpreopt_config_zip: $(DEXPREOPT_CONFIG_ZIP)
+$(call declare-1p-target,$(DEXPREOPT_CONFIG_ZIP),)
+
# -----------------------------------------------------------------
# A zip of the symbols directory. Keep the full paths to make it
# more obvious where these files came from.
+# Also produces a textproto containing mappings from elf IDs to symbols
+# filename, which will allow finding the appropriate symbols to deobfuscate
+# a stack trace frame.
#
+
name := $(TARGET_PRODUCT)
ifeq ($(TARGET_BUILD_TYPE),debug)
name := $(name)_debug
endif
-name := $(name)-symbols-$(FILE_NAME_TAG)
-SYMBOLS_ZIP := $(PRODUCT_OUT)/$(name).zip
+# The path to the zip file containing binaries with symbols.
+SYMBOLS_ZIP := $(PRODUCT_OUT)/$(name)-symbols-$(FILE_NAME_TAG).zip
+# The path to a file containing mappings from elf IDs to filenames.
+SYMBOLS_MAPPING := $(PRODUCT_OUT)/$(name)-symbols-mapping-$(FILE_NAME_TAG).textproto
+.KATI_READONLY := SYMBOLS_ZIP SYMBOLS_MAPPING
# For apps_only build we'll establish the dependency later in build/make/core/main.mk.
ifeq (,$(TARGET_BUILD_UNBUNDLED))
$(SYMBOLS_ZIP): $(INTERNAL_ALLIMAGES_FILES) $(updater_dep)
endif
$(SYMBOLS_ZIP): PRIVATE_LIST_FILE := $(call intermediates-dir-for,PACKAGING,symbols)/filelist
-$(SYMBOLS_ZIP): $(SOONG_ZIP)
+$(SYMBOLS_ZIP): PRIVATE_MAPPING_PACKAGING_DIR := $(call intermediates-dir-for,PACKAGING,elf_symbol_mapping)
+$(SYMBOLS_ZIP): $(SOONG_ZIP) $(SYMBOLS_MAP)
@echo "Package symbols: $@"
$(hide) rm -rf $@ $(PRIVATE_LIST_FILE)
- $(hide) mkdir -p $(dir $@) $(TARGET_OUT_UNSTRIPPED) $(dir $(PRIVATE_LIST_FILE))
+ $(hide) mkdir -p $(TARGET_OUT_UNSTRIPPED) $(dir $(PRIVATE_LIST_FILE)) $(PRIVATE_MAPPING_PACKAGING_DIR)
+ # Find all of the files in the symbols directory and zip them into the symbols zip.
$(hide) find -L $(TARGET_OUT_UNSTRIPPED) -type f | sort >$(PRIVATE_LIST_FILE)
$(hide) $(SOONG_ZIP) --ignore_missing_files -d -o $@ -C $(OUT_DIR)/.. -l $(PRIVATE_LIST_FILE)
+ # Find all of the files in the symbols mapping directory and merge them into the symbols mapping textproto.
+ $(hide) find -L $(PRIVATE_MAPPING_PACKAGING_DIR) -type f | sort >$(PRIVATE_LIST_FILE)
+ $(hide) $(SYMBOLS_MAP) -merge $(SYMBOLS_MAPPING) -ignore_missing_files @$(PRIVATE_LIST_FILE)
+$(SYMBOLS_ZIP): .KATI_IMPLICIT_OUTPUTS := $(SYMBOLS_MAPPING)
+
+$(call declare-1p-container,$(SYMBOLS_ZIP),)
+ifeq (,$(TARGET_BUILD_UNBUNDLED))
+$(call declare-container-license-deps,$(SYMBOLS_ZIP),$(INTERNAL_ALLIMAGES_FILES) $(updater_dep),$(PRODUCT_OUT)/:/)
+endif
+
# -----------------------------------------------------------------
# A zip of the coverage directory.
#
@@ -5902,17 +6319,27 @@
$(hide) find $(TARGET_OUT_COVERAGE) | sort >$(PRIVATE_LIST_FILE)
$(hide) $(SOONG_ZIP) -d -o $@ -C $(TARGET_OUT_COVERAGE) -l $(PRIVATE_LIST_FILE)
+$(call declare-1p-container,$(COVERAGE_ZIP),)
+ifeq (,$(TARGET_BUILD_UNBUNDLED))
+$(call declare-container-license-deps,$(COVERAGE_ZIP),$(INTERNAL_ALLIMAGE_FILES),$(PRODUCT_OUT)/:/)
+endif
+
+SYSTEM_NOTICE_DEPS += $(COVERAGE_ZIP)
+
#------------------------------------------------------------------
# Export the LLVM profile data tool and dependencies for Clang coverage processing
#
ifeq (true,$(CLANG_COVERAGE))
LLVM_PROFDATA := $(LLVM_PREBUILTS_BASE)/linux-x86/$(LLVM_PREBUILTS_VERSION)/bin/llvm-profdata
+ LLVM_COV := $(LLVM_PREBUILTS_BASE)/linux-x86/$(LLVM_PREBUILTS_VERSION)/bin/llvm-cov
LIBCXX := $(LLVM_PREBUILTS_BASE)/linux-x86/$(LLVM_PREBUILTS_VERSION)/lib64/libc++.so.1
- PROFDATA_ZIP := $(PRODUCT_OUT)/llvm-profdata.zip
- $(PROFDATA_ZIP): $(SOONG_ZIP)
- $(hide) $(SOONG_ZIP) -d -o $@ -C $(LLVM_PREBUILTS_BASE)/linux-x86/$(LLVM_PREBUILTS_VERSION) -f $(LLVM_PROFDATA) -f $(LIBCXX)
+ # Use llvm-profdata.zip for backwards compatibility with tradefed code.
+ LLVM_COVERAGE_TOOLS_ZIP := $(PRODUCT_OUT)/llvm-profdata.zip
- $(call dist-for-goals,droidcore-unbundled apps_only,$(PROFDATA_ZIP))
+ $(LLVM_COVERAGE_TOOLS_ZIP): $(SOONG_ZIP)
+ $(hide) $(SOONG_ZIP) -d -o $@ -C $(LLVM_PREBUILTS_BASE)/linux-x86/$(LLVM_PREBUILTS_VERSION) -f $(LLVM_PROFDATA) -f $(LIBCXX) -f $(LLVM_COV)
+
+ $(call dist-for-goals,droidcore-unbundled apps_only,$(LLVM_COVERAGE_TOOLS_ZIP))
endif
# -----------------------------------------------------------------
@@ -5967,17 +6394,40 @@
#------------------------------------------------------------------
# A zip of Proguard obfuscation dictionary files.
+# Also produces a textproto containing mappings from the hashes of the
+# dictionary contents (which are also stored in the dex files on the
+# devices) to the filename of the proguard dictionary, which will allow
+# finding the appropriate dictionary to deobfuscate a stack trace frame.
#
+
+# The path to the zip file containing proguard dictionaries.
PROGUARD_DICT_ZIP := $(PRODUCT_OUT)/$(TARGET_PRODUCT)-proguard-dict-$(FILE_NAME_TAG).zip
+# The path to the zip file containing mappings from dictionary hashes to filenames.
+PROGUARD_DICT_MAPPING := $(PRODUCT_OUT)/$(TARGET_PRODUCT)-proguard-dict-mapping-$(FILE_NAME_TAG).textproto
+.KATI_READONLY := PROGUARD_DICT_ZIP PROGUARD_DICT_MAPPING
# For apps_only build we'll establish the dependency later in build/make/core/main.mk.
ifeq (,$(TARGET_BUILD_UNBUNDLED))
$(PROGUARD_DICT_ZIP): $(INTERNAL_ALLIMAGES_FILES) $(updater_dep)
endif
$(PROGUARD_DICT_ZIP): PRIVATE_PACKAGING_DIR := $(call intermediates-dir-for,PACKAGING,proguard_dictionary)
-$(PROGUARD_DICT_ZIP): $(SOONG_ZIP)
+$(PROGUARD_DICT_ZIP): PRIVATE_MAPPING_PACKAGING_DIR := $(call intermediates-dir-for,PACKAGING,proguard_dictionary_mapping)
+$(PROGUARD_DICT_ZIP): PRIVATE_LIST_FILE := $(call intermediates-dir-for,PACKAGING,proguard_dictionary_filelist)/filelist
+$(PROGUARD_DICT_ZIP): $(SOONG_ZIP) $(SYMBOLS_MAP)
@echo "Packaging Proguard obfuscation dictionary files."
- mkdir -p $(dir $@) $(PRIVATE_PACKAGING_DIR)
- $(SOONG_ZIP) --ignore_missing_files -d -o $@ -C $(PRIVATE_PACKAGING_DIR) -P out/target/common/obj -D $(PRIVATE_PACKAGING_DIR)
+ rm -rf $@ $(PRIVATE_LIST_FILE)
+ mkdir -p $(PRIVATE_PACKAGING_DIR) $(PRIVATE_MAPPING_PACKAGING_DIR) $(dir $(PRIVATE_LIST_FILE))
+ # Zip all of the files in the proguard dictionary directory.
+ $(SOONG_ZIP) --ignore_missing_files -d -o $@ -C $(PRIVATE_PACKAGING_DIR) -D $(PRIVATE_PACKAGING_DIR)
+ # Find all of the files in the proguard dictionary mapping directory and merge them into the mapping textproto.
+ # Strip the PRIVATE_PACKAGING_DIR off the filenames to match soong_zip's -C argument.
+ $(hide) find -L $(PRIVATE_MAPPING_PACKAGING_DIR) -type f | sort >$(PRIVATE_LIST_FILE)
+ $(SYMBOLS_MAP) -merge $(PROGUARD_DICT_MAPPING) -strip_prefix $(PRIVATE_PACKAGING_DIR)/ -ignore_missing_files @$(PRIVATE_LIST_FILE)
+$(PROGUARD_DICT_ZIP): .KATI_IMPLICIT_OUTPUTS := $(PROGUARD_DICT_MAPPING)
+
+$(call declare-1p-container,$(PROGUARD_DICT_ZIP),)
+ifeq (,$(TARGET_BUILD_UNBUNDLED))
+$(call declare-container-license-deps,$(PROGUARD_DICT_ZIP),$(INTERNAL_ALLIMAGES_FILES) $(updater_dep),$(PRODUCT_OUT)/:/)
+endif
#------------------------------------------------------------------
# A zip of Proguard usage files.
@@ -6008,6 +6458,23 @@
find $(PRIVATE_PACKAGING_DIR) -name proguard_usage.zip > $(PRIVATE_LIST_FILE)
$(MERGE_ZIPS) $@ @$(PRIVATE_LIST_FILE)
+$(call declare-1p-container,$(PROGUARD_USAGE_ZIP),)
+ifeq (,$(TARGET_BUILD_UNBUNDLED))
+$(call declare-container-license-deps,$(PROGUARD_USAGE_ZIP),$(INSTALLED_SYSTEMIMAGE_TARGET) \
+ $(INSTALLED_RAMDISK_TARGET) \
+ $(INSTALLED_BOOTIMAGE_TARGET) \
+ $(INSTALLED_INIT_BOOT_IMAGE_TARGET) \
+ $(INSTALLED_USERDATAIMAGE_TARGET) \
+ $(INSTALLED_VENDORIMAGE_TARGET) \
+ $(INSTALLED_PRODUCTIMAGE_TARGET) \
+ $(INSTALLED_SYSTEM_EXTIMAGE_TARGET) \
+ $(INSTALLED_ODMIMAGE_TARGET) \
+ $(INSTALLED_VENDOR_DLKMIMAGE_TARGET) \
+ $(INSTALLED_ODM_DLKMIMAGE_TARGET) \
+ $(INSTALLED_SYSTEM_DLKMIMAGE_TARGET) \
+ $(updater_dep),$(PROGUARD_USAGE_ZIP):/)
+endif
+
ifeq (true,$(PRODUCT_USE_DYNAMIC_PARTITIONS))
# Dump variables used by build_super_image.py (for building super.img and super_empty.img).
@@ -6130,6 +6597,8 @@
$(call dist-for-goals,dist_files,$(INSTALLED_SUPERIMAGE_EMPTY_TARGET))
+$(call declare-0p-target,$(INSTALLED_SUPERIMAGE_EMPTY_TARGET))
+
endif # BUILDING_SUPER_EMPTY_IMAGE
@@ -6151,6 +6620,9 @@
--additional IMAGES/VerifiedBootParams.textproto:VerifiedBootParams.textproto \
$(BUILT_TARGET_FILES_PACKAGE) $@
+$(call declare-1p-container,$(INTERNAL_UPDATE_PACKAGE_TARGET),)
+$(call declare-container-license-deps,$(INTERNAL_UPDATE_PACKAGE_TARGET),$(BUILT_TARGET_FILES_PACKAGE) $(IMG_FROM_TARGET_FILES),$(PRODUCT_OUT)/:/)
+
.PHONY: updatepackage
updatepackage: $(INTERNAL_UPDATE_PACKAGE_TARGET)
$(call dist-for-goals,updatepackage,$(INTERNAL_UPDATE_PACKAGE_TARGET))
@@ -6278,7 +6750,6 @@
ifeq ($(BUILD_EMULATOR),true)
INTERNAL_EMULATOR_PACKAGE_FILES += \
$(HOST_OUT_EXECUTABLES)/emulator$(HOST_EXECUTABLE_SUFFIX) \
- prebuilts/qemu-kernel/$(TARGET_ARCH)/kernel-qemu \
$(INSTALLED_RAMDISK_TARGET) \
$(INSTALLED_SYSTEMIMAGE_TARGET) \
$(INSTALLED_USERDATAIMAGE_TARGET)
@@ -6499,3 +6970,11 @@
.PHONY: haiku-rust
haiku-rust: $(SOONG_RUST_FUZZ_PACKAGING_ARCH_MODULES) $(ALL_RUST_FUZZ_TARGETS)
$(call dist-for-goals,haiku-rust,$(SOONG_RUST_FUZZ_PACKAGING_ARCH_MODULES))
+
+
+# -----------------------------------------------------------------
+# OS Licensing
+
+include $(BUILD_SYSTEM)/os_licensing.mk
+
+# When appending new code to this file, please insert above OS Licensing
diff --git a/core/android_soong_config_vars.mk b/core/android_soong_config_vars.mk
index 0befbfa..6c32da4 100644
--- a/core/android_soong_config_vars.mk
+++ b/core/android_soong_config_vars.mk
@@ -36,65 +36,41 @@
$(call add_soong_config_var,ANDROID,BOARD_BUILD_SYSTEM_ROOT_IMAGE)
$(call add_soong_config_var,ANDROID,PRODUCT_INSTALL_DEBUG_POLICY_TO_SYSTEM_EXT)
-ifneq (,$(filter sdk win_sdk sdk_addon,$(MAKECMDGOALS)))
- # The artifacts in the SDK zip are OK to build with prebuilt stubs enabled,
- # even if prebuilt apexes are not enabled, because the system images in the
- # SDK stub are not currently used (and will be removed: b/205008975).
- MODULE_BUILD_FROM_SOURCE ?= false
-else ifeq (,$(findstring com.google.android.conscrypt,$(PRODUCT_PACKAGES)))
+# Default behavior for the tree wrt building modules or using prebuilts. This
+# can always be overridden by setting the environment variable
+# MODULE_BUILD_FROM_SOURCE.
+BRANCH_DEFAULT_MODULE_BUILD_FROM_SOURCE := true
+
+ifneq (,$(MODULE_BUILD_FROM_SOURCE))
+ # Keep an explicit setting.
+else ifeq (,$(filter sdk win_sdk sdk_addon,$(MAKECMDGOALS))$(findstring com.google.android.conscrypt,$(PRODUCT_PACKAGES)))
# Prebuilt module SDKs require prebuilt modules to work, and currently
# prebuilt modules are only provided for com.google.android.xxx. If we can't
# find one of them in PRODUCT_PACKAGES then assume com.android.xxx are in use,
# and disable prebuilt SDKs. In particular this applies to AOSP builds.
+ #
+ # However, sdk/win_sdk/sdk_addon builds might not include com.google.android.xxx
+ # packages, so for those we respect the default behavior.
MODULE_BUILD_FROM_SOURCE := true
+else ifneq (,$(PRODUCT_MODULE_BUILD_FROM_SOURCE))
+ # Let products override the branch default.
+ MODULE_BUILD_FROM_SOURCE := $(PRODUCT_MODULE_BUILD_FROM_SOURCE)
+else
+ MODULE_BUILD_FROM_SOURCE := $(BRANCH_DEFAULT_MODULE_BUILD_FROM_SOURCE)
endif
-# TODO(b/172480615): Remove when platform uses ART Module prebuilts by default.
-ifeq (,$(filter art_module,$(SOONG_CONFIG_NAMESPACES)))
- $(call add_soong_config_namespace,art_module)
- SOONG_CONFIG_art_module += source_build
-endif
-ifneq (,$(SOONG_CONFIG_art_module_source_build))
+ifneq (,$(ART_MODULE_BUILD_FROM_SOURCE))
# Keep an explicit setting.
else ifneq (,$(findstring .android.art,$(TARGET_BUILD_APPS)))
# Build ART modules from source if they are listed in TARGET_BUILD_APPS.
- SOONG_CONFIG_art_module_source_build := true
-else ifeq (,$(filter-out modules_% mainline_modules_%,$(TARGET_PRODUCT)))
- # Always build from source for the module targets. This ought to be covered by
- # the TARGET_BUILD_APPS check above, but there are test builds that don't set it.
- SOONG_CONFIG_art_module_source_build := true
-else ifeq (true,$(MODULE_BUILD_FROM_SOURCE))
- # Build from source if other Mainline modules are.
- SOONG_CONFIG_art_module_source_build := true
-else ifneq (,$(filter true,$(NATIVE_COVERAGE) $(CLANG_COVERAGE)))
- # Always build ART APEXes from source in coverage builds since the prebuilts
- # aren't built with instrumentation.
- # TODO(b/172480617): Find another solution for this.
- SOONG_CONFIG_art_module_source_build := true
-else ifneq (,$(SANITIZE_TARGET)$(SANITIZE_HOST))
- # Prebuilts aren't built with sanitizers either.
- 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.
- SOONG_CONFIG_art_module_source_build := true
-else ifneq (,$(filter dex2oatds dex2oats,$(PRODUCT_HOST_PACKAGES)))
- # Some products depend on host tools that aren't available as prebuilts.
- SOONG_CONFIG_art_module_source_build := true
-else ifeq (,$(findstring com.google.android.art,$(PRODUCT_PACKAGES)))
- # TODO(b/192006406): There is currently no good way to control which prebuilt
- # APEX (com.google.android.art or com.android.art) gets picked for deapexing
- # to provide dex jars for hiddenapi and dexpreopting. Instead the AOSP APEX is
- # completely disabled, and we build from source for AOSP products.
- SOONG_CONFIG_art_module_source_build := true
+ ART_MODULE_BUILD_FROM_SOURCE := true
else
- # This sets the default for building ART APEXes from source rather than
- # prebuilts (in packages/modules/ArtPrebuilt and prebuilt/module_sdk/art) in
- # all other platform builds.
- SOONG_CONFIG_art_module_source_build ?= true
+ # Do the same as other modules by default.
+ ART_MODULE_BUILD_FROM_SOURCE := $(MODULE_BUILD_FROM_SOURCE)
endif
+$(call soong_config_set,art_module,source_build,$(ART_MODULE_BUILD_FROM_SOURCE))
+
# Apex build mode variables
ifdef APEX_BUILD_FOR_PRE_S_DEVICES
$(call add_soong_config_var_value,ANDROID,library_linking_strategy,prefer_static)
@@ -104,6 +80,11 @@
$(call add_soong_config_var_value,ANDROID,module_build_from_source,true)
endif
+# Messaging app vars
+ifeq (eng,$(TARGET_BUILD_VARIANT))
+$(call soong_config_set,messaging,build_variant_eng,true)
+endif
+
# TODO(b/203088572): Remove when Java optimizations enabled by default for
# SystemUI.
$(call add_soong_config_var,ANDROID,SYSTEMUI_OPTIMIZE_JAVA)
diff --git a/core/artifact_path_requirements.mk b/core/artifact_path_requirements.mk
index ceaefa2..566b9f7 100644
--- a/core/artifact_path_requirements.mk
+++ b/core/artifact_path_requirements.mk
@@ -22,6 +22,10 @@
$(TARGET_OUT_SYSTEM_OTHER)/%.art
endif
+ifneq (,$(filter-out true false relaxed strict,$(PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS))$(filter-out 1 0,$(words $(PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS))))
+ $(error PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS must be one of [true, false, relaxed, strict], found: $(PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS))
+endif
+
all_offending_files :=
$(foreach makefile,$(ARTIFACT_PATH_REQUIREMENT_PRODUCTS),\
$(eval requirements := $(PRODUCTS.$(makefile).ARTIFACT_PATH_REQUIREMENTS)) \
@@ -46,7 +50,7 @@
$(eval allowed_patterns := $(call resolve-product-relative-paths,$(allowed))) \
$(eval offending_files := $(filter-out $(allowed_patterns),$(files_in_requirement))) \
$(eval enforcement := $(PRODUCT_ENFORCE_ARTIFACT_PATH_REQUIREMENTS)) \
- $(if $(enforcement),\
+ $(if $(filter-out false,$(enforcement)),\
$(call maybe-print-list-and-error,$(offending_files),\
$(INTERNAL_PRODUCT) produces files inside $(makefile)s artifact path requirement. \
$(PRODUCT_ARTIFACT_PATH_REQUIREMENT_HINT)) \
diff --git a/core/base_rules.mk b/core/base_rules.mk
index e26f456..e6b8f20 100644
--- a/core/base_rules.mk
+++ b/core/base_rules.mk
@@ -33,6 +33,9 @@
endif
$(call verify-module-name)
+my_test_data :=
+my_test_config :=
+
LOCAL_IS_HOST_MODULE := $(strip $(LOCAL_IS_HOST_MODULE))
ifdef LOCAL_IS_HOST_MODULE
ifneq ($(LOCAL_IS_HOST_MODULE),true)
@@ -710,6 +713,10 @@
endif
ifdef LOCAL_MULTILIB
multi_arch := true
+else ifeq ($(LOCAL_MODULE_MAKEFILE),$(SOONG_ANDROID_MK))
+ ifeq ($(LOCAL_MODULE_CLASS),SHARED_LIBRARIES)
+ multi_arch := true
+ endif
endif
ifdef multi_arch
diff --git a/core/binary.mk b/core/binary.mk
index 94e3a0f..665270e 100644
--- a/core/binary.mk
+++ b/core/binary.mk
@@ -573,8 +573,6 @@
# the dependencies.
my_gen_src_files := $(filter %.c %$(LOCAL_CPP_EXTENSION) %.S %.s,$(my_generated_sources))
-ALL_GENERATED_SOURCES += $(my_generated_sources)
-
####################################################
## Compile RenderScript with reflected C++
####################################################
diff --git a/core/board_config.mk b/core/board_config.mk
index 97b258d..dc50a68 100644
--- a/core/board_config.mk
+++ b/core/board_config.mk
@@ -161,11 +161,15 @@
_board_strip_list += BOARD_AVB_VENDOR_BOOT_KEY_PATH
_board_strip_list += BOARD_AVB_VENDOR_BOOT_ALGORITHM
_board_strip_list += BOARD_AVB_VENDOR_BOOT_ROLLBACK_INDEX_LOCATION
+_board_strip_list += BOARD_AVB_VENDOR_KERNEL_BOOT_KEY_PATH
+_board_strip_list += BOARD_AVB_VENDOR_KERNEL_BOOT_ALGORITHM
+_board_strip_list += BOARD_AVB_VENDOR_KERNEL_BOOT_ROLLBACK_INDEX_LOCATION
_board_strip_list += BOARD_GKI_SIGNING_SIGNATURE_ARGS
_board_strip_list += BOARD_GKI_SIGNING_ALGORITHM
_board_strip_list += BOARD_GKI_SIGNING_KEY_PATH
_board_strip_list += BOARD_MKBOOTIMG_ARGS
_board_strip_list += BOARD_VENDOR_BOOTIMAGE_PARTITION_SIZE
+_board_strip_list += BOARD_VENDOR_KERNEL_BOOTIMAGE_PARTITION_SIZE
_board_strip_list += ODM_MANIFEST_SKUS
@@ -239,7 +243,7 @@
$(shell mkdir -p $(OUT_DIR)/rbc)
$(call dump-variables-rbc, $(OUT_DIR)/rbc/make_vars_pre_board_config.mk)
- $(shell $(OUT_DIR)/soong/mk2rbc \
+ $(shell $(OUT_DIR)/mk2rbc \
--mode=write -r --outdir $(OUT_DIR)/rbc \
--boardlauncher=$(OUT_DIR)/rbc/boardlauncher.rbc \
--input_variables=$(OUT_DIR)/rbc/make_vars_pre_board_config.mk \
@@ -250,7 +254,7 @@
endif
$(shell build/soong/scripts/update_out $(OUT_DIR)/rbc/rbc_board_config_results.mk \
- $(OUT_DIR)/soong/rbcrun RBC_OUT="make,global" $(OUT_DIR)/rbc/boardlauncher.rbc)
+ $(OUT_DIR)/rbcrun RBC_OUT="make" $(OUT_DIR)/rbc/boardlauncher.rbc)
ifneq ($(.SHELLSTATUS),0)
$(error board configuration runner failed: $(.SHELLSTATUS))
endif
@@ -520,6 +524,25 @@
endif
.KATI_READONLY := BUILDING_VENDOR_BOOT_IMAGE
+# Are we building a vendor kernel boot image
+BUILDING_VENDOR_KERNEL_BOOT_IMAGE :=
+ifeq ($(PRODUCT_BUILD_VENDOR_KERNEL_BOOT_IMAGE),true)
+ ifneq ($(BUILDING_VENDOR_BOOT_IMAGE),true)
+ $(error BUILDING_VENDOR_BOOT_IMAGE is required, but BUILDING_VENDOR_BOOT_IMAGE is not true)
+ endif
+ ifndef BOARD_VENDOR_KERNEL_BOOTIMAGE_PARTITION_SIZE
+ $(error BOARD_VENDOR_KERNEL_BOOTIMAGE_PARTITION_SIZE is required when PRODUCT_BUILD_VENDOR_KERNEL_BOOT_IMAGE is true)
+ endif
+ BUILDING_VENDOR_KERNEL_BOOT_IMAGE := true
+else ifeq ($(PRODUCT_BUILD_VENDOR_KERNEL),)
+ ifdef BOARD_VENDOR_KERNEL_BOOTIMAGE_PARTITION_SIZE
+ ifeq ($(BUILDING_VENDOR_BOOT_IMAGE),true)
+ BUILDING_VENDOR_KERNEL_BOOT_IMAGE := true
+ endif
+ endif
+endif # end of PRODUCT_BUILD_VENDOR_KERNEL_BOOT_IMAGE
+.KATI_READONLY := BUILDING_VENDOR_KERNEL_BOOT_IMAGE
+
# Are we building a ramdisk image
BUILDING_RAMDISK_IMAGE := true
ifeq ($(PRODUCT_BUILD_RAMDISK_IMAGE),)
diff --git a/core/build-system.html b/core/build-system.html
index b872909c..181e939 100644
--- a/core/build-system.html
+++ b/core/build-system.html
@@ -444,8 +444,12 @@
<p>Unbundled build has several meanings by the context.
Let me explain the meaning by the flags related to "unbundled build"</p>
<h4>TARGET_BUILD_UNBUNDLED</h4>
-<p>The source tree might not have the full platform sources. It is always set if
-<code>TARGET_BUILD_APPS</code> or <code>TARGET_BUILD_UNBUNDLED_IMAGE</code> is set.</p>
+<p>
+ The source tree might not have the full platform sources. It turns on
+ <code>TARGET_BUILD_USE_PREBUILT_SDKS</code>, unless
+ <code>UNBUNDLED_BUILD_SDKS_FROM_SOURCE</code> is set. It is always set if
+ <code>TARGET_BUILD_APPS</code> or <code>TARGET_BUILD_UNBUNDLED_IMAGE</code> is set.
+</p>
<h4>TARGET_BUILD_USE_PREBUILT_SDKS</h4>
<p>It is an internal flag. If it is set, prebuilt SDKs are used, even if a module's
<code>LOCAL_SDK_VERSION</code> is <code>current</code> (including <code>system_current</code>,
diff --git a/core/clear_vars.mk b/core/clear_vars.mk
index 57f9ef8..b5b371c 100644
--- a/core/clear_vars.mk
+++ b/core/clear_vars.mk
@@ -510,6 +510,8 @@
full_android_manifest :=
non_system_module :=
+module_license_metadata :=
+
# Trim MAKEFILE_LIST so that $(call my-dir) doesn't need to
# iterate over thousands of entries every time.
# Leave the current makefile to make sure we don't break anything
diff --git a/core/config.mk b/core/config.mk
index 935bdb8..7af600f 100644
--- a/core/config.mk
+++ b/core/config.mk
@@ -159,6 +159,8 @@
$(KATI_deprecated_var BOARD_PLAT_PRIVATE_SEPOLICY_DIR,Use SYSTEM_EXT_PRIVATE_SEPOLICY_DIRS instead)
$(KATI_obsolete_var TARGET_NO_VENDOR_BOOT,Use PRODUCT_BUILD_VENDOR_BOOT_IMAGE instead)
$(KATI_obsolete_var PRODUCT_CHECK_ELF_FILES,Use BUILD_BROKEN_PREBUILT_ELF_FILES instead)
+$(KATI_obsolete_var ALL_GENERATED_SOURCES,ALL_GENERATED_SOURCES is no longer used)
+$(KATI_obsolete_var ALL_ORIGINAL_DYNAMIC_BINARIES,ALL_ORIGINAL_DYNAMIC_BINARIES is no longer used)
# Used to force goals to build. Only use for conditionally defined goals.
.PHONY: FORCE
@@ -425,6 +427,21 @@
$(hide) $(HOST_NM) -gP $(1) | cut -f1-2 -d" " | (grep -v U$$ >> $(2) || true)
endef
+GOMA_POOL :=
+RBE_POOL :=
+GOMA_OR_RBE_POOL :=
+# When goma or RBE are enabled, kati will be passed --default_pool=local_pool to put
+# most rules into the local pool. Explicitly set the pool to "none" for rules that
+# should be run outside the local pool, i.e. with -j500.
+ifneq (,$(filter-out false,$(USE_GOMA)))
+ GOMA_POOL := none
+ GOMA_OR_RBE_POOL := none
+else ifneq (,$(filter-out false,$(USE_RBE)))
+ RBE_POOL := none
+ GOMA_OR_RBE_POOL := none
+endif
+.KATI_READONLY := GOMA_POOL RBE_POOL GOMA_OR_RBE_POOL
+
ifeq ($(CALLED_FROM_SETUP),true)
include $(BUILD_SYSTEM)/ccache.mk
include $(BUILD_SYSTEM)/goma.mk
@@ -494,7 +511,9 @@
DISABLE_PREOPT :=
ifneq (,$(TARGET_BUILD_APPS)$(TARGET_BUILD_UNBUNDLED_IMAGE))
DISABLE_PREOPT := true
- ifndef UNBUNDLED_BUILD_SDKS_FROM_SOURCE
+endif
+ifeq (true,$(TARGET_BUILD_UNBUNDLED))
+ ifneq (true,$(UNBUNDLED_BUILD_SDKS_FROM_SOURCE))
TARGET_BUILD_USE_PREBUILT_SDKS := true
endif
endif
@@ -616,6 +635,7 @@
OTA_FROM_TARGET_FILES := $(HOST_OUT_EXECUTABLES)/ota_from_target_files$(HOST_EXECUTABLE_SUFFIX)
SPARSE_IMG := $(HOST_OUT_EXECUTABLES)/sparse_img$(HOST_EXECUTABLE_SUFFIX)
CHECK_PARTITION_SIZES := $(HOST_OUT_EXECUTABLES)/check_partition_sizes$(HOST_EXECUTABLE_SUFFIX)
+SYMBOLS_MAP := $(HOST_OUT_EXECUTABLES)/symbols_map
PROGUARD_HOME := external/proguard
PROGUARD := $(PROGUARD_HOME)/bin/proguard.sh
@@ -816,7 +836,7 @@
# is made which breaks compatibility with the previous platform sepolicy version,
# not just on every increase in PLATFORM_SDK_VERSION. The minor version should
# be reset to 0 on every bump of the PLATFORM_SDK_VERSION.
-sepolicy_major_vers := 31
+sepolicy_major_vers := 32
sepolicy_minor_vers := 0
ifneq ($(sepolicy_major_vers), $(PLATFORM_SDK_VERSION))
@@ -1213,25 +1233,9 @@
$(filter $(ANDROID_WARNING_ALLOWED_PROJECTS),$(1)/)
endef
-GOMA_POOL :=
-RBE_POOL :=
-GOMA_OR_RBE_POOL :=
-# When goma or RBE are enabled, kati will be passed --default_pool=local_pool to put
-# most rules into the local pool. Explicitly set the pool to "none" for rules that
-# should be run outside the local pool, i.e. with -j500.
-ifneq (,$(filter-out false,$(USE_GOMA)))
- GOMA_POOL := none
- GOMA_OR_RBE_POOL := none
-else ifneq (,$(filter-out false,$(USE_RBE)))
- RBE_POOL := none
- GOMA_OR_RBE_POOL := none
-endif
-.KATI_READONLY := GOMA_POOL RBE_POOL GOMA_OR_RBE_POOL
-
# These goals don't need to collect and include Android.mks/CleanSpec.mks
# in the source tree.
-dont_bother_goals := out \
- product-graph dump-products
+dont_bother_goals := out product-graph
# Make ANDROID Soong config variables visible to Android.mk files, for
# consistency with those defined in BoardConfig.mk files.
diff --git a/core/definitions.mk b/core/definitions.mk
index 314ba0a..0d72473 100644
--- a/core/definitions.mk
+++ b/core/definitions.mk
@@ -59,16 +59,10 @@
# its sub-variables.)
ALL_MODULE_NAME_TAGS:=
-# Full path to all files that are made by some tool
-ALL_GENERATED_SOURCES:=
-
# Full path to all asm, C, C++, lex and yacc generated C files.
# These all have an order-only dependency on the copied headers
ALL_C_CPP_ETC_OBJECTS:=
-# The list of dynamic binaries that haven't been stripped/compressed/etc.
-ALL_ORIGINAL_DYNAMIC_BINARIES:=
-
# These files go into the SDK
ALL_SDK_FILES:=
@@ -580,9 +574,12 @@
# License metadata targets corresponding to targets in $(1)
###########################################################
define corresponding-license-metadata
-$(strip $(eval _dir := $(call license-metadata-dir)) \
-$(foreach target, $(sort $(1)), $(_dir)/$(target).meta_lic) \
-)
+$(strip $(foreach target, $(sort $(1)), \
+ $(if $(strip $(ALL_MODULES.$(target).META_LIC)), \
+ $(ALL_MODULES.$(target).META_LIC), \
+ $(if $(strip $(ALL_TARGETS.$(target).META_LIC)), \
+ $(ALL_TARGETS.$(target).META_LIC), \
+ $(call append-path,$(call license-metadata-dir),$(patsubst $(OUT_DIR)%,out%,$(target).meta_lic))))))
endef
###########################################################
@@ -590,9 +587,10 @@
###########################################################
define license-metadata-rule
$(foreach meta_lic, $(ALL_MODULES.$(1).DELAYED_META_LIC),$(call _license-metadata-rule,$(1),$(meta_lic)))
-$(call notice-rule,$(1))
endef
+$(KATI_obsolete_var notice-rule, This function has been removed)
+
define _license-metadata-rule
$(strip $(eval _srcs := $(strip $(foreach d,$(ALL_MODULES.$(1).NOTICE_DEPS),$(if $(strip $(ALL_MODULES.$(call word-colon,1,$(d)).INSTALLED)), $(ALL_MODULES.$(call word-colon,1,$(d)).INSTALLED),$(if $(strip $(ALL_MODULES.$(call word-colon,1,$(d)).BUILT)), $(ALL_MODULES.$(call word-colon,1,$(d)).BUILT), $(call word-colon,1,$d)))))))
$(strip $(eval _deps := $(sort $(filter-out $(2)%,\
@@ -625,47 +623,32 @@
$(2): PRIVATE_MODULE_TYPE := $(ALL_MODULES.$(1).MODULE_TYPE)
$(2): PRIVATE_MODULE_CLASS := $(ALL_MODULES.$(1).MODULE_CLASS)
$(2): PRIVATE_INSTALL_MAP := $(_map)
+$(2): PRIVATE_ARGUMENT_FILE := $(call intermediates-dir-for,PACKAGING,notice)/$(2)/arguments
$(2): $(BUILD_LICENSE_METADATA)
$(2) : $(foreach d,$(_deps),$(call word-colon,1,$(d))) $(foreach n,$(_notices),$(call word-colon,1,$(n)) )
rm -f $$@
mkdir -p $$(dir $$@)
- $(BUILD_LICENSE_METADATA) \
- $$(addprefix -mt ,$$(PRIVATE_MODULE_TYPE)) \
- $$(addprefix -mc ,$$(PRIVATE_MODULE_CLASS)) \
- $$(addprefix -k ,$$(PRIVATE_KINDS)) \
- $$(addprefix -c ,$$(PRIVATE_CONDITIONS)) \
- $$(addprefix -n ,$$(PRIVATE_NOTICES)) \
- $$(addprefix -d ,$$(PRIVATE_NOTICE_DEPS)) \
- $$(addprefix -s ,$$(PRIVATE_SOURCES)) \
- $$(addprefix -m ,$$(PRIVATE_INSTALL_MAP)) \
- $$(addprefix -t ,$$(PRIVATE_TARGETS)) \
- $$(addprefix -i ,$$(PRIVATE_INSTALLED)) \
+ mkdir -p $$(dir $$(PRIVATE_ARGUMENT_FILE))
+ $$(call dump-words-to-file,\
+ $$(addprefix -mt ,$$(PRIVATE_MODULE_TYPE))\
+ $$(addprefix -mc ,$$(PRIVATE_MODULE_CLASS))\
+ $$(addprefix -k ,$$(PRIVATE_KINDS))\
+ $$(addprefix -c ,$$(PRIVATE_CONDITIONS))\
+ $$(addprefix -n ,$$(PRIVATE_NOTICES))\
+ $$(addprefix -d ,$$(PRIVATE_NOTICE_DEPS))\
+ $$(addprefix -s ,$$(PRIVATE_SOURCES))\
+ $$(addprefix -m ,$$(PRIVATE_INSTALL_MAP))\
+ $$(addprefix -t ,$$(PRIVATE_TARGETS))\
+ $$(addprefix -i ,$$(PRIVATE_INSTALLED))\
+ $$(addprefix -r ,$$(PRIVATE_PATH)),\
+ $$(PRIVATE_ARGUMENT_FILE))
+ OUT_DIR=$(OUT_DIR) $(BUILD_LICENSE_METADATA) \
$$(if $$(PRIVATE_IS_CONTAINER),-is_container) \
-p '$$(PRIVATE_PACKAGE_NAME)' \
- $$(addprefix -r ,$$(PRIVATE_PATH)) \
+ @$$(PRIVATE_ARGUMENT_FILE) \
-o $$@
endef
-define notice-rule
-$(strip $(eval _mifs := $(sort $(ALL_MODULES.$(1).MODULE_INSTALLED_FILENAMES))))
-$(strip $(eval _infs := $(sort $(ALL_MODULES.$(1).INSTALLED_NOTICE_FILE))))
-
-# Emit each installed notice file rule if it references the current module
-$(if $(_infs),$(foreach inf,$(_infs),
-$(if $(strip $(filter $(1),$(INSTALLED_NOTICE_FILES.$(inf).MODULE))),
-$(strip $(eval _mif := $(firstword $(foreach m,$(_mifs),$(if $(filter %/src/$(m).txt,$(inf)),$(m))))))
-
-$(inf): PRIVATE_INSTALLED_MODULE := $(_mif)
-$(inf) : PRIVATE_NOTICES := $(sort $(foreach n,$(_notices),$(call word-colon,1,$(n) )))
-
-$(inf): $(foreach n,$(_notices),$(call word-colon,1,$(n)) )
- @echo Notice file: $$< -- $$@
- mkdir -p $$(dir $$@)
- awk 'FNR==1 && NR > 1 {print "\n"} {print}' $$(PRIVATE_NOTICES) > $$@
-
-)))
-
-endef
###########################################################
## License metadata build rule for non-module target $(1)
@@ -673,44 +656,50 @@
define non-module-license-metadata-rule
$(strip $(eval _dir := $(call license-metadata-dir)))
$(strip $(eval _tgt := $(strip $(1))))
+$(strip $(eval _meta := $(call append-path,$(_dir),$(patsubst $(OUT_DIR)%,out%,$(_tgt).meta_lic))))
$(strip $(eval _deps := $(sort $(filter-out 0p: :,$(foreach d,$(strip $(ALL_NON_MODULES.$(_tgt).DEPENDENCIES)),$(ALL_TARGETS.$(call word-colon,1,$(d)).META_LIC):$(call wordlist-colon,2,9999,$(d)))))))
$(strip $(eval _notices := $(sort $(ALL_NON_MODULES.$(_tgt).NOTICES))))
$(strip $(eval _path := $(sort $(ALL_NON_MODULES.$(_tgt).PATH))))
$(strip $(eval _install_map := $(ALL_NON_MODULES.$(_tgt).ROOT_MAPPINGS)))
-$(strip \
- $(foreach d,$(strip $(ALL_NON_MODULES.$(_tgt).DEPENDENCIES)), \
- $(if $(strip $(ALL_TARGETS.$(d).META_LIC)), \
+$(strip $(eval \
+ $$(foreach d,$(strip $(ALL_NON_MODULES.$(_tgt).DEPENDENCIES)), \
+ $$(if $$(strip $$(ALL_TARGETS.$$(d).META_LIC)), \
, \
- $(eval NON_MODULES_WITHOUT_LICENSE_METADATA += $(d))) \
- ) \
+ $$(eval NON_MODULES_WITHOUT_LICENSE_METADATA += $$(d))) \
+ )) \
)
-$(_dir)/$(_tgt).meta_lic: PRIVATE_KINDS := $(sort $(ALL_NON_MODULES.$(_tgt).LICENSE_KINDS))
-$(_dir)/$(_tgt).meta_lic: PRIVATE_CONDITIONS := $(sort $(ALL_NON_MODULES.$(_tgt).LICENSE_CONDITIONS))
-$(_dir)/$(_tgt).meta_lic: PRIVATE_NOTICES := $(_notices)
-$(_dir)/$(_tgt).meta_lic: PRIVATE_NOTICE_DEPS := $(_deps)
-$(_dir)/$(_tgt).meta_lic: PRIVATE_SOURCES := $(ALL_NON_MODULES.$(_tgt).DEPENDENCIES)
-$(_dir)/$(_tgt).meta_lic: PRIVATE_TARGETS := $(_tgt)
-$(_dir)/$(_tgt).meta_lic: PRIVATE_PATH := $(_path)
-$(_dir)/$(_tgt).meta_lic: PRIVATE_IS_CONTAINER := $(ALL_NON_MODULES.$(_tgt).IS_CONTAINER)
-$(_dir)/$(_tgt).meta_lic: PRIVATE_PACKAGE_NAME := $(strip $(ALL_NON_MODULES.$(_tgt).LICENSE_PACKAGE_NAME))
-$(_dir)/$(_tgt).meta_lic: PRIVATE_INSTALL_MAP := $(strip $(_install_map))
-$(_dir)/$(_tgt).meta_lic: $(BUILD_LICENSE_METADATA)
-$(_dir)/$(_tgt).meta_lic : $(foreach d,$(_deps),$(call word-colon,1,$(d))) $(foreach n,$(_notices),$(call word-colon,1,$(n)) )
+$(_meta): PRIVATE_KINDS := $(sort $(ALL_NON_MODULES.$(_tgt).LICENSE_KINDS))
+$(_meta): PRIVATE_CONDITIONS := $(sort $(ALL_NON_MODULES.$(_tgt).LICENSE_CONDITIONS))
+$(_meta): PRIVATE_NOTICES := $(_notices)
+$(_meta): PRIVATE_NOTICE_DEPS := $(_deps)
+$(_meta): PRIVATE_SOURCES := $(ALL_NON_MODULES.$(_tgt).DEPENDENCIES)
+$(_meta): PRIVATE_TARGETS := $(_tgt)
+$(_meta): PRIVATE_PATH := $(_path)
+$(_meta): PRIVATE_IS_CONTAINER := $(ALL_NON_MODULES.$(_tgt).IS_CONTAINER)
+$(_meta): PRIVATE_PACKAGE_NAME := $(strip $(ALL_NON_MODULES.$(_tgt).LICENSE_PACKAGE_NAME))
+$(_meta): PRIVATE_INSTALL_MAP := $(strip $(_install_map))
+$(_meta): PRIVATE_ARGUMENT_FILE := $(call intermediates-dir-for,PACKAGING,notice)/$(_meta)/arguments
+$(_meta): $(BUILD_LICENSE_METADATA)
+$(_meta) : $(foreach d,$(_deps),$(call word-colon,1,$(d))) $(foreach n,$(_notices),$(call word-colon,1,$(n)) )
rm -f $$@
mkdir -p $$(dir $$@)
- $(BUILD_LICENSE_METADATA) \
+ mkdir -p $$(dir $$(PRIVATE_ARGUMENT_FILE))
+ $$(call dump-words-to-file,\
+ $$(addprefix -k ,$$(PRIVATE_KINDS))\
+ $$(addprefix -c ,$$(PRIVATE_CONDITIONS))\
+ $$(addprefix -n ,$$(PRIVATE_NOTICES))\
+ $$(addprefix -d ,$$(PRIVATE_NOTICE_DEPS))\
+ $$(addprefix -s ,$$(PRIVATE_SOURCES))\
+ $$(addprefix -m ,$$(PRIVATE_INSTALL_MAP))\
+ $$(addprefix -t ,$$(PRIVATE_TARGETS))\
+ $$(addprefix -r ,$$(PRIVATE_PATH)),\
+ $$(PRIVATE_ARGUMENT_FILE))
+ OUT_DIR=$(OUT_DIR) $(BUILD_LICENSE_METADATA) \
-mt raw -mc unknown \
- $$(addprefix -k ,$$(PRIVATE_KINDS)) \
- $$(addprefix -c ,$$(PRIVATE_CONDITIONS)) \
- $$(addprefix -n ,$$(PRIVATE_NOTICES)) \
- $$(addprefix -d ,$$(PRIVATE_NOTICE_DEPS)) \
- $$(addprefix -s ,$$(PRIVATE_SOURCES)) \
- $$(addprefix -m ,$$(PRIVATE_INSTALL_MAP)) \
- $$(addprefix -t ,$$(PRIVATE_TARGETS)) \
$$(if $$(PRIVATE_IS_CONTAINER),-is_container) \
- -p '$$(PRIVATE_PACKAGE_NAME)' \
$$(addprefix -r ,$$(PRIVATE_PATH)) \
+ @$$(PRIVATE_ARGUMENT_FILE) \
-o $$@
endef
@@ -726,7 +715,7 @@
###########################################################
define declare-license-metadata
$(strip \
- $(eval _tgt := $(strip $(1))) \
+ $(eval _tgt := $(subst //,/,$(strip $(1)))) \
$(eval ALL_NON_MODULES += $(_tgt)) \
$(eval ALL_NON_MODULES.$(_tgt).LICENSE_KINDS := $(strip $(2))) \
$(eval ALL_NON_MODULES.$(_tgt).LICENSE_CONDITIONS := $(strip $(3))) \
@@ -766,7 +755,7 @@
###########################################################
define declare-container-license-metadata
$(strip \
- $(eval _tgt := $(strip $(1))) \
+ $(eval _tgt := $(subst //,/,$(strip $(1)))) \
$(eval ALL_NON_MODULES += $(_tgt)) \
$(eval ALL_NON_MODULES.$(_tgt).LICENSE_KINDS := $(strip $(2))) \
$(eval ALL_NON_MODULES.$(_tgt).LICENSE_CONDITIONS := $(strip $(3))) \
@@ -784,7 +773,7 @@
###########################################################
define declare-0p-target
$(strip \
- $(eval _tgt := $(strip $(1))) \
+ $(eval _tgt := $(subst //,/,$(strip $(1)))) \
$(eval ALL_0P_TARGETS += $(_tgt)) \
)
endef
@@ -868,9 +857,11 @@
define report-missing-licenses-rule
.PHONY: reportmissinglicenses
reportmissinglicenses: PRIVATE_NON_MODULES:=$(sort $(NON_MODULES_WITHOUT_LICENSE_METADATA))
+reportmissinglicenses: PRIVATE_COPIED_FILES:=$(sort $(filter $(NON_MODULES_WITHOUT_LICENSE_METADATA),$(foreach _pair,$(PRODUCT_COPY_FILES), $(PRODUCT_OUT)/$(call word-colon,2,$(_pair)))))
reportmissinglicenses:
@echo Reporting $$(words $$(PRIVATE_NON_MODULES)) targets without license metadata
$$(foreach t,$$(PRIVATE_NON_MODULES),if ! [ -h $$(t) ]; then echo No license metadata for $$(t) >&2; fi;)
+ $$(foreach t,$$(PRIVATE_COPIED_FILES),if ! [ -h $$(t) ]; then echo No license metadata for copied file $$(t) >&2; fi;)
endef
@@ -899,10 +890,22 @@
$(hide) rm -f $$(PRIVATE_LIST_FILE)
$(hide) mkdir -p $$(dir $$(PRIVATE_LIST_FILE))
$(hide) find out -name '*meta_lic' -type f -printf '"%p"\n' >$$(PRIVATE_LIST_FILE)
- $(COMPLIANCENOTICE_SHIPPEDLIBS) @$$(PRIVATE_LIST_FILE)
+ OUT_DIR=$(OUT_DIR) $(COMPLIANCENOTICE_SHIPPEDLIBS) @$$(PRIVATE_LIST_FILE)
endef
###########################################################
+# Declares the rule to build all license metadata.
+###########################################################
+define build-all-license-metadata-rule
+$(strip $(eval _all := $(call all-license-metadata)))
+
+.PHONY: alllicensemetadata
+alllicensemetadata: $(_all)
+ @echo Building all $(words $(_all)) license metadata files
+endef
+
+
+###########################################################
## Declares a license metadata build rule for ALL_MODULES
###########################################################
define build-license-metadata
@@ -912,12 +915,13 @@
$(eval ALL_TARGETS.$(t).META_LIC := 0p) \
) \
$(foreach t,$(sort $(ALL_NON_MODULES)), \
- $(eval ALL_TARGETS.$(t).META_LIC := $(_dir)/$(t).meta_lic) \
+ $(eval ALL_TARGETS.$(t).META_LIC := $(call append-path,$(_dir),$(patsubst $(OUT_DIR)%,out%,$(t).meta_lic))) \
) \
$(foreach t,$(sort $(ALL_NON_MODULES)),$(eval $(call non-module-license-metadata-rule,$(t)))) \
$(foreach m,$(sort $(ALL_MODULES)),$(eval $(call license-metadata-rule,$(m)))) \
$(eval $(call report-missing-licenses-rule)) \
- $(eval $(call report-all-notice-library-names-rule)))
+ $(eval $(call report-all-notice-library-names-rule)) \
+ $(eval $(call build-all-license-metadata-rule)))
endef
###########################################################
@@ -2355,7 +2359,59 @@
@$(call emit-line,$(wordlist 12001,12500,$(1)),$(2))
@$(call emit-line,$(wordlist 12501,13000,$(1)),$(2))
@$(call emit-line,$(wordlist 13001,13500,$(1)),$(2))
- @$(if $(wordlist 13501,13502,$(1)),$(error Too many words ($(words $(1)))))
+ @$(call emit-line,$(wordlist 13501,14000,$(1)),$(2))
+ @$(call emit-line,$(wordlist 14001,14500,$(1)),$(2))
+ @$(call emit-line,$(wordlist 14501,15000,$(1)),$(2))
+ @$(call emit-line,$(wordlist 15001,15500,$(1)),$(2))
+ @$(call emit-line,$(wordlist 15501,16000,$(1)),$(2))
+ @$(call emit-line,$(wordlist 16001,16500,$(1)),$(2))
+ @$(call emit-line,$(wordlist 16501,17000,$(1)),$(2))
+ @$(call emit-line,$(wordlist 17001,17500,$(1)),$(2))
+ @$(call emit-line,$(wordlist 17501,18000,$(1)),$(2))
+ @$(call emit-line,$(wordlist 18001,18500,$(1)),$(2))
+ @$(call emit-line,$(wordlist 18501,19000,$(1)),$(2))
+ @$(call emit-line,$(wordlist 19001,19500,$(1)),$(2))
+ @$(call emit-line,$(wordlist 19501,20000,$(1)),$(2))
+ @$(call emit-line,$(wordlist 20001,20500,$(1)),$(2))
+ @$(call emit-line,$(wordlist 20501,21000,$(1)),$(2))
+ @$(call emit-line,$(wordlist 21001,21500,$(1)),$(2))
+ @$(call emit-line,$(wordlist 21501,22000,$(1)),$(2))
+ @$(call emit-line,$(wordlist 22001,22500,$(1)),$(2))
+ @$(call emit-line,$(wordlist 22501,23000,$(1)),$(2))
+ @$(call emit-line,$(wordlist 23001,23500,$(1)),$(2))
+ @$(call emit-line,$(wordlist 23501,24000,$(1)),$(2))
+ @$(call emit-line,$(wordlist 24001,24500,$(1)),$(2))
+ @$(call emit-line,$(wordlist 24501,25000,$(1)),$(2))
+ @$(call emit-line,$(wordlist 25001,25500,$(1)),$(2))
+ @$(call emit-line,$(wordlist 25501,26000,$(1)),$(2))
+ @$(call emit-line,$(wordlist 26001,26500,$(1)),$(2))
+ @$(call emit-line,$(wordlist 26501,27000,$(1)),$(2))
+ @$(call emit-line,$(wordlist 27001,27500,$(1)),$(2))
+ @$(call emit-line,$(wordlist 27501,28000,$(1)),$(2))
+ @$(call emit-line,$(wordlist 28001,28500,$(1)),$(2))
+ @$(call emit-line,$(wordlist 28501,29000,$(1)),$(2))
+ @$(call emit-line,$(wordlist 29001,29500,$(1)),$(2))
+ @$(call emit-line,$(wordlist 29501,30000,$(1)),$(2))
+ @$(call emit-line,$(wordlist 30001,30500,$(1)),$(2))
+ @$(call emit-line,$(wordlist 30501,31000,$(1)),$(2))
+ @$(call emit-line,$(wordlist 31001,31500,$(1)),$(2))
+ @$(call emit-line,$(wordlist 31501,32000,$(1)),$(2))
+ @$(call emit-line,$(wordlist 32001,32500,$(1)),$(2))
+ @$(call emit-line,$(wordlist 32501,33000,$(1)),$(2))
+ @$(call emit-line,$(wordlist 33001,33500,$(1)),$(2))
+ @$(call emit-line,$(wordlist 33501,34000,$(1)),$(2))
+ @$(call emit-line,$(wordlist 34001,34500,$(1)),$(2))
+ @$(call emit-line,$(wordlist 34501,35000,$(1)),$(2))
+ @$(call emit-line,$(wordlist 35001,35500,$(1)),$(2))
+ @$(call emit-line,$(wordlist 35501,36000,$(1)),$(2))
+ @$(call emit-line,$(wordlist 36001,36500,$(1)),$(2))
+ @$(call emit-line,$(wordlist 36501,37000,$(1)),$(2))
+ @$(call emit-line,$(wordlist 37001,37500,$(1)),$(2))
+ @$(call emit-line,$(wordlist 37501,38000,$(1)),$(2))
+ @$(call emit-line,$(wordlist 38001,38500,$(1)),$(2))
+ @$(call emit-line,$(wordlist 38501,39000,$(1)),$(2))
+ @$(call emit-line,$(wordlist 39001,39500,$(1)),$(2))
+ @$(if $(wordlist 39501,39502,$(1)),$(error Too many words ($(words $(1)))))
endef
# Return jar arguments to compress files in a given directory
# $(1): directory
@@ -3061,6 +3117,8 @@
# $(3): full path to destination
define symlink-file
$(eval $(_symlink-file))
+$(eval $(call declare-license-metadata,$(3),,,,,,))
+$(eval $(call declare-license-deps,$(3),$(1)))
endef
define _symlink-file
@@ -3096,6 +3154,50 @@
fi
endef
+# Copy an unstripped binary to the symbols directory while also extracting
+# a hash mapping to the mapping directory.
+# $(1): unstripped intermediates file
+# $(2): path in symbols directory
+define copy-unstripped-elf-file-with-mapping
+$(call _copy-symbols-file-with-mapping,$(1),$(2),\
+ elf,$(patsubst $(TARGET_OUT_UNSTRIPPED)/%,$(call intermediates-dir-for,PACKAGING,elf_symbol_mapping)/%,$(2).textproto))
+endef
+
+# Copy an R8 dictionary to the packaging directory while also extracting
+# a hash mapping to the mapping directory.
+# $(1): unstripped intermediates file
+# $(2): path in packaging directory
+# $(3): path in mappings packaging directory
+define copy-r8-dictionary-file-with-mapping
+$(call _copy-symbols-file-with-mapping,$(1),$(2),r8,$(3))
+endef
+
+# Copy an unstripped binary or R8 dictionary to the symbols directory
+# while also extracting a hash mapping to the mapping directory.
+# $(1): unstripped intermediates file
+# $(2): path in symbols directory
+# $(3): file type (elf or r8)
+# $(4): path in the mappings directory
+define _copy-symbols-file-with-mapping
+$(2): .KATI_IMPLICIT_OUTPUTS := $(4)
+$(2): $(SYMBOLS_MAP)
+$(2): $(1)
+ @echo "Copy symbols with mapping: $$@"
+ $$(copy-file-to-target)
+ $(SYMBOLS_MAP) -$(strip $(3)) $(2) -write_if_changed $(4)
+.KATI_RESTAT: $(2)
+endef
+
+# Returns the directory to copy proguard dictionaries into
+define local-proguard-dictionary-directory
+$(call intermediates-dir-for,PACKAGING,proguard_dictionary)/out/target/common/obj/$(LOCAL_MODULE_CLASS)/$(LOCAL_MODULE)_intermediates
+endef
+
+# Returns the directory to copy proguard dictionary mappings into
+define local-proguard-dictionary-mapping-directory
+$(call intermediates-dir-for,PACKAGING,proguard_dictionary_mapping)/out/target/common/obj/$(LOCAL_MODULE_CLASS)/$(LOCAL_MODULE)_intermediates
+endef
+
###########################################################
## Commands to call R8
@@ -3301,6 +3403,14 @@
# and use my_compat_dist_$(suite) to define the others.
define create-suite-dependencies
$(foreach suite, $(LOCAL_COMPATIBILITY_SUITE), \
+ $(eval $(if $(strip $(module_license_metadata)),\
+ $$(foreach f,$$(my_compat_dist_$(suite)),$$(eval ALL_TARGETS.$$(call word-colon,2,$$(f)).META_LIC := $(module_license_metadata))),\
+ $$(eval my_test_data += $$(foreach f,$$(my_compat_dist_$(suite)), $$(call word-colon,2,$$(f)))) \
+ )) \
+ $(eval $(if $(strip $(module_license_metadata)),\
+ $$(foreach f,$$(my_compat_dist_config_$(suite)),$$(eval ALL_TARGETS.$$(call word-colon,2,$$(f)).META_LIC := $(module_license_metadata))),\
+ $$(eval my_test_config += $$(foreach f,$$(my_compat_dist_config_$(suite)), $$(call word-colon,2,$$(f)))) \
+ )) \
$(if $(filter $(suite),$(ALL_COMPATIBILITY_SUITES)),,\
$(eval ALL_COMPATIBILITY_SUITES += $(suite)) \
$(eval COMPATIBILITY.$(suite).FILES :=) \
diff --git a/core/dex_preopt_libart.mk b/core/dex_preopt_libart.mk
index 393053d..a2c9942 100644
--- a/core/dex_preopt_libart.mk
+++ b/core/dex_preopt_libart.mk
@@ -17,52 +17,83 @@
#
####################################
-# Install $(1) to $(2) so that it is shared between architectures.
-# Returns the target path of the shared vdex file and installed symlink.
-define copy-vdex-file
-$(strip \
- $(eval # Remove the arch dir) \
- $(eval my_vdex_shared := $(dir $(patsubst %/,%,$(dir $(2))))$(notdir $(2))) \
- $(if $(filter-out %_2ND_ARCH,$(my_boot_image_arch)), \
- $(eval # Copy $(1) to directory one level up (i.e. with the arch dir removed).) \
- $(eval $(call copy-one-file,$(1),$(my_vdex_shared))) \
- ) \
- $(eval # Create symlink at $(2) which points to the actual physical copy.) \
- $(call symlink-file,$(my_vdex_shared),../$(notdir $(2)),$(2)) \
- $(my_vdex_shared) $(2) \
-)
+# Takes a list of src:dest install pairs and returns a new list with a path
+# prefixed to each dest value.
+# $(1): list of src:dest install pairs
+# $(2): path to prefix to each dest value
+define prefix-copy-many-files-dest
+$(foreach v,$(1),$(call word-colon,1,$(v)):$(2)$(call word-colon,2,$(v)))
endef
-# Same as 'copy-many-files' but it uses the vdex-specific helper above.
-define copy-vdex-files
-$(foreach v,$(1),$(call copy-vdex-file,$(call word-colon,1,$(v)),$(2)$(call word-colon,2,$(v))))
+# Converts an architecture-specific vdex path into a location that can be shared
+# between architectures.
+define vdex-shared-install-path
+$(dir $(patsubst %/,%,$(dir $(1))))$(notdir $(1))
+endef
+
+# Takes a list of src:dest install pairs of vdex files and returns a new list
+# where each dest has been rewritten to the shared location for vdex files.
+define vdex-copy-many-files-shared-dest
+$(foreach v,$(1),$(call word-colon,1,$(v)):$(call vdex-shared-install-path,$(call word-colon,2,$(v))))
+endef
+
+# Creates a rule to symlink an architecture specific vdex file to the shared
+# location for that vdex file.
+define symlink-vdex-file
+$(strip \
+ $(call symlink-file,\
+ $(call vdex-shared-install-path,$(1)),\
+ ../$(notdir $(1)),\
+ $(1))\
+ $(1))
+endef
+
+# Takes a list of src:dest install pairs of vdex files and creates rules to
+# symlink each dest to the shared location for that vdex file.
+define symlink-vdex-files
+$(foreach v,$(1),$(call symlink-vdex-file,$(call word-colon,2,$(v))))
endef
my_boot_image_module :=
my_suffix := $(my_boot_image_name)_$($(my_boot_image_arch))
-my_copy_pairs := $(strip $(DEXPREOPT_IMAGE_BUILT_INSTALLED_$(my_suffix)))
+my_copy_pairs := $(call prefix-copy-many-files-dest,$(DEXPREOPT_IMAGE_BUILT_INSTALLED_$(my_suffix)),$(my_boot_image_out))
+my_vdex_copy_pairs := $(call prefix-copy-many-files-dest,$(DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_$(my_suffix)),$(my_boot_image_out))
+my_vdex_copy_shared_pairs := $(call vdex-copy-many-files-shared-dest,$(my_vdex_copy_pairs))
+ifeq (,$(filter %_2ND_ARCH,$(my_boot_image_arch)))
+ # Only install the vdex to the shared location for the primary architecture.
+ my_copy_pairs += $(my_vdex_copy_shared_pairs)
+endif
+
+my_unstripped_copy_pairs := $(call prefix-copy-many-files-dest,$(DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_$(my_suffix)),$(my_boot_image_syms))
# Generate the boot image module only if there is any file to install.
-ifneq (,$(my_copy_pairs))
+ifneq (,$(strip $(my_copy_pairs)))
my_first_pair := $(firstword $(my_copy_pairs))
my_rest_pairs := $(wordlist 2,$(words $(my_copy_pairs)),$(my_copy_pairs))
my_first_src := $(call word-colon,1,$(my_first_pair))
- my_first_dest := $(my_boot_image_out)$(call word-colon,2,$(my_first_pair))
+ my_first_dest := $(call word-colon,2,$(my_first_pair))
- my_installed := $(call copy-many-files,$(my_rest_pairs),$(my_boot_image_out))
- my_installed += $(call copy-vdex-files,$(DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_$(my_suffix)),$(my_boot_image_out))
- my_unstripped_installed := $(call copy-many-files,$(DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_$(my_suffix)),$(my_boot_image_syms))
+ my_installed := $(call copy-many-files,$(my_copy_pairs))
+ my_unstripped_installed := $(call copy-many-files,$(my_unstripped_copy_pairs))
+
+ my_symlinks := $(call symlink-vdex-files,$(my_vdex_copy_pairs))
# We don't have a LOCAL_PATH for the auto-generated modules, so let it be the $(BUILD_SYSTEM).
LOCAL_PATH := $(BUILD_SYSTEM)
+ # Hack to let these pseudo-modules wrapped around Soong modules use LOCAL_SOONG_INSTALLED_MODULE.
+ LOCAL_MODULE_MAKEFILE := $(SOONG_ANDROID_MK)
include $(CLEAR_VARS)
LOCAL_MODULE := dexpreopt_bootjar.$(my_suffix)
LOCAL_PREBUILT_MODULE_FILE := $(my_first_src)
LOCAL_MODULE_PATH := $(dir $(my_first_dest))
LOCAL_MODULE_STEM := $(notdir $(my_first_dest))
+ LOCAL_SOONG_INSTALL_PAIRS := $(my_copy_pairs)
+ LOCAL_SOONG_INSTALL_SYMLINKS := $(my_symlinks)
+ LOCAL_SOONG_INSTALLED_MODULE := $(my_first_dest)
+ LOCAL_SOONG_LICENSE_METADATA := $(DEXPREOPT_IMAGE_LICENSE_METADATA_$(my_suffix))
ifneq (,$(strip $(filter HOST_%,$(my_boot_image_arch))))
LOCAL_IS_HOST_MODULE := true
endif
@@ -71,9 +102,8 @@
$(LOCAL_BUILT_MODULE): | $(my_unstripped_installed)
# Installing boot.art causes all boot image bits to be installed.
# Keep this old behavior in case anyone still needs it.
- $(LOCAL_INSTALLED_MODULE): $(my_installed)
- ALL_MODULES.$(my_register_name).INSTALLED += $(my_installed)
- $(my_all_targets): $(my_installed)
+ $(LOCAL_INSTALLED_MODULE): $(wordlist 2,$(words $(my_installed)),$(my_installed)) $(my_symlinks)
+ $(my_all_targets): $(my_installed) $(my_symlinks)
my_boot_image_module := $(LOCAL_MODULE)
endif # my_copy_pairs != empty
diff --git a/core/dumpconfig.mk b/core/dumpconfig.mk
index 9b1f2c2..640fe10 100644
--- a/core/dumpconfig.mk
+++ b/core/dumpconfig.mk
@@ -117,7 +117,6 @@
9 \
LOCAL_PATH \
MAKEFILE_LIST \
- PARENT_PRODUCT_FILES \
current_mk \
_eiv_ev \
_eiv_i \
diff --git a/core/dumpvar.mk b/core/dumpvar.mk
index 6b5c030..6f3d14f 100644
--- a/core/dumpvar.mk
+++ b/core/dumpvar.mk
@@ -35,3 +35,7 @@
printf "'\n";)
endif # CALLED_FROM_SETUP
+
+ifneq (,$(RBC_DUMP_CONFIG_FILE))
+$(call dump-variables-rbc,$(RBC_DUMP_CONFIG_FILE))
+endif
diff --git a/core/dynamic_binary.mk b/core/dynamic_binary.mk
index a9b3720..0d2cd7f 100644
--- a/core/dynamic_binary.mk
+++ b/core/dynamic_binary.mk
@@ -25,13 +25,8 @@
# The includer of this file will define a rule to build this target.
linked_module := $(intermediates)/LINKED/$(notdir $(my_installed_module_stem))
-ALL_ORIGINAL_DYNAMIC_BINARIES += $(linked_module)
-
-# Because TARGET_SYMBOL_FILTER_FILE depends on ALL_ORIGINAL_DYNAMIC_BINARIES,
-# the linked_module rules won't necessarily inherit the PRIVATE_
-# variables from LOCAL_BUILT_MODULE. This tells binary.make to explicitly
-# define the PRIVATE_ variables for linked_module as well as for
-# LOCAL_BUILT_MODULE.
+# This tells binary.make to explicitly define the PRIVATE_ variables for
+# linked_module as well as for LOCAL_BUILT_MODULE.
LOCAL_INTERMEDIATE_TARGETS := $(linked_module)
###################################
@@ -60,9 +55,7 @@
endif
symbolic_input := $(inject_module)
symbolic_output := $(my_unstripped_path)/$(my_installed_module_stem)
-$(symbolic_output) : $(symbolic_input)
- @echo "target Symbolic: $(PRIVATE_MODULE) ($@)"
- $(copy-file-to-target)
+$(eval $(call copy-unstripped-elf-file-with-mapping,$(symbolic_input),$(symbolic_output)))
###########################################################
## Store breakpad symbols
diff --git a/core/envsetup.mk b/core/envsetup.mk
index 5c5b565..c32d380 100644
--- a/core/envsetup.mk
+++ b/core/envsetup.mk
@@ -282,6 +282,7 @@
_system_dlkm_path_placeholder := ||SYSTEM_DLKM-PATH-PH||
TARGET_COPY_OUT_VENDOR := $(_vendor_path_placeholder)
TARGET_COPY_OUT_VENDOR_RAMDISK := vendor_ramdisk
+TARGET_COPY_OUT_VENDOR_KERNEL_RAMDISK := vendor_kernel_ramdisk
TARGET_COPY_OUT_PRODUCT := $(_product_path_placeholder)
# TODO(b/135957588) TARGET_COPY_OUT_PRODUCT_SERVICES will copy the target to
# product
@@ -324,12 +325,27 @@
# instead of the raw variable values, because mk2rbc can't read the
# raw ones.
define dump-variables-rbc
-$(file >$(OUT_DIR)/dump-variables-rbc-temp.txt,$(subst $(space),$(newline),$(.VARIABLES)))\
+$(eval _dump_variables_rbc_excluded := \
+ BOARD_PLAT_PRIVATE_SEPOLICY_DIR \
+ BOARD_PLAT_PUBLIC_SEPOLICY_DIR \
+ BUILD_NUMBER \
+ DATE \
+ LOCAL_PATH \
+ MAKEFILE_LIST \
+ PRODUCTS \
+ PRODUCT_COPY_OUT_% \
+ RBC_PRODUCT_CONFIG \
+ RBC_BOARD_CONFIG \
+ SOONG_% \
+ TOPDIR \
+ TRACE_BEGIN_SOONG \
+ USER)
+$(file >$(OUT_DIR)/dump-variables-rbc-temp.txt,$(subst $(space),$(newline),$(sort $(filter-out $(_dump_variables_rbc_excluded),$(.VARIABLES)))))
$(file >$(1),\
-$(foreach v, $(shell grep -he "^[A-Z][A-Z0-9_]*$$" $(OUT_DIR)/dump-variables-rbc-temp.txt | grep -vhE "^(SOONG_.*|LOCAL_PATH|TOPDIR|PRODUCT_COPY_OUT_.*|TRACE_BEGIN_SOONG)$$"),\
+$(foreach v, $(shell grep -he "^[A-Z][A-Z0-9_]*$$" $(OUT_DIR)/dump-variables-rbc-temp.txt),\
$(v) := $(strip $($(v)))$(newline))\
-$(foreach ns,$(SOONG_CONFIG_NAMESPACES),\
-$(foreach v,$(SOONG_CONFIG_$(ns)),\
+$(foreach ns,$(sort $(SOONG_CONFIG_NAMESPACES)),\
+$(foreach v,$(sort $(SOONG_CONFIG_$(ns))),\
$$(call soong_config_set,$(ns),$(v),$(SOONG_CONFIG_$(ns)_$(v)))$(newline))))
endef
@@ -988,6 +1004,7 @@
.KATI_READONLY := TARGET_SYSTEM_DLKM_OUT
TARGET_VENDOR_RAMDISK_OUT := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_VENDOR_RAMDISK)
+TARGET_VENDOR_KERNEL_RAMDISK_OUT := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_VENDOR_KERNEL_RAMDISK)
TARGET_ROOT_OUT := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_ROOT)
TARGET_ROOT_OUT_BIN := $(TARGET_ROOT_OUT)/bin
diff --git a/core/jacoco.mk b/core/jacoco.mk
index e8c74ee..7099526 100644
--- a/core/jacoco.mk
+++ b/core/jacoco.mk
@@ -50,6 +50,7 @@
unzip -qDD $(PRIVATE_FULL_CLASSES_PRE_JACOCO_JAR) \
-d $(PRIVATE_UNZIPPED_PATH) \
$(PRIVATE_INCLUDE_ARGS)
+ chmod -R =rwX $(PRIVATE_UNZIPPED_PATH)
(cd $(PRIVATE_UNZIPPED_PATH) && rm -rf $(PRIVATE_EXCLUDE_ARGS))
(cd $(PRIVATE_UNZIPPED_PATH) && find -not -name "*.class" -type f -exec rm {} \;)
touch $(PRIVATE_UNZIPPED_TIMESTAMP_PATH)
diff --git a/core/java.mk b/core/java.mk
index 123cbe8..a29f820 100644
--- a/core/java.mk
+++ b/core/java.mk
@@ -266,6 +266,7 @@
# TODO(b/143658984): goma can't handle the --system argument to javac.
#$(full_classes_compiled_jar): .KATI_NINJA_POOL := $(GOMA_POOL)
+$(full_classes_compiled_jar): .KATI_NINJA_POOL := $(JAVAC_NINJA_POOL)
$(full_classes_compiled_jar): PRIVATE_JAVACFLAGS := $(LOCAL_JAVACFLAGS) $(annotation_processor_flags)
$(full_classes_compiled_jar): PRIVATE_JAR_EXCLUDE_FILES := $(LOCAL_JAR_EXCLUDE_FILES)
$(full_classes_compiled_jar): PRIVATE_JAR_PACKAGES := $(LOCAL_JAR_PACKAGES)
@@ -489,12 +490,14 @@
$(built_dex_intermediate): PRIVATE_DX_FLAGS := $(LOCAL_DX_FLAGS)
ifdef LOCAL_PROGUARD_ENABLED
+ $(built_dex_intermediate): .KATI_NINJA_POOL := $(R8_NINJA_POOL)
$(built_dex_intermediate): PRIVATE_EXTRA_INPUT_JAR := $(extra_input_jar)
$(built_dex_intermediate): PRIVATE_PROGUARD_FLAGS := $(legacy_proguard_flags) $(common_proguard_flags) $(LOCAL_PROGUARD_FLAGS)
$(built_dex_intermediate): PRIVATE_PROGUARD_DICTIONARY := $(proguard_dictionary)
$(built_dex_intermediate) : $(full_classes_pre_proguard_jar) $(extra_input_jar) $(my_proguard_sdk_raise) $(common_proguard_flag_files) $(legacy_proguard_lib_deps) $(R8_COMPAT_PROGUARD) $(LOCAL_PROGUARD_FLAGS_DEPS)
$(transform-jar-to-dex-r8)
else # !LOCAL_PROGUARD_ENABLED
+ $(built_dex_intermediate): .KATI_NINJA_POOL := $(D8_NINJA_POOL)
$(built_dex_intermediate): PRIVATE_D8_LIBS := $(full_java_bootclasspath_libs) $(full_shared_java_header_libs)
$(built_dex_intermediate): $(full_java_bootclasspath_libs) $(full_shared_java_header_libs)
$(built_dex_intermediate): $(full_classes_pre_proguard_jar) $(DX) $(ZIP2ZIP)
diff --git a/core/main.mk b/core/main.mk
index d5dc49f..e0efdad 100644
--- a/core/main.mk
+++ b/core/main.mk
@@ -935,6 +935,7 @@
$(eval my_testcases := $(HOST_OUT_TESTCASES)),\
$(eval my_testcases := $$(COMPATIBILITY_TESTCASES_OUT_$(suite))))\
$(eval target := $(my_testcases)/$(lastword $(subst /, ,$(dir $(f))))/$(notdir $(f)))\
+ $(if $(strip $(ALL_TARGETS.$(target).META_LIC)),,$(eval ALL_TARGETS.$(target).META_LIC:=$(module_license_metadata)))\
$(eval COMPATIBILITY.$(suite).HOST_SHARED_LIBRARY.FILES := \
$$(COMPATIBILITY.$(suite).HOST_SHARED_LIBRARY.FILES) $(f):$(target))\
$(eval COMPATIBILITY.$(suite).HOST_SHARED_LIBRARY.FILES := \
@@ -1234,42 +1235,14 @@
# 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 _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 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 auto-included-modules) \
) \
$(eval ### Filter out the overridden packages and executables before doing expansion) \
@@ -1280,13 +1253,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 _product-var,$(1),PRODUCT_COPY_FILES),$(call word-colon,2,$(cf))))
+ $(foreach cf,$(call get-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 _product-var,$(1),PRODUCT_HOST_PACKAGES)) \
+ $(eval _hif_modules := $(call get-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))) \
@@ -1375,7 +1348,7 @@
# Verify the artifact path requirements made by included products.
is_asan := $(if $(filter address,$(SANITIZE_TARGET)),true)
- ifeq (,$(or $(is_asan),$(DISABLE_ARTIFACT_PATH_REQUIREMENTS),$(RBC_PRODUCT_CONFIG),$(RBC_BOARD_CONFIG)))
+ ifeq (,$(or $(is_asan),$(DISABLE_ARTIFACT_PATH_REQUIREMENTS)))
include $(BUILD_SYSTEM)/artifact_path_requirements.mk
endif
else
@@ -1483,12 +1456,6 @@
# fix-notice-deps replaces those unadorned module names with every built variant.
$(call fix-notice-deps)
-# Create a license metadata rule per module. Could happen in base_rules.mk or
-# notice_files.mk; except, it has to happen after fix-notice-deps to avoid
-# missing dependency errors.
-$(call build-license-metadata)
-
-
# These are additional goals that we build, in order to make sure that there
# is as little code as possible in the tree that doesn't build.
modules_to_check := $(foreach m,$(ALL_MODULES),$(ALL_MODULES.$(m).CHECKED))
@@ -1560,6 +1527,9 @@
.PHONY: vendorbootimage
vendorbootimage: $(INSTALLED_VENDOR_BOOTIMAGE_TARGET)
+.PHONY: vendorkernelbootimage
+vendorkernelbootimage: $(INSTALLED_VENDOR_KERNEL_BOOTIMAGE_TARGET)
+
.PHONY: vendorbootimage_debug
vendorbootimage_debug: $(INSTALLED_VENDOR_DEBUG_BOOTIMAGE_TARGET)
@@ -1569,6 +1539,9 @@
.PHONY: vendorramdisk
vendorramdisk: $(INSTALLED_VENDOR_RAMDISK_TARGET)
+.PHONY: vendorkernelramdisk
+vendorkernelramdisk: $(INSTALLED_VENDOR_KERNEL_RAMDISK_TARGET)
+
.PHONY: vendorramdisk_debug
vendorramdisk_debug: $(INSTALLED_VENDOR_DEBUG_RAMDISK_TARGET)
@@ -1628,6 +1601,7 @@
# perform a full system build (either unbundled or not).
.PHONY: droidcore-unbundled
droidcore-unbundled: $(filter $(HOST_OUT_ROOT)/%,$(modules_to_install)) \
+ $(INSTALLED_FILES_OUTSIDE_IMAGES) \
$(INSTALLED_SYSTEMIMAGE_TARGET) \
$(INSTALLED_RAMDISK_TARGET) \
$(INSTALLED_BOOTIMAGE_TARGET) \
@@ -1644,10 +1618,12 @@
$(INSTALLED_BPTIMAGE_TARGET) \
$(INSTALLED_VENDORIMAGE_TARGET) \
$(INSTALLED_VENDOR_BOOTIMAGE_TARGET) \
+ $(INSTALLED_VENDOR_KERNEL_BOOTIMAGE_TARGET) \
$(INSTALLED_VENDOR_DEBUG_BOOTIMAGE_TARGET) \
$(INSTALLED_VENDOR_TEST_HARNESS_RAMDISK_TARGET) \
$(INSTALLED_VENDOR_TEST_HARNESS_BOOTIMAGE_TARGET) \
$(INSTALLED_VENDOR_RAMDISK_TARGET) \
+ $(INSTALLED_VENDOR_KERNEL_RAMDISK_TARGET) \
$(INSTALLED_VENDOR_DEBUG_RAMDISK_TARGET) \
$(INSTALLED_ODMIMAGE_TARGET) \
$(INSTALLED_VENDOR_DLKMIMAGE_TARGET) \
@@ -1684,6 +1660,8 @@
$(INSTALLED_FILES_JSON_VENDOR_RAMDISK) \
$(INSTALLED_FILES_FILE_VENDOR_DEBUG_RAMDISK) \
$(INSTALLED_FILES_JSON_VENDOR_DEBUG_RAMDISK) \
+ $(INSTALLED_FILES_FILE_VENDOR_KERNEL_RAMDISK) \
+ $(INSTALLED_FILES_JSON_VENDOR_KERNEL_RAMDISK) \
$(INSTALLED_FILES_FILE_ROOT) \
$(INSTALLED_FILES_JSON_ROOT) \
$(INSTALLED_FILES_FILE_RECOVERY) \
@@ -1750,28 +1728,32 @@
endif
$(PROGUARD_DICT_ZIP) : $(apps_only_installed_files)
- $(call dist-for-goals,apps_only, $(PROGUARD_DICT_ZIP))
+ $(call dist-for-goals,apps_only, $(PROGUARD_DICT_ZIP) $(PROGUARD_DICT_MAPPING))
+ $(call declare-container-license-deps,$(PROGUARD_DICT_ZIP),$(apps_only_installed_files),$(PRODUCT_OUT)/:/)
$(PROGUARD_USAGE_ZIP) : $(apps_only_installed_files)
$(call dist-for-goals,apps_only, $(PROGUARD_USAGE_ZIP))
+ $(call declare-container-license-deps,$(PROGUARD_USAGE_ZIP),$(apps_only_installed_files),$(PRODUCT_OUT)/:/)
$(SYMBOLS_ZIP) : $(apps_only_installed_files)
- $(call dist-for-goals,apps_only, $(SYMBOLS_ZIP))
+ $(call dist-for-goals,apps_only, $(SYMBOLS_ZIP) $(SYMBOLS_MAPPING))
+ $(call declare-container-license-deps,$(SYMBOLS_ZIP),$(apps_only_installed_files),$(PRODUCT_OUT)/:/)
$(COVERAGE_ZIP) : $(apps_only_installed_files)
$(call dist-for-goals,apps_only, $(COVERAGE_ZIP))
+ $(call declare-container-license-deps,$(COVERAGE_ZIP),$(apps_only_installed_files),$(PRODUCT_OUT)/:/)
apps_only: $(unbundled_build_modules)
droid_targets: apps_only
-# Combine the NOTICE files for a apps_only build
-$(eval $(call combine-notice-files, html, \
- $(target_notice_file_txt), \
- $(target_notice_file_html_or_xml), \
- "Notices for files for apps:", \
- $(TARGET_OUT_NOTICE_FILES), \
- $(apps_only_installed_files)))
+# NOTICE files for a apps_only build
+$(eval $(call html-notice-rule,$(target_notice_file_html_or_xml),"Apps","Notices for files for apps:",$(unbundled_build_modules),$(PRODUCT_OUT)/ $(HOST_OUT)/))
+
+$(eval $(call text-notice-rule,$(target_notice_file_txt),"Apps","Notices for files for apps:",$(unbundled_build_modules),$(PRODUCT_OUT)/ $(HOST_OUT)/))
+
+$(call declare-0p-target,$(target_notice_file_txt))
+$(call declare-0p-target,$(target_notice_html_or_xml))
else ifeq ($(TARGET_BUILD_UNBUNDLED),$(TARGET_BUILD_UNBUNDLED_IMAGE))
@@ -1807,7 +1789,9 @@
$(INTERNAL_OTA_PARTIAL_PACKAGE_TARGET) \
$(INTERNAL_OTA_RETROFIT_DYNAMIC_PARTITIONS_PACKAGE_TARGET) \
$(SYMBOLS_ZIP) \
+ $(SYMBOLS_MAPPING) \
$(PROGUARD_DICT_ZIP) \
+ $(PROGUARD_DICT_MAPPING) \
$(PROGUARD_USAGE_ZIP) \
$(COVERAGE_ZIP) \
$(INSTALLED_FILES_FILE) \
@@ -1867,6 +1851,8 @@
$(INSTALLED_FILES_JSON_DEBUG_RAMDISK) \
$(INSTALLED_FILES_FILE_VENDOR_RAMDISK) \
$(INSTALLED_FILES_JSON_VENDOR_RAMDISK) \
+ $(INSTALLED_FILES_FILE_VENDOR_KERNEL_RAMDISK) \
+ $(INSTALLED_FILES_JSON_VENDOR_KERNEL_RAMDISK) \
$(INSTALLED_FILES_FILE_VENDOR_DEBUG_RAMDISK) \
$(INSTALLED_FILES_JSON_VENDOR_DEBUG_RAMDISK) \
$(INSTALLED_DEBUG_RAMDISK_TARGET) \
@@ -1878,6 +1864,7 @@
$(INSTALLED_VENDOR_TEST_HARNESS_BOOTIMAGE_TARGET) \
$(INSTALLED_VENDOR_RAMDISK_TARGET) \
$(INSTALLED_VENDOR_DEBUG_RAMDISK_TARGET) \
+ $(INSTALLED_VENDOR_KERNEL_RAMDISK_TARGET) \
)
endif
@@ -1908,6 +1895,8 @@
$(hide) mkdir -p $(dir $@)
$(hide) $(APICHECK_COMMAND) --input-api-jar $< --api-xml $@
+ $(foreach xml,$(sort $(api_xmls)),$(call declare-1p-target,$(xml),))
+
$(call dist-for-goals, dist_files, $(api_xmls))
api_xmls :=
@@ -1948,6 +1937,7 @@
$(call dist-for-goals,sdk, \
$(ALL_SDK_TARGETS) \
$(SYMBOLS_ZIP) \
+ $(SYMBOLS_MAPPING) \
$(COVERAGE_ZIP) \
$(APPCOMPAT_ZIP) \
$(INSTALLED_BUILD_PROP_TARGET) \
@@ -2019,6 +2009,11 @@
droidcore: ${APEX_ALLOWED_DEPS_CHECK}
endif
+# Create a license metadata rule per module. Could happen in base_rules.mk or
+# notice_files.mk; except, it has to happen after fix-notice-deps to avoid
+# missing dependency errors.
+$(call build-license-metadata)
+
$(call dist-write-file,$(KATI_PACKAGE_MK_DIR)/dist.mk)
$(info [$(call inc_and_print,subdir_makefiles_inc)/$(subdir_makefiles_total)] writing build rules ...)
diff --git a/core/ninja_config.mk b/core/ninja_config.mk
index 2157c9e..e436b2c 100644
--- a/core/ninja_config.mk
+++ b/core/ninja_config.mk
@@ -25,7 +25,6 @@
cts \
custom_images \
dicttool_aosp \
- dump-products \
eng \
oem_image \
online-system-api-sdk-docs \
diff --git a/core/notice_files.mk b/core/notice_files.mk
index 4ebbe2e..c05d4ea 100644
--- a/core/notice_files.mk
+++ b/core/notice_files.mk
@@ -127,7 +127,7 @@
ifdef my_register_name
module_license_metadata := $(call local-intermediates-dir)/$(my_register_name).meta_lic
- $(foreach target,$(ALL_MODULES.$(my_register_name).BUILT) $(ALL_MODULES.$(my_register_name).INSTALLED),\
+ $(foreach target,$(ALL_MODULES.$(my_register_name).BUILT) $(ALL_MODULES.$(my_register_name).INSTALLED) $(my_test_data) $(my_test_config),\
$(eval ALL_TARGETS.$(target).META_LIC := $(module_license_metadata)))
ALL_MODULES.$(my_register_name).META_LIC := $(strip $(ALL_MODULES.$(my_register_name).META_LIC) $(module_license_metadata))
@@ -157,102 +157,4 @@
ALL_MODULES.$(my_register_name).NOTICES := $(ALL_MODULES.$(my_register_name).NOTICES) $(notice_file)
endif
-# This relies on the name of the directory in PRODUCT_OUT matching where
-# it's installed on the target - i.e. system, data, etc. This does
-# not work for root and isn't exact, but it's probably good enough for
-# compliance.
-# Includes the leading slash
-ifdef LOCAL_INSTALLED_MODULE
- module_installed_filename := $(patsubst $(PRODUCT_OUT)/%,%,$(LOCAL_INSTALLED_MODULE))
-else
- # This module isn't installable
- ifneq ($(filter STATIC_LIBRARIES RLIB_LIBRARIES PROC_MACRO_LIBRARIES HEADER_LIBRARIES,$(LOCAL_MODULE_CLASS)),)
- # Stick the static libraries with the dynamic libraries.
- # We can't use xxx_OUT_STATIC_LIBRARIES because it points into
- # device-obj or host-obj.
- module_installed_filename := \
- $(patsubst $(PRODUCT_OUT)/%,%,$($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)OUT_SHARED_LIBRARIES))/$(notdir $(LOCAL_BUILT_MODULE))
- else ifeq ($(LOCAL_MODULE_CLASS),SHARED_LIBRARIES)
- # Shared modules may be uninstallable(e.g. TARGET_SKIP_CURRENT_VNDK=true)
- module_installed_filename :=
- else
- ifeq ($(LOCAL_MODULE_CLASS),JAVA_LIBRARIES)
- # Stick the static java libraries with the regular java libraries.
- module_leaf := $(notdir $(LOCAL_BUILT_MODULE))
- # javalib.jar is the default name for the build module (and isn't meaningful)
- # If that's what we have, substitute the module name instead. These files
- # aren't included on the device, so this name is synthetic anyway.
- # Extra path "static" is added to try to avoid name conflict between the notice file of
- # this 'uninstallable' Java module and the notice file for another 'installable' Java module
- # whose stem is the same as this module's name.
- ifneq ($(filter javalib.jar,$(module_leaf)),)
- module_leaf := static/$(LOCAL_MODULE).jar
- endif
- module_installed_filename := \
- $(patsubst $(PRODUCT_OUT)/%,%,$($(my_prefix)OUT_JAVA_LIBRARIES))/$(module_leaf)
- else ifneq ($(filter ETC DATA,$(LOCAL_MODULE_CLASS)),)
- # ETC and DATA modules may be uninstallable, yet still have a NOTICE file.
- # e.g. apex components
- module_installed_filename :=
- else ifneq (,$(and $(filter %.sdk,$(LOCAL_MODULE)),$(filter $(patsubst %.sdk,%,$(LOCAL_MODULE)),$(SOONG_SDK_VARIANT_MODULES))))
- # Soong produces uninstallable *.sdk shared libraries for embedding in APKs.
- module_installed_filename := \
- $(patsubst $(PRODUCT_OUT)/%,%,$($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)OUT_SHARED_LIBRARIES))/$(notdir $(LOCAL_BUILT_MODULE))
- endif # JAVA_LIBRARIES
- endif # STATIC_LIBRARIES
-endif
-
-ifdef module_installed_filename
-
-# In case it's actually a host file
-module_installed_filename := $(patsubst $(HOST_OUT)/%,%,$(module_installed_filename))
-module_installed_filename := $(patsubst $(HOST_CROSS_OUT)/%,%,$(module_installed_filename))
-
-installed_notice_file := $($(my_prefix)OUT_NOTICE_FILES)/src/$(module_installed_filename).txt
-
-$(installed_notice_file): $(module_license_metadata)
-
-ifdef my_register_name
-ALL_MODULES.$(my_register_name).INSTALLED_NOTICE_FILE := $(ALL_MODULES.$(my_register_name).INSTALLED_NOTICE_FILE) $(installed_notice_file)
-ALL_MODULES.$(my_register_name).MODULE_INSTALLED_FILENAMES := $(ALL_MODULES.$(my_register_name).MODULE_INSTALLED_FILENAMES) $(module_installed_filename)
-INSTALLED_NOTICE_FILES.$(installed_notice_file).MODULE := $(my_register_name)
-else
-$(installed_notice_file): PRIVATE_INSTALLED_MODULE := $(module_installed_filename)
-$(installed_notice_file) : PRIVATE_NOTICES := $(sort $(foreach n,$(notice_file),$(if $(filter %:%,$(n)), $(call word-colon,1,$(n)), $(n))))
-
-$(installed_notice_file): $(foreach n,$(notice_file),$(if $(filter %:%,$(n)), $(call word-colon,1,$(n)), $(n)))
- @echo Notice file: $< -- $@
- $(hide) mkdir -p $(dir $@)
- $(hide) awk 'FNR==1 && NR > 1 {print "\n"} {print}' $(PRIVATE_NOTICES) > $@
-endif
-
-ifdef LOCAL_INSTALLED_MODULE
-# Make LOCAL_INSTALLED_MODULE depend on NOTICE files if they exist
-# libraries so they get installed along with it. Make it an order-only
-# dependency so we don't re-install a module when the NOTICE changes.
-$(LOCAL_INSTALLED_MODULE): | $(installed_notice_file)
-endif
-
-# To facilitate collecting NOTICE files for apps_only build,
-# we install the NOTICE file even if a module gets built but not installed,
-# because shared jni libraries won't be installed to the system image.
-ifdef TARGET_BUILD_APPS
-# for static Java libraries, we don't need to even build LOCAL_BUILT_MODULE,
-# but just javalib.jar in the common intermediate dir.
-ifeq ($(LOCAL_MODULE_CLASS),JAVA_LIBRARIES)
-$(intermediates.COMMON)/javalib.jar : | $(installed_notice_file)
-else
-$(LOCAL_BUILT_MODULE): | $(installed_notice_file)
-endif # JAVA_LIBRARIES
-endif # TARGET_BUILD_APPS
-
-endif # module_installed_filename
endif # notice_file
-
-# Create a predictable, phony target to build this notice file.
-# Define it even if the notice file doesn't exist so that other
-# modules can depend on it.
-notice_target := NOTICE-$(if \
- $(LOCAL_IS_HOST_MODULE),HOST$(if $(my_host_cross),_CROSS,),TARGET)-$(LOCAL_MODULE_CLASS)-$(LOCAL_MODULE)
-.PHONY: $(notice_target)
-$(notice_target): $(installed_notice_file)
diff --git a/core/os_licensing.mk b/core/os_licensing.mk
new file mode 100644
index 0000000..d8d3c78
--- /dev/null
+++ b/core/os_licensing.mk
@@ -0,0 +1,175 @@
+ifeq ($(TARGET_BUILD_APPS),)
+
+.PHONY: systemlicense
+systemlicense: $(call corresponding-license-metadata, $(SYSTEM_NOTICE_DEPS)) reportmissinglicenses
+
+ifneq (,$(SYSTEM_NOTICE_DEPS))
+
+SYSTEM_NOTICE_DEPS += $(UNMOUNTED_NOTICE_DEPS)
+
+ifneq ($(PRODUCT_NOTICE_SPLIT),true)
+$(eval $(call html-notice-rule,$(target_notice_file_html_gz),"System image",$(system_notice_file_message),$(SYSTEM_NOTICE_DEPS),$(SYSTEM_NOTICE_DEPS)))
+
+$(installed_notice_html_or_xml_gz): $(target_notice_file_html_gz)
+ $(copy-file-to-target)
+else
+$(eval $(call xml-notice-rule,$(target_notice_file_xml_gz),"System image",$(system_notice_file_message),$(SYSTEM_NOTICE_DEPS),$(SYSTEM_NOTICE_DEPS)))
+
+$(eval $(call text-notice-rule,$(target_notice_file_txt),"System image",$(system_notice_file_message),$(SYSTEM_NOTICE_DEPS),$(SYSTEM_NOTICE_DEPS)))
+
+$(installed_notice_html_or_xml_gz): $(target_notice_file_xml_gz)
+ $(copy-file-to-target)
+endif
+
+$(call declare-0p-target,$(target_notice_file_xml_gz))
+$(call declare-0p-target,$(installed_notice_html_or_xml_gz))
+ALL_DEFAULT_INSTALLED_MODULES += $(installed_notice_html_or_xml_gz)
+endif
+
+.PHONY: vendorlicense
+vendorlicense: $(call corresponding-license-metadata, $(VENDOR_NOTICE_DEPS)) reportmissinglicenses
+
+ifneq (,$(VENDOR_NOTICE_DEPS))
+
+VENDOR_NOTICE_DEPS += $(UNMOUNTED_NOTICE_DEPS)
+
+$(eval $(call text-notice-rule,$(target_vendor_notice_file_txt),"Vendor image", \
+ "Notices for files contained in all filesystem images except system/system_ext/product/odm/vendor_dlkm/odm_dlkm in this directory:", \
+ $(VENDOR_NOTICE_DEPS)))
+
+$(eval $(call xml-notice-rule,$(target_vendor_notice_file_xml_gz),"Vendor image", \
+ "Notices for files contained in all filesystem images except system/system_ext/product/odm/vendor_dlkm/odm_dlkm in this directory:", \
+ $(VENDOR_NOTICE_DEPS)))
+
+$(installed_vendor_notice_xml_gz): $(target_vendor_notice_file_xml_gz)
+ $(copy-file-to-target)
+
+$(call declare-0p-target,$(target_vendor_notice_file_xml_gz))
+$(call declare-0p-target,$(installed_vendor_notice_xml_gz))
+ALL_DEFAULT_INSTALLED_MODULES += $(installed_vendor_notice_xml_gz)
+endif
+
+.PHONY: odmlicense
+odmlicense: $(call corresponding-license-metadata, $(ODM_NOTICE_DEPS)) reportmissinglicenses
+
+ifneq (,$(ODM_NOTICE_DEPS))
+$(eval $(call text-notice-rule,$(target_odm_notice_file_txt),"ODM filesystem image", \
+ "Notices for files contained in the odm filesystem image in this directory:", \
+ $(ODM_NOTICE_DEPS)))
+
+$(eval $(call xml-notice-rule,$(target_odm_notice_file_xml_gz),"ODM filesystem image", \
+ "Notices for files contained in the odm filesystem image in this directory:", \
+ $(ODM_NOTICE_DEPS)))
+
+$(installed_odm_notice_xml_gz): $(target_odm_notice_file_xml_gz)
+ $(copy-file-to-target)
+
+$(call declare-0p-target,$(target_odm_notice_file_xml_gz))
+$(call declare-0p-target,$(installed_odm_notice_xml_gz))
+ALL_DEFAULT_INSTALLED_MODULES += $(installed_odm_notice_xml_gz)
+endif
+
+.PHONY: oemlicense
+oemlicense: $(call corresponding-license-metadata, $(OEM_NOTICE_DEPS)) reportmissinglicenses
+
+.PHONY: productlicense
+productlicense: $(call corresponding-license-metadata, $(PRODUCT_NOTICE_DEPS)) reportmissinglicenses
+
+ifneq (,$(PRODUCT_NOTICE_DEPS))
+$(eval $(call text-notice-rule,$(target_product_notice_file_txt),"Product image", \
+ "Notices for files contained in the product filesystem image in this directory:", \
+ $(PRODUCT_NOTICE_DEPS)))
+
+$(eval $(call xml-notice-rule,$(target_product_notice_file_xml_gz),"Product image", \
+ "Notices for files contained in the product filesystem image in this directory:", \
+ $(PRODUCT_NOTICE_DEPS)))
+
+$(installed_product_notice_xml_gz): $(target_product_notice_file_xml_gz)
+ $(copy-file-to-target)
+
+$(call declare-0p-target,$(target_product_notice_file_xml_gz))
+$(call declare-0p-target,$(installed_product_notice_xml_gz))
+ALL_DEFAULT_INSTALLED_MODULES += $(installed_product_notice_xml_gz)
+endif
+
+.PHONY: systemextlicense
+systemextlicense: $(call corresponding-license-metadata, $(SYSTEM_EXT_NOTICE_DEPS)) reportmissinglicenses
+
+ifneq (,$(SYSTEM_EXT_NOTICE_DEPS))
+$(eval $(call text-notice-rule,$(target_system_ext_notice_file_txt),"System_ext image", \
+ "Notices for files contained in the system_ext filesystem image in this directory:", \
+ $(SYSTEM_EXT_NOTICE_DEPS)))
+
+$(eval $(call xml-notice-rule,$(target_system_ext_notice_file_xml_gz),"System_ext image", \
+ "Notices for files contained in the system_ext filesystem image in this directory:", \
+ $(SYSTEM_EXT_NOTICE_DEPS)))
+
+$(installed_system_ext_notice_xml_gz): $(target_system_ext_notice_file_xml_gz)
+ $(copy-file-to-target)
+
+$(call declare-0p-target,$(target_system_ext_notice_file_xml_gz))
+$(call declare-0p-target,$(installed_system_ext_notice_xml_gz))
+ALL_DEFAULT_INSTALLED_MODULES += $(installed_system_ext_notice_xml_gz)
+endif
+
+.PHONY: vendor_dlkmlicense
+vendor_dlkmlicense: $(call corresponding-license-metadata, $(VENDOR_DLKM_NOTICE_DEPS)) reportmissinglicenses
+
+ifneq (,$(VENDOR_DLKM_NOTICE_DEPS))
+$(eval $(call text-notice-rule,$(target_vendor_dlkm_notice_file_txt),"Vendor_dlkm image", \
+ "Notices for files contained in the vendor_dlkm filesystem image in this directory:", \
+ $(VENDOR_DLKM_NOTICE_DEPS)))
+
+$(eval $(call xml-notice-rule,$(target_vendor_dlkm_notice_file_xml_gz),"Vendor_dlkm image", \
+ "Notices for files contained in the vendor_dlkm filesystem image in this directory:", \
+ $(VENDOR_DLKM_NOTICE_DEPS)))
+
+$(installed_vendor_dlkm_notice_xml_gz): $(target_vendor_dlkm_notice_file_xml_gz)
+ $(copy-file-to-target)
+
+$(call declare-0p-target,$(target_vendor_dlkm_notice_file_xml_gz))
+$(call declare-0p-target,$(installed_vendor_dlkm_notice_xml_gz))
+ALL_DEFAULT_INSTALLED_MODULES += $(installed_vendor_dlkm_notice_xml_gz)
+endif
+
+.PHONY: odm_dlkmlicense
+odm_dlkmlicense: $(call corresponding-license-metadata, $(ODM_DLKM_NOTICE_DEPS)) reportmissinglicenses
+
+ifneq (,$(ODM_DLKM_NOTICE_DEPS))
+$(eval $(call text-notice-rule,$(target_odm_dlkm_notice_file_txt),"ODM_dlkm filesystem image", \
+ "Notices for files contained in the odm_dlkm filesystem image in this directory:", \
+ $(ODM_DLKM_NOTICE_DEPS)))
+
+$(eval $(call xml-notice-rule,$(target_odm_dlkm_notice_file_xml_gz),"ODM_dlkm filesystem image", \
+ "Notices for files contained in the odm_dlkm filesystem image in this directory:", \
+ $(ODM_DLMK_NOTICE_DEPS)))
+
+$(installed_odm_dlkm_notice_xml_gz): $(target_odm_dlkm_notice_file_xml_gz)
+ $(copy-file-to-target)
+
+$(call declare-0p-target,$(target_odm_dlkm_notice_file_xml_gz))
+$(call declare-0p-target,$(installed_odm_dlkm_notice_xml_gz))
+ALL_DEFAULT_INSTALLED_MODULES += $(installed_odm_dlkm_notice_xml_gz)
+endif
+
+.PHONY: system_dlkmlicense
+system_dlkmlicense: $(call corresponding-license-metadata, $(SYSTEM_DLKM_NOTICE_DEPS)) reportmissinglicenses
+
+ifneq (,$(SYSTEM_DLKM_NOTICE_DEPS))
+$(eval $(call text-notice-rule,$(target_system_dlkm_notice_file_txt),"System_dlkm filesystem image", \
+ "Notices for files contained in the system_dlkm filesystem image in this directory:", \
+ $(SYSTEM_DLKM_NOTICE_DEPS)))
+
+$(eval $(call xml-notice-rule,$(target_system_dlkm_notice_file_xml_gz),"System_dlkm filesystem image", \
+ "Notices for files contained in the system_dlkm filesystem image in this directory:", \
+ $(SYSTEM_DLMK_NOTICE_DEPS)))
+
+$(installed_system_dlkm_notice_xml_gz): $(target_system_dlkm_notice_file_xml_gz)
+ $(copy-file-to-target)
+
+$(call declare-0p-target,$(target_system_dlkm_notice_file_xml_gz))
+$(call declare-0p-target,$(installed_sysetm_dlkm_notice_xml_gz))
+ALL_DEFAULT_INSTALLED_MODULES += $(installed_system_dlkm_notice_xml_gz)
+endif
+
+endif # not TARGET_BUILD_APPS
diff --git a/core/product-graph.mk b/core/product-graph.mk
index 6d51db1..379110e 100644
--- a/core/product-graph.mk
+++ b/core/product-graph.mk
@@ -15,12 +15,12 @@
#
# the sort also acts as a strip to remove the single space entries that creep in because of the evals
-define gather-all-products
+define gather-all-makefiles-for-current-product
$(eval _all_products_visited := )\
-$(sort $(call all-products-inner, $(PARENT_PRODUCT_FILES)))
+$(sort $(call gather-all-makefiles-for-current-product-inner,$(INTERNAL_PRODUCT)))
endef
-define all-products-inner
+define gather-all-makefiles-for-current-product-inner
$(foreach p,$(1),\
$(if $(filter $(p),$(_all_products_visited)),, \
$(p) \
@@ -30,30 +30,12 @@
)
endef
-this_makefile := build/make/core/product-graph.mk
-
-products_graph := $(OUT_DIR)/products.dot
-ifeq ($(strip $(ANDROID_PRODUCT_GRAPH)),)
-products_list := $(INTERNAL_PRODUCT)
-else
-ifeq ($(strip $(ANDROID_PRODUCT_GRAPH)),--all)
-products_list := --all
-else
-products_list := $(foreach prod,$(ANDROID_PRODUCT_GRAPH),$(call resolve-short-product-name,$(prod)))
-endif
-endif
-
-all_products := $(call gather-all-products)
-
-open_parethesis := (
-close_parenthesis := )
-
node_color_target := orange
node_color_common := beige
node_color_vendor := lavenderblush
node_color_default := white
define node-color
-$(if $(filter $(1),$(PRIVATE_PRODUCTS_FILTER)),\
+$(if $(filter $(1),$(PRIVATE_TOP_LEVEL_MAKEFILE)),\
$(node_color_target),\
$(if $(filter build/make/target/product/%,$(1)),\
$(node_color_common),\
@@ -62,45 +44,36 @@
)
endef
+open_parethesis := (
+close_parenthesis := )
+
# Emit properties of a product node to a file.
# $(1) the product
# $(2) the output file
define emit-product-node-props
$(hide) echo \"$(1)\" [ \
-label=\"$(dir $(1))\\n$(notdir $(1))\\n\\n$(subst $(close_parenthesis),,$(subst $(open_parethesis),,$(call get-product-var,$(1),PRODUCT_MODEL)))\\n$(call get-product-var,$(1),PRODUCT_DEVICE)\" \
+label=\"$(dir $(1))\\n$(notdir $(1))$(if $(filter $(1),$(PRIVATE_TOP_LEVEL_MAKEFILE)),$(subst $(open_parethesis),,$(subst $(close_parenthesis),,\\n\\n$(PRODUCT_MODEL)\\n$(PRODUCT_DEVICE))))\" \
style=\"filled\" fillcolor=\"$(strip $(call node-color,$(1)))\" \
colorscheme=\"svg\" fontcolor=\"darkblue\" \
] >> $(2)
endef
-$(products_graph): PRIVATE_PRODUCTS := $(all_products)
-$(products_graph): PRIVATE_PRODUCTS_FILTER := $(products_list)
+products_graph := $(OUT_DIR)/products.dot
-$(products_graph): $(this_makefile)
-ifeq (,$(RBC_PRODUCT_CONFIG)$(RBC_NO_PRODUCT_GRAPH)$(RBC_BOARD_CONFIG))
- @echo Product graph DOT: $@ for $(PRIVATE_PRODUCTS_FILTER)
- $(hide) echo 'digraph {' > $@.in
- $(hide) echo 'graph [ ratio=.5 ];' >> $@.in
- $(hide) $(foreach p,$(PRIVATE_PRODUCTS), \
- $(foreach d,$(PRODUCTS.$(strip $(p)).INHERITS_FROM), echo \"$(d)\" -\> \"$(p)\" >> $@.in;))
- $(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
-
-ifeq (,$(RBC_PRODUCT_CONFIG)$(RBC_NO_PRODUCT_GRAPH)$(RBC_BOARD_CONFIG))
+$(products_graph): PRIVATE_ALL_MAKEFILES_FOR_THIS_PRODUCT := $(call gather-all-makefiles-for-current-product)
+$(products_graph): PRIVATE_TOP_LEVEL_MAKEFILE := $(INTERNAL_PRODUCT)
+$(products_graph):
+ @echo Product graph DOT: $@ for $(PRIVATE_TOP_LEVEL_MAKEFILE)
+ $(hide) echo 'digraph {' > $@
+ $(hide) echo 'graph [ ratio=.5 ];' >> $@
+ $(hide) $(foreach p,$(PRIVATE_ALL_MAKEFILES_FOR_THIS_PRODUCT), \
+ $(foreach d,$(PRODUCTS.$(strip $(p)).INHERITS_FROM), echo \"$(d)\" -\> \"$(p)\" >> $@;))
+ $(foreach p,$(PRIVATE_ALL_MAKEFILES_FOR_THIS_PRODUCT),$(call emit-product-node-props,$(p),$@))
+ $(hide) echo '}' >> $@
.PHONY: product-graph
product-graph: $(products_graph)
@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
diff --git a/core/product.mk b/core/product.mk
index 43724a8..53fee1c 100644
--- a/core/product.mk
+++ b/core/product.mk
@@ -14,98 +14,6 @@
# limitations under the License.
#
-#
-# Functions for including AndroidProducts.mk files
-# PRODUCT_MAKEFILES is set up in AndroidProducts.mks.
-# Format of PRODUCT_MAKEFILES:
-# <product_name>:<path_to_the_product_makefile>
-# If the <product_name> is the same as the base file name (without dir
-# and the .mk suffix) of the product makefile, "<product_name>:" can be
-# omitted.
-
-#
-# Returns the list of all AndroidProducts.mk files.
-# $(call ) isn't necessary.
-#
-define _find-android-products-files
-$(file <$(OUT_DIR)/.module_paths/AndroidProducts.mk.list) \
- $(SRC_TARGET_DIR)/product/AndroidProducts.mk
-endef
-
-#
-# For entries returned by get-product-makefiles, decode an entry to a short
-# product name. These either may be in the form of <name>:path/to/file.mk or
-# path/to/<name>.mk
-# $(1): The entry to decode
-#
-# Returns two words:
-# <name> <file>
-#
-define _decode-product-name
-$(strip \
- $(eval _cpm_words := $(subst :,$(space),$(1))) \
- $(if $(word 2,$(_cpm_words)), \
- $(wordlist 1,2,$(_cpm_words)), \
- $(basename $(notdir $(1))) $(1)))
-endef
-
-#
-# Validates the new common lunch choices -- ensures that they're in an
-# appropriate form, and are paired with definitions of their products.
-# $(1): The new list of COMMON_LUNCH_CHOICES
-# $(2): The new list of PRODUCT_MAKEFILES
-#
-define _validate-common-lunch-choices
-$(strip $(foreach choice,$(1),\
- $(eval _parts := $(subst -,$(space),$(choice))) \
- $(if $(call math_lt,$(words $(_parts)),2), \
- $(error $(LOCAL_DIR): $(choice): Invalid lunch choice)) \
- $(if $(call math_gt_or_eq,$(words $(_parts)),4), \
- $(error $(LOCAL_DIR): $(choice): Invalid lunch choice)) \
- $(if $(filter-out eng userdebug user,$(word 2,$(_parts))), \
- $(error $(LOCAL_DIR): $(choice): Invalid variant: $(word 2,$(_parts)))) \
- $(if $(filter-out $(foreach p,$(2),$(call _decode-product-name,$(p))),$(word 1,$(_parts))), \
- $(error $(LOCAL_DIR): $(word 1,$(_parts)): Product not defined in this file)) \
- ))
-endef
-
-#
-# Returns the sorted concatenation of PRODUCT_MAKEFILES
-# variables set in the given AndroidProducts.mk files.
-# $(1): the list of AndroidProducts.mk files.
-#
-# As a side-effect, COMMON_LUNCH_CHOICES will be set to a
-# union of all of the COMMON_LUNCH_CHOICES definitions within
-# each AndroidProducts.mk file.
-#
-define get-product-makefiles
-$(sort \
- $(eval _COMMON_LUNCH_CHOICES :=) \
- $(foreach f,$(1), \
- $(eval PRODUCT_MAKEFILES :=) \
- $(eval COMMON_LUNCH_CHOICES :=) \
- $(eval LOCAL_DIR := $(patsubst %/,%,$(dir $(f)))) \
- $(eval include $(f)) \
- $(call _validate-common-lunch-choices,$(COMMON_LUNCH_CHOICES),$(PRODUCT_MAKEFILES)) \
- $(eval _COMMON_LUNCH_CHOICES += $(COMMON_LUNCH_CHOICES)) \
- $(PRODUCT_MAKEFILES) \
- ) \
- $(eval PRODUCT_MAKEFILES :=) \
- $(eval LOCAL_DIR :=) \
- $(eval COMMON_LUNCH_CHOICES := $(sort $(_COMMON_LUNCH_CHOICES))) \
- $(eval _COMMON_LUNCH_CHOICES :=) \
- )
-endef
-
-#
-# Returns the sorted concatenation of all PRODUCT_MAKEFILES
-# variables set in all AndroidProducts.mk files.
-# $(call ) isn't necessary.
-#
-define get-all-product-makefiles
-$(call get-product-makefiles,$(_find-android-products-files))
-endef
-
# Variables that are meant to hold only a single value.
# - The value set in the current makefile takes precedence over inherited values
# - If multiple inherited makefiles set the var, the first-inherited value wins
@@ -402,6 +310,7 @@
_product_single_value_vars += PRODUCT_BUILD_INIT_BOOT_IMAGE
_product_single_value_vars += PRODUCT_BUILD_DEBUG_BOOT_IMAGE
_product_single_value_vars += PRODUCT_BUILD_VENDOR_BOOT_IMAGE
+_product_single_value_vars += PRODUCT_BUILD_VENDOR_KERNEL_BOOT_IMAGE
_product_single_value_vars += PRODUCT_BUILD_DEBUG_VENDOR_BOOT_IMAGE
_product_single_value_vars += PRODUCT_BUILD_VBMETA_IMAGE
_product_single_value_vars += PRODUCT_BUILD_SUPER_EMPTY_IMAGE
@@ -461,20 +370,13 @@
# "/system/framework/foo.jar" will be "system/framework/foo.jar.fsv_meta".
_product_single_value_vars += PRODUCT_SYSTEM_FSVERITY_GENERATE_METADATA
+# If true, sets the default for MODULE_BUILD_FROM_SOURCE. This overrides
+# BRANCH_DEFAULT_MODULE_BUILD_FROM_SOURCE but not an explicitly set value.
+_product_single_value_vars += PRODUCT_MODULE_BUILD_FROM_SOURCE
+
.KATI_READONLY := _product_single_value_vars _product_list_vars
_product_var_list :=$= $(_product_single_value_vars) $(_product_list_vars)
-define dump-product
-$(warning ==== $(1) ====)\
-$(foreach v,$(_product_var_list),\
-$(warning PRODUCTS.$(1).$(v) := $(call get-product-var,$(1),$(v))))\
-$(warning --------)
-endef
-
-define dump-products
-$(foreach p,$(PRODUCTS),$(call dump-product,$(p)))
-endef
-
#
# Functions for including product makefiles
#
@@ -483,26 +385,27 @@
# $(1): product to inherit
#
# To be called from product makefiles, and is later evaluated during the import-nodes
-# call below. It does three things:
+# call below. It does the following:
# 1. Inherits all of the variables from $1.
# 2. Records the inheritance in the .INHERITS_FROM variable
-# 3. Records the calling makefile in PARENT_PRODUCT_FILES
#
-# (2) and (3) can be used together to reconstruct the include hierarchy
+# (2) and the PRODUCTS variable can be used together to reconstruct the include hierarchy
# See e.g. product-graph.mk for an example of this.
#
define inherit-product
- $(if $(findstring ../,$(1)),\
- $(eval np := $(call normalize-paths,$(1))),\
- $(eval np := $(strip $(1))))\
- $(foreach v,$(_product_var_list), \
- $(eval $(v) := $($(v)) $(INHERIT_TAG)$(np))) \
- $(eval current_mk := $(strip $(word 1,$(_include_stack)))) \
- $(eval inherit_var := PRODUCTS.$(current_mk).INHERITS_FROM) \
- $(eval $(inherit_var) := $(sort $($(inherit_var)) $(np))) \
- $(eval PARENT_PRODUCT_FILES := $(sort $(PARENT_PRODUCT_FILES) $(current_mk))) \
- $(call dump-inherit,$(strip $(word 1,$(_include_stack))),$(1)) \
- $(call dump-config-vals,$(current_mk),inherit)
+ $(eval _inherit_product_wildcard := $(wildcard $(1)))\
+ $(if $(_inherit_product_wildcard),,$(error $(1) does not exist.))\
+ $(foreach part,$(_inherit_product_wildcard),\
+ $(if $(findstring ../,$(part)),\
+ $(eval np := $(call normalize-paths,$(part))),\
+ $(eval np := $(strip $(part))))\
+ $(foreach v,$(_product_var_list), \
+ $(eval $(v) := $($(v)) $(INHERIT_TAG)$(np))) \
+ $(eval current_mk := $(strip $(word 1,$(_include_stack)))) \
+ $(eval inherit_var := PRODUCTS.$(current_mk).INHERITS_FROM) \
+ $(eval $(inherit_var) := $(sort $($(inherit_var)) $(np))) \
+ $(call dump-inherit,$(strip $(word 1,$(_include_stack))),$(1)) \
+ $(call dump-config-vals,$(current_mk),inherit))
endef
# Specifies a number of path prefixes, relative to PRODUCT_OUT, where the
@@ -550,64 +453,18 @@
#
-# Does various consistency checks on all of the known products.
+# Does various consistency checks on the current product.
# Takes no parameters, so $(call ) is not necessary.
#
-define check-all-products
+define check-current-product
$(if ,, \
- $(eval _cap_names :=) \
- $(foreach p,$(PRODUCTS), \
- $(eval pn := $(strip $(PRODUCTS.$(p).PRODUCT_NAME))) \
- $(if $(pn),,$(error $(p): PRODUCT_NAME must be defined.)) \
- $(if $(filter $(pn),$(_cap_names)), \
- $(error $(p): PRODUCT_NAME must be unique; "$(pn)" already used by $(strip \
- $(foreach \
- pp,$(PRODUCTS),
- $(if $(filter $(pn),$(PRODUCTS.$(pp).PRODUCT_NAME)), \
- $(pp) \
- ))) \
- ) \
- ) \
- $(eval _cap_names += $(pn)) \
- $(if $(call is-c-identifier,$(pn)),, \
- $(error $(p): PRODUCT_NAME must be a valid C identifier, not "$(pn)") \
- ) \
- $(eval pb := $(strip $(PRODUCTS.$(p).PRODUCT_BRAND))) \
- $(if $(pb),,$(error $(p): PRODUCT_BRAND must be defined.)) \
- $(foreach cf,$(strip $(PRODUCTS.$(p).PRODUCT_COPY_FILES)), \
- $(if $(filter 2 3,$(words $(subst :,$(space),$(cf)))),, \
- $(error $(p): malformed COPY_FILE "$(cf)") \
- ) \
- ) \
- ) \
-)
-endef
-
-
-#
-# Returns the product makefile path for the product with the provided name
-#
-# $(1): short product name like "generic"
-#
-define _resolve-short-product-name
- $(eval pn := $(strip $(1)))
- $(eval p := \
- $(foreach p,$(PRODUCTS), \
- $(if $(filter $(pn),$(PRODUCTS.$(p).PRODUCT_NAME)), \
- $(p) \
- )) \
- )
- $(eval p := $(sort $(p)))
- $(if $(filter 1,$(words $(p))), \
- $(p), \
- $(if $(filter 0,$(words $(p))), \
- $(error No matches for product "$(pn)"), \
- $(error Product "$(pn)" ambiguous: matches $(p)) \
- ) \
- )
-endef
-define resolve-short-product-name
-$(strip $(call _resolve-short-product-name,$(1)))
+ $(if $(call is-c-identifier,$(PRODUCT_NAME)),, \
+ $(error $(INTERNAL_PRODUCT): PRODUCT_NAME must be a valid C identifier, not "$(pn)")) \
+ $(if $(PRODUCT_BRAND),, \
+ $(error $(INTERNAL_PRODUCT): PRODUCT_BRAND must be defined.)) \
+ $(foreach cf,$(strip $(PRODUCT_COPY_FILES)), \
+ $(if $(filter 2 3,$(words $(subst :,$(space),$(cf)))),, \
+ $(error $(p): malformed COPY_FILE "$(cf)"))))
endef
# BoardConfig variables that are also inherited in product mks. Should ideally
diff --git a/core/product_config.mk b/core/product_config.mk
index 1deb39b..1e74fa9 100644
--- a/core/product_config.mk
+++ b/core/product_config.mk
@@ -146,60 +146,91 @@
include $(BUILD_SYSTEM)/product.mk
include $(BUILD_SYSTEM)/device.mk
-# Read in all of the product definitions specified by the AndroidProducts.mk
-# files in the tree.
-all_product_configs := $(get-all-product-makefiles)
+# Read all product definitions.
+#
+# Products are defined in AndroidProducts.mk files:
+android_products_makefiles := $(file <$(OUT_DIR)/.module_paths/AndroidProducts.mk.list) \
+ $(SRC_TARGET_DIR)/product/AndroidProducts.mk
-all_named_products :=
+# An AndroidProduct.mk file sets the following variables:
+# PRODUCT_MAKEFILES specifies product makefiles. Each item in this list
+# is either a <product>:path/to/file.mk, or just path/to/<product.mk>
+# COMMON_LUNCH_CHOICES specifies <product>-<variant> values to be shown
+# in the `lunch` menu
+# STARLARK_OPT_IN_PRODUCTS specifies products to use Starlark-based
+# product configuration by default
-# Find the product config makefile for the current product.
-# all_product_configs consists items like:
-# <product_name>:<path_to_the_product_makefile>
-# or just <path_to_the_product_makefile> in case the product name is the
-# same as the base filename of the product config makefile.
-current_product_makefile :=
-all_product_makefiles :=
-$(foreach f, $(all_product_configs),\
- $(eval _cpm_words := $(call _decode-product-name,$(f)))\
- $(eval _cpm_word1 := $(word 1,$(_cpm_words)))\
- $(eval _cpm_word2 := $(word 2,$(_cpm_words)))\
- $(eval all_product_makefiles += $(_cpm_word2))\
- $(eval all_named_products += $(_cpm_word1))\
- $(if $(filter $(TARGET_PRODUCT),$(_cpm_word1)),\
- $(eval current_product_makefile += $(_cpm_word2)),))
-_cpm_words :=
-_cpm_word1 :=
-_cpm_word2 :=
-current_product_makefile := $(strip $(current_product_makefile))
-all_product_makefiles := $(strip $(all_product_makefiles))
+# Builds a list of first/second elements of each pair:
+# $(call _first,a:A b:B,:) returns 'a b'
+# $(call _second,a-A b-B,-) returns 'A B'
+_first=$(filter-out $(2)%,$(subst $(2),$(space)$(2),$(1)))
+_second=$(filter-out %$(2),$(subst $(2),$(2)$(space),$(1)))
-load_all_product_makefiles :=
-ifneq (,$(filter product-graph, $(MAKECMDGOALS)))
-ifeq ($(ANDROID_PRODUCT_GRAPH),--all)
-load_all_product_makefiles := true
-endif
-endif
-ifneq (,$(filter dump-products,$(MAKECMDGOALS)))
-ifeq ($(ANDROID_DUMP_PRODUCTS),all)
-load_all_product_makefiles := true
-endif
-endif
+# Returns <product>:<path> pair from a PRODUCT_MAKEFILE item.
+# If an item is <product>:path/to/file.mk, return it as is,
+# otherwise assume that an item is path/to/<product>.mk and
+# return <product>:path/to/<product>.mk
+_product-spec=$(strip $(if $(findstring :,$(1)),$(1),$(basename $(notdir $(1))):$(1)))
+
+# Reads given AndroidProduct.mk file and sets the following variables:
+# ap_product_paths -- the list of <product>:<path> pairs
+# ap_common_lunch_choices -- the list of <product>-<build variant> items
+# ap_products_using_starlark_config -- the list of products using starlark config
+# In addition, validates COMMON_LUNCH_CHOICES and STARLARK_OPT_IN_PRODUCTS values
+define _read-ap-file
+ $(eval PRODUCT_MAKEFILES :=) \
+ $(eval COMMON_LUNCH_CHOICES :=) \
+ $(eval STARLARK_OPT_IN_PRODUCTS := ) \
+ $(eval ap_product_paths :=) \
+ $(eval LOCAL_DIR := $(patsubst %/,%,$(dir $(f)))) \
+ $(eval include $(f)) \
+ $(foreach p, $(PRODUCT_MAKEFILES),$(eval ap_product_paths += $(call _product-spec,$(p)))) \
+ $(eval ap_common_lunch_choices := $(COMMON_LUNCH_CHOICES)) \
+ $(eval ap_products_using_starlark_config := $(STARLARK_OPT_IN_PRODUCTS)) \
+ $(eval _products := $(call _first,$(ap_product_paths),:)) \
+ $(eval _bad := $(filter-out $(_products),$(call _first,$(ap_common_lunch_choices),-))) \
+ $(if $(_bad),$(error COMMON_LUNCH_CHOICES contains products(s) not defined in this file: $(_bad))) \
+ $(eval _bad := $(filter-out %-eng %-userdebug %-user,$(ap_common_lunch_choices))) \
+ $(if $(_bad),$(error invalid variant in COMMON_LUNCH_CHOICES: $(_bad)))
+ $(eval _bad := $(filter-out $(_products),$(ap_products_using_starlark_config))) \
+ $(if $(_bad),$(error STARLARK_OPT_IN_PRODUCTS contains product(s) not defined in this file: $(_bad)))
+endef
+
+# Build cumulative lists of all product specs/lunch choices/Starlark-based products.
+product_paths :=
+common_lunch_choices :=
+products_using_starlark_config :=
+$(foreach f,$(android_products_makefiles), \
+ $(call _read-ap-file,$(f)) \
+ $(eval product_paths += $(ap_product_paths)) \
+ $(eval common_lunch_choices += $(ap_common_lunch_choices)) \
+ $(eval products_using_starlark_config += $(ap_products_using_starlark_config)) \
+)
+
+# Dedup, extract product names, etc.
+product_paths := $(sort $(product_paths))
+all_named_products := $(sort $(call _first,$(product_paths),:))
+all_product_makefiles := $(sort $(call _second,$(product_paths),:))
+current_product_makefile := $(call _second,$(filter $(TARGET_PRODUCT):%,$(product_paths)),:)
+COMMON_LUNCH_CHOICES := $(sort $(common_lunch_choices))
+
+# Check that there are no duplicate product names
+$(foreach p,$(all_named_products), \
+ $(if $(filter 1,$(words $(filter $(p):%,$(product_paths)))),, \
+ $(error Product name must be unique, "$(p)" used by $(call _second,$(filter $(p):%,$(product_paths)),:))))
ifneq ($(ALLOW_RULES_IN_PRODUCT_CONFIG),)
_product_config_saved_KATI_ALLOW_RULES := $(.KATI_ALLOW_RULES)
.KATI_ALLOW_RULES := $(ALLOW_RULES_IN_PRODUCT_CONFIG)
endif
-ifeq ($(load_all_product_makefiles),true)
-# Import all product makefiles.
-$(call import-products, $(all_product_makefiles))
-else
-# Import just the current product.
-ifndef current_product_makefile
-$(error Can not locate config makefile for product "$(TARGET_PRODUCT)")
+ifeq (,$(current_product_makefile))
+ $(error Can not locate config makefile for product "$(TARGET_PRODUCT)")
endif
-ifneq (1,$(words $(current_product_makefile)))
-$(error Product "$(TARGET_PRODUCT)" ambiguous: matches $(current_product_makefile))
+
+ifneq (,$(filter $(TARGET_PRODUCT),$(products_using_starlark_config)))
+ RBC_PRODUCT_CONFIG := true
+ RBC_BOARD_CONFIG := true
endif
ifndef RBC_PRODUCT_CONFIG
@@ -217,49 +248,30 @@
$(error product configuration converter failed: $(.SHELLSTATUS))
endif
include $(OUT_DIR)/rbc/rbc_product_config_results.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),)
+# This step was already handled in the RBC product configuration.
+ifeq ($(RBC_PRODUCT_CONFIG)$(SKIP_ARTIFACT_PATH_REQUIREMENT_PRODUCTS_CHECK),)
# Import all the products that have made artifact path requirements, so that we can verify
-# the artifacts they produce.
-# These are imported after check-all-products because some of them might not be real products.
+# the artifacts they produce. They might be intermediate makefiles instead of real products.
$(foreach makefile,$(ARTIFACT_PATH_REQUIREMENT_PRODUCTS),\
$(if $(filter-out $(makefile),$(PRODUCTS)),$(eval $(call import-products,$(makefile))))\
)
endif
+INTERNAL_PRODUCT := $(current_product_makefile)
+# Strip and assign the PRODUCT_ variables.
+$(call strip-product-vars)
+
+# Quick check
+$(check-current-product)
+
ifneq ($(ALLOW_RULES_IN_PRODUCT_CONFIG),)
.KATI_ALLOW_RULES := $(_saved_KATI_ALLOW_RULES)
_product_config_saved_KATI_ALLOW_RULES :=
endif
-ifneq ($(filter dump-products, $(MAKECMDGOALS)),)
-$(dump-products)
-endif
-
-ifndef RBC_PRODUCT_CONFIG
-# Convert a short name like "sooner" into the path to the product
-# file defining that product.
-#
-INTERNAL_PRODUCT := $(call resolve-short-product-name, $(TARGET_PRODUCT))
-ifneq ($(current_product_makefile),$(INTERNAL_PRODUCT))
-$(error PRODUCT_NAME inconsistent in $(current_product_makefile) and $(INTERNAL_PRODUCT))
-endif
-
-
############################################################################
-# Strip and assign the PRODUCT_ variables.
-$(call strip-product-vars)
-else
-INTERNAL_PRODUCT := $(current_product_makefile)
-endif
current_product_makefile :=
all_product_makefiles :=
diff --git a/core/product_config.rbc b/core/product_config.rbc
index 469b0f7..917475a 100644
--- a/core/product_config.rbc
+++ b/core/product_config.rbc
@@ -70,14 +70,7 @@
def _printvars(state):
"""Prints configuration and global variables."""
- (globals, cfg, globals_base) = state
- for attr, val in sorted(cfg.items()):
- __print_attr(attr, val)
- if _options.print_globals:
- print()
- _printglobals(globals, globals_base)
-
-def _printglobals(globals, globals_base):
+ (globals, globals_base) = state
for attr, val in sorted(globals.items()):
if attr == _soong_config_namespaces_key:
__print_attr("SOONG_CONFIG_NAMESPACES", val.keys())
@@ -127,25 +120,19 @@
globals, globals_base = _init_globals(input_variables_init)
- config_postfix = [] # Configs in postfix order
-
# Each PCM is represented by a quadruple of function, config, children names
# and readyness (that is, the configurations from inherited PCMs have been
# substituted).
configs = {top_pcm_name: (top_pcm, None, [], False)} # All known PCMs
- stash = [] # Configs to push once their descendants are done
-
- # Stack containing PCMs to be processed. An item in the stack
- # is a pair of PCMs name and its height in the product inheritance tree.
- pcm_stack = [(top_pcm_name, 0)]
- pcm_count = 0
+ # Stack containing PCMs to be processed
+ pcm_stack = [top_pcm_name]
# Run it until pcm_stack is exhausted, but no more than N times
for n in range(1000):
if not pcm_stack:
break
- (name, height) = pcm_stack.pop()
+ name = pcm_stack.pop()
pcm, cfg, c, _ = configs[name]
# cfg is set only after PCM has been called, leverage this
@@ -153,9 +140,6 @@
if cfg != None:
continue
- # Push ancestors until we reach this node's height
- config_postfix.extend([stash.pop() for i in range(len(stash) - height)])
-
# Run this one, obtaining its configuration and child PCMs.
if _options.trace_modules:
print("#%d: %s" % (n, name))
@@ -164,39 +148,93 @@
handle = __h_new()
pcm(globals, handle)
+ if handle.artifact_path_requirements:
+ globals["PRODUCTS."+name+".mk.ARTIFACT_PATH_REQUIREMENTS"] = handle.artifact_path_requirements
+ globals["PRODUCTS."+name+".mk.ARTIFACT_PATH_ALLOWED_LIST"] = handle.artifact_path_allowed_list
+ globals["PRODUCTS."+name+".mk.ARTIFACT_PATH_REQUIREMENT_IS_RELAXED"] = "true" if handle.artifact_path_requirement_is_relaxed[0] else ""
+ globals.setdefault("ARTIFACT_PATH_REQUIREMENT_PRODUCTS", [])
+ globals["ARTIFACT_PATH_REQUIREMENT_PRODUCTS"] = sorted(globals["ARTIFACT_PATH_REQUIREMENT_PRODUCTS"] + [name+".mk"])
+
+ if handle.product_enforce_packages_exist[0]:
+ globals["PRODUCTS."+name+".mk.PRODUCT_ENFORCE_PACKAGES_EXIST"] = "true"
+ globals["PRODUCTS."+name+".mk.PRODUCT_ENFORCE_PACKAGES_EXIST_ALLOW_LIST"] = handle.product_enforce_packages_exist_allow_list
+
# Now we know everything about this PCM, record it in 'configs'.
children = handle.inherited_modules
if _options.trace_modules:
print("# ", " ".join(children.keys()))
+ # Starlark dictionaries are guaranteed to iterate through in insertion order,
+ # so children.keys() will be ordered by the inherit() calls
configs[name] = (pcm, handle.cfg, children.keys(), False)
- pcm_count = pcm_count + 1
- if len(children) == 0:
- # Leaf PCM goes straight to the config_postfix
- config_postfix.append(name)
- continue
-
- # Stash this PCM, process children in the sorted order
- stash.append(name)
for child_name in sorted(children, reverse = True):
if child_name not in configs:
configs[child_name] = (children[child_name], None, [], False)
- pcm_stack.append((child_name, len(stash)))
+ pcm_stack.append(child_name)
if pcm_stack:
fail("Inheritance processing took too many iterations")
- # Flush the stash
- config_postfix.extend([stash.pop() for i in range(len(stash))])
- if len(config_postfix) != pcm_count:
- fail("Ran %d modules but postfix tree has only %d entries" % (pcm_count, len(config_postfix)))
+ for pcm_name in globals.get("ARTIFACT_PATH_REQUIREMENT_PRODUCTS", []):
+ for var, val in evaluate_finalized_product_variables(configs, pcm_name[:-3]).items():
+ globals["PRODUCTS."+pcm_name+"."+var] = val
- if _options.trace_modules:
+ # Copy product config variables from the cfg dictionary to the
+ # PRODUCTS.<top_level_makefile_name>.<var_name> global variables.
+ for var, val in evaluate_finalized_product_variables(configs, top_pcm_name, _options.trace_modules).items():
+ globals["PRODUCTS."+top_pcm_name+".mk."+var] = val
+
+ # Record inheritance hierarchy in PRODUCTS.<file>.INHERITS_FROM variables.
+ # This is required for m product-graph.
+ for config in configs:
+ if len(configs[config][2]) > 0:
+ globals["PRODUCTS."+config+".mk.INHERITS_FROM"] = sorted([x + ".mk" for x in configs[config][2]])
+ globals["PRODUCTS"] = __words(globals.get("PRODUCTS", [])) + [top_pcm_name + ".mk"]
+
+ return (globals, globals_base)
+
+def evaluate_finalized_product_variables(configs, top_level_pcm_name, trace=False):
+ configs_postfix = []
+ pcm_stack = [(top_level_pcm_name, True)]
+ for i in range(1000):
+ if not pcm_stack:
+ break
+
+ pcm_name, before = pcm_stack.pop()
+ if before:
+ pcm_stack.append((pcm_name, False))
+ for child in sorted(configs[pcm_name][2], reverse = True):
+ pcm_stack.append((child, True))
+ else:
+ configs_postfix.append(pcm_name)
+ if pcm_stack:
+ fail("Inheritance processing took too many iterations")
+
+ # clone the configs, because in the process of evaluating the
+ # final cfg dictionary we will remove values from the intermediate
+ # cfg dictionaries. We need to be able to call evaluate_finalized_product_variables()
+ # multiple times, so we can't change the origional configs object.
+ cloned_configs = {}
+ for pcm_name in configs:
+ # skip unneeded pcms
+ if pcm_name not in configs_postfix:
+ continue
+ pcm, cfg, children_names, ready = configs[pcm_name]
+ cloned_cfg = {}
+ for var, val in cfg.items():
+ if type(val) == 'list':
+ cloned_cfg[var] = list(val)
+ else:
+ cloned_cfg[var] = val
+ cloned_configs[pcm_name] = (pcm, cloned_cfg, children_names, ready)
+ configs = cloned_configs
+
+ if trace:
print("\n#---Postfix---")
- for x in config_postfix:
+ for x in configs_postfix:
print("# ", x)
# Traverse the tree from the bottom, evaluating inherited values
- for pcm_name in config_postfix:
+ for pcm_name in configs_postfix:
pcm, cfg, children_names, ready = configs[pcm_name]
# Should run
@@ -215,9 +253,7 @@
_substitute_inherited(configs, pcm_name, cfg)
_percolate_inherited(configs, pcm_name, cfg, children_names)
configs[pcm_name] = pcm, cfg, children_names, True
-
- return (globals, configs[top_pcm_name][1], globals_base)
-
+ return configs[top_level_pcm_name][1]
def _dictionary_difference(a, b):
result = {}
@@ -235,7 +271,14 @@
input_variables_init(globals_base, h_base)
input_variables_init(globals, h)
board_config_init(globals, h)
- return (globals, _dictionary_difference(h.cfg, h_base.cfg), globals_base)
+
+ # Board configuration files aren't really supposed to change
+ # product configuration variables, but some do. You lose the
+ # inheritance features of the product config variables if you do.
+ for var, value in _dictionary_difference(h.cfg, h_base.cfg).items():
+ globals[var] = value
+
+ return (globals, globals_base)
def _substitute_inherited(configs, pcm_name, cfg):
@@ -291,9 +334,6 @@
child_cfg = configs[child_name][1]
for attr, value in child_cfg.items():
if type(value) != "list":
- if attr in percolated_attrs or not attr in cfg:
- cfg[attr] = value
- percolated_attrs[attr] = True
continue
if attr in percolated_attrs:
# We already are percolating this one, just add this list
@@ -303,6 +343,19 @@
cfg[attr] = []
__move_items(cfg[attr], child_cfg, attr)
+ # single value variables need to be inherited in alphabetical order,
+ # not in the order of inherit() calls.
+ for child_name in sorted(children_names):
+ child_cfg = configs[child_name][1]
+ for attr, value in child_cfg.items():
+ if type(value) != "list":
+ # Single value variables take the first value available from the leftmost
+ # branch of the tree. If we also had "or attr in percolated_attrs" in this
+ # if statement, it would take the value from the rightmost branch.
+ if cfg.get(attr, "") == "":
+ cfg[attr] = value
+ percolated_attrs[attr] = True
+
for attr in _options.trace_variables:
if attr in percolated_attrs:
print("%s: %s^=%s" % (cfg_name, attr, cfg[attr]))
@@ -382,7 +435,7 @@
def __words(string_or_list):
if type(string_or_list) == "list":
- return string_or_list
+ string_or_list = " ".join(string_or_list)
return _mkstrip(string_or_list).split()
# Handle manipulation functions.
@@ -395,7 +448,12 @@
return struct(
cfg = dict(),
inherited_modules = dict(),
- default_list_value = list()
+ default_list_value = list(),
+ artifact_path_requirements = list(),
+ artifact_path_allowed_list = list(),
+ artifact_path_requirement_is_relaxed = [False], # as a list so that we can reassign it
+ product_enforce_packages_exist = [False],
+ product_enforce_packages_exist_allow_list = [],
)
def __h_cfg(handle):
@@ -460,11 +518,11 @@
# Check that l[0] exists
return [":".join(value)] if rblf_file_exists(value[0]) else []
-def _enforce_product_packages_exist(pkg_string_or_list):
+def _enforce_product_packages_exist(handle, pkg_string_or_list=[]):
"""Makes including non-existent modules in PRODUCT_PACKAGES an error."""
-
- #TODO(asmundak)
- pass
+ handle.product_enforce_packages_exist[0] = True
+ handle.product_enforce_packages_exist_allow_list.clear()
+ handle.product_enforce_packages_exist_allow_list.extend(__words(pkg_string_or_list))
def _add_product_dex_preopt_module_config(handle, modules, config):
"""Equivalent to add-product-dex-preopt-module-config from build/make/core/product.mk."""
@@ -479,8 +537,8 @@
def _find_and_copy(pattern, from_dir, to_dir):
"""Return a copy list for the files matching the pattern."""
- return sorted(["%s/%s:%s/%s" % (
- from_dir, f, to_dir, f) for f in rblf_find_files(from_dir, pattern, only_files=1)])
+ return sorted([("%s/%s:%s/%s" % (from_dir, f, to_dir, f))
+ .replace("//", "/") for f in rblf_find_files(from_dir, pattern, only_files=1)])
def _findstring(needle, haystack):
"""Equivalent to GNU make's $(findstring)."""
@@ -497,10 +555,15 @@
Return:
list of words
"""
- rex = __mk2regex(__words(pattern))
+ patterns = [__mkparse_pattern(x) for x in __words(pattern)]
res = []
for w in __words(text):
- if not _regex_match(rex, w):
+ match = False
+ for p in patterns:
+ if __mkpattern_matches(p, w):
+ match = True
+ break
+ if not match:
res.append(w)
return res
@@ -512,13 +575,22 @@
which stands for any sequence of characters.
text: string or list of words.
"""
- rex = __mk2regex(__words(pattern))
+ patterns = [__mkparse_pattern(x) for x in __words(pattern)]
res = []
for w in __words(text):
- if _regex_match(rex, w):
- res.append(w)
+ for p in patterns:
+ if __mkpattern_matches(p, w):
+ res.append(w)
+ break
return res
+def _dir(paths):
+ """Equivalent to the GNU make function $(dir).
+
+ Returns the folder of the file for each path in paths.
+ """
+ return " ".join([w.rsplit("/",1)[0] for w in __words(paths)])
+
def _notdir(paths):
"""Equivalent to the GNU make function $(notdir).
@@ -526,22 +598,17 @@
"""
return " ".join([__base(w) for w in __words(paths)])
-def __mk2regex(words):
- """Returns regular expression equivalent to Make pattern."""
+def _require_artifacts_in_path(handle, paths, allowed_paths):
+ """Equivalent to require-artifacts-in-path in Make."""
+ handle.artifact_path_requirements.clear()
+ handle.artifact_path_requirements.extend(__words(paths))
+ handle.artifact_path_allowed_list.clear()
+ handle.artifact_path_allowed_list.extend(__words(allowed_paths))
- # TODO(asmundak): this will mishandle '\%'
- return "^(" + "|".join([w.replace("%", ".*", 1) for w in words if w]) + ")$"
-
-def _regex_match(regex, w):
- return rblf_regex(regex, w)
-
-def _require_artifacts_in_path(paths, allowed_paths):
- """TODO."""
- pass
-
-def _require_artifacts_in_path_relaxed(paths, allowed_paths):
- """TODO."""
- pass
+def _require_artifacts_in_path_relaxed(handle, paths, allowed_paths):
+ """Equivalent to require-artifacts-in-path-relaxed in Make."""
+ _require_artifacts_in_path(handle, paths, allowed_paths)
+ handle.artifact_path_requirement_is_relaxed[0] = True
def _expand_wildcard(pattern):
"""Expands shell wildcard pattern."""
@@ -591,7 +658,11 @@
def __mkparse_pattern(pattern):
- """Parses Make's patsubst pattern."""
+ """Parses Make's patsubst pattern.
+
+ This is equivalent to pattern.split('%', 1), except it
+ also takes into account escaping the % symbols.
+ """
in_escape = False
res = []
acc = ""
@@ -611,6 +682,21 @@
res.append(acc)
return res
+def __mkpattern_matches(pattern, word):
+ """Returns if a pattern matches a given word.
+
+ The pattern must be a list of strings of length at most 2.
+ This checks if word is either equal to the pattern or
+ starts/ends with the two parts of the pattern.
+ """
+ if len(pattern) > 2:
+ fail("Pattern can have at most 2 components")
+ elif len(pattern) == 1:
+ return pattern[0]==word
+ else:
+ return ((len(word) >= len(pattern[0])+len(pattern[1]))
+ and word.startswith(pattern[0])
+ and word.endswith(pattern[1]))
def __mkpatsubst_word(parsed_pattern,parsed_subst, word):
(before, after) = parsed_pattern
@@ -632,15 +718,28 @@
$1 in regex terms).
"""
parsed_pattern = __mkparse_pattern(pattern)
- words = s if type(s) == "list" else _mkstrip(s).split(" ")
if len(parsed_pattern) == 1:
- out_words = [ replacement if x == pattern else x for x in words]
+ out_words = [ replacement if x == pattern else x for x in __words(s)]
else:
parsed_replacement = __mkparse_pattern(replacement)
- out_words = [__mkpatsubst_word(parsed_pattern, parsed_replacement, x) for x in words]
+ out_words = [__mkpatsubst_word(parsed_pattern, parsed_replacement, x) for x in __words(s)]
return out_words if type(s) == "list" else " ".join(out_words)
+def _mksort(input):
+ """Emulate Make's sort.
+
+ This is unique from a regular sort in that it also strips
+ the input, and removes duplicate words from the input.
+ """
+ input = sorted(__words(input))
+ result = []
+ for w in input:
+ if len(result) == 0 or result[-1] != w:
+ result.append(w)
+ return result
+
+
def _mkstrip(s):
"""Emulates Make's strip.
@@ -691,7 +790,6 @@
"""Returns struct containing runtime global settings."""
settings = dict(
format = "pretty",
- print_globals = False,
rearrange = "",
trace_modules = False,
trace_variables = [],
@@ -705,7 +803,8 @@
elif x == "pretty" or x == "make":
settings["format"] = x
elif x == "global":
- settings["print_globals"] = True
+ # TODO: Remove this, kept for backwards compatibility
+ pass
elif x != "":
fail("RBC_OUT: got %s, should be one of: [pretty|make] [sort|unique]" % x)
for x in getattr(rblf_cli, "RBC_DEBUG", "").split(","):
@@ -733,6 +832,7 @@
copy_files = _copy_files,
copy_if_exists = _copy_if_exists,
cfg = __h_cfg,
+ dir = _dir,
enforce_product_packages_exist = _enforce_product_packages_exist,
expand_wildcard = _expand_wildcard,
file_exists = rblf_file_exists,
@@ -749,11 +849,11 @@
mkerror = _mkerror,
mkpatsubst = _mkpatsubst,
mkwarning = _mkwarning,
+ mksort = _mksort,
mkstrip = _mkstrip,
mksubst = _mksubst,
notdir = _notdir,
printvars = _printvars,
- printglobals = _printglobals,
product_configuration = _product_configuration,
board_configuration = _board_configuration,
product_copy_files_by_pattern = _product_copy_files_by_pattern,
diff --git a/core/rbe.mk b/core/rbe.mk
index 370d4bd..e399ec1 100644
--- a/core/rbe.mk
+++ b/core/rbe.mk
@@ -14,6 +14,10 @@
# limitations under the License.
#
+JAVAC_NINJA_POOL :=
+R8_NINJA_POOL :=
+D8_NINJA_POOL :=
+
# Notice: this works only with Google's RBE service.
ifneq ($(filter-out false,$(USE_RBE)),)
ifdef RBE_DIR
@@ -84,16 +88,20 @@
ifdef RBE_JAVAC
JAVAC_WRAPPER := $(strip $(JAVAC_WRAPPER) $(RBE_WRAPPER) --labels=type=compile,lang=java,compiler=javac --exec_strategy=$(javac_exec_strategy) --platform=$(java_r8_d8_platform))
+ JAVAC_NINJA_POOL := $(RBE_POOL)
endif
ifdef RBE_R8
R8_WRAPPER := $(strip $(RBE_WRAPPER) --labels=type=compile,compiler=r8 --exec_strategy=$(r8_exec_strategy) --platform=$(java_r8_d8_platform) --inputs=out/soong/host/linux-x86/framework/r8-compat-proguard.jar,build/make/core/proguard_basic_keeps.flags --toolchain_inputs=prebuilts/jdk/jdk11/linux-x86/bin/java)
+ R8_NINJA_POOL := $(RBE_POOL)
endif
ifdef RBE_D8
D8_WRAPPER := $(strip $(RBE_WRAPPER) --labels=type=compile,compiler=d8 --exec_strategy=$(d8_exec_strategy) --platform=$(java_r8_d8_platform) --inputs=out/soong/host/linux-x86/framework/d8.jar --toolchain_inputs=prebuilts/jdk/jdk11/linux-x86/bin/java)
+ D8_NINJA_POOL := $(RBE_POOL)
endif
rbe_dir :=
endif
+.KATI_READONLY := JAVAC_NINJA_POOL R8_NINJA_POOL D8_NINJA_POOL
diff --git a/core/soong_app_prebuilt.mk b/core/soong_app_prebuilt.mk
index 006e1dc..d771d22 100644
--- a/core/soong_app_prebuilt.mk
+++ b/core/soong_app_prebuilt.mk
@@ -100,18 +100,24 @@
endif
ifdef LOCAL_SOONG_PROGUARD_DICT
+ my_proguard_dictionary_directory := $(local-proguard-dictionary-directory)
+ my_proguard_dictionary_mapping_directory := $(local-proguard-dictionary-mapping-directory)
$(eval $(call copy-one-file,$(LOCAL_SOONG_PROGUARD_DICT),\
$(intermediates.COMMON)/proguard_dictionary))
- $(eval $(call copy-one-file,$(LOCAL_SOONG_PROGUARD_DICT),\
- $(call local-packaging-dir,proguard_dictionary)/proguard_dictionary))
+ $(eval $(call copy-r8-dictionary-file-with-mapping,\
+ $(LOCAL_SOONG_PROGUARD_DICT),\
+ $(my_proguard_dictionary_directory)/proguard_dictionary,\
+ $(my_proguard_dictionary_mapping_directory)/proguard_dictionary.textproto))
$(eval $(call copy-one-file,$(LOCAL_SOONG_CLASSES_JAR),\
- $(call local-packaging-dir,proguard_dictionary)/classes.jar))
+ $(my_proguard_dictionary_directory)/classes.jar))
$(call add-dependency,$(LOCAL_BUILT_MODULE),\
$(intermediates.COMMON)/proguard_dictionary)
$(call add-dependency,$(LOCAL_BUILT_MODULE),\
- $(call local-packaging-dir,proguard_dictionary)/proguard_dictionary)
+ $(my_proguard_dictionary_directory)/proguard_dictionary)
$(call add-dependency,$(LOCAL_BUILT_MODULE),\
- $(call local-packaging-dir,proguard_dictionary)/classes.jar)
+ $(my_proguard_dictionary_mapping_directory)/proguard_dictionary.textproto)
+ $(call add-dependency,$(LOCAL_BUILT_MODULE),\
+ $(my_proguard_dictionary_directory)/classes.jar)
endif
ifdef LOCAL_SOONG_PROGUARD_USAGE_ZIP
diff --git a/core/soong_cc_rust_prebuilt.mk b/core/soong_cc_rust_prebuilt.mk
index ca52374..7a177ff 100644
--- a/core/soong_cc_rust_prebuilt.mk
+++ b/core/soong_cc_rust_prebuilt.mk
@@ -184,7 +184,7 @@
# drop /root as /root is mounted as /
my_unstripped_path := $(patsubst $(TARGET_OUT_UNSTRIPPED)/root/%,$(TARGET_OUT_UNSTRIPPED)/%, $(my_unstripped_path))
symbolic_output := $(my_unstripped_path)/$(my_installed_module_stem)
- $(eval $(call copy-one-file,$(LOCAL_SOONG_UNSTRIPPED_BINARY),$(symbolic_output)))
+ $(eval $(call copy-unstripped-elf-file-with-mapping,$(LOCAL_SOONG_UNSTRIPPED_BINARY),$(symbolic_output)))
$(LOCAL_BUILT_MODULE): | $(symbolic_output)
ifeq ($(BREAKPAD_GENERATE_SYMBOLS),true)
diff --git a/core/soong_config.mk b/core/soong_config.mk
index c24df60..32675f2 100644
--- a/core/soong_config.mk
+++ b/core/soong_config.mk
@@ -46,6 +46,7 @@
$(call add_json_bool, Eng, $(filter eng,$(TARGET_BUILD_VARIANT)))
$(call add_json_str, DeviceName, $(TARGET_DEVICE))
+$(call add_json_str, DeviceProduct, $(TARGET_PRODUCT))
$(call add_json_str, DeviceArch, $(TARGET_ARCH))
$(call add_json_str, DeviceArchVariant, $(TARGET_ARCH_VARIANT))
$(call add_json_str, DeviceCpuVariant, $(TARGET_CPU_VARIANT))
@@ -119,6 +120,7 @@
$(call add_json_bool, GcovCoverage, $(filter true,$(NATIVE_COVERAGE)))
$(call add_json_bool, ClangCoverage, $(filter true,$(CLANG_COVERAGE)))
+$(call add_json_bool, ClangCoverageContinuousMode, $(filter true,$(CLANG_COVERAGE_CONTINUOUS_MODE)))
$(call add_json_list, NativeCoveragePaths, $(NATIVE_COVERAGE_PATHS))
$(call add_json_list, NativeCoverageExcludePaths, $(NATIVE_COVERAGE_EXCLUDE_PATHS))
@@ -225,6 +227,8 @@
$(call add_json_list, PackageNameOverrides, $(PRODUCT_PACKAGE_NAME_OVERRIDES))
$(call add_json_list, CertificateOverrides, $(PRODUCT_CERTIFICATE_OVERRIDES))
+$(call add_json_str, ApexGlobalMinSdkVersionOverride, $(APEX_GLOBAL_MIN_SDK_VERSION_OVERRIDE))
+
$(call add_json_bool, EnforceSystemCertificate, $(filter true,$(ENFORCE_SYSTEM_CERTIFICATE)))
$(call add_json_list, EnforceSystemCertificateAllowList, $(ENFORCE_SYSTEM_CERTIFICATE_ALLOW_LIST))
diff --git a/core/soong_droiddoc_prebuilt.mk b/core/soong_droiddoc_prebuilt.mk
index 4dc5d08..ba597c5 100644
--- a/core/soong_droiddoc_prebuilt.mk
+++ b/core/soong_droiddoc_prebuilt.mk
@@ -6,6 +6,7 @@
ifdef LOCAL_DROIDDOC_STUBS_SRCJAR
$(eval $(call copy-one-file,$(LOCAL_DROIDDOC_STUBS_SRCJAR),$(OUT_DOCS)/$(LOCAL_MODULE)-stubs.srcjar))
+$(eval ALL_TARGETS.$(OUT_DOCS)/$(LOCAL_MODULE)-stubs.srcjar.META_LIC := $(LOCAL_SOONG_LICENSE_METADATA))
ALL_DOCS += $(OUT_DOCS)/$(LOCAL_MODULE)-stubs.srcjar
.PHONY: $(LOCAL_MODULE)
@@ -14,6 +15,7 @@
ifdef LOCAL_DROIDDOC_DOC_ZIP
$(eval $(call copy-one-file,$(LOCAL_DROIDDOC_DOC_ZIP),$(OUT_DOCS)/$(LOCAL_MODULE)-docs.zip))
+$(eval ALL_TARGETS.$(OUT_DOCS)/$(LOCAL_MODULE)-docs.zip.META_LIC := $(LOCAL_SOONG_LICENSE_METADATA))
$(call dist-for-goals,docs,$(OUT_DOCS)/$(LOCAL_MODULE)-docs.zip)
.PHONY: $(LOCAL_MODULE) $(LOCAL_MODULE)-docs.zip
@@ -23,12 +25,15 @@
ifdef LOCAL_DROIDDOC_ANNOTATIONS_ZIP
$(eval $(call copy-one-file,$(LOCAL_DROIDDOC_ANNOTATIONS_ZIP),$(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING/$(LOCAL_MODULE)_annotations.zip))
+$(eval ALL_TARGETS.$(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING/$(LOCAL_MODULE)_annotations.zip.META_LIC := $(LOCAL_SOONG_LICENSE_METADATA))
endif
ifdef LOCAL_DROIDDOC_API_VERSIONS_XML
$(eval $(call copy-one-file,$(LOCAL_DROIDDOC_API_VERSIONS_XML),$(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING/$(LOCAL_MODULE)_generated-api-versions.xml))
+$(eval ALL_TARGETS.$(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING/$(LOCAL_MODULE)_generated-api-versions.xml.META_LIC := $(LOCAL_SOONG_LICENSE_METADATA))
endif
ifdef LOCAL_DROIDDOC_METADATA_ZIP
$(eval $(call copy-one-file,$(LOCAL_DROIDDOC_METADATA_ZIP),$(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING/$(LOCAL_MODULE)-metadata.zip))
+$(eval ALL_TARGETS.$(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING/$(LOCAL_MODULE)-metadata.zip.META_LIC := $(LOCAL_SOONG_LICENSE_METADATA))
endif
diff --git a/core/soong_java_prebuilt.mk b/core/soong_java_prebuilt.mk
index b819cdc..a8f475f 100644
--- a/core/soong_java_prebuilt.mk
+++ b/core/soong_java_prebuilt.mk
@@ -62,18 +62,24 @@
endif
ifdef LOCAL_SOONG_PROGUARD_DICT
+ my_proguard_dictionary_directory := $(local-proguard-dictionary-directory)
+ my_proguard_dictionary_mapping_directory := $(local-proguard-dictionary-mapping-directory)
$(eval $(call copy-one-file,$(LOCAL_SOONG_PROGUARD_DICT),\
$(intermediates.COMMON)/proguard_dictionary))
- $(eval $(call copy-one-file,$(LOCAL_SOONG_PROGUARD_DICT),\
- $(call local-packaging-dir,proguard_dictionary)/proguard_dictionary))
+ $(eval $(call copy-r8-dictionary-file-with-mapping,\
+ $(LOCAL_SOONG_PROGUARD_DICT),\
+ $(my_proguard_dictionary_directory)/proguard_dictionary,\
+ $(my_proguard_dictionary_mapping_directory)/proguard_dictionary.textproto))
$(eval $(call copy-one-file,$(LOCAL_SOONG_CLASSES_JAR),\
- $(call local-packaging-dir,proguard_dictionary)/classes.jar))
+ $(my_proguard_dictionary_directory)/classes.jar))
$(call add-dependency,$(common_javalib.jar),\
$(intermediates.COMMON)/proguard_dictionary)
$(call add-dependency,$(common_javalib.jar),\
- $(call local-packaging-dir,proguard_dictionary)/proguard_dictionary)
+ $(my_proguard_dictionary_directory)/proguard_dictionary)
$(call add-dependency,$(common_javalib.jar),\
- $(call local-packaging-dir,proguard_dictionary)/classes.jar)
+ $(my_proguard_dictionary_mapping_directory)/proguard_dictionary.textproto)
+ $(call add-dependency,$(common_javalib.jar),\
+ $(my_proguard_dictionary_directory)/classes.jar)
endif
ifdef LOCAL_SOONG_PROGUARD_USAGE_ZIP
diff --git a/core/sysprop.mk b/core/sysprop.mk
index 43b8953..61c07ba 100644
--- a/core/sysprop.mk
+++ b/core/sysprop.mk
@@ -128,6 +128,8 @@
cat $(file) >> $$@;\
fi;)
$(hide) echo "# end of file" >> $$@
+
+$(call declare-0p-target,$(2))
endef
# -----------------------------------------------------------------
@@ -319,6 +321,8 @@
$(empty),\
$(empty)))
+$(eval $(call declare-1p-target,$(INSTALLED_BUILD_PROP_TARGET)))
+
# -----------------------------------------------------------------
# vendor/build.prop
#
@@ -357,6 +361,8 @@
$(empty),\
$(empty)))
+$(eval $(call declare-1p-target,$(INSTALLED_VENDOR_BUILD_PROP_TARGET)))
+
# -----------------------------------------------------------------
# product/etc/build.prop
#
@@ -409,6 +415,8 @@
$(_footers_),\
$(_skip_common_properties)))
+$(eval $(call declare-1p-target,$(INSTALLED_PRODUCT_BUILD_PROP_TARGET)))
+
_skip_common_properties :=
# ----------------------------------------------------------------
@@ -434,6 +442,8 @@
$(empty),\
$(empty)))
+$(eval $(call declare-1p-target,$(INSTALLED_ODM_BUILD_PROP_TARGET)))
+
# ----------------------------------------------------------------
# vendor_dlkm/etc/build.prop
#
@@ -448,6 +458,8 @@
$(empty),\
$(empty)))
+$(eval $(call declare-1p-target,$(INSTALLED_VENDOR_DLKM_BUILD_PROP_TARGET)))
+
# ----------------------------------------------------------------
# odm_dlkm/etc/build.prop
#
@@ -462,6 +474,8 @@
$(empty),\
$(empty)))
+$(eval $(call declare-1p-target,$(INSTALLED_ODM_DLKM_BUILD_PROP_TARGET)))
+
# ----------------------------------------------------------------
# system_dlkm/build.prop
#
@@ -476,6 +490,8 @@
$(empty),\
$(empty)))
+$(eval $(call declare-1p-target,$(INSTALLED_SYSTEM_DLKM_BUILD_PROP_TARGET)))
+
# -----------------------------------------------------------------
# system_ext/etc/build.prop
#
@@ -497,6 +513,8 @@
$(empty),\
$(empty)))
+$(eval $(call declare-1p-target,$(INSTALLED_SYSTEM_EXT_BUILD_PROP_TARGET)))
+
# ----------------------------------------------------------------
# ramdisk/boot/etc/build.prop
#
@@ -511,3 +529,5 @@
$(empty),\
$(empty),\
$(empty)))
+
+$(eval $(call declare-1p-target,$(INSTALLED_RAMDISK_BUILD_PROP_TARGET)))
diff --git a/core/tasks/art-host-tests.mk b/core/tasks/art-host-tests.mk
index b9a349d..2af1ded 100644
--- a/core/tasks/art-host-tests.mk
+++ b/core/tasks/art-host-tests.mk
@@ -42,4 +42,7 @@
art-host-tests: $(art_host_tests_zip)
$(call dist-for-goals, art-host-tests, $(art_host_tests_zip))
+$(call declare-1p-container,$(art_host_tests_zip),)
+$(call declare-container-license-deps,$(art_host_tests_zip),$(COMPATIBILITY.art-host-tests.FILES) $(my_host_shared_lib_for_art_host_tests),$(PRODUCT_OUT)/:/)
+
tests: art-host-tests
diff --git a/core/tasks/cts.mk b/core/tasks/cts.mk
index 876d77a..c282268 100644
--- a/core/tasks/cts.mk
+++ b/core/tasks/cts.mk
@@ -17,6 +17,9 @@
test_suite_dynamic_config := cts/tools/cts-tradefed/DynamicConfig.xml
test_suite_readme := cts/tools/cts-tradefed/README
+$(call declare-1p-target,$(test_suite_dynamic_config),cts)
+$(call declare-1p-target,$(test_suite_readme),cts)
+
include $(BUILD_SYSTEM)/tasks/tools/compatibility.mk
.PHONY: cts
@@ -195,6 +198,13 @@
$(call dist-for-goals, cts-api-coverage, $(cts-combined-coverage-report):cts-combined-coverage-report.html)
$(call dist-for-goals, cts-api-coverage, $(cts-combined-xml-coverage-report):cts-combined-coverage-report.xml)
+ALL_TARGETS.$(cts-test-coverage-report).META_LIC:=$(module_license_metadata)
+ALL_TARGETS.$(cts-system-api-coverage-report).META_LIC:=$(module_license_metadata)
+ALL_TARGETS.$(cts-system-api-xml-coverage-report).META_LIC:=$(module_license_metadata)
+ALL_TARGETS.$(cts-verifier-coverage-report).META_LIC:=$(module_license_metadata)
+ALL_TARGETS.$(cts-combined-coverage-report).META_LIC:=$(module_license_metadata)
+ALL_TARGETS.$(cts-combined-xml-coverage-report).META_LIC:=$(module_license_metadata)
+
# Arguments;
# 1 - Name of the report printed out on the screen
# 2 - List of apk files that will be scanned to generate the report
diff --git a/core/tasks/device-tests.mk b/core/tasks/device-tests.mk
index 73fad7c..3196f52 100644
--- a/core/tasks/device-tests.mk
+++ b/core/tasks/device-tests.mk
@@ -55,4 +55,7 @@
device-tests: $(device-tests-zip)
$(call dist-for-goals, device-tests, $(device-tests-zip) $(device-tests-list-zip) $(device-tests-configs-zip) $(device_tests_host_shared_libs_zip))
+$(call declare-1p-container,$(device-tests-zip),)
+$(call declare-container-license-deps,$(device-tests-zip),$(COMPATIBILITY.device-tests.FILES) $(my_host_shared_lib_for_device_tests),$(PRODUCT_OUT)/:/)
+
tests: device-tests
diff --git a/core/tasks/find-shareduid-violation.mk b/core/tasks/find-shareduid-violation.mk
index d6885eb..b5feef1 100644
--- a/core/tasks/find-shareduid-violation.mk
+++ b/core/tasks/find-shareduid-violation.mk
@@ -35,4 +35,5 @@
--copy_out_system_ext $(TARGET_COPY_OUT_SYSTEM_EXT) \
> $@
+$(call declare-0p-target,$(shareduid_violation_modules_filename))
$(call dist-for-goals,droidcore,$(shareduid_violation_modules_filename))
diff --git a/core/tasks/general-tests.mk b/core/tasks/general-tests.mk
index a820a28..5252394 100644
--- a/core/tasks/general-tests.mk
+++ b/core/tasks/general-tests.mk
@@ -40,6 +40,18 @@
# Create an artifact to include all shared librariy files in general-tests.
general_tests_host_shared_libs_zip := $(PRODUCT_OUT)/general-tests_host-shared-libs.zip
+# Copy kernel test modules to testcases directories
+include $(BUILD_SYSTEM)/tasks/tools/vts-kernel-tests.mk
+kernel_test_copy_pairs := \
+ $(call target-native-copy-pairs,$(kernel_test_modules),$(kernel_test_host_out))
+copy_kernel_tests := $(call copy-many-files,$(kernel_test_copy_pairs))
+
+# PHONY target to be used to build and test `vts_kernel_tests` without building full vts
+.PHONY: vts_kernel_tests
+vts_kernel_tests: $(copy_kernel_tests)
+
+$(general_tests_zip) : $(copy_kernel_tests)
+$(general_tests_zip) : PRIVATE_KERNEL_TEST_HOST_OUT := $(kernel_test_host_out)
$(general_tests_zip) : PRIVATE_general_tests_list_zip := $(general_tests_list_zip)
$(general_tests_zip) : .KATI_IMPLICIT_OUTPUTS := $(general_tests_list_zip) $(general_tests_configs_zip) $(general_tests_host_shared_libs_zip)
$(general_tests_zip) : PRIVATE_TOOLS := $(general_tests_tools)
@@ -52,6 +64,7 @@
rm -f $@ $(PRIVATE_general_tests_list_zip)
mkdir -p $(PRIVATE_INTERMEDIATES_DIR) $(PRIVATE_INTERMEDIATES_DIR)/tools
echo $(sort $(COMPATIBILITY.general-tests.FILES)) | tr " " "\n" > $(PRIVATE_INTERMEDIATES_DIR)/list
+ find $(PRIVATE_KERNEL_TEST_HOST_OUT) >> $(PRIVATE_INTERMEDIATES_DIR)/list
grep $(HOST_OUT_TESTCASES) $(PRIVATE_INTERMEDIATES_DIR)/list > $(PRIVATE_INTERMEDIATES_DIR)/host.list || true
grep $(TARGET_OUT_TESTCASES) $(PRIVATE_INTERMEDIATES_DIR)/list > $(PRIVATE_INTERMEDIATES_DIR)/target.list || true
grep -e .*\\.config$$ $(PRIVATE_INTERMEDIATES_DIR)/host.list > $(PRIVATE_INTERMEDIATES_DIR)/host-test-configs.list || true
@@ -78,6 +91,9 @@
general-tests: $(general_tests_zip)
$(call dist-for-goals, general-tests, $(general_tests_zip) $(general_tests_list_zip) $(general_tests_configs_zip) $(general_tests_host_shared_libs_zip))
+$(call declare-1p-container,$(general_tests_zip),)
+$(call declare-container-license-deps,$(general_tests_zip),$(COMPATIBILITY.general-tests.FILES) $(general_tests_tools) $(my_host_shared_lib_for_general_tests),$(PRODUCT_OUT)/:/)
+
intermediates_dir :=
general_tests_tools :=
general_tests_zip :=
diff --git a/core/tasks/host-unit-tests.mk b/core/tasks/host-unit-tests.mk
index 755b589..ed2f2a6 100644
--- a/core/tasks/host-unit-tests.mk
+++ b/core/tasks/host-unit-tests.mk
@@ -47,4 +47,7 @@
host-unit-tests: $(host_unit_tests_zip)
$(call dist-for-goals, host-unit-tests, $(host_unit_tests_zip))
+$(call declare-1p-container,$(host_unit_tests_zip),)
+$(call declare-container-license-deps,$(host_unit_tests_zip),$(COMPATIBILITY.host-unit-tests.FILES) $(my_host_shared_lib_for_host_unit_tests),$(PRODUCT_OUT)/:/)
+
tests: host-unit-tests
diff --git a/core/tasks/oem_image.mk b/core/tasks/oem_image.mk
index a847b9d..134be01 100644
--- a/core/tasks/oem_image.mk
+++ b/core/tasks/oem_image.mk
@@ -43,4 +43,7 @@
oem_image : $(INSTALLED_OEMIMAGE_TARGET)
$(call dist-for-goals, oem_image, $(INSTALLED_OEMIMAGE_TARGET))
+$(call declare-1p-container,$(INSTALLED_OEMIMAGE_TARGET),)
+$(call declare-container-license-deps,$(INSTALLED_OEMIMAGE_TARGET),$(INTERNAL_USERIMAGE_DEPS) $(INTERNAL_OEMIMAGE_FILES),$(INSTALLED_OEMIMAGE_TARGET):)
+
endif # oem_image in $(MAKECMDGOALS)
diff --git a/core/tasks/owners.mk b/core/tasks/owners.mk
index 6f32aaf..806b8ee 100644
--- a/core/tasks/owners.mk
+++ b/core/tasks/owners.mk
@@ -31,3 +31,5 @@
owners : $(owners_zip)
$(call dist-for-goals, general-tests, $(owners_zip))
+
+$(call declare-0p-target,$(owners_zip))
diff --git a/core/tasks/test_mapping.mk b/core/tasks/test_mapping.mk
index da64cab..0b0c93c 100644
--- a/core/tasks/test_mapping.mk
+++ b/core/tasks/test_mapping.mk
@@ -36,3 +36,5 @@
test_mapping : $(test_mappings_zip)
$(call dist-for-goals, dist_files test_mapping,$(test_mappings_zip))
+
+$(call declare-1p-target,$(test_mappings_zip),)
diff --git a/core/tasks/tools/compatibility.mk b/core/tasks/tools/compatibility.mk
index 47cf440..add580d 100644
--- a/core/tasks/tools/compatibility.mk
+++ b/core/tasks/tools/compatibility.mk
@@ -40,6 +40,8 @@
$(HOST_OUT_EXECUTABLES)/$(test_suite_tradefed) \
$(test_suite_readme)
+$(foreach f,$(test_suite_readme),$(if $(strip $(ALL_TARGETS.$(f).META_LIC)),,$(eval ALL_TARGETS.$(f).META_LIC := $(module_license_metadata))))
+
test_tools += $(test_suite_tools)
# The JDK to package into the test suite zip file. Always package the linux JDK.
@@ -51,9 +53,24 @@
$(test_suite_jdk): $(SOONG_ZIP)
$(SOONG_ZIP) -o $@ -P $(PRIVATE_SUBDIR)/jdk -C $(PRIVATE_JDK_DIR) -D $(PRIVATE_JDK_DIR)
+$(call declare-license-metadata,$(test_suite_jdk),SPDX-license-identifier-GPL-2.0-with-classpath-exception,restricted,\
+ $(test_suite_jdk_dir)/legal/java.base/LICENSE,JDK,prebuilts/jdk/$(notdir $(patsubst %/,%,$(dir $(test_suite_jdk_dir)))))
+
+
# Include host shared libraries
host_shared_libs := $(call copy-many-files, $(COMPATIBILITY.$(test_suite_name).HOST_SHARED_LIBRARY.FILES))
+$(if $(strip $(host_shared_libs)),\
+ $(foreach p,$(COMPATIBILITY.$(test_suite_name).HOST_SHARED_LIBRARY.FILES),\
+ $(eval _src := $(call word-colon,1,$(p)))\
+ $(eval _dst := $(call word-colon,2,$(p)))\
+ $(if $(strip $(ALL_TARGETS.$(_src).META_LIC)),\
+ $(eval ALL_TARGETS.$(_dst).META_LIC := $(ALL_TARGETS.$(_src).META_LIC)),\
+ $(warning $(_src) has no license metadata for $(_dst))\
+ )\
+ )\
+)
+
compatibility_zip_deps := \
$(test_artifacts) \
$(test_tools) \
@@ -63,6 +80,7 @@
$(MERGE_ZIPS) \
$(SOONG_ZIP) \
$(host_shared_libs) \
+ $(test_suite_extra_deps) \
compatibility_zip_resources := $(out_dir)/tools $(out_dir)/testcases $(out_dir)/lib $(out_dir)/lib64
@@ -70,13 +88,6 @@
test_suite_notice_txt := $(out_dir)/NOTICE.txt
test_suite_notice_html := $(out_dir)/NOTICE.html
-$(eval $(call combine-notice-files, html, \
- $(test_suite_notice_txt), \
- $(test_suite_notice_html), \
- "Notices for files contained in the test suites filesystem image in this directory:", \
- $(HOST_OUT_NOTICE_FILES) $(TARGET_OUT_NOTICE_FILES), \
- $(compatibility_zip_deps)))
-
compatibility_zip_deps += $(test_suite_notice_txt)
compatibility_zip_resources += $(test_suite_notice_txt)
@@ -110,6 +121,17 @@
$(SOONG_ZIP) -d -o $(PRIVATE_tests_list_zip) -j -f $(PRIVATE_tests_list)
rm -f $(PRIVATE_tests_list)
+$(call declare-0p-target,$(compatibility_tests_list_zip),)
+
+$(call declare-1p-container,$(compatibility_zip),)
+$(call declare-container-license-deps,$(compatibility_zip),$(compatibility_zip_deps) $(test_suite_jdk), $(out_dir)/:/)
+
+$(eval $(call html-notice-rule,$(test_suite_notice_html),"Test suites","Notices for files contained in the test suites filesystem image:",$(compatibility_zip),$(compatibility_zip)))
+$(eval $(call text-notice-rule,$(test_suite_notice_txt),"Test suites","Notices for files contained in the test suites filesystem image:",$(compatibility_zip),$(compatibility_zip)))
+
+$(call declare-0p-target,$(test_suite_notice_html))
+$(call declare-0p-target,$(test_suite_notice_txt))
+
# Reset all input variables
test_suite_name :=
test_suite_tradefed :=
@@ -120,3 +142,4 @@
test_suite_jdk :=
test_suite_jdk_dir :=
host_shared_libs :=
+test_suite_extra_deps :=
diff --git a/core/tasks/tools/vts-kernel-tests.mk b/core/tasks/tools/vts-kernel-tests.mk
new file mode 100644
index 0000000..5fbb589
--- /dev/null
+++ b/core/tasks/tools/vts-kernel-tests.mk
@@ -0,0 +1,26 @@
+# Copyright (C) 2022 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.
+
+-include external/linux-kselftest/android/kselftest_test_list.mk
+-include external/ltp/android/ltp_package_list.mk
+
+include $(BUILD_SYSTEM)/tasks/tools/vts_package_utils.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
+kernel_test_modules := \
+ $(kselftest_modules) \
+ ltp \
+ $(ltp_packages)
\ No newline at end of file
diff --git a/core/tasks/tools/vts_package_utils.mk b/core/tasks/tools/vts_package_utils.mk
index 47bf29c..f1159b3 100644
--- a/core/tasks/tools/vts_package_utils.mk
+++ b/core/tasks/tools/vts_package_utils.mk
@@ -29,5 +29,6 @@
$(eval my_copy_dest := $(patsubst data/%,DATA/%,\
$(patsubst system/%,DATA/%,\
$(patsubst $(PRODUCT_OUT)/%,%,$(ins)))))\
+ $(eval ALL_TARGETS.$(2)/$(my_copy_dest).META_LIC := $(if $(strip $(ALL_MODULES.$(m).META_LIC)),$(ALL_MODULES.$(m).META_LIC),$(ALL_MODULES.$(m).DELAYED_META_LIC)))\
$(bui):$(2)/$(my_copy_dest))))
endef
diff --git a/core/tasks/tradefed-tests-list.mk b/core/tasks/tradefed-tests-list.mk
index bcbdfcf..61bf136 100644
--- a/core/tasks/tradefed-tests-list.mk
+++ b/core/tasks/tradefed-tests-list.mk
@@ -35,4 +35,6 @@
tradefed-tests-list : $(tradefed_tests_list_zip)
$(call dist-for-goals, tradefed-tests-list, $(tradefed_tests_list_zip))
+$(call declare-1p-target,$(tradefed_tests_list_zip),)
+
tests: tradefed-tests-list
diff --git a/core/tasks/vts-core-tests.mk b/core/tasks/vts-core-tests.mk
index 3c838b5..5e1b5d5 100644
--- a/core/tasks/vts-core-tests.mk
+++ b/core/tasks/vts-core-tests.mk
@@ -12,37 +12,21 @@
# 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
-
-include $(BUILD_SYSTEM)/tasks/tools/vts_package_utils.mk
-
test_suite_name := vts
test_suite_tradefed := vts-tradefed
test_suite_readme := test/vts/tools/vts-core-tradefed/README
-# 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
-kernel_test_modules := \
- $(kselftest_modules) \
- ltp \
- $(ltp_packages)
+include $(BUILD_SYSTEM)/tasks/tools/vts-kernel-tests.mk
kernel_test_copy_pairs := \
- $(call target-native-copy-pairs,$(kernel_test_modules),$(kernel_test_vts_out)) \
- $(call target-native-copy-pairs,$(kernel_test_modules),$(kernel_test_host_out))
+ $(call target-native-copy-pairs,$(kernel_test_modules),$(kernel_test_vts_out))
copy_kernel_tests := $(call copy-many-files,$(kernel_test_copy_pairs))
-# PHONY target to be used to build and test `vts_kernel_tests` without building full vts
-.PHONY: vts_kernel_tests
-vts_kernel_tests: $(copy_kernel_tests)
+test_suite_extra_deps := $(copy_kernel_tests)
include $(BUILD_SYSTEM)/tasks/tools/compatibility.mk
-$(compatibility_zip): $(copy_kernel_tests)
-
.PHONY: vts
vts: $(compatibility_zip) $(compatibility_tests_list_zip)
$(call dist-for-goals, vts, $(compatibility_zip) $(compatibility_tests_list_zip))
diff --git a/core/tasks/with-license.mk b/core/tasks/with-license.mk
index 469ad76..d41e77a 100644
--- a/core/tasks/with-license.mk
+++ b/core/tasks/with-license.mk
@@ -37,6 +37,10 @@
RADIO/bootloader.img:bootloader.img RADIO/radio.img:radio.img \
IMAGES/*.img:. OTA/android-info.txt:android-info.txt
endif
+
+$(call declare-1p-container,$(license_image_input_zip),build)
+$(call declare-container-deps,$(license_image_input_zip),$(BUILT_TARGET_FILES_PACKAGE))
+
with_license_zip := $(PRODUCT_OUT)/$(name).sh
$(with_license_zip): PRIVATE_NAME := $(name)
$(with_license_zip): PRIVATE_INPUT_ZIP := $(license_image_input_zip)
@@ -48,3 +52,7 @@
$(PRIVATE_INPUT_ZIP) $(PRIVATE_NAME) $(PRIVATE_VENDOR_BLOBS_LICENSE)
with-license : $(with_license_zip)
$(call dist-for-goals, with-license, $(with_license_zip))
+
+$(call declare-1p-container,$(with_license_zip),)
+$(call declare-container-license-deps,$(with_license_zip),$(license_image_input_zip),$(with_license_zip):)
+
diff --git a/core/version_defaults.mk b/core/version_defaults.mk
index f19e841..c8b381d 100644
--- a/core/version_defaults.mk
+++ b/core/version_defaults.mk
@@ -73,7 +73,7 @@
# When you increment the PLATFORM_SDK_VERSION please ensure you also
# clear out the following text file of all older PLATFORM_VERSION's:
# cts/tests/tests/os/assets/platform_versions.txt
- PLATFORM_SDK_VERSION := 31
+ PLATFORM_SDK_VERSION := 32
endif
.KATI_READONLY := PLATFORM_SDK_VERSION
@@ -98,7 +98,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 := 2022-02-05
+ PLATFORM_SECURITY_PATCH := 2022-04-05
endif
.KATI_READONLY := PLATFORM_SECURITY_PATCH
diff --git a/envsetup.sh b/envsetup.sh
index 87e6e0a..e7b8538 100644
--- a/envsetup.sh
+++ b/envsetup.sh
@@ -425,6 +425,61 @@
complete -F _complete_android_module_names m
}
+function multitree_lunch_help()
+{
+ echo "usage: lunch PRODUCT-VARIANT" 1>&2
+ echo " Set up android build environment based on a product short name and variant" 1>&2
+ echo 1>&2
+ echo "lunch COMBO_FILE VARIANT" 1>&2
+ echo " Set up android build environment based on a specific lunch combo file" 1>&2
+ echo " and variant." 1>&2
+ echo 1>&2
+ echo "lunch --print [CONFIG]" 1>&2
+ echo " Print the contents of a configuration. If CONFIG is supplied, that config" 1>&2
+ echo " will be flattened and printed. If CONFIG is not supplied, the currently" 1>&2
+ echo " selected config will be printed. Returns 0 on success or nonzero on error." 1>&2
+ echo 1>&2
+ echo "lunch --list" 1>&2
+ echo " List all possible combo files available in the current tree" 1>&2
+ echo 1>&2
+ echo "lunch --help" 1>&2
+ echo "lunch -h" 1>&2
+ echo " Prints this message." 1>&2
+}
+
+function multitree_lunch()
+{
+ local code
+ local results
+ if $(echo "$1" | grep -q '^-') ; then
+ # Calls starting with a -- argument are passed directly and the function
+ # returns with the lunch.py exit code.
+ build/make/orchestrator/core/lunch.py "$@"
+ code=$?
+ if [[ $code -eq 2 ]] ; then
+ echo 1>&2
+ multitree_lunch_help
+ return $code
+ elif [[ $code -ne 0 ]] ; then
+ return $code
+ fi
+ else
+ # All other calls go through the --lunch variant of lunch.py
+ results=($(build/make/orchestrator/core/lunch.py --lunch "$@"))
+ code=$?
+ if [[ $code -eq 2 ]] ; then
+ echo 1>&2
+ multitree_lunch_help
+ return $code
+ elif [[ $code -ne 0 ]] ; then
+ return $code
+ fi
+
+ export TARGET_BUILD_COMBO=${results[0]}
+ export TARGET_BUILD_VARIANT=${results[1]}
+ fi
+}
+
function choosetype()
{
echo "Build type choices are:"
diff --git a/orchestrator/core/lunch.py b/orchestrator/core/lunch.py
new file mode 100755
index 0000000..35dac73
--- /dev/null
+++ b/orchestrator/core/lunch.py
@@ -0,0 +1,329 @@
+#!/usr/bin/python3
+#
+# Copyright (C) 2022 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 argparse
+import glob
+import json
+import os
+import sys
+
+EXIT_STATUS_OK = 0
+EXIT_STATUS_ERROR = 1
+EXIT_STATUS_NEED_HELP = 2
+
+def FindDirs(path, name, ttl=6):
+ """Search at most ttl directories deep inside path for a directory called name."""
+ # The dance with subdirs is so that we recurse in sorted order.
+ subdirs = []
+ with os.scandir(path) as it:
+ for dirent in sorted(it, key=lambda x: x.name):
+ try:
+ if dirent.is_dir():
+ if dirent.name == name:
+ yield os.path.join(path, dirent.name)
+ elif ttl > 0:
+ subdirs.append(dirent.name)
+ except OSError:
+ # Consume filesystem errors, e.g. too many links, permission etc.
+ pass
+ for subdir in subdirs:
+ yield from FindDirs(os.path.join(path, subdir), name, ttl-1)
+
+
+def WalkPaths(path, matcher, ttl=10):
+ """Do a traversal of all files under path yielding each file that matches
+ matcher."""
+ # First look for files, then recurse into directories as needed.
+ # The dance with subdirs is so that we recurse in sorted order.
+ subdirs = []
+ with os.scandir(path) as it:
+ for dirent in sorted(it, key=lambda x: x.name):
+ try:
+ if dirent.is_file():
+ if matcher(dirent.name):
+ yield os.path.join(path, dirent.name)
+ if dirent.is_dir():
+ if ttl > 0:
+ subdirs.append(dirent.name)
+ except OSError:
+ # Consume filesystem errors, e.g. too many links, permission etc.
+ pass
+ for subdir in sorted(subdirs):
+ yield from WalkPaths(os.path.join(path, subdir), matcher, ttl-1)
+
+
+def FindFile(path, filename):
+ """Return a file called filename inside path, no more than ttl levels deep.
+
+ Directories are searched alphabetically.
+ """
+ for f in WalkPaths(path, lambda x: x == filename):
+ return f
+
+
+def FindConfigDirs(workspace_root):
+ """Find the configuration files in the well known locations inside workspace_root
+
+ <workspace_root>/build/orchestrator/multitree_combos
+ (AOSP devices, such as cuttlefish)
+
+ <workspace_root>/vendor/**/multitree_combos
+ (specific to a vendor and not open sourced)
+
+ <workspace_root>/device/**/multitree_combos
+ (specific to a vendor and are open sourced)
+
+ Directories are returned specifically in this order, so that aosp can't be
+ overridden, but vendor overrides device.
+ """
+
+ # TODO: When orchestrator is in its own git project remove the "make/" here
+ yield os.path.join(workspace_root, "build/make/orchestrator/multitree_combos")
+
+ dirs = ["vendor", "device"]
+ for d in dirs:
+ yield from FindDirs(os.path.join(workspace_root, d), "multitree_combos")
+
+
+def FindNamedConfig(workspace_root, shortname):
+ """Find the config with the given shortname inside workspace_root.
+
+ Config directories are searched in the order described in FindConfigDirs,
+ and inside those directories, alphabetically."""
+ filename = shortname + ".mcombo"
+ for config_dir in FindConfigDirs(workspace_root):
+ found = FindFile(config_dir, filename)
+ if found:
+ return found
+ return None
+
+
+def ParseProductVariant(s):
+ """Split a PRODUCT-VARIANT name, or return None if it doesn't match that pattern."""
+ split = s.split("-")
+ if len(split) != 2:
+ return None
+ return split
+
+
+def ChooseConfigFromArgs(workspace_root, args):
+ """Return the config file we should use for the given argument,
+ or null if there's no file that matches that."""
+ if len(args) == 1:
+ # Prefer PRODUCT-VARIANT syntax so if there happens to be a matching
+ # file we don't match that.
+ pv = ParseProductVariant(args[0])
+ if pv:
+ config = FindNamedConfig(workspace_root, pv[0])
+ if config:
+ return (config, pv[1])
+ return None, None
+ # Look for a specifically named file
+ if os.path.isfile(args[0]):
+ return (args[0], args[1] if len(args) > 1 else None)
+ # That file didn't exist, return that we didn't find it.
+ return None, None
+
+
+class ConfigException(Exception):
+ ERROR_PARSE = "parse"
+ ERROR_CYCLE = "cycle"
+
+ def __init__(self, kind, message, locations, line=0):
+ """Error thrown when loading and parsing configurations.
+
+ Args:
+ message: Error message to display to user
+ locations: List of filenames of the include history. The 0 index one
+ the location where the actual error occurred
+ """
+ if len(locations):
+ s = locations[0]
+ if line:
+ s += ":"
+ s += str(line)
+ s += ": "
+ else:
+ s = ""
+ s += message
+ if len(locations):
+ for loc in locations[1:]:
+ s += "\n included from %s" % loc
+ super().__init__(s)
+ self.kind = kind
+ self.message = message
+ self.locations = locations
+ self.line = line
+
+
+def LoadConfig(filename):
+ """Load a config, including processing the inherits fields.
+
+ Raises:
+ ConfigException on errors
+ """
+ def LoadAndMerge(fn, visited):
+ with open(fn) as f:
+ try:
+ contents = json.load(f)
+ except json.decoder.JSONDecodeError as ex:
+ if True:
+ raise ConfigException(ConfigException.ERROR_PARSE, ex.msg, visited, ex.lineno)
+ else:
+ sys.stderr.write("exception %s" % ex.__dict__)
+ raise ex
+ # Merge all the parents into one data, with first-wins policy
+ inherited_data = {}
+ for parent in contents.get("inherits", []):
+ if parent in visited:
+ raise ConfigException(ConfigException.ERROR_CYCLE, "Cycle detected in inherits",
+ visited)
+ DeepMerge(inherited_data, LoadAndMerge(parent, [parent,] + visited))
+ # Then merge inherited_data into contents, but what's already there will win.
+ DeepMerge(contents, inherited_data)
+ contents.pop("inherits", None)
+ return contents
+ return LoadAndMerge(filename, [filename,])
+
+
+def DeepMerge(merged, addition):
+ """Merge all fields of addition into merged. Pre-existing fields win."""
+ for k, v in addition.items():
+ if k in merged:
+ if isinstance(v, dict) and isinstance(merged[k], dict):
+ DeepMerge(merged[k], v)
+ else:
+ merged[k] = v
+
+
+def Lunch(args):
+ """Handle the lunch command."""
+ # Check that we're at the top of a multitree workspace
+ # TODO: Choose the right sentinel file
+ if not os.path.exists("build/make/orchestrator"):
+ sys.stderr.write("ERROR: lunch.py must be run from the root of a multi-tree workspace\n")
+ return EXIT_STATUS_ERROR
+
+ # Choose the config file
+ config_file, variant = ChooseConfigFromArgs(".", args)
+
+ if config_file == None:
+ sys.stderr.write("Can't find lunch combo file for: %s\n" % " ".join(args))
+ return EXIT_STATUS_NEED_HELP
+ if variant == None:
+ sys.stderr.write("Can't find variant for: %s\n" % " ".join(args))
+ return EXIT_STATUS_NEED_HELP
+
+ # Parse the config file
+ try:
+ config = LoadConfig(config_file)
+ except ConfigException as ex:
+ sys.stderr.write(str(ex))
+ return EXIT_STATUS_ERROR
+
+ # Fail if the lunchable bit isn't set, because this isn't a usable config
+ if not config.get("lunchable", False):
+ sys.stderr.write("%s: Lunch config file (or inherited files) does not have the 'lunchable'"
+ % config_file)
+ sys.stderr.write(" flag set, which means it is probably not a complete lunch spec.\n")
+
+ # All the validation has passed, so print the name of the file and the variant
+ sys.stdout.write("%s\n" % config_file)
+ sys.stdout.write("%s\n" % variant)
+
+ return EXIT_STATUS_OK
+
+
+def FindAllComboFiles(workspace_root):
+ """Find all .mcombo files in the prescribed locations in the tree."""
+ for dir in FindConfigDirs(workspace_root):
+ for file in WalkPaths(dir, lambda x: x.endswith(".mcombo")):
+ yield file
+
+
+def IsFileLunchable(config_file):
+ """Parse config_file, flatten the inheritance, and return whether it can be
+ used as a lunch target."""
+ try:
+ config = LoadConfig(config_file)
+ except ConfigException as ex:
+ sys.stderr.write("%s" % ex)
+ return False
+ return config.get("lunchable", False)
+
+
+def FindAllLunchable(workspace_root):
+ """Find all mcombo files in the tree (rooted at workspace_root) that when
+ parsed (and inheritance is flattened) have lunchable: true."""
+ for f in [x for x in FindAllComboFiles(workspace_root) if IsFileLunchable(x)]:
+ yield f
+
+
+def List():
+ """Handle the --list command."""
+ for f in sorted(FindAllLunchable(".")):
+ print(f)
+
+
+def Print(args):
+ """Handle the --print command."""
+ # Parse args
+ if len(args) == 0:
+ config_file = os.environ.get("TARGET_BUILD_COMBO")
+ if not config_file:
+ sys.stderr.write("TARGET_BUILD_COMBO not set. Run lunch or pass a combo file.\n")
+ return EXIT_STATUS_NEED_HELP
+ elif len(args) == 1:
+ config_file = args[0]
+ else:
+ return EXIT_STATUS_NEED_HELP
+
+ # Parse the config file
+ try:
+ config = LoadConfig(config_file)
+ except ConfigException as ex:
+ sys.stderr.write(str(ex))
+ return EXIT_STATUS_ERROR
+
+ # Print the config in json form
+ json.dump(config, sys.stdout, indent=4)
+
+ return EXIT_STATUS_OK
+
+
+def main(argv):
+ if len(argv) < 2 or argv[1] == "-h" or argv[1] == "--help":
+ return EXIT_STATUS_NEED_HELP
+
+ if len(argv) == 2 and argv[1] == "--list":
+ List()
+ return EXIT_STATUS_OK
+
+ if len(argv) == 2 and argv[1] == "--print":
+ return Print(argv[2:])
+ return EXIT_STATUS_OK
+
+ if (len(argv) == 2 or len(argv) == 3) and argv[1] == "--lunch":
+ return Lunch(argv[2:])
+
+ sys.stderr.write("Unknown lunch command: %s\n" % " ".join(argv[1:]))
+ return EXIT_STATUS_NEED_HELP
+
+if __name__ == "__main__":
+ sys.exit(main(sys.argv))
+
+
+# vim: sts=4:ts=4:sw=4
diff --git a/orchestrator/core/test/configs/another/bad.mcombo b/orchestrator/core/test/configs/another/bad.mcombo
new file mode 100644
index 0000000..0967ef4
--- /dev/null
+++ b/orchestrator/core/test/configs/another/bad.mcombo
@@ -0,0 +1 @@
+{}
diff --git a/orchestrator/core/test/configs/another/dir/a b/orchestrator/core/test/configs/another/dir/a
new file mode 100644
index 0000000..7898192
--- /dev/null
+++ b/orchestrator/core/test/configs/another/dir/a
@@ -0,0 +1 @@
+a
diff --git a/orchestrator/core/test/configs/b-eng b/orchestrator/core/test/configs/b-eng
new file mode 100644
index 0000000..eceb3f3
--- /dev/null
+++ b/orchestrator/core/test/configs/b-eng
@@ -0,0 +1 @@
+INVALID FILE
diff --git a/orchestrator/core/test/configs/build/make/orchestrator/multitree_combos/b.mcombo b/orchestrator/core/test/configs/build/make/orchestrator/multitree_combos/b.mcombo
new file mode 100644
index 0000000..8cc8370
--- /dev/null
+++ b/orchestrator/core/test/configs/build/make/orchestrator/multitree_combos/b.mcombo
@@ -0,0 +1,3 @@
+{
+ "lunchable": "true"
+}
diff --git a/orchestrator/core/test/configs/build/make/orchestrator/multitree_combos/nested/nested.mcombo b/orchestrator/core/test/configs/build/make/orchestrator/multitree_combos/nested/nested.mcombo
new file mode 100644
index 0000000..0967ef4
--- /dev/null
+++ b/orchestrator/core/test/configs/build/make/orchestrator/multitree_combos/nested/nested.mcombo
@@ -0,0 +1 @@
+{}
diff --git a/orchestrator/core/test/configs/build/make/orchestrator/multitree_combos/not_a_combo.txt b/orchestrator/core/test/configs/build/make/orchestrator/multitree_combos/not_a_combo.txt
new file mode 100644
index 0000000..f9805f2
--- /dev/null
+++ b/orchestrator/core/test/configs/build/make/orchestrator/multitree_combos/not_a_combo.txt
@@ -0,0 +1 @@
+not a combo file
diff --git a/orchestrator/core/test/configs/device/aa/bb/multitree_combos/b.mcombo b/orchestrator/core/test/configs/device/aa/bb/multitree_combos/b.mcombo
new file mode 100644
index 0000000..0967ef4
--- /dev/null
+++ b/orchestrator/core/test/configs/device/aa/bb/multitree_combos/b.mcombo
@@ -0,0 +1 @@
+{}
diff --git a/orchestrator/core/test/configs/device/aa/bb/multitree_combos/d.mcombo b/orchestrator/core/test/configs/device/aa/bb/multitree_combos/d.mcombo
new file mode 100644
index 0000000..0967ef4
--- /dev/null
+++ b/orchestrator/core/test/configs/device/aa/bb/multitree_combos/d.mcombo
@@ -0,0 +1 @@
+{}
diff --git a/orchestrator/core/test/configs/device/aa/bb/multitree_combos/v.mcombo b/orchestrator/core/test/configs/device/aa/bb/multitree_combos/v.mcombo
new file mode 100644
index 0000000..0967ef4
--- /dev/null
+++ b/orchestrator/core/test/configs/device/aa/bb/multitree_combos/v.mcombo
@@ -0,0 +1 @@
+{}
diff --git a/orchestrator/core/test/configs/device/this/one/is/deeper/than/will/be/found/by/the/ttl/multitree_combos/too_deep.mcombo b/orchestrator/core/test/configs/device/this/one/is/deeper/than/will/be/found/by/the/ttl/multitree_combos/too_deep.mcombo
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/orchestrator/core/test/configs/device/this/one/is/deeper/than/will/be/found/by/the/ttl/multitree_combos/too_deep.mcombo
diff --git a/orchestrator/core/test/configs/parsing/cycles/1.mcombo b/orchestrator/core/test/configs/parsing/cycles/1.mcombo
new file mode 100644
index 0000000..ab8fe33
--- /dev/null
+++ b/orchestrator/core/test/configs/parsing/cycles/1.mcombo
@@ -0,0 +1,5 @@
+{
+ "inherits": [
+ "test/configs/parsing/cycles/2.mcombo"
+ ]
+}
diff --git a/orchestrator/core/test/configs/parsing/cycles/2.mcombo b/orchestrator/core/test/configs/parsing/cycles/2.mcombo
new file mode 100644
index 0000000..2b774d0
--- /dev/null
+++ b/orchestrator/core/test/configs/parsing/cycles/2.mcombo
@@ -0,0 +1,6 @@
+{
+ "inherits": [
+ "test/configs/parsing/cycles/3.mcombo"
+ ]
+}
+
diff --git a/orchestrator/core/test/configs/parsing/cycles/3.mcombo b/orchestrator/core/test/configs/parsing/cycles/3.mcombo
new file mode 100644
index 0000000..41b629b
--- /dev/null
+++ b/orchestrator/core/test/configs/parsing/cycles/3.mcombo
@@ -0,0 +1,6 @@
+{
+ "inherits": [
+ "test/configs/parsing/cycles/1.mcombo"
+ ]
+}
+
diff --git a/orchestrator/core/test/configs/parsing/merge/1.mcombo b/orchestrator/core/test/configs/parsing/merge/1.mcombo
new file mode 100644
index 0000000..a5a57d7
--- /dev/null
+++ b/orchestrator/core/test/configs/parsing/merge/1.mcombo
@@ -0,0 +1,13 @@
+{
+ "inherits": [
+ "test/configs/parsing/merge/2.mcombo",
+ "test/configs/parsing/merge/3.mcombo"
+ ],
+ "in_1": "1",
+ "in_1_2": "1",
+ "merged": {
+ "merged_1": "1",
+ "merged_1_2": "1"
+ },
+ "dict_1": { "a" : "b" }
+}
diff --git a/orchestrator/core/test/configs/parsing/merge/2.mcombo b/orchestrator/core/test/configs/parsing/merge/2.mcombo
new file mode 100644
index 0000000..00963e2
--- /dev/null
+++ b/orchestrator/core/test/configs/parsing/merge/2.mcombo
@@ -0,0 +1,12 @@
+{
+ "in_1_2": "2",
+ "in_2": "2",
+ "in_2_3": "2",
+ "merged": {
+ "merged_1_2": "2",
+ "merged_2": "2",
+ "merged_2_3": "2"
+ },
+ "dict_2": { "a" : "b" }
+}
+
diff --git a/orchestrator/core/test/configs/parsing/merge/3.mcombo b/orchestrator/core/test/configs/parsing/merge/3.mcombo
new file mode 100644
index 0000000..5fc9d90
--- /dev/null
+++ b/orchestrator/core/test/configs/parsing/merge/3.mcombo
@@ -0,0 +1,10 @@
+{
+ "in_3": "3",
+ "in_2_3": "3",
+ "merged": {
+ "merged_3": "3",
+ "merged_2_3": "3"
+ },
+ "dict_3": { "a" : "b" }
+}
+
diff --git a/orchestrator/core/test/configs/vendor/aa/bb/multitree_combos/b.mcombo b/orchestrator/core/test/configs/vendor/aa/bb/multitree_combos/b.mcombo
new file mode 100644
index 0000000..0967ef4
--- /dev/null
+++ b/orchestrator/core/test/configs/vendor/aa/bb/multitree_combos/b.mcombo
@@ -0,0 +1 @@
+{}
diff --git a/orchestrator/core/test/configs/vendor/aa/bb/multitree_combos/v.mcombo b/orchestrator/core/test/configs/vendor/aa/bb/multitree_combos/v.mcombo
new file mode 100644
index 0000000..0967ef4
--- /dev/null
+++ b/orchestrator/core/test/configs/vendor/aa/bb/multitree_combos/v.mcombo
@@ -0,0 +1 @@
+{}
diff --git a/orchestrator/core/test/configs/vendor/this/one/is/deeper/than/will/be/found/by/the/ttl/multitree_combos/too_deep.mcombo b/orchestrator/core/test/configs/vendor/this/one/is/deeper/than/will/be/found/by/the/ttl/multitree_combos/too_deep.mcombo
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/orchestrator/core/test/configs/vendor/this/one/is/deeper/than/will/be/found/by/the/ttl/multitree_combos/too_deep.mcombo
diff --git a/orchestrator/core/test_lunch.py b/orchestrator/core/test_lunch.py
new file mode 100755
index 0000000..3c39493
--- /dev/null
+++ b/orchestrator/core/test_lunch.py
@@ -0,0 +1,128 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2008 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 sys
+import unittest
+
+sys.dont_write_bytecode = True
+import lunch
+
+class TestStringMethods(unittest.TestCase):
+
+ def test_find_dirs(self):
+ self.assertEqual([x for x in lunch.FindDirs("test/configs", "multitree_combos")], [
+ "test/configs/build/make/orchestrator/multitree_combos",
+ "test/configs/device/aa/bb/multitree_combos",
+ "test/configs/vendor/aa/bb/multitree_combos"])
+
+ def test_find_file(self):
+ # Finds the one in device first because this is searching from the root,
+ # not using FindNamedConfig.
+ self.assertEqual(lunch.FindFile("test/configs", "v.mcombo"),
+ "test/configs/device/aa/bb/multitree_combos/v.mcombo")
+
+ def test_find_config_dirs(self):
+ self.assertEqual([x for x in lunch.FindConfigDirs("test/configs")], [
+ "test/configs/build/make/orchestrator/multitree_combos",
+ "test/configs/vendor/aa/bb/multitree_combos",
+ "test/configs/device/aa/bb/multitree_combos"])
+
+ def test_find_named_config(self):
+ # Inside build/orchestrator, overriding device and vendor
+ self.assertEqual(lunch.FindNamedConfig("test/configs", "b"),
+ "test/configs/build/make/orchestrator/multitree_combos/b.mcombo")
+
+ # Nested dir inside a combo dir
+ self.assertEqual(lunch.FindNamedConfig("test/configs", "nested"),
+ "test/configs/build/make/orchestrator/multitree_combos/nested/nested.mcombo")
+
+ # Inside vendor, overriding device
+ self.assertEqual(lunch.FindNamedConfig("test/configs", "v"),
+ "test/configs/vendor/aa/bb/multitree_combos/v.mcombo")
+
+ # Inside device
+ self.assertEqual(lunch.FindNamedConfig("test/configs", "d"),
+ "test/configs/device/aa/bb/multitree_combos/d.mcombo")
+
+ # Make sure we don't look too deep (for performance)
+ self.assertIsNone(lunch.FindNamedConfig("test/configs", "too_deep"))
+
+
+ def test_choose_config_file(self):
+ # Empty string argument
+ self.assertEqual(lunch.ChooseConfigFromArgs("test/configs", [""]),
+ (None, None))
+
+ # A PRODUCT-VARIANT name
+ self.assertEqual(lunch.ChooseConfigFromArgs("test/configs", ["v-eng"]),
+ ("test/configs/vendor/aa/bb/multitree_combos/v.mcombo", "eng"))
+
+ # A PRODUCT-VARIANT name that conflicts with a file
+ self.assertEqual(lunch.ChooseConfigFromArgs("test/configs", ["b-eng"]),
+ ("test/configs/build/make/orchestrator/multitree_combos/b.mcombo", "eng"))
+
+ # A PRODUCT-VARIANT that doesn't exist
+ self.assertEqual(lunch.ChooseConfigFromArgs("test/configs", ["z-user"]),
+ (None, None))
+
+ # An explicit file
+ self.assertEqual(lunch.ChooseConfigFromArgs("test/configs",
+ ["test/configs/build/make/orchestrator/multitree_combos/b.mcombo", "eng"]),
+ ("test/configs/build/make/orchestrator/multitree_combos/b.mcombo", "eng"))
+
+ # An explicit file that doesn't exist
+ self.assertEqual(lunch.ChooseConfigFromArgs("test/configs",
+ ["test/configs/doesnt_exist.mcombo", "eng"]),
+ (None, None))
+
+ # An explicit file without a variant should fail
+ self.assertEqual(lunch.ChooseConfigFromArgs("test/configs",
+ ["test/configs/build/make/orchestrator/multitree_combos/b.mcombo"]),
+ ("test/configs/build/make/orchestrator/multitree_combos/b.mcombo", None))
+
+
+ def test_config_cycles(self):
+ # Test that we catch cycles
+ with self.assertRaises(lunch.ConfigException) as context:
+ lunch.LoadConfig("test/configs/parsing/cycles/1.mcombo")
+ self.assertEqual(context.exception.kind, lunch.ConfigException.ERROR_CYCLE)
+
+ def test_config_merge(self):
+ # Test the merge logic
+ self.assertEqual(lunch.LoadConfig("test/configs/parsing/merge/1.mcombo"), {
+ "in_1": "1",
+ "in_1_2": "1",
+ "merged": {"merged_1": "1",
+ "merged_1_2": "1",
+ "merged_2": "2",
+ "merged_2_3": "2",
+ "merged_3": "3"},
+ "dict_1": {"a": "b"},
+ "in_2": "2",
+ "in_2_3": "2",
+ "dict_2": {"a": "b"},
+ "in_3": "3",
+ "dict_3": {"a": "b"}
+ })
+
+ def test_list(self):
+ self.assertEqual(sorted(lunch.FindAllLunchable("test/configs")),
+ ["test/configs/build/make/orchestrator/multitree_combos/b.mcombo"])
+
+if __name__ == "__main__":
+ unittest.main()
+
+# vim: sts=4:ts=4:sw=4
diff --git a/orchestrator/multitree_combos/test.mcombo b/orchestrator/multitree_combos/test.mcombo
new file mode 100644
index 0000000..3ad0717
--- /dev/null
+++ b/orchestrator/multitree_combos/test.mcombo
@@ -0,0 +1,16 @@
+{
+ "lunchable": true,
+ "system": {
+ "tree": "inner_tree_system",
+ "product": "system_lunch_product"
+ },
+ "vendor": {
+ "tree": "inner_tree_vendor",
+ "product": "vendor_lunch_product"
+ },
+ "modules": {
+ "com.android.something": {
+ "tree": "inner_tree_module"
+ }
+ }
+}
diff --git a/target/board/Android.mk b/target/board/Android.mk
index 142270e..baa3d3a 100644
--- a/target/board/Android.mk
+++ b/target/board/Android.mk
@@ -30,6 +30,8 @@
$(hide) echo "" > $@
endif
+$(call declare-0p-target,$(INSTALLED_ANDROID_INFO_TXT_TARGET))
+
# Copy compatibility metadata to the device.
# Device Manifest
diff --git a/target/board/BoardConfigGkiCommon.mk b/target/board/BoardConfigGkiCommon.mk
deleted file mode 100644
index 63ef2b4..0000000
--- a/target/board/BoardConfigGkiCommon.mk
+++ /dev/null
@@ -1,40 +0,0 @@
-# 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.
-#
-
-# Enable GKI 2.0 signing.
-BOARD_GKI_SIGNING_KEY_PATH := build/make/target/product/gsi/testkey_rsa2048.pem
-BOARD_GKI_SIGNING_ALGORITHM := SHA256_RSA2048
-BOARD_GKI_SIGNING_SIGNATURE_ARGS :=
-
-# 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
-BOARD_MKBOOTIMG_ARGS += --header_version $(BOARD_BOOT_HEADER_VERSION)
-BOARD_USES_RECOVERY_AS_BOOT :=
-TARGET_NO_KERNEL := false
-BOARD_USES_GENERIC_KERNEL_IMAGE := true
-
-# Copy boot image in $OUT to target files. This is defined for targets where
-# the installed GKI APEXes are built from source.
-BOARD_COPY_BOOT_IMAGE_TO_TARGET_FILES := true
-
-# No vendor_boot
-BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT :=
-
-# No recovery
-BOARD_EXCLUDE_KERNEL_FROM_RECOVERY_IMAGE :=
diff --git a/target/board/BoardConfigGsiCommon.mk b/target/board/BoardConfigGsiCommon.mk
index c577870..45cd515 100644
--- a/target/board/BoardConfigGsiCommon.mk
+++ b/target/board/BoardConfigGsiCommon.mk
@@ -11,8 +11,11 @@
# This flag is set by mainline but isn't desired for GSI.
BOARD_USES_SYSTEM_OTHER_ODEX :=
-# system.img is always ext4 and non-sparsed.
+# system.img is ext4/erofs and non-sparsed.
+GSI_FILE_SYSTEM_TYPE ?= ext4
+BOARD_SYSTEMIMAGE_FILE_SYSTEM_TYPE := $(GSI_FILE_SYSTEM_TYPE)
TARGET_USERIMAGES_SPARSE_EXT_DISABLED := true
+TARGET_USERIMAGES_SPARSE_EROFS_DISABLED := true
# GSI also includes make_f2fs to support userdata parition in f2fs
# for some devices
@@ -57,12 +60,6 @@
# This flag is set by mainline but isn't desired for GSI
BOARD_BLUETOOTH_BDROID_BUILDCFG_INCLUDE_DIR :=
-# 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/generic_arm64/BoardConfig.mk b/target/board/generic_arm64/BoardConfig.mk
index b0c9950..45ed3da 100644
--- a/target/board/generic_arm64/BoardConfig.mk
+++ b/target/board/generic_arm64/BoardConfig.mk
@@ -53,29 +53,6 @@
endif
include build/make/target/board/BoardConfigGsiCommon.mk
-include build/make/target/board/BoardConfigGkiCommon.mk
-
-BOARD_KERNEL-4.19-GZ_BOOTIMAGE_PARTITION_SIZE := 47185920
-BOARD_KERNEL-4.19-GZ-ALLSYMS_BOOTIMAGE_PARTITION_SIZE := 47185920
-BOARD_KERNEL-5.10_BOOTIMAGE_PARTITION_SIZE := 67108864
-BOARD_KERNEL-5.10-ALLSYMS_BOOTIMAGE_PARTITION_SIZE := 67108864
-BOARD_KERNEL-5.10-GZ_BOOTIMAGE_PARTITION_SIZE := 47185920
-BOARD_KERNEL-5.10-GZ-ALLSYMS_BOOTIMAGE_PARTITION_SIZE := 47185920
-BOARD_KERNEL-5.10-LZ4_BOOTIMAGE_PARTITION_SIZE := 53477376
-BOARD_KERNEL-5.10-LZ4-ALLSYMS_BOOTIMAGE_PARTITION_SIZE := 53477376
-
-BOARD_USERDATAIMAGE_PARTITION_SIZE := 576716800
-
-BOARD_KERNEL_BINARIES := \
- kernel-4.19-gz \
- kernel-5.10 kernel-5.10-gz kernel-5.10-lz4 \
-
-ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT)))
-BOARD_KERNEL_BINARIES += \
- kernel-4.19-gz-allsyms \
- kernel-5.10-allsyms kernel-5.10-gz-allsyms kernel-5.10-lz4-allsyms \
-
-endif
# Some vendors still haven't cleaned up all device specific directories under
# root!
diff --git a/target/board/generic_arm64/device.mk b/target/board/generic_arm64/device.mk
index 0a05d9c..598bef1 100644
--- a/target/board/generic_arm64/device.mk
+++ b/target/board/generic_arm64/device.mk
@@ -13,26 +13,3 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
-
-PRODUCT_COPY_FILES += \
- kernel/prebuilts/4.19/arm64/kernel-4.19-gz:kernel-4.19-gz \
- kernel/prebuilts/5.10/arm64/kernel-5.10:kernel-5.10 \
- kernel/prebuilts/5.10/arm64/kernel-5.10-gz:kernel-5.10-gz \
- kernel/prebuilts/5.10/arm64/kernel-5.10-lz4:kernel-5.10-lz4 \
-
-$(call dist-for-goals, dist_files, kernel/prebuilts/4.19/arm64/prebuilt-info.txt:kernel/4.19/prebuilt-info.txt)
-$(call dist-for-goals, dist_files, kernel/prebuilts/5.10/arm64/prebuilt-info.txt:kernel/5.10/prebuilt-info.txt)
-
-ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT)))
-PRODUCT_COPY_FILES += \
- kernel/prebuilts/4.19/arm64/kernel-4.19-gz-allsyms:kernel-4.19-gz-allsyms \
- kernel/prebuilts/5.10/arm64/kernel-5.10-allsyms:kernel-5.10-allsyms \
- kernel/prebuilts/5.10/arm64/kernel-5.10-gz-allsyms:kernel-5.10-gz-allsyms \
- kernel/prebuilts/5.10/arm64/kernel-5.10-lz4-allsyms:kernel-5.10-lz4-allsyms \
-
-endif
-
-PRODUCT_BUILD_VENDOR_BOOT_IMAGE := false
-PRODUCT_BUILD_RECOVERY_IMAGE := false
-
-$(call inherit-product, $(SRC_TARGET_DIR)/product/generic_ramdisk.mk)
diff --git a/target/board/generic_x86_64/BoardConfig.mk b/target/board/generic_x86_64/BoardConfig.mk
index 640216c..93694f2 100755
--- a/target/board/generic_x86_64/BoardConfig.mk
+++ b/target/board/generic_x86_64/BoardConfig.mk
@@ -24,25 +24,7 @@
include build/make/target/board/BoardConfigGsiCommon.mk
-ifdef BUILDING_GSI
-include build/make/target/board/BoardConfigGkiCommon.mk
-
-BOARD_KERNEL-5.4_BOOTIMAGE_PARTITION_SIZE := 67108864
-BOARD_KERNEL-5.10_BOOTIMAGE_PARTITION_SIZE := 67108864
-BOARD_KERNEL-5.10-ALLSYMS_BOOTIMAGE_PARTITION_SIZE := 67108864
-
-BOARD_USERDATAIMAGE_PARTITION_SIZE := 576716800
-
-BOARD_KERNEL_BINARIES := \
- kernel-5.10 \
-
-ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT)))
-BOARD_KERNEL_BINARIES += \
- kernel-5.10-allsyms \
-
-endif
-
-else # BUILDING_GSI
+ifndef BUILDING_GSI
include build/make/target/board/BoardConfigEmuCommon.mk
BOARD_USERDATAIMAGE_PARTITION_SIZE := 576716800
@@ -60,4 +42,4 @@
WIFI_DRIVER_FW_PATH_STA := "/dev/null"
WIFI_DRIVER_FW_PATH_AP := "/dev/null"
-endif # BUILDING_GSI
+endif # !BUILDING_GSI
diff --git a/target/board/generic_x86_64/device.mk b/target/board/generic_x86_64/device.mk
index d28ace7..fa1eb67 100755
--- a/target/board/generic_x86_64/device.mk
+++ b/target/board/generic_x86_64/device.mk
@@ -13,19 +13,3 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
-
-PRODUCT_COPY_FILES += \
- kernel/prebuilts/5.10/x86_64/kernel-5.10:kernel-5.10 \
-
-$(call dist-for-goals, dist_files, kernel/prebuilts/5.10/x86_64/prebuilt-info.txt:kernel/5.10/prebuilt-info.txt)
-
-ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT)))
-PRODUCT_COPY_FILES += \
- kernel/prebuilts/5.10/x86_64/kernel-5.10-allsyms:kernel-5.10-allsyms \
-
-endif
-
-PRODUCT_BUILD_VENDOR_BOOT_IMAGE := false
-PRODUCT_BUILD_RECOVERY_IMAGE := false
-
-$(call inherit-product, $(SRC_TARGET_DIR)/product/generic_ramdisk.mk)
diff --git a/target/product/base_system.mk b/target/product/base_system.mk
index 55047df..05ddfe5 100644
--- a/target/product/base_system.mk
+++ b/target/product/base_system.mk
@@ -118,7 +118,6 @@
init_system \
input \
installd \
- iorapd \
ip \
iptables \
ip-up-vpn \
@@ -295,7 +294,7 @@
# HWASAN runtime for SANITIZE_TARGET=hwaddress builds
ifneq (,$(filter hwaddress,$(SANITIZE_TARGET)))
PRODUCT_PACKAGES += \
- libclang_rt.hwasan-aarch64-android.bootstrap
+ libclang_rt.hwasan.bootstrap
endif
# Jacoco agent JARS to be built and installed, if any.
diff --git a/target/product/cfi-common.mk b/target/product/cfi-common.mk
index 6ce4fbe..3aa2be7 100644
--- a/target/product/cfi-common.mk
+++ b/target/product/cfi-common.mk
@@ -30,7 +30,7 @@
hardware/qcom/wlan/qcwcn/wpa_supplicant_8_lib \
hardware/interfaces/keymaster \
hardware/interfaces/security \
- system/bt \
+ packages/modules/Bluetooth/system \
system/chre \
system/core/libnetutils \
system/libziparchive \
diff --git a/target/product/generic_ramdisk.mk b/target/product/generic_ramdisk.mk
index 80d34be..fb0370e 100644
--- a/target/product/generic_ramdisk.mk
+++ b/target/product/generic_ramdisk.mk
@@ -22,6 +22,10 @@
# Ramdisk
PRODUCT_PACKAGES += \
init_first_stage \
+ e2fsck.ramdisk \
+ fsck.f2fs.ramdisk \
+ tune2fs.ramdisk \
+ snapuserd.ramdisk \
# Debug ramdisk
PRODUCT_PACKAGES += \
diff --git a/target/product/gsi/32.txt b/target/product/gsi/32.txt
new file mode 100644
index 0000000..971ec92
--- /dev/null
+++ b/target/product/gsi/32.txt
@@ -0,0 +1,223 @@
+LLNDK: libEGL.so
+LLNDK: libGLESv1_CM.so
+LLNDK: libGLESv2.so
+LLNDK: libGLESv3.so
+LLNDK: libRS.so
+LLNDK: libandroid_net.so
+LLNDK: libbinder_ndk.so
+LLNDK: libc.so
+LLNDK: libcgrouprc.so
+LLNDK: libdl.so
+LLNDK: libft2.so
+LLNDK: liblog.so
+LLNDK: libm.so
+LLNDK: libmediandk.so
+LLNDK: libnativewindow.so
+LLNDK: libneuralnetworks.so
+LLNDK: libselinux.so
+LLNDK: libsync.so
+LLNDK: libvndksupport.so
+LLNDK: libvulkan.so
+VNDK-SP: android.hardware.common-V2-ndk_platform.so
+VNDK-SP: android.hardware.common.fmq-V1-ndk_platform.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
+VNDK-SP: android.hardware.graphics.common@1.2.so
+VNDK-SP: android.hardware.graphics.mapper@2.0.so
+VNDK-SP: android.hardware.graphics.mapper@2.1.so
+VNDK-SP: android.hardware.graphics.mapper@3.0.so
+VNDK-SP: android.hardware.graphics.mapper@4.0.so
+VNDK-SP: android.hardware.renderscript@1.0.so
+VNDK-SP: android.hidl.memory.token@1.0.so
+VNDK-SP: android.hidl.memory@1.0-impl.so
+VNDK-SP: android.hidl.memory@1.0.so
+VNDK-SP: android.hidl.safe_union@1.0.so
+VNDK-SP: libRSCpuRef.so
+VNDK-SP: libRSDriver.so
+VNDK-SP: libRS_internal.so
+VNDK-SP: libbacktrace.so
+VNDK-SP: libbase.so
+VNDK-SP: libbcinfo.so
+VNDK-SP: libblas.so
+VNDK-SP: libc++.so
+VNDK-SP: libcompiler_rt.so
+VNDK-SP: libcutils.so
+VNDK-SP: libdmabufheap.so
+VNDK-SP: libgralloctypes.so
+VNDK-SP: libhardware.so
+VNDK-SP: libhidlbase.so
+VNDK-SP: libhidlmemory.so
+VNDK-SP: libion.so
+VNDK-SP: libjsoncpp.so
+VNDK-SP: liblzma.so
+VNDK-SP: libprocessgroup.so
+VNDK-SP: libunwindstack.so
+VNDK-SP: libutils.so
+VNDK-SP: libutilscallstack.so
+VNDK-SP: libz.so
+VNDK-core: android.hardware.audio.common@2.0.so
+VNDK-core: android.hardware.authsecret-V1-ndk_platform.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
+VNDK-core: android.hardware.configstore@1.1.so
+VNDK-core: android.hardware.confirmationui-support-lib.so
+VNDK-core: android.hardware.gnss-V1-ndk_platform.so
+VNDK-core: android.hardware.graphics.allocator@2.0.so
+VNDK-core: android.hardware.graphics.allocator@3.0.so
+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_platform.so
+VNDK-core: android.hardware.identity-V3-ndk_platform.so
+VNDK-core: android.hardware.keymaster-V3-ndk_platform.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_platform.so
+VNDK-core: android.hardware.memtrack@1.0.so
+VNDK-core: android.hardware.oemlock-V1-ndk_platform.so
+VNDK-core: android.hardware.power-V2-ndk_platform.so
+VNDK-core: android.hardware.power.stats-V1-ndk_platform.so
+VNDK-core: android.hardware.rebootescrow-V1-ndk_platform.so
+VNDK-core: android.hardware.security.keymint-V1-ndk_platform.so
+VNDK-core: android.hardware.security.secureclock-V1-ndk_platform.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-V2-ndk_platform.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_platform.so
+VNDK-core: android.system.suspend@1.0.so
+VNDK-core: libaudioroute.so
+VNDK-core: libaudioutils.so
+VNDK-core: libbinder.so
+VNDK-core: libbufferqueueconverter.so
+VNDK-core: libcamera_metadata.so
+VNDK-core: libcap.so
+VNDK-core: libcn-cbor.so
+VNDK-core: libcodec2.so
+VNDK-core: libcrypto.so
+VNDK-core: libcrypto_utils.so
+VNDK-core: libcurl.so
+VNDK-core: libdiskconfig.so
+VNDK-core: libdumpstateutil.so
+VNDK-core: libevent.so
+VNDK-core: libexif.so
+VNDK-core: libexpat.so
+VNDK-core: libfmq.so
+VNDK-core: libgatekeeper.so
+VNDK-core: libgui.so
+VNDK-core: libhardware_legacy.so
+VNDK-core: libhidlallocatorutils.so
+VNDK-core: libjpeg.so
+VNDK-core: libldacBT_abr.so
+VNDK-core: libldacBT_enc.so
+VNDK-core: liblz4.so
+VNDK-core: libmedia_helper.so
+VNDK-core: libmedia_omx.so
+VNDK-core: libmemtrack.so
+VNDK-core: libminijail.so
+VNDK-core: libmkbootimg_abi_check.so
+VNDK-core: libnetutils.so
+VNDK-core: libnl.so
+VNDK-core: libpcre2.so
+VNDK-core: libpiex.so
+VNDK-core: libpng.so
+VNDK-core: libpower.so
+VNDK-core: libprocinfo.so
+VNDK-core: libradio_metadata.so
+VNDK-core: libspeexresampler.so
+VNDK-core: libsqlite.so
+VNDK-core: libssl.so
+VNDK-core: libstagefright_bufferpool@2.0.so
+VNDK-core: libstagefright_bufferqueue_helper.so
+VNDK-core: libstagefright_foundation.so
+VNDK-core: libstagefright_omx.so
+VNDK-core: libstagefright_omx_utils.so
+VNDK-core: libstagefright_xmlparser.so
+VNDK-core: libsysutils.so
+VNDK-core: libtinyalsa.so
+VNDK-core: libtinyxml2.so
+VNDK-core: libui.so
+VNDK-core: libusbhost.so
+VNDK-core: libwifi-system-iface.so
+VNDK-core: libxml2.so
+VNDK-core: libyuv.so
+VNDK-core: libziparchive.so
+VNDK-private: libbacktrace.so
+VNDK-private: libblas.so
+VNDK-private: libcompiler_rt.so
+VNDK-private: libft2.so
+VNDK-private: libgui.so
+VNDK-product: android.hardware.audio.common@2.0.so
+VNDK-product: android.hardware.configstore@1.0.so
+VNDK-product: android.hardware.configstore@1.1.so
+VNDK-product: android.hardware.graphics.allocator@2.0.so
+VNDK-product: android.hardware.graphics.allocator@3.0.so
+VNDK-product: android.hardware.graphics.allocator@4.0.so
+VNDK-product: android.hardware.graphics.bufferqueue@1.0.so
+VNDK-product: android.hardware.graphics.bufferqueue@2.0.so
+VNDK-product: android.hardware.graphics.common@1.0.so
+VNDK-product: android.hardware.graphics.common@1.1.so
+VNDK-product: android.hardware.graphics.common@1.2.so
+VNDK-product: android.hardware.graphics.mapper@2.0.so
+VNDK-product: android.hardware.graphics.mapper@2.1.so
+VNDK-product: android.hardware.graphics.mapper@3.0.so
+VNDK-product: android.hardware.graphics.mapper@4.0.so
+VNDK-product: android.hardware.media.bufferpool@2.0.so
+VNDK-product: android.hardware.media.omx@1.0.so
+VNDK-product: android.hardware.media@1.0.so
+VNDK-product: android.hardware.memtrack@1.0.so
+VNDK-product: android.hardware.renderscript@1.0.so
+VNDK-product: android.hardware.soundtrigger@2.0.so
+VNDK-product: android.hidl.memory.token@1.0.so
+VNDK-product: android.hidl.memory@1.0.so
+VNDK-product: android.hidl.safe_union@1.0.so
+VNDK-product: android.hidl.token@1.0.so
+VNDK-product: android.system.suspend@1.0.so
+VNDK-product: libaudioutils.so
+VNDK-product: libbacktrace.so
+VNDK-product: libbase.so
+VNDK-product: libc++.so
+VNDK-product: libcamera_metadata.so
+VNDK-product: libcap.so
+VNDK-product: libcompiler_rt.so
+VNDK-product: libcrypto.so
+VNDK-product: libcurl.so
+VNDK-product: libcutils.so
+VNDK-product: libevent.so
+VNDK-product: libexpat.so
+VNDK-product: libfmq.so
+VNDK-product: libhidlbase.so
+VNDK-product: libhidlmemory.so
+VNDK-product: libion.so
+VNDK-product: libjpeg.so
+VNDK-product: libjsoncpp.so
+VNDK-product: libldacBT_abr.so
+VNDK-product: libldacBT_enc.so
+VNDK-product: liblz4.so
+VNDK-product: liblzma.so
+VNDK-product: libminijail.so
+VNDK-product: libnl.so
+VNDK-product: libpcre2.so
+VNDK-product: libpiex.so
+VNDK-product: libpng.so
+VNDK-product: libprocessgroup.so
+VNDK-product: libprocinfo.so
+VNDK-product: libspeexresampler.so
+VNDK-product: libssl.so
+VNDK-product: libtinyalsa.so
+VNDK-product: libtinyxml2.so
+VNDK-product: libunwindstack.so
+VNDK-product: libutils.so
+VNDK-product: libutilscallstack.so
+VNDK-product: libwifi-system-iface.so
+VNDK-product: libxml2.so
+VNDK-product: libyuv.so
+VNDK-product: libz.so
+VNDK-product: libziparchive.so
diff --git a/target/product/gsi_release.mk b/target/product/gsi_release.mk
index b1266ee..74501cd 100644
--- a/target/product/gsi_release.mk
+++ b/target/product/gsi_release.mk
@@ -68,6 +68,7 @@
29 \
30 \
31 \
+ 32 \
# Do not build non-GSI partition images.
PRODUCT_BUILD_CACHE_IMAGE := false
diff --git a/target/product/media_system.mk b/target/product/media_system.mk
index 30a8621..79bd74a 100644
--- a/target/product/media_system.mk
+++ b/target/product/media_system.mk
@@ -27,7 +27,6 @@
com.android.media.remotedisplay.xml \
CompanionDeviceManager \
drmserver \
- ethernet-service \
fsck.f2fs \
HTMLViewer \
libfilterpack_imageproc \
@@ -51,8 +50,7 @@
# The order here is the same order they end up on the classpath, so it matters.
PRODUCT_SYSTEM_SERVER_JARS := \
com.android.location.provider \
- services \
- ethernet-service
+ services
PRODUCT_COPY_FILES += \
system/core/rootdir/etc/public.libraries.android.txt:system/etc/public.libraries.txt
diff --git a/target/product/module_common.mk b/target/product/module_common.mk
index 03340db..54f3949 100644
--- a/target/product/module_common.mk
+++ b/target/product/module_common.mk
@@ -21,3 +21,7 @@
# Enables treble, which enabled certain -D compilation flags. In particular, libhidlbase
# uses -DENFORCE_VINTF_MANIFEST. See b/185759877
PRODUCT_SHIPPING_API_LEVEL := 29
+
+# Builds using a module product should build modules from source, even if
+# BRANCH_DEFAULT_MODULE_BUILD_FROM_SOURCE says otherwise.
+PRODUCT_MODULE_BUILD_FROM_SOURCE := true
diff --git a/target/product/runtime_libart.mk b/target/product/runtime_libart.mk
index ee63757..b6560fc 100644
--- a/target/product/runtime_libart.mk
+++ b/target/product/runtime_libart.mk
@@ -148,17 +148,6 @@
dalvik.vm.minidebuginfo=true \
dalvik.vm.dex2oat-minidebuginfo=true
-# Two other device configs are added to IORap besides "ro.iorapd.enable".
-# IORap by default is off and starts when
-# (https://source.corp.google.com/android/system/iorap/iorapd.rc?q=iorapd.rc)
-#
-# * "ro.iorapd.enable" is true excluding unset
-# * One of the device configs is true.
-#
-# "ro.iorapd.enable" has to be set to true, so that iorap can be started.
-PRODUCT_SYSTEM_PROPERTIES += \
- ro.iorapd.enable?=true
-
# Enable Madvising of the whole art, odex and vdex files to MADV_WILLNEED.
# The size specified here is the size limit of how much of the file
# (in bytes) is madvised.
diff --git a/target/product/security/sdk_sandbox.pk8 b/target/product/security/sdk_sandbox.pk8
new file mode 100644
index 0000000..23b880b
--- /dev/null
+++ b/target/product/security/sdk_sandbox.pk8
Binary files differ
diff --git a/target/product/security/sdk_sandbox.x509.pem b/target/product/security/sdk_sandbox.x509.pem
new file mode 100644
index 0000000..0bd20f3
--- /dev/null
+++ b/target/product/security/sdk_sandbox.x509.pem
@@ -0,0 +1,24 @@
+-----BEGIN CERTIFICATE-----
+MIIECzCCAvOgAwIBAgIUMWJGQnrJU7zBEpPqv63u2HOlib0wDQYJKoZIhvcNAQEL
+BQAwgZQxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQH
+DA1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKDAdBbmRyb2lkMRAwDgYDVQQLDAdBbmRy
+b2lkMRAwDgYDVQQDDAdBbmRyb2lkMSIwIAYJKoZIhvcNAQkBFhNhbmRyb2lkQGFu
+ZHJvaWQuY29tMB4XDTIxMTEwMjE3MDIxNFoXDTQ5MDMyMDE3MDIxNFowgZQxCzAJ
+BgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1Nb3VudGFp
+biBWaWV3MRAwDgYDVQQKDAdBbmRyb2lkMRAwDgYDVQQLDAdBbmRyb2lkMRAwDgYD
+VQQDDAdBbmRyb2lkMSIwIAYJKoZIhvcNAQkBFhNhbmRyb2lkQGFuZHJvaWQuY29t
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA09j3dyTxv8ojb4sXjrWX
+smXTYEez/u6X6po8+mWXp1xl1Y9xjYrxZROIE1MJL8aay8iYJihqx7RBWTPJYtYZ
+TLElA3dyQuMgDIKtlQR3QAMRoc2IKrkfcIboEs71xl78EnTSQfRJTUEFvNigzjfB
+e3JVtNDC9BR/33Iv9oNED84qW9C54h4TWHLyvo75unzPQUGS6uEIhhHa/8ynZZQW
+YEd0NwAQNqbcMdbN8Bn6sRRCidEOIPd8Uu8DtIofLi7/YMo4CH1Q5f5UQbtPtqU2
+m8fjQN9WYzMazvWltRE+HYDH9YnXCLAsVicNdmFhAlXri15nG2AiRnSrHu/panAc
+6wIDAQABo1MwUTAdBgNVHQ4EFgQU3F5r2DhJbRfkJKuqs1hjP/0dCUEwHwYDVR0j
+BBgwFoAU3F5r2DhJbRfkJKuqs1hjP/0dCUEwDwYDVR0TAQH/BAUwAwEB/zANBgkq
+hkiG9w0BAQsFAAOCAQEAwQQ8/D3f/WS5cwqcsFpT+Qzik9yTu53nsXz/pBDSbeM3
+zX1RCejXsmXhPjN7cu0uJYlrIuArOagHSC5pDci6GzcwunnnkRazSAmTpHLSRgeb
+cLgKHLCph9sulI1r82x9upF47zLlbfkTrtGJryej+yWJ2Ne8irJIPeNR0z0sTBWJ
+2Ngg55ezFWj3mihzw4Z6YU9txJB7Gj9eNYXdcubjoNs2mSU/6dR+HwJtD64FuH3x
+QLGMZscizCN8N6b5xayjwPsszQhaHI4iR4oGJ9prbDd0JoylwWr2LrQhYuWQCn20
+cG5YhrtZshj6f1eGV1TDYd8xziapilqwzrchARvP8g==
+-----END CERTIFICATE-----
diff --git a/target/product/virtual_ab_ota/android_t_baseline.mk b/target/product/virtual_ab_ota/android_t_baseline.mk
new file mode 100644
index 0000000..18e08e4
--- /dev/null
+++ b/target/product/virtual_ab_ota/android_t_baseline.mk
@@ -0,0 +1,52 @@
+#
+# Copyright (C) 2022 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.
+
+# This file enables baseline features, such as io_uring,
+# userspace merge, etc. But sets compression method to none.
+# This .mk file also removes snapuserd from vendor ramdisk,
+# as T launching devices will have init_boot which has snapuserd
+# in generic ramdisk.
+# T launching devices should include this .mk file, and configure
+# compression algorithm by setting
+# PRODUCT_VIRTUAL_AB_COMPRESSION_METHOD to gz or brotli. Complete
+# set of supported algorithms can be found in
+# system/core/fs_mgr/libsnapshot/cow_writer.cpp
+
+PRODUCT_VIRTUAL_AB_OTA := true
+
+PRODUCT_VENDOR_PROPERTIES += ro.virtual_ab.enabled=true
+
+PRODUCT_VENDOR_PROPERTIES += ro.virtual_ab.compression.enabled=true
+PRODUCT_VENDOR_PROPERTIES += ro.virtual_ab.userspace.snapshots.enabled=true
+PRODUCT_VENDOR_PROPERTIES += ro.virtual_ab.io_uring.enabled=true
+PRODUCT_VENDOR_PROPERTIES += ro.virtual_ab.compression.xor.enabled=true
+
+PRODUCT_VIRTUAL_AB_COMPRESSION := true
+PRODUCT_VIRTUAL_AB_COMPRESSION_METHOD ?= none
+PRODUCT_PACKAGES += \
+ snapuserd \
+
+# For dedicated recovery partitions, we need to include snapuserd
+# For GKI devices, BOARD_USES_RECOVERY_AS_BOOT is empty, but
+# so is BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT.
+ifdef BUILDING_RECOVERY_IMAGE
+ifneq ($(BOARD_USES_RECOVERY_AS_BOOT),true)
+ifneq ($(BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT),true)
+PRODUCT_PACKAGES += \
+ snapuserd.recovery
+endif
+endif
+endif
+
diff --git a/tests/artifact_path_requirements/inherit1.rbc b/tests/artifact_path_requirements/inherit1.rbc
new file mode 100644
index 0000000..dcef1bf
--- /dev/null
+++ b/tests/artifact_path_requirements/inherit1.rbc
@@ -0,0 +1,21 @@
+# Copyright 2022 Google LLC
+#
+# 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
+#
+# https://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.
+
+load("//build/make/core:product_config.rbc", "rblf")
+load(":inherit3.rbc", _inherit3_init = "init")
+
+def init(g, handle):
+ cfg = rblf.cfg(handle)
+
+ rblf.inherit(handle, "test/inherit3", _inherit3_init)
diff --git a/tests/artifact_path_requirements/inherit2.rbc b/tests/artifact_path_requirements/inherit2.rbc
new file mode 100644
index 0000000..597b4e9
--- /dev/null
+++ b/tests/artifact_path_requirements/inherit2.rbc
@@ -0,0 +1,22 @@
+# Copyright 2022 Google LLC
+#
+# 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
+#
+# https://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.
+
+load("//build/make/core:product_config.rbc", "rblf")
+load(":inherit4.rbc", _inherit4_init = "init")
+
+def init(g, handle):
+ cfg = rblf.cfg(handle)
+
+ rblf.inherit(handle, "test/inherit4", _inherit4_init)
+ rblf.require_artifacts_in_path(handle, "vendor/", "")
diff --git a/tests/artifact_path_requirements/inherit3.rbc b/tests/artifact_path_requirements/inherit3.rbc
new file mode 100644
index 0000000..597b4e9
--- /dev/null
+++ b/tests/artifact_path_requirements/inherit3.rbc
@@ -0,0 +1,22 @@
+# Copyright 2022 Google LLC
+#
+# 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
+#
+# https://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.
+
+load("//build/make/core:product_config.rbc", "rblf")
+load(":inherit4.rbc", _inherit4_init = "init")
+
+def init(g, handle):
+ cfg = rblf.cfg(handle)
+
+ rblf.inherit(handle, "test/inherit4", _inherit4_init)
+ rblf.require_artifacts_in_path(handle, "vendor/", "")
diff --git a/tests/artifact_path_requirements/inherit4.rbc b/tests/artifact_path_requirements/inherit4.rbc
new file mode 100644
index 0000000..52028fe
--- /dev/null
+++ b/tests/artifact_path_requirements/inherit4.rbc
@@ -0,0 +1,21 @@
+# Copyright 2022 Google LLC
+#
+# 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
+#
+# https://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.
+
+load("//build/make/core:product_config.rbc", "rblf")
+
+def init(g, handle):
+ cfg = rblf.cfg(handle)
+
+ rblf.setdefault(handle, "PRODUCT_COPY_FILES")
+ cfg["PRODUCT_COPY_FILES"] += ["foo/bar/baz.txt:vendor/etc/baz.txt"]
diff --git a/tests/artifact_path_requirements/product.rbc b/tests/artifact_path_requirements/product.rbc
new file mode 100644
index 0000000..7d1f169
--- /dev/null
+++ b/tests/artifact_path_requirements/product.rbc
@@ -0,0 +1,24 @@
+# Copyright 2022 Google LLC
+#
+# 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
+#
+# https://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.
+
+load("//build/make/core:product_config.rbc", "rblf")
+load(":inherit1.rbc", _inherit1_init = "init")
+load(":inherit2.rbc", _inherit2_init = "init")
+load(":inherit3.rbc", _inherit3_init = "init")
+
+def init(g, handle):
+ cfg = rblf.cfg(handle)
+ rblf.inherit(handle, "test/inherit1", _inherit1_init)
+ rblf.inherit(handle, "test/inherit2", _inherit2_init)
+ rblf.inherit(handle, "test/inherit3", _inherit3_init)
diff --git a/tests/artifact_path_requirements/test.rbc b/tests/artifact_path_requirements/test.rbc
new file mode 100644
index 0000000..0a344d1
--- /dev/null
+++ b/tests/artifact_path_requirements/test.rbc
@@ -0,0 +1,27 @@
+# Copyright 2022 Google LLC
+#
+# 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
+#
+# https://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.
+
+load("//build/make/core:product_config.rbc", "rblf")
+load("//build/make/tests/input_variables.rbc", input_variables_init = "init")
+load(":product.rbc", "init")
+
+def assert_eq(expected, actual):
+ if expected != actual:
+ fail("Expected '%s', got '%s'" % (expected, actual))
+
+def test():
+ (globals, globals_base) = rblf.product_configuration("test/product", init, input_variables_init)
+ assert_eq(["foo/bar/baz.txt:vendor/etc/baz.txt"], globals["PRODUCTS.test/product.mk.PRODUCT_COPY_FILES"])
+ assert_eq(["foo/bar/baz.txt:vendor/etc/baz.txt"], globals["PRODUCTS.test/inherit2.mk.PRODUCT_COPY_FILES"])
+ assert_eq(["foo/bar/baz.txt:vendor/etc/baz.txt"], globals["PRODUCTS.test/inherit3.mk.PRODUCT_COPY_FILES"])
diff --git a/tests/run.rbc b/tests/run.rbc
index b82887f..56ba394 100644
--- a/tests/run.rbc
+++ b/tests/run.rbc
@@ -25,12 +25,21 @@
load(":product.rbc", "init")
load(":board.rbc", board_init = "init")
load(":board_input_vars.rbc", board_input_vars_init = "init")
+load("//build/make/tests/single_value_inheritance:test.rbc", test_single_value_inheritance = "test")
+load("//build/make/tests/artifact_path_requirements:test.rbc", test_artifact_path_requirements = "test")
def assert_eq(expected, actual):
if expected != actual:
fail("Expected '%s', got '%s'" % (expected, actual))
+def assert_dict_subset(expected, actual):
+ for key, val in expected.items():
+ assert_eq(val, actual[key])
+
# Unit tests for non-trivial runtime functions
+assert_eq(["a", "b", "c"], rblf.mksort("b a c c"))
+assert_eq(["a", "b", "c"], rblf.mksort(["b", "a", "c", "c"]))
+
assert_eq("", rblf.mkstrip(" \n \t "))
assert_eq("a b c", rblf.mkstrip(" a b \n c \t"))
assert_eq(1, rblf.mkstrip(1))
@@ -52,7 +61,11 @@
assert_eq(["from/a:to/a", "from/b:to/b"], rblf.product_copy_files_by_pattern("from/%", "to/%", "a b"))
assert_eq([], rblf.filter(["a", "", "b"], "f"))
-assert_eq(["", "b"], rblf.filter_out(["a", "" ], ["a", "", "b"] ))
+assert_eq(["ab%c", "axyzb%c"], rblf.filter(["a%b%c"], ["ab%c", "axyzb%c", "axyzb%cd", "axyzbwc"]))
+assert_eq(["abc", "bcd"], rblf.filter(["a%", "b%"], ["abc", "def", "bcd", "xabc"]))
+assert_eq(["b", "ab"], rblf.filter_out(["a", "" ], ["a", "", "b", "ab"]))
+assert_eq(["c"], rblf.filter_out(["a", "b" ], ["a", "b", "c"]))
+assert_eq(["c"], rblf.filter_out(["a%", "b" ], ["abc", "b", "c"]))
assert_eq("foo.c no_folder", rblf.notdir(["src/foo.c", "no_folder"]))
assert_eq("foo.c no_folder", rblf.notdir("src/foo.c no_folder"))
@@ -72,31 +85,28 @@
rblf.expand_wildcard("build/make/tests/run.rbc build/make/tests/nonexistent.rbc")
)
-(globals, config, globals_base) = rblf.product_configuration("test/device", init, input_variables_init)
-assert_eq(
- {
- "PRODUCT_COPY_FILES": [
- "part_from:part_to",
- "device_from:device_to",
- "device/google/redfin/audio/audio_platform_info_noextcodec_snd.xml:||VENDOR-PATH-PH||/etc/audio/audio_platform_info_noextcodec_snd.xml",
- "xyz:/etc/xyz",
- "x.xml:/etc/x.xml",
- "y.xml:/etc/y.xml",
- "from/sub/x:to/x",
- "from/sub/y:to/y",
- ],
- "PRODUCT_HOST_PACKAGES": ["host"],
- "PRODUCT_PACKAGES": [
- "dev",
- "inc",
- "dev_after",
- "board1_in",
- "board1_is",
- ],
- "PRODUCT_PRODUCT_PROPERTIES": ["part_properties"]
- },
- { k:v for k, v in sorted(config.items()) }
-)
+(globals, globals_base) = rblf.product_configuration("test/device", init, input_variables_init)
+assert_dict_subset({
+ "PRODUCTS.test/device.mk.PRODUCT_COPY_FILES": [
+ "part_from:part_to",
+ "device_from:device_to",
+ "device/google/redfin/audio/audio_platform_info_noextcodec_snd.xml:||VENDOR-PATH-PH||/etc/audio/audio_platform_info_noextcodec_snd.xml",
+ "xyz:/etc/xyz",
+ "x.xml:/etc/x.xml",
+ "y.xml:/etc/y.xml",
+ "from/sub/x:to/x",
+ "from/sub/y:to/y",
+ ],
+ "PRODUCTS.test/device.mk.PRODUCT_HOST_PACKAGES": ["host"],
+ "PRODUCTS.test/device.mk.PRODUCT_PACKAGES": [
+ "dev",
+ "inc",
+ "dev_after",
+ "board1_in",
+ "board1_is",
+ ],
+ "PRODUCTS.test/device.mk.PRODUCT_PRODUCT_PROPERTIES": ["part_properties"]
+}, globals)
ns = globals["$SOONG_CONFIG_NAMESPACES"]
assert_eq(
@@ -126,6 +136,9 @@
{ k:v for k,v in sorted(goals.items()) }
)
-(board_globals, board_config, board_globals_base) = rblf.board_configuration(board_init, board_input_vars_init)
+(board_globals, board_globals_base) = rblf.board_configuration(board_init, board_input_vars_init)
assert_eq({"A_LIST_VARIABLE": ["foo", "bar"]}, board_globals)
assert_eq({"A_LIST_VARIABLE": ["foo"]}, board_globals_base)
+
+test_single_value_inheritance()
+test_artifact_path_requirements()
diff --git a/tests/single_value_inheritance/inherit1.rbc b/tests/single_value_inheritance/inherit1.rbc
new file mode 100644
index 0000000..0cc98a9
--- /dev/null
+++ b/tests/single_value_inheritance/inherit1.rbc
@@ -0,0 +1,23 @@
+# Copyright 2022 Google LLC
+#
+# 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
+#
+# https://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.
+
+load("//build/make/core:product_config.rbc", "rblf")
+
+def init(g, handle):
+ cfg = rblf.cfg(handle)
+
+ cfg["PRODUCT_CHARACTERISTICS"] = "tablet"
+ cfg["PRODUCT_DEFAULT_DEV_CERTIFICATE"] = "vendor/myvendor/certs/devkeys/devkey"
+ cfg.setdefault("PRODUCT_PACKAGES", [])
+ cfg["PRODUCT_PACKAGES"] += ["bar"]
diff --git a/tests/single_value_inheritance/inherit2.rbc b/tests/single_value_inheritance/inherit2.rbc
new file mode 100644
index 0000000..ed5e569
--- /dev/null
+++ b/tests/single_value_inheritance/inherit2.rbc
@@ -0,0 +1,22 @@
+# Copyright 2022 Google LLC
+#
+# 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
+#
+# https://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.
+
+load("//build/make/core:product_config.rbc", "rblf")
+
+def init(g, handle):
+ cfg = rblf.cfg(handle)
+
+ cfg["PRODUCT_CHARACTERISTICS"] = "nosdcard"
+ cfg.setdefault("PRODUCT_PACKAGES", [])
+ cfg["PRODUCT_PACKAGES"] += ["foo"]
diff --git a/tests/single_value_inheritance/product.rbc b/tests/single_value_inheritance/product.rbc
new file mode 100644
index 0000000..d090af6
--- /dev/null
+++ b/tests/single_value_inheritance/product.rbc
@@ -0,0 +1,24 @@
+# Copyright 2022 Google LLC
+#
+# 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
+#
+# https://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.
+
+load("//build/make/core:product_config.rbc", "rblf")
+load(":inherit1.rbc", _inherit1_init = "init")
+load(":inherit2.rbc", _inherit2_init = "init")
+
+def init(g, handle):
+ cfg = rblf.cfg(handle)
+ rblf.inherit(handle, "test/inherit2", _inherit2_init)
+ rblf.inherit(handle, "test/inherit1", _inherit1_init)
+
+ cfg["PRODUCT_DEFAULT_DEV_CERTIFICATE"] = ""
diff --git a/tests/single_value_inheritance/test.rbc b/tests/single_value_inheritance/test.rbc
new file mode 100644
index 0000000..e4f44f4
--- /dev/null
+++ b/tests/single_value_inheritance/test.rbc
@@ -0,0 +1,28 @@
+# Copyright 2022 Google LLC
+#
+# 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
+#
+# https://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.
+
+load("//build/make/core:product_config.rbc", "rblf")
+load("//build/make/tests/input_variables.rbc", input_variables_init = "init")
+load(":product.rbc", "init")
+
+
+def assert_eq(expected, actual):
+ if expected != actual:
+ fail("Expected '%s', got '%s'" % (expected, actual))
+
+def test():
+ (globals, globals_base) = rblf.product_configuration("test/device", init, input_variables_init)
+ assert_eq("tablet", globals["PRODUCTS.test/device.mk.PRODUCT_CHARACTERISTICS"])
+ assert_eq("vendor/myvendor/certs/devkeys/devkey", globals["PRODUCTS.test/device.mk.PRODUCT_DEFAULT_DEV_CERTIFICATE"])
+ assert_eq(["foo", "bar"], globals["PRODUCTS.test/device.mk.PRODUCT_PACKAGES"])
diff --git a/tools/checkowners.py b/tools/checkowners.py
index d6853d8..f037321 100755
--- a/tools/checkowners.py
+++ b/tools/checkowners.py
@@ -5,8 +5,8 @@
import argparse
import re
import sys
-import urllib
-import urllib2
+import urllib.request, urllib.parse, urllib.error
+import urllib.request, urllib.error, urllib.parse
parser = argparse.ArgumentParser(description='Check OWNERS file syntax')
parser.add_argument('-v', '--verbose', dest='verbose',
@@ -25,15 +25,15 @@
def echo(msg):
if args.verbose:
- print msg
+ print(msg)
def find_address(address):
if address not in checked_addresses:
request = (gerrit_server + '/accounts/?n=1&q=email:'
- + urllib.quote(address))
+ + urllib.parse.quote(address))
echo('Checking email address: ' + address)
- result = urllib2.urlopen(request).read()
+ result = urllib.request.urlopen(request).read()
checked_addresses[address] = result.find('"_account_id":') >= 0
if checked_addresses[address]:
echo('Found email address: ' + address)
@@ -43,7 +43,7 @@
def check_address(fname, num, address):
if find_address(address):
return 0
- print '%s:%d: ERROR: unknown email address: %s' % (fname, num, address)
+ print('%s:%d: ERROR: unknown email address: %s' % (fname, num, address))
return 1
@@ -72,7 +72,7 @@
stripped_line = re.sub('#.*$', '', line).strip()
if not patterns.match(stripped_line):
error += 1
- print '%s:%d: ERROR: unknown line [%s]' % (fname, num, line.strip())
+ print('%s:%d: ERROR: unknown line [%s]' % (fname, num, line.strip()))
elif args.check_address:
if perfile_pattern.match(stripped_line):
for addr in perfile_pattern.match(stripped_line).group(1).split(','):
diff --git a/tools/compliance/Android.bp b/tools/compliance/Android.bp
index ec0f2f9..7a6c4ba 100644
--- a/tools/compliance/Android.bp
+++ b/tools/compliance/Android.bp
@@ -18,7 +18,7 @@
}
blueprint_go_binary {
- name: "checkshare",
+ name: "compliance_checkshare",
srcs: ["cmd/checkshare/checkshare.go"],
deps: ["compliance-module"],
testSrcs: ["cmd/checkshare/checkshare_test.go"],
@@ -42,21 +42,21 @@
}
blueprint_go_binary {
- name: "listshare",
+ name: "compliance_listshare",
srcs: ["cmd/listshare/listshare.go"],
deps: ["compliance-module"],
testSrcs: ["cmd/listshare/listshare_test.go"],
}
blueprint_go_binary {
- name: "dumpgraph",
+ name: "compliance_dumpgraph",
srcs: ["cmd/dumpgraph/dumpgraph.go"],
deps: ["compliance-module"],
testSrcs: ["cmd/dumpgraph/dumpgraph_test.go"],
}
blueprint_go_binary {
- name: "dumpresolutions",
+ name: "compliance_dumpresolutions",
srcs: ["cmd/dumpresolutions/dumpresolutions.go"],
deps: ["compliance-module"],
testSrcs: ["cmd/dumpresolutions/dumpresolutions_test.go"],
@@ -73,7 +73,7 @@
}
blueprint_go_binary {
- name: "rtrace",
+ name: "compliance_rtrace",
srcs: ["cmd/rtrace/rtrace.go"],
deps: ["compliance-module"],
testSrcs: ["cmd/rtrace/rtrace_test.go"],
diff --git a/tools/compliance/cmd/bom/bom.go b/tools/compliance/cmd/bom/bom.go
index 5363a59..b613a1f 100644
--- a/tools/compliance/cmd/bom/bom.go
+++ b/tools/compliance/cmd/bom/bom.go
@@ -116,7 +116,7 @@
ofile = &bytes.Buffer{}
}
- ctx := &context{ofile, os.Stderr, os.DirFS("."), *stripPrefix}
+ ctx := &context{ofile, os.Stderr, compliance.FS, *stripPrefix}
err := billOfMaterials(ctx, flag.Args()...)
if err != nil {
diff --git a/tools/compliance/cmd/bom/bom_test.go b/tools/compliance/cmd/bom/bom_test.go
index 4a9889f..87a3b50 100644
--- a/tools/compliance/cmd/bom/bom_test.go
+++ b/tools/compliance/cmd/bom/bom_test.go
@@ -21,6 +21,8 @@
"os"
"strings"
"testing"
+
+ "android/soong/tools/compliance"
)
func TestMain(m *testing.M) {
@@ -37,6 +39,7 @@
tests := []struct {
condition string
name string
+ outDir string
roots []string
stripPrefix string
expectedOut []string
@@ -282,7 +285,7 @@
rootFiles = append(rootFiles, "testdata/"+tt.condition+"/"+r)
}
- ctx := context{stdout, stderr, os.DirFS("."), []string{tt.stripPrefix}}
+ ctx := context{stdout, stderr, compliance.GetFS(tt.outDir), []string{tt.stripPrefix}}
err := billOfMaterials(&ctx, rootFiles...)
if err != nil {
diff --git a/tools/compliance/cmd/checkshare/checkshare.go b/tools/compliance/cmd/checkshare/checkshare.go
index 752d14b..73bdcb5 100644
--- a/tools/compliance/cmd/checkshare/checkshare.go
+++ b/tools/compliance/cmd/checkshare/checkshare.go
@@ -18,6 +18,7 @@
"flag"
"fmt"
"io"
+ "io/fs"
"os"
"path/filepath"
"sort"
@@ -68,7 +69,7 @@
os.Exit(2)
}
- err := checkShare(os.Stdout, os.Stderr, flag.Args()...)
+ err := checkShare(os.Stdout, os.Stderr, compliance.FS, flag.Args()...)
if err != nil {
if err != failConflicts {
if err == failNoneRequested {
@@ -82,14 +83,14 @@
}
// checkShare implements the checkshare utility.
-func checkShare(stdout, stderr io.Writer, files ...string) error {
+func checkShare(stdout, stderr io.Writer, rootFS fs.FS, files ...string) error {
if len(files) < 1 {
return failNoneRequested
}
// Read the license graph from the license metadata files (*.meta_lic).
- licenseGraph, err := compliance.ReadLicenseGraph(os.DirFS("."), stderr, files)
+ licenseGraph, err := compliance.ReadLicenseGraph(rootFS, stderr, files)
if err != nil {
return fmt.Errorf("Unable to read license metadata file(s) %q: %w\n", files, err)
}
diff --git a/tools/compliance/cmd/checkshare/checkshare_test.go b/tools/compliance/cmd/checkshare/checkshare_test.go
index c9b62e1..fdcab29 100644
--- a/tools/compliance/cmd/checkshare/checkshare_test.go
+++ b/tools/compliance/cmd/checkshare/checkshare_test.go
@@ -20,6 +20,8 @@
"os"
"strings"
"testing"
+
+ "android/soong/tools/compliance"
)
func TestMain(m *testing.M) {
@@ -56,6 +58,7 @@
tests := []struct {
condition string
name string
+ outDir string
roots []string
expectedStdout string
expectedOutcomes outcomeList
@@ -248,7 +251,7 @@
for _, r := range tt.roots {
rootFiles = append(rootFiles, "testdata/"+tt.condition+"/"+r)
}
- err := checkShare(stdout, stderr, rootFiles...)
+ err := checkShare(stdout, stderr, compliance.GetFS(tt.outDir), rootFiles...)
if err != nil && err != failConflicts {
t.Fatalf("checkshare: error = %v, stderr = %v", err, stderr)
return
diff --git a/tools/compliance/cmd/dumpgraph/dumpgraph.go b/tools/compliance/cmd/dumpgraph/dumpgraph.go
index fa16b1b..32a3fc4 100644
--- a/tools/compliance/cmd/dumpgraph/dumpgraph.go
+++ b/tools/compliance/cmd/dumpgraph/dumpgraph.go
@@ -18,6 +18,7 @@
"flag"
"fmt"
"io"
+ "io/fs"
"os"
"path/filepath"
"sort"
@@ -97,7 +98,7 @@
ctx := &context{*graphViz, *labelConditions, *stripPrefix}
- err := dumpGraph(ctx, os.Stdout, os.Stderr, flag.Args()...)
+ err := dumpGraph(ctx, os.Stdout, os.Stderr, compliance.FS, flag.Args()...)
if err != nil {
if err == failNoneRequested {
flag.Usage()
@@ -109,13 +110,13 @@
}
// dumpGraph implements the dumpgraph utility.
-func dumpGraph(ctx *context, stdout, stderr io.Writer, files ...string) error {
+func dumpGraph(ctx *context, stdout, stderr io.Writer, rootFS fs.FS, files ...string) error {
if len(files) < 1 {
return failNoneRequested
}
// Read the license graph from the license metadata files (*.meta_lic).
- licenseGraph, err := compliance.ReadLicenseGraph(os.DirFS("."), stderr, files)
+ licenseGraph, err := compliance.ReadLicenseGraph(rootFS, stderr, files)
if err != nil {
return fmt.Errorf("Unable to read license metadata file(s) %q: %w\n", files, err)
}
diff --git a/tools/compliance/cmd/dumpgraph/dumpgraph_test.go b/tools/compliance/cmd/dumpgraph/dumpgraph_test.go
index 67b2b40..d1deed3 100644
--- a/tools/compliance/cmd/dumpgraph/dumpgraph_test.go
+++ b/tools/compliance/cmd/dumpgraph/dumpgraph_test.go
@@ -20,6 +20,8 @@
"os"
"strings"
"testing"
+
+ "android/soong/tools/compliance"
)
func TestMain(m *testing.M) {
@@ -36,6 +38,7 @@
tests := []struct {
condition string
name string
+ outDir string
roots []string
ctx context
expectedOut []string
@@ -491,7 +494,7 @@
for _, r := range tt.roots {
rootFiles = append(rootFiles, "testdata/"+tt.condition+"/"+r)
}
- err := dumpGraph(&tt.ctx, stdout, stderr, rootFiles...)
+ err := dumpGraph(&tt.ctx, stdout, stderr, compliance.GetFS(tt.outDir), rootFiles...)
if err != nil {
t.Fatalf("dumpgraph: error = %v, stderr = %v", err, stderr)
return
@@ -583,6 +586,7 @@
tests := []struct {
condition string
name string
+ outDir string
roots []string
ctx context
expectedOut []getMatcher
@@ -1217,7 +1221,7 @@
rootFiles = append(rootFiles, "testdata/"+tt.condition+"/"+r)
}
tt.ctx.graphViz = true
- err := dumpGraph(&tt.ctx, stdout, stderr, rootFiles...)
+ err := dumpGraph(&tt.ctx, stdout, stderr, compliance.GetFS(tt.outDir), rootFiles...)
if err != nil {
t.Fatalf("dumpgraph: error = %v, stderr = %v", err, stderr)
return
diff --git a/tools/compliance/cmd/dumpresolutions/dumpresolutions.go b/tools/compliance/cmd/dumpresolutions/dumpresolutions.go
index 9c5e972..d02c238 100644
--- a/tools/compliance/cmd/dumpresolutions/dumpresolutions.go
+++ b/tools/compliance/cmd/dumpresolutions/dumpresolutions.go
@@ -18,6 +18,7 @@
"flag"
"fmt"
"io"
+ "io/fs"
"os"
"path/filepath"
"sort"
@@ -110,7 +111,7 @@
labelConditions: *labelConditions,
stripPrefix: *stripPrefix,
}
- _, err := dumpResolutions(ctx, os.Stdout, os.Stderr, flag.Args()...)
+ _, err := dumpResolutions(ctx, os.Stdout, os.Stderr, compliance.FS, flag.Args()...)
if err != nil {
if err == failNoneRequested {
flag.Usage()
@@ -122,13 +123,13 @@
}
// dumpResolutions implements the dumpresolutions utility.
-func dumpResolutions(ctx *context, stdout, stderr io.Writer, files ...string) (*compliance.LicenseGraph, error) {
+func dumpResolutions(ctx *context, stdout, stderr io.Writer, rootFS fs.FS, files ...string) (*compliance.LicenseGraph, error) {
if len(files) < 1 {
return nil, failNoneRequested
}
// Read the license graph from the license metadata files (*.meta_lic).
- licenseGraph, err := compliance.ReadLicenseGraph(os.DirFS("."), stderr, files)
+ licenseGraph, err := compliance.ReadLicenseGraph(rootFS, stderr, files)
if err != nil {
return nil, fmt.Errorf("Unable to read license metadata file(s) %q: %v\n", files, err)
}
diff --git a/tools/compliance/cmd/dumpresolutions/dumpresolutions_test.go b/tools/compliance/cmd/dumpresolutions/dumpresolutions_test.go
index 6fe1e8a..63fd157 100644
--- a/tools/compliance/cmd/dumpresolutions/dumpresolutions_test.go
+++ b/tools/compliance/cmd/dumpresolutions/dumpresolutions_test.go
@@ -38,6 +38,7 @@
tests := []struct {
condition string
name string
+ outDir string
roots []string
ctx context
expectedOut []string
@@ -902,7 +903,7 @@
for _, r := range tt.roots {
rootFiles = append(rootFiles, "testdata/"+tt.condition+"/"+r)
}
- _, err := dumpResolutions(&tt.ctx, stdout, stderr, rootFiles...)
+ _, err := dumpResolutions(&tt.ctx, stdout, stderr, compliance.GetFS(tt.outDir), rootFiles...)
if err != nil {
t.Fatalf("dumpresolutions: error = %v, stderr = %v", err, stderr)
return
@@ -1011,6 +1012,7 @@
tests := []struct {
condition string
name string
+ outDir string
roots []string
ctx context
expectedOut []getMatcher
@@ -3298,7 +3300,7 @@
rootFiles = append(rootFiles, "testdata/"+tt.condition+"/"+r)
}
tt.ctx.graphViz = true
- lg, err := dumpResolutions(&tt.ctx, stdout, stderr, rootFiles...)
+ lg, err := dumpResolutions(&tt.ctx, stdout, stderr, compliance.GetFS(tt.outDir), rootFiles...)
if err != nil {
t.Fatalf("dumpresolutions: error = %v, stderr = %v", err, stderr)
return
diff --git a/tools/compliance/cmd/htmlnotice/htmlnotice.go b/tools/compliance/cmd/htmlnotice/htmlnotice.go
index ffb0585..e98b272 100644
--- a/tools/compliance/cmd/htmlnotice/htmlnotice.go
+++ b/tools/compliance/cmd/htmlnotice/htmlnotice.go
@@ -141,7 +141,7 @@
var deps []string
- ctx := &context{ofile, os.Stderr, os.DirFS("."), *includeTOC, *product, *stripPrefix, *title, &deps}
+ ctx := &context{ofile, os.Stderr, compliance.FS, *includeTOC, *product, *stripPrefix, *title, &deps}
err := htmlNotice(ctx, flag.Args()...)
if err != nil {
diff --git a/tools/compliance/cmd/htmlnotice/htmlnotice_test.go b/tools/compliance/cmd/htmlnotice/htmlnotice_test.go
index 1b01d16..b927018 100644
--- a/tools/compliance/cmd/htmlnotice/htmlnotice_test.go
+++ b/tools/compliance/cmd/htmlnotice/htmlnotice_test.go
@@ -24,6 +24,8 @@
"regexp"
"strings"
"testing"
+
+ "android/soong/tools/compliance"
)
var (
@@ -54,6 +56,7 @@
tests := []struct {
condition string
name string
+ outDir string
roots []string
includeTOC bool
stripPrefix string
@@ -651,7 +654,7 @@
var deps []string
- ctx := context{stdout, stderr, os.DirFS("."), tt.includeTOC, "", []string{tt.stripPrefix}, tt.title, &deps}
+ ctx := context{stdout, stderr, compliance.GetFS(tt.outDir), tt.includeTOC, "", []string{tt.stripPrefix}, tt.title, &deps}
err := htmlNotice(&ctx, rootFiles...)
if err != nil {
diff --git a/tools/compliance/cmd/listshare/listshare.go b/tools/compliance/cmd/listshare/listshare.go
index 030caa7..7f4038b 100644
--- a/tools/compliance/cmd/listshare/listshare.go
+++ b/tools/compliance/cmd/listshare/listshare.go
@@ -18,6 +18,7 @@
"flag"
"fmt"
"io"
+ "io/fs"
"os"
"path/filepath"
"sort"
@@ -54,7 +55,7 @@
os.Exit(2)
}
- err := listShare(os.Stdout, os.Stderr, flag.Args()...)
+ err := listShare(os.Stdout, os.Stderr, compliance.FS, flag.Args()...)
if err != nil {
if err == failNoneRequested {
flag.Usage()
@@ -66,14 +67,14 @@
}
// listShare implements the listshare utility.
-func listShare(stdout, stderr io.Writer, files ...string) error {
+func listShare(stdout, stderr io.Writer, rootFS fs.FS, files ...string) error {
// Must be at least one root file.
if len(files) < 1 {
return failNoneRequested
}
// Read the license graph from the license metadata files (*.meta_lic).
- licenseGraph, err := compliance.ReadLicenseGraph(os.DirFS("."), stderr, files)
+ licenseGraph, err := compliance.ReadLicenseGraph(rootFS, stderr, files)
if err != nil {
return fmt.Errorf("Unable to read license metadata file(s) %q: %v\n", files, err)
}
diff --git a/tools/compliance/cmd/listshare/listshare_test.go b/tools/compliance/cmd/listshare/listshare_test.go
index 91e9a43..c1e38be 100644
--- a/tools/compliance/cmd/listshare/listshare_test.go
+++ b/tools/compliance/cmd/listshare/listshare_test.go
@@ -20,6 +20,8 @@
"os"
"strings"
"testing"
+
+ "android/soong/tools/compliance"
)
func TestMain(m *testing.M) {
@@ -40,6 +42,7 @@
tests := []struct {
condition string
name string
+ outDir string
roots []string
expectedOut []projectShare
}{
@@ -481,7 +484,7 @@
for _, r := range tt.roots {
rootFiles = append(rootFiles, "testdata/"+tt.condition+"/"+r)
}
- err := listShare(stdout, stderr, rootFiles...)
+ err := listShare(stdout, stderr, compliance.GetFS(tt.outDir), rootFiles...)
if err != nil {
t.Fatalf("listshare: error = %v, stderr = %v", err, stderr)
return
diff --git a/tools/compliance/cmd/rtrace/rtrace.go b/tools/compliance/cmd/rtrace/rtrace.go
index 7c63979..91171c4 100644
--- a/tools/compliance/cmd/rtrace/rtrace.go
+++ b/tools/compliance/cmd/rtrace/rtrace.go
@@ -18,6 +18,7 @@
"flag"
"fmt"
"io"
+ "io/fs"
"os"
"path/filepath"
"sort"
@@ -107,7 +108,7 @@
sources: *sources,
stripPrefix: *stripPrefix,
}
- _, err := traceRestricted(ctx, os.Stdout, os.Stderr, flag.Args()...)
+ _, err := traceRestricted(ctx, os.Stdout, os.Stderr, compliance.FS, flag.Args()...)
if err != nil {
if err == failNoneRequested {
flag.Usage()
@@ -119,7 +120,7 @@
}
// traceRestricted implements the rtrace utility.
-func traceRestricted(ctx *context, stdout, stderr io.Writer, files ...string) (*compliance.LicenseGraph, error) {
+func traceRestricted(ctx *context, stdout, stderr io.Writer, rootFS fs.FS, files ...string) (*compliance.LicenseGraph, error) {
if len(files) < 1 {
return nil, failNoneRequested
}
@@ -129,7 +130,7 @@
}
// Read the license graph from the license metadata files (*.meta_lic).
- licenseGraph, err := compliance.ReadLicenseGraph(os.DirFS("."), stderr, files)
+ licenseGraph, err := compliance.ReadLicenseGraph(rootFS, stderr, files)
if err != nil {
return nil, fmt.Errorf("Unable to read license metadata file(s) %q: %v\n", files, err)
}
diff --git a/tools/compliance/cmd/rtrace/rtrace_test.go b/tools/compliance/cmd/rtrace/rtrace_test.go
index a8eb884..cbe9461 100644
--- a/tools/compliance/cmd/rtrace/rtrace_test.go
+++ b/tools/compliance/cmd/rtrace/rtrace_test.go
@@ -20,6 +20,8 @@
"os"
"strings"
"testing"
+
+ "android/soong/tools/compliance"
)
func TestMain(m *testing.M) {
@@ -36,6 +38,7 @@
tests := []struct {
condition string
name string
+ outDir string
roots []string
ctx context
expectedOut []string
@@ -289,7 +292,7 @@
if len(tt.ctx.sources) < 1 {
tt.ctx.sources = rootFiles
}
- _, err := traceRestricted(&tt.ctx, stdout, stderr, rootFiles...)
+ _, err := traceRestricted(&tt.ctx, stdout, stderr, compliance.GetFS(tt.outDir), rootFiles...)
t.Logf("rtrace: stderr = %v", stderr)
t.Logf("rtrace: stdout = %v", stdout)
if err != nil {
diff --git a/tools/compliance/cmd/shippedlibs/shippedlibs.go b/tools/compliance/cmd/shippedlibs/shippedlibs.go
index 94b19f1..9d25dd3 100644
--- a/tools/compliance/cmd/shippedlibs/shippedlibs.go
+++ b/tools/compliance/cmd/shippedlibs/shippedlibs.go
@@ -117,7 +117,7 @@
ofile = &bytes.Buffer{}
}
- ctx := &context{ofile, os.Stderr, os.DirFS(".")}
+ ctx := &context{ofile, os.Stderr, compliance.FS}
err = shippedLibs(ctx, flags.Args()...)
if err != nil {
diff --git a/tools/compliance/cmd/shippedlibs/shippedlibs_test.go b/tools/compliance/cmd/shippedlibs/shippedlibs_test.go
index b6aad6d..983747c 100644
--- a/tools/compliance/cmd/shippedlibs/shippedlibs_test.go
+++ b/tools/compliance/cmd/shippedlibs/shippedlibs_test.go
@@ -21,6 +21,8 @@
"os"
"strings"
"testing"
+
+ "android/soong/tools/compliance"
)
func TestMain(m *testing.M) {
@@ -37,6 +39,7 @@
tests := []struct {
condition string
name string
+ outDir string
roots []string
expectedOut []string
}{
@@ -201,7 +204,7 @@
rootFiles = append(rootFiles, "testdata/"+tt.condition+"/"+r)
}
- ctx := context{stdout, stderr, os.DirFS(".")}
+ ctx := context{stdout, stderr, compliance.GetFS(tt.outDir)}
err := shippedLibs(&ctx, rootFiles...)
if err != nil {
diff --git a/tools/compliance/cmd/textnotice/textnotice.go b/tools/compliance/cmd/textnotice/textnotice.go
index 58afb48..cfa0859 100644
--- a/tools/compliance/cmd/textnotice/textnotice.go
+++ b/tools/compliance/cmd/textnotice/textnotice.go
@@ -137,7 +137,7 @@
var deps []string
- ctx := &context{ofile, os.Stderr, os.DirFS("."), *product, *stripPrefix, *title, &deps}
+ ctx := &context{ofile, os.Stderr, compliance.FS, *product, *stripPrefix, *title, &deps}
err := textNotice(ctx, flag.Args()...)
if err != nil {
diff --git a/tools/compliance/cmd/textnotice/textnotice_test.go b/tools/compliance/cmd/textnotice/textnotice_test.go
index 9d8d0ca..e661a44 100644
--- a/tools/compliance/cmd/textnotice/textnotice_test.go
+++ b/tools/compliance/cmd/textnotice/textnotice_test.go
@@ -23,6 +23,8 @@
"regexp"
"strings"
"testing"
+
+ "android/soong/tools/compliance"
)
var (
@@ -43,6 +45,7 @@
tests := []struct {
condition string
name string
+ outDir string
roots []string
stripPrefix string
expectedOut []matcher
@@ -564,7 +567,7 @@
var deps []string
- ctx := context{stdout, stderr, os.DirFS("."), "", []string{tt.stripPrefix}, "", &deps}
+ ctx := context{stdout, stderr, compliance.GetFS(tt.outDir), "", []string{tt.stripPrefix}, "", &deps}
err := textNotice(&ctx, rootFiles...)
if err != nil {
diff --git a/tools/compliance/cmd/xmlnotice/xmlnotice.go b/tools/compliance/cmd/xmlnotice/xmlnotice.go
index 1c712cb..84859d7 100644
--- a/tools/compliance/cmd/xmlnotice/xmlnotice.go
+++ b/tools/compliance/cmd/xmlnotice/xmlnotice.go
@@ -139,7 +139,7 @@
var deps []string
- ctx := &context{ofile, os.Stderr, os.DirFS("."), *product, *stripPrefix, *title, &deps}
+ ctx := &context{ofile, os.Stderr, compliance.FS, *product, *stripPrefix, *title, &deps}
err := xmlNotice(ctx, flag.Args()...)
if err != nil {
diff --git a/tools/compliance/cmd/xmlnotice/xmlnotice_test.go b/tools/compliance/cmd/xmlnotice/xmlnotice_test.go
index 424c95e..731e783 100644
--- a/tools/compliance/cmd/xmlnotice/xmlnotice_test.go
+++ b/tools/compliance/cmd/xmlnotice/xmlnotice_test.go
@@ -24,6 +24,8 @@
"regexp"
"strings"
"testing"
+
+ "android/soong/tools/compliance"
)
var (
@@ -45,6 +47,7 @@
tests := []struct {
condition string
name string
+ outDir string
roots []string
stripPrefix string
expectedOut []matcher
@@ -459,7 +462,7 @@
var deps []string
- ctx := context{stdout, stderr, os.DirFS("."), "", []string{tt.stripPrefix}, "", &deps}
+ ctx := context{stdout, stderr, compliance.GetFS(tt.outDir), "", []string{tt.stripPrefix}, "", &deps}
err := xmlNotice(&ctx, rootFiles...)
if err != nil {
diff --git a/tools/compliance/readgraph.go b/tools/compliance/readgraph.go
index 6f91e1c..7516440 100644
--- a/tools/compliance/readgraph.go
+++ b/tools/compliance/readgraph.go
@@ -18,6 +18,7 @@
"fmt"
"io"
"io/fs"
+ "os"
"strings"
"sync"
@@ -31,6 +32,22 @@
ConcurrentReaders = 5
)
+type globalFS struct{}
+
+func (s globalFS) Open(name string) (fs.File, error) {
+ return os.Open(name)
+}
+
+var FS globalFS
+
+// GetFS returns a filesystem for accessing files under the OUT_DIR environment variable.
+func GetFS(outDir string) fs.FS {
+ if len(outDir) > 0 {
+ return os.DirFS(outDir)
+ }
+ return os.DirFS(".")
+}
+
// result describes the outcome of reading and parsing a single license metadata file.
type result struct {
// file identifies the path to the license metadata file
diff --git a/tools/event_log_tags.bzl b/tools/event_log_tags.bzl
index 3766da4..35305ae 100644
--- a/tools/event_log_tags.bzl
+++ b/tools/event_log_tags.bzl
@@ -1,7 +1,6 @@
"""Event log tags generation rule"""
load("@bazel_skylib//lib:paths.bzl", "paths")
-load("@rules_android//rules:rules.bzl", "android_library")
def _event_log_tags_impl(ctx):
out_files = []
@@ -22,7 +21,7 @@
)
return [DefaultInfo(files = depset(out_files))]
-_event_log_tags = rule(
+event_log_tags = rule(
implementation = _event_log_tags_impl,
attrs = {
"srcs": attr.label_list(allow_files = [".logtags"], mandatory = True),
@@ -34,14 +33,3 @@
),
},
)
-
-def event_log_tags(name, srcs):
- _event_log_tags(
- name = name + "_gen_logtags",
- srcs = srcs,
- )
-
- android_library(
- name = name,
- srcs = [name + "_gen_logtags"],
- )
diff --git a/tools/filter-product-graph.py b/tools/filter-product-graph.py
deleted file mode 100755
index b3a5b42..0000000
--- a/tools/filter-product-graph.py
+++ /dev/null
@@ -1,68 +0,0 @@
-#!/usr/bin/env python
-# vim: ts=2 sw=2 nocindent
-
-import re
-import sys
-
-def choose_regex(regs, line):
- for func,reg in regs:
- m = reg.match(line)
- if m:
- return (func,m)
- return (None,None)
-
-def gather(included, deps):
- result = set()
- for inc in included:
- result.add(inc)
- for d in deps:
- if inc == d[1]:
- result.add(d[0])
- return result
-
-def main():
- deps = []
- infos = []
- def dependency(m):
- deps.append((m.group(1), m.group(2)))
- def info(m):
- infos.append((m.group(1), m.group(2)))
-
- REGS = [
- (dependency, re.compile(r'"(.*)"\s*->\s*"(.*)"')),
- (info, re.compile(r'"(.*)"(\s*\[.*\])')),
- ]
-
- lines = sys.stdin.readlines()
- lines = [line.strip() for line in lines]
-
- for line in lines:
- func,m = choose_regex(REGS, line)
- if func:
- func(m)
-
- # filter
- sys.stderr.write("argv: " + str(sys.argv) + "\n")
- if not (len(sys.argv) == 2 and sys.argv[1] == "--all"):
- targets = sys.argv[1:]
-
- included = set(targets)
- prevLen = -1
- while prevLen != len(included):
- prevLen = len(included)
- included = gather(included, deps)
-
- deps = [dep for dep in deps if dep[1] in included]
- infos = [info for info in infos if info[0] in included]
-
- print "digraph {"
- print "graph [ ratio=.5 ];"
- for dep in deps:
- print '"%s" -> "%s"' % dep
- for info in infos:
- print '"%s"%s' % info
- print "}"
-
-
-if __name__ == "__main__":
- main()
diff --git a/tools/mk2bp_catalog.py b/tools/mk2bp_catalog.py
index c2afb9b..3fc6236 100755
--- a/tools/mk2bp_catalog.py
+++ b/tools/mk2bp_catalog.py
@@ -308,19 +308,31 @@
print("""<th class="Count Warning">%s</th>""" % analyzer.title)
print(" </tr>")
+# get all modules in $(PRODUCT_PACKAGE) and the corresponding deps
+def get_module_product_packages_plus_deps(initial_modules, result, soong_data):
+ for module in initial_modules:
+ if module in result:
+ continue
+ result.add(module)
+ if module in soong_data.deps:
+ get_module_product_packages_plus_deps(soong_data.deps[module], result, soong_data)
+
def main():
parser = argparse.ArgumentParser(description="Info about remaining Android.mk files.")
parser.add_argument("--device", type=str, required=True,
help="TARGET_DEVICE")
+ parser.add_argument("--product-packages", type=argparse.FileType('r'),
+ default=None,
+ help="PRODUCT_PACKAGES")
parser.add_argument("--title", type=str,
help="page title")
parser.add_argument("--codesearch", type=str,
default="https://cs.android.com/android/platform/superproject/+/master:",
help="page title")
- parser.add_argument("--out_dir", type=str,
+ parser.add_argument("--out-dir", type=str,
default=None,
help="Equivalent of $OUT_DIR, which will also be checked if"
- + " --out_dir is unset. If neither is set, default is"
+ + " --out-dir is unset. If neither is set, default is"
+ " 'out'.")
parser.add_argument("--mode", type=str,
default="html",
@@ -354,16 +366,25 @@
continue
all_makefiles[filename] = Makefile(filename)
+ # Get all the modules in $(PRODUCT_PACKAGES) and the correspoding deps
+ product_package_modules_plus_deps = set()
+ if args.product_packages:
+ product_package_top_modules = args.product_packages.read().strip().split('\n')
+ get_module_product_packages_plus_deps(product_package_top_modules, product_package_modules_plus_deps, soong)
+
if args.mode == "html":
- HtmlProcessor(args=args, soong=soong, all_makefiles=all_makefiles).execute()
+ HtmlProcessor(args=args, soong=soong, all_makefiles=all_makefiles,
+ product_packages_modules=product_package_modules_plus_deps).execute()
elif args.mode == "csv":
- CsvProcessor(args=args, soong=soong, all_makefiles=all_makefiles).execute()
+ CsvProcessor(args=args, soong=soong, all_makefiles=all_makefiles,
+ product_packages_modules=product_package_modules_plus_deps).execute()
class HtmlProcessor(object):
- def __init__(self, args, soong, all_makefiles):
+ def __init__(self, args, soong, all_makefiles, product_packages_modules):
self.args = args
self.soong = soong
self.all_makefiles = all_makefiles
+ self.product_packages_modules = product_packages_modules
self.annotations = Annotations()
def execute(self):
@@ -376,6 +397,8 @@
modules_by_partition = dict()
partitions = set()
for installed, module in self.soong.installed.items():
+ if len(self.product_packages_modules) > 0 and module not in self.product_packages_modules:
+ continue
partition = get_partition_from_installed(HOST_OUT_ROOT, PRODUCT_OUT, installed)
modules_by_partition.setdefault(partition, []).append(module)
partitions.add(partition)
@@ -985,10 +1008,11 @@
return "";
class CsvProcessor(object):
- def __init__(self, args, soong, all_makefiles):
+ def __init__(self, args, soong, all_makefiles, product_packages_modules):
self.args = args
self.soong = soong
self.all_makefiles = all_makefiles
+ self.product_packages_modules = product_packages_modules
def execute(self):
csvout = csv.writer(sys.stdout)
@@ -1004,6 +1028,8 @@
for filename in sorted(self.all_makefiles.keys()):
makefile = self.all_makefiles[filename]
for module in self.soong.reverse_makefiles[filename]:
+ if len(self.product_packages_modules) > 0 and module not in self.product_packages_modules:
+ continue
row = [filename, module]
# Partitions
row.append(";".join(sorted(set([get_partition_from_installed(HOST_OUT_ROOT, PRODUCT_OUT,
diff --git a/tools/mk2bp_partition.py b/tools/mk2bp_partition.py
new file mode 100644
index 0000000..30c1135
--- /dev/null
+++ b/tools/mk2bp_partition.py
@@ -0,0 +1,100 @@
+#!/usr/bin/env python3
+
+"""
+The complete list of the remaining Make files in each partition for all lunch targets
+
+How to run?
+python3 $(path-to-file)/mk2bp_partition.py
+"""
+
+from pathlib import Path
+
+import csv
+import datetime
+import os
+import shutil
+import subprocess
+import sys
+import time
+
+def get_top():
+ path = '.'
+ while not os.path.isfile(os.path.join(path, 'build/soong/soong_ui.bash')):
+ if os.path.abspath(path) == '/':
+ sys.exit('Could not find android source tree root.')
+ path = os.path.join(path, '..')
+ return os.path.abspath(path)
+
+# get the values of a build variable
+def get_build_var(variable, product, build_variant):
+ """Returns the result of the shell command get_build_var."""
+ env = {
+ **os.environ,
+ 'TARGET_PRODUCT': product if product else '',
+ 'TARGET_BUILD_VARIANT': build_variant if build_variant else '',
+ }
+ return subprocess.run([
+ 'build/soong/soong_ui.bash',
+ '--dumpvar-mode',
+ variable
+ ], check=True, capture_output=True, env=env, text=True).stdout.strip()
+
+def get_make_file_partitions():
+ lunch_targets = set(get_build_var("all_named_products", "", "").split())
+ total_lunch_targets = len(lunch_targets)
+ makefile_by_partition = dict()
+ partitions = set()
+ current_count = 0
+ start_time = time.time()
+ # cannot run command `m lunch_target`
+ broken_targets = {"mainline_sdk", "ndk"}
+ for lunch_target in sorted(lunch_targets):
+ current_count += 1
+ current_time = time.time()
+ print (current_count, "/", total_lunch_targets, lunch_target, datetime.timedelta(seconds=current_time - start_time))
+ if lunch_target in broken_targets:
+ continue
+ installed_product_out = get_build_var("PRODUCT_OUT", lunch_target, "userdebug")
+ filename = os.path.join(installed_product_out, "mk2bp_remaining.csv")
+ copy_filename = os.path.join(installed_product_out, lunch_target + "_mk2bp_remaining.csv")
+ # only generate if not exists
+ if not os.path.exists(copy_filename):
+ bash_cmd = "bash build/soong/soong_ui.bash --make-mode TARGET_PRODUCT=" + lunch_target
+ bash_cmd += " TARGET_BUILD_VARIANT=userdebug " + filename
+ subprocess.run(bash_cmd, shell=True, text=True, check=True, stdout=subprocess.DEVNULL)
+ # generate a copied .csv file, to avoid possible overwritings
+ with open(copy_filename, "w") as file:
+ shutil.copyfile(filename, copy_filename)
+
+ # open mk2bp_remaining.csv file
+ with open(copy_filename, "r") as csvfile:
+ reader = csv.reader(csvfile, delimiter=",", quotechar='"')
+ # bypass the header row
+ next(reader, None)
+ for row in reader:
+ # read partition information
+ partition = row[2]
+ makefile_by_partition.setdefault(partition, set()).add(row[0])
+ partitions.add(partition)
+
+ # write merged make file list for each partition into a csv file
+ installed_path = Path(installed_product_out).parents[0].as_posix()
+ csv_path = installed_path + "/mk2bp_partition.csv"
+ with open(csv_path, "wt") as csvfile:
+ writer = csv.writer(csvfile, delimiter=",")
+ count_makefile = 0
+ for partition in sorted(partitions):
+ number_file = len(makefile_by_partition[partition])
+ count_makefile += number_file
+ writer.writerow([partition, number_file])
+ for makefile in sorted(makefile_by_partition[partition]):
+ writer.writerow([makefile])
+ row = ["The total count of make files is ", count_makefile]
+ writer.writerow(row)
+
+def main():
+ os.chdir(get_top())
+ get_make_file_partitions()
+
+if __name__ == "__main__":
+ main()
diff --git a/tools/post_process_props.py b/tools/post_process_props.py
index efbf614..38d17a8 100755
--- a/tools/post_process_props.py
+++ b/tools/post_process_props.py
@@ -38,11 +38,6 @@
else:
val = val + ",adb"
prop_list.put("persist.sys.usb.config", val)
- # UsbDeviceManager expects a value here. If it doesn't get it, it will
- # default to "adb". That might not the right policy there, but it's better
- # to be explicit.
- if not prop_list.get_value("persist.sys.usb.config"):
- prop_list.put("persist.sys.usb.config", "none")
def validate_grf_props(prop_list, sdk_version):
"""Validate GRF properties if exist.
diff --git a/tools/rbcrun/host.go b/tools/rbcrun/host.go
index 4915de9..c6e89f0 100644
--- a/tools/rbcrun/host.go
+++ b/tools/rbcrun/host.go
@@ -20,7 +20,6 @@
"os"
"os/exec"
"path/filepath"
- "regexp"
"strings"
"go.starlark.net/starlark"
@@ -125,23 +124,6 @@
return starlark.True, nil
}
-// regexMatch(pattern, s) returns True if s matches pattern (a regex)
-func regexMatch(_ *starlark.Thread, b *starlark.Builtin, args starlark.Tuple,
- kwargs []starlark.Tuple) (starlark.Value, error) {
- var pattern, s string
- if err := starlark.UnpackPositionalArgs(b.Name(), args, kwargs, 2, &pattern, &s); err != nil {
- return starlark.None, err
- }
- match, err := regexp.MatchString(pattern, s)
- if err != nil {
- return starlark.None, err
- }
- if match {
- return starlark.True, nil
- }
- return starlark.False, nil
-}
-
// wildcard(pattern, top=None) expands shell's glob pattern. If 'top' is present,
// the 'top/pattern' is globbed and then 'top/' prefix is removed.
func wildcard(_ *starlark.Thread, b *starlark.Builtin, args starlark.Tuple,
@@ -291,8 +273,6 @@
"rblf_file_exists": starlark.NewBuiltin("rblf_file_exists", fileExists),
// To convert find-copy-subdir and product-copy-files-by pattern
"rblf_find_files": starlark.NewBuiltin("rblf_find_files", find),
- // To convert makefile's $(filter ...)/$(filter-out)
- "rblf_regex": starlark.NewBuiltin("rblf_regex", regexMatch),
// To convert makefile's $(shell cmd)
"rblf_shell": starlark.NewBuiltin("rblf_shell", shell),
// Output to stderr
diff --git a/tools/rbcrun/host_test.go b/tools/rbcrun/host_test.go
index 3be5ee6..97f6ce9 100644
--- a/tools/rbcrun/host_test.go
+++ b/tools/rbcrun/host_test.go
@@ -147,10 +147,6 @@
}
}
-func TestRegex(t *testing.T) {
- exerciseStarlarkTestFile(t, "testdata/regex.star")
-}
-
func TestShell(t *testing.T) {
if err := os.Setenv("TEST_DATA_DIR", dataDir()); err != nil {
t.Fatal(err)
diff --git a/tools/rbcrun/testdata/regex.star b/tools/rbcrun/testdata/regex.star
deleted file mode 100644
index 04e1d42..0000000
--- a/tools/rbcrun/testdata/regex.star
+++ /dev/null
@@ -1,13 +0,0 @@
-# Tests rblf_regex
-load("assert.star", "assert")
-
-
-def test():
- pattern = "^(foo.*bar|abc.*d|1.*)$"
- for w in ("foobar", "fooxbar", "abcxd", "123"):
- assert.true(rblf_regex(pattern, w), "%s should match %s" % (w, pattern))
- for w in ("afoobar", "abcde"):
- assert.true(not rblf_regex(pattern, w), "%s should not match %s" % (w, pattern))
-
-
-test()
diff --git a/tools/releasetools/Android.bp b/tools/releasetools/Android.bp
index 90adcaa..d8e34b7 100644
--- a/tools/releasetools/Android.bp
+++ b/tools/releasetools/Android.bp
@@ -440,46 +440,6 @@
}
python_binary_host {
- name: "merge_builds",
- defaults: ["releasetools_binary_defaults"],
- srcs: [
- "merge_builds.py",
- ],
- libs: [
- "releasetools_build_super_image",
- "releasetools_common",
- ],
-}
-
-python_binary_host {
- name: "merge_target_files",
- defaults: ["releasetools_binary_defaults"],
- srcs: [
- "merge_target_files.py",
- ],
- libs: [
- "releasetools_add_img_to_target_files",
- "releasetools_build_super_image",
- "releasetools_check_target_files_vintf",
- "releasetools_common",
- "releasetools_find_shareduid_violation",
- "releasetools_img_from_target_files",
- "releasetools_ota_from_target_files",
- ],
- required: [
- "checkvintf",
- "host_init_verifier",
- "secilc",
- ],
- target: {
- darwin: {
- // libs dep "releasetools_ota_from_target_files" is disabled on darwin
- enabled: false,
- },
- },
-}
-
-python_binary_host {
name: "ota_from_target_files",
defaults: [
"releasetools_binary_defaults",
@@ -597,11 +557,12 @@
"check_partition_sizes.py",
"check_target_files_signatures.py",
"make_recovery_patch.py",
- "merge_target_files.py",
"ota_package_parser.py",
"sign_apex.py",
"sign_target_files_apks.py",
"validate_target_files.py",
+ ":releasetools_merge_sources",
+ ":releasetools_merge_tests",
"test_*.py",
],
diff --git a/tools/releasetools/OWNERS b/tools/releasetools/OWNERS
index 4ceb6ff..59235e0 100644
--- a/tools/releasetools/OWNERS
+++ b/tools/releasetools/OWNERS
@@ -1,6 +1,3 @@
elsk@google.com
nhdo@google.com
zhangkelvin@google.com
-
-per-file *merge_*.py = danielnorman@google.com, jgalmes@google.com, rseymour@google.com
-
diff --git a/tools/releasetools/add_img_to_target_files.py b/tools/releasetools/add_img_to_target_files.py
index da7e11a..e3db161 100644
--- a/tools/releasetools/add_img_to_target_files.py
+++ b/tools/releasetools/add_img_to_target_files.py
@@ -783,6 +783,7 @@
has_boot = OPTIONS.info_dict.get("no_boot") != "true"
has_init_boot = OPTIONS.info_dict.get("init_boot") == "true"
has_vendor_boot = OPTIONS.info_dict.get("vendor_boot") == "true"
+ has_vendor_kernel_boot = OPTIONS.info_dict.get("vendor_kernel_boot") == "true"
# {vendor,odm,product,system_ext,vendor_dlkm,odm_dlkm, system_dlkm, system, system_other}.img
# can be built from source, or dropped into target_files.zip as a prebuilt blob.
@@ -868,6 +869,19 @@
if output_zip:
vendor_boot_image.AddToZip(output_zip)
+ if has_vendor_kernel_boot:
+ banner("vendor_kernel_boot")
+ vendor_kernel_boot_image = common.GetVendorBootImage(
+ "IMAGES/vendor_kernel_boot.img", "vendor_kernel_boot.img", OPTIONS.input_tmp,
+ "VENDOR_KERNEL_BOOT")
+ if vendor_kernel_boot_image:
+ partitions['vendor_kernel_boot'] = os.path.join(OPTIONS.input_tmp, "IMAGES",
+ "vendor_kernel_boot.img")
+ if not os.path.exists(partitions['vendor_kernel_boot']):
+ vendor_kernel_boot_image.WriteToDir(OPTIONS.input_tmp)
+ if output_zip:
+ vendor_kernel_boot_image.AddToZip(output_zip)
+
recovery_image = None
if has_recovery:
banner("recovery")
diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py
index 9feb8af..bd3af68 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -97,6 +97,7 @@
self.stash_threshold = 0.8
self.logfile = None
self.host_tools = {}
+ self.sepolicy_name = 'sepolicy.apex'
OPTIONS = Options()
@@ -471,10 +472,6 @@
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]
diff --git a/tools/releasetools/merge/Android.bp b/tools/releasetools/merge/Android.bp
new file mode 100644
index 0000000..219acf8
--- /dev/null
+++ b/tools/releasetools/merge/Android.bp
@@ -0,0 +1,75 @@
+// Copyright (C) 2022 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.
+
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+filegroup {
+ name: "releasetools_merge_sources",
+ srcs: [
+ "merge_compatibility_checks.py",
+ "merge_dexopt.py",
+ "merge_meta.py",
+ "merge_target_files.py",
+ "merge_utils.py",
+ ],
+}
+
+filegroup {
+ name: "releasetools_merge_tests",
+ srcs: [
+ "test_merge_compatibility_checks.py",
+ "test_merge_meta.py",
+ "test_merge_utils.py",
+ ],
+}
+
+python_binary_host {
+ name: "merge_target_files",
+ defaults: ["releasetools_binary_defaults"],
+ srcs: [":releasetools_merge_sources"],
+ libs: [
+ "releasetools_add_img_to_target_files",
+ "releasetools_build_super_image",
+ "releasetools_check_target_files_vintf",
+ "releasetools_common",
+ "releasetools_find_shareduid_violation",
+ "releasetools_img_from_target_files",
+ "releasetools_ota_from_target_files",
+ ],
+ required: [
+ "checkvintf",
+ "host_init_verifier",
+ "secilc",
+ ],
+ target: {
+ darwin: {
+ // libs dep "releasetools_ota_from_target_files" is disabled on darwin
+ enabled: false,
+ },
+ },
+}
+
+python_binary_host {
+ name: "merge_builds",
+ defaults: ["releasetools_binary_defaults"],
+ srcs: [
+ "merge_builds.py",
+ ],
+ libs: [
+ "releasetools_build_super_image",
+ "releasetools_common",
+ ],
+}
diff --git a/tools/releasetools/merge/OWNERS b/tools/releasetools/merge/OWNERS
new file mode 100644
index 0000000..9012e3a
--- /dev/null
+++ b/tools/releasetools/merge/OWNERS
@@ -0,0 +1,3 @@
+danielnorman@google.com
+jgalmes@google.com
+rseymour@google.com
diff --git a/tools/releasetools/merge_builds.py b/tools/releasetools/merge/merge_builds.py
similarity index 100%
rename from tools/releasetools/merge_builds.py
rename to tools/releasetools/merge/merge_builds.py
diff --git a/tools/releasetools/merge/merge_compatibility_checks.py b/tools/releasetools/merge/merge_compatibility_checks.py
new file mode 100644
index 0000000..207abe2
--- /dev/null
+++ b/tools/releasetools/merge/merge_compatibility_checks.py
@@ -0,0 +1,206 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2022 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.
+#
+"""Compatibility checks that should be performed on merged target_files."""
+
+import json
+import logging
+import os
+from xml.etree import ElementTree
+
+import apex_utils
+import check_target_files_vintf
+import common
+import find_shareduid_violation
+
+logger = logging.getLogger(__name__)
+OPTIONS = common.OPTIONS
+
+
+def CheckCompatibility(target_files_dir, partition_map):
+ """Runs various compatibility checks.
+
+ Returns a possibly-empty list of error messages.
+ """
+ errors = []
+
+ errors.extend(CheckVintf(target_files_dir))
+ errors.extend(CheckShareduidViolation(target_files_dir, partition_map))
+ errors.extend(CheckApexDuplicatePackages(target_files_dir, partition_map))
+
+ # The remaining checks only use the following partitions:
+ partition_map = {
+ partition: path
+ for partition, path in partition_map.items()
+ if partition in ('system', 'system_ext', 'product', 'vendor', 'odm')
+ }
+
+ errors.extend(CheckInitRcFiles(target_files_dir, partition_map))
+ errors.extend(CheckCombinedSepolicy(target_files_dir, partition_map))
+
+ return errors
+
+
+def CheckVintf(target_files_dir):
+ """Check for any VINTF issues using check_vintf."""
+ errors = []
+ try:
+ if not check_target_files_vintf.CheckVintf(target_files_dir):
+ errors.append('Incompatible VINTF.')
+ except RuntimeError as err:
+ errors.append(str(err))
+ return errors
+
+
+def CheckShareduidViolation(target_files_dir, partition_map):
+ """Check for any APK sharedUserId violations across partition sets.
+
+ Writes results to META/shareduid_violation_modules.json to help
+ with followup debugging.
+ """
+ errors = []
+ violation = find_shareduid_violation.FindShareduidViolation(
+ target_files_dir, partition_map)
+ shareduid_violation_modules = os.path.join(
+ target_files_dir, 'META', 'shareduid_violation_modules.json')
+ with open(shareduid_violation_modules, 'w') as f:
+ # Write the output to a file to enable debugging.
+ f.write(violation)
+
+ # Check for violations across the partition sets.
+ shareduid_errors = common.SharedUidPartitionViolations(
+ json.loads(violation),
+ [OPTIONS.framework_partition_set, OPTIONS.vendor_partition_set])
+ if shareduid_errors:
+ for error in shareduid_errors:
+ errors.append('APK sharedUserId error: %s' % error)
+ errors.append('See APK sharedUserId violations file: %s' %
+ shareduid_violation_modules)
+ return errors
+
+
+def CheckInitRcFiles(target_files_dir, partition_map):
+ """Check for any init.rc issues using host_init_verifier."""
+ try:
+ common.RunHostInitVerifier(
+ product_out=target_files_dir, partition_map=partition_map)
+ except RuntimeError as err:
+ return [str(err)]
+ return []
+
+
+def CheckCombinedSepolicy(target_files_dir, partition_map, execute=True):
+ """Uses secilc to compile a split sepolicy file.
+
+ Depends on various */etc/selinux/* and */etc/vintf/* files within partitions.
+ """
+ errors = []
+
+ def get_file(partition, path):
+ if partition not in partition_map:
+ logger.warning('Cannot load SEPolicy files for missing partition %s',
+ partition)
+ return None
+ file_path = os.path.join(target_files_dir, partition_map[partition], path)
+ if os.path.exists(file_path):
+ return file_path
+ return None
+
+ # Load the kernel sepolicy version from the FCM. This is normally provided
+ # directly to selinux.cpp as a build flag, but is also available in this file.
+ fcm_file = get_file('system', 'etc/vintf/compatibility_matrix.device.xml')
+ if not fcm_file:
+ errors.append('Missing required file for loading sepolicy: '
+ '/system/etc/vintf/compatibility_matrix.device.xml')
+ return errors
+ kernel_sepolicy_version = ElementTree.parse(fcm_file).getroot().find(
+ 'sepolicy/kernel-sepolicy-version').text
+
+ # Load the vendor's plat sepolicy version. This is the version used for
+ # locating sepolicy mapping files.
+ vendor_plat_version_file = get_file('vendor',
+ 'etc/selinux/plat_sepolicy_vers.txt')
+ if not vendor_plat_version_file:
+ errors.append('Missing required sepolicy file %s' %
+ vendor_plat_version_file)
+ return errors
+ with open(vendor_plat_version_file) as f:
+ vendor_plat_version = f.read().strip()
+
+ # Use the same flags and arguments as selinux.cpp OpenSplitPolicy().
+ cmd = ['secilc', '-m', '-M', 'true', '-G', '-N']
+ cmd.extend(['-c', kernel_sepolicy_version])
+ cmd.extend(['-o', os.path.join(target_files_dir, 'META/combined_sepolicy')])
+ cmd.extend(['-f', '/dev/null'])
+
+ required_policy_files = (
+ ('system', 'etc/selinux/plat_sepolicy.cil'),
+ ('system', 'etc/selinux/mapping/%s.cil' % vendor_plat_version),
+ ('vendor', 'etc/selinux/vendor_sepolicy.cil'),
+ ('vendor', 'etc/selinux/plat_pub_versioned.cil'),
+ )
+ for policy in (map(lambda partition_and_path: get_file(*partition_and_path),
+ required_policy_files)):
+ if not policy:
+ errors.append('Missing required sepolicy file %s' % policy)
+ return errors
+ cmd.append(policy)
+
+ optional_policy_files = (
+ ('system', 'etc/selinux/mapping/%s.compat.cil' % vendor_plat_version),
+ ('system_ext', 'etc/selinux/system_ext_sepolicy.cil'),
+ ('system_ext', 'etc/selinux/mapping/%s.cil' % vendor_plat_version),
+ ('product', 'etc/selinux/product_sepolicy.cil'),
+ ('product', 'etc/selinux/mapping/%s.cil' % vendor_plat_version),
+ ('odm', 'etc/selinux/odm_sepolicy.cil'),
+ )
+ for policy in (map(lambda partition_and_path: get_file(*partition_and_path),
+ optional_policy_files)):
+ if policy:
+ cmd.append(policy)
+
+ try:
+ if execute:
+ common.RunAndCheckOutput(cmd)
+ else:
+ return cmd
+ except RuntimeError as err:
+ errors.append(str(err))
+
+ return errors
+
+
+def CheckApexDuplicatePackages(target_files_dir, partition_map):
+ """Checks if the same APEX package name is provided by multiple partitions."""
+ errors = []
+
+ apex_packages = set()
+ for partition in partition_map.keys():
+ try:
+ apex_info = apex_utils.GetApexInfoFromTargetFiles(
+ target_files_dir, partition, compressed_only=False)
+ except RuntimeError as err:
+ errors.append(str(err))
+ apex_info = []
+ partition_apex_packages = set([info.package_name for info in apex_info])
+ duplicates = apex_packages.intersection(partition_apex_packages)
+ if duplicates:
+ errors.append(
+ 'Duplicate APEX package_names found in multiple partitions: %s' %
+ ' '.join(duplicates))
+ apex_packages.update(partition_apex_packages)
+
+ return errors
diff --git a/tools/releasetools/merge/merge_dexopt.py b/tools/releasetools/merge/merge_dexopt.py
new file mode 100644
index 0000000..7bf9bd4
--- /dev/null
+++ b/tools/releasetools/merge/merge_dexopt.py
@@ -0,0 +1,323 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2022 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.
+#
+"""Generates dexopt files for vendor apps, from a merged target_files.
+
+Expects items in OPTIONS prepared by merge_target_files.py.
+"""
+
+import glob
+import json
+import logging
+import os
+import shutil
+import subprocess
+
+import common
+import merge_utils
+
+logger = logging.getLogger(__name__)
+OPTIONS = common.OPTIONS
+
+
+def MergeDexopt(temp_dir, output_target_files_dir):
+ """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.
+ output_target_files_dir: The name of a directory that will be used to create
+ the output target files package after all the special cases are processed.
+ """
+ # Load vendor and framework META/misc_info.txt.
+ if (OPTIONS.vendor_misc_info.get('building_with_vsdk') != 'true' or
+ OPTIONS.framework_dexpreopt_tools is None or
+ OPTIONS.framework_dexpreopt_config is None or
+ OPTIONS.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')
+
+ merge_utils.ExtractItems(
+ input_zip=OPTIONS.framework_dexpreopt_tools,
+ output_dir=dexpreopt_tools_files_temp_dir,
+ extract_item_list=('*',))
+ merge_utils.ExtractItems(
+ input_zip=OPTIONS.framework_dexpreopt_config,
+ output_dir=dexpreopt_framework_config_files_temp_dir,
+ extract_item_list=('*',))
+ merge_utils.ExtractItems(
+ input_zip=OPTIONS.vendor_dexpreopt_config,
+ output_dir=dexpreopt_vendor_config_files_temp_dir,
+ extract_item_list=('*',))
+
+ os.symlink(
+ os.path.join(output_target_files_dir, 'SYSTEM'),
+ os.path.join(temp_dir, 'system'))
+ os.symlink(
+ os.path.join(output_target_files_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_dir, 'SYSTEM', 'apex')
+
+ # Check for flattended versus updatable APEX.
+ if OPTIONS.framework_misc_info.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_dir, 'IMAGES', 'vendor.img')
+ if os.path.exists(vendor_img):
+ logging.info('Deleting %s', vendor_img)
+ os.remove(vendor_img)
diff --git a/tools/releasetools/merge/merge_meta.py b/tools/releasetools/merge/merge_meta.py
new file mode 100644
index 0000000..580b3ce
--- /dev/null
+++ b/tools/releasetools/merge/merge_meta.py
@@ -0,0 +1,287 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2022 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.
+#
+"""Functions for merging META/* files from partial builds.
+
+Expects items in OPTIONS prepared by merge_target_files.py.
+"""
+
+import logging
+import os
+import re
+import shutil
+
+import build_image
+import common
+import merge_utils
+import sparse_img
+import verity_utils
+
+from common import ExternalError
+
+logger = logging.getLogger(__name__)
+
+OPTIONS = common.OPTIONS
+
+# In apexkeys.txt or apkcerts.txt, we will find partition tags on each entry in
+# the file. We use these partition tags to filter the entries in those files
+# from the two different target files packages to produce a merged apexkeys.txt
+# or apkcerts.txt file. A partition tag (e.g., for the product partition) looks
+# like this: 'partition="product"'. We use the group syntax grab the value of
+# the tag. We use non-greedy matching in case there are other fields on the
+# same line.
+
+PARTITION_TAG_PATTERN = re.compile(r'partition="(.*?)"')
+
+# The sorting algorithm for apexkeys.txt and apkcerts.txt does not include the
+# ".apex" or ".apk" suffix, so we use the following pattern to extract a key.
+
+MODULE_KEY_PATTERN = re.compile(r'name="(.+)\.(apex|apk)"')
+
+
+def MergeMetaFiles(temp_dir, merged_dir):
+ """Merges various files in META/*."""
+
+ framework_meta_dir = os.path.join(temp_dir, 'framework_meta', 'META')
+ merge_utils.ExtractItems(
+ input_zip=OPTIONS.framework_target_files,
+ output_dir=os.path.dirname(framework_meta_dir),
+ extract_item_list=('META/*',))
+
+ vendor_meta_dir = os.path.join(temp_dir, 'vendor_meta', 'META')
+ merge_utils.ExtractItems(
+ input_zip=OPTIONS.vendor_target_files,
+ output_dir=os.path.dirname(vendor_meta_dir),
+ extract_item_list=('META/*',))
+
+ merged_meta_dir = os.path.join(merged_dir, 'META')
+
+ # Merge META/misc_info.txt into OPTIONS.merged_misc_info,
+ # but do not write it yet. The following functions may further
+ # modify this dict.
+ OPTIONS.merged_misc_info = MergeMiscInfo(
+ framework_meta_dir=framework_meta_dir,
+ vendor_meta_dir=vendor_meta_dir,
+ merged_meta_dir=merged_meta_dir)
+
+ CopyNamedFileContexts(
+ framework_meta_dir=framework_meta_dir,
+ vendor_meta_dir=vendor_meta_dir,
+ merged_meta_dir=merged_meta_dir)
+
+ if OPTIONS.merged_misc_info.get('use_dynamic_partitions') == 'true':
+ MergeDynamicPartitionsInfo(
+ framework_meta_dir=framework_meta_dir,
+ vendor_meta_dir=vendor_meta_dir,
+ merged_meta_dir=merged_meta_dir)
+
+ if OPTIONS.merged_misc_info.get('ab_update') == 'true':
+ MergeAbPartitions(
+ framework_meta_dir=framework_meta_dir,
+ vendor_meta_dir=vendor_meta_dir,
+ merged_meta_dir=merged_meta_dir)
+ UpdateCareMapImageSizeProps(images_dir=os.path.join(merged_dir, 'IMAGES'))
+
+ for file_name in ('apkcerts.txt', 'apexkeys.txt'):
+ MergePackageKeys(
+ framework_meta_dir=framework_meta_dir,
+ vendor_meta_dir=vendor_meta_dir,
+ merged_meta_dir=merged_meta_dir,
+ file_name=file_name)
+
+ # Write the now-finalized OPTIONS.merged_misc_info.
+ merge_utils.WriteSortedData(
+ data=OPTIONS.merged_misc_info,
+ path=os.path.join(merged_meta_dir, 'misc_info.txt'))
+
+
+def MergeAbPartitions(framework_meta_dir, vendor_meta_dir, merged_meta_dir):
+ """Merges META/ab_partitions.txt.
+
+ The output contains the union of the partition names.
+ """
+ with open(os.path.join(framework_meta_dir, 'ab_partitions.txt')) as f:
+ framework_ab_partitions = f.read().splitlines()
+
+ with open(os.path.join(vendor_meta_dir, 'ab_partitions.txt')) as f:
+ vendor_ab_partitions = f.read().splitlines()
+
+ merge_utils.WriteSortedData(
+ data=set(framework_ab_partitions + vendor_ab_partitions),
+ path=os.path.join(merged_meta_dir, 'ab_partitions.txt'))
+
+
+def MergeMiscInfo(framework_meta_dir, vendor_meta_dir, merged_meta_dir):
+ """Merges META/misc_info.txt.
+
+ The output contains a combination of key=value pairs from both inputs.
+ Most pairs are taken from the vendor input, while some are taken from
+ the framework input.
+ """
+
+ OPTIONS.framework_misc_info = common.LoadDictionaryFromFile(
+ os.path.join(framework_meta_dir, 'misc_info.txt'))
+ OPTIONS.vendor_misc_info = common.LoadDictionaryFromFile(
+ os.path.join(vendor_meta_dir, 'misc_info.txt'))
+
+ # Merged misc info is a combination of vendor misc info plus certain values
+ # from the framework misc info.
+
+ merged_dict = OPTIONS.vendor_misc_info
+ for key in OPTIONS.framework_misc_info_keys:
+ if key in OPTIONS.framework_misc_info:
+ merged_dict[key] = OPTIONS.framework_misc_info[key]
+
+ # If AVB is enabled then ensure that we build vbmeta.img.
+ # Partial builds with AVB enabled may set PRODUCT_BUILD_VBMETA_IMAGE=false to
+ # skip building an incomplete vbmeta.img.
+ if merged_dict.get('avb_enable') == 'true':
+ merged_dict['avb_building_vbmeta_image'] = 'true'
+
+ return merged_dict
+
+
+def MergeDynamicPartitionsInfo(framework_meta_dir, vendor_meta_dir,
+ merged_meta_dir):
+ """Merge META/dynamic_partitions_info.txt."""
+ framework_dynamic_partitions_dict = common.LoadDictionaryFromFile(
+ os.path.join(framework_meta_dir, 'dynamic_partitions_info.txt'))
+ vendor_dynamic_partitions_dict = common.LoadDictionaryFromFile(
+ os.path.join(vendor_meta_dir, 'dynamic_partitions_info.txt'))
+
+ merged_dynamic_partitions_dict = common.MergeDynamicPartitionInfoDicts(
+ framework_dict=framework_dynamic_partitions_dict,
+ vendor_dict=vendor_dynamic_partitions_dict)
+
+ merge_utils.WriteSortedData(
+ data=merged_dynamic_partitions_dict,
+ path=os.path.join(merged_meta_dir, 'dynamic_partitions_info.txt'))
+
+ # Merge misc info keys used for Dynamic Partitions.
+ OPTIONS.merged_misc_info.update(merged_dynamic_partitions_dict)
+ # Ensure that add_img_to_target_files rebuilds super split images for
+ # devices that retrofit dynamic partitions. This flag may have been set to
+ # false in the partial builds to prevent duplicate building of super.img.
+ OPTIONS.merged_misc_info['build_super_partition'] = 'true'
+
+
+def MergePackageKeys(framework_meta_dir, vendor_meta_dir, merged_meta_dir,
+ file_name):
+ """Merges APK/APEX key list files."""
+
+ if file_name not in ('apkcerts.txt', 'apexkeys.txt'):
+ raise ExternalError(
+ 'Unexpected file_name provided to merge_package_keys_txt: %s',
+ file_name)
+
+ def read_helper(d):
+ temp = {}
+ with open(os.path.join(d, file_name)) as f:
+ for line in f.read().splitlines():
+ line = line.strip()
+ if line:
+ name_search = MODULE_KEY_PATTERN.search(line.split()[0])
+ temp[name_search.group(1)] = line
+ return temp
+
+ framework_dict = read_helper(framework_meta_dir)
+ vendor_dict = read_helper(vendor_meta_dir)
+ merged_dict = {}
+
+ def filter_into_merged_dict(item_dict, partition_set):
+ for key, value in item_dict.items():
+ tag_search = PARTITION_TAG_PATTERN.search(value)
+
+ if tag_search is None:
+ raise ValueError('Entry missing partition tag: %s' % value)
+
+ partition_tag = tag_search.group(1)
+
+ if partition_tag in partition_set:
+ if key in merged_dict:
+ if OPTIONS.allow_duplicate_apkapex_keys:
+ # TODO(b/150582573) Always raise on duplicates.
+ logger.warning('Duplicate key %s' % key)
+ continue
+ else:
+ raise ValueError('Duplicate key %s' % key)
+
+ merged_dict[key] = value
+
+ # Prioritize framework keys first.
+ # Duplicate keys from vendor are an error, or ignored.
+ filter_into_merged_dict(framework_dict, OPTIONS.framework_partition_set)
+ filter_into_merged_dict(vendor_dict, OPTIONS.vendor_partition_set)
+
+ # The following code is similar to WriteSortedData, but different enough
+ # that we couldn't use that function. We need the output to be sorted by the
+ # basename of the apex/apk (without the ".apex" or ".apk" suffix). This
+ # allows the sort to be consistent with the framework/vendor input data and
+ # eases comparison of input data with merged data.
+ with open(os.path.join(merged_meta_dir, file_name), 'w') as output:
+ for key, value in sorted(merged_dict.items()):
+ output.write(value + '\n')
+
+
+def CopyNamedFileContexts(framework_meta_dir, vendor_meta_dir, merged_meta_dir):
+ """Creates named copies of each partial build's file_contexts.bin.
+
+ Used when regenerating images from the partial build.
+ """
+
+ def copy_fc_file(source_dir, file_name):
+ for name in (file_name, 'file_contexts.bin'):
+ fc_path = os.path.join(source_dir, name)
+ if os.path.exists(fc_path):
+ shutil.copyfile(fc_path, os.path.join(merged_meta_dir, file_name))
+ return
+ raise ValueError('Missing file_contexts file from %s: %s', source_dir,
+ file_name)
+
+ copy_fc_file(framework_meta_dir, 'framework_file_contexts.bin')
+ copy_fc_file(vendor_meta_dir, 'vendor_file_contexts.bin')
+
+ # Replace <image>_selinux_fc values with framework or vendor file_contexts.bin
+ # depending on which dictionary the key came from.
+ # Only the file basename is required because all selinux_fc properties are
+ # replaced with the full path to the file under META/ when misc_info.txt is
+ # loaded from target files for repacking. See common.py LoadInfoDict().
+ for key in OPTIONS.vendor_misc_info:
+ if key.endswith('_selinux_fc'):
+ OPTIONS.merged_misc_info[key] = 'vendor_file_contexts.bin'
+ for key in OPTIONS.framework_misc_info:
+ if key.endswith('_selinux_fc'):
+ OPTIONS.merged_misc_info[key] = 'framework_file_contexts.bin'
+
+
+def UpdateCareMapImageSizeProps(images_dir):
+ """Sets <partition>_image_size props in misc_info.
+
+ add_images_to_target_files uses these props to generate META/care_map.pb.
+ Regenerated images will have this property set during regeneration.
+
+ However, images copied directly from input partial target files packages
+ need this value calculated here.
+ """
+ for partition in common.PARTITIONS_WITH_CARE_MAP:
+ image_path = os.path.join(images_dir, '{}.img'.format(partition))
+ if os.path.exists(image_path):
+ partition_size = sparse_img.GetImagePartitionSize(image_path)
+ image_props = build_image.ImagePropFromGlobalDict(
+ OPTIONS.merged_misc_info, partition)
+ verity_image_builder = verity_utils.CreateVerityImageBuilder(image_props)
+ image_size = verity_image_builder.CalculateMaxImageSize(partition_size)
+ OPTIONS.merged_misc_info['{}_image_size'.format(partition)] = image_size
diff --git a/tools/releasetools/merge/merge_target_files.py b/tools/releasetools/merge/merge_target_files.py
new file mode 100755
index 0000000..c06fd4c
--- /dev/null
+++ b/tools/releasetools/merge/merge_target_files.py
@@ -0,0 +1,611 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2022 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.
+#
+"""This script merges two partial target files packages.
+
+One input package contains framework files, and the other contains vendor files.
+
+This script produces a complete, merged target files package:
+ - This package can be used to generate a flashable IMG package.
+ See --output-img.
+ - This package can be used to generate an OTA package. See --output-ota.
+ - The merged package is checked for compatibility between the two inputs.
+
+Usage: merge_target_files [args]
+
+ --framework-target-files framework-target-files-zip-archive
+ The input target files package containing framework bits. This is a zip
+ archive.
+
+ --framework-item-list framework-item-list-file
+ The optional path to a newline-separated config file of items that
+ are extracted as-is from the framework target files package.
+
+ --framework-misc-info-keys framework-misc-info-keys-file
+ The optional path to a newline-separated config file of keys to
+ extract from the framework META/misc_info.txt file.
+
+ --vendor-target-files vendor-target-files-zip-archive
+ The input target files package containing vendor bits. This is a zip
+ archive.
+
+ --vendor-item-list vendor-item-list-file
+ The optional path to a newline-separated config file of items that
+ are extracted as-is from the vendor target files package.
+
+ --output-target-files output-target-files-package
+ If provided, the output merged target files package. Also a zip archive.
+
+ --output-dir output-directory
+ If provided, the destination directory for saving merged files. Requires
+ the --output-item-list flag.
+ Can be provided alongside --output-target-files, or by itself.
+
+ --output-item-list output-item-list-file.
+ The optional path to a newline-separated config file that specifies the
+ file patterns to copy into the --output-dir. Required if providing
+ the --output-dir flag.
+
+ --output-ota output-ota-package
+ The output ota package. This is a zip archive. Use of this flag may
+ require passing the --path common flag; see common.py.
+
+ --output-img output-img-package
+ The output img package, suitable for use with 'fastboot update'. Use of
+ this flag may require passing the --path common flag; see common.py.
+
+ --output-super-empty output-super-empty-image
+ If provided, creates a super_empty.img file from the merged target
+ files package and saves it at this path.
+
+ --rebuild_recovery
+ Copy the recovery image used by non-A/B devices, used when
+ regenerating vendor images with --rebuild-sepolicy.
+
+ --allow-duplicate-apkapex-keys
+ If provided, duplicate APK/APEX keys are ignored and the value from the
+ framework is used.
+
+ --rebuild-sepolicy
+ If provided, rebuilds odm.img or vendor.img to include merged sepolicy
+ files. If odm is present then odm is preferred.
+
+ --vendor-otatools otatools.zip
+ If provided, use this otatools.zip when recompiling the odm or vendor
+ image to include sepolicy.
+
+ --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.
+"""
+
+import logging
+import os
+import shutil
+import subprocess
+import sys
+import zipfile
+
+import add_img_to_target_files
+import build_image
+import build_super_image
+import common
+import img_from_target_files
+import merge_compatibility_checks
+import merge_dexopt
+import merge_meta
+import merge_utils
+import ota_from_target_files
+
+from common import ExternalError
+
+logger = logging.getLogger(__name__)
+
+OPTIONS = common.OPTIONS
+# Always turn on verbose logging.
+OPTIONS.verbose = True
+OPTIONS.framework_target_files = None
+OPTIONS.framework_item_list = []
+OPTIONS.framework_misc_info_keys = []
+OPTIONS.vendor_target_files = None
+OPTIONS.vendor_item_list = []
+OPTIONS.output_target_files = None
+OPTIONS.output_dir = None
+OPTIONS.output_item_list = []
+OPTIONS.output_ota = None
+OPTIONS.output_img = None
+OPTIONS.output_super_empty = None
+OPTIONS.rebuild_recovery = False
+# TODO(b/150582573): Remove this option.
+OPTIONS.allow_duplicate_apkapex_keys = False
+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
+
+
+def create_merged_package(temp_dir):
+ """Merges two target files packages into one target files structure.
+
+ Returns:
+ Path to merged package under temp directory.
+ """
+ # Extract "as is" items from the input framework and vendor partial target
+ # files packages directly into the output temporary directory, since these items
+ # do not need special case processing.
+
+ output_target_files_temp_dir = os.path.join(temp_dir, 'output')
+ merge_utils.ExtractItems(
+ input_zip=OPTIONS.framework_target_files,
+ output_dir=output_target_files_temp_dir,
+ extract_item_list=OPTIONS.framework_item_list)
+ merge_utils.ExtractItems(
+ input_zip=OPTIONS.vendor_target_files,
+ output_dir=output_target_files_temp_dir,
+ extract_item_list=OPTIONS.vendor_item_list)
+
+ # 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.
+ merge_meta.MergeMetaFiles(
+ temp_dir=temp_dir, merged_dir=output_target_files_temp_dir)
+
+ merge_dexopt.MergeDexopt(
+ temp_dir=temp_dir, output_target_files_dir=output_target_files_temp_dir)
+
+ return output_target_files_temp_dir
+
+
+def generate_missing_images(target_files_dir):
+ """Generate any missing images from target files."""
+
+ # Regenerate IMAGES in the target directory.
+
+ add_img_args = [
+ '--verbose',
+ '--add_missing',
+ ]
+ if OPTIONS.rebuild_recovery:
+ add_img_args.append('--rebuild_recovery')
+ add_img_args.append(target_files_dir)
+
+ add_img_to_target_files.main(add_img_args)
+
+
+def rebuild_image_with_sepolicy(target_files_dir):
+ """Rebuilds odm.img or vendor.img to include merged sepolicy files.
+
+ If odm is present then odm is preferred -- otherwise vendor is used.
+ """
+ partition = 'vendor'
+ if os.path.exists(os.path.join(target_files_dir, 'ODM')) or os.path.exists(
+ os.path.join(target_files_dir, 'IMAGES/odm.img')):
+ partition = 'odm'
+ partition_img = '{}.img'.format(partition)
+ partition_map = '{}.map'.format(partition)
+
+ logger.info('Recompiling %s using the merged sepolicy files.', partition_img)
+
+ # Copy the combined SEPolicy file and framework hashes to the image that is
+ # being rebuilt.
+ def copy_selinux_file(input_path, output_filename):
+ input_filename = os.path.join(target_files_dir, input_path)
+ if not os.path.exists(input_filename):
+ input_filename = input_filename.replace('SYSTEM_EXT/', 'SYSTEM/system_ext/') \
+ .replace('PRODUCT/', 'SYSTEM/product/')
+ if not os.path.exists(input_filename):
+ logger.info('Skipping copy_selinux_file for %s', input_filename)
+ return
+ shutil.copy(
+ input_filename,
+ os.path.join(target_files_dir, partition.upper(), 'etc/selinux',
+ output_filename))
+
+ copy_selinux_file('META/combined_sepolicy', 'precompiled_sepolicy')
+ copy_selinux_file('SYSTEM/etc/selinux/plat_sepolicy_and_mapping.sha256',
+ 'precompiled_sepolicy.plat_sepolicy_and_mapping.sha256')
+ copy_selinux_file(
+ 'SYSTEM_EXT/etc/selinux/system_ext_sepolicy_and_mapping.sha256',
+ 'precompiled_sepolicy.system_ext_sepolicy_and_mapping.sha256')
+ copy_selinux_file('PRODUCT/etc/selinux/product_sepolicy_and_mapping.sha256',
+ 'precompiled_sepolicy.product_sepolicy_and_mapping.sha256')
+
+ if not OPTIONS.vendor_otatools:
+ # Remove the partition from the merged target-files archive. It will be
+ # rebuilt later automatically by generate_missing_images().
+ os.remove(os.path.join(target_files_dir, 'IMAGES', partition_img))
+ return
+
+ # TODO(b/192253131): Remove the need for vendor_otatools by fixing
+ # backwards-compatibility issues when compiling images across releases.
+ if not OPTIONS.vendor_target_files:
+ raise ValueError(
+ 'Expected vendor_target_files if vendor_otatools is not None.')
+ logger.info(
+ '%s recompilation will be performed using the vendor otatools.zip',
+ partition_img)
+
+ # Unzip the vendor build's otatools.zip and target-files archive.
+ vendor_otatools_dir = common.MakeTempDir(
+ prefix='merge_target_files_vendor_otatools_')
+ vendor_target_files_dir = common.MakeTempDir(
+ prefix='merge_target_files_vendor_target_files_')
+ common.UnzipToDir(OPTIONS.vendor_otatools, vendor_otatools_dir)
+ common.UnzipToDir(OPTIONS.vendor_target_files, vendor_target_files_dir)
+
+ # Copy the partition contents from the merged target-files archive to the
+ # vendor target-files archive.
+ shutil.rmtree(os.path.join(vendor_target_files_dir, partition.upper()))
+ shutil.copytree(
+ os.path.join(target_files_dir, partition.upper()),
+ os.path.join(vendor_target_files_dir, partition.upper()),
+ symlinks=True)
+
+ # Delete then rebuild the partition.
+ os.remove(os.path.join(vendor_target_files_dir, 'IMAGES', partition_img))
+ rebuild_partition_command = [
+ os.path.join(vendor_otatools_dir, 'bin', 'add_img_to_target_files'),
+ '--verbose',
+ '--add_missing',
+ ]
+ if OPTIONS.rebuild_recovery:
+ rebuild_partition_command.append('--rebuild_recovery')
+ rebuild_partition_command.append(vendor_target_files_dir)
+ logger.info('Recompiling %s: %s', partition_img,
+ ' '.join(rebuild_partition_command))
+ common.RunAndCheckOutput(rebuild_partition_command, verbose=True)
+
+ # Move the newly-created image to the merged target files dir.
+ if not os.path.exists(os.path.join(target_files_dir, 'IMAGES')):
+ os.makedirs(os.path.join(target_files_dir, 'IMAGES'))
+ shutil.move(
+ os.path.join(vendor_target_files_dir, 'IMAGES', partition_img),
+ os.path.join(target_files_dir, 'IMAGES', partition_img))
+ shutil.move(
+ os.path.join(vendor_target_files_dir, 'IMAGES', partition_map),
+ os.path.join(target_files_dir, 'IMAGES', partition_map))
+
+ def copy_recovery_file(filename):
+ for subdir in ('VENDOR', 'SYSTEM/vendor'):
+ source = os.path.join(vendor_target_files_dir, subdir, filename)
+ if os.path.exists(source):
+ dest = os.path.join(target_files_dir, subdir, filename)
+ shutil.copy(source, dest)
+ return
+ logger.info('Skipping copy_recovery_file for %s, file not found', filename)
+
+ if OPTIONS.rebuild_recovery:
+ copy_recovery_file('etc/recovery.img')
+ copy_recovery_file('bin/install-recovery.sh')
+ copy_recovery_file('recovery-from-boot.p')
+
+
+def generate_super_empty_image(target_dir, output_super_empty):
+ """Generates super_empty image from target package.
+
+ Args:
+ target_dir: Path to the target file package which contains misc_info.txt for
+ detailed information for super image.
+ output_super_empty: If provided, copies a super_empty.img file from the
+ target files package to this path.
+ """
+ # Create super_empty.img using the merged misc_info.txt.
+
+ misc_info_txt = os.path.join(target_dir, 'META', 'misc_info.txt')
+
+ use_dynamic_partitions = common.LoadDictionaryFromFile(misc_info_txt).get(
+ 'use_dynamic_partitions')
+
+ if use_dynamic_partitions != 'true' and output_super_empty:
+ raise ValueError(
+ 'Building super_empty.img requires use_dynamic_partitions=true.')
+ elif use_dynamic_partitions == 'true':
+ super_empty_img = os.path.join(target_dir, 'IMAGES', 'super_empty.img')
+ build_super_image_args = [
+ misc_info_txt,
+ super_empty_img,
+ ]
+ build_super_image.main(build_super_image_args)
+
+ # Copy super_empty.img to the user-provided output_super_empty location.
+ if output_super_empty:
+ shutil.copyfile(super_empty_img, output_super_empty)
+
+
+def create_target_files_archive(output_zip, source_dir, temp_dir):
+ """Creates a target_files zip archive from the input source dir.
+
+ Args:
+ output_zip: The name of the zip archive target files package.
+ source_dir: The target directory contains package to be archived.
+ temp_dir: Path to temporary directory for any intermediate files.
+ """
+ output_target_files_list = os.path.join(temp_dir, 'output.list')
+ output_target_files_meta_dir = os.path.join(source_dir, 'META')
+
+ def files_from_path(target_path, extra_args=None):
+ """Gets files under the given path and return a sorted list."""
+ find_command = ['find', target_path] + (extra_args or [])
+ find_process = common.Run(
+ find_command, stdout=subprocess.PIPE, verbose=False)
+ return common.RunAndCheckOutput(['sort'],
+ stdin=find_process.stdout,
+ verbose=False)
+
+ # META content appears first in the zip. This is done by the
+ # standard build system for optimized extraction of those files,
+ # so we do the same step for merged target_files.zips here too.
+ meta_content = files_from_path(output_target_files_meta_dir)
+ other_content = files_from_path(
+ source_dir,
+ ['-path', output_target_files_meta_dir, '-prune', '-o', '-print'])
+
+ with open(output_target_files_list, 'w') as f:
+ f.write(meta_content)
+ f.write(other_content)
+
+ command = [
+ 'soong_zip',
+ '-d',
+ '-o',
+ os.path.abspath(output_zip),
+ '-C',
+ source_dir,
+ '-r',
+ output_target_files_list,
+ ]
+
+ logger.info('creating %s', output_zip)
+ common.RunAndCheckOutput(command, verbose=True)
+ logger.info('finished creating %s', output_zip)
+
+
+def merge_target_files(temp_dir):
+ """Merges two target files packages together.
+
+ This function uses framework and vendor target files packages as input,
+ performs various file extractions, special case processing, and finally
+ creates a merged zip archive as output.
+
+ Args:
+ temp_dir: The name of a directory we use when we extract items from the
+ input target files packages, and also a scratch directory that we use for
+ temporary files.
+ """
+
+ logger.info('starting: merge framework %s and vendor %s into output %s',
+ OPTIONS.framework_target_files, OPTIONS.vendor_target_files,
+ OPTIONS.output_target_files)
+
+ output_target_files_temp_dir = create_merged_package(temp_dir)
+
+ partition_map = common.PartitionMapFromTargetFiles(
+ output_target_files_temp_dir)
+
+ compatibility_errors = merge_compatibility_checks.CheckCompatibility(
+ target_files_dir=output_target_files_temp_dir,
+ partition_map=partition_map)
+ if compatibility_errors:
+ for error in compatibility_errors:
+ logger.error(error)
+ raise ExternalError(
+ 'Found incompatibilities in the merged target files package.')
+
+ # Include the compiled policy in an image if requested.
+ if OPTIONS.rebuild_sepolicy:
+ rebuild_image_with_sepolicy(output_target_files_temp_dir)
+
+ generate_missing_images(output_target_files_temp_dir)
+
+ generate_super_empty_image(output_target_files_temp_dir,
+ OPTIONS.output_super_empty)
+
+ # Finally, create the output target files zip archive and/or copy the
+ # output items to the output target files directory.
+
+ if OPTIONS.output_dir:
+ merge_utils.CopyItems(output_target_files_temp_dir, OPTIONS.output_dir,
+ OPTIONS.output_item_list)
+
+ if not OPTIONS.output_target_files:
+ return
+
+ create_target_files_archive(OPTIONS.output_target_files,
+ output_target_files_temp_dir, temp_dir)
+
+ # Create the IMG package from the merged target files package.
+ if OPTIONS.output_img:
+ img_from_target_files.main(
+ [OPTIONS.output_target_files, OPTIONS.output_img])
+
+ # Create the OTA package from the merged target files package.
+
+ if OPTIONS.output_ota:
+ ota_from_target_files.main(
+ [OPTIONS.output_target_files, OPTIONS.output_ota])
+
+
+def main():
+ """The main function.
+
+ Process command line arguments, then call merge_target_files to
+ perform the heavy lifting.
+ """
+
+ common.InitLogging()
+
+ def option_handler(o, a):
+ if o == '--system-target-files':
+ logger.warning(
+ '--system-target-files has been renamed to --framework-target-files')
+ OPTIONS.framework_target_files = a
+ elif o == '--framework-target-files':
+ OPTIONS.framework_target_files = a
+ elif o == '--system-item-list':
+ logger.warning(
+ '--system-item-list has been renamed to --framework-item-list')
+ OPTIONS.framework_item_list = a
+ elif o == '--framework-item-list':
+ OPTIONS.framework_item_list = a
+ elif o == '--system-misc-info-keys':
+ logger.warning('--system-misc-info-keys has been renamed to '
+ '--framework-misc-info-keys')
+ OPTIONS.framework_misc_info_keys = a
+ elif o == '--framework-misc-info-keys':
+ OPTIONS.framework_misc_info_keys = a
+ elif o == '--other-target-files':
+ logger.warning(
+ '--other-target-files has been renamed to --vendor-target-files')
+ OPTIONS.vendor_target_files = a
+ elif o == '--vendor-target-files':
+ OPTIONS.vendor_target_files = a
+ elif o == '--other-item-list':
+ logger.warning('--other-item-list has been renamed to --vendor-item-list')
+ OPTIONS.vendor_item_list = a
+ elif o == '--vendor-item-list':
+ OPTIONS.vendor_item_list = a
+ elif o == '--output-target-files':
+ OPTIONS.output_target_files = a
+ elif o == '--output-dir':
+ OPTIONS.output_dir = a
+ elif o == '--output-item-list':
+ OPTIONS.output_item_list = a
+ elif o == '--output-ota':
+ OPTIONS.output_ota = a
+ elif o == '--output-img':
+ OPTIONS.output_img = a
+ elif o == '--output-super-empty':
+ OPTIONS.output_super_empty = a
+ elif o == '--rebuild_recovery' or o == '--rebuild-recovery':
+ OPTIONS.rebuild_recovery = True
+ elif o == '--allow-duplicate-apkapex-keys':
+ OPTIONS.allow_duplicate_apkapex_keys = True
+ elif o == '--vendor-otatools':
+ OPTIONS.vendor_otatools = a
+ elif o == '--rebuild-sepolicy':
+ 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
+
+ args = common.ParseOptions(
+ sys.argv[1:],
+ __doc__,
+ extra_long_opts=[
+ 'system-target-files=',
+ 'framework-target-files=',
+ 'system-item-list=',
+ 'framework-item-list=',
+ 'system-misc-info-keys=',
+ 'framework-misc-info-keys=',
+ 'other-target-files=',
+ 'vendor-target-files=',
+ 'other-item-list=',
+ 'vendor-item-list=',
+ 'output-target-files=',
+ 'output-dir=',
+ 'output-item-list=',
+ 'output-ota=',
+ 'output-img=',
+ 'output-super-empty=',
+ 'framework-dexpreopt-config=',
+ 'framework-dexpreopt-tools=',
+ 'vendor-dexpreopt-config=',
+ 'rebuild_recovery',
+ 'rebuild-recovery',
+ 'allow-duplicate-apkapex-keys',
+ 'vendor-otatools=',
+ 'rebuild-sepolicy',
+ 'keep-tmp',
+ ],
+ extra_option_handler=option_handler)
+
+ # pylint: disable=too-many-boolean-expressions
+ if (args or OPTIONS.framework_target_files is None or
+ OPTIONS.vendor_target_files is None or
+ (OPTIONS.output_target_files is None and OPTIONS.output_dir is None) or
+ (OPTIONS.output_dir is not None and not OPTIONS.output_item_list) or
+ (OPTIONS.rebuild_recovery and not OPTIONS.rebuild_sepolicy)):
+ common.Usage(__doc__)
+ sys.exit(1)
+
+ with zipfile.ZipFile(OPTIONS.framework_target_files, allowZip64=True) as fz:
+ framework_namelist = fz.namelist()
+ with zipfile.ZipFile(OPTIONS.vendor_target_files, allowZip64=True) as vz:
+ vendor_namelist = vz.namelist()
+
+ if OPTIONS.framework_item_list:
+ OPTIONS.framework_item_list = common.LoadListFromFile(
+ OPTIONS.framework_item_list)
+ else:
+ OPTIONS.framework_item_list = merge_utils.InferItemList(
+ input_namelist=framework_namelist, framework=True)
+ OPTIONS.framework_partition_set = merge_utils.ItemListToPartitionSet(
+ OPTIONS.framework_item_list)
+
+ if OPTIONS.framework_misc_info_keys:
+ OPTIONS.framework_misc_info_keys = common.LoadListFromFile(
+ OPTIONS.framework_misc_info_keys)
+ else:
+ OPTIONS.framework_misc_info_keys = merge_utils.InferFrameworkMiscInfoKeys(
+ input_namelist=framework_namelist)
+
+ if OPTIONS.vendor_item_list:
+ OPTIONS.vendor_item_list = common.LoadListFromFile(OPTIONS.vendor_item_list)
+ else:
+ OPTIONS.vendor_item_list = merge_utils.InferItemList(
+ input_namelist=vendor_namelist, framework=False)
+ OPTIONS.vendor_partition_set = merge_utils.ItemListToPartitionSet(
+ OPTIONS.vendor_item_list)
+
+ if OPTIONS.output_item_list:
+ OPTIONS.output_item_list = common.LoadListFromFile(OPTIONS.output_item_list)
+
+ if not merge_utils.ValidateConfigLists():
+ sys.exit(1)
+
+ temp_dir = common.MakeTempDir(prefix='merge_target_files_')
+ try:
+ merge_target_files(temp_dir)
+ finally:
+ if OPTIONS.keep_tmp:
+ logger.info('Keeping temp_dir %s', temp_dir)
+ else:
+ common.Cleanup()
+
+
+if __name__ == '__main__':
+ main()
diff --git a/tools/releasetools/merge/merge_utils.py b/tools/releasetools/merge/merge_utils.py
new file mode 100644
index 0000000..f623ad2
--- /dev/null
+++ b/tools/releasetools/merge/merge_utils.py
@@ -0,0 +1,237 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2022 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.
+#
+"""Common utility functions shared by merge_* scripts.
+
+Expects items in OPTIONS prepared by merge_target_files.py.
+"""
+
+import fnmatch
+import logging
+import os
+import re
+import shutil
+import zipfile
+
+import common
+
+logger = logging.getLogger(__name__)
+OPTIONS = common.OPTIONS
+
+
+def ExtractItems(input_zip, output_dir, extract_item_list):
+ """Extracts items in extract_item_list from a zip to a dir."""
+
+ # Filter the extract_item_list to remove any items that do not exist in the
+ # zip file. Otherwise, the extraction step will fail.
+
+ with zipfile.ZipFile(input_zip, allowZip64=True) as input_zipfile:
+ input_namelist = input_zipfile.namelist()
+
+ filtered_extract_item_list = []
+ for pattern in extract_item_list:
+ if fnmatch.filter(input_namelist, pattern):
+ filtered_extract_item_list.append(pattern)
+
+ common.UnzipToDir(input_zip, output_dir, filtered_extract_item_list)
+
+
+def CopyItems(from_dir, to_dir, patterns):
+ """Similar to ExtractItems() except uses an input dir instead of zip."""
+ file_paths = []
+ for dirpath, _, filenames in os.walk(from_dir):
+ file_paths.extend(
+ os.path.relpath(path=os.path.join(dirpath, filename), start=from_dir)
+ for filename in filenames)
+
+ filtered_file_paths = set()
+ for pattern in patterns:
+ filtered_file_paths.update(fnmatch.filter(file_paths, pattern))
+
+ for file_path in filtered_file_paths:
+ original_file_path = os.path.join(from_dir, file_path)
+ copied_file_path = os.path.join(to_dir, file_path)
+ copied_file_dir = os.path.dirname(copied_file_path)
+ if not os.path.exists(copied_file_dir):
+ os.makedirs(copied_file_dir)
+ if os.path.islink(original_file_path):
+ os.symlink(os.readlink(original_file_path), copied_file_path)
+ else:
+ shutil.copyfile(original_file_path, copied_file_path)
+
+
+def WriteSortedData(data, path):
+ """Writes the sorted contents of either a list or dict to file.
+
+ This function sorts the contents of the list or dict and then writes the
+ resulting sorted contents to a file specified by path.
+
+ Args:
+ data: The list or dict to sort and write.
+ path: Path to the file to write the sorted values to. The file at path will
+ be overridden if it exists.
+ """
+ with open(path, 'w') as output:
+ for entry in sorted(data):
+ out_str = '{}={}\n'.format(entry, data[entry]) if isinstance(
+ data, dict) else '{}\n'.format(entry)
+ output.write(out_str)
+
+
+def ValidateConfigLists():
+ """Performs validations on the merge config lists.
+
+ Returns:
+ False if a validation fails, otherwise true.
+ """
+ has_error = False
+
+ # Check that partitions only come from one input.
+ for partition in _FRAMEWORK_PARTITIONS.union(_VENDOR_PARTITIONS):
+ image_path = 'IMAGES/{}.img'.format(partition.lower().replace('/', ''))
+ in_framework = (
+ any(item.startswith(partition) for item in OPTIONS.framework_item_list)
+ or image_path in OPTIONS.framework_item_list)
+ in_vendor = (
+ any(item.startswith(partition) for item in OPTIONS.vendor_item_list) or
+ image_path in OPTIONS.vendor_item_list)
+ if in_framework and in_vendor:
+ logger.error(
+ 'Cannot extract items from %s for both the framework and vendor'
+ ' builds. Please ensure only one merge config item list'
+ ' includes %s.', partition, partition)
+ has_error = True
+
+ if any([
+ key in OPTIONS.framework_misc_info_keys
+ for key in ('dynamic_partition_list', 'super_partition_groups')
+ ]):
+ logger.error('Dynamic partition misc info keys should come from '
+ 'the vendor instance of META/misc_info.txt.')
+ has_error = True
+
+ return not has_error
+
+
+# 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
+# system partition). The following regex matches this and extracts the
+# partition name.
+
+_PARTITION_ITEM_PATTERN = re.compile(r'^([A-Z_]+)/\*$')
+
+
+def ItemListToPartitionSet(item_list):
+ """Converts a target files item list to a partition set.
+
+ The item list contains items that might look like 'SYSTEM/*' or 'VENDOR/*' or
+ 'OTA/android-info.txt'. Items that end in '/*' are assumed to match entire
+ directories where 'SYSTEM' or 'VENDOR' is a directory name that identifies the
+ contents of a partition of the same name. Other items in the list, such as the
+ 'OTA' example contain metadata. This function iterates such a list, returning
+ a set that contains the partition entries.
+
+ Args:
+ item_list: A list of items in a target files package.
+
+ Returns:
+ A set of partitions extracted from the list of items.
+ """
+
+ partition_set = set()
+
+ for item in item_list:
+ partition_match = _PARTITION_ITEM_PATTERN.search(item.strip())
+ partition_tag = partition_match.group(
+ 1).lower() if partition_match else None
+
+ if partition_tag:
+ partition_set.add(partition_tag)
+
+ return partition_set
+
+
+# Partitions that are grabbed from the framework partial build by default.
+_FRAMEWORK_PARTITIONS = {
+ 'system', 'product', 'system_ext', 'system_other', 'root', 'system_dlkm'
+}
+# Partitions that are grabbed from the vendor partial build by default.
+_VENDOR_PARTITIONS = {
+ 'vendor', 'odm', 'oem', 'boot', 'vendor_boot', 'recovery',
+ 'prebuilt_images', 'radio', 'data', 'vendor_dlkm', 'odm_dlkm'
+}
+
+
+def InferItemList(input_namelist, framework):
+ item_list = []
+
+ # Some META items are grabbed from partial builds directly.
+ # Others are combined in merge_meta.py.
+ if framework:
+ item_list.extend([
+ 'META/liblz4.so',
+ 'META/postinstall_config.txt',
+ 'META/update_engine_config.txt',
+ 'META/zucchini_config.txt',
+ ])
+ else: # vendor
+ item_list.extend([
+ 'META/kernel_configs.txt',
+ 'META/kernel_version.txt',
+ 'META/otakeys.txt',
+ 'META/releasetools.py',
+ 'OTA/android-info.txt',
+ ])
+
+ # Grab a set of items for the expected partitions in the partial build.
+ for partition in (_FRAMEWORK_PARTITIONS if framework else _VENDOR_PARTITIONS):
+ for namelist in input_namelist:
+ if namelist.startswith('%s/' % partition.upper()):
+ fs_config_prefix = '' if partition == 'system' else '%s_' % partition
+ item_list.extend([
+ '%s/*' % partition.upper(),
+ 'IMAGES/%s.img' % partition,
+ 'IMAGES/%s.map' % partition,
+ 'META/%sfilesystem_config.txt' % fs_config_prefix,
+ ])
+ break
+
+ return sorted(item_list)
+
+
+def InferFrameworkMiscInfoKeys(input_namelist):
+ keys = [
+ 'ab_update',
+ 'avb_vbmeta_system',
+ 'avb_vbmeta_system_algorithm',
+ 'avb_vbmeta_system_key_path',
+ 'avb_vbmeta_system_rollback_index_location',
+ 'default_system_dev_certificate',
+ ]
+
+ for partition in _FRAMEWORK_PARTITIONS:
+ for namelist in input_namelist:
+ if namelist.startswith('%s/' % partition.upper()):
+ fs_type_prefix = '' if partition == 'system' else '%s_' % partition
+ keys.extend([
+ 'avb_%s_hashtree_enable' % partition,
+ 'avb_%s_add_hashtree_footer_args' % partition,
+ '%s_disable_sparse' % partition,
+ 'building_%s_image' % partition,
+ '%sfs_type' % fs_type_prefix,
+ ])
+
+ return sorted(keys)
diff --git a/tools/releasetools/merge/test_merge_compatibility_checks.py b/tools/releasetools/merge/test_merge_compatibility_checks.py
new file mode 100644
index 0000000..0f319de
--- /dev/null
+++ b/tools/releasetools/merge/test_merge_compatibility_checks.py
@@ -0,0 +1,114 @@
+#
+# Copyright (C) 2022 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 os.path
+import shutil
+
+import common
+import merge_compatibility_checks
+import merge_target_files
+import test_utils
+
+
+class MergeCompatibilityChecksTest(test_utils.ReleaseToolsTestCase):
+
+ def setUp(self):
+ self.testdata_dir = test_utils.get_testdata_dir()
+ self.partition_map = {
+ 'system': 'system',
+ 'system_ext': 'system_ext',
+ 'product': 'product',
+ 'vendor': 'vendor',
+ 'odm': 'odm',
+ }
+ self.OPTIONS = merge_target_files.OPTIONS
+ self.OPTIONS.framework_partition_set = set(
+ ['product', 'system', 'system_ext'])
+ self.OPTIONS.vendor_partition_set = set(['odm', 'vendor'])
+
+ def test_CheckCombinedSepolicy(self):
+ product_out_dir = common.MakeTempDir()
+
+ def write_temp_file(path, data=''):
+ full_path = os.path.join(product_out_dir, path)
+ if not os.path.exists(os.path.dirname(full_path)):
+ os.makedirs(os.path.dirname(full_path))
+ with open(full_path, 'w') as f:
+ f.write(data)
+
+ write_temp_file(
+ 'system/etc/vintf/compatibility_matrix.device.xml', """
+ <compatibility-matrix>
+ <sepolicy>
+ <kernel-sepolicy-version>30</kernel-sepolicy-version>
+ </sepolicy>
+ </compatibility-matrix>""")
+ write_temp_file('vendor/etc/selinux/plat_sepolicy_vers.txt', '30.0')
+
+ write_temp_file('system/etc/selinux/plat_sepolicy.cil')
+ write_temp_file('system/etc/selinux/mapping/30.0.cil')
+ write_temp_file('product/etc/selinux/mapping/30.0.cil')
+ write_temp_file('vendor/etc/selinux/vendor_sepolicy.cil')
+ write_temp_file('vendor/etc/selinux/plat_pub_versioned.cil')
+
+ cmd = merge_compatibility_checks.CheckCombinedSepolicy(
+ product_out_dir, self.partition_map, execute=False)
+ self.assertEqual(' '.join(cmd),
+ ('secilc -m -M true -G -N -c 30 '
+ '-o {OTP}/META/combined_sepolicy -f /dev/null '
+ '{OTP}/system/etc/selinux/plat_sepolicy.cil '
+ '{OTP}/system/etc/selinux/mapping/30.0.cil '
+ '{OTP}/vendor/etc/selinux/vendor_sepolicy.cil '
+ '{OTP}/vendor/etc/selinux/plat_pub_versioned.cil '
+ '{OTP}/product/etc/selinux/mapping/30.0.cil').format(
+ OTP=product_out_dir))
+
+ def _copy_apex(self, source, output_dir, partition):
+ shutil.copy(
+ source,
+ os.path.join(output_dir, partition, 'apex', os.path.basename(source)))
+
+ @test_utils.SkipIfExternalToolsUnavailable()
+ def test_CheckApexDuplicatePackages(self):
+ output_dir = common.MakeTempDir()
+ os.makedirs(os.path.join(output_dir, 'SYSTEM/apex'))
+ os.makedirs(os.path.join(output_dir, 'VENDOR/apex'))
+
+ self._copy_apex(
+ os.path.join(self.testdata_dir, 'has_apk.apex'), output_dir, 'SYSTEM')
+ self._copy_apex(
+ os.path.join(test_utils.get_current_dir(),
+ 'com.android.apex.compressed.v1.capex'), output_dir,
+ 'VENDOR')
+ self.assertEqual(
+ len(
+ merge_compatibility_checks.CheckApexDuplicatePackages(
+ output_dir, self.partition_map)), 0)
+
+ @test_utils.SkipIfExternalToolsUnavailable()
+ def test_CheckApexDuplicatePackages_RaisesOnPackageInMultiplePartitions(self):
+ output_dir = common.MakeTempDir()
+ os.makedirs(os.path.join(output_dir, 'SYSTEM/apex'))
+ os.makedirs(os.path.join(output_dir, 'VENDOR/apex'))
+
+ same_apex_package = os.path.join(self.testdata_dir, 'has_apk.apex')
+ self._copy_apex(same_apex_package, output_dir, 'SYSTEM')
+ self._copy_apex(same_apex_package, output_dir, 'VENDOR')
+ self.assertEqual(
+ merge_compatibility_checks.CheckApexDuplicatePackages(
+ output_dir, self.partition_map)[0],
+ 'Duplicate APEX package_names found in multiple partitions: com.android.wifi'
+ )
diff --git a/tools/releasetools/merge/test_merge_meta.py b/tools/releasetools/merge/test_merge_meta.py
new file mode 100644
index 0000000..34fe580
--- /dev/null
+++ b/tools/releasetools/merge/test_merge_meta.py
@@ -0,0 +1,110 @@
+#
+# Copyright (C) 2017 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 os.path
+import shutil
+
+import common
+import merge_meta
+import merge_target_files
+import test_utils
+
+
+class MergeMetaTest(test_utils.ReleaseToolsTestCase):
+
+ def setUp(self):
+ self.testdata_dir = test_utils.get_testdata_dir()
+ self.OPTIONS = merge_target_files.OPTIONS
+ self.OPTIONS.framework_partition_set = set(
+ ['product', 'system', 'system_ext'])
+ self.OPTIONS.vendor_partition_set = set(['odm', 'vendor'])
+
+ def test_MergePackageKeys_ReturnsTrueIfNoConflicts(self):
+ output_meta_dir = common.MakeTempDir()
+
+ framework_meta_dir = common.MakeTempDir()
+ os.symlink(
+ os.path.join(self.testdata_dir, 'apexkeys_framework.txt'),
+ os.path.join(framework_meta_dir, 'apexkeys.txt'))
+
+ vendor_meta_dir = common.MakeTempDir()
+ os.symlink(
+ os.path.join(self.testdata_dir, 'apexkeys_vendor.txt'),
+ os.path.join(vendor_meta_dir, 'apexkeys.txt'))
+
+ merge_meta.MergePackageKeys(framework_meta_dir, vendor_meta_dir,
+ output_meta_dir, 'apexkeys.txt')
+
+ merged_entries = []
+ merged_path = os.path.join(self.testdata_dir, 'apexkeys_merge.txt')
+
+ with open(merged_path) as f:
+ merged_entries = f.read().split('\n')
+
+ output_entries = []
+ output_path = os.path.join(output_meta_dir, 'apexkeys.txt')
+
+ with open(output_path) as f:
+ output_entries = f.read().split('\n')
+
+ return self.assertEqual(merged_entries, output_entries)
+
+ def test_MergePackageKeys_ReturnsFalseIfConflictsPresent(self):
+ output_meta_dir = common.MakeTempDir()
+
+ framework_meta_dir = common.MakeTempDir()
+ os.symlink(
+ os.path.join(self.testdata_dir, 'apexkeys_framework.txt'),
+ os.path.join(framework_meta_dir, 'apexkeys.txt'))
+
+ conflict_meta_dir = common.MakeTempDir()
+ os.symlink(
+ os.path.join(self.testdata_dir, 'apexkeys_framework_conflict.txt'),
+ os.path.join(conflict_meta_dir, 'apexkeys.txt'))
+
+ self.assertRaises(ValueError, merge_meta.MergePackageKeys,
+ framework_meta_dir, conflict_meta_dir, output_meta_dir,
+ 'apexkeys.txt')
+
+ def test_MergePackageKeys_HandlesApkCertsSyntax(self):
+ output_meta_dir = common.MakeTempDir()
+
+ framework_meta_dir = common.MakeTempDir()
+ os.symlink(
+ os.path.join(self.testdata_dir, 'apkcerts_framework.txt'),
+ os.path.join(framework_meta_dir, 'apkcerts.txt'))
+
+ vendor_meta_dir = common.MakeTempDir()
+ os.symlink(
+ os.path.join(self.testdata_dir, 'apkcerts_vendor.txt'),
+ os.path.join(vendor_meta_dir, 'apkcerts.txt'))
+
+ merge_meta.MergePackageKeys(framework_meta_dir, vendor_meta_dir,
+ output_meta_dir, 'apkcerts.txt')
+
+ merged_entries = []
+ merged_path = os.path.join(self.testdata_dir, 'apkcerts_merge.txt')
+
+ with open(merged_path) as f:
+ merged_entries = f.read().split('\n')
+
+ output_entries = []
+ output_path = os.path.join(output_meta_dir, 'apkcerts.txt')
+
+ with open(output_path) as f:
+ output_entries = f.read().split('\n')
+
+ return self.assertEqual(merged_entries, output_entries)
diff --git a/tools/releasetools/merge/test_merge_utils.py b/tools/releasetools/merge/test_merge_utils.py
new file mode 100644
index 0000000..1949050
--- /dev/null
+++ b/tools/releasetools/merge/test_merge_utils.py
@@ -0,0 +1,197 @@
+#
+# Copyright (C) 2017 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 os.path
+
+import common
+import merge_target_files
+import merge_utils
+import test_utils
+
+
+class MergeUtilsTest(test_utils.ReleaseToolsTestCase):
+
+ def setUp(self):
+ self.OPTIONS = merge_target_files.OPTIONS
+
+ def test_CopyItems_CopiesItemsMatchingPatterns(self):
+
+ def createEmptyFile(path):
+ if not os.path.exists(os.path.dirname(path)):
+ os.makedirs(os.path.dirname(path))
+ open(path, 'a').close()
+ return path
+
+ def createSymLink(source, dest):
+ os.symlink(source, dest)
+ return dest
+
+ def getRelPaths(start, filepaths):
+ return set(
+ os.path.relpath(path=filepath, start=start) for filepath in filepaths)
+
+ input_dir = common.MakeTempDir()
+ output_dir = common.MakeTempDir()
+ expected_copied_items = []
+ actual_copied_items = []
+ patterns = ['*.cpp', 'subdir/*.txt']
+
+ # Create various files that we expect to get copied because they
+ # match one of the patterns.
+ expected_copied_items.extend([
+ createEmptyFile(os.path.join(input_dir, 'a.cpp')),
+ createEmptyFile(os.path.join(input_dir, 'b.cpp')),
+ createEmptyFile(os.path.join(input_dir, 'subdir', 'c.txt')),
+ createEmptyFile(os.path.join(input_dir, 'subdir', 'd.txt')),
+ createEmptyFile(
+ os.path.join(input_dir, 'subdir', 'subsubdir', 'e.txt')),
+ createSymLink('a.cpp', os.path.join(input_dir, 'a_link.cpp')),
+ ])
+ # Create some more files that we expect to not get copied.
+ createEmptyFile(os.path.join(input_dir, 'a.h'))
+ createEmptyFile(os.path.join(input_dir, 'b.h'))
+ createEmptyFile(os.path.join(input_dir, 'subdir', 'subsubdir', 'f.gif'))
+ createSymLink('a.h', os.path.join(input_dir, 'a_link.h'))
+
+ # Copy items.
+ merge_utils.CopyItems(input_dir, output_dir, patterns)
+
+ # Assert the actual copied items match the ones we expected.
+ for dirpath, _, filenames in os.walk(output_dir):
+ actual_copied_items.extend(
+ os.path.join(dirpath, filename) for filename in filenames)
+ self.assertEqual(
+ getRelPaths(output_dir, actual_copied_items),
+ getRelPaths(input_dir, expected_copied_items))
+ self.assertEqual(
+ os.readlink(os.path.join(output_dir, 'a_link.cpp')), 'a.cpp')
+
+ def test_ValidateConfigLists_ReturnsFalseIfSharedExtractedPartition(self):
+ self.OPTIONS.system_item_list = [
+ 'SYSTEM/*',
+ ]
+ self.OPTIONS.vendor_item_list = [
+ 'SYSTEM/my_system_file',
+ 'VENDOR/*',
+ ]
+ self.OPTIONS.vendor_item_list.append('SYSTEM/my_system_file')
+ self.assertFalse(merge_utils.ValidateConfigLists())
+
+ def test_ValidateConfigLists_ReturnsFalseIfSharedExtractedPartitionImage(
+ self):
+ self.OPTIONS.system_item_list = [
+ 'SYSTEM/*',
+ ]
+ self.OPTIONS.vendor_item_list = [
+ 'IMAGES/system.img',
+ 'VENDOR/*',
+ ]
+ self.assertFalse(merge_utils.ValidateConfigLists())
+
+ def test_ValidateConfigLists_ReturnsFalseIfBadSystemMiscInfoKeys(self):
+ for bad_key in ['dynamic_partition_list', 'super_partition_groups']:
+ self.OPTIONS.framework_misc_info_keys = [bad_key]
+ self.assertFalse(merge_utils.ValidateConfigLists())
+
+ def test_ItemListToPartitionSet(self):
+ item_list = [
+ 'META/apexkeys.txt',
+ 'META/apkcerts.txt',
+ 'META/filesystem_config.txt',
+ 'PRODUCT/*',
+ 'SYSTEM/*',
+ 'SYSTEM_EXT/*',
+ ]
+ partition_set = merge_utils.ItemListToPartitionSet(item_list)
+ self.assertEqual(set(['product', 'system', 'system_ext']), partition_set)
+
+ def test_InferItemList_Framework(self):
+ zip_namelist = [
+ 'SYSTEM/my_system_file',
+ 'PRODUCT/my_product_file',
+ ]
+
+ item_list = merge_utils.InferItemList(zip_namelist, framework=True)
+
+ expected_framework_item_list = [
+ 'IMAGES/product.img',
+ 'IMAGES/product.map',
+ 'IMAGES/system.img',
+ 'IMAGES/system.map',
+ 'META/filesystem_config.txt',
+ 'META/liblz4.so',
+ 'META/postinstall_config.txt',
+ 'META/product_filesystem_config.txt',
+ 'META/update_engine_config.txt',
+ 'META/zucchini_config.txt',
+ 'PRODUCT/*',
+ 'SYSTEM/*',
+ ]
+
+ self.assertEqual(item_list, expected_framework_item_list)
+
+ def test_InferItemList_Vendor(self):
+ zip_namelist = [
+ 'VENDOR/my_vendor_file',
+ 'ODM/my_odm_file',
+ ]
+
+ item_list = merge_utils.InferItemList(zip_namelist, framework=False)
+
+ expected_vendor_item_list = [
+ 'IMAGES/odm.img',
+ 'IMAGES/odm.map',
+ 'IMAGES/vendor.img',
+ 'IMAGES/vendor.map',
+ 'META/kernel_configs.txt',
+ 'META/kernel_version.txt',
+ 'META/odm_filesystem_config.txt',
+ 'META/otakeys.txt',
+ 'META/releasetools.py',
+ 'META/vendor_filesystem_config.txt',
+ 'ODM/*',
+ 'OTA/android-info.txt',
+ 'VENDOR/*',
+ ]
+ self.assertEqual(item_list, expected_vendor_item_list)
+
+ def test_InferFrameworkMiscInfoKeys(self):
+ zip_namelist = [
+ 'SYSTEM/my_system_file',
+ 'SYSTEM_EXT/my_system_ext_file',
+ ]
+
+ keys = merge_utils.InferFrameworkMiscInfoKeys(zip_namelist)
+
+ expected_keys = [
+ 'ab_update',
+ 'avb_system_add_hashtree_footer_args',
+ 'avb_system_ext_add_hashtree_footer_args',
+ 'avb_system_ext_hashtree_enable',
+ 'avb_system_hashtree_enable',
+ 'avb_vbmeta_system',
+ 'avb_vbmeta_system_algorithm',
+ 'avb_vbmeta_system_key_path',
+ 'avb_vbmeta_system_rollback_index_location',
+ 'building_system_ext_image',
+ 'building_system_image',
+ 'default_system_dev_certificate',
+ 'fs_type',
+ 'system_disable_sparse',
+ 'system_ext_disable_sparse',
+ 'system_ext_fs_type',
+ ]
+ self.assertEqual(keys, expected_keys)
diff --git a/tools/releasetools/merge_target_files.py b/tools/releasetools/merge_target_files.py
deleted file mode 100755
index 6d3ee3f..0000000
--- a/tools/releasetools/merge_target_files.py
+++ /dev/null
@@ -1,1556 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2022 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.
-#
-"""This script merges two partial target files packages.
-
-One input package contains framework files, and the other contains vendor files.
-
-This script produces a complete, merged target files package:
- - This package can be used to generate a flashable IMG package.
- See --output-img.
- - This package can be used to generate an OTA package. See --output-ota.
- - The merged package is checked for compatibility between the two inputs.
-
-Usage: merge_target_files [args]
-
- --framework-target-files framework-target-files-zip-archive
- The input target files package containing framework bits. This is a zip
- archive.
-
- --framework-item-list framework-item-list-file
- The optional path to a newline-separated config file that replaces the
- contents of DEFAULT_FRAMEWORK_ITEM_LIST if provided.
-
- --framework-misc-info-keys framework-misc-info-keys-file
- The optional path to a newline-separated config file that replaces the
- contents of DEFAULT_FRAMEWORK_MISC_INFO_KEYS if provided.
-
- --vendor-target-files vendor-target-files-zip-archive
- The input target files package containing vendor bits. This is a zip
- archive.
-
- --vendor-item-list vendor-item-list-file
- The optional path to a newline-separated config file that replaces the
- contents of DEFAULT_VENDOR_ITEM_LIST if provided.
-
- --output-target-files output-target-files-package
- If provided, the output merged target files package. Also a zip archive.
-
- --output-dir output-directory
- If provided, the destination directory for saving merged files. Requires
- the --output-item-list flag.
- Can be provided alongside --output-target-files, or by itself.
-
- --output-item-list output-item-list-file.
- The optional path to a newline-separated config file that specifies the
- file patterns to copy into the --output-dir. Required if providing
- the --output-dir flag.
-
- --output-ota output-ota-package
- The output ota package. This is a zip archive. Use of this flag may
- require passing the --path common flag; see common.py.
-
- --output-img output-img-package
- The output img package, suitable for use with 'fastboot update'. Use of
- this flag may require passing the --path common flag; see common.py.
-
- --output-super-empty output-super-empty-image
- If provided, creates a super_empty.img file from the merged target
- files package and saves it at this path.
-
- --rebuild_recovery
- Copy the recovery image used by non-A/B devices, used when
- regenerating vendor images with --rebuild-sepolicy.
-
- --allow-duplicate-apkapex-keys
- If provided, duplicate APK/APEX keys are ignored and the value from the
- framework is used.
-
- --rebuild-sepolicy
- If provided, rebuilds odm.img or vendor.img to include merged sepolicy
- files. If odm is present then odm is preferred.
-
- --vendor-otatools otatools.zip
- If provided, use this otatools.zip when recompiling the odm or vendor
- image to include sepolicy.
-
- --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.
-"""
-
-import fnmatch
-import glob
-import json
-import logging
-import os
-import re
-import shutil
-import subprocess
-import sys
-import zipfile
-from xml.etree import ElementTree
-
-import add_img_to_target_files
-import apex_utils
-import build_image
-import build_super_image
-import check_target_files_vintf
-import common
-import img_from_target_files
-import find_shareduid_violation
-import ota_from_target_files
-import sparse_img
-import verity_utils
-
-from common import ExternalError
-
-logger = logging.getLogger(__name__)
-
-OPTIONS = common.OPTIONS
-# Always turn on verbose logging.
-OPTIONS.verbose = True
-OPTIONS.framework_target_files = None
-OPTIONS.framework_item_list = None
-OPTIONS.framework_misc_info_keys = None
-OPTIONS.vendor_target_files = None
-OPTIONS.vendor_item_list = None
-OPTIONS.output_target_files = None
-OPTIONS.output_dir = None
-OPTIONS.output_item_list = None
-OPTIONS.output_ota = None
-OPTIONS.output_img = None
-OPTIONS.output_super_empty = None
-OPTIONS.rebuild_recovery = False
-# TODO(b/150582573): Remove this option.
-OPTIONS.allow_duplicate_apkapex_keys = False
-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
-# system partition). The following regex matches this and extracts the
-# partition name.
-
-PARTITION_ITEM_PATTERN = re.compile(r'^([A-Z_]+)/\*$')
-
-# In apexkeys.txt or apkcerts.txt, we will find partition tags on each entry in
-# the file. We use these partition tags to filter the entries in those files
-# from the two different target files packages to produce a merged apexkeys.txt
-# or apkcerts.txt file. A partition tag (e.g., for the product partition) looks
-# like this: 'partition="product"'. We use the group syntax grab the value of
-# the tag. We use non-greedy matching in case there are other fields on the
-# same line.
-
-PARTITION_TAG_PATTERN = re.compile(r'partition="(.*?)"')
-
-# The sorting algorithm for apexkeys.txt and apkcerts.txt does not include the
-# ".apex" or ".apk" suffix, so we use the following pattern to extract a key.
-
-MODULE_KEY_PATTERN = re.compile(r'name="(.+)\.(apex|apk)"')
-
-# DEFAULT_FRAMEWORK_ITEM_LIST is a list of items to extract from the partial
-# framework target files package as is, meaning these items will land in the
-# output target files package exactly as they appear in the input partial
-# framework target files package.
-
-DEFAULT_FRAMEWORK_ITEM_LIST = (
- 'META/apkcerts.txt',
- 'META/filesystem_config.txt',
- 'META/root_filesystem_config.txt',
- 'META/update_engine_config.txt',
- 'PRODUCT/*',
- 'ROOT/*',
- 'SYSTEM/*',
-)
-
-# DEFAULT_FRAMEWORK_MISC_INFO_KEYS is a list of keys to obtain from the
-# framework instance of META/misc_info.txt. The remaining keys should come
-# from the vendor instance.
-
-DEFAULT_FRAMEWORK_MISC_INFO_KEYS = (
- 'avb_system_hashtree_enable',
- 'avb_system_add_hashtree_footer_args',
- 'avb_system_key_path',
- 'avb_system_algorithm',
- 'avb_system_rollback_index_location',
- 'avb_product_hashtree_enable',
- 'avb_product_add_hashtree_footer_args',
- 'avb_system_ext_hashtree_enable',
- 'avb_system_ext_add_hashtree_footer_args',
- 'system_root_image',
- 'root_dir',
- 'ab_update',
- 'default_system_dev_certificate',
- 'system_size',
- 'building_system_image',
- 'building_system_ext_image',
- 'building_product_image',
-)
-
-# DEFAULT_VENDOR_ITEM_LIST is a list of items to extract from the partial
-# vendor target files package as is, meaning these items will land in the output
-# target files package exactly as they appear in the input partial vendor target
-# files package.
-
-DEFAULT_VENDOR_ITEM_LIST = (
- 'META/boot_filesystem_config.txt',
- 'META/otakeys.txt',
- 'META/releasetools.py',
- 'META/vendor_filesystem_config.txt',
- 'BOOT/*',
- 'DATA/*',
- 'ODM/*',
- 'OTA/android-info.txt',
- 'PREBUILT_IMAGES/*',
- 'RADIO/*',
- 'VENDOR/*',
-)
-
-# The merge config lists should not attempt to extract items from both
-# builds for any of the following partitions. The partitions in
-# SINGLE_BUILD_PARTITIONS should come entirely from a single build (either
-# framework or vendor, but not both).
-
-SINGLE_BUILD_PARTITIONS = (
- 'BOOT/',
- 'DATA/',
- 'ODM/',
- 'PRODUCT/',
- 'SYSTEM_EXT/',
- 'RADIO/',
- 'RECOVERY/',
- 'ROOT/',
- 'SYSTEM/',
- 'SYSTEM_OTHER/',
- 'VENDOR/',
- 'VENDOR_DLKM/',
- 'ODM_DLKM/',
- 'SYSTEM_DLKM/',
-)
-
-
-def write_sorted_data(data, path):
- """Writes the sorted contents of either a list or dict to file.
-
- This function sorts the contents of the list or dict and then writes the
- resulting sorted contents to a file specified by path.
-
- Args:
- data: The list or dict to sort and write.
- path: Path to the file to write the sorted values to. The file at path will
- be overridden if it exists.
- """
- with open(path, 'w') as output:
- for entry in sorted(data):
- out_str = '{}={}\n'.format(entry, data[entry]) if isinstance(
- data, dict) else '{}\n'.format(entry)
- output.write(out_str)
-
-
-def extract_items(input_zip, output_dir, extract_item_list):
- """Extracts items in extra_item_list from a zip to a dir."""
-
- logger.info('extracting from %s', input_zip)
-
- # Filter the extract_item_list to remove any items that do not exist in the
- # zip file. Otherwise, the extraction step will fail.
-
- with zipfile.ZipFile(input_zip, allowZip64=True) as input_zipfile:
- input_namelist = input_zipfile.namelist()
-
- filtered_extract_item_list = []
- for pattern in extract_item_list:
- matching_namelist = fnmatch.filter(input_namelist, pattern)
- if not matching_namelist:
- logger.warning('no match for %s', pattern)
- else:
- filtered_extract_item_list.append(pattern)
-
- common.UnzipToDir(input_zip, output_dir, filtered_extract_item_list)
-
-
-def copy_items(from_dir, to_dir, patterns):
- """Similar to extract_items() except uses an input dir instead of zip."""
- file_paths = []
- for dirpath, _, filenames in os.walk(from_dir):
- file_paths.extend(
- os.path.relpath(path=os.path.join(dirpath, filename), start=from_dir)
- for filename in filenames)
-
- filtered_file_paths = set()
- for pattern in patterns:
- filtered_file_paths.update(fnmatch.filter(file_paths, pattern))
-
- for file_path in filtered_file_paths:
- original_file_path = os.path.join(from_dir, file_path)
- copied_file_path = os.path.join(to_dir, file_path)
- copied_file_dir = os.path.dirname(copied_file_path)
- if not os.path.exists(copied_file_dir):
- os.makedirs(copied_file_dir)
- if os.path.islink(original_file_path):
- os.symlink(os.readlink(original_file_path), copied_file_path)
- else:
- shutil.copyfile(original_file_path, copied_file_path)
-
-
-def validate_config_lists():
- """Performs validations on the merge config lists.
-
- Returns:
- False if a validation fails, otherwise true.
- """
- has_error = False
-
- default_combined_item_set = set(DEFAULT_FRAMEWORK_ITEM_LIST)
- default_combined_item_set.update(DEFAULT_VENDOR_ITEM_LIST)
-
- combined_item_set = set(OPTIONS.framework_item_list)
- combined_item_set.update(OPTIONS.vendor_item_list)
-
- # Check that the merge config lists are not missing any item specified
- # by the default config lists.
- difference = default_combined_item_set.difference(combined_item_set)
- if difference:
- logger.error('Missing merge config items: %s', list(difference))
- logger.error('Please ensure missing items are in either the '
- 'framework-item-list or vendor-item-list files provided to '
- 'this script.')
- has_error = True
-
- # Check that partitions only come from one input.
- for partition in SINGLE_BUILD_PARTITIONS:
- image_path = 'IMAGES/{}.img'.format(partition.lower().replace('/', ''))
- in_framework = (
- any(item.startswith(partition) for item in OPTIONS.framework_item_list)
- or image_path in OPTIONS.framework_item_list)
- in_vendor = (
- any(item.startswith(partition) for item in OPTIONS.vendor_item_list) or
- image_path in OPTIONS.vendor_item_list)
- if in_framework and in_vendor:
- logger.error(
- 'Cannot extract items from %s for both the framework and vendor'
- ' builds. Please ensure only one merge config item list'
- ' includes %s.', partition, partition)
- has_error = True
-
- if ('dynamic_partition_list' in OPTIONS.framework_misc_info_keys) or (
- 'super_partition_groups' in OPTIONS.framework_misc_info_keys):
- logger.error('Dynamic partition misc info keys should come from '
- 'the vendor instance of META/misc_info.txt.')
- has_error = True
-
- return not has_error
-
-
-def merge_ab_partitions_txt(framework_meta_dir, vendor_meta_dir,
- merged_meta_dir):
- """Merges META/ab_partitions.txt.
-
- The output contains the union of the partition names.
- """
- with open(os.path.join(framework_meta_dir, 'ab_partitions.txt')) as f:
- framework_ab_partitions = f.read().splitlines()
-
- with open(os.path.join(vendor_meta_dir, 'ab_partitions.txt')) as f:
- vendor_ab_partitions = f.read().splitlines()
-
- write_sorted_data(
- data=set(framework_ab_partitions + vendor_ab_partitions),
- path=os.path.join(merged_meta_dir, 'ab_partitions.txt'))
-
-
-def merge_misc_info_txt(framework_meta_dir, vendor_meta_dir, merged_meta_dir):
- """Merges META/misc_info.txt.
-
- The output contains a combination of key=value pairs from both inputs.
- Most pairs are taken from the vendor input, while some are taken from
- the framework input.
- """
-
- OPTIONS.framework_misc_info = common.LoadDictionaryFromFile(
- os.path.join(framework_meta_dir, 'misc_info.txt'))
- OPTIONS.vendor_misc_info = common.LoadDictionaryFromFile(
- os.path.join(vendor_meta_dir, 'misc_info.txt'))
-
- # Merged misc info is a combination of vendor misc info plus certain values
- # from the framework misc info.
-
- merged_dict = OPTIONS.vendor_misc_info
- for key in OPTIONS.framework_misc_info_keys:
- merged_dict[key] = OPTIONS.framework_misc_info[key]
-
- # If AVB is enabled then ensure that we build vbmeta.img.
- # Partial builds with AVB enabled may set PRODUCT_BUILD_VBMETA_IMAGE=false to
- # skip building an incomplete vbmeta.img.
- if merged_dict.get('avb_enable') == 'true':
- merged_dict['avb_building_vbmeta_image'] = 'true'
-
- return merged_dict
-
-
-def merge_dynamic_partitions_info_txt(framework_meta_dir, vendor_meta_dir,
- merged_meta_dir):
- """Merge META/dynamic_partitions_info.txt."""
- framework_dynamic_partitions_dict = common.LoadDictionaryFromFile(
- os.path.join(framework_meta_dir, 'dynamic_partitions_info.txt'))
- vendor_dynamic_partitions_dict = common.LoadDictionaryFromFile(
- os.path.join(vendor_meta_dir, 'dynamic_partitions_info.txt'))
-
- merged_dynamic_partitions_dict = common.MergeDynamicPartitionInfoDicts(
- framework_dict=framework_dynamic_partitions_dict,
- vendor_dict=vendor_dynamic_partitions_dict)
-
- write_sorted_data(
- data=merged_dynamic_partitions_dict,
- path=os.path.join(merged_meta_dir, 'dynamic_partitions_info.txt'))
-
- # Merge misc info keys used for Dynamic Partitions.
- OPTIONS.merged_misc_info.update(merged_dynamic_partitions_dict)
- # Ensure that add_img_to_target_files rebuilds super split images for
- # devices that retrofit dynamic partitions. This flag may have been set to
- # false in the partial builds to prevent duplicate building of super.img.
- OPTIONS.merged_misc_info['build_super_partition'] = 'true'
-
-
-def item_list_to_partition_set(item_list):
- """Converts a target files item list to a partition set.
-
- The item list contains items that might look like 'SYSTEM/*' or 'VENDOR/*' or
- 'OTA/android-info.txt'. Items that end in '/*' are assumed to match entire
- directories where 'SYSTEM' or 'VENDOR' is a directory name that identifies the
- contents of a partition of the same name. Other items in the list, such as the
- 'OTA' example contain metadata. This function iterates such a list, returning
- a set that contains the partition entries.
-
- Args:
- item_list: A list of items in a target files package.
-
- Returns:
- A set of partitions extracted from the list of items.
- """
-
- partition_set = set()
-
- for item in item_list:
- match = PARTITION_ITEM_PATTERN.search(item.strip())
- partition_tag = match.group(1).lower() if match else None
-
- if partition_tag:
- partition_set.add(partition_tag)
-
- return partition_set
-
-
-def merge_package_keys_txt(framework_meta_dir, vendor_meta_dir, merged_meta_dir,
- file_name):
- """Merges APK/APEX key list files."""
-
- if file_name not in ('apkcerts.txt', 'apexkeys.txt'):
- raise ExternalError(
- 'Unexpected file_name provided to merge_package_keys_txt: %s',
- file_name)
-
- def read_helper(d):
- temp = {}
- with open(os.path.join(d, file_name)) as f:
- for line in f.read().splitlines():
- line = line.strip()
- if line:
- name_search = MODULE_KEY_PATTERN.search(line.split()[0])
- temp[name_search.group(1)] = line
- return temp
-
- framework_dict = read_helper(framework_meta_dir)
- vendor_dict = read_helper(vendor_meta_dir)
- merged_dict = {}
-
- def filter_into_merged_dict(item_dict, partition_set):
- for key, value in item_dict.items():
- tag_search = PARTITION_TAG_PATTERN.search(value)
-
- if tag_search is None:
- raise ValueError('Entry missing partition tag: %s' % value)
-
- partition_tag = tag_search.group(1)
-
- if partition_tag in partition_set:
- if key in merged_dict:
- if OPTIONS.allow_duplicate_apkapex_keys:
- # TODO(b/150582573) Always raise on duplicates.
- logger.warning('Duplicate key %s' % key)
- continue
- else:
- raise ValueError('Duplicate key %s' % key)
-
- merged_dict[key] = value
-
- # Prioritize framework keys first.
- # Duplicate keys from vendor are an error, or ignored.
- filter_into_merged_dict(framework_dict, OPTIONS.framework_partition_set)
- filter_into_merged_dict(vendor_dict, OPTIONS.vendor_partition_set)
-
- # The following code is similar to write_sorted_data, but different enough
- # that we couldn't use that function. We need the output to be sorted by the
- # basename of the apex/apk (without the ".apex" or ".apk" suffix). This
- # allows the sort to be consistent with the framework/vendor input data and
- # eases comparison of input data with merged data.
- with open(os.path.join(merged_meta_dir, file_name), 'w') as output:
- for key, value in sorted(merged_dict.items()):
- output.write(value + '\n')
-
-
-def create_file_contexts_copies(framework_meta_dir, vendor_meta_dir,
- merged_meta_dir):
- """Creates named copies of each partial build's file_contexts.bin.
-
- Used when regenerating images from the partial build.
- """
-
- def copy_fc_file(source_dir, file_name):
- for name in (file_name, 'file_contexts.bin'):
- fc_path = os.path.join(source_dir, name)
- if os.path.exists(fc_path):
- shutil.copyfile(fc_path, os.path.join(merged_meta_dir, file_name))
- return
- raise ValueError('Missing file_contexts file from %s: %s', source_dir,
- file_name)
-
- copy_fc_file(framework_meta_dir, 'framework_file_contexts.bin')
- copy_fc_file(vendor_meta_dir, 'vendor_file_contexts.bin')
-
- # Replace <image>_selinux_fc values with framework or vendor file_contexts.bin
- # depending on which dictionary the key came from.
- # Only the file basename is required because all selinux_fc properties are
- # replaced with the full path to the file under META/ when misc_info.txt is
- # loaded from target files for repacking. See common.py LoadInfoDict().
- for key in OPTIONS.vendor_misc_info:
- if key.endswith('_selinux_fc'):
- OPTIONS.merged_misc_info[key] = 'vendor_file_contexts.bin'
- for key in OPTIONS.framework_misc_info:
- if key.endswith('_selinux_fc'):
- OPTIONS.merged_misc_info[key] = 'framework_file_contexts.bin'
-
-
-def compile_split_sepolicy(target_files_dir, partition_map):
- """Uses secilc to compile a split sepolicy file.
-
- Depends on various */etc/selinux/* and */etc/vintf/* files within partitions.
-
- Args:
- target_files_dir: Extracted directory of target_files, containing partition
- directories.
- partition_map: A map of partition name -> relative path within
- target_files_dir.
-
- Returns:
- A command list that can be executed to create the compiled sepolicy.
- """
-
- def get_file(partition, path):
- if partition not in partition_map:
- logger.warning('Cannot load SEPolicy files for missing partition %s',
- partition)
- return None
- return os.path.join(target_files_dir, partition_map[partition], path)
-
- # Load the kernel sepolicy version from the FCM. This is normally provided
- # directly to selinux.cpp as a build flag, but is also available in this file.
- fcm_file = get_file('system', 'etc/vintf/compatibility_matrix.device.xml')
- if not fcm_file or not os.path.exists(fcm_file):
- raise ExternalError('Missing required file for loading sepolicy: %s', fcm)
- kernel_sepolicy_version = ElementTree.parse(fcm_file).getroot().find(
- 'sepolicy/kernel-sepolicy-version').text
-
- # Load the vendor's plat sepolicy version. This is the version used for
- # locating sepolicy mapping files.
- vendor_plat_version_file = get_file('vendor',
- 'etc/selinux/plat_sepolicy_vers.txt')
- if not vendor_plat_version_file or not os.path.exists(
- vendor_plat_version_file):
- raise ExternalError('Missing required sepolicy file %s',
- vendor_plat_version_file)
- with open(vendor_plat_version_file) as f:
- vendor_plat_version = f.read().strip()
-
- # Use the same flags and arguments as selinux.cpp OpenSplitPolicy().
- cmd = ['secilc', '-m', '-M', 'true', '-G', '-N']
- cmd.extend(['-c', kernel_sepolicy_version])
- cmd.extend(['-o', os.path.join(target_files_dir, 'META/combined_sepolicy')])
- cmd.extend(['-f', '/dev/null'])
-
- required_policy_files = (
- ('system', 'etc/selinux/plat_sepolicy.cil'),
- ('system', 'etc/selinux/mapping/%s.cil' % vendor_plat_version),
- ('vendor', 'etc/selinux/vendor_sepolicy.cil'),
- ('vendor', 'etc/selinux/plat_pub_versioned.cil'),
- )
- for policy in (map(lambda partition_and_path: get_file(*partition_and_path),
- required_policy_files)):
- if not policy or not os.path.exists(policy):
- raise ExternalError('Missing required sepolicy file %s', policy)
- cmd.append(policy)
-
- optional_policy_files = (
- ('system', 'etc/selinux/mapping/%s.compat.cil' % vendor_plat_version),
- ('system_ext', 'etc/selinux/system_ext_sepolicy.cil'),
- ('system_ext', 'etc/selinux/mapping/%s.cil' % vendor_plat_version),
- ('product', 'etc/selinux/product_sepolicy.cil'),
- ('product', 'etc/selinux/mapping/%s.cil' % vendor_plat_version),
- ('odm', 'etc/selinux/odm_sepolicy.cil'),
- )
- for policy in (map(lambda partition_and_path: get_file(*partition_and_path),
- optional_policy_files)):
- if policy and os.path.exists(policy):
- cmd.append(policy)
-
- return cmd
-
-
-def validate_merged_apex_info(target_files_dir, partitions):
- """Validates the APEX files in the merged target files directory.
-
- Checks the APEX files in all possible preinstalled APEX directories.
- Depends on the <partition>/apex/* APEX files within partitions.
-
- Args:
- target_files_dir: Extracted directory of target_files, containing partition
- directories.
- partitions: A list of all the partitions in the output directory.
-
- Raises:
- RuntimeError: if apex_utils fails to parse any APEX file.
- ExternalError: if the same APEX package is provided by multiple partitions.
- """
- apex_packages = set()
-
- apex_partitions = ('system', 'system_ext', 'product', 'vendor', 'odm')
- for partition in filter(lambda p: p in apex_partitions, partitions):
- apex_info = apex_utils.GetApexInfoFromTargetFiles(
- target_files_dir, partition, compressed_only=False)
- partition_apex_packages = set([info.package_name for info in apex_info])
- duplicates = apex_packages.intersection(partition_apex_packages)
- if duplicates:
- raise ExternalError(
- 'Duplicate APEX packages found in multiple partitions: %s' %
- ' '.join(duplicates))
- apex_packages.update(partition_apex_packages)
-
-
-def generate_care_map(partitions, target_files_dir):
- """Generates a merged META/care_map.pb file in the target files dir.
-
- Depends on the info dict from META/misc_info.txt, as well as built images
- within IMAGES/.
-
- Args:
- partitions: A list of partitions to potentially include in the care map.
- target_files_dir: Extracted directory of target_files, containing partition
- directories.
- """
- OPTIONS.info_dict = common.LoadInfoDict(target_files_dir)
- partition_image_map = {}
- for partition in partitions:
- image_path = os.path.join(target_files_dir, 'IMAGES',
- '{}.img'.format(partition))
- if os.path.exists(image_path):
- partition_image_map[partition] = image_path
- # Regenerated images should have their image_size property already set.
- image_size_prop = '{}_image_size'.format(partition)
- if image_size_prop not in OPTIONS.info_dict:
- # Images copied directly from input target files packages will need
- # their image sizes calculated.
- partition_size = sparse_img.GetImagePartitionSize(image_path)
- image_props = build_image.ImagePropFromGlobalDict(
- OPTIONS.info_dict, partition)
- verity_image_builder = verity_utils.CreateVerityImageBuilder(
- image_props)
- image_size = verity_image_builder.CalculateMaxImageSize(partition_size)
- OPTIONS.info_dict[image_size_prop] = image_size
-
-
-def merge_meta_files(temp_dir, merged_dir):
- """Merges various files in META/*."""
-
- framework_meta_dir = os.path.join(temp_dir, 'framework_meta', 'META')
- extract_items(
- input_zip=OPTIONS.framework_target_files,
- output_dir=os.path.dirname(framework_meta_dir),
- extract_item_list=('META/*',))
-
- vendor_meta_dir = os.path.join(temp_dir, 'vendor_meta', 'META')
- extract_items(
- input_zip=OPTIONS.vendor_target_files,
- output_dir=os.path.dirname(vendor_meta_dir),
- extract_item_list=('META/*',))
-
- merged_meta_dir = os.path.join(merged_dir, 'META')
-
- # Merge META/misc_info.txt into OPTIONS.merged_misc_info,
- # but do not write it yet. The following functions may further
- # modify this dict.
- OPTIONS.merged_misc_info = merge_misc_info_txt(
- framework_meta_dir=framework_meta_dir,
- vendor_meta_dir=vendor_meta_dir,
- merged_meta_dir=merged_meta_dir)
-
- create_file_contexts_copies(
- framework_meta_dir=framework_meta_dir,
- vendor_meta_dir=vendor_meta_dir,
- merged_meta_dir=merged_meta_dir)
-
- if OPTIONS.merged_misc_info.get('use_dynamic_partitions') == 'true':
- merge_dynamic_partitions_info_txt(
- framework_meta_dir=framework_meta_dir,
- vendor_meta_dir=vendor_meta_dir,
- merged_meta_dir=merged_meta_dir)
-
- if OPTIONS.merged_misc_info.get('ab_update') == 'true':
- merge_ab_partitions_txt(
- framework_meta_dir=framework_meta_dir,
- vendor_meta_dir=vendor_meta_dir,
- merged_meta_dir=merged_meta_dir)
-
- for file_name in ('apkcerts.txt', 'apexkeys.txt'):
- merge_package_keys_txt(
- framework_meta_dir=framework_meta_dir,
- vendor_meta_dir=vendor_meta_dir,
- merged_meta_dir=merged_meta_dir,
- file_name=file_name)
-
- # Write the now-finalized OPTIONS.merged_misc_info.
- write_sorted_data(
- data=OPTIONS.merged_misc_info,
- path=os.path.join(merged_meta_dir, 'misc_info.txt'))
-
-
-def process_dexopt(temp_dir, output_target_files_dir):
- """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.
- output_target_files_dir: The name of a directory that will be used to create
- the output target files package after all the special cases are processed.
- """
- # Load vendor and framework META/misc_info.txt.
- if (OPTIONS.vendor_misc_info.get('building_with_vsdk') != 'true' or
- OPTIONS.framework_dexpreopt_tools is None or
- OPTIONS.framework_dexpreopt_config is None or
- OPTIONS.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(
- input_zip=OPTIONS.framework_dexpreopt_tools,
- output_dir=dexpreopt_tools_files_temp_dir,
- extract_item_list=('*',))
- extract_items(
- input_zip=OPTIONS.framework_dexpreopt_config,
- output_dir=dexpreopt_framework_config_files_temp_dir,
- extract_item_list=('*',))
- extract_items(
- input_zip=OPTIONS.vendor_dexpreopt_config,
- output_dir=dexpreopt_vendor_config_files_temp_dir,
- extract_item_list=('*',))
-
- os.symlink(
- os.path.join(output_target_files_dir, 'SYSTEM'),
- os.path.join(temp_dir, 'system'))
- os.symlink(
- os.path.join(output_target_files_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_dir, 'SYSTEM', 'apex')
-
- # Check for flattended versus updatable APEX.
- if OPTIONS.framework_misc_info.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_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):
- """Merges two target files packages into one target files structure.
-
- Returns:
- Path to merged package under temp directory.
- """
- # Extract "as is" items from the input framework and vendor partial target
- # files packages directly into the output temporary directory, since these items
- # do not need special case processing.
-
- output_target_files_temp_dir = os.path.join(temp_dir, 'output')
- extract_items(
- input_zip=OPTIONS.framework_target_files,
- output_dir=output_target_files_temp_dir,
- extract_item_list=OPTIONS.framework_item_list)
- extract_items(
- input_zip=OPTIONS.vendor_target_files,
- output_dir=output_target_files_temp_dir,
- extract_item_list=OPTIONS.vendor_item_list)
-
- # 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.
- merge_meta_files(temp_dir=temp_dir, merged_dir=output_target_files_temp_dir)
-
- process_dexopt(
- temp_dir=temp_dir, output_target_files_dir=output_target_files_temp_dir)
-
- return output_target_files_temp_dir
-
-
-def generate_missing_images(target_files_dir):
- """Generate any missing images from target files."""
-
- # Regenerate IMAGES in the target directory.
-
- add_img_args = [
- '--verbose',
- '--add_missing',
- ]
- if OPTIONS.rebuild_recovery:
- add_img_args.append('--rebuild_recovery')
- add_img_args.append(target_files_dir)
-
- add_img_to_target_files.main(add_img_args)
-
-
-def rebuild_image_with_sepolicy(target_files_dir):
- """Rebuilds odm.img or vendor.img to include merged sepolicy files.
-
- If odm is present then odm is preferred -- otherwise vendor is used.
- """
- partition = 'vendor'
- if os.path.exists(os.path.join(target_files_dir, 'ODM')) or os.path.exists(
- os.path.join(target_files_dir, 'IMAGES/odm.img')):
- partition = 'odm'
- partition_img = '{}.img'.format(partition)
- partition_map = '{}.map'.format(partition)
-
- logger.info('Recompiling %s using the merged sepolicy files.', partition_img)
-
- # Copy the combined SEPolicy file and framework hashes to the image that is
- # being rebuilt.
- def copy_selinux_file(input_path, output_filename):
- input_filename = os.path.join(target_files_dir, input_path)
- if not os.path.exists(input_filename):
- input_filename = input_filename.replace('SYSTEM_EXT/', 'SYSTEM/system_ext/') \
- .replace('PRODUCT/', 'SYSTEM/product/')
- if not os.path.exists(input_filename):
- logger.info('Skipping copy_selinux_file for %s', input_filename)
- return
- shutil.copy(
- input_filename,
- os.path.join(target_files_dir, partition.upper(), 'etc/selinux',
- output_filename))
-
- copy_selinux_file('META/combined_sepolicy', 'precompiled_sepolicy')
- copy_selinux_file('SYSTEM/etc/selinux/plat_sepolicy_and_mapping.sha256',
- 'precompiled_sepolicy.plat_sepolicy_and_mapping.sha256')
- copy_selinux_file(
- 'SYSTEM_EXT/etc/selinux/system_ext_sepolicy_and_mapping.sha256',
- 'precompiled_sepolicy.system_ext_sepolicy_and_mapping.sha256')
- copy_selinux_file('PRODUCT/etc/selinux/product_sepolicy_and_mapping.sha256',
- 'precompiled_sepolicy.product_sepolicy_and_mapping.sha256')
-
- if not OPTIONS.vendor_otatools:
- # Remove the partition from the merged target-files archive. It will be
- # rebuilt later automatically by generate_missing_images().
- os.remove(os.path.join(target_files_dir, 'IMAGES', partition_img))
- return
-
- # TODO(b/192253131): Remove the need for vendor_otatools by fixing
- # backwards-compatibility issues when compiling images across releases.
- if not OPTIONS.vendor_target_files:
- raise ValueError(
- 'Expected vendor_target_files if vendor_otatools is not None.')
- logger.info(
- '%s recompilation will be performed using the vendor otatools.zip',
- partition_img)
-
- # Unzip the vendor build's otatools.zip and target-files archive.
- vendor_otatools_dir = common.MakeTempDir(
- prefix='merge_target_files_vendor_otatools_')
- vendor_target_files_dir = common.MakeTempDir(
- prefix='merge_target_files_vendor_target_files_')
- common.UnzipToDir(OPTIONS.vendor_otatools, vendor_otatools_dir)
- common.UnzipToDir(OPTIONS.vendor_target_files, vendor_target_files_dir)
-
- # Copy the partition contents from the merged target-files archive to the
- # vendor target-files archive.
- shutil.rmtree(os.path.join(vendor_target_files_dir, partition.upper()))
- shutil.copytree(
- os.path.join(target_files_dir, partition.upper()),
- os.path.join(vendor_target_files_dir, partition.upper()),
- symlinks=True)
-
- # Delete then rebuild the partition.
- os.remove(os.path.join(vendor_target_files_dir, 'IMAGES', partition_img))
- rebuild_partition_command = [
- os.path.join(vendor_otatools_dir, 'bin', 'add_img_to_target_files'),
- '--verbose',
- '--add_missing',
- ]
- if OPTIONS.rebuild_recovery:
- rebuild_partition_command.append('--rebuild_recovery')
- rebuild_partition_command.append(vendor_target_files_dir)
- logger.info('Recompiling %s: %s', partition_img,
- ' '.join(rebuild_partition_command))
- common.RunAndCheckOutput(rebuild_partition_command, verbose=True)
-
- # Move the newly-created image to the merged target files dir.
- if not os.path.exists(os.path.join(target_files_dir, 'IMAGES')):
- os.makedirs(os.path.join(target_files_dir, 'IMAGES'))
- shutil.move(
- os.path.join(vendor_target_files_dir, 'IMAGES', partition_img),
- os.path.join(target_files_dir, 'IMAGES', partition_img))
- shutil.move(
- os.path.join(vendor_target_files_dir, 'IMAGES', partition_map),
- os.path.join(target_files_dir, 'IMAGES', partition_map))
-
- def copy_recovery_file(filename):
- for subdir in ('VENDOR', 'SYSTEM/vendor'):
- source = os.path.join(vendor_target_files_dir, subdir, filename)
- if os.path.exists(source):
- dest = os.path.join(target_files_dir, subdir, filename)
- shutil.copy(source, dest)
- return
- logger.info('Skipping copy_recovery_file for %s, file not found', filename)
-
- if OPTIONS.rebuild_recovery:
- copy_recovery_file('etc/recovery.img')
- copy_recovery_file('bin/install-recovery.sh')
- copy_recovery_file('recovery-from-boot.p')
-
-
-def generate_super_empty_image(target_dir, output_super_empty):
- """Generates super_empty image from target package.
-
- Args:
- target_dir: Path to the target file package which contains misc_info.txt for
- detailed information for super image.
- output_super_empty: If provided, copies a super_empty.img file from the
- target files package to this path.
- """
- # Create super_empty.img using the merged misc_info.txt.
-
- misc_info_txt = os.path.join(target_dir, 'META', 'misc_info.txt')
-
- use_dynamic_partitions = common.LoadDictionaryFromFile(misc_info_txt).get(
- 'use_dynamic_partitions')
-
- if use_dynamic_partitions != 'true' and output_super_empty:
- raise ValueError(
- 'Building super_empty.img requires use_dynamic_partitions=true.')
- elif use_dynamic_partitions == 'true':
- super_empty_img = os.path.join(target_dir, 'IMAGES', 'super_empty.img')
- build_super_image_args = [
- misc_info_txt,
- super_empty_img,
- ]
- build_super_image.main(build_super_image_args)
-
- # Copy super_empty.img to the user-provided output_super_empty location.
- if output_super_empty:
- shutil.copyfile(super_empty_img, output_super_empty)
-
-
-def create_target_files_archive(output_zip, source_dir, temp_dir):
- """Creates a target_files zip archive from the input source dir.
-
- Args:
- output_zip: The name of the zip archive target files package.
- source_dir: The target directory contains package to be archived.
- temp_dir: Path to temporary directory for any intermediate files.
- """
- output_target_files_list = os.path.join(temp_dir, 'output.list')
- output_target_files_meta_dir = os.path.join(source_dir, 'META')
-
- def files_from_path(target_path, extra_args=None):
- """Gets files under the given path and return a sorted list."""
- find_command = ['find', target_path] + (extra_args or [])
- find_process = common.Run(
- find_command, stdout=subprocess.PIPE, verbose=False)
- return common.RunAndCheckOutput(['sort'],
- stdin=find_process.stdout,
- verbose=False)
-
- # META content appears first in the zip. This is done by the
- # standard build system for optimized extraction of those files,
- # so we do the same step for merged target_files.zips here too.
- meta_content = files_from_path(output_target_files_meta_dir)
- other_content = files_from_path(
- source_dir,
- ['-path', output_target_files_meta_dir, '-prune', '-o', '-print'])
-
- with open(output_target_files_list, 'w') as f:
- f.write(meta_content)
- f.write(other_content)
-
- command = [
- 'soong_zip',
- '-d',
- '-o',
- os.path.abspath(output_zip),
- '-C',
- source_dir,
- '-r',
- output_target_files_list,
- ]
-
- logger.info('creating %s', output_zip)
- common.RunAndCheckOutput(command, verbose=True)
- logger.info('finished creating %s', output_zip)
-
-
-def merge_target_files(temp_dir):
- """Merges two target files packages together.
-
- This function uses framework and vendor target files packages as input,
- performs various file extractions, special case processing, and finally
- creates a merged zip archive as output.
-
- Args:
- temp_dir: The name of a directory we use when we extract items from the
- input target files packages, and also a scratch directory that we use for
- temporary files.
- """
-
- logger.info('starting: merge framework %s and vendor %s into output %s',
- OPTIONS.framework_target_files, OPTIONS.vendor_target_files,
- OPTIONS.output_target_files)
-
- output_target_files_temp_dir = create_merged_package(temp_dir)
-
- if not check_target_files_vintf.CheckVintf(output_target_files_temp_dir):
- raise RuntimeError('Incompatible VINTF metadata')
-
- partition_map = common.PartitionMapFromTargetFiles(
- output_target_files_temp_dir)
-
- # Generate and check for cross-partition violations of sharedUserId
- # values in APKs. This requires the input target-files packages to contain
- # *.apk files.
- shareduid_violation_modules = os.path.join(
- output_target_files_temp_dir, 'META', 'shareduid_violation_modules.json')
- with open(shareduid_violation_modules, 'w') as f:
- violation = find_shareduid_violation.FindShareduidViolation(
- output_target_files_temp_dir, partition_map)
-
- # Write the output to a file to enable debugging.
- f.write(violation)
-
- # Check for violations across the input builds' partition groups.
- shareduid_errors = common.SharedUidPartitionViolations(
- json.loads(violation),
- [OPTIONS.framework_partition_set, OPTIONS.vendor_partition_set])
- if shareduid_errors:
- for error in shareduid_errors:
- logger.error(error)
- raise ValueError('sharedUserId APK error. See %s' %
- shareduid_violation_modules)
-
- # host_init_verifier and secilc check only the following partitions:
- filtered_partitions = {
- partition: path
- for partition, path in partition_map.items()
- if partition in ['system', 'system_ext', 'product', 'vendor', 'odm']
- }
-
- # Run host_init_verifier on the combined init rc files.
- common.RunHostInitVerifier(
- product_out=output_target_files_temp_dir,
- partition_map=filtered_partitions)
-
- # Check that the split sepolicy from the multiple builds can compile.
- split_sepolicy_cmd = compile_split_sepolicy(output_target_files_temp_dir,
- filtered_partitions)
- logger.info('Compiling split sepolicy: %s', ' '.join(split_sepolicy_cmd))
- common.RunAndCheckOutput(split_sepolicy_cmd)
- # Include the compiled policy in an image if requested.
- if OPTIONS.rebuild_sepolicy:
- rebuild_image_with_sepolicy(output_target_files_temp_dir)
-
- # Run validation checks on the pre-installed APEX files.
- validate_merged_apex_info(output_target_files_temp_dir, partition_map.keys())
-
- generate_missing_images(output_target_files_temp_dir)
-
- generate_super_empty_image(output_target_files_temp_dir,
- OPTIONS.output_super_empty)
-
- # Finally, create the output target files zip archive and/or copy the
- # output items to the output target files directory.
-
- if OPTIONS.output_dir:
- copy_items(output_target_files_temp_dir, OPTIONS.output_dir,
- OPTIONS.output_item_list)
-
- if not OPTIONS.output_target_files:
- return
-
- # Create the merged META/care_map.pb if the device uses A/B updates.
- if OPTIONS.merged_misc_info.get('ab_update') == 'true':
- generate_care_map(partition_map.keys(), output_target_files_temp_dir)
-
- create_target_files_archive(OPTIONS.output_target_files,
- output_target_files_temp_dir, temp_dir)
-
- # Create the IMG package from the merged target files package.
- if OPTIONS.output_img:
- img_from_target_files.main(
- [OPTIONS.output_target_files, OPTIONS.output_img])
-
- # Create the OTA package from the merged target files package.
-
- if OPTIONS.output_ota:
- ota_from_target_files.main(
- [OPTIONS.output_target_files, OPTIONS.output_ota])
-
-
-def call_func_with_temp_dir(func, keep_tmp):
- """Manages the creation and cleanup of the temporary directory.
-
- This function calls the given function after first creating a temporary
- directory. It also cleans up the temporary directory.
-
- Args:
- func: The function to call. Should accept one parameter, the path to the
- temporary directory.
- keep_tmp: Keep the temporary directory after processing is complete.
- """
-
- # Create a temporary directory. This will serve as the parent of directories
- # we use when we extract items from the input target files packages, and also
- # a scratch directory that we use for temporary files.
-
- temp_dir = common.MakeTempDir(prefix='merge_target_files_')
-
- try:
- func(temp_dir)
- finally:
- if keep_tmp:
- logger.info('keeping %s', temp_dir)
- else:
- common.Cleanup()
-
-
-def main():
- """The main function.
-
- Process command line arguments, then call merge_target_files to
- perform the heavy lifting.
- """
-
- common.InitLogging()
-
- def option_handler(o, a):
- if o == '--system-target-files':
- logger.warning(
- '--system-target-files has been renamed to --framework-target-files')
- OPTIONS.framework_target_files = a
- elif o == '--framework-target-files':
- OPTIONS.framework_target_files = a
- elif o == '--system-item-list':
- logger.warning(
- '--system-item-list has been renamed to --framework-item-list')
- OPTIONS.framework_item_list = a
- elif o == '--framework-item-list':
- OPTIONS.framework_item_list = a
- elif o == '--system-misc-info-keys':
- logger.warning('--system-misc-info-keys has been renamed to '
- '--framework-misc-info-keys')
- OPTIONS.framework_misc_info_keys = a
- elif o == '--framework-misc-info-keys':
- OPTIONS.framework_misc_info_keys = a
- elif o == '--other-target-files':
- logger.warning(
- '--other-target-files has been renamed to --vendor-target-files')
- OPTIONS.vendor_target_files = a
- elif o == '--vendor-target-files':
- OPTIONS.vendor_target_files = a
- elif o == '--other-item-list':
- logger.warning('--other-item-list has been renamed to --vendor-item-list')
- OPTIONS.vendor_item_list = a
- elif o == '--vendor-item-list':
- OPTIONS.vendor_item_list = a
- elif o == '--output-target-files':
- OPTIONS.output_target_files = a
- elif o == '--output-dir':
- OPTIONS.output_dir = a
- elif o == '--output-item-list':
- OPTIONS.output_item_list = a
- elif o == '--output-ota':
- OPTIONS.output_ota = a
- elif o == '--output-img':
- OPTIONS.output_img = a
- elif o == '--output-super-empty':
- OPTIONS.output_super_empty = a
- elif o == '--rebuild_recovery':
- OPTIONS.rebuild_recovery = True
- elif o == '--allow-duplicate-apkapex-keys':
- OPTIONS.allow_duplicate_apkapex_keys = True
- elif o == '--vendor-otatools':
- OPTIONS.vendor_otatools = a
- elif o == '--rebuild-sepolicy':
- 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
-
- args = common.ParseOptions(
- sys.argv[1:],
- __doc__,
- extra_long_opts=[
- 'system-target-files=',
- 'framework-target-files=',
- 'system-item-list=',
- 'framework-item-list=',
- 'system-misc-info-keys=',
- 'framework-misc-info-keys=',
- 'other-target-files=',
- 'vendor-target-files=',
- 'other-item-list=',
- 'vendor-item-list=',
- 'output-target-files=',
- 'output-dir=',
- 'output-item-list=',
- 'output-ota=',
- 'output-img=',
- 'output-super-empty=',
- 'framework-dexpreopt-config=',
- 'framework-dexpreopt-tools=',
- 'vendor-dexpreopt-config=',
- 'rebuild_recovery',
- 'allow-duplicate-apkapex-keys',
- 'vendor-otatools=',
- 'rebuild-sepolicy',
- 'keep-tmp',
- ],
- extra_option_handler=option_handler)
-
- # pylint: disable=too-many-boolean-expressions
- if (args or OPTIONS.framework_target_files is None or
- OPTIONS.vendor_target_files is None or
- (OPTIONS.output_target_files is None and OPTIONS.output_dir is None) or
- (OPTIONS.output_dir is not None and OPTIONS.output_item_list is None) or
- (OPTIONS.rebuild_recovery and not OPTIONS.rebuild_sepolicy)):
- common.Usage(__doc__)
- sys.exit(1)
-
- if OPTIONS.framework_item_list:
- OPTIONS.framework_item_list = common.LoadListFromFile(
- OPTIONS.framework_item_list)
- else:
- OPTIONS.framework_item_list = DEFAULT_FRAMEWORK_ITEM_LIST
- OPTIONS.framework_partition_set = item_list_to_partition_set(
- OPTIONS.framework_item_list)
-
- if OPTIONS.framework_misc_info_keys:
- OPTIONS.framework_misc_info_keys = common.LoadListFromFile(
- OPTIONS.framework_misc_info_keys)
- else:
- OPTIONS.framework_misc_info_keys = DEFAULT_FRAMEWORK_MISC_INFO_KEYS
-
- if OPTIONS.vendor_item_list:
- OPTIONS.vendor_item_list = common.LoadListFromFile(OPTIONS.vendor_item_list)
- else:
- OPTIONS.vendor_item_list = DEFAULT_VENDOR_ITEM_LIST
- OPTIONS.vendor_partition_set = item_list_to_partition_set(
- OPTIONS.vendor_item_list)
-
- if OPTIONS.output_item_list:
- OPTIONS.output_item_list = common.LoadListFromFile(OPTIONS.output_item_list)
- else:
- OPTIONS.output_item_list = None
-
- if not validate_config_lists():
- sys.exit(1)
-
- call_func_with_temp_dir(lambda temp_dir: merge_target_files(temp_dir),
- OPTIONS.keep_tmp)
-
-
-if __name__ == '__main__':
- main()
diff --git a/tools/releasetools/ota_from_target_files.py b/tools/releasetools/ota_from_target_files.py
index 93e7042..522d489 100755
--- a/tools/releasetools/ota_from_target_files.py
+++ b/tools/releasetools/ota_from_target_files.py
@@ -241,6 +241,9 @@
--spl_downgrade
Force generate an SPL downgrade OTA. Only needed if target build has an
older SPL.
+
+ --vabc_compression_param
+ Compression algorithm to be used for VABC. Available options: gz, brotli, none
"""
from __future__ import print_function
@@ -312,6 +315,7 @@
OPTIONS.compressor_types = None
OPTIONS.enable_zucchini = True
OPTIONS.enable_lz4diff = False
+OPTIONS.vabc_compression_param = None
POSTINSTALL_CONFIG = 'META/postinstall_config.txt'
DYNAMIC_PARTITION_INFO = 'META/dynamic_partitions_info.txt'
@@ -539,8 +543,7 @@
oem_dicts = []
for oem_file in oem_source:
- with open(oem_file) as fp:
- oem_dicts.append(common.LoadDictionaryFromLines(fp.readlines()))
+ oem_dicts.append(common.LoadDictionaryFromFile(oem_file))
return oem_dicts
@@ -651,6 +654,24 @@
return (payload_offset, metadata_total)
+def ModifyVABCCompressionParam(content, algo):
+ """ Update update VABC Compression Param in dynamic_partitions_info.txt
+ Args:
+ content: The string content of dynamic_partitions_info.txt
+ algo: The compression algorithm should be used for VABC. See
+ https://cs.android.com/android/platform/superproject/+/master:system/core/fs_mgr/libsnapshot/cow_writer.cpp;l=127;bpv=1;bpt=1?q=CowWriter::ParseOptions&sq=
+ Returns:
+ Updated content of dynamic_partitions_info.txt , with custom compression algo
+ """
+ output_list = []
+ for line in content.splitlines():
+ if line.startswith("virtual_ab_compression_method="):
+ continue
+ output_list.append(line)
+ output_list.append("virtual_ab_compression_method="+algo)
+ return "\n".join(output_list)
+
+
def UpdatesInfoForSpecialUpdates(content, partitions_filter,
delete_keys=None):
""" Updates info file for secondary payload generation, partial update, etc.
@@ -805,6 +826,27 @@
return common.LoadInfoDict(zfp)
+def GetTargetFilesZipForCustomVABCCompression(input_file, vabc_compression_param):
+ """Returns a target-files.zip with a custom VABC compression param.
+ Args:
+ input_file: The input target-files.zip path
+ vabc_compression_param: Custom Virtual AB Compression algorithm
+
+ Returns:
+ The path to modified target-files.zip
+ """
+ target_file = common.MakeTempFile(prefix="targetfiles-", suffix=".zip")
+ shutil.copyfile(input_file, target_file)
+ common.ZipDelete(target_file, DYNAMIC_PARTITION_INFO)
+ with zipfile.ZipFile(input_file, 'r', allowZip64=True) as zfp:
+ dynamic_partition_info = zfp.read(DYNAMIC_PARTITION_INFO).decode()
+ dynamic_partition_info = ModifyVABCCompressionParam(
+ dynamic_partition_info, vabc_compression_param)
+ with zipfile.ZipFile(target_file, "a", allowZip64=True) as output_zip:
+ output_zip.writestr(DYNAMIC_PARTITION_INFO, dynamic_partition_info)
+ return target_file
+
+
def GetTargetFilesZipForPartialUpdates(input_file, ab_partitions):
"""Returns a target-files.zip for partial ota update package generation.
@@ -879,6 +921,9 @@
content = input_zip.read(info_file).decode()
modified_info = UpdatesInfoForSpecialUpdates(
content, lambda p: p in ab_partitions)
+ if OPTIONS.vabc_compression_param and info_file == DYNAMIC_PARTITION_INFO:
+ modified_info = ModifyVABCCompressionParam(
+ modified_info, OPTIONS.vabc_compression_param)
common.ZipWriteStr(partial_target_zip, info_file, modified_info)
# TODO(xunchang) handle META/postinstall_config.txt'
@@ -1114,7 +1159,7 @@
# Source build's update_engine must be able to write XOR ops, and target
# build's snapuserd must be able to interpret XOR ops.
if not target_info.is_vabc_xor or OPTIONS.disable_vabc or \
- (source_info is not None and not source_info.is_vabc_xor):
+ (source_info is not None and not source_info.is_vabc_xor):
logger.info("VABC XOR Not supported, disabling")
OPTIONS.enable_vabc_xor = False
additional_args = []
@@ -1132,6 +1177,9 @@
target_file = GetTargetFilesZipForPartialUpdates(target_file,
OPTIONS.partial)
additional_args += ["--is_partial_update", "true"]
+ elif OPTIONS.vabc_compression_param:
+ target_file = GetTargetFilesZipForCustomVABCCompression(
+ target_file, OPTIONS.vabc_compression_param)
elif OPTIONS.skip_postinstall:
target_file = GetTargetFilesZipWithoutPostinstallConfig(target_file)
# Target_file may have been modified, reparse ab_partitions
@@ -1166,7 +1214,7 @@
str(OPTIONS.enable_zucchini).lower()]
if not ota_utils.IsLz4diffCompatible(source_file, target_file):
- logger.warn(
+ logger.warning(
"Source build doesn't support lz4diff, or source/target don't have compatible lz4diff versions. Disabling lz4diff.")
OPTIONS.enable_lz4diff = False
@@ -1377,6 +1425,8 @@
elif o == "--enable_lz4diff":
assert a.lower() in ["true", "false"]
OPTIONS.enable_lz4diff = a.lower() != "false"
+ elif o == "--vabc_compression_param":
+ OPTIONS.vabc_compression_param = a.lower()
else:
return False
return True
@@ -1424,8 +1474,9 @@
"enable_vabc_xor=",
"force_minor_version=",
"compressor_types=",
- "enable_zucchin=",
+ "enable_zucchini=",
"enable_lz4diff=",
+ "vabc_compression_param=",
], extra_option_handler=option_handler)
if len(args) != 2:
diff --git a/tools/releasetools/sign_apex.py b/tools/releasetools/sign_apex.py
index 722359b..a68f1ec 100755
--- a/tools/releasetools/sign_apex.py
+++ b/tools/releasetools/sign_apex.py
@@ -61,6 +61,7 @@
import common
logger = logging.getLogger(__name__)
+OPTIONS = common.OPTIONS
def SignApexFile(avbtool, apex_file, payload_key, container_key, no_hashtree,
@@ -81,7 +82,7 @@
apk_keys=apk_keys,
signing_args=signing_args,
sign_tool=sign_tool,
- is_sepolicy=apex_file.endswith("sepolicy.apex"),
+ is_sepolicy=apex_file.endswith(OPTIONS.sepolicy_name),
sepolicy_key=sepolicy_key,
sepolicy_cert=sepolicy_cert,
fsverity_tool=fsverity_tool)
diff --git a/tools/releasetools/sign_target_files_apks.py b/tools/releasetools/sign_target_files_apks.py
index 054315f..c803340 100755
--- a/tools/releasetools/sign_target_files_apks.py
+++ b/tools/releasetools/sign_target_files_apks.py
@@ -137,6 +137,15 @@
--android_jar_path <path>
Path to the android.jar to repack the apex file.
+ --sepolicy_key <key>
+ Optional flag that specifies the sepolicy signing key, defaults to payload_key for the sepolicy.apex.
+
+ --sepolicy_cert <cert>
+ Optional flag that specifies the sepolicy signing cert.
+
+ --fsverity_tool <path>
+ Optional flag that specifies the path to fsverity tool to sign SEPolicy, defaults to fsverity.
+
--allow_gsi_debug_sepolicy
Allow the existence of the file 'userdebug_plat_sepolicy.cil' under
(/system/system_ext|/system_ext)/etc/selinux.
@@ -196,6 +205,9 @@
OPTIONS.android_jar_path = None
OPTIONS.vendor_partitions = set()
OPTIONS.vendor_otatools = None
+OPTIONS.sepolicy_key = None
+OPTIONS.sepolicy_cert = None
+OPTIONS.fsverity_tool = None
OPTIONS.allow_gsi_debug_sepolicy = False
@@ -234,6 +246,8 @@
def IsApexFile(filename):
return filename.endswith(".apex") or filename.endswith(".capex")
+def IsSepolicyApex(filename):
+ return filename.endswith(OPTIONS.sepolicy_name)
def GetApexFilename(filename):
name = os.path.basename(filename)
@@ -256,6 +270,24 @@
return certmap
+def GetSepolicyKeys(keys_info):
+ """Gets SEPolicy signing keys applying overrides from command line options.
+
+ Args:
+ keys_info: A dict that maps from the SEPolicy APEX filename to a tuple of
+ (sepolicy_key, sepolicy_cert, fsverity_tool).
+
+ Returns:
+ A dict that contains the updated APEX key mapping, which should be used for
+ the current signing.
+ """
+ for name in keys_info:
+ (sepolicy_key, sepolicy_cert, fsverity_tool) = keys_info[name]
+ sepolicy_key = OPTIONS.sepolicy_key if OPTIONS.sepolicy_key else sepolicy_key
+ sepolicy_cert = OPTIONS.sepolicy_cert if OPTIONS.sepolicy_cert else sepolicy_cert
+ fsverity_tool = OPTIONS.fsverity_tool if OPTIONS.fsverity_tool else fsverity_tool
+ keys_info[name] = (sepolicy_key, sepolicy_cert, fsverity_tool)
+ return keys_info
def GetApexKeys(keys_info, key_map):
"""Gets APEX payload and container signing keys by applying the mapping rules.
@@ -518,7 +550,7 @@
def ProcessTargetFiles(input_tf_zip, output_tf_zip, misc_info,
apk_keys, apex_keys, key_passwords,
platform_api_level, codename_to_api_level_map,
- compressed_extension):
+ compressed_extension, sepolicy_keys):
# maxsize measures the maximum filename length, including the ones to be
# skipped.
try:
@@ -586,6 +618,17 @@
print(" : %-*s payload (%s)" % (
maxsize, name, payload_key))
+ sepolicy_key = None
+ sepolicy_cert = None
+ fsverity_tool = None
+
+ if IsSepolicyApex(name):
+ (sepolicy_key, sepolicy_cert, fsverity_tool) = sepolicy_keys[name]
+ print(" : %-*s sepolicy key (%s)" % (
+ maxsize, name, sepolicy_key))
+ print(" : %-*s sepolicy cert (%s)" % (
+ maxsize, name, sepolicy_cert))
+
signed_apex = apex_utils.SignApex(
misc_info['avb_avbtool'],
data,
@@ -596,7 +639,11 @@
codename_to_api_level_map,
no_hashtree=None, # Let apex_util determine if hash tree is needed
signing_args=OPTIONS.avb_extra_args.get('apex'),
- sign_tool=sign_tool)
+ sign_tool=sign_tool,
+ is_sepolicy=IsSepolicyApex(name),
+ sepolicy_key=sepolicy_key,
+ sepolicy_cert=sepolicy_cert,
+ fsverity_tool=fsverity_tool)
common.ZipWrite(output_tf_zip, signed_apex, filename)
else:
@@ -1206,20 +1253,24 @@
def ReadApexKeysInfo(tf_zip):
"""Parses the APEX keys info from a given target-files zip.
- Given a target-files ZipFile, parses the META/apexkeys.txt entry and returns a
- dict that contains the mapping from APEX names (e.g. com.android.tzdata) to a
- tuple of (payload_key, container_key, sign_tool).
+ Given a target-files ZipFile, parses the META/apexkeys.txt entry and returns
+ two dicts, the first one contains the mapping from APEX names
+ (e.g. com.android.tzdata) to a tuple of (payload_key, container_key,
+ sign_tool). The second one maps the sepolicy APEX name to a tuple containing
+ (sepolicy_key, sepolicy_cert, fsverity_tool).
Args:
tf_zip: The input target_files ZipFile (already open).
Returns:
- (payload_key, container_key, sign_tool):
+ name : (payload_key, container_key, sign_tool)
- payload_key contains the path to the payload signing key
- container_key contains the path to the container signing key
- sign_tool is an apex-specific signing tool for its payload contents
+ name : (sepolicy_key, sepolicy_cert, fsverity_tool)
"""
keys = {}
+ sepolicy_keys = {}
for line in tf_zip.read('META/apexkeys.txt').decode().split('\n'):
line = line.strip()
if not line:
@@ -1230,6 +1281,9 @@
r'private_key="(?P<PAYLOAD_PRIVATE_KEY>.*)"\s+'
r'container_certificate="(?P<CONTAINER_CERT>.*)"\s+'
r'container_private_key="(?P<CONTAINER_PRIVATE_KEY>.*?)"'
+ r'(\s+sepolicy_key="(?P<SEPOLICY_KEY>.*?)")?'
+ r'(\s+sepolicy_certificate="(?P<SEPOLICY_CERT>.*?)")?'
+ r'(\s+fsverity_tool="(?P<FSVERITY_TOOL>.*?)")?'
r'(\s+partition="(?P<PARTITION>.*?)")?'
r'(\s+sign_tool="(?P<SIGN_TOOL>.*?)")?$',
line)
@@ -1258,12 +1312,18 @@
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))
+ raise ValueError("Failed to parse container keys: \n{} **** {}".format(container_cert, container_private_key))
sign_tool = matches.group("SIGN_TOOL")
keys[name] = (payload_private_key, container_key, sign_tool)
- return keys
+ if IsSepolicyApex(name):
+ sepolicy_key = matches.group('SEPOLICY_KEY')
+ sepolicy_cert = matches.group('SEPOLICY_CERT')
+ fsverity_tool = matches.group('FSVERITY_TOOL')
+ sepolicy_keys[name] = (sepolicy_key, sepolicy_cert, fsverity_tool)
+
+ return keys, sepolicy_keys
def BuildVendorPartitions(output_zip_path):
@@ -1278,6 +1338,9 @@
vendor_tempdir = common.UnzipTemp(output_zip_path, [
"META/*",
"SYSTEM/build.prop",
+ "RECOVERY/*",
+ "BOOT/*",
+ "OTA/",
] + ["{}/*".format(p.upper()) for p in OPTIONS.vendor_partitions])
# Disable various partitions that build based on misc_info fields.
@@ -1286,9 +1349,12 @@
# otatools if necessary.
vendor_misc_info_path = os.path.join(vendor_tempdir, "META/misc_info.txt")
vendor_misc_info = common.LoadDictionaryFromFile(vendor_misc_info_path)
- vendor_misc_info["no_boot"] = "true" # boot
- vendor_misc_info["vendor_boot"] = "false" # vendor_boot
- vendor_misc_info["no_recovery"] = "true" # recovery
+ # Ignore if not rebuilding recovery
+ if not OPTIONS.rebuild_recovery:
+ vendor_misc_info["no_boot"] = "true" # boot
+ vendor_misc_info["vendor_boot"] = "false" # vendor_boot
+ vendor_misc_info["no_recovery"] = "true" # recovery
+
vendor_misc_info["board_bpt_enable"] = "false" # partition-table
vendor_misc_info["has_dtbo"] = "false" # dtbo
vendor_misc_info["has_pvmfw"] = "false" # pvmfw
@@ -1321,8 +1387,12 @@
os.remove(os.path.join(vendor_tempdir, "META/pack_radioimages.txt"))
# Build vendor images using vendor otatools.
- vendor_otatools_dir = common.MakeTempDir(prefix="vendor_otatools_")
- common.UnzipToDir(OPTIONS.vendor_otatools, vendor_otatools_dir)
+ # Accept either a zip file or extracted directory.
+ if os.path.isfile(OPTIONS.vendor_otatools):
+ vendor_otatools_dir = common.MakeTempDir(prefix="vendor_otatools_")
+ common.UnzipToDir(OPTIONS.vendor_otatools, vendor_otatools_dir)
+ else:
+ vendor_otatools_dir = OPTIONS.vendor_otatools
cmd = [
os.path.join(vendor_otatools_dir, "bin", "add_img_to_target_files"),
"--is_signing",
@@ -1330,6 +1400,9 @@
"--verbose",
vendor_tempdir,
]
+ if OPTIONS.rebuild_recovery:
+ cmd.insert(4, "--rebuild_recovery")
+
common.RunAndCheckOutput(cmd, verbose=True)
logger.info("Writing vendor partitions to output archive.")
@@ -1337,8 +1410,16 @@
output_zip_path, "a", compression=zipfile.ZIP_DEFLATED,
allowZip64=True) as output_zip:
for p in OPTIONS.vendor_partitions:
- path = "IMAGES/{}.img".format(p)
- common.ZipWrite(output_zip, os.path.join(vendor_tempdir, path), path)
+ img_file_path = "IMAGES/{}.img".format(p)
+ map_file_path = "IMAGES/{}.map".format(p)
+ common.ZipWrite(output_zip, os.path.join(vendor_tempdir, img_file_path), img_file_path)
+ common.ZipWrite(output_zip, os.path.join(vendor_tempdir, map_file_path), map_file_path)
+ # copy recovery patch & install.sh
+ if OPTIONS.rebuild_recovery:
+ recovery_patch_path = "VENDOR/recovery-from-boot.p"
+ recovery_sh_path = "VENDOR/bin/install-recovery.sh"
+ common.ZipWrite(output_zip, os.path.join(vendor_tempdir, recovery_patch_path), recovery_patch_path)
+ common.ZipWrite(output_zip, os.path.join(vendor_tempdir, recovery_sh_path), recovery_sh_path)
def main(argv):
@@ -1454,6 +1535,12 @@
OPTIONS.vendor_otatools = a
elif o == "--vendor_partitions":
OPTIONS.vendor_partitions = set(a.split(","))
+ elif o == '--sepolicy_key':
+ OPTIONS.sepolicy_key = a
+ elif o == '--sepolicy_cert':
+ OPTIONS.sepolicy_cert = a
+ elif o == '--fsverity_tool':
+ OPTIONS.fsverity_tool = a
elif o == "--allow_gsi_debug_sepolicy":
OPTIONS.allow_gsi_debug_sepolicy = True
else:
@@ -1508,6 +1595,9 @@
"gki_signing_extra_args=",
"vendor_partitions=",
"vendor_otatools=",
+ "sepolicy_key=",
+ "sepolicy_cert=",
+ "fsverity_tool=",
"allow_gsi_debug_sepolicy",
],
extra_option_handler=option_handler)
@@ -1530,8 +1620,9 @@
apk_keys_info, compressed_extension = common.ReadApkCerts(input_zip)
apk_keys = GetApkCerts(apk_keys_info)
- apex_keys_info = ReadApexKeysInfo(input_zip)
+ apex_keys_info, sepolicy_keys_info = ReadApexKeysInfo(input_zip)
apex_keys = GetApexKeys(apex_keys_info, apk_keys)
+ sepolicy_keys = GetSepolicyKeys(sepolicy_keys_info)
# TODO(xunchang) check for the apks inside the apex files, and abort early if
# the keys are not available.
@@ -1549,7 +1640,7 @@
ProcessTargetFiles(input_zip, output_zip, misc_info,
apk_keys, apex_keys, key_passwords,
platform_api_level, codename_to_api_level_map,
- compressed_extension)
+ compressed_extension, sepolicy_keys)
common.ZipClose(input_zip)
common.ZipClose(output_zip)
diff --git a/tools/releasetools/test_merge_target_files.py b/tools/releasetools/test_merge_target_files.py
deleted file mode 100644
index 088ebee..0000000
--- a/tools/releasetools/test_merge_target_files.py
+++ /dev/null
@@ -1,288 +0,0 @@
-#
-# Copyright (C) 2017 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 os.path
-import shutil
-
-import common
-import merge_target_files
-import test_utils
-from merge_target_files import (
- validate_config_lists, DEFAULT_FRAMEWORK_ITEM_LIST,
- DEFAULT_VENDOR_ITEM_LIST, DEFAULT_FRAMEWORK_MISC_INFO_KEYS, copy_items,
- item_list_to_partition_set, merge_package_keys_txt, compile_split_sepolicy,
- validate_merged_apex_info)
-
-
-class MergeTargetFilesTest(test_utils.ReleaseToolsTestCase):
-
- def setUp(self):
- self.testdata_dir = test_utils.get_testdata_dir()
- self.OPTIONS = merge_target_files.OPTIONS
- self.OPTIONS.framework_item_list = DEFAULT_FRAMEWORK_ITEM_LIST
- self.OPTIONS.framework_misc_info_keys = DEFAULT_FRAMEWORK_MISC_INFO_KEYS
- self.OPTIONS.vendor_item_list = DEFAULT_VENDOR_ITEM_LIST
- self.OPTIONS.framework_partition_set = set(
- ['product', 'system', 'system_ext'])
- self.OPTIONS.vendor_partition_set = set(['odm', 'vendor'])
-
- def test_copy_items_CopiesItemsMatchingPatterns(self):
-
- def createEmptyFile(path):
- if not os.path.exists(os.path.dirname(path)):
- os.makedirs(os.path.dirname(path))
- open(path, 'a').close()
- return path
-
- def createSymLink(source, dest):
- os.symlink(source, dest)
- return dest
-
- def getRelPaths(start, filepaths):
- return set(
- os.path.relpath(path=filepath, start=start) for filepath in filepaths)
-
- input_dir = common.MakeTempDir()
- output_dir = common.MakeTempDir()
- expected_copied_items = []
- actual_copied_items = []
- patterns = ['*.cpp', 'subdir/*.txt']
-
- # Create various files that we expect to get copied because they
- # match one of the patterns.
- expected_copied_items.extend([
- createEmptyFile(os.path.join(input_dir, 'a.cpp')),
- createEmptyFile(os.path.join(input_dir, 'b.cpp')),
- createEmptyFile(os.path.join(input_dir, 'subdir', 'c.txt')),
- createEmptyFile(os.path.join(input_dir, 'subdir', 'd.txt')),
- createEmptyFile(
- os.path.join(input_dir, 'subdir', 'subsubdir', 'e.txt')),
- createSymLink('a.cpp', os.path.join(input_dir, 'a_link.cpp')),
- ])
- # Create some more files that we expect to not get copied.
- createEmptyFile(os.path.join(input_dir, 'a.h'))
- createEmptyFile(os.path.join(input_dir, 'b.h'))
- createEmptyFile(os.path.join(input_dir, 'subdir', 'subsubdir', 'f.gif'))
- createSymLink('a.h', os.path.join(input_dir, 'a_link.h'))
-
- # Copy items.
- copy_items(input_dir, output_dir, patterns)
-
- # Assert the actual copied items match the ones we expected.
- for dirpath, _, filenames in os.walk(output_dir):
- actual_copied_items.extend(
- os.path.join(dirpath, filename) for filename in filenames)
- self.assertEqual(
- getRelPaths(output_dir, actual_copied_items),
- getRelPaths(input_dir, expected_copied_items))
- self.assertEqual(
- os.readlink(os.path.join(output_dir, 'a_link.cpp')), 'a.cpp')
-
- def test_validate_config_lists_ReturnsFalseIfMissingDefaultItem(self):
- self.OPTIONS.framework_item_list = list(DEFAULT_FRAMEWORK_ITEM_LIST)
- self.OPTIONS.framework_item_list.remove('SYSTEM/*')
- self.assertFalse(validate_config_lists())
-
- def test_validate_config_lists_ReturnsTrueIfDefaultItemInDifferentList(self):
- self.OPTIONS.framework_item_list = list(DEFAULT_FRAMEWORK_ITEM_LIST)
- self.OPTIONS.framework_item_list.remove('ROOT/*')
- self.OPTIONS.vendor_item_list = list(DEFAULT_VENDOR_ITEM_LIST)
- self.OPTIONS.vendor_item_list.append('ROOT/*')
- self.assertTrue(validate_config_lists())
-
- def test_validate_config_lists_ReturnsTrueIfExtraItem(self):
- self.OPTIONS.framework_item_list = list(DEFAULT_FRAMEWORK_ITEM_LIST)
- self.OPTIONS.framework_item_list.append('MY_NEW_PARTITION/*')
- self.assertTrue(validate_config_lists())
-
- def test_validate_config_lists_ReturnsFalseIfSharedExtractedPartition(self):
- self.OPTIONS.vendor_item_list = list(DEFAULT_VENDOR_ITEM_LIST)
- self.OPTIONS.vendor_item_list.append('SYSTEM/my_system_file')
- self.assertFalse(validate_config_lists())
-
- def test_validate_config_lists_ReturnsFalseIfSharedExtractedPartitionImage(
- self):
- self.OPTIONS.vendor_item_list = list(DEFAULT_VENDOR_ITEM_LIST)
- self.OPTIONS.vendor_item_list.append('IMAGES/system.img')
- self.assertFalse(validate_config_lists())
-
- def test_validate_config_lists_ReturnsFalseIfBadSystemMiscInfoKeys(self):
- for bad_key in ['dynamic_partition_list', 'super_partition_groups']:
- self.OPTIONS.framework_misc_info_keys = list(
- DEFAULT_FRAMEWORK_MISC_INFO_KEYS)
- self.OPTIONS.framework_misc_info_keys.append(bad_key)
- self.assertFalse(validate_config_lists())
-
- def test_merge_package_keys_txt_ReturnsTrueIfNoConflicts(self):
- output_meta_dir = common.MakeTempDir()
-
- framework_meta_dir = common.MakeTempDir()
- os.symlink(
- os.path.join(self.testdata_dir, 'apexkeys_framework.txt'),
- os.path.join(framework_meta_dir, 'apexkeys.txt'))
-
- vendor_meta_dir = common.MakeTempDir()
- os.symlink(
- os.path.join(self.testdata_dir, 'apexkeys_vendor.txt'),
- os.path.join(vendor_meta_dir, 'apexkeys.txt'))
-
- merge_package_keys_txt(framework_meta_dir, vendor_meta_dir, output_meta_dir,
- 'apexkeys.txt')
-
- merged_entries = []
- merged_path = os.path.join(self.testdata_dir, 'apexkeys_merge.txt')
-
- with open(merged_path) as f:
- merged_entries = f.read().split('\n')
-
- output_entries = []
- output_path = os.path.join(output_meta_dir, 'apexkeys.txt')
-
- with open(output_path) as f:
- output_entries = f.read().split('\n')
-
- return self.assertEqual(merged_entries, output_entries)
-
- def test_process_apex_keys_apk_certs_ReturnsFalseIfConflictsPresent(self):
- output_meta_dir = common.MakeTempDir()
-
- framework_meta_dir = common.MakeTempDir()
- os.symlink(
- os.path.join(self.testdata_dir, 'apexkeys_framework.txt'),
- os.path.join(framework_meta_dir, 'apexkeys.txt'))
-
- conflict_meta_dir = common.MakeTempDir()
- os.symlink(
- os.path.join(self.testdata_dir, 'apexkeys_framework_conflict.txt'),
- os.path.join(conflict_meta_dir, 'apexkeys.txt'))
-
- self.assertRaises(ValueError, merge_package_keys_txt, framework_meta_dir,
- conflict_meta_dir, output_meta_dir, 'apexkeys.txt')
-
- def test_process_apex_keys_apk_certs_HandlesApkCertsSyntax(self):
- output_meta_dir = common.MakeTempDir()
-
- framework_meta_dir = common.MakeTempDir()
- os.symlink(
- os.path.join(self.testdata_dir, 'apkcerts_framework.txt'),
- os.path.join(framework_meta_dir, 'apkcerts.txt'))
-
- vendor_meta_dir = common.MakeTempDir()
- os.symlink(
- os.path.join(self.testdata_dir, 'apkcerts_vendor.txt'),
- os.path.join(vendor_meta_dir, 'apkcerts.txt'))
-
- merge_package_keys_txt(framework_meta_dir, vendor_meta_dir, output_meta_dir,
- 'apkcerts.txt')
-
- merged_entries = []
- merged_path = os.path.join(self.testdata_dir, 'apkcerts_merge.txt')
-
- with open(merged_path) as f:
- merged_entries = f.read().split('\n')
-
- output_entries = []
- output_path = os.path.join(output_meta_dir, 'apkcerts.txt')
-
- with open(output_path) as f:
- output_entries = f.read().split('\n')
-
- return self.assertEqual(merged_entries, output_entries)
-
- def test_item_list_to_partition_set(self):
- item_list = [
- 'META/apexkeys.txt',
- 'META/apkcerts.txt',
- 'META/filesystem_config.txt',
- 'PRODUCT/*',
- 'SYSTEM/*',
- 'SYSTEM_EXT/*',
- ]
- partition_set = item_list_to_partition_set(item_list)
- self.assertEqual(set(['product', 'system', 'system_ext']), partition_set)
-
- def test_compile_split_sepolicy(self):
- product_out_dir = common.MakeTempDir()
-
- def write_temp_file(path, data=''):
- full_path = os.path.join(product_out_dir, path)
- if not os.path.exists(os.path.dirname(full_path)):
- os.makedirs(os.path.dirname(full_path))
- with open(full_path, 'w') as f:
- f.write(data)
-
- write_temp_file(
- 'system/etc/vintf/compatibility_matrix.device.xml', """
- <compatibility-matrix>
- <sepolicy>
- <kernel-sepolicy-version>30</kernel-sepolicy-version>
- </sepolicy>
- </compatibility-matrix>""")
- write_temp_file('vendor/etc/selinux/plat_sepolicy_vers.txt', '30.0')
-
- write_temp_file('system/etc/selinux/plat_sepolicy.cil')
- write_temp_file('system/etc/selinux/mapping/30.0.cil')
- write_temp_file('product/etc/selinux/mapping/30.0.cil')
- write_temp_file('vendor/etc/selinux/vendor_sepolicy.cil')
- write_temp_file('vendor/etc/selinux/plat_pub_versioned.cil')
-
- cmd = compile_split_sepolicy(product_out_dir, {
- 'system': 'system',
- 'product': 'product',
- 'vendor': 'vendor',
- })
- self.assertEqual(' '.join(cmd),
- ('secilc -m -M true -G -N -c 30 '
- '-o {OTP}/META/combined_sepolicy -f /dev/null '
- '{OTP}/system/etc/selinux/plat_sepolicy.cil '
- '{OTP}/system/etc/selinux/mapping/30.0.cil '
- '{OTP}/vendor/etc/selinux/vendor_sepolicy.cil '
- '{OTP}/vendor/etc/selinux/plat_pub_versioned.cil '
- '{OTP}/product/etc/selinux/mapping/30.0.cil').format(
- OTP=product_out_dir))
-
- def _copy_apex(self, source, output_dir, partition):
- shutil.copy(
- source,
- os.path.join(output_dir, partition, 'apex', os.path.basename(source)))
-
- @test_utils.SkipIfExternalToolsUnavailable()
- def test_validate_merged_apex_info(self):
- output_dir = common.MakeTempDir()
- os.makedirs(os.path.join(output_dir, 'SYSTEM/apex'))
- os.makedirs(os.path.join(output_dir, 'VENDOR/apex'))
-
- self._copy_apex(
- os.path.join(self.testdata_dir, 'has_apk.apex'), output_dir, 'SYSTEM')
- self._copy_apex(
- os.path.join(test_utils.get_current_dir(),
- 'com.android.apex.compressed.v1.capex'), output_dir,
- 'VENDOR')
- validate_merged_apex_info(output_dir, ('system', 'vendor'))
-
- @test_utils.SkipIfExternalToolsUnavailable()
- def test_validate_merged_apex_info_RaisesOnPackageInMultiplePartitions(self):
- output_dir = common.MakeTempDir()
- os.makedirs(os.path.join(output_dir, 'SYSTEM/apex'))
- os.makedirs(os.path.join(output_dir, 'VENDOR/apex'))
-
- same_apex_package = os.path.join(self.testdata_dir, 'has_apk.apex')
- self._copy_apex(same_apex_package, output_dir, 'SYSTEM')
- self._copy_apex(same_apex_package, output_dir, 'VENDOR')
- self.assertRaisesRegexp(
- common.ExternalError,
- 'Duplicate APEX packages found in multiple partitions: com.android.wifi',
- validate_merged_apex_info, output_dir, ('system', 'vendor'))
diff --git a/tools/releasetools/test_sign_target_files_apks.py b/tools/releasetools/test_sign_target_files_apks.py
index 0f13add..144a3cd 100644
--- a/tools/releasetools/test_sign_target_files_apks.py
+++ b/tools/releasetools/test_sign_target_files_apks.py
@@ -476,7 +476,7 @@
target_files_zip.writestr('META/apexkeys.txt', self.APEX_KEYS_TXT)
with zipfile.ZipFile(target_files, allowZip64=True) as target_files_zip:
- keys_info = ReadApexKeysInfo(target_files_zip)
+ keys_info, sepolicy_keys_info = ReadApexKeysInfo(target_files_zip)
self.assertEqual({
'apex.apexd_test.apex': (
@@ -486,6 +486,7 @@
'system/apex/apexd/apexd_testdata/com.android.apex.test_package_2.pem',
'build/make/target/product/security/testkey', None),
}, keys_info)
+ self.assertEqual({}, sepolicy_keys_info)
def test_ReadApexKeysInfo_mismatchingContainerKeys(self):
# Mismatching payload public / private keys.
@@ -515,7 +516,7 @@
target_files_zip.writestr('META/apexkeys.txt', apex_keys)
with zipfile.ZipFile(target_files, allowZip64=True) as target_files_zip:
- keys_info = ReadApexKeysInfo(target_files_zip)
+ keys_info, sepolicy_keys_info = ReadApexKeysInfo(target_files_zip)
self.assertEqual({
'apex.apexd_test.apex': (
@@ -525,6 +526,7 @@
'system/apex/apexd/apexd_testdata/com.android.apex.test_package_2.pem',
'build/make/target/product/security/testkey', None),
}, keys_info)
+ self.assertEqual({}, sepolicy_keys_info)
def test_ReadApexKeysInfo_missingPayloadPublicKey(self):
# Invalid lines will be skipped.
@@ -538,7 +540,7 @@
target_files_zip.writestr('META/apexkeys.txt', apex_keys)
with zipfile.ZipFile(target_files, allowZip64=True) as target_files_zip:
- keys_info = ReadApexKeysInfo(target_files_zip)
+ keys_info, sepolicy_keys_info = ReadApexKeysInfo(target_files_zip)
self.assertEqual({
'apex.apexd_test.apex': (
@@ -548,6 +550,7 @@
'system/apex/apexd/apexd_testdata/com.android.apex.test_package_2.pem',
'build/make/target/product/security/testkey', None),
}, keys_info)
+ self.assertEqual({}, sepolicy_keys_info)
def test_ReadApexKeysInfo_presignedKeys(self):
apex_keys = self.APEX_KEYS_TXT + (
@@ -561,7 +564,7 @@
target_files_zip.writestr('META/apexkeys.txt', apex_keys)
with zipfile.ZipFile(target_files, allowZip64=True) as target_files_zip:
- keys_info = ReadApexKeysInfo(target_files_zip)
+ keys_info, sepolicy_keys_info = ReadApexKeysInfo(target_files_zip)
self.assertEqual({
'apex.apexd_test.apex': (
@@ -571,6 +574,7 @@
'system/apex/apexd/apexd_testdata/com.android.apex.test_package_2.pem',
'build/make/target/product/security/testkey', None),
}, keys_info)
+ self.assertEqual({}, sepolicy_keys_info)
def test_ReadApexKeysInfo_presignedKeys(self):
apex_keys = self.APEX_KEYS_TXT + (
@@ -584,7 +588,7 @@
target_files_zip.writestr('META/apexkeys.txt', apex_keys)
with zipfile.ZipFile(target_files, allowZip64=True) as target_files_zip:
- keys_info = ReadApexKeysInfo(target_files_zip)
+ keys_info, sepolicy_keys_info = ReadApexKeysInfo(target_files_zip)
self.assertEqual({
'apex.apexd_test.apex': (
@@ -594,6 +598,72 @@
'system/apex/apexd/apexd_testdata/com.android.apex.test_package_2.pem',
'build/make/target/product/security/testkey', None),
}, keys_info)
+ self.assertEqual({}, sepolicy_keys_info)
+
+ def test_ReadApexKeysInfo_withSepolicyKeys(self):
+ apex_keys = self.APEX_KEYS_TXT + (
+ 'name="sepolicy.apex" '
+ 'public_key="system/apex/apexd/apexd_testdata/com.android.apex.test_package_2.avbpubkey" '
+ 'private_key="system/apex/apexd/apexd_testdata/com.android.apex.test_package_2.pem" '
+ 'container_certificate="build/make/target/product/security/testkey.x509.pem" '
+ 'container_private_key="build/make/target/product/security/testkey.pk8" '
+ 'sepolicy_key="build/make/target/product/security/testkey.key" '
+ 'sepolicy_certificate="build/make/target/product/security/testkey.x509.pem" '
+ 'fsverity_tool="fsverity"')
+ target_files = common.MakeTempFile(suffix='.zip')
+ with zipfile.ZipFile(target_files, 'w', allowZip64=True) as target_files_zip:
+ target_files_zip.writestr('META/apexkeys.txt', apex_keys)
+
+ with zipfile.ZipFile(target_files, allowZip64=True) as target_files_zip:
+ keys_info, sepolicy_keys_info = ReadApexKeysInfo(target_files_zip)
+
+ self.assertEqual({
+ 'apex.apexd_test.apex': (
+ 'system/apex/apexd/apexd_testdata/com.android.apex.test_package.pem',
+ 'build/make/target/product/security/testkey', None),
+ 'apex.apexd_test_different_app.apex': (
+ 'system/apex/apexd/apexd_testdata/com.android.apex.test_package_2.pem',
+ 'build/make/target/product/security/testkey', None),
+ 'sepolicy.apex': (
+ 'system/apex/apexd/apexd_testdata/com.android.apex.test_package_2.pem',
+ 'build/make/target/product/security/testkey', None),
+ }, keys_info)
+ self.assertEqual({'sepolicy.apex': (
+ 'build/make/target/product/security/testkey.key',
+ 'build/make/target/product/security/testkey.x509.pem',
+ 'fsverity'),
+ }, sepolicy_keys_info)
+
+ def test_ReadApexKeysInfo_withSepolicyApex(self):
+ apex_keys = self.APEX_KEYS_TXT + (
+ 'name="sepolicy.apex" '
+ 'public_key="system/apex/apexd/apexd_testdata/com.android.apex.test_package_2.avbpubkey" '
+ 'private_key="system/apex/apexd/apexd_testdata/com.android.apex.test_package_2.pem" '
+ 'container_certificate="build/make/target/product/security/testkey.x509.pem" '
+ 'container_private_key="build/make/target/product/security/testkey.pk8" ')
+ target_files = common.MakeTempFile(suffix='.zip')
+ with zipfile.ZipFile(target_files, 'w', allowZip64=True) as target_files_zip:
+ target_files_zip.writestr('META/apexkeys.txt', apex_keys)
+
+ with zipfile.ZipFile(target_files, allowZip64=True) as target_files_zip:
+ keys_info, sepolicy_keys_info = ReadApexKeysInfo(target_files_zip)
+
+ self.assertEqual({
+ 'apex.apexd_test.apex': (
+ 'system/apex/apexd/apexd_testdata/com.android.apex.test_package.pem',
+ 'build/make/target/product/security/testkey', None),
+ 'apex.apexd_test_different_app.apex': (
+ 'system/apex/apexd/apexd_testdata/com.android.apex.test_package_2.pem',
+ 'build/make/target/product/security/testkey', None),
+ 'sepolicy.apex': (
+ 'system/apex/apexd/apexd_testdata/com.android.apex.test_package_2.pem',
+ 'build/make/target/product/security/testkey', None),
+ }, keys_info)
+ self.assertEqual({'sepolicy.apex': (
+ None,
+ None,
+ None),
+ }, sepolicy_keys_info)
def test_ReplaceGkiSigningKey(self):
common.OPTIONS.gki_signing_key = 'release_gki_key'
diff --git a/tools/releasetools/test_utils.py b/tools/releasetools/test_utils.py
index 808b392..e30d2b9 100755
--- a/tools/releasetools/test_utils.py
+++ b/tools/releasetools/test_utils.py
@@ -33,6 +33,8 @@
# Some test runner doesn't like outputs from stderr.
logging.basicConfig(stream=sys.stdout)
+ALLOWED_TEST_SUBDIRS = ('merge',)
+
# Use ANDROID_BUILD_TOP as an indicator to tell if the needed tools (e.g.
# avbtool, mke2fs) are available while running the tests, unless
# FORCE_RUN_RELEASETOOLS is set to '1'. Not having the required vars means we
@@ -244,9 +246,12 @@
# os walk and load them manually.
test_modules = []
base_path = os.path.dirname(os.path.realpath(__file__))
+ test_dirs = [base_path] + [
+ os.path.join(base_path, subdir) for subdir in ALLOWED_TEST_SUBDIRS
+ ]
for dirpath, _, files in os.walk(base_path):
for fn in files:
- if dirpath == base_path and re.match('test_.*\\.py$', fn):
+ if dirpath in test_dirs and re.match('test_.*\\.py$', fn):
test_modules.append(fn[:-3])
test_suite = unittest.TestLoader().loadTestsFromNames(test_modules)
diff --git a/tools/releasetools/validate_target_files.py b/tools/releasetools/validate_target_files.py
index 282dc99..beb9e75 100755
--- a/tools/releasetools/validate_target_files.py
+++ b/tools/releasetools/validate_target_files.py
@@ -131,8 +131,10 @@
logging.warning('Skipped due to target using non-sparse images')
return
- # Verify IMAGES/system.img.
- CheckAllFiles('system')
+ # Verify IMAGES/system.img if applicable.
+ # Some targets, e.g., gki_arm64, gki_x86_64, etc., are system.img-less.
+ if 'IMAGES/system.img' in input_zip.namelist():
+ CheckAllFiles('system')
# Verify IMAGES/vendor.img if applicable.
if 'VENDOR/' in input_zip.namelist():
@@ -259,9 +261,6 @@
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'
@@ -398,7 +397,7 @@
verity_key_mincrypt, stdoutdata.rstrip())
# Handle the case of Verified Boot 2.0 (AVB).
- if info_dict.get("avb_enable") == "true":
+ if info_dict.get("avb_building_vbmeta_image") == "true":
logging.info('Verifying Verified Boot 2.0 (AVB) images...')
key = options['verity_key']