Merge changes from topic "no_hidl_support" into main
* changes:
Add symlink to hwservicemanager
Remove hwservicemanager and hidl allocator.
diff --git a/Changes.md b/Changes.md
index fc6701d..6836528 100644
--- a/Changes.md
+++ b/Changes.md
@@ -10,8 +10,9 @@
build team via email android-building@googlegroups.com (external) for any
questions, or see [go/soong](http://go/soong) (internal).
-To omit the validation, `BUILD_BROKEN_PLUGIN_VALIDATION` expects a list of
-plugins to omit from the validation.
+To omit the validation, `BUILD_BROKEN_PLUGIN_VALIDATION` expects a
+space-separated list of plugins to omit from the validation. This must be set
+within a product configuration .mk file, board config .mk file, or buildspec.mk.
## Python 2 to 3 migration
diff --git a/core/Makefile b/core/Makefile
index 397b07d..7a6ffd9 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -16,53 +16,93 @@
ODM_DLKM_NOTICE_DEPS :=
SYSTEM_DLKM_NOTICE_DEPS :=
-# -----------------------------------------------------------------
-# Release Config Flags
-# Create a summary file of build flags for each partition
-# $(1): build flags json file
-# $(2): flag names
-define generate-partition-build-flag-file
-$(eval $(strip $(1)): PRIVATE_OUT := $(strip $(1)))
-$(eval $(strip $(1)): PRIVATE_FLAG_NAMES := $(strip $(2)))
-$(strip $(1)):
- mkdir -p $$(dir $$(PRIVATE_OUT))
- echo '{' > $$(PRIVATE_OUT)
- echo '"flags": [' >> $$(PRIVATE_OUT)
- $$(foreach flag, $$(PRIVATE_FLAG_NAMES), \
- ( \
- printf ' { "name": "%s", "value": "%s", ' \
- '$$(flag)' \
- '$$(_ALL_RELEASE_FLAGS.$$(flag).VALUE)' \
- ; \
- printf '"set": "%s", "default": "%s", "declared": "%s" }' \
- '$$(_ALL_RELEASE_FLAGS.$$(flag).SET_IN)' \
- '$$(_ALL_RELEASE_FLAGS.$$(flag).DEFAULT)' \
- '$$(_ALL_RELEASE_FLAGS.$$(flag).DECLARED_IN)' \
- ; \
- printf '$$(if $$(filter $$(lastword $$(PRIVATE_FLAG_NAMES)),$$(flag)),,$$(comma))\n' ; \
- ) >> $$(PRIVATE_OUT) \
- )
- echo "]" >> $$(PRIVATE_OUT)
- echo "}" >> $$(PRIVATE_OUT)
+# IMAGES_TO_BUILD is a list of the partition .img files that will be created.
+IMAGES_TO_BUILD:=
+ifneq ($(BUILDING_BOOT_IMAGE),)
+ IMAGES_TO_BUILD += boot
+endif
+ifneq ($(BUILDING_CACHE_IMAGE),)
+ IMAGES_TO_BUILD += cache
+endif
+ifneq ($(BUILDING_DEBUG_BOOT_IMAGE),)
+ IMAGES_TO_BUILD += debug_boot
+endif
+ifneq ($(BUILDING_DEBUG_VENDOR_BOOT_IMAGE),)
+ IMAGES_TO_BUILD += debug_vendor_boot
+endif
+ifneq ($(BUILDING_INIT_BOOT_IMAGE),)
+ IMAGES_TO_BUILD += init_boot
+endif
+ifneq ($(BUILDING_ODM_DLKM_IMAGE),)
+ IMAGES_TO_BUILD += odm_dlkm
+endif
+ifneq ($(BUILDING_ODM_IMAGE),)
+ IMAGES_TO_BUILD += odm
+endif
+ifneq ($(BUILDING_PRODUCT_IMAGE),)
+ IMAGES_TO_BUILD += product
+endif
+ifneq ($(BUILDING_RAMDISK_IMAGE),)
+ IMAGES_TO_BUILD += ramdisk
+endif
+ifneq ($(BUILDING_RECOVERY_IMAGE),)
+ IMAGES_TO_BUILD += recovery
+endif
+ifneq ($(BUILDING_SUPER_EMPTY_IMAGE),)
+ IMAGES_TO_BUILD += super_empty
+endif
+ifneq ($(BUILDING_SYSTEM_DLKM_IMAGE),)
+ IMAGES_TO_BUILD += system_dlkm
+endif
+ifneq ($(BUILDING_SYSTEM_EXT_IMAGE),)
+ IMAGES_TO_BUILD += system_ext
+endif
+ifneq ($(BUILDING_SYSTEM_IMAGE),)
+ IMAGES_TO_BUILD += system
+endif
+ifneq ($(BUILDING_SYSTEM_OTHER_IMAGE),)
+ IMAGES_TO_BUILD += system_other
+endif
+ifneq ($(BUILDING_USERDATA_IMAGE),)
+ IMAGES_TO_BUILD += userdata
+endif
+ifneq ($(BUILDING_VBMETA_IMAGE),)
+ IMAGES_TO_BUILD += vbmeta
+endif
+ifneq ($(BUILDING_VENDOR_BOOT_IMAGE),)
+ IMAGES_TO_BUILD += vendor_boot
+endif
+ifneq ($(BUILDING_VENDOR_DLKM_IMAGE),)
+ IMAGES_TO_BUILD += vendor_dlkm
+endif
+ifneq ($(BUILDING_VENDOR_IMAGE),)
+ IMAGES_TO_BUILD += vendor
+endif
+ifneq ($(BUILDING_VENDOR_KERNEL_BOOT_IMAGE),)
+ IMAGES_TO_BUILD += vendor_kernel_boot
+endif
+
+
+###########################################################
+# Get the module names suitable for ALL_MODULES.* variables that are installed
+# for a given partition
+#
+# $(1): Partition
+###########################################################
+define register-names-for-partition
+$(sort $(foreach m,$(product_MODULES),\
+ $(if $(filter $(PRODUCT_OUT)/$(strip $(1))/%, $(ALL_MODULES.$(m).INSTALLED)), \
+ $(m)
+ ) \
+))
endef
-_FLAG_PARTITIONS := product system system_ext vendor
-$(foreach partition, $(_FLAG_PARTITIONS), \
- $(eval BUILD_FLAG_SUMMARIES.$(partition) \
- := $(TARGET_OUT_FLAGS)/$(partition)/etc/build_flags.json) \
- $(eval $(call generate-partition-build-flag-file, \
- $(BUILD_FLAG_SUMMARIES.$(partition)), \
- $(_ALL_RELEASE_FLAGS.PARTITIONS.$(partition)) \
- ) \
- ) \
-)
+# Release & Aconfig Flags
+# -----------------------------------------------------------------
+include $(BUILD_SYSTEM)/packaging/flags.mk
-# TODO: Remove
-.PHONY: flag-files
-flag-files: $(foreach partition, $(_FLAG_PARTITIONS), \
- $(TARGET_OUT_FLAGS)/$(partition)/etc/build_flags.json)
# -----------------------------------------------------------------
# Define rules to copy PRODUCT_COPY_FILES defined by the product.
@@ -323,6 +363,10 @@
)
INTERNAL_VENDOR_RAMDISK_FRAGMENTS += $(BOARD_VENDOR_RAMDISK_FRAGMENTS)
+ifneq ($(BOARD_KERNEL_MODULES_16K),)
+INTERNAL_VENDOR_RAMDISK_FRAGMENTS += 16K
+endif
+
# Strip the list in case of any whitespace.
INTERNAL_VENDOR_RAMDISK_FRAGMENTS := \
$(strip $(INTERNAL_VENDOR_RAMDISK_FRAGMENTS))
@@ -412,7 +456,7 @@
unzip -qoDD -d $$(PRIVATE_MODULE_DIR) $$(PRIVATE_MODULE_ARCHIVE); \
mkdir -p $$(PRIVATE_OUTPUT_DIR)/lib; \
cp -r $(3)/$(DEPMOD_STAGING_SUBDIR)/$(2)/lib/modules $$(PRIVATE_OUTPUT_DIR)/lib/; \
- find $$(PRIVATE_MODULE_DIR) -type f -name *.ko | xargs basename -a > $$(PRIVATE_LOAD_FILE); \
+ find $$(PRIVATE_MODULE_DIR) -type f -name '*.ko' | xargs basename -a > $$(PRIVATE_LOAD_FILE); \
)
$(if $(1),\
cp $$(PRIVATE_MODULES) $$(PRIVATE_MODULE_DIR)/; \
@@ -1010,16 +1054,32 @@
BUILT_RAMDISK_16K_TARGET := $(PRODUCT_OUT)/ramdisk_16k.img
RAMDISK_16K_STAGING_DIR := $(call intermediates-dir-for,PACKAGING,depmod_ramdisk_16k)
-$(BUILT_RAMDISK_16K_TARGET): $(DEPMOD) $(MKBOOTFS)
-$(BUILT_RAMDISK_16K_TARGET): $(call copy-many-files,$(foreach file,$(BOARD_KERNEL_MODULES_16K),$(file):$(RAMDISK_16K_STAGING_DIR)/lib/modules/0.0/$(notdir $(file))))
+$(foreach \
+ file,\
+ $(BOARD_KERNEL_MODULES_16K),\
+ $(eval \
+ $(call copy-and-strip-kernel-module,\
+ $(file),\
+ $(RAMDISK_16K_STAGING_DIR)/lib/modules/0.0/$(notdir $(file)) \
+ ) \
+ ) \
+)
+
+BOARD_VENDOR_RAMDISK_FRAGMENT.16K.PREBUILT := $(BUILT_RAMDISK_16K_TARGET)
+
+$(BUILT_RAMDISK_16K_TARGET): $(DEPMOD) $(MKBOOTFS) $(EXTRACT_KERNEL) $(COMPRESSION_COMMAND_DEPS)
+$(BUILT_RAMDISK_16K_TARGET): $(foreach file,$(BOARD_KERNEL_MODULES_16K),$(RAMDISK_16K_STAGING_DIR)/lib/modules/0.0/$(notdir $(file)))
$(DEPMOD) -b $(RAMDISK_16K_STAGING_DIR) 0.0
for MODULE in $(BOARD_KERNEL_MODULES_16K); do \
basename $$MODULE >> $(RAMDISK_16K_STAGING_DIR)/lib/modules/0.0/modules.load ; \
done;
- mkdir -p $(TARGET_OUT_RAMDISK_16K)/lib
rm -rf $(TARGET_OUT_RAMDISK_16K)/lib/modules
- cp -r $(RAMDISK_16K_STAGING_DIR)/lib/modules/0.0 $(TARGET_OUT_RAMDISK_16K)/lib/modules
- $(MKBOOTFS) $(TARGET_OUT_RAMDISK_16K) > $@
+ mkdir -p $(TARGET_OUT_RAMDISK_16K)/lib/modules
+ KERNEL_RELEASE=`$(EXTRACT_KERNEL) --tools lz4:$(LZ4) --input $(BOARD_KERNEL_PATH_16K) --output-release` ;\
+ IS_16K_KERNEL=`$(EXTRACT_KERNEL) --tools lz4:$(LZ4) --input $(BOARD_KERNEL_PATH_16K) --output-config` ;\
+ if [[ "$$IS_16K_KERNEL" == *"CONFIG_ARM64_16K_PAGES=y"* ]]; then SUFFIX=_16k; fi ;\
+ cp -r $(RAMDISK_16K_STAGING_DIR)/lib/modules/0.0 $(TARGET_OUT_RAMDISK_16K)/lib/modules/$$KERNEL_RELEASE$$SUFFIX
+ $(MKBOOTFS) $(TARGET_OUT_RAMDISK_16K) | $(COMPRESSION_COMMAND) > $@
# Builds a ramdisk using modules defined in BOARD_KERNEL_MODULES_16K
ramdisk_16k: $(BUILT_RAMDISK_16K_TARGET)
@@ -1036,6 +1096,28 @@
kernel_16k: $(BUILT_KERNEL_16K_TARGET)
.PHONY: kernel_16k
+BUILT_BOOTIMAGE_16K_TARGET := $(PRODUCT_OUT)/boot_16k.img
+
+$(BUILT_BOOTIMAGE_16K_TARGET): $(MKBOOTIMG) $(AVBTOOL) $(INTERNAL_BOOTIMAGE_FILES) $(BOARD_AVB_BOOT_KEY_PATH) $(INTERNAL_GKI_CERTIFICATE_DEPS)
+ $(call pretty,"Target boot 16k image: $@")
+ $(call build_boot_from_kernel_avb_enabled,$@,$(BUILT_KERNEL_16K_TARGET))
+
+
+bootimage_16k: $(BUILT_BOOTIMAGE_16K_TARGET)
+.PHONY: bootimage_16k
+
+BUILT_BOOT_OTA_PACKAGE_16K := $(PRODUCT_OUT)/boot_ota_16k.zip
+$(BUILT_BOOT_OTA_PACKAGE_16K): $(OTA_FROM_RAW_IMG) $(BUILT_BOOTIMAGE_16K_TARGET) $(DEFAULT_SYSTEM_DEV_CERTIFICATE).pk8
+ $(OTA_FROM_RAW_IMG) --package_key $(DEFAULT_SYSTEM_DEV_CERTIFICATE) \
+ --max_timestamp `cat $(BUILD_DATETIME_FILE)` \
+ --path $(HOST_OUT) \
+ --partition_name boot \
+ --output $@ \
+ $(BUILT_BOOTIMAGE_16K_TARGET)
+
+boototapackage_16k: $(BUILT_BOOT_OTA_PACKAGE_16K)
+.PHONY: boototapackage_16k
+
endif
@@ -1045,8 +1127,8 @@
COMPRESSION_COMMAND := $(LZ4) -l -12 --favor-decSpeed
RAMDISK_EXT := .lz4
else
-COMPRESSION_COMMAND_DEPS := $(MINIGZIP)
-COMPRESSION_COMMAND := $(MINIGZIP)
+COMPRESSION_COMMAND_DEPS := $(GZIP)
+COMPRESSION_COMMAND := $(GZIP)
RAMDISK_EXT := .gz
endif
@@ -1131,6 +1213,29 @@
$(if $(1),--partition_size $(1),--dynamic_partition_size)
endef
+# $1: output boot image target
+# $2: input path to kernel binary
+define build_boot_from_kernel_avb_enabled
+ $(eval kernel := $(2))
+ $(MKBOOTIMG) --kernel $(kernel) $(INTERNAL_BOOTIMAGE_ARGS) $(INTERNAL_MKBOOTIMG_VERSION_ARGS) $(BOARD_MKBOOTIMG_ARGS) --output $(1)
+ $(if $(BOARD_GKI_SIGNING_KEY_PATH), \
+ $(eval boot_signature := $(call intermediates-dir-for,PACKAGING,generic_boot)/$(notdir $(1)).boot_signature) \
+ $(eval kernel_signature := $(call intermediates-dir-for,PACKAGING,generic_kernel)/$(notdir $(kernel)).boot_signature) \
+ $(call generate_generic_boot_image_certificate,$(1),$(boot_signature),boot,$(BOARD_AVB_BOOT_ADD_HASH_FOOTER_ARGS)) $(newline) \
+ $(call generate_generic_boot_image_certificate,$(kernel),$(kernel_signature),generic_kernel,$(BOARD_AVB_BOOT_ADD_HASH_FOOTER_ARGS)) $(newline) \
+ cat $(kernel_signature) >> $(boot_signature) $(newline) \
+ $(call assert-max-image-size,$(boot_signature),16 << 10) $(newline) \
+ truncate -s $$(( 16 << 10 )) $(boot_signature) $(newline) \
+ cat "$(boot_signature)" >> $(1))
+ $(call assert-max-image-size,$(1),$(call get-hash-image-max-size,$(call get-bootimage-partition-size,$(1),boot)))
+ $(AVBTOOL) add_hash_footer \
+ --image $(1) \
+ $(call get-partition-size-argument,$(call get-bootimage-partition-size,$(1),boot)) \
+ --partition_name boot $(INTERNAL_AVB_BOOT_SIGNING_ARGS) \
+ $(BOARD_AVB_BOOT_ADD_HASH_FOOTER_ARGS)
+endef
+
+
ifndef BOARD_PREBUILT_BOOTIMAGE
ifneq ($(strip $(TARGET_NO_KERNEL)),true)
@@ -1235,22 +1340,7 @@
# $1: boot image target
define build_boot_board_avb_enabled
$(eval kernel := $(call bootimage-to-kernel,$(1)))
- $(MKBOOTIMG) --kernel $(kernel) $(INTERNAL_BOOTIMAGE_ARGS) $(INTERNAL_MKBOOTIMG_VERSION_ARGS) $(BOARD_MKBOOTIMG_ARGS) --output $(1)
- $(if $(BOARD_GKI_SIGNING_KEY_PATH), \
- $(eval boot_signature := $(call intermediates-dir-for,PACKAGING,generic_boot)/$(notdir $(1)).boot_signature) \
- $(eval kernel_signature := $(call intermediates-dir-for,PACKAGING,generic_kernel)/$(notdir $(kernel)).boot_signature) \
- $(call generate_generic_boot_image_certificate,$(1),$(boot_signature),boot,$(BOARD_AVB_BOOT_ADD_HASH_FOOTER_ARGS)) $(newline) \
- $(call generate_generic_boot_image_certificate,$(kernel),$(kernel_signature),generic_kernel,$(BOARD_AVB_BOOT_ADD_HASH_FOOTER_ARGS)) $(newline) \
- cat $(kernel_signature) >> $(boot_signature) $(newline) \
- $(call assert-max-image-size,$(boot_signature),16 << 10) $(newline) \
- truncate -s $$(( 16 << 10 )) $(boot_signature) $(newline) \
- cat "$(boot_signature)" >> $(1))
- $(call assert-max-image-size,$(1),$(call get-hash-image-max-size,$(call get-bootimage-partition-size,$(1),boot)))
- $(AVBTOOL) add_hash_footer \
- --image $(1) \
- $(call get-partition-size-argument,$(call get-bootimage-partition-size,$(1),boot)) \
- --partition_name boot $(INTERNAL_AVB_BOOT_SIGNING_ARGS) \
- $(BOARD_AVB_BOOT_ADD_HASH_FOOTER_ARGS)
+ $(call build_boot_from_kernel_avb_enabled,$(1),$(kernel))
endef
$(INSTALLED_BOOTIMAGE_TARGET): $(MKBOOTIMG) $(AVBTOOL) $(INTERNAL_BOOTIMAGE_FILES) $(BOARD_AVB_BOOT_KEY_PATH) $(INTERNAL_GKI_CERTIFICATE_DEPS)
@@ -2170,6 +2260,8 @@
$(hide) echo "root_dir=$(TARGET_ROOT_OUT)" >> $(1)
$(if $(filter true,$(PRODUCT_USE_DYNAMIC_PARTITION_SIZE)),\
$(hide) echo "use_dynamic_partition_size=true" >> $(1))
+$(if $(COPY_IMAGES_FOR_TARGET_FILES_ZIP),\
+ $(hide) echo "use_fixed_timestamp=true" >> $(1))
$(if $(3),$(hide) $(foreach kv,$(3),echo "$(kv)" >> $(1);))
endef
@@ -2471,7 +2563,11 @@
TARGET_RECOVERY_UI_PROGRESS_BAR_BASELINE:progress_bar_baseline \
TARGET_RECOVERY_UI_TOUCH_LOW_THRESHOLD:touch_low_threshold \
TARGET_RECOVERY_UI_TOUCH_HIGH_THRESHOLD:touch_high_threshold \
- TARGET_RECOVERY_UI_VR_STEREO_OFFSET:vr_stereo_offset
+ TARGET_RECOVERY_UI_VR_STEREO_OFFSET:vr_stereo_offset \
+ TARGET_RECOVERY_UI_BRIGHTNESS_FILE:brightness_file \
+ TARGET_RECOVERY_UI_MAX_BRIGHTNESS_FILE:max_brightness_file \
+ TARGET_RECOVERY_UI_BRIGHTNESS_NORMAL:brightness_normal_percent \
+ TARGET_RECOVERY_UI_BRIGHTNESS_DIMMED:brightness_dimmed_percent
# Parses the given list of build variables and writes their values as build properties if defined.
# For example, if a target defines `TARGET_RECOVERY_UI_MARGIN_HEIGHT := 100`,
@@ -3315,6 +3411,10 @@
$(call intermediates-dir-for,PACKAGING,systemimage)
BUILT_SYSTEMIMAGE := $(systemimage_intermediates)/system.img
+# Used by the bazel sandwich to request the staging dir be built
+$(systemimage_intermediates)/staging_dir.stamp: $(FULL_SYSTEMIMAGE_DEPS)
+ touch $@
+
# $(1): output file
define build-systemimage-target
@echo "Target system fs image: $(1)"
@@ -3467,45 +3567,6 @@
tar cfj $(ASAN_IN_SYSTEM_INSTALLED) $(ASAN_SYSTEM_INSTALL_OPTIONS) -C $(TARGET_OUT_DATA)/.. $(ASAN_OUT_DIRS_FOR_SYSTEM_INSTALL) >/dev/null
# -----------------------------------------------------------------
-# partition table image
-ifdef BOARD_BPT_INPUT_FILES
-
-BUILT_BPTIMAGE_TARGET := $(PRODUCT_OUT)/partition-table.img
-BUILT_BPTJSON_TARGET := $(PRODUCT_OUT)/partition-table.bpt
-
-INTERNAL_BVBTOOL_MAKE_TABLE_ARGS := \
- --output_gpt $(BUILT_BPTIMAGE_TARGET) \
- --output_json $(BUILT_BPTJSON_TARGET) \
- $(foreach file, $(BOARD_BPT_INPUT_FILES), --input $(file))
-
-ifdef BOARD_BPT_DISK_SIZE
-INTERNAL_BVBTOOL_MAKE_TABLE_ARGS += --disk_size $(BOARD_BPT_DISK_SIZE)
-endif
-
-define build-bptimage-target
- $(call pretty,"Target partition table image: $(INSTALLED_BPTIMAGE_TARGET)")
- $(hide) $(BPTTOOL) make_table $(INTERNAL_BVBTOOL_MAKE_TABLE_ARGS) $(BOARD_BPT_MAKE_TABLE_ARGS)
-endef
-
-INSTALLED_BPTIMAGE_TARGET := $(BUILT_BPTIMAGE_TARGET)
-$(BUILT_BPTJSON_TARGET): $(INSTALLED_BPTIMAGE_TARGET)
- $(hide) touch -c $(BUILT_BPTJSON_TARGET)
-
-$(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_VENDOR_DEPS+= $(INSTALLED_BPTIMAGE_TARGET)
-
-.PHONY: bptimage-nodeps
-bptimage-nodeps:
- $(build-bptimage-target)
-
-endif # BOARD_BPT_INPUT_FILES
-
-# -----------------------------------------------------------------
# cache partition image
INSTALLED_FILES_OUTSIDE_IMAGES := $(filter-out $(TARGET_OUT_CACHE)/%, $(INSTALLED_FILES_OUTSIDE_IMAGES))
ifdef BUILDING_CACHE_IMAGE
@@ -4168,7 +4229,7 @@
INSTALLED_PVMFWIMAGE_TARGET := $(PRODUCT_OUT)/pvmfw.img
INSTALLED_PVMFW_EMBEDDED_AVBKEY_TARGET := $(PRODUCT_OUT)/pvmfw_embedded.avbpubkey
-INSTALLED_PVMFW_BINARY_TARGET := $(call module-installed-files,pvmfw_bin)
+INSTALLED_PVMFW_BINARY_TARGET := $(call module-target-built-files,pvmfw_bin)
INTERNAL_PVMFWIMAGE_FILES := $(call module-target-built-files,pvmfw_img)
INTERNAL_PVMFW_EMBEDDED_AVBKEY := $(call module-target-built-files,pvmfw_embedded_key)
INTERNAL_PVMFW_SYMBOL := $(TARGET_OUT_EXECUTABLES_UNSTRIPPED)/pvmfw
@@ -4206,6 +4267,13 @@
ifneq ($(strip $(BOARD_CUSTOMIMAGES_PARTITION_LIST)),)
INTERNAL_AVB_CUSTOMIMAGES_SIGNING_ARGS :=
+BOARD_AVB_CUSTOMIMAGES_PARTITION_LIST :=
+# If BOARD_AVB_$(call to-upper,$(partition))_KEY_PATH is set, the image will be included in
+# BOARD_AVB_CUSTOMIMAGES_PARTITION_LIST, otherwise the image won't be AVB signed.
+$(foreach partition,$(BOARD_CUSTOMIMAGES_PARTITION_LIST), \
+ $(if $(BOARD_AVB_$(call to-upper,$(partition))_KEY_PATH), \
+ $(eval BOARD_AVB_CUSTOMIMAGES_PARTITION_LIST += $(partition)) \
+ $(eval BOARD_$(call to-upper,$(partition))_IMAGE_LIST := $(BOARD_AVB_$(call to-upper,$(partition))_IMAGE_LIST))))
# Sign custom image.
# $(1): the prebuilt custom image.
@@ -4230,9 +4298,26 @@
INSTALLED_CUSTOMIMAGES_TARGET += $(3)
endef
-$(foreach partition,$(BOARD_CUSTOMIMAGES_PARTITION_LIST), \
+# Copy unsigned custom image.
+# $(1): the prebuilt custom image.
+# $(2): the signed custom image target.
+define copy_custom_image
+$(2): $(1) $(INTERNAL_USERIMAGES_DEPS)
+ @echo Target custom image: $(2)
+ mkdir -p $(dir $(2))
+ cp $(1) $(2)
+INSTALLED_CUSTOMIMAGES_TARGET += $(2)
+endef
+
+# Add AVB custom image to droid target
+$(foreach partition,$(BOARD_AVB_CUSTOMIMAGES_PARTITION_LIST), \
$(foreach image,$(BOARD_AVB_$(call to-upper,$(partition))_IMAGE_LIST), \
$(eval $(call sign_custom_image,$(image),$(partition),$(PRODUCT_OUT)/$(notdir $(image))))))
+
+# Add unsigned custom image to droid target
+$(foreach partition,$(filter-out $(BOARD_AVB_CUSTOMIMAGES_PARTITION_LIST), $(BOARD_CUSTOMIMAGES_PARTITION_LIST)), \
+ $(foreach image,$(BOARD_$(call to-upper,$(partition))_IMAGE_LIST), \
+ $(eval $(call copy_custom_image,$(image),$(PRODUCT_OUT)/$(notdir $(image))))))
endif
# -----------------------------------------------------------------
@@ -4509,7 +4594,9 @@
$(eval part := $(1))
$(eval PART=$(call to-upper,$(part)))
$(eval _rollback_index_location := BOARD_AVB_$(PART)_ROLLBACK_INDEX_LOCATION)
+$(eval _key_path := BOARD_AVB_$(PART)_KEY_PATH)
$(if $($(_rollback_index_location)),,$(error $(_rollback_index_location) is not defined))
+$(if $($(_key_path)),,$(error $(_key_path) is not defined))
INTERNAL_AVB_MAKE_VBMETA_IMAGE_ARGS += \
--chain_partition $(part):$($(_rollback_index_location)):$(AVB_CHAIN_KEY_DIR)/$(part).avbpubkey
@@ -4589,8 +4676,8 @@
$(foreach partition,$(BOARD_AVB_VBMETA_CUSTOM_PARTITIONS),$(eval BOARD_AVB_MAKE_VBMETA_$(call to-upper,$(partition))_IMAGE_ARGS += --padding_size 4096))
endif
-ifneq ($(strip $(BOARD_CUSTOMIMAGES_PARTITION_LIST)),)
-$(foreach partition,$(BOARD_CUSTOMIMAGES_PARTITION_LIST), \
+ifneq ($(strip $(BOARD_AVB_CUSTOMIMAGES_PARTITION_LIST)),)
+$(foreach partition,$(BOARD_AVB_CUSTOMIMAGES_PARTITION_LIST), \
$(eval $(call check-and-set-custom-avb-chain-args,$(partition))))
endif
@@ -4677,8 +4764,8 @@
$(if $(BOARD_AVB_VBMETA_VENDOR_KEY_PATH),\
$(hide) $(AVBTOOL) extract_public_key --key $(BOARD_AVB_VBMETA_VENDOR_KEY_PATH) \
--output $(1)/vbmeta_vendor.avbpubkey)
- $(if $(BOARD_CUSTOMIMAGES_PARTITION_LIST),\
- $(hide) $(foreach partition,$(BOARD_CUSTOMIMAGES_PARTITION_LIST), \
+ $(if $(BOARD_AVB_CUSTOMIMAGES_PARTITION_LIST),\
+ $(hide) $(foreach partition,$(BOARD_AVB_CUSTOMIMAGES_PARTITION_LIST), \
$(AVBTOOL) extract_public_key --key $(BOARD_AVB_$(call to-upper,$(partition))_KEY_PATH) \
--output $(1)/$(partition).avbpubkey;)) \
$(if $(BOARD_AVB_VBMETA_CUSTOM_PARTITIONS),\
@@ -5001,7 +5088,9 @@
endif # INSTALLED_BOOTIMAGE_TARGET
endif # my_board_extracted_kernel
-ifneq ($(my_board_extracted_kernel),true)
+ifeq ($(my_board_extracted_kernel),true)
+$(call dist-for-goals, droid_targets, $(BUILT_KERNEL_VERSION_FILE))
+else
$(warning Neither INSTALLED_KERNEL_TARGET nor INSTALLED_BOOTIMAGE_TARGET is defined when \
PRODUCT_OTA_ENFORCE_VINTF_KERNEL_REQUIREMENTS is true. Information about the updated kernel \
cannot be built into OTA update package. You can fix this by: \
@@ -5264,7 +5353,6 @@
make_f2fs_casefold \
merge_ota \
merge_target_files \
- minigzip \
mk_combined_img \
mkbootfs \
mkbootimg \
@@ -5291,6 +5379,7 @@
toybox \
tune2fs \
unpack_bootimg \
+ update_device \
update_host_simulator \
validate_target_files \
verity_signer \
@@ -5302,6 +5391,7 @@
# Additional tools to unpack and repack the apex file.
INTERNAL_OTATOOLS_MODULES += \
+ apexd_host \
apexer \
apex_compression_tool \
deapexer \
@@ -5420,6 +5510,9 @@
ifeq ($(BOARD_USES_PVMFWIMAGE),true)
$(hide) echo "flash pvmfw" >> $@
endif
+ifneq ($(INSTALLED_VENDOR_BOOTIMAGE_TARGET),)
+ $(hide) echo "flash vendor_boot" >> $@
+endif
ifeq ($(BOARD_AVB_ENABLE),true)
ifeq ($(BUILDING_VBMETA_IMAGE),true)
$(hide) echo "flash --apply-vbmeta vbmeta" >> $@
@@ -5430,9 +5523,6 @@
ifneq (,$(strip $(BOARD_AVB_VBMETA_VENDOR)))
$(hide) echo "flash --apply-vbmeta vbmeta_vendor" >> $@
endif
-ifneq ($(INSTALLED_VENDOR_BOOTIMAGE_TARGET),)
- $(hide) echo "flash vendor_boot" >> $@
-endif
ifneq (,$(strip $(BOARD_AVB_VBMETA_CUSTOM_PARTITIONS)))
$(hide) $(foreach partition,$(BOARD_AVB_VBMETA_CUSTOM_PARTITIONS), \
echo "flash vbmeta_$(partition)" >> $@;)
@@ -5596,15 +5686,20 @@
$(hide) echo "avb_recovery_rollback_index_location=$(BOARD_AVB_RECOVERY_ROLLBACK_INDEX_LOCATION)" >> $@
endif # BOARD_AVB_RECOVERY_KEY_PATH
ifneq (,$(strip $(BOARD_CUSTOMIMAGES_PARTITION_LIST)))
- $(hide) echo "avb_custom_images_partition_list=$(BOARD_CUSTOMIMAGES_PARTITION_LIST)" >> $@
- $(hide) $(foreach partition,$(BOARD_CUSTOMIMAGES_PARTITION_LIST), \
+ $(hide) echo "custom_images_partition_list=$(filter-out $(BOARD_AVB_CUSTOMIMAGES_PARTITION_LIST), $(BOARD_CUSTOMIMAGES_PARTITION_LIST))" >> $@
+ $(hide) $(foreach partition,$(filter-out $(BOARD_AVB_CUSTOMIMAGES_PARTITION_LIST), $(BOARD_CUSTOMIMAGES_PARTITION_LIST)), \
+ echo "$(partition)_image_list=$(foreach image,$(BOARD_$(call to-upper,$(partition))_IMAGE_LIST),$(notdir $(image)))" >> $@;)
+endif # BOARD_CUSTOMIMAGES_PARTITION_LIST
+ifneq (,$(strip $(BOARD_AVB_CUSTOMIMAGES_PARTITION_LIST)))
+ $(hide) echo "avb_custom_images_partition_list=$(BOARD_AVB_CUSTOMIMAGES_PARTITION_LIST)" >> $@
+ $(hide) $(foreach partition,$(BOARD_AVB_CUSTOMIMAGES_PARTITION_LIST), \
echo "avb_$(partition)_key_path=$(BOARD_AVB_$(call to-upper,$(partition))_KEY_PATH)" >> $@; \
echo "avb_$(partition)_algorithm=$(BOARD_AVB_$(call to-upper,$(partition))_ALGORITHM)" >> $@; \
echo "avb_$(partition)_add_hashtree_footer_args=$(BOARD_AVB_$(call to-upper,$(partition))_ADD_HASHTREE_FOOTER_ARGS)" >> $@; \
echo "avb_$(partition)_rollback_index_location=$(BOARD_AVB_$(call to-upper,$(partition))_ROLLBACK_INDEX_LOCATION)" >> $@; \
echo "avb_$(partition)_partition_size=$(BOARD_AVB_$(call to-upper,$(partition))_PARTITION_SIZE)" >> $@; \
echo "avb_$(partition)_image_list=$(foreach image,$(BOARD_AVB_$(call to-upper,$(partition))_IMAGE_LIST),$(notdir $(image)))" >> $@;)
-endif # BOARD_CUSTOMIMAGES_PARTITION_LIST
+endif # BOARD_AVB_CUSTOMIMAGES_PARTITION_LIST
ifneq (,$(strip $(BOARD_AVB_VBMETA_SYSTEM)))
$(hide) echo "avb_vbmeta_system=$(BOARD_AVB_VBMETA_SYSTEM)" >> $@
$(hide) echo "avb_vbmeta_system_args=$(BOARD_AVB_MAKE_VBMETA_SYSTEM_IMAGE_ARGS)" >> $@
@@ -5629,14 +5724,6 @@
echo "avb_vbmeta_$(partition)_rollback_index_location=$(BOARD_AVB_VBMETA_$(call to-upper,$(partition))_ROLLBACK_INDEX_LOCATION)" >> $@ ;)
endif # BOARD_AVB_VBMETA_CUSTOM_PARTITIONS
endif # BOARD_AVB_ENABLE
-ifdef BOARD_BPT_INPUT_FILES
- $(hide) echo "board_bpt_enable=true" >> $@
- $(hide) echo "board_bpt_make_table_args=$(BOARD_BPT_MAKE_TABLE_ARGS)" >> $@
- $(hide) echo "board_bpt_input_files=$(BOARD_BPT_INPUT_FILES)" >> $@
-endif
-ifdef BOARD_BPT_DISK_SIZE
- $(hide) echo "board_bpt_disk_size=$(BOARD_BPT_DISK_SIZE)" >> $@
-endif
$(call generate-userimage-prop-dictionary, $@)
ifeq ($(AB_OTA_UPDATER),true)
@# Include the build type in META/misc_info.txt so the server can easily differentiate production builds.
@@ -5699,9 +5786,6 @@
ifeq ($(BUILDING_WITH_VSDK),true)
$(hide) echo "building_with_vsdk=true" >> $@
endif
-ifeq ($(TARGET_FLATTEN_APEX),false)
- $(hide) echo "target_flatten_apex=false" >> $@
-endif
$(call declare-0p-target,$(INSTALLED_FASTBOOT_INFO_TARGET))
@@ -5738,11 +5822,11 @@
# $(1): Directory to copy
# $(2): Location to copy it to
-# The "ls -A" is to prevent "acp s/* d" from failing if s is empty.
+# The "ls -A" is to skip if $(1) is empty.
define package_files-copy-root
if [ -d "$(strip $(1))" -a "$$(ls -A $(1))" ]; then \
mkdir -p $(2) && \
- $(ACP) -rd $(strip $(1))/* $(2); \
+ $(ACP) -rd $(strip $(1))/. $(strip $(2))/; \
fi
endef
@@ -5903,17 +5987,19 @@
# $(2): target out directory
# $(3): image name to generate a map file. skip generating map file if empty
define copy-image-and-generate-map
- $(eval _supported_fs_for_map_file_generator := erofs ext%)
- $(eval _img := $(call to-upper,$(3)))
- $(if $(3),$(eval _map_fs_type := $(BOARD_$(_img)IMAGE_FILE_SYSTEM_TYPE)),\
- $(eval _no_map_file := "true"))
- $(if $(filter $(_supported_fs_for_map_file_generator),$(_map_fs_type))$(_no_map_file),\
- mkdir -p $(2); \
- cp $(1) $(2); \
- $(if $(3),$(HOST_OUT_EXECUTABLES)/map_file_generator $(1) $(2)/$(3).map))
- $(eval _img :=)
- $(eval _map_fs_type :=)
- $(eval _no_map_file :=)
+ $(if $(COPY_IMAGES_FOR_TARGET_FILES_ZIP), \
+ $(eval _supported_fs_for_map_file_generator := erofs ext%) \
+ $(eval _img := $(call to-upper,$(3))) \
+ $(if $(3),$(eval _map_fs_type := $(BOARD_$(_img)IMAGE_FILE_SYSTEM_TYPE)),\
+ $(eval _no_map_file := "true")) \
+ $(if $(filter $(_supported_fs_for_map_file_generator),$(_map_fs_type))$(_no_map_file),\
+ mkdir -p $(2); \
+ cp $(1) $(2); \
+ $(if $(3),$(HOST_OUT_EXECUTABLES)/map_file_generator $(1) $(2)/$(3).map)) \
+ $(eval _img :=) \
+ $(eval _map_fs_type :=) \
+ $(eval _no_map_file :=) \
+ )
endef
# By conditionally including the dependency of the target files package on the
@@ -5921,7 +6007,9 @@
# image.
ifdef BUILDING_SYSTEM_IMAGE
$(BUILT_TARGET_FILES_DIR): $(FULL_SYSTEMIMAGE_DEPS)
- $(BUILT_TARGET_FILES_DIR): $(BUILT_SYSTEMIMAGE)
+ ifdef COPY_IMAGES_FOR_TARGET_FILES_ZIP
+ $(BUILT_TARGET_FILES_DIR): $(BUILT_SYSTEMIMAGE)
+ endif
else
# releasetools may need the system build.prop even when building a
# system-image-less product.
@@ -5934,7 +6022,9 @@
ifdef BUILDING_SYSTEM_OTHER_IMAGE
$(BUILT_TARGET_FILES_DIR): $(INTERNAL_SYSTEMOTHERIMAGE_FILES)
- $(BUILT_TARGET_FILES_DIR): $(BUILT_SYSTEMOTHERIMAGE_TARGET)
+ ifdef COPY_IMAGES_FOR_TARGET_FILES_ZIP
+ $(BUILT_TARGET_FILES_DIR): $(BUILT_SYSTEMOTHERIMAGE_TARGET)
+ endif
endif
ifdef BUILDING_VENDOR_BOOT_IMAGE
@@ -5966,21 +6056,27 @@
ifdef BUILDING_VENDOR_IMAGE
$(BUILT_TARGET_FILES_DIR): $(INTERNAL_VENDORIMAGE_FILES)
- $(BUILT_TARGET_FILES_DIR): $(BUILT_VENDORIMAGE_TARGET)
+ ifdef COPY_IMAGES_FOR_TARGET_FILES_ZIP
+ $(BUILT_TARGET_FILES_DIR): $(BUILT_VENDORIMAGE_TARGET)
+ endif
else ifdef BOARD_PREBUILT_VENDORIMAGE
$(BUILT_TARGET_FILES_DIR): $(INSTALLED_VENDORIMAGE_TARGET)
endif
ifdef BUILDING_PRODUCT_IMAGE
$(BUILT_TARGET_FILES_DIR): $(INTERNAL_PRODUCTIMAGE_FILES)
- $(BUILT_TARGET_FILES_DIR): $(BUILT_PRODUCTIMAGE_TARGET)
+ ifdef COPY_IMAGES_FOR_TARGET_FILES_ZIP
+ $(BUILT_TARGET_FILES_DIR): $(BUILT_PRODUCTIMAGE_TARGET)
+ endif
else ifdef BOARD_PREBUILT_PRODUCTIMAGE
$(BUILT_TARGET_FILES_DIR): $(INSTALLED_PRODUCTIMAGE_TARGET)
endif
ifdef BUILDING_SYSTEM_EXT_IMAGE
$(BUILT_TARGET_FILES_DIR): $(INTERNAL_SYSTEM_EXTIMAGE_FILES)
- $(BUILT_TARGET_FILES_DIR): $(BUILT_SYSTEM_EXTIMAGE_TARGET)
+ ifdef COPY_IMAGES_FOR_TARGET_FILES_ZIP
+ $(BUILT_TARGET_FILES_DIR): $(BUILT_SYSTEM_EXTIMAGE_TARGET)
+ endif
else ifdef BOARD_PREBUILT_SYSTEM_EXTIMAGE
$(BUILT_TARGET_FILES_DIR): $(INSTALLED_SYSTEM_EXTIMAGE_TARGET)
endif
@@ -5995,28 +6091,36 @@
ifdef BUILDING_ODM_IMAGE
$(BUILT_TARGET_FILES_DIR): $(INTERNAL_ODMIMAGE_FILES)
- $(BUILT_TARGET_FILES_DIR): $(BUILT_ODMIMAGE_TARGET)
+ ifdef COPY_IMAGES_FOR_TARGET_FILES_ZIP
+ $(BUILT_TARGET_FILES_DIR): $(BUILT_ODMIMAGE_TARGET)
+ endif
else ifdef BOARD_PREBUILT_ODMIMAGE
$(BUILT_TARGET_FILES_DIR): $(INSTALLED_ODMIMAGE_TARGET)
endif
ifdef BUILDING_VENDOR_DLKM_IMAGE
$(BUILT_TARGET_FILES_DIR): $(INTERNAL_VENDOR_DLKMIMAGE_FILES)
- $(BUILT_TARGET_FILES_DIR): $(BUILT_VENDOR_DLKMIMAGE_TARGET)
+ ifdef COPY_IMAGES_FOR_TARGET_FILES_ZIP
+ $(BUILT_TARGET_FILES_DIR): $(BUILT_VENDOR_DLKMIMAGE_TARGET)
+ endif
else ifdef BOARD_PREBUILT_VENDOR_DLKMIMAGE
$(BUILT_TARGET_FILES_DIR): $(INSTALLED_VENDOR_DLKMIMAGE_TARGET)
endif
ifdef BUILDING_ODM_DLKM_IMAGE
$(BUILT_TARGET_FILES_DIR): $(INTERNAL_ODM_DLKMIMAGE_FILES)
- $(BUILT_TARGET_FILES_DIR): $(BUILT_ODM_DLKMIMAGE_TARGET)
+ ifdef COPY_IMAGES_FOR_TARGET_FILES_ZIP
+ $(BUILT_TARGET_FILES_DIR): $(BUILT_ODM_DLKMIMAGE_TARGET)
+ endif
else ifdef BOARD_PREBUILT_ODM_DLKMIMAGE
$(BUILT_TARGET_FILES_DIR): $(INSTALLED_ODM_DLKMIMAGE_TARGET)
endif
ifdef BUILDING_SYSTEM_DLKM_IMAGE
$(BUILT_TARGET_FILES_DIR): $(INTERNAL_SYSTEM_DLKMIMAGE_FILES)
- $(BUILT_TARGET_FILES_DIR): $(BUILT_SYSTEM_DLKMIMAGE_TARGET)
+ ifdef COPY_IMAGES_FOR_TARGET_FILES_ZIP
+ $(BUILT_TARGET_FILES_DIR): $(BUILT_SYSTEM_DLKMIMAGE_TARGET)
+ endif
else ifdef BOARD_PREBUILT_SYSTEM_DLKMIMAGE
$(BUILT_TARGET_FILES_DIR): $(INSTALLED_SYSTEM_DLKMIMAGE_TARGET)
endif
@@ -6415,7 +6519,7 @@
ifneq ($(strip $(BOARD_CUSTOMIMAGES_PARTITION_LIST)),)
$(hide) mkdir -p $(zip_root)/PREBUILT_IMAGES
$(hide) $(foreach partition,$(BOARD_CUSTOMIMAGES_PARTITION_LIST), \
- $(foreach image,$(BOARD_AVB_$(call to-upper,$(partition))_IMAGE_LIST),cp $(image) $(zip_root)/PREBUILT_IMAGES/;))
+ $(foreach image,$(BOARD_$(call to-upper,$(partition))_IMAGE_LIST),cp $(image) $(zip_root)/PREBUILT_IMAGES/;))
endif # BOARD_CUSTOMIMAGES_PARTITION_LIST
@# The radio images in BOARD_PACK_RADIOIMAGES will be additionally copied from RADIO/ into
@# IMAGES/, which then will be added into <product>-img.zip. Such images must be listed in
@@ -6782,7 +6886,7 @@
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)/lib/x86_64-unknown-linux-gnu/libc++.so.1
+ LIBCXX := $(LLVM_PREBUILTS_BASE)/linux-x86/$(LLVM_PREBUILTS_VERSION)/lib/x86_64-unknown-linux-gnu/libc++.so
# Use llvm-profdata.zip for backwards compatibility with tradefed code.
LLVM_COVERAGE_TOOLS_ZIP := $(PRODUCT_OUT)/llvm-profdata.zip
@@ -6839,6 +6943,14 @@
ifeq (,$(TARGET_BUILD_UNBUNDLED))
$(JACOCO_REPORT_CLASSES_ALL): $(INTERNAL_ALLIMAGES_FILES)
endif
+
+# This is not ideal, but it is difficult to correctly figure out the actual jacoco report
+# jars we need to add here as dependencies, so we add the device-tests as a dependency when
+# the env variable is set and this should guarantee thaat all the jacoco report jars are ready
+# when we package the final report jar here.
+ifeq ($(JACOCO_PACKAGING_INCLUDE_DEVICE_TESTS),true)
+ $(JACOCO_REPORT_CLASSES_ALL): $(COMPATIBILITY.device-tests.FILES)
+endif
endif # EMMA_INSTRUMENT=true
@@ -7068,6 +7180,7 @@
PATH=$(INTERNAL_USERIMAGES_BINARY_PATHS):$(dir $(ZIP2ZIP)):$$PATH \
$(IMG_FROM_TARGET_FILES) \
--additional IMAGES/VerifiedBootParams.textproto:VerifiedBootParams.textproto \
+ --build_super_image $(BUILD_SUPER_IMAGE) \
$(BUILT_TARGET_FILES_PACKAGE) $@
$(call declare-1p-container,$(INTERNAL_UPDATE_PACKAGE_TARGET),)
@@ -7413,6 +7526,9 @@
haiku-rust: $(SOONG_RUST_FUZZ_PACKAGING_ARCH_MODULES) $(ALL_RUST_FUZZ_TARGETS)
$(call dist-for-goals,haiku-rust,$(SOONG_RUST_FUZZ_PACKAGING_ARCH_MODULES))
$(call dist-for-goals,haiku-rust,$(PRODUCT_OUT)/module-info.json)
+.PHONY: haiku-presubmit
+haiku-presubmit: $(SOONG_PRESUBMIT_FUZZ_PACKAGING_ARCH_MODULES) $(ALL_PRESUBMIT_FUZZ_TARGETS)
+$(call dist-for-goals,haiku-presubmit,$(SOONG_PRESUBMIT_FUZZ_PACKAGING_ARCH_MODULES))
# -----------------------------------------------------------------
# Extract platform fonts used in Layoutlib
diff --git a/core/aapt2.mk b/core/aapt2.mk
index 7b17df4..0e23477 100644
--- a/core/aapt2.mk
+++ b/core/aapt2.mk
@@ -68,6 +68,8 @@
# support for it.
my_static_library_resources := $(foreach l, $(call reverse-list,$(LOCAL_STATIC_ANDROID_LIBRARIES) $(LOCAL_STATIC_JAVA_AAR_LIBRARIES)),\
$(call intermediates-dir-for,JAVA_LIBRARIES,$(l),,COMMON)/package-res.apk)
+my_static_library_transitive_resource_packages_lists := $(foreach l, $(call reverse-list,$(LOCAL_STATIC_ANDROID_LIBRARIES) $(LOCAL_STATIC_JAVA_AAR_LIBRARIES)),\
+ $(call intermediates-dir-for,JAVA_LIBRARIES,$(l),,COMMON)/transitive-res-packages)
my_static_library_extra_packages := $(foreach l, $(call reverse-list,$(LOCAL_STATIC_ANDROID_LIBRARIES) $(LOCAL_STATIC_JAVA_AAR_LIBRARIES)),\
$(call intermediates-dir-for,JAVA_LIBRARIES,$(l),,COMMON)/extra_packages)
my_shared_library_resources := $(foreach l, $(LOCAL_SHARED_ANDROID_LIBRARIES),\
@@ -95,6 +97,7 @@
$(my_res_package): PRIVATE_JAVA_GEN_DIR := $(intermediates.COMMON)/aapt2
$(my_res_package): PRIVATE_SRCJAR := $(my_srcjar)
$(my_res_package): PRIVATE_STATIC_LIBRARY_EXTRA_PACKAGES := $(my_static_library_extra_packages)
+$(my_res_package): PRIVATE_STATIC_LIBRARY_TRANSITIVE_RES_PACKAGES_LISTS := $(my_static_library_transitive_resource_packages_lists)
$(my_res_package): PRIVATE_AAPT_EXTRA_PACKAGES := $(aapt_extra_packages)
$(my_res_package): .KATI_IMPLICIT_OUTPUTS := $(my_srcjar) $(aapt_extra_packages)
@@ -117,7 +120,7 @@
$(my_res_package): .KATI_IMPLICIT_OUTPUTS += $(proguard_options_file)
endif
-$(my_res_package): $(full_android_manifest) $(my_static_library_resources) $(my_shared_library_resources)
+$(my_res_package): $(full_android_manifest) $(my_static_library_resources) $(my_static_library_transitive_resource_packages_lists) $(my_shared_library_resources)
$(my_res_package): $(my_full_asset_paths)
$(my_res_package): $(my_res_resources_flat) $(my_overlay_resources_flat) \
$(my_resources_flata) $(my_static_library_resources) $(my_static_library_extra_packages) \
diff --git a/core/app_prebuilt_internal.mk b/core/app_prebuilt_internal.mk
index 9fab44d..b141a98 100644
--- a/core/app_prebuilt_internal.mk
+++ b/core/app_prebuilt_internal.mk
@@ -227,7 +227,7 @@
$(built_module): PRIVATE_EMBEDDED_JNI_LIBS := $(embedded_prebuilt_jni_libs)
ifdef LOCAL_COMPRESSED_MODULE
-$(built_module) : $(MINIGZIP)
+$(built_module) : $(GZIP)
endif
ifeq ($(module_run_appcompat),true)
@@ -305,4 +305,4 @@
###########################################################
## SBOM generation
###########################################################
-include $(BUILD_SBOM_GEN)
\ No newline at end of file
+include $(BUILD_SBOM_GEN)
diff --git a/core/base_rules.mk b/core/base_rules.mk
index 9ad1cc5..b3c5b94 100644
--- a/core/base_rules.mk
+++ b/core/base_rules.mk
@@ -578,7 +578,9 @@
ALL_VINTF_MANIFEST_FRAGMENTS_LIST += $(my_vintf_new_pairs)
- $(my_all_targets) : $(my_vintf_new_installed)
+ $(my_all_targets) : $(my_vintf_installed)
+ # Install fragments together with the target
+ $(LOCAL_INSTALLED_MODULE) : | $(my_vintf_installed)
endif # my_vintf_fragments
# Rule to install the module's companion init.rc.
@@ -615,6 +617,8 @@
ALL_INIT_RC_INSTALLED_PAIRS += $(my_init_rc_new_pairs)
$(my_all_targets) : $(my_init_rc_installed)
+ # Install init_rc together with the target
+ $(LOCAL_INSTALLED_MODULE) : | $(my_init_rc_installed)
endif # my_init_rc
endif # !LOCAL_IS_HOST_MODULE
@@ -961,6 +965,9 @@
$(my_init_rc_installed) \
$(my_installed_test_data) \
$(my_vintf_installed))
+
+ ALL_MODULES.$(my_register_name).INSTALLED_SYMLINKS := $(LOCAL_SOONG_INSTALL_SYMLINKS)
+
# Store the list of colon-separated pairs of the built and installed locations
# of files provided by this module. Used by custom packaging rules like
# package-modules.mk that need to copy the built files to a custom install
@@ -975,6 +982,11 @@
$(my_init_rc_pairs) \
$(my_test_data_pairs) \
$(my_vintf_pairs))
+ # Store the list of vintf/init_rc as order-only dependencies
+ ALL_MODULES.$(my_register_name).ORDERONLY_INSTALLED := \
+ $(strip $(ALL_MODULES.$(my_register_name).ORDERONLY_INSTALLED) \
+ $(my_init_rc_installed) \
+ $(my_vintf_installed))
else ifneq (true,$(LOCAL_UNINSTALLABLE_MODULE))
ALL_MODULES.$(my_register_name).INSTALLED := \
$(strip $(ALL_MODULES.$(my_register_name).INSTALLED) \
@@ -984,6 +996,10 @@
$(strip $(ALL_MODULES.$(my_register_name).BUILT_INSTALLED) \
$(LOCAL_BUILT_MODULE):$(LOCAL_INSTALLED_MODULE) \
$(my_init_rc_pairs) $(my_test_data_pairs) $(my_vintf_pairs))
+ ALL_MODULES.$(my_register_name).ORDERONLY_INSTALLED := \
+ $(strip $(ALL_MODULES.$(my_register_name).ORDERONLY_INSTALLED) \
+ $(my_init_rc_installed) \
+ $(my_vintf_installed))
endif
ifdef LOCAL_PICKUP_FILES
# Files or directories ready to pick up by the build system
@@ -1045,6 +1061,10 @@
$(ALL_MODULES.$(my_register_name).SUPPORTED_VARIANTS) \
$(filter-out $(ALL_MODULES.$(my_register_name).SUPPORTED_VARIANTS),$(my_supported_variant))
+ALL_MODULES.$(my_register_name).ACONFIG_FILES := \
+ $(ALL_MODULES.$(my_register_name).ACONFIG_FILES) $(LOCAL_ACONFIG_FILES)
+
+
##########################################################################
## When compiling against API imported module, use API import stub
## libraries.
diff --git a/core/board_config.mk b/core/board_config.mk
index 663ec7c..2699512 100644
--- a/core/board_config.mk
+++ b/core/board_config.mk
@@ -144,9 +144,6 @@
_board_strip_list += BOARD_AVB_PVMFW_ALGORITHM
_board_strip_list += BOARD_AVB_PVMFW_ROLLBACK_INDEX_LOCATION
_board_strip_list += BOARD_PARTIAL_OTA_UPDATE_PARTITIONS_LIST
-_board_strip_list += BOARD_BPT_DISK_SIZE
-_board_strip_list += BOARD_BPT_INPUT_FILES
-_board_strip_list += BOARD_BPT_MAKE_TABLE_ARGS
_board_strip_list += BOARD_AVB_VBMETA_VENDOR_ROLLBACK_INDEX_LOCATION
_board_strip_list += BOARD_AVB_VBMETA_VENDOR_ALGORITHM
_board_strip_list += BOARD_AVB_VBMETA_VENDOR_KEY_PATH
@@ -174,7 +171,6 @@
_build_broken_var_list := \
- BUILD_BROKEN_PLUGIN_VALIDATION \
BUILD_BROKEN_CLANG_PROPERTY \
BUILD_BROKEN_CLANG_ASFLAGS \
BUILD_BROKEN_CLANG_CFLAGS \
@@ -189,7 +185,6 @@
BUILD_BROKEN_PREBUILT_ELF_FILES \
BUILD_BROKEN_TREBLE_SYSPROP_NEVERALLOW \
BUILD_BROKEN_USES_NETWORK \
- BUILD_BROKEN_USES_SOONG_PYTHON2_MODULES \
BUILD_BROKEN_VENDOR_PROPERTY_NAMESPACE \
BUILD_BROKEN_VINTF_PRODUCT_COPY_FILES \
@@ -976,24 +971,6 @@
endif
TARGET_VENDOR_TEST_SUFFIX := /vendor
-###########################################
-# APEXes are by default not flattened, i.e. updatable.
-#
-# APEX flattening can also be forcibly enabled (resp. disabled) by
-# setting OVERRIDE_TARGET_FLATTEN_APEX to true (resp. false), e.g. by
-# setting the OVERRIDE_TARGET_FLATTEN_APEX environment variable.
-ifdef OVERRIDE_TARGET_FLATTEN_APEX
- TARGET_FLATTEN_APEX := $(OVERRIDE_TARGET_FLATTEN_APEX)
-endif
-
-# TODO(b/278826656) Remove the following message
-ifeq (true,$(TARGET_FLATTEN_APEX))
- $(warning ********************************************************************************)
- $(warning Flattened APEX will be deprecated soon. Please stop using flattened APEX and use)
- $(warning "image" APEX instead.)
- $(warning ********************************************************************************)
-endif
-
ifeq (,$(TARGET_BUILD_UNBUNDLED))
ifdef PRODUCT_EXTRA_VNDK_VERSIONS
$(foreach v,$(PRODUCT_EXTRA_VNDK_VERSIONS),$(call check_vndk_version,$(v)))
diff --git a/core/build_id.mk b/core/build_id.mk
index ba5ca42..4c2c7fa 100644
--- a/core/build_id.mk
+++ b/core/build_id.mk
@@ -18,4 +18,4 @@
# (like "CRB01"). It must be a single word, and is
# capitalized by convention.
-BUILD_ID=AOSP.MASTER
+BUILD_ID=AOSP.MAIN
diff --git a/core/clear_vars.mk b/core/clear_vars.mk
index bb7ba1b..409e559 100644
--- a/core/clear_vars.mk
+++ b/core/clear_vars.mk
@@ -9,6 +9,7 @@
LOCAL_AAPT_FLAGS:=
LOCAL_AAPT_INCLUDE_ALL_RESOURCES:=
LOCAL_AAPT_NAMESPACES:=
+LOCAL_ACONFIG_FILES:=
LOCAL_ADDITIONAL_CERTIFICATES:=
LOCAL_ADDITIONAL_CHECKED_MODULE:=
LOCAL_ADDITIONAL_DEPENDENCIES:=
@@ -297,6 +298,7 @@
LOCAL_SOONG_PROGUARD_DICT :=
LOCAL_SOONG_PROGUARD_USAGE_ZIP :=
LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE :=
+LOCAL_SOONG_TRANSITIVE_RES_PACKAGES :=
LOCAL_SOONG_DEVICE_RRO_DIRS :=
LOCAL_SOONG_PRODUCT_RRO_DIRS :=
LOCAL_SOONG_STATIC_LIBRARY_EXTRA_PACKAGES :=
diff --git a/core/config.mk b/core/config.mk
index c166ef7..ac49cec 100644
--- a/core/config.mk
+++ b/core/config.mk
@@ -342,6 +342,23 @@
JAVA_TMPDIR_ARG :=
endif
+# These build broken variables are intended to be set in a buildspec file,
+# while other build broken flags are expected to be set in a board config.
+# These are build broken variables that are expected to apply across board
+# configs, generally for cross-cutting features.
+
+# Build broken variables that should be treated as booleans
+_build_broken_bool_vars := \
+ BUILD_BROKEN_USES_SOONG_PYTHON2_MODULES \
+
+# Build broken variables that should be treated as lists
+_build_broken_list_vars := \
+ BUILD_BROKEN_PLUGIN_VALIDATION \
+
+_build_broken_var_names := $(_build_broken_bool_vars)
+_build_broken_var_names += $(_build_broken_list_vars)
+$(foreach v,$(_build_broken_var_names),$(eval $(v) :=))
+
# ###############################################################
# Include sub-configuration files
# ###############################################################
@@ -371,6 +388,13 @@
# are specific to the user's build configuration.
include $(BUILD_SYSTEM)/envsetup.mk
+
+$(foreach var,$(_build_broken_bool_vars), \
+ $(if $(filter-out true false,$($(var))), \
+ $(error Valid values of $(var) are "true", "false", and "". Not "$($(var))")))
+
+.KATI_READONLY := $(_build_broken_var_names)
+
# Returns true if it is a low memory device, otherwise it returns false.
define is-low-mem-device
$(if $(findstring ro.config.low_ram=true,$(PRODUCT_PROPERTY_OVERRIDES)),true,\
@@ -384,23 +408,8 @@
$(if $(findstring ro.config.low_ram=true,$(PRODUCT_ODM_PROPERTIES)),true,false)))))))))
endef
-# Get the board API level.
-board_api_level := $(PLATFORM_SDK_VERSION)
-ifdef BOARD_API_LEVEL
- board_api_level := $(BOARD_API_LEVEL)
-else ifdef BOARD_SHIPPING_API_LEVEL
- # Vendors with GRF must define BOARD_SHIPPING_API_LEVEL for the vendor API level.
- board_api_level := $(BOARD_SHIPPING_API_LEVEL)
-endif
-
-# Calculate the VSR vendor API level.
-vsr_vendor_api_level := $(board_api_level)
-
-ifdef PRODUCT_SHIPPING_API_LEVEL
- vsr_vendor_api_level := $(call math_min,$(PRODUCT_SHIPPING_API_LEVEL),$(board_api_level))
-endif
-
# Set TARGET_MAX_PAGE_SIZE_SUPPORTED.
+# TARGET_MAX_PAGE_SIZE_SUPPORTED indicates the alignment of the ELF segments.
ifdef PRODUCT_MAX_PAGE_SIZE_SUPPORTED
TARGET_MAX_PAGE_SIZE_SUPPORTED := $(PRODUCT_MAX_PAGE_SIZE_SUPPORTED)
else ifeq ($(strip $(call is-low-mem-device)),true)
@@ -410,12 +419,34 @@
# The default binary alignment for userspace is 4096.
TARGET_MAX_PAGE_SIZE_SUPPORTED := 4096
# When VSR vendor API level >= 34, binary alignment will be 65536.
- ifeq ($(call math_gt_or_eq,$(vsr_vendor_api_level),34),true)
+ ifeq ($(call math_gt_or_eq,$(VSR_VENDOR_API_LEVEL),34),true)
+ ifeq ($(TARGET_ARCH),arm64)
TARGET_MAX_PAGE_SIZE_SUPPORTED := 65536
+ endif
endif
endif
.KATI_READONLY := TARGET_MAX_PAGE_SIZE_SUPPORTED
+# Only arm64 arch supports TARGET_MAX_PAGE_SIZE_SUPPORTED greater than 4096.
+ifneq ($(TARGET_MAX_PAGE_SIZE_SUPPORTED),4096)
+ ifneq ($(TARGET_ARCH),arm64)
+ $(error TARGET_MAX_PAGE_SIZE_SUPPORTED=$(TARGET_MAX_PAGE_SIZE_SUPPORTED) is greater than 4096. Only supported in arm64 arch)
+ endif
+endif
+
+# Boolean variable determining if AOSP is page size agnostic. This means
+# that AOSP can use a kernel configured with 4k/16k/64k PAGE SIZES.
+TARGET_PAGE_SIZE_AGNOSTIC := false
+ifdef PRODUCT_PAGE_SIZE_AGNOSTIC
+ TARGET_PAGE_SIZE_AGNOSTIC := $(PRODUCT_PAGE_SIZE_AGNOSTIC)
+ ifeq ($(TARGET_PAGE_SIZE_AGNOSTIC),true)
+ ifneq ($(TARGET_MAX_PAGE_SIZE_SUPPORTED),65536)
+ $(error TARGET_MAX_PAGE_SIZE_SUPPORTED has to be 65536 to support page size agnostic)
+ endif
+ endif
+endif
+.KATI_READONLY := TARGET_PAGE_SIZE_AGNOSTIC
+
# Pruned directory options used when using findleaves.py
# See envsetup.mk for a description of SCAN_EXCLUDE_DIRS
FIND_LEAVES_EXCLUDES := $(addprefix --prune=, $(SCAN_EXCLUDE_DIRS) .repo .git)
@@ -625,6 +656,7 @@
FILESLIST_UTIL :=$= build/make/tools/fileslist_util.py
HOST_INIT_VERIFIER := $(HOST_OUT_EXECUTABLES)/host_init_verifier
XMLLINT := $(HOST_OUT_EXECUTABLES)/xmllint
+ACONFIG := $(HOST_OUT_EXECUTABLES)/aconfig
# SOONG_ZIP is exported by Soong, but needs to be defined early for
# $OUT/dexpreopt.global. It will be verified against the Soong version.
@@ -645,10 +677,11 @@
# For non-supported hosts, do not generate breakpad symbols.
BREAKPAD_GENERATE_SYMBOLS := false
endif
+GZIP := prebuilts/build-tools/path/$(BUILD_OS)-$(HOST_PREBUILT_ARCH)/gzip
PROTOC := $(HOST_OUT_EXECUTABLES)/aprotoc$(HOST_EXECUTABLE_SUFFIX)
NANOPB_SRCS := $(HOST_OUT_EXECUTABLES)/protoc-gen-nanopb
MKBOOTFS := $(HOST_OUT_EXECUTABLES)/mkbootfs$(HOST_EXECUTABLE_SUFFIX)
-MINIGZIP := $(HOST_OUT_EXECUTABLES)/minigzip$(HOST_EXECUTABLE_SUFFIX)
+MINIGZIP := $(GZIP)
LZ4 := $(HOST_OUT_EXECUTABLES)/lz4$(HOST_EXECUTABLE_SUFFIX)
GENERATE_GKI_CERTIFICATE := $(HOST_OUT_EXECUTABLES)/generate_gki_certificate$(HOST_EXECUTABLE_SUFFIX)
ifeq (,$(strip $(BOARD_CUSTOM_MKBOOTIMG)))
@@ -691,6 +724,7 @@
IMG_FROM_TARGET_FILES := $(HOST_OUT_EXECUTABLES)/img_from_target_files$(HOST_EXECUTABLE_SUFFIX)
MAKE_RECOVERY_PATCH := $(HOST_OUT_EXECUTABLES)/make_recovery_patch$(HOST_EXECUTABLE_SUFFIX)
OTA_FROM_TARGET_FILES := $(HOST_OUT_EXECUTABLES)/ota_from_target_files$(HOST_EXECUTABLE_SUFFIX)
+OTA_FROM_RAW_IMG := $(HOST_OUT_EXECUTABLES)/ota_from_raw_img$(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
@@ -722,7 +756,7 @@
# Path to tools.jar
HOST_JDK_TOOLS_JAR := $(ANDROID_JAVA8_HOME)/lib/tools.jar
-APICHECK_COMMAND := $(JAVA) -Xmx4g -jar $(APICHECK) --no-banner
+APICHECK_COMMAND := $(JAVA) -Xmx4g -jar $(APICHECK)
# Boolean variable determining if the allow list for compatible properties is enabled
PRODUCT_COMPATIBLE_PROPERTY := true
@@ -777,6 +811,9 @@
requirements :=
+# Set default value of KEEP_VNDK.
+KEEP_VNDK ?= true
+
# BOARD_PROPERTY_OVERRIDES_SPLIT_ENABLED can be true only if early-mount of
# partitions is supported. But the early-mount must be supported for full
# treble products, and so BOARD_PROPERTY_OVERRIDES_SPLIT_ENABLED should be set
@@ -893,13 +930,14 @@
.KATI_READONLY := IS_TARGET_MIXED_SEPOLICY
# A list of SEPolicy versions, besides PLATFORM_SEPOLICY_VERSION, that the framework supports.
-PLATFORM_SEPOLICY_COMPAT_VERSIONS := \
+PLATFORM_SEPOLICY_COMPAT_VERSIONS := $(filter-out $(PLATFORM_SEPOLICY_VERSION), \
29.0 \
30.0 \
31.0 \
32.0 \
33.0 \
34.0 \
+ )
.KATI_READONLY := \
PLATFORM_SEPOLICY_COMPAT_VERSIONS \
diff --git a/core/config_sanitizers.mk b/core/config_sanitizers.mk
index 7fa190f..82b17be 100644
--- a/core/config_sanitizers.mk
+++ b/core/config_sanitizers.mk
@@ -413,7 +413,6 @@
my_cflags += -fvisibility=default
endif
my_ldflags += $(CFI_EXTRA_LDFLAGS)
- my_arflags += --plugin $(LLVM_PREBUILTS_PATH)/../lib64/LLVMgold.so
ifeq ($(LOCAL_FORCE_STATIC_EXECUTABLE),true)
my_ldflags := $(filter-out -fsanitize-cfi-cross-dso,$(my_ldflags))
diff --git a/core/definitions.mk b/core/definitions.mk
index be40584..8a24f4c 100644
--- a/core/definitions.mk
+++ b/core/definitions.mk
@@ -1547,10 +1547,10 @@
#
# You must call this with $(eval).
define define-aidl-java-rule
-define-aidl-java-rule-src := $(patsubst %.aidl,%.java,$(subst ../,dotdot/,$(addprefix $(2)/,$(1))))
-$$(define-aidl-java-rule-src) : $(call clean-path,$(LOCAL_PATH)/$(1)) $(AIDL)
+define_aidl_java_rule_src := $(patsubst %.aidl,%.java,$(subst ../,dotdot/,$(addprefix $(2)/,$(1))))
+$$(define_aidl_java_rule_src) : $(call clean-path,$(LOCAL_PATH)/$(1)) $(AIDL)
$$(transform-aidl-to-java)
-$(3) += $$(define-aidl-java-rule-src)
+$(3) += $$(define_aidl_java_rule_src)
endef
## Given a .aidl file path generate the rule to compile it a .cpp file.
@@ -1560,10 +1560,10 @@
#
# You must call this with $(eval).
define define-aidl-cpp-rule
-define-aidl-cpp-rule-src := $(patsubst %.aidl,%$(LOCAL_CPP_EXTENSION),$(subst ../,dotdot/,$(addprefix $(2)/,$(1))))
-$$(define-aidl-cpp-rule-src) : $(call clean-path,$(LOCAL_PATH)/$(1)) $(AIDL_CPP)
+define_aidl_cpp_rule_src := $(patsubst %.aidl,%$(LOCAL_CPP_EXTENSION),$(subst ../,dotdot/,$(addprefix $(2)/,$(1))))
+$$(define_aidl_cpp_rule_src) : $(call clean-path,$(LOCAL_PATH)/$(1)) $(AIDL_CPP)
$$(transform-aidl-to-cpp)
-$(3) += $$(define-aidl-cpp-rule-src)
+$(3) += $$(define_aidl_cpp_rule_src)
endef
###########################################################
@@ -1585,10 +1585,10 @@
#
# You must call this with $(eval).
define define-vts-cpp-rule
-define-vts-cpp-rule-src := $(patsubst %.vts,%$(LOCAL_CPP_EXTENSION),$(subst ../,dotdot/,$(addprefix $(2)/,$(1))))
-$$(define-vts-cpp-rule-src) : $(LOCAL_PATH)/$(1) $(VTSC)
+define_vts_cpp_rule_src := $(patsubst %.vts,%$(LOCAL_CPP_EXTENSION),$(subst ../,dotdot/,$(addprefix $(2)/,$(1))))
+$$(define_vts_cpp_rule_src) : $(LOCAL_PATH)/$(1) $(VTSC)
$$(transform-vts-to-cpp)
-$(3) += $$(define-vts-cpp-rule-src)
+$(3) += $$(define_vts_cpp_rule_src)
endef
###########################################################
@@ -2377,6 +2377,7 @@
mkdir -p $(PRIVATE_JAVA_GEN_DIR)
$(call dump-words-to-file,$(PRIVATE_RES_FLAT),$(dir $@)aapt2-flat-list)
$(call dump-words-to-file,$(PRIVATE_OVERLAY_FLAT),$(dir $@)aapt2-flat-overlay-list)
+cat $(PRIVATE_STATIC_LIBRARY_TRANSITIVE_RES_PACKAGES_LISTS) | sort -u | tr '\n' ' ' > $(dir $@)aapt2-transitive-overlay-list
$(hide) $(AAPT2) link -o $@ \
$(PRIVATE_AAPT_FLAGS) \
$(if $(PRIVATE_STATIC_LIBRARY_EXTRA_PACKAGES),$$(cat $(PRIVATE_STATIC_LIBRARY_EXTRA_PACKAGES))) \
@@ -2396,6 +2397,7 @@
$(addprefix --rename-manifest-package ,$(PRIVATE_MANIFEST_PACKAGE_NAME)) \
$(addprefix --rename-instrumentation-target-package ,$(PRIVATE_MANIFEST_INSTRUMENTATION_FOR)) \
-R \@$(dir $@)aapt2-flat-overlay-list \
+ -R \@$(dir $@)aapt2-transitive-overlay-list \
\@$(dir $@)aapt2-flat-list
$(SOONG_ZIP) -o $(PRIVATE_SRCJAR) -C $(PRIVATE_JAVA_GEN_DIR) -D $(PRIVATE_JAVA_GEN_DIR)
$(EXTRACT_JAR_PACKAGES) -i $(PRIVATE_SRCJAR) -o $(PRIVATE_AAPT_EXTRA_PACKAGES) --prefix '--extra-packages '
@@ -2941,7 +2943,7 @@
define compress-package
$(hide) \
mv $@ $@.uncompressed; \
- $(MINIGZIP) -9 -c $@.uncompressed > $@.compressed; \
+ $(GZIP) -9 -c $@.uncompressed > $@.compressed; \
rm -f $@.uncompressed; \
mv $@.compressed $@;
endef
@@ -3201,8 +3203,9 @@
define copy-vintf-manifest-checked
$(2): $(1) $(HOST_OUT_EXECUTABLES)/assemble_vintf
@echo "Copy xml: $$@"
- $(hide) $(HOST_OUT_EXECUTABLES)/assemble_vintf -i $$< >/dev/null # Don't print the xml file to stdout.
- $$(copy-file-to-target)
+ $(hide) mkdir -p "$$(dir $$@)"
+ $(hide) VINTF_IGNORE_TARGET_FCM_VERSION=true\
+ $(HOST_OUT_EXECUTABLES)/assemble_vintf -i $$< -o $$@
endef
# Copies many vintf manifest files checked.
diff --git a/core/dex_preopt_config.mk b/core/dex_preopt_config.mk
index 7b9c4db..6739459 100644
--- a/core/dex_preopt_config.mk
+++ b/core/dex_preopt_config.mk
@@ -111,6 +111,7 @@
$(call add_json_list, BootJars, $(PRODUCT_BOOT_JARS))
$(call add_json_list, ApexBootJars, $(PRODUCT_APEX_BOOT_JARS))
$(call add_json_list, ArtApexJars, $(filter $(PRODUCT_BOOT_JARS),$(ART_APEX_JARS)))
+ $(call add_json_list, TestOnlyArtBootImageJars, $(PRODUCT_TEST_ONLY_ART_BOOT_IMAGE_JARS))
$(call add_json_list, SystemServerJars, $(PRODUCT_SYSTEM_SERVER_JARS))
$(call add_json_list, SystemServerApps, $(PRODUCT_SYSTEM_SERVER_APPS))
$(call add_json_list, ApexSystemServerJars, $(PRODUCT_APEX_SYSTEM_SERVER_JARS))
diff --git a/core/dex_preopt_odex_install.mk b/core/dex_preopt_odex_install.mk
index bdd47a8..af6d921 100644
--- a/core/dex_preopt_odex_install.mk
+++ b/core/dex_preopt_odex_install.mk
@@ -152,6 +152,9 @@
$(LOCAL_USES_LIBRARIES) \
$(my_filtered_optional_uses_libraries)
+# The order needs to be deterministic.
+my_dexpreopt_libs_all := $(sort $(my_dexpreopt_libs) $(my_dexpreopt_libs_compat))
+
# Module dexpreopt.config depends on dexpreopt.config files of each
# <uses-library> dependency, because these libraries may be processed after
# the current module by Make (there's no topological order), so the dependency
@@ -442,17 +445,38 @@
@cp $(PRIVATE_BUILT_MODULE) $@
endif
+ # The root "product_packages.txt" is generated by `build/make/core/Makefile`. It contains a list
+ # of all packages that are installed on the device. We use `grep` to filter the list by the app's
+ # dependencies to create a per-app list, and use `rsync --checksum` to prevent the file's mtime
+ # from being changed if the contents don't change. This avoids unnecessary dexpreopt reruns.
+ my_dexpreopt_product_packages := $(intermediates)/product_packages.txt
+ .KATI_RESTAT: $(my_dexpreopt_product_packages)
+ $(my_dexpreopt_product_packages): PRIVATE_MODULE := $(LOCAL_MODULE)
+ $(my_dexpreopt_product_packages): PRIVATE_LIBS := $(my_dexpreopt_libs_all)
+ $(my_dexpreopt_product_packages): PRIVATE_STAGING := $(my_dexpreopt_product_packages).tmp
+ $(my_dexpreopt_product_packages): $(PRODUCT_OUT)/product_packages.txt
+ @echo "$(PRIVATE_MODULE) dexpreopt product_packages"
+ ifneq (,$(my_dexpreopt_libs_all))
+ grep -F -x \
+ $(addprefix -e ,$(PRIVATE_LIBS)) \
+ $(PRODUCT_OUT)/product_packages.txt \
+ > $(PRIVATE_STAGING) \
+ || true
+ else
+ rm -f $(PRIVATE_STAGING) && touch $(PRIVATE_STAGING)
+ endif
+ rsync --checksum $(PRIVATE_STAGING) $@
+
my_dexpreopt_script := $(intermediates)/dexpreopt.sh
- my_dexpreopt_zip := $(intermediates)/dexpreopt.zip
- DEXPREOPT.$(LOCAL_MODULE).POST_INSTALLED_DEXPREOPT_ZIP := $(my_dexpreopt_zip)
.KATI_RESTAT: $(my_dexpreopt_script)
$(my_dexpreopt_script): PRIVATE_MODULE := $(LOCAL_MODULE)
$(my_dexpreopt_script): PRIVATE_GLOBAL_SOONG_CONFIG := $(DEX_PREOPT_SOONG_CONFIG_FOR_MAKE)
$(my_dexpreopt_script): PRIVATE_GLOBAL_CONFIG := $(DEX_PREOPT_CONFIG_FOR_MAKE)
$(my_dexpreopt_script): PRIVATE_MODULE_CONFIG := $(my_dexpreopt_config)
+ $(my_dexpreopt_script): PRIVATE_PRODUCT_PACKAGES := $(my_dexpreopt_product_packages)
$(my_dexpreopt_script): $(DEXPREOPT_GEN)
$(my_dexpreopt_script): $(my_dexpreopt_jar_copy)
- $(my_dexpreopt_script): $(my_dexpreopt_config) $(DEX_PREOPT_SOONG_CONFIG_FOR_MAKE) $(DEX_PREOPT_CONFIG_FOR_MAKE)
+ $(my_dexpreopt_script): $(my_dexpreopt_config) $(DEX_PREOPT_SOONG_CONFIG_FOR_MAKE) $(DEX_PREOPT_CONFIG_FOR_MAKE) $(my_dexpreopt_product_packages)
@echo "$(PRIVATE_MODULE) dexpreopt gen"
$(DEXPREOPT_GEN) \
-global_soong $(PRIVATE_GLOBAL_SOONG_CONFIG) \
@@ -460,12 +484,12 @@
-module $(PRIVATE_MODULE_CONFIG) \
-dexpreopt_script $@ \
-out_dir $(OUT_DIR) \
- -product_packages $(PRODUCT_OUT)/product_packages.txt
+ -product_packages $(PRIVATE_PRODUCT_PACKAGES)
my_dexpreopt_deps := $(my_dex_jar)
my_dexpreopt_deps += $(if $(my_process_profile),$(LOCAL_DEX_PREOPT_PROFILE))
my_dexpreopt_deps += \
- $(foreach lib, $(my_dexpreopt_libs) $(my_dexpreopt_libs_compat), \
+ $(foreach lib, $(my_dexpreopt_libs_all), \
$(call intermediates-dir-for,JAVA_LIBRARIES,$(lib),,COMMON)/javalib.jar)
my_dexpreopt_deps += $(my_dexpreopt_images_deps)
my_dexpreopt_deps += $(DEXPREOPT_BOOTCLASSPATH_DEX_FILES)
@@ -473,36 +497,68 @@
my_dexpreopt_deps += $(intermediates)/enforce_uses_libraries.status
endif
+ # We need to add all the installed files to ALL_MODULES.$(my_register_name).INSTALLED in order
+ # for the build system to properly track installed files. (for sbom, installclean, etc)
+ # We install all the files in a zip file generated at execution time, which means we have to guess
+ # what's going to be in that zip file before it's created. We then check at executation time that
+ # our guess is correct.
+ # _system_other corresponds to OdexOnSystemOtherByName() in soong.
+ # The other paths correspond to dexpreoptCommand()
+ _dexlocation := $(patsubst $(PRODUCT_OUT)/%,%,$(LOCAL_INSTALLED_MODULE))
+ _dexname := $(basename $(notdir $(_dexlocation)))
+ _system_other := $(strip $(if $(strip $(BOARD_USES_SYSTEM_OTHER_ODEX)), \
+ $(if $(strip $(SANITIZE_LITE)),, \
+ $(if $(filter $(_dexname),$(PRODUCT_DEXPREOPT_SPEED_APPS))$(filter $(_dexname),$(PRODUCT_SYSTEM_SERVER_APPS)),, \
+ $(if $(strip $(foreach myfilter,$(SYSTEM_OTHER_ODEX_FILTER),$(filter system/$(myfilter),$(_dexlocation)))), \
+ system_other/)))))
+ # _dexdir has a trailing /
+ _dexdir := $(_system_other)$(dir $(_dexlocation))
+ my_dexpreopt_zip_contents := $(sort \
+ $(foreach arch,$(my_dexpreopt_archs), \
+ $(_dexdir)oat/$(arch)/$(_dexname).odex \
+ $(_dexdir)oat/$(arch)/$(_dexname).vdex \
+ $(if $(filter false,$(LOCAL_DEX_PREOPT_APP_IMAGE)),, \
+ $(if $(my_process_profile)$(filter true,$(LOCAL_DEX_PREOPT_APP_IMAGE)), \
+ $(_dexdir)oat/$(arch)/$(_dexname).art))) \
+ $(if $(my_process_profile),$(_dexlocation).prof))
+ _dexlocation :=
+ _dexdir :=
+ _dexname :=
+ _system_other :=
+
+ my_dexpreopt_zip := $(intermediates)/dexpreopt.zip
+ DEXPREOPT.$(LOCAL_MODULE).POST_INSTALLED_DEXPREOPT_ZIP := $(my_dexpreopt_zip)
$(my_dexpreopt_zip): PRIVATE_MODULE := $(LOCAL_MODULE)
$(my_dexpreopt_zip): $(my_dexpreopt_deps)
$(my_dexpreopt_zip): | $(DEXPREOPT_GEN_DEPS)
$(my_dexpreopt_zip): .KATI_DEPFILE := $(my_dexpreopt_zip).d
$(my_dexpreopt_zip): PRIVATE_DEX := $(my_dex_jar)
$(my_dexpreopt_zip): PRIVATE_SCRIPT := $(my_dexpreopt_script)
+ $(my_dexpreopt_zip): PRIVATE_ZIP_CONTENTS := $(my_dexpreopt_zip_contents)
$(my_dexpreopt_zip): $(my_dexpreopt_script)
@echo "$(PRIVATE_MODULE) dexpreopt"
+ rm -f $@
+ echo -n > $@.contents
+ $(foreach f,$(PRIVATE_ZIP_CONTENTS),echo "$(f)" >> $@.contents$(newline))
bash $(PRIVATE_SCRIPT) $(PRIVATE_DEX) $@
+ if ! diff <(zipinfo -1 $@ | sort) $@.contents >&2; then \
+ echo "Contents of $@ did not match what make was expecting." >&2 && exit 1; \
+ fi
- ifdef LOCAL_POST_INSTALL_CMD
- # Add a shell command separator
- LOCAL_POST_INSTALL_CMD += &&
- endif
+ $(foreach installed_dex_file,$(my_dexpreopt_zip_contents),\
+ $(eval $(PRODUCT_OUT)/$(installed_dex_file): $(my_dexpreopt_zip) \
+$(newline) unzip -qoDD -d $(PRODUCT_OUT) $(my_dexpreopt_zip) $(installed_dex_file)))
- LOCAL_POST_INSTALL_CMD += \
- for i in $$(zipinfo -1 $(my_dexpreopt_zip)); \
- do mkdir -p $(PRODUCT_OUT)/$$(dirname $$i); \
- done && \
- ( unzip -qoDD -d $(PRODUCT_OUT) $(my_dexpreopt_zip) 2>&1 | grep -v "zipfile is empty"; exit $${PIPESTATUS[0]} ) || \
- ( code=$$?; if [ $$code -ne 0 -a $$code -ne 1 ]; then exit $$code; fi )
-
- $(LOCAL_INSTALLED_MODULE): PRIVATE_POST_INSTALL_CMD := $(LOCAL_POST_INSTALL_CMD)
- $(LOCAL_INSTALLED_MODULE): $(my_dexpreopt_zip)
-
- $(my_all_targets): $(my_dexpreopt_zip)
+ ALL_MODULES.$(my_register_name).INSTALLED += $(addprefix $(PRODUCT_OUT)/,$(my_dexpreopt_zip_contents))
my_dexpreopt_config :=
+ my_dexpreopt_config_for_postprocessing :=
+ my_dexpreopt_jar_copy :=
+ my_dexpreopt_product_packages :=
my_dexpreopt_script :=
my_dexpreopt_zip :=
- my_dexpreopt_config_for_postprocessing :=
+ my_dexpreopt_zip_contents :=
endif # LOCAL_DEX_PREOPT
endif # my_create_dexpreopt_config
+
+my_dexpreopt_libs_all :=
diff --git a/core/dupcheck.sh b/core/dupcheck.sh
new file mode 100755
index 0000000..13ab782
--- /dev/null
+++ b/core/dupcheck.sh
@@ -0,0 +1,118 @@
+#!/bin/bash
+
+# Find duplicate shared libraries by md5 checksum and possible duplicates by size.
+# Results will be available in the out directory of the build.
+# Usage:
+# ./dupcheck.sh <out_dir> <image>
+
+OUT_DIR="$1"
+IMG="$2"
+TMP_MD5="${OUT_DIR}/_dup_md5"
+TMP_SIZE="${OUT_DIR}/_dup_size"
+TMP_CHECK="${OUT_DIR}/_dup_tmp_check"
+TMP_SIZE_REAL="${OUT_DIR}/_dup_size_real"
+TMP_FILE1="${OUT_DIR}/_dup_f1"
+TMP_FILE2="${OUT_DIR}/_dup_f2"
+MD5_DUPLICATES="${OUT_DIR}/duplicate-libs-md5-${IMG}.txt"
+SIZE_DUPLICATES="${OUT_DIR}/duplicate-libs-size-${IMG}.txt"
+
+# Check arguments
+if [ "$#" -ne 2 ]; then
+ echo "Usage: ./dupcheck.sh <out_dir> <image>"
+ exit 1
+fi
+
+# Check host and toolchain version
+CHECK_HOST=$(uname)
+if [ "${CHECK_HOST}" == "Linux" ]; then
+ ARCH="linux-x86"
+else
+ ARCH="darwin-x86"
+fi
+BINUTILS_PATH="./prebuilts/clang/host/${ARCH}/llvm-binutils-stable"
+
+# Remove any old files if they exist.
+if [ -f "${MD5_DUPLICATES}" ]; then
+ rm "${MD5_DUPLICATES}"
+fi
+
+if [ -f "${SIZE_DUPLICATES}" ]; then
+ rm "${SIZE_DUPLICATES}"
+fi
+
+# Find all .so files and calculate their md5.
+find ./"${OUT_DIR}"/${IMG}/ -name "lib*.so" -type f -print0 | xargs -0 md5sum | sed -e "s# .*/# #" | sort | uniq -c | sort -g | sed "/^.*1 /d" | sed "s/^. *[0-9] //" > "${TMP_MD5}" 2>&1
+
+if [ -s "${TMP_MD5}" ]; then
+ while read -r list; do
+ checksum=$(echo "${list}" | cut -f1 -d ' ')
+ filename=$(echo "${list}" | cut -f2 -d ' ')
+ # For each md5, list the file paths that match.
+ {
+ echo "MD5: ${checksum}"; \
+ find ./"${OUT_DIR}"/${IMG}/ -name "${filename}" -type f -print0 | xargs -0 md5sum | grep "${checksum}" | sed 's/^.* //'; \
+ echo ""; \
+ } >> "${MD5_DUPLICATES}"
+ done <"${TMP_MD5}"
+else
+ echo "No duplicate files by md5 found." >> "${MD5_DUPLICATES}"
+fi
+
+# Cleanup
+rm "${TMP_MD5}"
+
+# Find possible duplicate .so files by size.
+find ./"${OUT_DIR}"/${IMG}/ -name "*.so" -type f -print0 | xargs -0 stat --format="%s %n" 2>/dev/null | sed -e "s# .*/# #" | sort | uniq -c | sort -g | sed "/^.*1 /d" > "${TMP_SIZE}" 2>&1
+if [ -s "${TMP_SIZE}" ]; then
+ while read -r list; do
+ size=$(echo "${list}" | cut -f2 -d ' ')
+ filename=$(echo "${list}" | cut -f3 -d ' ')
+ # Check if the files are not in the md5sum list and do nothing if that is the case.
+ find ./"${OUT_DIR}"/${IMG}/ -name "${filename}" -type f -print0 | xargs -0 stat --format="%s %n" 2>/dev/null | grep "${size}" | sed "s/^.* //" | sort > "${TMP_CHECK}" 2>&1
+ while read -r filepath; do
+ found=$(grep -F "${filepath}" "${MD5_DUPLICATES}")
+ if [ -z "${found}" ]; then
+ echo "${filepath}" >> "${TMP_SIZE_REAL}"
+ fi
+ done<"${TMP_CHECK}"
+ # For every duplication found, diff the .note and .text sections.
+ if [ -s "${TMP_SIZE_REAL}" ]; then
+ {
+ echo "File: ${filename}, Size: ${size}"; \
+ cat "${TMP_SIZE_REAL}"; \
+ echo ""; \
+ } >> "${SIZE_DUPLICATES}"
+ count=$(wc -l "${TMP_SIZE_REAL}" | cut -f1 -d ' ')
+ # Limitation: this only works for file pairs. If more than two possible duplications are found, the user need to check manually
+ # all the possible combinations using the llvm-readelf and llvm-objdump commands below.
+ if [ "${count}" = 2 ]; then
+ file1=$(head -n 1 "${TMP_SIZE_REAL}")
+ file2=$(tail -n 1 "${TMP_SIZE_REAL}")
+ # Check .note section
+ ${BINUTILS_PATH}/llvm-readelf --wide --notes "${file1}" > "${TMP_FILE1}" 2>&1
+ ${BINUTILS_PATH}/llvm-readelf --wide --notes "${file2}" > "${TMP_FILE2}" 2>&1
+ {
+ diff -u "${TMP_FILE1}" "${TMP_FILE2}" | sed "1d;2d;3d"; \
+ echo "";
+ } >> "${SIZE_DUPLICATES}"
+ # Check .text section
+ ${BINUTILS_PATH}/llvm-objdump --line-numbers --disassemble --demangle --reloc --no-show-raw-insn --section=.text "${file1}" | sed "1d;2d"> "${TMP_FILE1}" 2>&1
+ ${BINUTILS_PATH}/llvm-objdump --line-numbers --disassemble --demangle --reloc --no-show-raw-insn --section=.text "${file2}" | sed "1d;2d"> "${TMP_FILE2}" 2>&1
+ {
+ diff -u "${TMP_FILE1}" "${TMP_FILE2}" | sed "1d;2d;3d"; \
+ echo "";
+ } >> "${SIZE_DUPLICATES}"
+ # Cleanup
+ rm "${TMP_FILE1}" "${TMP_FILE2}"
+ else
+ echo "*Note: more than one duplicate. Manually verify all possible combinations." >> "${SIZE_DUPLICATES}"
+ fi
+ rm "${TMP_SIZE_REAL}"
+ echo "" >> "${SIZE_DUPLICATES}"
+ fi
+ done <"${TMP_SIZE}"
+ # Cleanup
+ rm "${TMP_SIZE}" "${TMP_CHECK}"
+else
+ echo "No duplicate files by size found." >> "${SIZE_DUPLICATES}"
+fi
diff --git a/core/main.mk b/core/main.mk
index 7b3584e..12b7bd0 100644
--- a/core/main.mk
+++ b/core/main.mk
@@ -218,6 +218,12 @@
else
ADDITIONAL_VENDOR_PROPERTIES := ro.vndk.version=$(BOARD_VNDK_VERSION)
endif
+
+ # TODO(b/290159430): ro.vndk.deprecate is a temporal variable for deprecating VNDK.
+ # This variable will be removed once ro.vndk.version can be removed.
+ ifneq ($(KEEP_VNDK),true)
+ ADDITIONAL_SYSTEM_PROPERTIES += ro.vndk.deprecate=true
+ endif
endif
# Add cpu properties for bionic and ART.
@@ -810,12 +816,14 @@
# Sets up dependencies such that whenever a target module is installed,
# any other target modules listed in $(ALL_MODULES.$(m).REQUIRED_FROM_TARGET) will also be installed
+# This doesn't apply to ORDERONLY_INSTALLED items.
define add-all-target-to-target-required-modules-deps
$(foreach m,$(ALL_MODULES), \
$(eval r := $(ALL_MODULES.$(m).REQUIRED_FROM_TARGET)) \
$(if $(r), \
$(eval r := $(call module-installed-files,$(r))) \
$(eval t_m := $(filter $(TARGET_OUT_ROOT)/%, $(ALL_MODULES.$(m).INSTALLED))) \
+ $(eval t_m := $(filter-out $(ALL_MODULES.$(m).ORDERONLY_INSTALLED), $(ALL_MODULES.$(m).INSTALLED))) \
$(eval t_r := $(filter $(TARGET_OUT_ROOT)/%, $(r))) \
$(eval t_r := $(filter-out $(t_m), $(t_r))) \
$(if $(t_m), $(eval $(call add-required-deps, $(t_m),$(t_r)))) \
@@ -1356,6 +1364,7 @@
product_host_FILES := $(call host-installed-files,$(INTERNAL_PRODUCT))
product_target_FILES := $(call product-installed-files, $(INTERNAL_PRODUCT))
# WARNING: The product_MODULES variable is depended on by external files.
+ # It contains the list of register names that will be installed on the device
product_MODULES := $(_pif_modules)
# Verify the artifact path requirements made by included products.
@@ -1708,11 +1717,13 @@
# If they used the magic goal "all" then build all apps in the source tree.
unbundled_build_modules := $(foreach m,$(sort $(ALL_MODULES)),$(if $(filter APPS,$(ALL_MODULES.$(m).CLASS)),$(m)))
else
- unbundled_build_modules := $(TARGET_BUILD_APPS)
+ unbundled_build_modules := $(sort $(TARGET_BUILD_APPS))
endif
- # Dist the installed files if they exist.
- apps_only_installed_files := $(foreach m,$(unbundled_build_modules),$(ALL_MODULES.$(m).INSTALLED))
+ # Dist the installed files if they exist, except the installed symlinks. dist-for-goals emits
+ # `cp src dest` commands, which will fail to copy dangling symlinks.
+ apps_only_installed_files := $(foreach m,$(unbundled_build_modules),\
+ $(filter-out $(ALL_MODULES.$(m).INSTALLED_SYMLINKS),$(ALL_MODULES.$(m).INSTALLED)))
$(call dist-for-goals,apps_only, $(apps_only_installed_files))
# Dist the bundle files if they exist.
@@ -2157,10 +2168,12 @@
# See the second foreach loop in the rule of sbom-metadata.csv for the detailed info of static libraries collected in _all_static_libs.
# is_static_lib: whether the file is a static library
+metadata_list := $(OUT_DIR)/.module_paths/METADATA.list
+metadata_files := $(subst $(newline),$(space),$(file <$(metadata_list)))
# (TODO: b/272358583 find another way of always rebuilding this target)
# Remove the sbom-metadata.csv whenever makefile is evaluated
$(shell rm $(PRODUCT_OUT)/sbom-metadata.csv >/dev/null 2>&1)
-$(PRODUCT_OUT)/sbom-metadata.csv: $(installed_files)
+$(PRODUCT_OUT)/sbom-metadata.csv: $(installed_files) $(metadata_list) $(metadata_files)
rm -f $@
echo installed_file,module_path,soong_module_type,is_prebuilt_make_module,product_copy_files,kernel_module_copy_files,is_platform_generated,build_output_path,static_libraries,whole_static_libraries,is_static_lib >> $@
$(eval _all_static_libs :=)
@@ -2184,7 +2197,9 @@
$(eval _is_fsverity_build_manifest_apk := $(if $(findstring $f,$(ALL_FSVERITY_BUILD_MANIFEST_APK)),Y)) \
$(eval _is_linker_config := $(if $(findstring $f,$(SYSTEM_LINKER_CONFIG) $(vendor_linker_config_file)),Y)) \
$(eval _is_partition_compat_symlink := $(if $(findstring $f,$(PARTITION_COMPAT_SYMLINKS)),Y)) \
- $(eval _is_platform_generated := $(_is_build_prop)$(_is_notice_file)$(_is_dexpreopt_image_profile)$(_is_product_system_other_avbkey)$(_is_event_log_tags_file)$(_is_system_other_odex_marker)$(_is_kernel_modules_blocklist)$(_is_fsverity_build_manifest_apk)$(_is_linker_config)$(_is_partition_compat_symlink)) \
+ $(eval _is_flags_file := $(if $(findstring $f, $(ALL_FLAGS_FILES)),Y)) \
+ $(eval _is_rootdir_symlink := $(if $(findstring $f, $(ALL_ROOTDIR_SYMLINKS)),Y)) \
+ $(eval _is_platform_generated := $(_is_build_prop)$(_is_notice_file)$(_is_dexpreopt_image_profile)$(_is_product_system_other_avbkey)$(_is_event_log_tags_file)$(_is_system_other_odex_marker)$(_is_kernel_modules_blocklist)$(_is_fsverity_build_manifest_apk)$(_is_linker_config)$(_is_partition_compat_symlink)$(_is_flags_file)$(_is_rootdir_symlink)) \
$(eval _static_libs := $(ALL_INSTALLED_FILES.$f.STATIC_LIBRARIES)) \
$(eval _whole_static_libs := $(ALL_INSTALLED_FILES.$f.WHOLE_STATIC_LIBRARIES)) \
$(foreach l,$(_static_libs),$(eval _all_static_libs += $l:$(strip $(sort $(ALL_MODULES.$l.PATH))):$(strip $(sort $(ALL_MODULES.$l.SOONG_MODULE_TYPE))):$(ALL_STATIC_LIBRARIES.$l.BUILT_FILE))) \
@@ -2215,17 +2230,47 @@
$(call dist-for-goals,droid,$(PRODUCT_OUT)/sbom.spdx.json:sbom/sbom.spdx.json)
else
-apps_only_sbom_files := $(sort $(patsubst %,%.spdx.json,$(filter %.apk,$(apps_only_installed_files))))
-$(apps_only_sbom_files): $(PRODUCT_OUT)/sbom-metadata.csv $(GEN_SBOM)
- rm -rf $@
- $(GEN_SBOM) --output_file $@ --metadata $(PRODUCT_OUT)/sbom-metadata.csv --build_version $(BUILD_FINGERPRINT_FROM_FILE) --product_mfr "$(PRODUCT_MANUFACTURER)" --unbundled_apk
+# Create build rules for generating SBOMs of unbundled APKs and APEXs
+# $1: sbom file
+# $2: sbom fragment file
+# $3: installed file
+# $4: sbom-metadata.csv file
+define generate-app-sbom
+$(eval _path_on_device := $(patsubst $(PRODUCT_OUT)/%,%,$(3)))
+$(eval _module_name := $(ALL_INSTALLED_FILES.$(3)))
+$(eval _module_path := $(strip $(sort $(ALL_MODULES.$(_module_name).PATH))))
+$(eval _soong_module_type := $(strip $(sort $(ALL_MODULES.$(_module_name).SOONG_MODULE_TYPE))))
+$(eval _dep_modules := $(filter %.$(_module_name),$(ALL_MODULES)) $(filter %.$(_module_name)$(TARGET_2ND_ARCH_MODULE_SUFFIX),$(ALL_MODULES)))
+$(eval _is_apex := $(filter %.apex,$(3)))
+
+$(4): $(3) $(metadata_list) $(metadata_files)
+ rm -rf $$@
+ echo installed_file,module_path,soong_module_type,is_prebuilt_make_module,product_copy_files,kernel_module_copy_files,is_platform_generated,build_output_path,static_libraries,whole_static_libraries,is_static_lib >> $$@
+ echo /$(_path_on_device),$(_module_path),$(_soong_module_type),,,,,$(3),,, >> $$@
+ $(if $(filter %.apex,$(3)),\
+ $(foreach m,$(_dep_modules),\
+ echo $(patsubst $(PRODUCT_OUT)/apex/$(_module_name)/%,%,$(ALL_MODULES.$m.INSTALLED)),$(sort $(ALL_MODULES.$m.PATH)),$(sort $(ALL_MODULES.$m.SOONG_MODULE_TYPE)),,,,,$(strip $(ALL_MODULES.$m.BUILT)),,, >> $$@;))
+
+$(2): $(1)
+$(1): $(4) $(GEN_SBOM)
+ rm -rf $$@
+ $(GEN_SBOM) --output_file $$@ --metadata $(4) --build_version $$(BUILD_FINGERPRINT_FROM_FILE) --product_mfr "$(PRODUCT_MANUFACTURER)" --json $(if $(filter %.apk,$(3)),--unbundled_apk,--unbundled_apex)
+endef
+
+apps_only_sbom_files :=
+apps_only_fragment_files :=
+$(foreach f,$(filter %.apk %.apex,$(installed_files)), \
+ $(eval _metadata_csv_file := $(patsubst %,%-sbom-metadata.csv,$f)) \
+ $(eval _sbom_file := $(patsubst %,%.spdx.json,$f)) \
+ $(eval _fragment_file := $(patsubst %,%-fragment.spdx,$f)) \
+ $(eval apps_only_sbom_files += $(_sbom_file)) \
+ $(eval apps_only_fragment_files += $(_fragment_file)) \
+ $(eval $(call generate-app-sbom,$(_sbom_file),$(_fragment_file),$f,$(_metadata_csv_file))) \
+)
sbom: $(apps_only_sbom_files)
-$(foreach f,$(apps_only_sbom_files),$(eval $(patsubst %.spdx.json,%-fragment.spdx,$f): $f))
-apps_only_fragment_files := $(patsubst %.spdx.json,%-fragment.spdx,$(apps_only_sbom_files))
$(foreach f,$(apps_only_fragment_files),$(eval apps_only_fragment_dist_files += :sbom/$(notdir $f)))
-
$(foreach f,$(apps_only_sbom_files),$(eval apps_only_sbom_dist_files += :sbom/$(notdir $f)))
$(call dist-for-goals,apps_only,$(join $(apps_only_sbom_files),$(apps_only_sbom_dist_files)) $(join $(apps_only_fragment_files),$(apps_only_fragment_dist_files)))
endif
diff --git a/core/package_internal.mk b/core/package_internal.mk
index 7cfab5b..a03a62b 100644
--- a/core/package_internal.mk
+++ b/core/package_internal.mk
@@ -531,7 +531,7 @@
$(LOCAL_BUILT_MODULE): PRIVATE_RES_PACKAGE := $(my_res_package)
$(LOCAL_BUILT_MODULE) : $(my_res_package) $(AAPT2)
ifdef LOCAL_COMPRESSED_MODULE
-$(LOCAL_BUILT_MODULE) : $(MINIGZIP)
+$(LOCAL_BUILT_MODULE) : $(GZIP)
endif
ifeq (true, $(LOCAL_UNCOMPRESS_DEX))
$(LOCAL_BUILT_MODULE) : $(ZIP2ZIP)
diff --git a/core/packaging/flags.mk b/core/packaging/flags.mk
new file mode 100644
index 0000000..697fe24
--- /dev/null
+++ b/core/packaging/flags.mk
@@ -0,0 +1,123 @@
+# Copyright (C) 2023 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 is included by build/make/core/Makefile, and contains the logic for
+# the combined flags files.
+#
+
+# TODO: Should we do all of the images in $(IMAGES_TO_BUILD)?
+_FLAG_PARTITIONS := product system system_ext vendor
+
+
+# -----------------------------------------------------------------
+# Release Config Flags
+
+# Create a summary file of build flags for each partition
+# $(1): built build flags json file
+# $(2): installed build flags json file
+# $(3): flag names
+define generate-partition-build-flag-file
+$(eval $(strip $(1)): PRIVATE_OUT := $(strip $(1)))
+$(eval $(strip $(1)): PRIVATE_FLAG_NAMES := $(strip $(3)))
+$(strip $(1)):
+ mkdir -p $$(dir $$(PRIVATE_OUT))
+ echo '{' > $$(PRIVATE_OUT)
+ echo '"flags": [' >> $$(PRIVATE_OUT)
+ $$(foreach flag, $$(PRIVATE_FLAG_NAMES), \
+ ( \
+ printf ' { "name": "%s", "value": "%s", ' \
+ '$$(flag)' \
+ '$$(_ALL_RELEASE_FLAGS.$$(flag).VALUE)' \
+ ; \
+ printf '"set": "%s", "default": "%s", "declared": "%s" }' \
+ '$$(_ALL_RELEASE_FLAGS.$$(flag).SET_IN)' \
+ '$$(_ALL_RELEASE_FLAGS.$$(flag).DEFAULT)' \
+ '$$(_ALL_RELEASE_FLAGS.$$(flag).DECLARED_IN)' \
+ ; \
+ printf '$$(if $$(filter $$(lastword $$(PRIVATE_FLAG_NAMES)),$$(flag)),,$$(comma))\n' ; \
+ ) >> $$(PRIVATE_OUT) ; \
+ )
+ echo "]" >> $$(PRIVATE_OUT)
+ echo "}" >> $$(PRIVATE_OUT)
+$(call copy-one-file, $(1), $(2))
+endef
+
+$(foreach partition, $(_FLAG_PARTITIONS), \
+ $(eval build_flag_summaries.$(partition) := $(PRODUCT_OUT)/$(partition)/etc/build_flags.json) \
+ $(eval $(call generate-partition-build-flag-file, \
+ $(TARGET_OUT_FLAGS)/$(partition)/build_flags.json, \
+ $(build_flag_summaries.$(partition)), \
+ $(_ALL_RELEASE_FLAGS.PARTITIONS.$(partition)) \
+ ) \
+ ) \
+)
+
+
+# -----------------------------------------------------------------
+# Aconfig Flags
+
+# Create a summary file of build flags for each partition
+# $(1): built aconfig flags textprot file (out)
+# $(2): installed aconfig flags textprot file (out)
+# $(3): input aconfig files for the partition (in)
+define generate-partition-aconfig-flag-file
+$(eval $(strip $(1)): PRIVATE_OUT := $(strip $(1)))
+$(eval $(strip $(1)): PRIVATE_IN := $(strip $(3)))
+$(strip $(1)): $(ACONFIG) $(strip $(3))
+ mkdir -p $$(dir $$(PRIVATE_OUT))
+ $$(if $$(PRIVATE_IN), \
+ $$(ACONFIG) dump --format textproto --out $$(PRIVATE_OUT) \
+ $$(addprefix --cache ,$$(PRIVATE_IN)), \
+ echo "# No aconfig flags" > $$(PRIVATE_OUT) \
+ )
+$(call copy-one-file, $(1), $(2))
+endef
+
+
+$(foreach partition, $(_FLAG_PARTITIONS), \
+ $(eval aconfig_flag_summaries.$(partition) := $(PRODUCT_OUT)/$(partition)/etc/aconfig_flags.textproto) \
+ $(eval $(call generate-partition-aconfig-flag-file, \
+ $(TARGET_OUT_FLAGS)/$(partition)/aconfig_flags.textproto, \
+ $(aconfig_flag_summaries.$(partition)), \
+ $(sort $(foreach m,$(call register-names-for-partition, $(partition)), \
+ $(ALL_MODULES.$(m).ACONFIG_FILES) \
+ )) \
+ )) \
+)
+
+
+# -----------------------------------------------------------------
+# Install the ones we need for the configured product
+required_flags_files := \
+ $(sort $(foreach partition, $(filter $(IMAGES_TO_BUILD), $(_FLAG_PARTITIONS)), \
+ $(build_flag_summaries.$(partition)) \
+ $(aconfig_flag_summaries.$(partition)) \
+ ))
+
+ALL_DEFAULT_INSTALLED_MODULES += $(required_flags_files)
+ALL_FLAGS_FILES := $(required_flags_files)
+
+# TODO: Remove
+.PHONY: flag-files
+flag-files: $(required_flags_files)
+
+
+# Clean up
+required_flags_files:=
+$(foreach partition, $(_FLAG_PARTITIONS), \
+ $(eval build_flag_summaries.$(partition):=) \
+ $(eval aconfig_flag_summaries.$(partition):=) \
+)
+
diff --git a/core/product.mk b/core/product.mk
index c29cf8a..54e3695 100644
--- a/core/product.mk
+++ b/core/product.mk
@@ -33,6 +33,10 @@
# 4096, 16384 and 65536.
_product_single_value_vars += PRODUCT_MAX_PAGE_SIZE_SUPPORTED
+# Indicates that AOSP can use a kernel configured with 4k/16k/64k page sizes.
+# The possible values are true or false.
+_product_single_value_vars += PRODUCT_PAGE_SIZE_AGNOSTIC
+
# The resource configuration options to use for this product.
_product_list_vars += PRODUCT_LOCALES
_product_list_vars += PRODUCT_AAPT_CONFIG
@@ -153,6 +157,9 @@
# PRODUCT_BOOT_JARS, so that device-specific jars go after common jars.
_product_list_vars += PRODUCT_BOOT_JARS_EXTRA
+# List of jars to be included in the ART boot image for testing.
+_product_list_vars += PRODUCT_TEST_ONLY_ART_BOOT_IMAGE_JARS
+
_product_single_value_vars += PRODUCT_SUPPORTS_VBOOT
_product_list_vars += PRODUCT_SYSTEM_SERVER_APPS
# List of system_server classpath jars on the platform.
@@ -324,6 +331,10 @@
_product_list_vars += PRODUCT_PACKAGE_NAME_OVERRIDES
_product_list_vars += PRODUCT_CERTIFICATE_OVERRIDES
+# Overrides the (apex, jar) pairs above when determining the on-device location. The format is:
+# <old_apex>:<old_jar>:<new_apex>:<new_jar>
+_product_list_vars += PRODUCT_CONFIGURED_JAR_LOCATION_OVERRIDES
+
# Controls for whether different partitions are built for the current product.
_product_single_value_vars += PRODUCT_BUILD_SYSTEM_IMAGE
_product_single_value_vars += PRODUCT_BUILD_SYSTEM_OTHER_IMAGE
@@ -426,6 +437,9 @@
# specified we default to COW version 2 in update_engine for backwards compatibility
_product_single_value_vars += PRODUCT_VIRTUAL_AB_COW_VERSION
+# If set, determines whether the build system checks vendor seapp contexts violations.
+_product_single_value_vars += PRODUCT_CHECK_VENDOR_SEAPP_VIOLATIONS
+
_product_list_vars += PRODUCT_AFDO_PROFILES
.KATI_READONLY := _product_single_value_vars _product_list_vars
diff --git a/core/product_config.mk b/core/product_config.mk
index ad13269..9f0cf25 100644
--- a/core/product_config.mk
+++ b/core/product_config.mk
@@ -575,6 +575,32 @@
$(PRODUCT_ENFORCE_RRO_EXEMPTED_TARGETS))
endif
+# Get the board API level.
+board_api_level := $(PLATFORM_SDK_VERSION)
+ifdef BOARD_API_LEVEL
+ board_api_level := $(BOARD_API_LEVEL)
+else ifdef BOARD_SHIPPING_API_LEVEL
+ # Vendors with GRF must define BOARD_SHIPPING_API_LEVEL for the vendor API level.
+ board_api_level := $(BOARD_SHIPPING_API_LEVEL)
+endif
+
+# Calculate the VSR vendor API level.
+VSR_VENDOR_API_LEVEL := $(board_api_level)
+
+ifdef PRODUCT_SHIPPING_API_LEVEL
+ VSR_VENDOR_API_LEVEL := $(call math_min,$(PRODUCT_SHIPPING_API_LEVEL),$(board_api_level))
+endif
+.KATI_READONLY := VSR_VENDOR_API_LEVEL
+
+# Boolean variable determining if vendor seapp contexts is enforced
+CHECK_VENDOR_SEAPP_VIOLATIONS := false
+ifneq ($(call math_gt,$(VSR_VENDOR_API_LEVEL),34),)
+ CHECK_VENDOR_SEAPP_VIOLATIONS := true
+else ifneq ($(PRODUCT_CHECK_VENDOR_SEAPP_VIOLATIONS),)
+ CHECK_VENDOR_SEAPP_VIOLATIONS := $(PRODUCT_CHECK_VENDOR_SEAPP_VIOLATIONS)
+endif
+.KATI_READONLY := CHECK_VENDOR_SEAPP_VIOLATIONS
+
define product-overrides-config
$$(foreach rule,$$(PRODUCT_$(1)_OVERRIDES),\
$$(if $$(filter 2,$$(words $$(subst :,$$(space),$$(rule)))),,\
diff --git a/core/proguard_basic_keeps.flags b/core/proguard_basic_keeps.flags
index b59527a..f6b34b8 100644
--- a/core/proguard_basic_keeps.flags
+++ b/core/proguard_basic_keeps.flags
@@ -10,6 +10,12 @@
# and RuntimeVisibleTypeAnnotations, as well as associated defaults.
-keepattributes RuntimeVisible*Annotation*,AnnotationDefault
+# With R8 full mode, certain attributes are only kept when matched with an
+# explicit keep rule for that target, even with a global -keepattributes rule.
+# As such, we can add the global keep rule here with minimal cost while
+# simplifying incremental development.
+-keepattributes Exceptions
+
# For enumeration classes, see http://proguard.sourceforge.net/manual/examples.html#enumerations
-keepclassmembers enum * {
public static **[] values();
diff --git a/core/release_config.mk b/core/release_config.mk
index b72ee89..4f9daaf 100644
--- a/core/release_config.mk
+++ b/core/release_config.mk
@@ -76,6 +76,12 @@
ifeq ($(filter $(_all_release_configs), $(TARGET_RELEASE)),)
$(error No release config found for TARGET_RELEASE: $(TARGET_RELEASE). Available releases are: $(_all_release_configs))
else
+# TODO(b/294161396): Remove this logic
+ifeq ($(TARGET_RELEASE),next)
+ifndef TESTING_TARGET_RELEASE_NEXT
+ $(error "next" releases are not supported yet. b/294161396)
+endif
+endif
# Choose flag files
# Don't sort this, use it in the order they gave us.
flag_value_files := $(_all_release_configs.$(TARGET_RELEASE).FILES)
diff --git a/core/rust_device_benchmark_config_template.xml b/core/rust_device_benchmark_config_template.xml
index 2055df2..541630c 100644
--- a/core/rust_device_benchmark_config_template.xml
+++ b/core/rust_device_benchmark_config_template.xml
@@ -16,7 +16,7 @@
<!-- This test config file is auto-generated. -->
<configuration description="Config to run {MODULE} rust benchmark tests.">
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
- <option name="cleanup" value="false" />
+ <option name="cleanup" value="true" />
<option name="push" value="{MODULE}->/data/local/tmp/{MODULE}" />
</target_preparer>
diff --git a/core/soong_app_prebuilt.mk b/core/soong_app_prebuilt.mk
index ccc5449..593dfa0 100644
--- a/core/soong_app_prebuilt.mk
+++ b/core/soong_app_prebuilt.mk
@@ -73,12 +73,14 @@
# We skip it for unbundled app builds where we cannot build veridex.
module_run_appcompat :=
ifeq (true,$(non_system_module))
-ifeq (,$(TARGET_BUILD_APPS)) # ! unbundled app build
+ifeq (,$(TARGET_BUILD_APPS)) # not unbundled app build
+ifeq (,$(filter sdk,$(MAKECMDGOALS))) # not sdk build (which is another form of unbundled build)
ifneq ($(UNSAFE_DISABLE_HIDDENAPI_FLAGS),true)
module_run_appcompat := true
endif
endif
endif
+endif
ifeq ($(module_run_appcompat),true)
$(LOCAL_BUILT_MODULE): $(appcompat-files)
diff --git a/core/soong_config.mk b/core/soong_config.mk
index 0d5799c..7d8092d 100644
--- a/core/soong_config.mk
+++ b/core/soong_config.mk
@@ -40,6 +40,7 @@
$(call add_json_str, Platform_base_os, $(PLATFORM_BASE_OS))
$(call add_json_str, Platform_version_last_stable, $(PLATFORM_VERSION_LAST_STABLE))
$(call add_json_str, Platform_version_known_codenames, $(PLATFORM_VERSION_KNOWN_CODENAMES))
+$(call add_json_bool, Release_aidl_use_unfrozen, $(RELEASE_AIDL_USE_UNFROZEN))
$(call add_json_str, Platform_min_supported_target_sdk_version, $(PLATFORM_MIN_SUPPORTED_TARGET_SDK_VERSION))
@@ -150,6 +151,7 @@
$(call add_json_bool, Malloc_pattern_fill_contents, $(MALLOC_PATTERN_FILL_CONTENTS))
$(call add_json_str, Override_rs_driver, $(OVERRIDE_RS_DRIVER))
$(call add_json_str, DeviceMaxPageSizeSupported, $(TARGET_MAX_PAGE_SIZE_SUPPORTED))
+$(call add_json_bool, DevicePageSizeAgnostic, $(filter true,$(TARGET_PAGE_SIZE_AGNOSTIC)))
$(call add_json_bool, UncompressPrivAppDex, $(call invert_bool,$(filter true,$(DONT_UNCOMPRESS_PRIV_APPS_DEXS))))
$(call add_json_list, ModulesLoadedByPrivilegedModules, $(PRODUCT_LOADED_BY_PRIVILEGED_MODULES))
@@ -235,6 +237,7 @@
$(call add_json_list, ManifestPackageNameOverrides, $(PRODUCT_MANIFEST_PACKAGE_NAME_OVERRIDES))
$(call add_json_list, PackageNameOverrides, $(PRODUCT_PACKAGE_NAME_OVERRIDES))
$(call add_json_list, CertificateOverrides, $(PRODUCT_CERTIFICATE_OVERRIDES))
+$(call add_json_list, ConfiguredJarLocationOverrides, $(PRODUCT_CONFIGURED_JAR_LOCATION_OVERRIDES))
$(call add_json_str, ApexGlobalMinSdkVersionOverride, $(APEX_GLOBAL_MIN_SDK_VERSION_OVERRIDE))
@@ -317,6 +320,11 @@
$(call add_json_str, ReleaseVersion, $(_RELEASE_VERSION))
$(call add_json_list, ReleaseAconfigValueSets, $(RELEASE_ACONFIG_VALUE_SETS))
+$(call add_json_str, ReleaseAconfigFlagDefaultPermission, $(RELEASE_ACONFIG_FLAG_DEFAULT_PERMISSION))
+
+$(call add_json_bool, KeepVndk, $(filter true,$(KEEP_VNDK)))
+
+$(call add_json_bool, CheckVendorSeappViolations, $(filter true,$(CHECK_VENDOR_SEAPP_VIOLATIONS)))
$(call json_end)
diff --git a/core/soong_java_prebuilt.mk b/core/soong_java_prebuilt.mk
index a8f475f..c7c6a11 100644
--- a/core/soong_java_prebuilt.mk
+++ b/core/soong_java_prebuilt.mk
@@ -99,6 +99,17 @@
$(call add-dependency,$(LOCAL_BUILT_MODULE),$(my_res_package))
+ my_transitive_res_packages := $(intermediates.COMMON)/transitive-res-packages
+ $(my_transitive_res_packages): PRIVATE_TRANSITIVE_RES_PACKAGES := $(filter-out $(LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE),$(LOCAL_SOONG_TRANSITIVE_RES_PACKAGES))
+ $(my_transitive_res_packages):
+ @echo Write transitive resource package list $@
+ rm -f $@
+ touch $@
+ $(foreach f,$(PRIVATE_TRANSITIVE_RES_PACKAGES),\
+ echo "$f" >> $@; )
+
+ $(call add-dependency,$(my_res_package),$(my_transitive_res_packages))
+
my_proguard_flags := $(intermediates.COMMON)/export_proguard_flags
$(my_proguard_flags): $(LOCAL_SOONG_EXPORT_PROGUARD_FLAGS)
@echo "Export proguard flags: $@"
diff --git a/core/static_java_library.mk b/core/static_java_library.mk
index 4053985..4a72a1f 100644
--- a/core/static_java_library.mk
+++ b/core/static_java_library.mk
@@ -127,6 +127,12 @@
endif
endif
+# transitive-res-packages is only populated for Soong modules for now, but needs
+# to exist so that other Make modules can depend on it. Create an empty file.
+my_transitive_res_packages := $(intermediates.COMMON)/transitive-res-packages
+$(my_transitive_res_packages):
+ touch $@
+
import_proguard_flag_files := $(strip $(foreach l,$(LOCAL_STATIC_ANDROID_LIBRARIES) $(LOCAL_STATIC_JAVA_AAR_LIBRARIES),\
$(call intermediates-dir-for,JAVA_LIBRARIES,$(l),,COMMON)/export_proguard_flags))
$(intermediates.COMMON)/export_proguard_flags: $(import_proguard_flag_files) $(addprefix $(LOCAL_PATH)/,$(LOCAL_EXPORT_PROGUARD_FLAG_FILES))
diff --git a/core/sysprop.mk b/core/sysprop.mk
index a2296a8..4536e5f 100644
--- a/core/sysprop.mk
+++ b/core/sysprop.mk
@@ -47,9 +47,21 @@
echo "ro.product.$(1).model=$(PRODUCT_MODEL)" >> $(2);\
echo "ro.product.$(1).name=$(TARGET_PRODUCT)" >> $(2);\
# Attestation specific properties for AOSP/GSI build running on device.
- echo "ro.product.model_for_attestation=$(PRODUCT_MODEL_FOR_ATTESTATION)" >> $(2);\
- echo "ro.product.brand_for_attestation=$(PRODUCT_BRAND_FOR_ATTESTATION)" >> $(2);\
- echo "ro.product.name_for_attestation=$(PRODUCT_NAME_FOR_ATTESTATION)" >> $(2);\
+ if [ -n "$(strip $(PRODUCT_MODEL_FOR_ATTESTATION))" ]; then \
+ echo "ro.product.model_for_attestation=$(PRODUCT_MODEL_FOR_ATTESTATION)" >> $(2);\
+ fi; \
+ if [ -n "$(strip $(PRODUCT_BRAND_FOR_ATTESTATION))" ]; then \
+ echo "ro.product.brand_for_attestation=$(PRODUCT_BRAND_FOR_ATTESTATION)" >> $(2);\
+ fi; \
+ if [ -n "$(strip $(PRODUCT_NAME_FOR_ATTESTATION))" ]; then \
+ echo "ro.product.name_for_attestation=$(PRODUCT_NAME_FOR_ATTESTATION)" >> $(2);\
+ fi; \
+ if [ -n "$(strip $(PRODUCT_DEVICE_FOR_ATTESTATION))" ]; then \
+ echo "ro.product.device_for_attestation=$(PRODUCT_DEVICE_FOR_ATTESTATION)" >> $(2);\
+ fi; \
+ if [ -n "$(strip $(PRODUCT_MANUFACTURER_FOR_ATTESTATION))" ]; then \
+ echo "ro.product.manufacturer_for_attestation=$(PRODUCT_MANUFACTURER_FOR_ATTESTATION)" >> $(2);\
+ fi; \
)\
$(if $(filter true,$(ZYGOTE_FORCE_64)),\
$(if $(filter vendor,$(1)),\
@@ -66,9 +78,12 @@
)\
echo "ro.$(1).build.date=`$(DATE_FROM_FILE)`" >> $(2);\
echo "ro.$(1).build.date.utc=`$(DATE_FROM_FILE) +%s`" >> $(2);\
- echo "ro.$(1).build.fingerprint=$(BUILD_FINGERPRINT_FROM_FILE)" >> $(2);\
- echo "ro.$(1).build.id=$(BUILD_ID)" >> $(2);\
- echo "ro.$(1).build.tags=$(BUILD_VERSION_TAGS)" >> $(2);\
+ # Allow optional assignments for ARC forward-declarations (b/249168657)
+ # TODO: Remove any tag-related inconsistencies once the goals from
+ # go/arc-android-sigprop-changes have been achieved.
+ echo "ro.$(1).build.fingerprint?=$(BUILD_FINGERPRINT_FROM_FILE)" >> $(2);\
+ echo "ro.$(1).build.id?=$(BUILD_ID)" >> $(2);\
+ echo "ro.$(1).build.tags?=$(BUILD_VERSION_TAGS)" >> $(2);\
echo "ro.$(1).build.type=$(TARGET_BUILD_VARIANT)" >> $(2);\
echo "ro.$(1).build.version.incremental=$(BUILD_NUMBER_FROM_FILE)" >> $(2);\
echo "ro.$(1).build.version.release=$(PLATFORM_VERSION_LAST_STABLE)" >> $(2);\
@@ -565,4 +580,4 @@
# $1 installed file path, e.g. out/target/product/vsoc_x86_64/system/build.prop
define is-build-prop
$(if $(findstring $1,$(ALL_INSTALLED_BUILD_PROP_FILES)),Y)
-endef
\ No newline at end of file
+endef
diff --git a/core/tasks/art-host-tests.mk b/core/tasks/art-host-tests.mk
index ff9eb09..c95f6e7 100644
--- a/core/tasks/art-host-tests.mk
+++ b/core/tasks/art-host-tests.mk
@@ -50,7 +50,8 @@
grep $(TARGET_OUT_TESTCASES) $(PRIVATE_INTERMEDIATES_DIR)/list > $(PRIVATE_INTERMEDIATES_DIR)/target.list || true
$(hide) $(SOONG_ZIP) -d -o $@ -P host -C $(HOST_OUT) -l $(PRIVATE_INTERMEDIATES_DIR)/host.list \
-P target -C $(PRODUCT_OUT) -l $(PRIVATE_INTERMEDIATES_DIR)/target.list \
- -P host/testcases -C $(HOST_OUT) -l $(PRIVATE_INTERMEDIATES_DIR)/shared-libs.list
+ -P host/testcases -C $(HOST_OUT) -l $(PRIVATE_INTERMEDIATES_DIR)/shared-libs.list \
+ -sha256
grep -e .*\\.config$$ $(PRIVATE_INTERMEDIATES_DIR)/host.list > $(PRIVATE_INTERMEDIATES_DIR)/host-test-configs.list || true
grep -e .*\\.config$$ $(PRIVATE_INTERMEDIATES_DIR)/target.list > $(PRIVATE_INTERMEDIATES_DIR)/target-test-configs.list || true
$(hide) $(SOONG_ZIP) -d -o $(PRIVATE_art_host_tests_configs_zip) \
diff --git a/core/tasks/cts.mk b/core/tasks/cts.mk
index c8b1183..593b7b6 100644
--- a/core/tasks/cts.mk
+++ b/core/tasks/cts.mk
@@ -37,16 +37,18 @@
cts_platform_release_path := cts/tests/tests/os/assets/platform_releases.txt
cts_platform_release_string := $(shell cat $(cts_platform_release_path))
- ifeq (,$(findstring $(PLATFORM_VERSION),$(cts_platform_version_string)))
- define error_msg
- ============================================================
- Could not find version "$(PLATFORM_VERSION)" in CTS platform version file:
- $(cts_platform_version_path)
- Most likely PLATFORM_VERSION in build/core/version_defaults.mk
- has changed and a new version must be added to this CTS file.
- ============================================================
- endef
- $(error $(error_msg))
+ ifeq ($(RELEASE_PLATFORM_VERSION_CODENAME_REL),)
+ ifeq (,$(findstring $(PLATFORM_VERSION),$(cts_platform_version_string)))
+ define error_msg
+ ============================================================
+ Could not find version "$(PLATFORM_VERSION)" in CTS platform version file:
+ $(cts_platform_version_path)
+ Most likely PLATFORM_VERSION in build/core/version_defaults.mk
+ has changed and a new version must be added to this CTS file.
+ ============================================================
+ endef
+ $(error $(error_msg))
+ endif
endif
ifeq (,$(findstring $(PLATFORM_VERSION_LAST_STABLE),$(cts_platform_release_string)))
define error_msg
diff --git a/core/tasks/module-info.mk b/core/tasks/module-info.mk
index 66ba8f1..9668b53 100644
--- a/core/tasks/module-info.mk
+++ b/core/tasks/module-info.mk
@@ -2,40 +2,40 @@
# Currently runtime_dependencies only include the runtime libs information for cc binaries.
MODULE_INFO_JSON := $(PRODUCT_OUT)/module-info.json
+COMMA := ,
+_NEWLINE := '\n'
$(MODULE_INFO_JSON):
@echo Generating $@
$(hide) echo -ne '{\n ' > $@
- $(hide) echo -ne $(foreach m, $(sort $(ALL_MODULES)), \
- ' "$(m)": {' \
- '"class": [$(foreach w,$(sort $(ALL_MODULES.$(m).CLASS)),"$(w)", )], ' \
- '"path": [$(foreach w,$(sort $(ALL_MODULES.$(m).PATH)),"$(w)", )], ' \
- '"tags": [$(foreach w,$(sort $(ALL_MODULES.$(m).TAGS)),"$(w)", )], ' \
- '"installed": [$(foreach w,$(sort $(ALL_MODULES.$(m).INSTALLED)),"$(w)", )], ' \
- '"compatibility_suites": [$(foreach w,$(sort $(ALL_MODULES.$(m).COMPATIBILITY_SUITES)),"$(w)", )], ' \
- '"auto_test_config": [$(ALL_MODULES.$(m).auto_test_config)], ' \
- '"module_name": "$(ALL_MODULES.$(m).MODULE_NAME)", ' \
- '"test_config": [$(foreach w,$(strip $(ALL_MODULES.$(m).TEST_CONFIG) $(ALL_MODULES.$(m).EXTRA_TEST_CONFIGS)),"$(w)", )], ' \
- '"dependencies": [$(foreach w,$(sort $(ALL_DEPS.$(m).ALL_DEPS)),"$(w)", )], ' \
- '"shared_libs": [$(foreach w,$(sort $(ALL_MODULES.$(m).SHARED_LIBS)),"$(w)", )], ' \
- '"static_libs": [$(foreach w,$(sort $(ALL_MODULES.$(m).STATIC_LIBS)),"$(w)", )], ' \
- '"system_shared_libs": [$(foreach w,$(sort $(ALL_MODULES.$(m).SYSTEM_SHARED_LIBS)),"$(w)", )], ' \
- '"srcs": [$(foreach w,$(sort $(ALL_MODULES.$(m).SRCS)),"$(w)", )], ' \
- '"srcjars": [$(foreach w,$(sort $(ALL_MODULES.$(m).SRCJARS)),"$(w)", )], ' \
- '"classes_jar": [$(foreach w,$(sort $(ALL_MODULES.$(m).CLASSES_JAR)),"$(w)", )], ' \
- '"test_mainline_modules": [$(foreach w,$(sort $(ALL_MODULES.$(m).TEST_MAINLINE_MODULES)),"$(w)", )], ' \
- '"is_unit_test": "$(ALL_MODULES.$(m).IS_UNIT_TEST)", ' \
- '"test_options_tags": [$(foreach w,$(sort $(ALL_MODULES.$(m).TEST_OPTIONS_TAGS)),"$(w)", )], ' \
- '"data": [$(foreach w,$(sort $(ALL_MODULES.$(m).TEST_DATA)),"$(w)", )], ' \
- '"runtime_dependencies": [$(foreach w,$(sort $(ALL_MODULES.$(m).LOCAL_RUNTIME_LIBRARIES)),"$(w)", )], ' \
- '"static_dependencies": [$(foreach w,$(sort $(ALL_MODULES.$(m).LOCAL_STATIC_LIBRARIES)),"$(w)", )], ' \
- '"data_dependencies": [$(foreach w,$(sort $(ALL_MODULES.$(m).TEST_DATA_BINS)),"$(w)", )], ' \
- '"supported_variants": [$(foreach w,$(sort $(ALL_MODULES.$(m).SUPPORTED_VARIANTS)),"$(w)", )], ' \
- '"host_dependencies": [$(foreach w,$(sort $(ALL_MODULES.$(m).HOST_REQUIRED_FROM_TARGET)),"$(w)", )], ' \
- '"target_dependencies": [$(foreach w,$(sort $(ALL_MODULES.$(m).TARGET_REQUIRED_FROM_HOST)),"$(w)", )], ' \
- '},\n' \
- ) | sed -e 's/, *\]/]/g' -e 's/, *\}/ }/g' -e '$$s/,$$//' >> $@
- $(hide) echo '}' >> $@
+ $(hide) echo -ne $(KATI_foreach_sep m,$(COMMA)$(_NEWLINE), $(sort $(ALL_MODULES)),\
+ '"$(m)": {' \
+ '"class": [$(KATI_foreach_sep w,$(COMMA) ,$(sort $(ALL_MODULES.$(m).CLASS)),"$(w)")],' \
+ '"path": [$(KATI_foreach_sep w,$(COMMA) ,$(sort $(ALL_MODULES.$(m).PATH)),"$(w)")],' \
+ '"tags": [$(KATI_foreach_sep w,$(COMMA) ,$(sort $(ALL_MODULES.$(m).TAGS)),"$(w)")],' \
+ '"installed": [$(KATI_foreach_sep w,$(COMMA) ,$(sort $(ALL_MODULES.$(m).INSTALLED)),"$(w)")],' \
+ '"compatibility_suites": [$(KATI_foreach_sep w,$(COMMA) ,$(sort $(ALL_MODULES.$(m).COMPATIBILITY_SUITES)),"$(w)")],' \
+ '"auto_test_config": [$(ALL_MODULES.$(m).auto_test_config)],' \
+ '"module_name": "$(ALL_MODULES.$(m).MODULE_NAME)"$(COMMA)' \
+ '"test_config": [$(KATI_foreach_sep w,$(COMMA) ,$(strip $(ALL_MODULES.$(m).TEST_CONFIG) $(ALL_MODULES.$(m).EXTRA_TEST_CONFIGS)),"$(w)")],' \
+ '"dependencies": [$(KATI_foreach_sep w,$(COMMA) ,$(sort $(ALL_DEPS.$(m).ALL_DEPS)),"$(w)")],' \
+ '"shared_libs": [$(KATI_foreach_sep w,$(COMMA) ,$(sort $(ALL_MODULES.$(m).SHARED_LIBS)),"$(w)")],' \
+ '"static_libs": [$(KATI_foreach_sep w,$(COMMA) ,$(sort $(ALL_MODULES.$(m).STATIC_LIBS)),"$(w)")],' \
+ '"system_shared_libs": [$(KATI_foreach_sep w,$(COMMA) ,$(sort $(ALL_MODULES.$(m).SYSTEM_SHARED_LIBS)),"$(w)")],' \
+ '"srcs": [$(KATI_foreach_sep w,$(COMMA) ,$(sort $(ALL_MODULES.$(m).SRCS)),"$(w)")],' \
+ '"srcjars": [$(KATI_foreach_sep w,$(COMMA) ,$(sort $(ALL_MODULES.$(m).SRCJARS)),"$(w)")],' \
+ '"classes_jar": [$(KATI_foreach_sep w,$(COMMA) ,$(sort $(ALL_MODULES.$(m).CLASSES_JAR)),"$(w)")],' \
+ '"test_mainline_modules": [$(KATI_foreach_sep w,$(COMMA) ,$(sort $(ALL_MODULES.$(m).TEST_MAINLINE_MODULES)),"$(w)")],' \
+ '"is_unit_test": "$(ALL_MODULES.$(m).IS_UNIT_TEST)"$(COMMA)' \
+ '"test_options_tags": [$(KATI_foreach_sep w,$(COMMA) ,$(sort $(ALL_MODULES.$(m).TEST_OPTIONS_TAGS)),"$(w)")],' \
+ '"data": [$(KATI_foreach_sep w,$(COMMA) ,$(sort $(ALL_MODULES.$(m).TEST_DATA)),"$(w)")],' \
+ '"runtime_dependencies": [$(KATI_foreach_sep w,$(COMMA) ,$(sort $(ALL_MODULES.$(m).LOCAL_RUNTIME_LIBRARIES)),"$(w)")],' \
+ '"static_dependencies": [$(KATI_foreach_sep w,$(COMMA) ,$(sort $(ALL_MODULES.$(m).LOCAL_STATIC_LIBRARIES)),"$(w)")],' \
+ '"data_dependencies": [$(KATI_foreach_sep w,$(COMMA) ,$(sort $(ALL_MODULES.$(m).TEST_DATA_BINS)),"$(w)")],' \
+ '"supported_variants": [$(KATI_foreach_sep w,$(COMMA) ,$(sort $(ALL_MODULES.$(m).SUPPORTED_VARIANTS)),"$(w)")],' \
+ '"host_dependencies": [$(KATI_foreach_sep w,$(COMMA) ,$(sort $(ALL_MODULES.$(m).HOST_REQUIRED_FROM_TARGET)),"$(w)")],' \
+ '"target_dependencies": [$(KATI_foreach_sep w,$(COMMA) ,$(sort $(ALL_MODULES.$(m).TARGET_REQUIRED_FROM_HOST)),"$(w)")]' \
+ '}')'\n}\n' >> $@
droidcore-unbundled: $(MODULE_INFO_JSON)
diff --git a/core/tasks/tools/compatibility.mk b/core/tasks/tools/compatibility.mk
index dd2305e..4e78d89 100644
--- a/core/tasks/tools/compatibility.mk
+++ b/core/tasks/tools/compatibility.mk
@@ -36,6 +36,7 @@
$(HOST_OUT_JAVA_LIBRARIES)/$(test_suite_tradefed).jar \
$(HOST_OUT_JAVA_LIBRARIES)/$(test_suite_tradefed)-tests.jar \
$(HOST_OUT_EXECUTABLES)/$(test_suite_tradefed) \
+ $(HOST_OUT_EXECUTABLES)/test-utils-script \
$(test_suite_readme)
$(foreach f,$(test_suite_readme),$(if $(strip $(ALL_TARGETS.$(f).META_LIC)),,$(eval ALL_TARGETS.$(f).META_LIC := $(module_license_metadata))))
diff --git a/core/version_defaults.mk b/core/version_defaults.mk
index c107254..99d69d1 100644
--- a/core/version_defaults.mk
+++ b/core/version_defaults.mk
@@ -52,6 +52,8 @@
# These are the current development codenames, if the build is not a final
# release build. If this is a final release build, it is simply "REL".
+# Note that this may be overridden by RELEASE_VERSION_CODENAME_REL in
+# version_util.mk.
PLATFORM_VERSION_CODENAME.UP1A := UpsideDownCake
PLATFORM_VERSION_CODENAME.VP1A := VanillaIceCream
@@ -103,7 +105,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 := 2023-06-05
+ PLATFORM_SECURITY_PATCH := 2023-07-05
endif
include $(BUILD_SYSTEM)/version_util.mk
diff --git a/core/version_util.mk b/core/version_util.mk
index d3fcdc2..457f0f7 100644
--- a/core/version_util.mk
+++ b/core/version_util.mk
@@ -56,6 +56,12 @@
# unreleased API level targetable by this branch, not just those that are valid
# lunch targets for this branch.
+# Release config flag to override the current version to REL. Note that the
+# codename can also be locked to REL by setting it in versino_defaults.mk.
+ifneq ($(RELEASE_PLATFORM_VERSION_CODENAME_REL),)
+ PLATFORM_VERSION_CODENAME.$(TARGET_PLATFORM_VERSION) := REL
+endif
+
PLATFORM_VERSION_CODENAME := $(PLATFORM_VERSION_CODENAME.$(TARGET_PLATFORM_VERSION))
ifndef PLATFORM_VERSION_CODENAME
# PLATFORM_VERSION_CODENAME falls back to TARGET_PLATFORM_VERSION
diff --git a/envsetup.sh b/envsetup.sh
index d292dbb..0a90460 100644
--- a/envsetup.sh
+++ b/envsetup.sh
@@ -62,8 +62,8 @@
invocations of 'm' etc.
- tapas: tapas [<App1> <App2> ...] [arm|x86|arm64|x86_64] [eng|userdebug|user]
Sets up the build environment for building unbundled apps (APKs).
-- banchan: banchan <module1> [<module2> ...] [arm|x86|arm64|x86_64|arm64_only|x86_64only] \
- [eng|userdebug|user]
+- banchan: banchan <module1> [<module2> ...] \
+ [arm|x86|arm64|riscv64|x86_64|arm64_only|x86_64only] [eng|userdebug|user]
Sets up the build environment for building unbundled modules (APEXes).
- croot: Changes directory to the top of the tree, or a subdirectory thereof.
- m: Makes from the top of the tree.
@@ -952,9 +952,9 @@
function banchan()
{
local showHelp="$(echo $* | xargs -n 1 echo | \grep -E '^(help)$' | xargs)"
- local product="$(echo $* | xargs -n 1 echo | \grep -E '^(.*_)?(arm|x86|arm64|x86_64|arm64only|x86_64only)$' | xargs)"
+ local product="$(echo $* | xargs -n 1 echo | \grep -E '^(.*_)?(arm|x86|arm64|riscv64|x86_64|arm64only|x86_64only)$' | xargs)"
local variant="$(echo $* | xargs -n 1 echo | \grep -E '^(user|userdebug|eng)$' | xargs)"
- local apps="$(echo $* | xargs -n 1 echo | \grep -E -v '^(user|userdebug|eng|(.*_)?(arm|x86|arm64|x86_64))$' | xargs)"
+ local apps="$(echo $* | xargs -n 1 echo | \grep -E -v '^(user|userdebug|eng|(.*_)?(arm|x86|arm64|riscv64|x86_64))$' | xargs)"
if [ "$showHelp" != "" ]; then
$(gettop)/build/make/banchanHelp.sh
@@ -980,6 +980,7 @@
arm) product=module_arm;;
x86) product=module_x86;;
arm64) product=module_arm64;;
+ riscv64) product=module_riscv64;;
x86_64) product=module_x86_64;;
arm64only) product=module_arm64only;;
x86_64only) product=module_x86_64only;;
@@ -1074,6 +1075,10 @@
echo "can't find Android.mk"
}
+function adb() {
+ command adb "${@}"
+}
+
# simplified version of ps; output in the form
# <pid> <procname>
function qpid() {
@@ -1357,53 +1362,6 @@
get_abs_build_var ANDROID_PREBUILTS
}
-function tracedmdump()
-{
- local T=$(gettop)
- if [ ! "$T" ]; then
- echo "Couldn't locate the top of the tree. Try setting TOP."
- return
- fi
- local prebuiltdir=$(getprebuilt)
- local arch=$(gettargetarch)
- local KERNEL=$T/prebuilts/qemu-kernel/$arch/vmlinux-qemu
-
- local TRACE=$1
- if [ ! "$TRACE" ] ; then
- echo "usage: tracedmdump tracename"
- return
- fi
-
- if [ ! -r "$KERNEL" ] ; then
- echo "Error: cannot find kernel: '$KERNEL'"
- return
- fi
-
- local BASETRACE=$(basename $TRACE)
- if [ "$BASETRACE" = "$TRACE" ] ; then
- TRACE=$ANDROID_PRODUCT_OUT/traces/$TRACE
- fi
-
- echo "post-processing traces..."
- rm -f $TRACE/qtrace.dexlist
- post_trace $TRACE
- if [ $? -ne 0 ]; then
- echo "***"
- echo "*** Error: malformed trace. Did you remember to exit the emulator?"
- echo "***"
- return
- fi
- echo "generating dexlist output..."
- /bin/ls $ANDROID_PRODUCT_OUT/system/framework/*.jar $ANDROID_PRODUCT_OUT/system/app/*.apk $ANDROID_PRODUCT_OUT/data/app/*.apk 2>/dev/null | xargs dexlist > $TRACE/qtrace.dexlist
- echo "generating dmtrace data..."
- q2dm -r $ANDROID_PRODUCT_OUT/symbols $TRACE $KERNEL $TRACE/dmtrace || return
- echo "generating html file..."
- dmtracedump -h $TRACE/dmtrace >| $TRACE/dmtrace.html || return
- echo "done, see $TRACE/dmtrace.html for details"
- echo "or run:"
- echo " traceview $TRACE/dmtrace"
-}
-
# communicate with a running device or emulator, set up necessary state,
# and run the hat command.
function runhat()
diff --git a/target/board/generic/BoardConfig.mk b/target/board/generic/BoardConfig.mk
index 87c16da..6720ddb 100644
--- a/target/board/generic/BoardConfig.mk
+++ b/target/board/generic/BoardConfig.mk
@@ -30,20 +30,3 @@
TARGET_CPU_ABI2 := armeabi
include build/make/target/board/BoardConfigGsiCommon.mk
-
-ifndef BUILDING_GSI
-include build/make/target/board/BoardConfigEmuCommon.mk
-
-BOARD_USERDATAIMAGE_PARTITION_SIZE := 576716800
-
-# Wifi.
-BOARD_WLAN_DEVICE := emulator
-BOARD_HOSTAPD_DRIVER := NL80211
-BOARD_WPA_SUPPLICANT_DRIVER := NL80211
-BOARD_HOSTAPD_PRIVATE_LIB := lib_driver_cmd_simulated
-BOARD_WPA_SUPPLICANT_PRIVATE_LIB := lib_driver_cmd_simulated
-WPA_SUPPLICANT_VERSION := VER_0_8_X
-WIFI_DRIVER_FW_PATH_PARAM := "/dev/null"
-WIFI_DRIVER_FW_PATH_STA := "/dev/null"
-WIFI_DRIVER_FW_PATH_AP := "/dev/null"
-endif
diff --git a/target/board/generic/device.mk b/target/board/generic/device.mk
index 76242c9..76edf6b 100644
--- a/target/board/generic/device.mk
+++ b/target/board/generic/device.mk
@@ -14,5 +14,3 @@
# limitations under the License.
#
-PRODUCT_SOONG_NAMESPACES += device/generic/goldfish # for libwifi-hal-emu
-PRODUCT_SOONG_NAMESPACES += device/generic/goldfish-opengl # for goldfish deps.
diff --git a/target/board/generic_64bitonly_x86_64/BoardConfig.mk b/target/board/generic_64bitonly_x86_64/BoardConfig.mk
index a240eab..a129ea0 100644
--- a/target/board/generic_64bitonly_x86_64/BoardConfig.mk
+++ b/target/board/generic_64bitonly_x86_64/BoardConfig.mk
@@ -28,23 +28,3 @@
TARGET_PRELINK_MODULE := false
include build/make/target/board/BoardConfigGsiCommon.mk
-
-ifndef BUILDING_GSI
-include build/make/target/board/BoardConfigEmuCommon.mk
-
-BOARD_USERDATAIMAGE_PARTITION_SIZE := 576716800
-
-BOARD_SEPOLICY_DIRS += device/generic/goldfish/sepolicy/x86
-
-# Wifi.
-BOARD_WLAN_DEVICE := emulator
-BOARD_HOSTAPD_DRIVER := NL80211
-BOARD_WPA_SUPPLICANT_DRIVER := NL80211
-BOARD_HOSTAPD_PRIVATE_LIB := lib_driver_cmd_simulated
-BOARD_WPA_SUPPLICANT_PRIVATE_LIB := lib_driver_cmd_simulated
-WPA_SUPPLICANT_VERSION := VER_0_8_X
-WIFI_DRIVER_FW_PATH_PARAM := "/dev/null"
-WIFI_DRIVER_FW_PATH_STA := "/dev/null"
-WIFI_DRIVER_FW_PATH_AP := "/dev/null"
-
-endif # !BUILDING_GSI
diff --git a/target/board/generic_x86/BoardConfig.mk b/target/board/generic_x86/BoardConfig.mk
index 47fd384..26bede8 100644
--- a/target/board/generic_x86/BoardConfig.mk
+++ b/target/board/generic_x86/BoardConfig.mk
@@ -19,23 +19,3 @@
TARGET_ARCH_VARIANT := x86
include build/make/target/board/BoardConfigGsiCommon.mk
-
-ifndef BUILDING_GSI
-include build/make/target/board/BoardConfigEmuCommon.mk
-
-# Resize to 4G to accomodate ASAN and CTS
-BOARD_USERDATAIMAGE_PARTITION_SIZE := 4294967296
-
-BOARD_SEPOLICY_DIRS += device/generic/goldfish/sepolicy/x86
-
-# Wifi.
-BOARD_WLAN_DEVICE := emulator
-BOARD_HOSTAPD_DRIVER := NL80211
-BOARD_WPA_SUPPLICANT_DRIVER := NL80211
-BOARD_HOSTAPD_PRIVATE_LIB := lib_driver_cmd_simulated
-BOARD_WPA_SUPPLICANT_PRIVATE_LIB := lib_driver_cmd_simulated
-WPA_SUPPLICANT_VERSION := VER_0_8_X
-WIFI_DRIVER_FW_PATH_PARAM := "/dev/null"
-WIFI_DRIVER_FW_PATH_STA := "/dev/null"
-WIFI_DRIVER_FW_PATH_AP := "/dev/null"
-endif
diff --git a/target/board/generic_x86/device.mk b/target/board/generic_x86/device.mk
index 5ad008f..60f0cc3 100644
--- a/target/board/generic_x86/device.mk
+++ b/target/board/generic_x86/device.mk
@@ -14,9 +14,6 @@
# limitations under the License.
#
-PRODUCT_SOONG_NAMESPACES += device/generic/goldfish # for libwifi-hal-emu
-PRODUCT_SOONG_NAMESPACES += device/generic/goldfish-opengl # for goldfish deps.
-
ifdef NET_ETH0_STARTONBOOT
PRODUCT_VENDOR_PROPERTIES += net.eth0.startonboot=1
endif
diff --git a/target/board/generic_x86_64/BoardConfig.mk b/target/board/generic_x86_64/BoardConfig.mk
old mode 100755
new mode 100644
index 36136f4..64da578
--- a/target/board/generic_x86_64/BoardConfig.mk
+++ b/target/board/generic_x86_64/BoardConfig.mk
@@ -28,23 +28,3 @@
TARGET_DYNAMIC_64_32_DRMSERVER := true
include build/make/target/board/BoardConfigGsiCommon.mk
-
-ifndef BUILDING_GSI
-include build/make/target/board/BoardConfigEmuCommon.mk
-
-BOARD_USERDATAIMAGE_PARTITION_SIZE := 576716800
-
-BOARD_SEPOLICY_DIRS += device/generic/goldfish/sepolicy/x86
-
-# Wifi.
-BOARD_WLAN_DEVICE := emulator
-BOARD_HOSTAPD_DRIVER := NL80211
-BOARD_WPA_SUPPLICANT_DRIVER := NL80211
-BOARD_HOSTAPD_PRIVATE_LIB := lib_driver_cmd_simulated
-BOARD_WPA_SUPPLICANT_PRIVATE_LIB := lib_driver_cmd_simulated
-WPA_SUPPLICANT_VERSION := VER_0_8_X
-WIFI_DRIVER_FW_PATH_PARAM := "/dev/null"
-WIFI_DRIVER_FW_PATH_STA := "/dev/null"
-WIFI_DRIVER_FW_PATH_AP := "/dev/null"
-
-endif # !BUILDING_GSI
diff --git a/target/board/generic_x86_64_arm64/BoardConfig.mk b/target/board/generic_x86_64_arm64/BoardConfig.mk
old mode 100755
new mode 100644
index f528294..818ec44
--- a/target/board/generic_x86_64_arm64/BoardConfig.mk
+++ b/target/board/generic_x86_64_arm64/BoardConfig.mk
@@ -13,7 +13,6 @@
# limitations under the License.
#
-# x86_64 emulator specific definitions
TARGET_CPU_ABI := x86_64
TARGET_ARCH := x86_64
TARGET_ARCH_VARIANT := x86_64
@@ -37,23 +36,9 @@
TARGET_PRELINK_MODULE := false
include build/make/target/board/BoardConfigMainlineCommon.mk
-include build/make/target/board/BoardConfigEmuCommon.mk
# the settings differ from BoardConfigMainlineCommon.mk
BOARD_USES_SYSTEM_OTHER_ODEX :=
# Resize to 4G to accommodate ASAN and CTS
BOARD_USERDATAIMAGE_PARTITION_SIZE := 4294967296
-
-BOARD_SEPOLICY_DIRS += device/generic/goldfish/sepolicy/x86
-
-# Wifi.
-BOARD_WLAN_DEVICE := emulator
-BOARD_HOSTAPD_DRIVER := NL80211
-BOARD_WPA_SUPPLICANT_DRIVER := NL80211
-BOARD_HOSTAPD_PRIVATE_LIB := lib_driver_cmd_simulated
-BOARD_WPA_SUPPLICANT_PRIVATE_LIB := lib_driver_cmd_simulated
-WPA_SUPPLICANT_VERSION := VER_0_8_X
-WIFI_DRIVER_FW_PATH_PARAM := "/dev/null"
-WIFI_DRIVER_FW_PATH_STA := "/dev/null"
-WIFI_DRIVER_FW_PATH_AP := "/dev/null"
diff --git a/target/board/generic_x86_64_arm64/device.mk b/target/board/generic_x86_64_arm64/device.mk
old mode 100755
new mode 100644
index 76242c9..76edf6b
--- a/target/board/generic_x86_64_arm64/device.mk
+++ b/target/board/generic_x86_64_arm64/device.mk
@@ -14,5 +14,3 @@
# limitations under the License.
#
-PRODUCT_SOONG_NAMESPACES += device/generic/goldfish # for libwifi-hal-emu
-PRODUCT_SOONG_NAMESPACES += device/generic/goldfish-opengl # for goldfish deps.
diff --git a/target/board/generic_x86_arm/BoardConfig.mk b/target/board/generic_x86_arm/BoardConfig.mk
index f6589b0..62bb5eb 100644
--- a/target/board/generic_x86_arm/BoardConfig.mk
+++ b/target/board/generic_x86_arm/BoardConfig.mk
@@ -13,7 +13,6 @@
# limitations under the License.
#
-# x86 emulator specific definitions
TARGET_CPU_ABI := x86
TARGET_ARCH := x86
TARGET_ARCH_VARIANT := x86
@@ -30,23 +29,9 @@
# The settings in latter makefiles overwrite those in the former.
#
include build/make/target/board/BoardConfigMainlineCommon.mk
-include build/make/target/board/BoardConfigEmuCommon.mk
# the settings differ from BoardConfigMainlineCommon.mk
BOARD_USES_SYSTEM_OTHER_ODEX :=
# Resize to 4G to accomodate ASAN and CTS
BOARD_USERDATAIMAGE_PARTITION_SIZE := 4294967296
-
-BOARD_SEPOLICY_DIRS += device/generic/goldfish/sepolicy/x86
-
-# Wifi.
-BOARD_WLAN_DEVICE := emulator
-BOARD_HOSTAPD_DRIVER := NL80211
-BOARD_WPA_SUPPLICANT_DRIVER := NL80211
-BOARD_HOSTAPD_PRIVATE_LIB := lib_driver_cmd_simulated
-BOARD_WPA_SUPPLICANT_PRIVATE_LIB := lib_driver_cmd_simulated
-WPA_SUPPLICANT_VERSION := VER_0_8_X
-WIFI_DRIVER_FW_PATH_PARAM := "/dev/null"
-WIFI_DRIVER_FW_PATH_STA := "/dev/null"
-WIFI_DRIVER_FW_PATH_AP := "/dev/null"
diff --git a/target/board/generic_x86_arm/device.mk b/target/board/generic_x86_arm/device.mk
index 76242c9..76edf6b 100644
--- a/target/board/generic_x86_arm/device.mk
+++ b/target/board/generic_x86_arm/device.mk
@@ -14,5 +14,3 @@
# limitations under the License.
#
-PRODUCT_SOONG_NAMESPACES += device/generic/goldfish # for libwifi-hal-emu
-PRODUCT_SOONG_NAMESPACES += device/generic/goldfish-opengl # for goldfish deps.
diff --git a/target/board/module_riscv64/BoardConfig.mk b/target/board/module_riscv64/BoardConfig.mk
new file mode 100644
index 0000000..8bc1999
--- /dev/null
+++ b/target/board/module_riscv64/BoardConfig.mk
@@ -0,0 +1,22 @@
+# Copyright (C) 2023 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.
+#
+
+TARGET_ARCH := riscv64
+TARGET_ARCH_VARIANT :=
+TARGET_CPU_VARIANT := generic
+TARGET_CPU_ABI := riscv64
+
+# Temporary hack while prebuilt modules are missing riscv64.
+ALLOW_MISSING_DEPENDENCIES := true
diff --git a/target/board/module_riscv64/README.md b/target/board/module_riscv64/README.md
new file mode 100644
index 0000000..edebaa9
--- /dev/null
+++ b/target/board/module_riscv64/README.md
@@ -0,0 +1,2 @@
+This device is suitable for an unbundled module targeted specifically to a
+riscv64 device. This is a 64-bit only device (no 32-bit support).
diff --git a/target/product/AndroidProducts.mk b/target/product/AndroidProducts.mk
index 133dc73..473a275 100644
--- a/target/product/AndroidProducts.mk
+++ b/target/product/AndroidProducts.mk
@@ -83,6 +83,7 @@
$(LOCAL_DIR)/module_arm.mk \
$(LOCAL_DIR)/module_arm64.mk \
$(LOCAL_DIR)/module_arm64only.mk \
+ $(LOCAL_DIR)/module_riscv64.mk \
$(LOCAL_DIR)/module_x86.mk \
$(LOCAL_DIR)/module_x86_64.mk \
$(LOCAL_DIR)/module_x86_64only.mk \
diff --git a/target/product/aosp_64bitonly_x86_64.mk b/target/product/aosp_64bitonly_x86_64.mk
index 75fd3c8..cf812a2 100644
--- a/target/product/aosp_64bitonly_x86_64.mk
+++ b/target/product/aosp_64bitonly_x86_64.mk
@@ -51,7 +51,6 @@
#
# All components inherited here go to vendor image
#
-$(call inherit-product, $(SRC_TARGET_DIR)/product/emulator_vendor.mk)
$(call inherit-product, $(SRC_TARGET_DIR)/board/generic_x86_64/device.mk)
#
diff --git a/target/product/aosp_arm.mk b/target/product/aosp_arm.mk
index 61c1316..d9c362e 100644
--- a/target/product/aosp_arm.mk
+++ b/target/product/aosp_arm.mk
@@ -50,7 +50,6 @@
# All components inherited here go to vendor image
#
$(call inherit-product-if-exists, build/make/target/product/ramdisk_stub.mk)
-$(call inherit-product, $(SRC_TARGET_DIR)/product/emulator_vendor.mk)
$(call inherit-product, $(SRC_TARGET_DIR)/board/generic_x86/device.mk)
#
diff --git a/target/product/aosp_arm64.mk b/target/product/aosp_arm64.mk
index 6c907db..d3514a5 100644
--- a/target/product/aosp_arm64.mk
+++ b/target/product/aosp_arm64.mk
@@ -54,7 +54,6 @@
#
# All components inherited here go to vendor or vendor_boot image
#
-$(call inherit-product, $(SRC_TARGET_DIR)/product/emulator_vendor.mk)
$(call inherit-product, $(SRC_TARGET_DIR)/board/generic_arm64/device.mk)
$(call inherit-product, $(SRC_TARGET_DIR)/product/non_ab_device.mk)
diff --git a/target/product/aosp_riscv64.mk b/target/product/aosp_riscv64.mk
index 270a989..fa503ff 100644
--- a/target/product/aosp_riscv64.mk
+++ b/target/product/aosp_riscv64.mk
@@ -46,7 +46,6 @@
#
# All components inherited here go to vendor image
#
-$(call inherit-product, $(SRC_TARGET_DIR)/product/emulator_vendor.mk)
$(call inherit-product, $(SRC_TARGET_DIR)/board/generic_riscv64/device.mk)
#
diff --git a/target/product/aosp_x86.mk b/target/product/aosp_x86.mk
index a2f0390..c26a8bf 100644
--- a/target/product/aosp_x86.mk
+++ b/target/product/aosp_x86.mk
@@ -47,7 +47,6 @@
#
# All components inherited here go to vendor image
#
-$(call inherit-product, $(SRC_TARGET_DIR)/product/emulator_vendor.mk)
$(call inherit-product, $(SRC_TARGET_DIR)/board/generic_x86/device.mk)
diff --git a/target/product/aosp_x86_64.mk b/target/product/aosp_x86_64.mk
index 535ee3f..3040dd3 100644
--- a/target/product/aosp_x86_64.mk
+++ b/target/product/aosp_x86_64.mk
@@ -56,7 +56,6 @@
#
# All components inherited here go to vendor image
#
-$(call inherit-product, $(SRC_TARGET_DIR)/product/emulator_vendor.mk)
$(call inherit-product, $(SRC_TARGET_DIR)/board/generic_x86_64/device.mk)
$(call inherit-product, $(SRC_TARGET_DIR)/product/non_ab_device.mk)
diff --git a/target/product/aosp_x86_arm.mk b/target/product/aosp_x86_arm.mk
index 39ad0d8..a103b1a 100644
--- a/target/product/aosp_x86_arm.mk
+++ b/target/product/aosp_x86_arm.mk
@@ -45,7 +45,6 @@
#
# All components inherited here go to vendor image
#
-$(call inherit-product, $(SRC_TARGET_DIR)/product/emulator_vendor.mk)
$(call inherit-product, $(SRC_TARGET_DIR)/board/generic_x86_arm/device.mk)
diff --git a/target/product/base_system.mk b/target/product/base_system.mk
index 65e9bd0..009d611 100644
--- a/target/product/base_system.mk
+++ b/target/product/base_system.mk
@@ -87,7 +87,6 @@
dump.erofs \
dumpstate \
dumpsys \
- DynamicSystemInstallationService \
e2fsck \
ExtShared \
flags_health_check \
@@ -295,6 +294,13 @@
endif
+# Product does not support Dynamic System Update
+ifneq ($(PRODUCT_NO_DYNAMIC_SYSTEM_UPDATE),true)
+ PRODUCT_PACKAGES += \
+ DynamicSystemInstallationService \
+
+endif
+
# VINTF data for system image
PRODUCT_PACKAGES += \
system_manifest.xml \
@@ -353,7 +359,6 @@
incident_report \
ld.mc \
lpdump \
- minigzip \
mke2fs \
mkfs.erofs \
resize2fs \
@@ -386,6 +391,7 @@
# Packages included only for eng or userdebug builds, previously debug tagged
PRODUCT_PACKAGES_DEBUG := \
adb_keys \
+ adevice_fingerprint \
arping \
dmuserd \
idlcli \
@@ -432,3 +438,6 @@
frameworks/base/config/dirty-image-objects:system/etc/dirty-image-objects)
$(call inherit-product, $(SRC_TARGET_DIR)/product/runtime_libart.mk)
+
+# Use "image" APEXes always.
+$(call inherit-product,$(SRC_TARGET_DIR)/product/updatable_apex.mk)
diff --git a/target/product/default_art_config.mk b/target/product/default_art_config.mk
index 1e28c80..3ca4187 100644
--- a/target/product/default_art_config.mk
+++ b/target/product/default_art_config.mk
@@ -38,6 +38,14 @@
PRODUCT_BOOT_JARS := \
$(ART_APEX_JARS)
+# List of jars to be included in the ART boot image for testing.
+# DO NOT reorder this list. The order must match the one described above.
+# Note: We use the host variant of "core-icu4j" and "conscrypt" for testing.
+PRODUCT_TEST_ONLY_ART_BOOT_IMAGE_JARS := \
+ $(ART_APEX_JARS) \
+ platform:core-icu4j-host \
+ platform:conscrypt-host \
+
# /system and /system_ext boot jars.
PRODUCT_BOOT_JARS += \
framework-minus-apex \
@@ -106,6 +114,13 @@
com.android.uwb:service-uwb \
com.android.wifi:service-wifi \
+# Overrides the (apex, jar) pairs above when determining the on-device location. The format is:
+# <old_apex>:<old_jar>:<new_apex>:<new_jar>
+PRODUCT_CONFIGURED_JAR_LOCATION_OVERRIDES := \
+ platform:framework-minus-apex:platform:framework \
+ platform:core-icu4j-host:com.android.i18n:core-icu4j \
+ platform:conscrypt-host:com.android.conscrypt:conscrypt \
+
# Minimal configuration for running dex2oat (default argument values).
# PRODUCT_USES_DEFAULT_ART_CONFIG must be true to enable boot image compilation.
PRODUCT_USES_DEFAULT_ART_CONFIG := true
diff --git a/target/product/full.manifest.xml b/target/product/full.manifest.xml
new file mode 100644
index 0000000..b8b0d37
--- /dev/null
+++ b/target/product/full.manifest.xml
@@ -0,0 +1,2 @@
+<manifest version="1.0" type="device" target-level="7">
+</manifest>
diff --git a/target/product/full.mk b/target/product/full.mk
index 945957f..da04f49 100644
--- a/target/product/full.mk
+++ b/target/product/full.mk
@@ -20,10 +20,11 @@
# entirely appropriate to inherit from for on-device configurations.
$(call inherit-product-if-exists, build/make/target/product/ramdisk_stub.mk)
-$(call inherit-product, $(SRC_TARGET_DIR)/product/emulator_vendor.mk)
$(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_base_telephony.mk)
$(call inherit-product, $(SRC_TARGET_DIR)/board/generic/device.mk)
+DEVICE_MANIFEST_FILE += build/make/target/product/full.manifest.xml
+
# Enable dynamic partition size
PRODUCT_USE_DYNAMIC_PARTITION_SIZE := true
diff --git a/target/product/full_x86.mk b/target/product/full_x86.mk
index 0f3be91..07f6472 100644
--- a/target/product/full_x86.mk
+++ b/target/product/full_x86.mk
@@ -23,10 +23,11 @@
# that isn't a wifi connection. This will instruct init.rc to enable the
# network connection so that you can use it with ADB
-$(call inherit-product, $(SRC_TARGET_DIR)/product/emulator_vendor.mk)
$(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_base_telephony.mk)
$(call inherit-product, $(SRC_TARGET_DIR)/board/generic_x86/device.mk)
+DEVICE_MANIFEST_FILE += build/make/target/product/full.manifest.xml
+
ifdef NET_ETH0_STARTONBOOT
PRODUCT_VENDOR_PROPERTIES += net.eth0.startonboot=1
endif
diff --git a/target/product/generic.mk b/target/product/generic.mk
index fb5b727..fd3b3fb 100644
--- a/target/product/generic.mk
+++ b/target/product/generic.mk
@@ -14,9 +14,6 @@
# limitations under the License.
#
-PRODUCT_SOONG_NAMESPACES += device/generic/goldfish # for libwifi-hal-emu
-PRODUCT_SOONG_NAMESPACES += device/generic/goldfish-opengl # for goldfish deps.
-
# This is a generic phone product that isn't specialized for a specific device.
# It includes the base Android platform.
diff --git a/target/product/generic_system.mk b/target/product/generic_system.mk
index 1a639ef..f194d8b 100644
--- a/target/product/generic_system.mk
+++ b/target/product/generic_system.mk
@@ -102,6 +102,11 @@
libaudiopolicyengineconfigurable \
libpolicy-subsystem
+
+ifneq ($(KEEP_VNDK),true)
+PRODUCT_PACKAGES += llndk.libraries.txt
+endif
+
# Include all zygote init scripts. "ro.zygote" will select one of them.
PRODUCT_COPY_FILES += \
system/core/rootdir/init.zygote32.rc:system/etc/init/hw/init.zygote32.rc \
diff --git a/target/product/gsi/Android.mk b/target/product/gsi/Android.mk
index 86d4622..adeb159 100644
--- a/target/product/gsi/Android.mk
+++ b/target/product/gsi/Android.mk
@@ -195,7 +195,10 @@
include $(CLEAR_VARS)
_vndk_versions :=
ifeq ($(filter com.android.vndk.current.on_vendor, $(PRODUCT_PACKAGES)),)
- _vndk_versions += $(PRODUCT_EXTRA_VNDK_VERSIONS)
+ _vndk_versions += $(if $(call math_is_number,$(PLATFORM_VNDK_VERSION)),\
+ $(foreach vndk_ver,$(PRODUCT_EXTRA_VNDK_VERSIONS),\
+ $(if $(call math_lt,$(vndk_ver),$(PLATFORM_VNDK_VERSION)),$(vndk_ver))),\
+ $(PRODUCT_EXTRA_VNDK_VERSIONS))
endif
ifneq ($(BOARD_VNDK_VERSION),current)
_vndk_versions += $(BOARD_VNDK_VERSION)
diff --git a/target/product/gsi_release.mk b/target/product/gsi_release.mk
index 375b7cb..bd85b9f 100644
--- a/target/product/gsi_release.mk
+++ b/target/product/gsi_release.mk
@@ -28,10 +28,15 @@
BUILDING_GSI := true
-# Exclude all files under system/product and system/system_ext
+# Exclude all files under system/product and system/system_ext,
+# and the vndk apex's compat symlinks
PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST += \
system/product/% \
- system/system_ext/%
+ system/system_ext/% \
+ system/lib/vndk-29 \
+ system/lib/vndk-sp-29 \
+ system/lib64/vndk-29 \
+ system/lib64/vndk-sp-29
# GSI should always support up-to-date platform features.
# Keep this value at the latest API level to ensure latest build system
@@ -80,3 +85,6 @@
# Additional settings used in all GSI builds
PRODUCT_PRODUCT_PROPERTIES += \
ro.crypto.metadata_init_delete_all_keys.enabled=false \
+
+# Window Extensions
+$(call inherit-product, $(SRC_TARGET_DIR)/product/window_extensions.mk)
\ No newline at end of file
diff --git a/target/product/module_riscv64.mk b/target/product/module_riscv64.mk
new file mode 100644
index 0000000..4fd38c0
--- /dev/null
+++ b/target/product/module_riscv64.mk
@@ -0,0 +1,21 @@
+#
+# Copyright (C) 2023 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+$(call inherit-product, $(SRC_TARGET_DIR)/product/module_common.mk)
+$(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit_only.mk)
+
+PRODUCT_NAME := module_riscv64
+PRODUCT_DEVICE := module_riscv64
diff --git a/target/product/sdk.mk b/target/product/sdk.mk
index fa7e1ad..e4cb7ff 100644
--- a/target/product/sdk.mk
+++ b/target/product/sdk.mk
@@ -14,11 +14,8 @@
# limitations under the License.
#
-# This is a simple product that uses configures the minimum amount
-# needed to build the SDK (without the emulator).
+# Don't modify this file - It's just an alias!
-$(call inherit-product, $(SRC_TARGET_DIR)/product/languages_default.mk)
+$(call inherit-product, $(SRC_TARGET_DIR)/product/sdk_x86.mk)
PRODUCT_NAME := sdk
-PRODUCT_BRAND := Android
-PRODUCT_DEVICE := mainline_x86
diff --git a/target/product/sdk_arm64.mk b/target/product/sdk_arm64.mk
index 8bb38f4..497f673 100644
--- a/target/product/sdk_arm64.mk
+++ b/target/product/sdk_arm64.mk
@@ -14,8 +14,11 @@
# limitations under the License.
#
-# Don't modify this file - It's just an alias!
+$(call inherit-product, $(SRC_TARGET_DIR)/product/languages_default.mk)
-$(call inherit-product, $(SRC_TARGET_DIR)/product/sdk_phone_arm64.mk)
+TARGET_SUPPORTS_32_BIT_APPS := true
+TARGET_SUPPORTS_64_BIT_APPS := true
PRODUCT_NAME := sdk_arm64
+PRODUCT_BRAND := Android
+PRODUCT_DEVICE := mainline_arm64
diff --git a/target/product/sdk_x86.mk b/target/product/sdk_x86.mk
index 13ee57d..843321f 100644
--- a/target/product/sdk_x86.mk
+++ b/target/product/sdk_x86.mk
@@ -14,8 +14,11 @@
# limitations under the License.
#
-# Don't modify this file - It's just an alias!
+# This is a simple product that uses configures the minimum amount
+# needed to build the SDK (without the emulator).
-$(call inherit-product, $(SRC_TARGET_DIR)/product/sdk_phone_x86.mk)
+$(call inherit-product, $(SRC_TARGET_DIR)/product/languages_default.mk)
-PRODUCT_NAME := sdk_x86
+PRODUCT_NAME := sdk_x86_64
+PRODUCT_BRAND := Android
+PRODUCT_DEVICE := mainline_x86
diff --git a/target/product/sdk_x86_64.mk b/target/product/sdk_x86_64.mk
index 5f6553e..c1caf7e 100644
--- a/target/product/sdk_x86_64.mk
+++ b/target/product/sdk_x86_64.mk
@@ -14,8 +14,14 @@
# limitations under the License.
#
-# Don't modify this file - It's just an alias!
+# This is a simple product that uses configures the minimum amount
+# needed to build the SDK (without the emulator).
-$(call inherit-product, $(SRC_TARGET_DIR)/product/sdk_phone_x86_64.mk)
+$(call inherit-product, $(SRC_TARGET_DIR)/product/languages_default.mk)
+
+TARGET_SUPPORTS_32_BIT_APPS := true
+TARGET_SUPPORTS_64_BIT_APPS := true
PRODUCT_NAME := sdk_x86_64
+PRODUCT_BRAND := Android
+PRODUCT_DEVICE := mainline_x86_64
diff --git a/target/product/updatable_apex.mk b/target/product/updatable_apex.mk
index c19982b..8357fdf 100644
--- a/target/product/updatable_apex.mk
+++ b/target/product/updatable_apex.mk
@@ -14,17 +14,13 @@
# limitations under the License.
#
-# Inherit this when the target needs to support updating APEXes
+# com.android.apex.cts.shim.v1_prebuilt overrides CtsShimPrebuilt
+# and CtsShimPrivPrebuilt since they are packaged inside the APEX.
+PRODUCT_PACKAGES += com.android.apex.cts.shim.v1_prebuilt
+PRODUCT_SYSTEM_PROPERTIES := ro.apex.updatable=true
-ifneq ($(OVERRIDE_TARGET_FLATTEN_APEX),true)
- # com.android.apex.cts.shim.v1_prebuilt overrides CtsShimPrebuilt
- # and CtsShimPrivPrebuilt since they are packaged inside the APEX.
- PRODUCT_PACKAGES += com.android.apex.cts.shim.v1_prebuilt
- PRODUCT_SYSTEM_PROPERTIES := ro.apex.updatable=true
- TARGET_FLATTEN_APEX := false
- # Use compressed apexes in pre-installed partitions.
- # Note: this doesn't mean that all pre-installed apexes will be compressed.
- # Whether an apex is compressed or not is controlled at apex Soong module
- # via compresible property.
- PRODUCT_COMPRESSED_APEX := true
-endif
+# Use compressed apexes in pre-installed partitions.
+# Note: this doesn't mean that all pre-installed apexes will be compressed.
+# Whether an apex is compressed or not is controlled at apex Soong module
+# via compresible property.
+PRODUCT_COMPRESSED_APEX := true
diff --git a/tests/b_tests.sh b/tests/b_tests.sh
index 491d762..68a13e3 100755
--- a/tests/b_tests.sh
+++ b/tests/b_tests.sh
@@ -23,6 +23,10 @@
test_target=//build/bazel/scripts/difftool:difftool
+if b build //build/bazel:nonexistent_module &>/dev/null ; then
+ echo "b did not fail when building a nonexistent module" >&2
+ exit 1
+fi
b build "$test_target"
b build -- "$test_target"
b build "$test_target" --run-soong-tests
diff --git a/tools/BUILD.bazel b/tools/BUILD.bazel
index 0de178b..2dbb585 100644
--- a/tools/BUILD.bazel
+++ b/tools/BUILD.bazel
@@ -1,6 +1,7 @@
py_library(
name = "event_log_tags",
srcs = ["event_log_tags.py"],
+ imports = ["."],
)
py_binary(
diff --git a/tools/aconfig/Android.bp b/tools/aconfig/Android.bp
index 5b7234e..28bf8a5 100644
--- a/tools/aconfig/Android.bp
+++ b/tools/aconfig/Android.bp
@@ -2,6 +2,36 @@
default_applicable_licenses: ["Android-Apache-2.0"],
}
+// proto libraries for consumers of `aconfig dump --format=protobuf` output
+
+java_library {
+ name: "libaconfig_java_proto_lite",
+ host_supported: true,
+ srcs: ["protos/aconfig.proto"],
+ static_libs: ["libprotobuf-java-lite"],
+ proto: {
+ type: "lite",
+ },
+ sdk_version: "current",
+}
+
+java_library_host {
+ name: "libaconfig_java_proto_full",
+ srcs: ["protos/aconfig.proto"],
+ static_libs: ["libprotobuf-java-full"],
+ proto: {
+ type: "full",
+ },
+}
+
+python_library_host {
+ name: "libaconfig_python_proto",
+ srcs: ["protos/aconfig.proto"],
+ proto: {
+ canonical_path_from_root: false,
+ },
+}
+
// host binary: aconfig
rust_protobuf_host {
@@ -45,7 +75,7 @@
],
}
-// integration tests: java
+// integration tests: general
aconfig_declarations {
name: "aconfig.test.flags",
@@ -69,22 +99,97 @@
],
}
+// integration tests: java
+
java_aconfig_library {
- name: "aconfig_test_java",
+ name: "aconfig_test_java_library",
aconfig_declarations: "aconfig.test.flags",
}
android_test {
name: "aconfig.test.java",
srcs: [
- "tests/**/*.java",
+ "tests/AconfigTest.java",
],
manifest: "tests/AndroidManifest.xml",
certificate: "platform",
static_libs: [
+ "aconfig_test_java_library",
"androidx.test.rules",
"testng",
- "aconfig_test_java",
],
test_suites: ["device-tests"],
}
+
+java_aconfig_library {
+ name: "aconfig_host_test_java_library",
+ aconfig_declarations: "aconfig.test.flags",
+ host_supported: true,
+ test: true,
+}
+
+java_test_host {
+ name: "AconfigJavaHostTest",
+ srcs: [
+ "tests/AconfigHostTest.java",
+ ],
+ static_libs: [
+ "aconfig_host_test_java_library",
+ "junit",
+ ],
+ test_suites: ["general-tests"],
+}
+
+// integration tests: C++
+
+cc_aconfig_library {
+ name: "aconfig_test_cpp_library",
+ aconfig_declarations: "aconfig.test.flags",
+}
+
+cc_test {
+ name: "aconfig.test.cpp",
+ srcs: [
+ "tests/aconfig_test.cpp",
+ ],
+ static_libs: [
+ "aconfig_test_cpp_library",
+ "libgmock",
+ ],
+ shared_libs: [
+ "server_configurable_flags",
+ ],
+}
+
+rust_aconfig_library {
+ name: "libaconfig_test_rust_library",
+ crate_name: "aconfig_test_rust_library",
+ aconfig_declarations: "aconfig.test.flags",
+}
+
+rust_test {
+ name: "aconfig.prod_mode.test.rust",
+ srcs: [
+ "tests/aconfig_prod_mode_test.rs"
+ ],
+ rustlibs: [
+ "libaconfig_test_rust_library",
+ ],
+}
+
+rust_aconfig_library {
+ name: "libaconfig_test_rust_library_with_test_mode",
+ crate_name: "aconfig_test_rust_library",
+ aconfig_declarations: "aconfig.test.flags",
+ test: true,
+}
+
+rust_test {
+ name: "aconfig.test_mode.test.rust",
+ srcs: [
+ "tests/aconfig_test_mode_test.rs"
+ ],
+ rustlibs: [
+ "libaconfig_test_rust_library_with_test_mode",
+ ],
+}
\ No newline at end of file
diff --git a/tools/aconfig/TEST_MAPPING b/tools/aconfig/TEST_MAPPING
new file mode 100644
index 0000000..74ac5ec
--- /dev/null
+++ b/tools/aconfig/TEST_MAPPING
@@ -0,0 +1,21 @@
+{
+ "presubmit": [
+ {
+ // Ensure changes on aconfig auto generated library is compatible with
+ // test testing filtering logic. Breakage on this test means all tests
+ // that using the flag annotations to do filtering will get affected.
+ "name": "FlagAnnotationTests",
+ "options": [
+ {
+ "include-filter": "android.cts.flags.tests.FlagAnnotationTest"
+ }
+ ]
+ },
+ {
+ // Ensure changes on aconfig auto generated library is compatible with
+ // test testing filtering logic. Breakage on this test means all tests
+ // that using the flag macros to do filtering will get affected.
+ "name": "FlagMacrosTests"
+ }
+ ]
+}
diff --git a/tools/aconfig/fake_device_config/Android.bp b/tools/aconfig/fake_device_config/Android.bp
new file mode 100644
index 0000000..5f62ae9
--- /dev/null
+++ b/tools/aconfig/fake_device_config/Android.bp
@@ -0,0 +1,21 @@
+// Copyright (C) 2023 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.
+
+java_library {
+ name: "fake_device_config",
+ srcs: ["src/**/*.java"],
+ sdk_version: "core_platform",
+ host_supported: true,
+}
+
diff --git a/tools/aconfig/fake_device_config/src/android/provider/DeviceConfig.java b/tools/aconfig/fake_device_config/src/android/provider/DeviceConfig.java
new file mode 100644
index 0000000..50b6289
--- /dev/null
+++ b/tools/aconfig/fake_device_config/src/android/provider/DeviceConfig.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2023 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 android.provider;
+
+/*
+ * This class allows generated aconfig code to compile independently of the framework.
+ */
+public class DeviceConfig {
+ private DeviceConfig() {
+ }
+
+ public static boolean getBoolean(String ns, String name, boolean def) {
+ return false;
+ }
+}
diff --git a/tools/aconfig/protos/aconfig.proto b/tools/aconfig/protos/aconfig.proto
index 4cad69a..d5e2868 100644
--- a/tools/aconfig/protos/aconfig.proto
+++ b/tools/aconfig/protos/aconfig.proto
@@ -39,6 +39,7 @@
optional string namespace = 2;
optional string description = 3;
repeated string bug = 4;
+ optional bool is_fixed_read_only = 5;
};
message flag_declarations {
@@ -75,6 +76,7 @@
optional flag_state state = 6;
optional flag_permission permission = 7;
repeated tracepoint trace = 8;
+ optional bool is_fixed_read_only = 9;
}
message parsed_flags {
diff --git a/tools/aconfig/src/codegen.rs b/tools/aconfig/src/codegen.rs
index d96d4f9..b7fb08f 100644
--- a/tools/aconfig/src/codegen.rs
+++ b/tools/aconfig/src/codegen.rs
@@ -32,12 +32,15 @@
}
pub fn is_valid_package_ident(s: &str) -> bool {
+ if !s.contains('.') {
+ return false;
+ }
s.split('.').all(is_valid_name_ident)
}
pub fn create_device_config_ident(package: &str, flag_name: &str) -> Result<String> {
ensure!(is_valid_package_ident(package), "bad package");
- ensure!(is_valid_package_ident(flag_name), "bad flag name");
+ ensure!(is_valid_name_ident(flag_name), "bad flag name");
Ok(format!("{}.{}", package, flag_name))
}
@@ -61,12 +64,13 @@
#[test]
fn test_is_valid_package_ident() {
- assert!(is_valid_package_ident("foo"));
- assert!(is_valid_package_ident("foo_bar_123"));
assert!(is_valid_package_ident("foo.bar"));
+ assert!(is_valid_package_ident("foo.bar_baz"));
assert!(is_valid_package_ident("foo.bar.a123"));
- assert!(!is_valid_package_ident("foo._bar"));
+ assert!(!is_valid_package_ident("foo_bar_123"));
+ assert!(!is_valid_package_ident("foo"));
+ assert!(!is_valid_package_ident("foo._bar"));
assert!(!is_valid_package_ident(""));
assert!(!is_valid_package_ident("123_foo"));
assert!(!is_valid_package_ident("foo-bar"));
@@ -75,6 +79,7 @@
assert!(!is_valid_package_ident(".foo.bar"));
assert!(!is_valid_package_ident("foo.bar."));
assert!(!is_valid_package_ident("."));
+ assert!(!is_valid_package_ident(".."));
assert!(!is_valid_package_ident("foo..bar"));
assert!(!is_valid_package_ident("foo.__bar"));
}
diff --git a/tools/aconfig/src/codegen_cpp.rs b/tools/aconfig/src/codegen_cpp.rs
index 2944e8a..8c2d7ba 100644
--- a/tools/aconfig/src/codegen_cpp.rs
+++ b/tools/aconfig/src/codegen_cpp.rs
@@ -16,13 +16,18 @@
use anyhow::{ensure, Result};
use serde::Serialize;
+use std::path::PathBuf;
use tinytemplate::TinyTemplate;
use crate::codegen;
-use crate::commands::OutputFile;
+use crate::commands::{CodegenMode, OutputFile};
use crate::protos::{ProtoFlagPermission, ProtoFlagState, ProtoParsedFlag};
-pub fn generate_cpp_code<'a, I>(package: &str, parsed_flags_iter: I) -> Result<OutputFile>
+pub fn generate_cpp_code<'a, I>(
+ package: &str,
+ parsed_flags_iter: I,
+ codegen_mode: CodegenMode,
+) -> Result<Vec<OutputFile>>
where
I: Iterator<Item = &'a ProtoParsedFlag>,
{
@@ -37,26 +42,52 @@
cpp_namespace,
package: package.to_string(),
readwrite,
+ for_test: codegen_mode == CodegenMode::Test,
class_elements,
};
+
+ let files = [
+ FileSpec {
+ name: &format!("{}.h", header),
+ template: include_str!("../templates/cpp_exported_header.template"),
+ dir: "include",
+ },
+ FileSpec {
+ name: &format!("{}.cc", header),
+ template: include_str!("../templates/cpp_source_file.template"),
+ dir: "",
+ },
+ ];
+ files.iter().map(|file| generate_file(file, &context)).collect()
+}
+
+pub fn generate_file(file: &FileSpec, context: &Context) -> Result<OutputFile> {
let mut template = TinyTemplate::new();
- template.add_template("cpp_code_gen", include_str!("../templates/cpp.template"))?;
- let contents = template.render("cpp_code_gen", &context)?;
- let path = ["aconfig", &(header + ".h")].iter().collect();
+ template.add_template(file.name, file.template)?;
+ let contents = template.render(file.name, &context)?;
+ let path: PathBuf = [&file.dir, &file.name].iter().collect();
Ok(OutputFile { contents: contents.into(), path })
}
#[derive(Serialize)]
-struct Context {
+pub struct FileSpec<'a> {
+ pub name: &'a str,
+ pub template: &'a str,
+ pub dir: &'a str,
+}
+
+#[derive(Serialize)]
+pub struct Context {
pub header: String,
pub cpp_namespace: String,
pub package: String,
pub readwrite: bool,
+ pub for_test: bool,
pub class_elements: Vec<ClassElement>,
}
#[derive(Serialize)]
-struct ClassElement {
+pub struct ClassElement {
pub readwrite: bool,
pub default_value: String,
pub flag_name: String,
@@ -82,51 +113,448 @@
#[cfg(test)]
mod tests {
use super::*;
+ use std::collections::HashMap;
- #[test]
- fn test_generate_cpp_code() {
- let parsed_flags = crate::test::parse_test_flags();
- let generated =
- generate_cpp_code(crate::test::TEST_PACKAGE, parsed_flags.parsed_flag.iter()).unwrap();
- assert_eq!("aconfig/com_android_aconfig_test.h", format!("{}", generated.path.display()));
- let expected = r#"
-#ifndef com_android_aconfig_test_HEADER_H
-#define com_android_aconfig_test_HEADER_H
-#include <server_configurable_flags/get_flags.h>
+ const EXPORTED_PROD_HEADER_EXPECTED: &str = r#"
+#pragma once
-using namespace server_configurable_flags;
+#ifdef __cplusplus
+
+#include <memory>
namespace com::android::aconfig::test {
- static const bool disabled_ro() {
- return false;
- }
+class flag_provider_interface {
+public:
+ virtual ~flag_provider_interface() = default;
- static const bool disabled_rw() {
- return GetServerConfigurableFlag(
- "aconfig_test",
- "com.android.aconfig.test.disabled_rw",
- "false") == "true";
- }
+ virtual bool disabled_ro() = 0;
- static const bool enabled_ro() {
- return true;
- }
+ virtual bool disabled_rw() = 0;
- static const bool enabled_rw() {
- return GetServerConfigurableFlag(
- "aconfig_test",
- "com.android.aconfig.test.enabled_rw",
- "true") == "true";
- }
+ virtual bool enabled_fixed_ro() = 0;
+
+ virtual bool enabled_ro() = 0;
+
+ virtual bool enabled_rw() = 0;
+};
+
+extern std::unique_ptr<flag_provider_interface> provider_;
+
+inline bool disabled_ro() {
+ return false;
}
+
+inline bool disabled_rw() {
+ return provider_->disabled_rw();
+}
+
+inline bool enabled_fixed_ro() {
+ return true;
+}
+
+inline bool enabled_ro() {
+ return true;
+}
+
+inline bool enabled_rw() {
+ return provider_->enabled_rw();
+}
+
+}
+
+extern "C" {
+#endif // __cplusplus
+
+bool com_android_aconfig_test_disabled_ro();
+
+bool com_android_aconfig_test_disabled_rw();
+
+bool com_android_aconfig_test_enabled_fixed_ro();
+
+bool com_android_aconfig_test_enabled_ro();
+
+bool com_android_aconfig_test_enabled_rw();
+
+#ifdef __cplusplus
+} // extern "C"
#endif
"#;
+
+ const EXPORTED_TEST_HEADER_EXPECTED: &str = r#"
+#pragma once
+
+#ifdef __cplusplus
+
+#include <memory>
+
+namespace com::android::aconfig::test {
+
+class flag_provider_interface {
+public:
+
+ virtual ~flag_provider_interface() = default;
+
+ virtual bool disabled_ro() = 0;
+
+ virtual void disabled_ro(bool val) = 0;
+
+ virtual bool disabled_rw() = 0;
+
+ virtual void disabled_rw(bool val) = 0;
+
+ virtual bool enabled_fixed_ro() = 0;
+
+ virtual void enabled_fixed_ro(bool val) = 0;
+
+ virtual bool enabled_ro() = 0;
+
+ virtual void enabled_ro(bool val) = 0;
+
+ virtual bool enabled_rw() = 0;
+
+ virtual void enabled_rw(bool val) = 0;
+
+ virtual void reset_flags() {}
+};
+
+extern std::unique_ptr<flag_provider_interface> provider_;
+
+inline bool disabled_ro() {
+ return provider_->disabled_ro();
+}
+
+inline void disabled_ro(bool val) {
+ provider_->disabled_ro(val);
+}
+
+inline bool disabled_rw() {
+ return provider_->disabled_rw();
+}
+
+inline void disabled_rw(bool val) {
+ provider_->disabled_rw(val);
+}
+
+inline bool enabled_fixed_ro() {
+ return provider_->enabled_fixed_ro();
+}
+
+inline void enabled_fixed_ro(bool val) {
+ provider_->enabled_fixed_ro(val);
+}
+
+inline bool enabled_ro() {
+ return provider_->enabled_ro();
+}
+
+inline void enabled_ro(bool val) {
+ provider_->enabled_ro(val);
+}
+
+inline bool enabled_rw() {
+ return provider_->enabled_rw();
+}
+
+inline void enabled_rw(bool val) {
+ provider_->enabled_rw(val);
+}
+
+inline void reset_flags() {
+ return provider_->reset_flags();
+}
+
+}
+
+extern "C" {
+#endif // __cplusplus
+
+bool com_android_aconfig_test_disabled_ro();
+
+void set_com_android_aconfig_test_disabled_ro(bool val);
+
+bool com_android_aconfig_test_disabled_rw();
+
+void set_com_android_aconfig_test_disabled_rw(bool val);
+
+bool com_android_aconfig_test_enabled_fixed_ro();
+
+void set_com_android_aconfig_test_enabled_fixed_ro(bool val);
+
+bool com_android_aconfig_test_enabled_ro();
+
+void set_com_android_aconfig_test_enabled_ro(bool val);
+
+bool com_android_aconfig_test_enabled_rw();
+
+void set_com_android_aconfig_test_enabled_rw(bool val);
+
+void com_android_aconfig_test_reset_flags();
+
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+
+"#;
+
+ const PROD_SOURCE_FILE_EXPECTED: &str = r#"
+#include "com_android_aconfig_test.h"
+#include <server_configurable_flags/get_flags.h>
+
+namespace com::android::aconfig::test {
+
+ class flag_provider : public flag_provider_interface {
+ public:
+
+ virtual bool disabled_ro() override {
+ return false;
+ }
+
+ virtual bool disabled_rw() override {
+ return server_configurable_flags::GetServerConfigurableFlag(
+ "aconfig_flags.aconfig_test",
+ "com.android.aconfig.test.disabled_rw",
+ "false") == "true";
+ }
+
+ virtual bool enabled_fixed_ro() override {
+ return true;
+ }
+
+ virtual bool enabled_ro() override {
+ return true;
+ }
+
+ virtual bool enabled_rw() override {
+ return server_configurable_flags::GetServerConfigurableFlag(
+ "aconfig_flags.aconfig_test",
+ "com.android.aconfig.test.enabled_rw",
+ "true") == "true";
+ }
+
+ };
+
+ std::unique_ptr<flag_provider_interface> provider_ =
+ std::make_unique<flag_provider>();
+}
+
+bool com_android_aconfig_test_disabled_ro() {
+ return false;
+}
+
+bool com_android_aconfig_test_disabled_rw() {
+ return com::android::aconfig::test::disabled_rw();
+}
+
+bool com_android_aconfig_test_enabled_fixed_ro() {
+ return true;
+}
+
+bool com_android_aconfig_test_enabled_ro() {
+ return true;
+}
+
+bool com_android_aconfig_test_enabled_rw() {
+ return com::android::aconfig::test::enabled_rw();
+}
+
+"#;
+
+ const TEST_SOURCE_FILE_EXPECTED: &str = r#"
+#include "com_android_aconfig_test.h"
+#include <server_configurable_flags/get_flags.h>
+
+namespace com::android::aconfig::test {
+
+ class flag_provider : public flag_provider_interface {
+ private:
+ std::unordered_map<std::string, bool> overrides_;
+
+ public:
+ flag_provider()
+ : overrides_()
+ {}
+
+ virtual bool disabled_ro() override {
+ auto it = overrides_.find("disabled_ro");
+ if (it != overrides_.end()) {
+ return it->second;
+ } else {
+ return false;
+ }
+ }
+
+ virtual void disabled_ro(bool val) override {
+ overrides_["disabled_ro"] = val;
+ }
+
+ virtual bool disabled_rw() override {
+ auto it = overrides_.find("disabled_rw");
+ if (it != overrides_.end()) {
+ return it->second;
+ } else {
+ return server_configurable_flags::GetServerConfigurableFlag(
+ "aconfig_flags.aconfig_test",
+ "com.android.aconfig.test.disabled_rw",
+ "false") == "true";
+ }
+ }
+
+ virtual void disabled_rw(bool val) override {
+ overrides_["disabled_rw"] = val;
+ }
+
+ virtual bool enabled_fixed_ro() override {
+ auto it = overrides_.find("enabled_fixed_ro");
+ if (it != overrides_.end()) {
+ return it->second;
+ } else {
+ return true;
+ }
+ }
+
+ virtual void enabled_fixed_ro(bool val) override {
+ overrides_["enabled_fixed_ro"] = val;
+ }
+
+ virtual bool enabled_ro() override {
+ auto it = overrides_.find("enabled_ro");
+ if (it != overrides_.end()) {
+ return it->second;
+ } else {
+ return true;
+ }
+ }
+
+ virtual void enabled_ro(bool val) override {
+ overrides_["enabled_ro"] = val;
+ }
+
+ virtual bool enabled_rw() override {
+ auto it = overrides_.find("enabled_rw");
+ if (it != overrides_.end()) {
+ return it->second;
+ } else {
+ return server_configurable_flags::GetServerConfigurableFlag(
+ "aconfig_flags.aconfig_test",
+ "com.android.aconfig.test.enabled_rw",
+ "true") == "true";
+ }
+ }
+
+ virtual void enabled_rw(bool val) override {
+ overrides_["enabled_rw"] = val;
+ }
+
+ virtual void reset_flags() override {
+ overrides_.clear();
+ }
+ };
+
+ std::unique_ptr<flag_provider_interface> provider_ =
+ std::make_unique<flag_provider>();
+}
+
+bool com_android_aconfig_test_disabled_ro() {
+ return com::android::aconfig::test::disabled_ro();
+}
+
+
+void set_com_android_aconfig_test_disabled_ro(bool val) {
+ com::android::aconfig::test::disabled_ro(val);
+}
+
+bool com_android_aconfig_test_disabled_rw() {
+ return com::android::aconfig::test::disabled_rw();
+}
+
+
+void set_com_android_aconfig_test_disabled_rw(bool val) {
+ com::android::aconfig::test::disabled_rw(val);
+}
+
+
+bool com_android_aconfig_test_enabled_fixed_ro() {
+ return com::android::aconfig::test::enabled_fixed_ro();
+}
+
+void set_com_android_aconfig_test_enabled_fixed_ro(bool val) {
+ com::android::aconfig::test::enabled_fixed_ro(val);
+}
+
+
+bool com_android_aconfig_test_enabled_ro() {
+ return com::android::aconfig::test::enabled_ro();
+}
+
+
+void set_com_android_aconfig_test_enabled_ro(bool val) {
+ com::android::aconfig::test::enabled_ro(val);
+}
+
+bool com_android_aconfig_test_enabled_rw() {
+ return com::android::aconfig::test::enabled_rw();
+}
+
+
+void set_com_android_aconfig_test_enabled_rw(bool val) {
+ com::android::aconfig::test::enabled_rw(val);
+}
+
+void com_android_aconfig_test_reset_flags() {
+ com::android::aconfig::test::reset_flags();
+}
+
+"#;
+
+ fn test_generate_cpp_code(mode: CodegenMode) {
+ let parsed_flags = crate::test::parse_test_flags();
+ let generated =
+ generate_cpp_code(crate::test::TEST_PACKAGE, parsed_flags.parsed_flag.iter(), mode)
+ .unwrap();
+ let mut generated_files_map = HashMap::new();
+ for file in generated {
+ generated_files_map.insert(
+ String::from(file.path.to_str().unwrap()),
+ String::from_utf8(file.contents.clone()).unwrap(),
+ );
+ }
+
+ let mut target_file_path = String::from("include/com_android_aconfig_test.h");
+ assert!(generated_files_map.contains_key(&target_file_path));
assert_eq!(
None,
crate::test::first_significant_code_diff(
- expected,
- &String::from_utf8(generated.contents).unwrap()
+ match mode {
+ CodegenMode::Production => EXPORTED_PROD_HEADER_EXPECTED,
+ CodegenMode::Test => EXPORTED_TEST_HEADER_EXPECTED,
+ },
+ generated_files_map.get(&target_file_path).unwrap()
)
);
+
+ target_file_path = String::from("com_android_aconfig_test.cc");
+ assert!(generated_files_map.contains_key(&target_file_path));
+ assert_eq!(
+ None,
+ crate::test::first_significant_code_diff(
+ match mode {
+ CodegenMode::Production => PROD_SOURCE_FILE_EXPECTED,
+ CodegenMode::Test => TEST_SOURCE_FILE_EXPECTED,
+ },
+ generated_files_map.get(&target_file_path).unwrap()
+ )
+ );
+ }
+
+ #[test]
+ fn test_generate_cpp_code_for_prod() {
+ test_generate_cpp_code(CodegenMode::Production);
+ }
+
+ #[test]
+ fn test_generate_cpp_code_for_test() {
+ test_generate_cpp_code(CodegenMode::Test);
}
}
diff --git a/tools/aconfig/src/codegen_java.rs b/tools/aconfig/src/codegen_java.rs
index 15eb2d6..7cdf486 100644
--- a/tools/aconfig/src/codegen_java.rs
+++ b/tools/aconfig/src/codegen_java.rs
@@ -47,9 +47,13 @@
"FeatureFlags.java",
include_str!("../templates/FeatureFlags.java.template"),
)?;
+ template.add_template(
+ "FakeFeatureFlagsImpl.java",
+ include_str!("../templates/FakeFeatureFlagsImpl.java.template"),
+ )?;
let path: PathBuf = package.split('.').collect();
- ["Flags.java", "FeatureFlagsImpl.java", "FeatureFlags.java"]
+ ["Flags.java", "FeatureFlags.java", "FeatureFlagsImpl.java", "FakeFeatureFlagsImpl.java"]
.iter()
.map(|file| {
Ok(OutputFile {
@@ -112,20 +116,23 @@
use super::*;
use std::collections::HashMap;
- const EXPECTED_FEATUREFLAGS_CONTENT: &str = r#"
+ const EXPECTED_FEATUREFLAGS_COMMON_CONTENT: &str = r#"
package com.android.aconfig.test;
public interface FeatureFlags {
boolean disabledRo();
boolean disabledRw();
+ boolean enabledFixedRo();
boolean enabledRo();
boolean enabledRw();
- }"#;
+ }
+ "#;
const EXPECTED_FLAG_COMMON_CONTENT: &str = r#"
package com.android.aconfig.test;
public final class Flags {
public static final String FLAG_DISABLED_RO = "com.android.aconfig.test.disabled_ro";
public static final String FLAG_DISABLED_RW = "com.android.aconfig.test.disabled_rw";
+ public static final String FLAG_ENABLED_FIXED_RO = "com.android.aconfig.test.enabled_fixed_ro";
public static final String FLAG_ENABLED_RO = "com.android.aconfig.test.enabled_ro";
public static final String FLAG_ENABLED_RW = "com.android.aconfig.test.enabled_rw";
@@ -135,6 +142,9 @@
public static boolean disabledRw() {
return FEATURE_FLAGS.disabledRw();
}
+ public static boolean enabledFixedRo() {
+ return FEATURE_FLAGS.enabledFixedRo();
+ }
public static boolean enabledRo() {
return FEATURE_FLAGS.enabledRo();
}
@@ -143,6 +153,64 @@
}
"#;
+ const EXPECTED_FAKEFEATUREFLAGSIMPL_CONTENT: &str = r#"
+ package com.android.aconfig.test;
+ import java.util.HashMap;
+ import java.util.Map;
+ public class FakeFeatureFlagsImpl implements FeatureFlags {
+ public FakeFeatureFlagsImpl() {
+ resetAll();
+ }
+ @Override
+ public boolean disabledRo() {
+ return getFlag(Flags.FLAG_DISABLED_RO);
+ }
+ @Override
+ public boolean disabledRw() {
+ return getFlag(Flags.FLAG_DISABLED_RW);
+ }
+ @Override
+ public boolean enabledFixedRo() {
+ return getFlag(Flags.FLAG_ENABLED_FIXED_RO);
+ }
+ @Override
+ public boolean enabledRo() {
+ return getFlag(Flags.FLAG_ENABLED_RO);
+ }
+ @Override
+ public boolean enabledRw() {
+ return getFlag(Flags.FLAG_ENABLED_RW);
+ }
+ public void setFlag(String flagName, boolean value) {
+ if (!this.mFlagMap.containsKey(flagName)) {
+ throw new IllegalArgumentException("no such flag " + flagName);
+ }
+ this.mFlagMap.put(flagName, value);
+ }
+ public void resetAll() {
+ for (Map.Entry entry : mFlagMap.entrySet()) {
+ entry.setValue(null);
+ }
+ }
+ private boolean getFlag(String flagName) {
+ Boolean value = this.mFlagMap.get(flagName);
+ if (value == null) {
+ throw new IllegalArgumentException(flagName + " is not set");
+ }
+ return value;
+ }
+ private Map<String, Boolean> mFlagMap = new HashMap<>(
+ Map.of(
+ Flags.FLAG_DISABLED_RO, false,
+ Flags.FLAG_DISABLED_RW, false,
+ Flags.FLAG_ENABLED_FIXED_RO, false,
+ Flags.FLAG_ENABLED_RO, false,
+ Flags.FLAG_ENABLED_RW, false
+ )
+ );
+ }
+ "#;
+
#[test]
fn test_generate_java_code_production() {
let parsed_flags = crate::test::parse_test_flags();
@@ -156,7 +224,8 @@
+ r#"
private static FeatureFlags FEATURE_FLAGS = new FeatureFlagsImpl();
}"#;
- let expected_featureflagsimpl_content = r#"
+
+ let expect_featureflagsimpl_content = r#"
package com.android.aconfig.test;
import android.provider.DeviceConfig;
public final class FeatureFlagsImpl implements FeatureFlags {
@@ -173,6 +242,10 @@
);
}
@Override
+ public boolean enabledFixedRo() {
+ return true;
+ }
+ @Override
public boolean enabledRo() {
return true;
}
@@ -188,8 +261,12 @@
"#;
let mut file_set = HashMap::from([
("com/android/aconfig/test/Flags.java", expect_flags_content.as_str()),
- ("com/android/aconfig/test/FeatureFlagsImpl.java", expected_featureflagsimpl_content),
- ("com/android/aconfig/test/FeatureFlags.java", EXPECTED_FEATUREFLAGS_CONTENT),
+ ("com/android/aconfig/test/FeatureFlagsImpl.java", expect_featureflagsimpl_content),
+ ("com/android/aconfig/test/FeatureFlags.java", EXPECTED_FEATUREFLAGS_COMMON_CONTENT),
+ (
+ "com/android/aconfig/test/FakeFeatureFlagsImpl.java",
+ EXPECTED_FAKEFEATUREFLAGSIMPL_CONTENT,
+ ),
]);
for file in generated_files {
@@ -219,69 +296,57 @@
CodegenMode::Test,
)
.unwrap();
+
let expect_flags_content = EXPECTED_FLAG_COMMON_CONTENT.to_string()
+ r#"
- public static void setFeatureFlagsImpl(FeatureFlags featureFlags) {
+ public static void setFeatureFlags(FeatureFlags featureFlags) {
Flags.FEATURE_FLAGS = featureFlags;
}
- public static void unsetFeatureFlagsImpl() {
+ public static void unsetFeatureFlags() {
Flags.FEATURE_FLAGS = null;
}
private static FeatureFlags FEATURE_FLAGS;
}
"#;
- let expected_featureflagsimpl_content = r#"
+ let expect_featureflagsimpl_content = r#"
package com.android.aconfig.test;
- import static java.util.stream.Collectors.toMap;
- import java.util.stream.Stream;
- import java.util.HashMap;
public final class FeatureFlagsImpl implements FeatureFlags {
@Override
public boolean disabledRo() {
- return getFlag(Flags.FLAG_DISABLED_RO);
+ throw new UnsupportedOperationException(
+ "Method is not implemented.");
}
@Override
public boolean disabledRw() {
- return getFlag(Flags.FLAG_DISABLED_RW);
+ throw new UnsupportedOperationException(
+ "Method is not implemented.");
+ }
+ @Override
+ public boolean enabledFixedRo() {
+ throw new UnsupportedOperationException(
+ "Method is not implemented.");
}
@Override
public boolean enabledRo() {
- return getFlag(Flags.FLAG_ENABLED_RO);
+ throw new UnsupportedOperationException(
+ "Method is not implemented.");
}
@Override
public boolean enabledRw() {
- return getFlag(Flags.FLAG_ENABLED_RW);
+ throw new UnsupportedOperationException(
+ "Method is not implemented.");
}
- public void setFlag(String flagName, boolean value) {
- if (!this.mFlagMap.containsKey(flagName)) {
- throw new IllegalArgumentException("no such flag" + flagName);
- }
- this.mFlagMap.put(flagName, value);
- }
- private boolean getFlag(String flagName) {
- Boolean value = this.mFlagMap.get(flagName);
- if (value == null) {
- throw new IllegalArgumentException(flagName + " is not set");
- }
- return value;
- }
- private HashMap<String, Boolean> mFlagMap = Stream.of(
- Flags.FLAG_DISABLED_RO,
- Flags.FLAG_DISABLED_RW,
- Flags.FLAG_ENABLED_RO,
- Flags.FLAG_ENABLED_RW
- )
- .collect(
- HashMap::new,
- (map, elem) -> map.put(elem, null),
- HashMap::putAll
- );
}
"#;
+
let mut file_set = HashMap::from([
("com/android/aconfig/test/Flags.java", expect_flags_content.as_str()),
- ("com/android/aconfig/test/FeatureFlagsImpl.java", expected_featureflagsimpl_content),
- ("com/android/aconfig/test/FeatureFlags.java", EXPECTED_FEATUREFLAGS_CONTENT),
+ ("com/android/aconfig/test/FeatureFlags.java", EXPECTED_FEATUREFLAGS_COMMON_CONTENT),
+ ("com/android/aconfig/test/FeatureFlagsImpl.java", expect_featureflagsimpl_content),
+ (
+ "com/android/aconfig/test/FakeFeatureFlagsImpl.java",
+ EXPECTED_FAKEFEATUREFLAGSIMPL_CONTENT,
+ ),
]);
for file in generated_files {
diff --git a/tools/aconfig/src/codegen_rust.rs b/tools/aconfig/src/codegen_rust.rs
index f931418..4e4c7dd 100644
--- a/tools/aconfig/src/codegen_rust.rs
+++ b/tools/aconfig/src/codegen_rust.rs
@@ -19,10 +19,14 @@
use tinytemplate::TinyTemplate;
use crate::codegen;
-use crate::commands::OutputFile;
+use crate::commands::{CodegenMode, OutputFile};
use crate::protos::{ProtoFlagPermission, ProtoFlagState, ProtoParsedFlag};
-pub fn generate_rust_code<'a, I>(package: &str, parsed_flags_iter: I) -> Result<OutputFile>
+pub fn generate_rust_code<'a, I>(
+ package: &str,
+ parsed_flags_iter: I,
+ codegen_mode: CodegenMode,
+) -> Result<OutputFile>
where
I: Iterator<Item = &'a ProtoParsedFlag>,
{
@@ -34,7 +38,13 @@
modules: package.split('.').map(|s| s.to_string()).collect::<Vec<_>>(),
};
let mut template = TinyTemplate::new();
- template.add_template("rust_code_gen", include_str!("../templates/rust.template"))?;
+ template.add_template(
+ "rust_code_gen",
+ match codegen_mode {
+ CodegenMode::Production => include_str!("../templates/rust_prod.template"),
+ CodegenMode::Test => include_str!("../templates/rust_test.template"),
+ },
+ )?;
let contents = template.render("rust_code_gen", &context)?;
let path = ["src", "lib.rs"].iter().collect();
Ok(OutputFile { contents: contents.into(), path })
@@ -49,41 +59,27 @@
#[derive(Serialize)]
struct TemplateParsedFlag {
+ pub readwrite: bool,
+ pub default_value: String,
pub name: String,
pub device_config_namespace: String,
pub device_config_flag: String,
-
- // TinyTemplate's conditionals are limited to single <bool> expressions; list all options here
- // Invariant: exactly one of these fields will be true
- pub is_read_only_enabled: bool,
- pub is_read_only_disabled: bool,
- pub is_read_write: bool,
}
impl TemplateParsedFlag {
#[allow(clippy::nonminimal_bool)]
fn new(package: &str, pf: &ProtoParsedFlag) -> Self {
let template = TemplateParsedFlag {
+ readwrite: pf.permission() == ProtoFlagPermission::READ_WRITE,
+ default_value: match pf.state() {
+ ProtoFlagState::ENABLED => "true".to_string(),
+ ProtoFlagState::DISABLED => "false".to_string(),
+ },
name: pf.name().to_string(),
device_config_namespace: pf.namespace().to_string(),
device_config_flag: codegen::create_device_config_ident(package, pf.name())
.expect("values checked at flag parse time"),
- is_read_only_enabled: pf.permission() == ProtoFlagPermission::READ_ONLY
- && pf.state() == ProtoFlagState::ENABLED,
- is_read_only_disabled: pf.permission() == ProtoFlagPermission::READ_ONLY
- && pf.state() == ProtoFlagState::DISABLED,
- is_read_write: pf.permission() == ProtoFlagPermission::READ_WRITE,
};
- #[rustfmt::skip]
- debug_assert!(
- (template.is_read_only_enabled && !template.is_read_only_disabled && !template.is_read_write) ||
- (!template.is_read_only_enabled && template.is_read_only_disabled && !template.is_read_write) ||
- (!template.is_read_only_enabled && !template.is_read_only_disabled && template.is_read_write),
- "TemplateParsedFlag invariant failed: {} {} {}",
- template.is_read_only_enabled,
- template.is_read_only_disabled,
- template.is_read_write,
- );
template
}
}
@@ -92,48 +88,259 @@
mod tests {
use super::*;
- #[test]
- fn test_generate_rust_code() {
- let parsed_flags = crate::test::parse_test_flags();
- let generated =
- generate_rust_code(crate::test::TEST_PACKAGE, parsed_flags.parsed_flag.iter()).unwrap();
- assert_eq!("src/lib.rs", format!("{}", generated.path.display()));
- let expected = r#"
-pub mod com {
-pub mod android {
-pub mod aconfig {
-pub mod test {
+ const PROD_EXPECTED: &str = r#"
+//! codegenerated rust flag lib
+
+/// flag provider
+pub struct FlagProvider;
+
+impl FlagProvider {
+ /// query flag disabled_ro
+ pub fn disabled_ro(&self) -> bool {
+ false
+ }
+
+ /// query flag disabled_rw
+ pub fn disabled_rw(&self) -> bool {
+ flags_rust::GetServerConfigurableFlag(
+ "aconfig_flags.aconfig_test",
+ "com.android.aconfig.test.disabled_rw",
+ "false") == "true"
+ }
+
+ /// query flag enabled_fixed_ro
+ pub fn enabled_fixed_ro(&self) -> bool {
+ true
+ }
+
+ /// query flag enabled_ro
+ pub fn enabled_ro(&self) -> bool {
+ true
+ }
+
+ /// query flag enabled_rw
+ pub fn enabled_rw(&self) -> bool {
+ flags_rust::GetServerConfigurableFlag(
+ "aconfig_flags.aconfig_test",
+ "com.android.aconfig.test.enabled_rw",
+ "true") == "true"
+ }
+}
+
+/// flag provider
+pub static PROVIDER: FlagProvider = FlagProvider;
+
+/// query flag disabled_ro
#[inline(always)]
-pub const fn r#disabled_ro() -> bool {
+pub fn disabled_ro() -> bool {
false
}
+/// query flag disabled_rw
#[inline(always)]
-pub fn r#disabled_rw() -> bool {
- flags_rust::GetServerConfigurableFlag("aconfig_test", "com.android.aconfig.test.disabled_rw", "false") == "true"
+pub fn disabled_rw() -> bool {
+ PROVIDER.disabled_rw()
}
+/// query flag enabled_fixed_ro
#[inline(always)]
-pub const fn r#enabled_ro() -> bool {
+pub fn enabled_fixed_ro() -> bool {
true
}
+/// query flag enabled_ro
#[inline(always)]
-pub fn r#enabled_rw() -> bool {
- flags_rust::GetServerConfigurableFlag("aconfig_test", "com.android.aconfig.test.enabled_rw", "false") == "true"
+pub fn enabled_ro() -> bool {
+ true
}
-}
-}
-}
+/// query flag enabled_rw
+#[inline(always)]
+pub fn enabled_rw() -> bool {
+ PROVIDER.enabled_rw()
}
"#;
+
+ const TEST_EXPECTED: &str = r#"
+//! codegenerated rust flag lib
+
+use std::collections::BTreeMap;
+use std::sync::Mutex;
+
+/// flag provider
+pub struct FlagProvider {
+ overrides: BTreeMap<&'static str, bool>,
+}
+
+impl FlagProvider {
+ /// query flag disabled_ro
+ pub fn disabled_ro(&self) -> bool {
+ self.overrides.get("disabled_ro").copied().unwrap_or(
+ false
+ )
+ }
+
+ /// set flag disabled_ro
+ pub fn set_disabled_ro(&mut self, val: bool) {
+ self.overrides.insert("disabled_ro", val);
+ }
+
+ /// query flag disabled_rw
+ pub fn disabled_rw(&self) -> bool {
+ self.overrides.get("disabled_rw").copied().unwrap_or(
+ flags_rust::GetServerConfigurableFlag(
+ "aconfig_flags.aconfig_test",
+ "com.android.aconfig.test.disabled_rw",
+ "false") == "true"
+ )
+ }
+
+ /// set flag disabled_rw
+ pub fn set_disabled_rw(&mut self, val: bool) {
+ self.overrides.insert("disabled_rw", val);
+ }
+
+ /// query flag enabled_fixed_ro
+ pub fn enabled_fixed_ro(&self) -> bool {
+ self.overrides.get("enabled_fixed_ro").copied().unwrap_or(
+ true
+ )
+ }
+
+ /// set flag enabled_fixed_ro
+ pub fn set_enabled_fixed_ro(&mut self, val: bool) {
+ self.overrides.insert("enabled_fixed_ro", val);
+ }
+
+ /// query flag enabled_ro
+ pub fn enabled_ro(&self) -> bool {
+ self.overrides.get("enabled_ro").copied().unwrap_or(
+ true
+ )
+ }
+
+ /// set flag enabled_ro
+ pub fn set_enabled_ro(&mut self, val: bool) {
+ self.overrides.insert("enabled_ro", val);
+ }
+
+ /// query flag enabled_rw
+ pub fn enabled_rw(&self) -> bool {
+ self.overrides.get("enabled_rw").copied().unwrap_or(
+ flags_rust::GetServerConfigurableFlag(
+ "aconfig_flags.aconfig_test",
+ "com.android.aconfig.test.enabled_rw",
+ "true") == "true"
+ )
+ }
+
+ /// set flag enabled_rw
+ pub fn set_enabled_rw(&mut self, val: bool) {
+ self.overrides.insert("enabled_rw", val);
+ }
+
+ /// clear all flag overrides
+ pub fn reset_flags(&mut self) {
+ self.overrides.clear();
+ }
+}
+
+/// flag provider
+pub static PROVIDER: Mutex<FlagProvider> = Mutex::new(
+ FlagProvider {overrides: BTreeMap::new()}
+);
+
+/// query flag disabled_ro
+#[inline(always)]
+pub fn disabled_ro() -> bool {
+ PROVIDER.lock().unwrap().disabled_ro()
+}
+
+/// set flag disabled_ro
+#[inline(always)]
+pub fn set_disabled_ro(val: bool) {
+ PROVIDER.lock().unwrap().set_disabled_ro(val);
+}
+
+/// query flag disabled_rw
+#[inline(always)]
+pub fn disabled_rw() -> bool {
+ PROVIDER.lock().unwrap().disabled_rw()
+}
+
+/// set flag disabled_rw
+#[inline(always)]
+pub fn set_disabled_rw(val: bool) {
+ PROVIDER.lock().unwrap().set_disabled_rw(val);
+}
+
+/// query flag enabled_fixed_ro
+#[inline(always)]
+pub fn enabled_fixed_ro() -> bool {
+ PROVIDER.lock().unwrap().enabled_fixed_ro()
+}
+
+/// set flag enabled_fixed_ro
+#[inline(always)]
+pub fn set_enabled_fixed_ro(val: bool) {
+ PROVIDER.lock().unwrap().set_enabled_fixed_ro(val);
+}
+
+/// query flag enabled_ro
+#[inline(always)]
+pub fn enabled_ro() -> bool {
+ PROVIDER.lock().unwrap().enabled_ro()
+}
+
+/// set flag enabled_ro
+#[inline(always)]
+pub fn set_enabled_ro(val: bool) {
+ PROVIDER.lock().unwrap().set_enabled_ro(val);
+}
+
+/// query flag enabled_rw
+#[inline(always)]
+pub fn enabled_rw() -> bool {
+ PROVIDER.lock().unwrap().enabled_rw()
+}
+
+/// set flag enabled_rw
+#[inline(always)]
+pub fn set_enabled_rw(val: bool) {
+ PROVIDER.lock().unwrap().set_enabled_rw(val);
+}
+
+/// clear all flag override
+pub fn reset_flags() {
+ PROVIDER.lock().unwrap().reset_flags()
+}
+"#;
+
+ fn test_generate_rust_code(mode: CodegenMode) {
+ let parsed_flags = crate::test::parse_test_flags();
+ let generated =
+ generate_rust_code(crate::test::TEST_PACKAGE, parsed_flags.parsed_flag.iter(), mode)
+ .unwrap();
+ assert_eq!("src/lib.rs", format!("{}", generated.path.display()));
assert_eq!(
None,
crate::test::first_significant_code_diff(
- expected,
+ match mode {
+ CodegenMode::Production => PROD_EXPECTED,
+ CodegenMode::Test => TEST_EXPECTED,
+ },
&String::from_utf8(generated.contents).unwrap()
)
);
}
+
+ #[test]
+ fn test_generate_rust_code_for_prod() {
+ test_generate_rust_code(CodegenMode::Production);
+ }
+
+ #[test]
+ fn test_generate_rust_code_for_test() {
+ test_generate_rust_code(CodegenMode::Test);
+ }
}
diff --git a/tools/aconfig/src/commands.rs b/tools/aconfig/src/commands.rs
index dd2087b..e4baa82 100644
--- a/tools/aconfig/src/commands.rs
+++ b/tools/aconfig/src/commands.rs
@@ -35,8 +35,15 @@
impl Input {
fn try_parse_flags(&mut self) -> Result<ProtoParsedFlags> {
let mut buffer = Vec::new();
- self.reader.read_to_end(&mut buffer)?;
+ self.reader
+ .read_to_end(&mut buffer)
+ .with_context(|| format!("failed to read {}", self.source))?;
crate::protos::parsed_flags::try_from_binary_proto(&buffer)
+ .with_context(|| self.error_context())
+ }
+
+ fn error_context(&self) -> String {
+ format!("failed to parse {}", self.source)
}
}
@@ -45,28 +52,36 @@
pub contents: Vec<u8>,
}
-const DEFAULT_FLAG_STATE: ProtoFlagState = ProtoFlagState::DISABLED;
-const DEFAULT_FLAG_PERMISSION: ProtoFlagPermission = ProtoFlagPermission::READ_WRITE;
+pub const DEFAULT_FLAG_STATE: ProtoFlagState = ProtoFlagState::DISABLED;
+pub const DEFAULT_FLAG_PERMISSION: ProtoFlagPermission = ProtoFlagPermission::READ_WRITE;
-pub fn parse_flags(package: &str, declarations: Vec<Input>, values: Vec<Input>) -> Result<Vec<u8>> {
+pub fn parse_flags(
+ package: &str,
+ declarations: Vec<Input>,
+ values: Vec<Input>,
+ default_permission: ProtoFlagPermission,
+) -> Result<Vec<u8>> {
let mut parsed_flags = ProtoParsedFlags::new();
for mut input in declarations {
let mut contents = String::new();
- input.reader.read_to_string(&mut contents)?;
+ input
+ .reader
+ .read_to_string(&mut contents)
+ .with_context(|| format!("failed to read {}", input.source))?;
let flag_declarations = crate::protos::flag_declarations::try_from_text_proto(&contents)
- .with_context(|| format!("Failed to parse {}", input.source))?;
+ .with_context(|| input.error_context())?;
ensure!(
package == flag_declarations.package(),
- "Failed to parse {}: expected package {}, got {}",
+ "failed to parse {}: expected package {}, got {}",
input.source,
package,
flag_declarations.package()
);
for mut flag_declaration in flag_declarations.flag.into_iter() {
crate::protos::flag_declaration::verify_fields(&flag_declaration)
- .with_context(|| format!("Failed to parse {}", input.source))?;
+ .with_context(|| input.error_context())?;
// create ParsedFlag using FlagDeclaration and default values
let mut parsed_flag = ProtoParsedFlag::new();
@@ -76,11 +91,17 @@
parsed_flag.set_description(flag_declaration.take_description());
parsed_flag.bug.append(&mut flag_declaration.bug);
parsed_flag.set_state(DEFAULT_FLAG_STATE);
- parsed_flag.set_permission(DEFAULT_FLAG_PERMISSION);
+ let flag_permission = if flag_declaration.is_fixed_read_only() {
+ ProtoFlagPermission::READ_ONLY
+ } else {
+ default_permission
+ };
+ parsed_flag.set_permission(flag_permission);
+ parsed_flag.set_is_fixed_read_only(flag_declaration.is_fixed_read_only());
let mut tracepoint = ProtoTracepoint::new();
tracepoint.set_source(input.source.clone());
tracepoint.set_state(DEFAULT_FLAG_STATE);
- tracepoint.set_permission(DEFAULT_FLAG_PERMISSION);
+ tracepoint.set_permission(flag_permission);
parsed_flag.trace.push(tracepoint);
// verify ParsedFlag looks reasonable
@@ -101,18 +122,32 @@
for mut input in values {
let mut contents = String::new();
- input.reader.read_to_string(&mut contents)?;
+ input
+ .reader
+ .read_to_string(&mut contents)
+ .with_context(|| format!("failed to read {}", input.source))?;
let flag_values = crate::protos::flag_values::try_from_text_proto(&contents)
- .with_context(|| format!("Failed to parse {}", input.source))?;
+ .with_context(|| input.error_context())?;
for flag_value in flag_values.flag_value.into_iter() {
crate::protos::flag_value::verify_fields(&flag_value)
- .with_context(|| format!("Failed to parse {}", input.source))?;
+ .with_context(|| input.error_context())?;
- let Some(parsed_flag) = parsed_flags.parsed_flag.iter_mut().find(|pf| pf.package() == flag_value.package() && pf.name() == flag_value.name()) else {
+ let Some(parsed_flag) = parsed_flags
+ .parsed_flag
+ .iter_mut()
+ .find(|pf| pf.package() == flag_value.package() && pf.name() == flag_value.name())
+ else {
// (silently) skip unknown flags
continue;
};
+ ensure!(
+ !parsed_flag.is_fixed_read_only()
+ || flag_value.permission() == ProtoFlagPermission::READ_ONLY,
+ "failed to set permission of flag {}, since this flag is fixed read only flag",
+ flag_value.name()
+ );
+
parsed_flag.set_state(flag_value.state());
parsed_flag.set_permission(flag_value.permission());
let mut tracepoint = ProtoTracepoint::new();
@@ -123,6 +158,8 @@
}
}
+ // Create a sorted parsed_flags
+ crate::protos::parsed_flags::sort_parsed_flags(&mut parsed_flags);
crate::protos::parsed_flags::verify_fields(&parsed_flags)?;
let mut output = Vec::new();
parsed_flags.write_to_vec(&mut output)?;
@@ -143,20 +180,20 @@
generate_java_code(package, parsed_flags.parsed_flag.iter(), codegen_mode)
}
-pub fn create_cpp_lib(mut input: Input) -> Result<OutputFile> {
+pub fn create_cpp_lib(mut input: Input, codegen_mode: CodegenMode) -> Result<Vec<OutputFile>> {
let parsed_flags = input.try_parse_flags()?;
let Some(package) = find_unique_package(&parsed_flags) else {
bail!("no parsed flags, or the parsed flags use different packages");
};
- generate_cpp_code(package, parsed_flags.parsed_flag.iter())
+ generate_cpp_code(package, parsed_flags.parsed_flag.iter(), codegen_mode)
}
-pub fn create_rust_lib(mut input: Input) -> Result<OutputFile> {
+pub fn create_rust_lib(mut input: Input, codegen_mode: CodegenMode) -> Result<OutputFile> {
let parsed_flags = input.try_parse_flags()?;
let Some(package) = find_unique_package(&parsed_flags) else {
bail!("no parsed flags, or the parsed flags use different packages");
};
- generate_rust_code(package, parsed_flags.parsed_flag.iter())
+ generate_rust_code(package, parsed_flags.parsed_flag.iter(), codegen_mode)
}
pub fn create_device_config_defaults(mut input: Input) -> Result<Vec<u8>> {
@@ -207,7 +244,7 @@
#[derive(Copy, Clone, Debug, PartialEq, Eq, ValueEnum)]
pub enum DumpFormat {
Text,
- Debug,
+ Verbose,
Protobuf,
Textproto,
}
@@ -223,18 +260,27 @@
DumpFormat::Text => {
for parsed_flag in parsed_flags.parsed_flag.into_iter() {
let line = format!(
- "{}/{}: {:?} {:?}\n",
+ "{}/{}: {:?} + {:?}\n",
parsed_flag.package(),
parsed_flag.name(),
- parsed_flag.state(),
- parsed_flag.permission()
+ parsed_flag.permission(),
+ parsed_flag.state()
);
output.extend_from_slice(line.as_bytes());
}
}
- DumpFormat::Debug => {
+ DumpFormat::Verbose => {
for parsed_flag in parsed_flags.parsed_flag.into_iter() {
- let line = format!("{:#?}\n", parsed_flag);
+ let sources: Vec<_> =
+ parsed_flag.trace.iter().map(|tracepoint| tracepoint.source()).collect();
+ let line = format!(
+ "{}/{}: {:?} + {:?} ({})\n",
+ parsed_flag.package(),
+ parsed_flag.name(),
+ parsed_flag.permission(),
+ parsed_flag.state(),
+ sources.join(", ")
+ );
output.extend_from_slice(line.as_bytes());
}
}
@@ -277,6 +323,7 @@
assert_eq!(ProtoFlagState::ENABLED, enabled_ro.state());
assert_eq!(ProtoFlagPermission::READ_ONLY, enabled_ro.permission());
assert_eq!(3, enabled_ro.trace.len());
+ assert!(!enabled_ro.is_fixed_read_only());
assert_eq!("tests/test.aconfig", enabled_ro.trace[0].source());
assert_eq!(ProtoFlagState::DISABLED, enabled_ro.trace[0].state());
assert_eq!(ProtoFlagPermission::READ_WRITE, enabled_ro.trace[0].permission());
@@ -287,8 +334,11 @@
assert_eq!(ProtoFlagState::ENABLED, enabled_ro.trace[2].state());
assert_eq!(ProtoFlagPermission::READ_ONLY, enabled_ro.trace[2].permission());
- assert_eq!(4, parsed_flags.parsed_flag.len());
+ assert_eq!(5, parsed_flags.parsed_flag.len());
for pf in parsed_flags.parsed_flag.iter() {
+ if pf.name() == "enabled_fixed_ro" {
+ continue;
+ }
let first = pf.trace.first().unwrap();
assert_eq!(DEFAULT_FLAG_STATE, first.state());
assert_eq!(DEFAULT_FLAG_PERMISSION, first.permission());
@@ -297,6 +347,85 @@
assert_eq!(pf.state(), last.state());
assert_eq!(pf.permission(), last.permission());
}
+
+ let enabled_fixed_ro =
+ parsed_flags.parsed_flag.iter().find(|pf| pf.name() == "enabled_fixed_ro").unwrap();
+ assert!(enabled_fixed_ro.is_fixed_read_only());
+ assert_eq!(ProtoFlagState::ENABLED, enabled_fixed_ro.state());
+ assert_eq!(ProtoFlagPermission::READ_ONLY, enabled_fixed_ro.permission());
+ assert_eq!(2, enabled_fixed_ro.trace.len());
+ assert_eq!(ProtoFlagPermission::READ_ONLY, enabled_fixed_ro.trace[0].permission());
+ assert_eq!(ProtoFlagPermission::READ_ONLY, enabled_fixed_ro.trace[1].permission());
+ }
+
+ #[test]
+ fn test_parse_flags_setting_default() {
+ let first_flag = r#"
+ package: "com.first"
+ flag {
+ name: "first"
+ namespace: "first_ns"
+ description: "This is the description of the first flag."
+ bug: "123"
+ }
+ "#;
+ let declaration =
+ vec![Input { source: "momery".to_string(), reader: Box::new(first_flag.as_bytes()) }];
+ let value: Vec<Input> = vec![];
+
+ let flags_bytes = crate::commands::parse_flags(
+ "com.first",
+ declaration,
+ value,
+ ProtoFlagPermission::READ_ONLY,
+ )
+ .unwrap();
+ let parsed_flags =
+ crate::protos::parsed_flags::try_from_binary_proto(&flags_bytes).unwrap();
+ assert_eq!(1, parsed_flags.parsed_flag.len());
+ let parsed_flag = parsed_flags.parsed_flag.first().unwrap();
+ assert_eq!(ProtoFlagState::DISABLED, parsed_flag.state());
+ assert_eq!(ProtoFlagPermission::READ_ONLY, parsed_flag.permission());
+ }
+
+ #[test]
+ fn test_parse_flags_override_fixed_read_only() {
+ let first_flag = r#"
+ package: "com.first"
+ flag {
+ name: "first"
+ namespace: "first_ns"
+ description: "This is the description of the first flag."
+ bug: "123"
+ is_fixed_read_only: true
+ }
+ "#;
+ let declaration =
+ vec![Input { source: "memory".to_string(), reader: Box::new(first_flag.as_bytes()) }];
+
+ let first_flag_value = r#"
+ flag_value {
+ package: "com.first"
+ name: "first"
+ state: DISABLED
+ permission: READ_WRITE
+ }
+ "#;
+ let value = vec![Input {
+ source: "memory".to_string(),
+ reader: Box::new(first_flag_value.as_bytes()),
+ }];
+ let error = crate::commands::parse_flags(
+ "com.first",
+ declaration,
+ value,
+ ProtoFlagPermission::READ_WRITE,
+ )
+ .unwrap_err();
+ assert_eq!(
+ format!("{:?}", error),
+ "failed to set permission of flag first, since this flag is fixed read only flag"
+ );
}
#[test]
@@ -320,7 +449,7 @@
let input = parse_test_flags_as_input();
let bytes = dump_parsed_flags(vec![input], DumpFormat::Text).unwrap();
let text = std::str::from_utf8(&bytes).unwrap();
- assert!(text.contains("com.android.aconfig.test/disabled_ro: DISABLED READ_ONLY"));
+ assert!(text.contains("com.android.aconfig.test/disabled_ro: READ_ONLY + DISABLED"));
}
#[test]
diff --git a/tools/aconfig/src/main.rs b/tools/aconfig/src/main.rs
index e20c60c..84073f7 100644
--- a/tools/aconfig/src/main.rs
+++ b/tools/aconfig/src/main.rs
@@ -16,7 +16,7 @@
//! `aconfig` is a build time tool to manage build time configurations, such as feature flags.
-use anyhow::{anyhow, bail, ensure, Result};
+use anyhow::{anyhow, bail, Context, Result};
use clap::{builder::ArgAction, builder::EnumValueParser, Arg, ArgMatches, Command};
use core::any::Any;
use std::fs;
@@ -44,6 +44,14 @@
.arg(Arg::new("package").long("package").required(true))
.arg(Arg::new("declarations").long("declarations").action(ArgAction::Append))
.arg(Arg::new("values").long("values").action(ArgAction::Append))
+ .arg(
+ Arg::new("default-permission")
+ .long("default-permission")
+ .value_parser(protos::flag_permission::parse_from_str)
+ .default_value(protos::flag_permission::to_string(
+ &commands::DEFAULT_FLAG_PERMISSION,
+ )),
+ )
.arg(Arg::new("cache").long("cache").required(true)),
)
.subcommand(
@@ -60,12 +68,24 @@
.subcommand(
Command::new("create-cpp-lib")
.arg(Arg::new("cache").long("cache").required(true))
- .arg(Arg::new("out").long("out").required(true)),
+ .arg(Arg::new("out").long("out").required(true))
+ .arg(
+ Arg::new("mode")
+ .long("mode")
+ .value_parser(EnumValueParser::<commands::CodegenMode>::new())
+ .default_value("production"),
+ ),
)
.subcommand(
Command::new("create-rust-lib")
.arg(Arg::new("cache").long("cache").required(true))
- .arg(Arg::new("out").long("out").required(true)),
+ .arg(Arg::new("out").long("out").required(true))
+ .arg(
+ Arg::new("mode")
+ .long("mode")
+ .value_parser(EnumValueParser::<commands::CodegenMode>::new())
+ .default_value("production"),
+ ),
)
.subcommand(
Command::new("create-device-config-defaults")
@@ -117,26 +137,27 @@
}
fn write_output_file_realtive_to_dir(root: &Path, output_file: &OutputFile) -> Result<()> {
- ensure!(
- root.is_dir(),
- "output directory {} does not exist or is not a directory",
- root.display()
- );
let path = root.join(output_file.path.clone());
let parent = path
.parent()
.ok_or(anyhow!("unable to locate parent of output file {}", path.display()))?;
- fs::create_dir_all(parent)?;
- let mut file = fs::File::create(path)?;
- file.write_all(&output_file.contents)?;
+ fs::create_dir_all(parent)
+ .with_context(|| format!("failed to create directory {}", parent.display()))?;
+ let mut file = fs::File::create(path.clone())
+ .with_context(|| format!("failed to open {}", path.display()))?;
+ file.write_all(&output_file.contents)
+ .with_context(|| format!("failed to write to {}", path.display()))?;
Ok(())
}
fn write_output_to_file_or_stdout(path: &str, data: &[u8]) -> Result<()> {
if path == "-" {
- io::stdout().write_all(data)?;
+ io::stdout().write_all(data).context("failed to write to stdout")?;
} else {
- fs::File::create(path)?.write_all(data)?;
+ fs::File::create(path)
+ .with_context(|| format!("failed to open {}", path))?
+ .write_all(data)
+ .with_context(|| format!("failed to write to {}", path))?;
}
Ok(())
}
@@ -148,14 +169,18 @@
let package = get_required_arg::<String>(sub_matches, "package")?;
let declarations = open_zero_or_more_files(sub_matches, "declarations")?;
let values = open_zero_or_more_files(sub_matches, "values")?;
- let output = commands::parse_flags(package, declarations, values)?;
+ let default_permission =
+ get_required_arg::<protos::ProtoFlagPermission>(sub_matches, "default-permission")?;
+ let output = commands::parse_flags(package, declarations, values, *default_permission)
+ .context("failed to create cache")?;
let path = get_required_arg::<String>(sub_matches, "cache")?;
write_output_to_file_or_stdout(path, &output)?;
}
Some(("create-java-lib", sub_matches)) => {
let cache = open_single_file(sub_matches, "cache")?;
let mode = get_required_arg::<CodegenMode>(sub_matches, "mode")?;
- let generated_files = commands::create_java_lib(cache, *mode)?;
+ let generated_files =
+ commands::create_java_lib(cache, *mode).context("failed to create java lib")?;
let dir = PathBuf::from(get_required_arg::<String>(sub_matches, "out")?);
generated_files
.iter()
@@ -163,31 +188,40 @@
}
Some(("create-cpp-lib", sub_matches)) => {
let cache = open_single_file(sub_matches, "cache")?;
- let generated_file = commands::create_cpp_lib(cache)?;
+ let mode = get_required_arg::<CodegenMode>(sub_matches, "mode")?;
+ let generated_files =
+ commands::create_cpp_lib(cache, *mode).context("failed to create cpp lib")?;
let dir = PathBuf::from(get_required_arg::<String>(sub_matches, "out")?);
- write_output_file_realtive_to_dir(&dir, &generated_file)?;
+ generated_files
+ .iter()
+ .try_for_each(|file| write_output_file_realtive_to_dir(&dir, file))?;
}
Some(("create-rust-lib", sub_matches)) => {
let cache = open_single_file(sub_matches, "cache")?;
- let generated_file = commands::create_rust_lib(cache)?;
+ let mode = get_required_arg::<CodegenMode>(sub_matches, "mode")?;
+ let generated_file =
+ commands::create_rust_lib(cache, *mode).context("failed to create rust lib")?;
let dir = PathBuf::from(get_required_arg::<String>(sub_matches, "out")?);
write_output_file_realtive_to_dir(&dir, &generated_file)?;
}
Some(("create-device-config-defaults", sub_matches)) => {
let cache = open_single_file(sub_matches, "cache")?;
- let output = commands::create_device_config_defaults(cache)?;
+ let output = commands::create_device_config_defaults(cache)
+ .context("failed to create device config defaults")?;
let path = get_required_arg::<String>(sub_matches, "out")?;
write_output_to_file_or_stdout(path, &output)?;
}
Some(("create-device-config-sysprops", sub_matches)) => {
let cache = open_single_file(sub_matches, "cache")?;
- let output = commands::create_device_config_sysprops(cache)?;
+ let output = commands::create_device_config_sysprops(cache)
+ .context("failed to create device config sysprops")?;
let path = get_required_arg::<String>(sub_matches, "out")?;
write_output_to_file_or_stdout(path, &output)?;
}
Some(("dump", sub_matches)) => {
let input = open_zero_or_more_files(sub_matches, "cache")?;
- let format = get_required_arg::<DumpFormat>(sub_matches, "format")?;
+ let format = get_required_arg::<DumpFormat>(sub_matches, "format")
+ .context("failed to dump previously parsed flags")?;
let output = commands::dump_parsed_flags(input, *format)?;
let path = get_required_arg::<String>(sub_matches, "out")?;
write_output_to_file_or_stdout(path, &output)?;
diff --git a/tools/aconfig/src/protos.rs b/tools/aconfig/src/protos.rs
index 4d824f2..b93abcc 100644
--- a/tools/aconfig/src/protos.rs
+++ b/tools/aconfig/src/protos.rs
@@ -92,8 +92,7 @@
ensure!(codegen::is_valid_name_ident(pdf.name()), "bad flag declaration: bad name");
ensure!(codegen::is_valid_name_ident(pdf.namespace()), "bad flag declaration: bad name");
ensure!(!pdf.description().is_empty(), "bad flag declaration: empty description");
-
- // ProtoFlagDeclaration.bug: Vec<String>: may be empty, no checks needed
+ ensure!(pdf.bug.len() == 1, "bad flag declaration: exactly one bug required");
Ok(())
}
@@ -157,6 +156,26 @@
}
}
+pub mod flag_permission {
+ use super::*;
+ use anyhow::bail;
+
+ pub fn parse_from_str(permission: &str) -> Result<ProtoFlagPermission> {
+ match permission.to_ascii_lowercase().as_str() {
+ "read_write" => Ok(ProtoFlagPermission::READ_WRITE),
+ "read_only" => Ok(ProtoFlagPermission::READ_ONLY),
+ _ => bail!("Permission needs to be read_only or read_write."),
+ }
+ }
+
+ pub fn to_string(permission: &ProtoFlagPermission) -> &str {
+ match permission {
+ ProtoFlagPermission::READ_WRITE => "read_write",
+ ProtoFlagPermission::READ_ONLY => "read_only",
+ }
+ }
+}
+
pub mod tracepoint {
use super::*;
use anyhow::ensure;
@@ -195,11 +214,15 @@
for tp in pf.trace.iter() {
super::tracepoint::verify_fields(tp)?;
}
-
- // ProtoParsedFlag.bug: Vec<String>: may be empty, no checks needed
+ ensure!(pf.bug.len() == 1, "bad flag declaration: exactly one bug required");
Ok(())
}
+
+ pub fn path_to_declaration(pf: &ProtoParsedFlag) -> &str {
+ debug_assert!(!pf.trace.is_empty());
+ pf.trace[0].source()
+ }
}
pub mod parsed_flags {
@@ -214,6 +237,8 @@
}
pub fn verify_fields(pf: &ProtoParsedFlags) -> Result<()> {
+ use crate::protos::parsed_flag::path_to_declaration;
+
let mut previous: Option<&ProtoParsedFlag> = None;
for parsed_flag in pf.parsed_flag.iter() {
if let Some(prev) = previous {
@@ -221,7 +246,12 @@
let b = create_sorting_key(parsed_flag);
match a.cmp(&b) {
Ordering::Less => {}
- Ordering::Equal => bail!("bad parsed flags: duplicate flag {}", a),
+ Ordering::Equal => bail!(
+ "bad parsed flags: duplicate flag {} (defined in {} and {})",
+ a,
+ path_to_declaration(prev),
+ path_to_declaration(parsed_flag)
+ ),
Ordering::Greater => {
bail!("bad parsed flags: not sorted: {} comes before {}", a, b)
}
@@ -243,6 +273,10 @@
Ok(merged)
}
+ pub fn sort_parsed_flags(pf: &mut ProtoParsedFlags) {
+ pf.parsed_flag.sort_by_key(create_sorting_key);
+ }
+
fn create_sorting_key(pf: &ProtoParsedFlag) -> String {
format!("{}.{}", pf.package(), pf.name())
}
@@ -263,12 +297,13 @@
namespace: "first_ns"
description: "This is the description of the first flag."
bug: "123"
- bug: "abc"
}
flag {
name: "second"
namespace: "second_ns"
description: "This is the description of the second flag."
+ bug: "abc"
+ is_fixed_read_only: true
}
"#,
)
@@ -278,14 +313,14 @@
assert_eq!(first.name(), "first");
assert_eq!(first.namespace(), "first_ns");
assert_eq!(first.description(), "This is the description of the first flag.");
- assert_eq!(first.bug.len(), 2);
- assert_eq!(first.bug[0], "123");
- assert_eq!(first.bug[1], "abc");
+ assert_eq!(first.bug, vec!["123"]);
+ assert!(!first.is_fixed_read_only());
let second = flag_declarations.flag.iter().find(|pf| pf.name() == "second").unwrap();
assert_eq!(second.name(), "second");
assert_eq!(second.namespace(), "second_ns");
assert_eq!(second.description(), "This is the description of the second flag.");
- assert_eq!(second.bug.len(), 0);
+ assert_eq!(second.bug, vec!["abc"]);
+ assert!(second.is_fixed_read_only());
// bad input: missing package in flag declarations
let error = flag_declarations::try_from_text_proto(
@@ -360,6 +395,36 @@
)
.unwrap_err();
assert!(format!("{:?}", error).contains("bad flag declaration: bad name"));
+
+ // bad input: no bug entries in flag declaration
+ let error = flag_declarations::try_from_text_proto(
+ r#"
+package: "com.foo.bar"
+flag {
+ name: "first"
+ namespace: "first_ns"
+ description: "This is the description of the first flag."
+}
+"#,
+ )
+ .unwrap_err();
+ assert!(format!("{:?}", error).contains("bad flag declaration: exactly one bug required"));
+
+ // bad input: multiple bug entries in flag declaration
+ let error = flag_declarations::try_from_text_proto(
+ r#"
+package: "com.foo.bar"
+flag {
+ name: "first"
+ namespace: "first_ns"
+ description: "This is the description of the first flag."
+ bug: "123"
+ bug: "abc"
+}
+"#,
+ )
+ .unwrap_err();
+ assert!(format!("{:?}", error).contains("bad flag declaration: exactly one bug required"));
}
#[test]
@@ -466,6 +531,7 @@
name: "first"
namespace: "first_ns"
description: "This is the description of the first flag."
+ bug: "SOME_BUG"
state: DISABLED
permission: READ_ONLY
trace {
@@ -479,6 +545,7 @@
name: "second"
namespace: "second_ns"
description: "This is the description of the second flag."
+ bug: "SOME_BUG"
state: ENABLED
permission: READ_WRITE
trace {
@@ -491,6 +558,7 @@
state: ENABLED
permission: READ_WRITE
}
+ is_fixed_read_only: true
}
"#;
let parsed_flags = try_from_binary_proto_from_text_proto(text_proto).unwrap();
@@ -500,6 +568,7 @@
assert_eq!(second.name(), "second");
assert_eq!(second.namespace(), "second_ns");
assert_eq!(second.description(), "This is the description of the second flag.");
+ assert_eq!(second.bug, vec!["SOME_BUG"]);
assert_eq!(second.state(), ProtoFlagState::ENABLED);
assert_eq!(second.permission(), ProtoFlagPermission::READ_WRITE);
assert_eq!(2, second.trace.len());
@@ -509,6 +578,7 @@
assert_eq!(second.trace[1].source(), "flags.values");
assert_eq!(second.trace[1].state(), ProtoFlagState::ENABLED);
assert_eq!(second.trace[1].permission(), ProtoFlagPermission::READ_WRITE);
+ assert!(second.is_fixed_read_only());
// valid input: empty
let parsed_flags = try_from_binary_proto_from_text_proto("").unwrap();
@@ -549,10 +619,11 @@
// bad input: parsed_flag not sorted by package
let text_proto = r#"
parsed_flag {
- package: "bbb"
+ package: "bbb.bbb"
name: "first"
namespace: "first_ns"
description: "This is the description of the first flag."
+ bug: ""
state: DISABLED
permission: READ_ONLY
trace {
@@ -562,10 +633,11 @@
}
}
parsed_flag {
- package: "aaa"
+ package: "aaa.aaa"
name: "second"
namespace: "second_ns"
description: "This is the description of the second flag."
+ bug: ""
state: ENABLED
permission: READ_WRITE
trace {
@@ -578,7 +650,7 @@
let error = try_from_binary_proto_from_text_proto(text_proto).unwrap_err();
assert_eq!(
format!("{:?}", error),
- "bad parsed flags: not sorted: bbb.first comes before aaa.second"
+ "bad parsed flags: not sorted: bbb.bbb.first comes before aaa.aaa.second"
);
// bad input: parsed_flag not sorted by name
@@ -588,6 +660,7 @@
name: "bbb"
namespace: "first_ns"
description: "This is the description of the first flag."
+ bug: ""
state: DISABLED
permission: READ_ONLY
trace {
@@ -601,6 +674,7 @@
name: "aaa"
namespace: "second_ns"
description: "This is the description of the second flag."
+ bug: ""
state: ENABLED
permission: READ_WRITE
trace {
@@ -623,6 +697,7 @@
name: "bar"
namespace: "first_ns"
description: "This is the description of the first flag."
+ bug: ""
state: DISABLED
permission: READ_ONLY
trace {
@@ -636,6 +711,7 @@
name: "bar"
namespace: "second_ns"
description: "This is the description of the second flag."
+ bug: ""
state: ENABLED
permission: READ_WRITE
trace {
@@ -646,7 +722,38 @@
}
"#;
let error = try_from_binary_proto_from_text_proto(text_proto).unwrap_err();
- assert_eq!(format!("{:?}", error), "bad parsed flags: duplicate flag com.foo.bar");
+ assert_eq!(format!("{:?}", error), "bad parsed flags: duplicate flag com.foo.bar (defined in flags.declarations and flags.declarations)");
+ }
+
+ #[test]
+ fn test_parsed_flag_path_to_declaration() {
+ let text_proto = r#"
+parsed_flag {
+ package: "com.foo"
+ name: "bar"
+ namespace: "first_ns"
+ description: "This is the description of the first flag."
+ bug: "b/12345678"
+ state: DISABLED
+ permission: READ_ONLY
+ trace {
+ source: "flags.declarations"
+ state: DISABLED
+ permission: READ_ONLY
+ }
+ trace {
+ source: "flags.values"
+ state: ENABLED
+ permission: READ_ONLY
+ }
+}
+"#;
+ let parsed_flags = try_from_binary_proto_from_text_proto(text_proto).unwrap();
+ let parsed_flag = &parsed_flags.parsed_flag[0];
+ assert_eq!(
+ crate::protos::parsed_flag::path_to_declaration(parsed_flag),
+ "flags.declarations"
+ );
}
#[test]
@@ -657,6 +764,7 @@
name: "first"
namespace: "first_ns"
description: "This is the description of the first flag."
+ bug: "a"
state: DISABLED
permission: READ_ONLY
trace {
@@ -670,6 +778,7 @@
name: "second"
namespace: "second_ns"
description: "This is the description of the second flag."
+ bug: "b"
state: ENABLED
permission: READ_WRITE
trace {
@@ -687,6 +796,7 @@
name: "first"
namespace: "first_ns"
description: "This is the description of the first flag."
+ bug: "a"
state: DISABLED
permission: READ_ONLY
trace {
@@ -703,6 +813,7 @@
package: "com.second"
name: "second"
namespace: "second_ns"
+ bug: "b"
description: "This is the description of the second flag."
state: ENABLED
permission: READ_WRITE
@@ -717,7 +828,7 @@
// bad cases
let error = parsed_flags::merge(vec![first.clone(), first.clone()]).unwrap_err();
- assert_eq!(format!("{:?}", error), "bad parsed flags: duplicate flag com.first.first");
+ assert_eq!(format!("{:?}", error), "bad parsed flags: duplicate flag com.first.first (defined in flags.declarations and flags.declarations)");
// valid cases
assert!(parsed_flags::merge(vec![]).unwrap().parsed_flag.is_empty());
diff --git a/tools/aconfig/src/test.rs b/tools/aconfig/src/test.rs
index 04bbe28..9034704 100644
--- a/tools/aconfig/src/test.rs
+++ b/tools/aconfig/src/test.rs
@@ -41,6 +41,7 @@
state: DISABLED
permission: READ_ONLY
}
+ is_fixed_read_only: false
}
parsed_flag {
package: "com.android.aconfig.test"
@@ -55,13 +56,33 @@
state: DISABLED
permission: READ_WRITE
}
+ is_fixed_read_only: false
+}
+parsed_flag {
+ package: "com.android.aconfig.test"
+ name: "enabled_fixed_ro"
+ namespace: "aconfig_test"
+ description: "This flag is fixed READ_ONLY + ENABLED"
+ bug: ""
+ state: ENABLED
+ permission: READ_ONLY
+ trace {
+ source: "tests/test.aconfig"
+ state: DISABLED
+ permission: READ_ONLY
+ }
+ trace {
+ source: "tests/first.values"
+ state: ENABLED
+ permission: READ_ONLY
+ }
+ is_fixed_read_only: true
}
parsed_flag {
package: "com.android.aconfig.test"
name: "enabled_ro"
namespace: "aconfig_test"
description: "This flag is ENABLED + READ_ONLY"
- bug: "789"
bug: "abc"
state: ENABLED
permission: READ_ONLY
@@ -80,12 +101,14 @@
state: ENABLED
permission: READ_ONLY
}
+ is_fixed_read_only: false
}
parsed_flag {
package: "com.android.aconfig.test"
name: "enabled_rw"
namespace: "aconfig_test"
description: "This flag is ENABLED + READ_WRITE"
+ bug: ""
state: ENABLED
permission: READ_WRITE
trace {
@@ -98,6 +121,7 @@
state: ENABLED
permission: READ_WRITE
}
+ is_fixed_read_only: false
}
"#;
@@ -118,6 +142,7 @@
reader: Box::new(include_bytes!("../tests/second.values").as_slice()),
},
],
+ crate::commands::DEFAULT_FLAG_PERMISSION,
)
.unwrap();
crate::protos::parsed_flags::try_from_binary_proto(&bytes).unwrap()
diff --git a/tools/aconfig/templates/FakeFeatureFlagsImpl.java.template b/tools/aconfig/templates/FakeFeatureFlagsImpl.java.template
new file mode 100644
index 0000000..82bea81
--- /dev/null
+++ b/tools/aconfig/templates/FakeFeatureFlagsImpl.java.template
@@ -0,0 +1,45 @@
+package {package_name};
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class FakeFeatureFlagsImpl implements FeatureFlags \{
+ public FakeFeatureFlagsImpl() \{
+ resetAll();
+ }
+
+{{ for item in class_elements}}
+ @Override
+ public boolean {item.method_name}() \{
+ return getFlag(Flags.FLAG_{item.flag_name_constant_suffix});
+ }
+{{ endfor}}
+ public void setFlag(String flagName, boolean value) \{
+ if (!this.mFlagMap.containsKey(flagName)) \{
+ throw new IllegalArgumentException("no such flag " + flagName);
+ }
+ this.mFlagMap.put(flagName, value);
+ }
+
+ public void resetAll() \{
+ for (Map.Entry entry : mFlagMap.entrySet()) \{
+ entry.setValue(null);
+ }
+ }
+
+ private boolean getFlag(String flagName) \{
+ Boolean value = this.mFlagMap.get(flagName);
+ if (value == null) \{
+ throw new IllegalArgumentException(flagName + " is not set");
+ }
+ return value;
+ }
+
+ private Map<String, Boolean> mFlagMap = new HashMap<>(
+ Map.of(
+ {{-for item in class_elements}}
+ Flags.FLAG_{item.flag_name_constant_suffix}, false{{ if not @last }},{{ endif }}
+ {{ -endfor }}
+ )
+ );
+}
diff --git a/tools/aconfig/templates/FeatureFlags.java.template b/tools/aconfig/templates/FeatureFlags.java.template
index b9e2cc7..e0f201f 100644
--- a/tools/aconfig/templates/FeatureFlags.java.template
+++ b/tools/aconfig/templates/FeatureFlags.java.template
@@ -1,7 +1,7 @@
package {package_name};
public interface FeatureFlags \{
- {{ for item in class_elements}}
+{{ for item in class_elements}}
boolean {item.method_name}();
- {{ endfor }}
-}
\ No newline at end of file
+{{ endfor }}
+}
diff --git a/tools/aconfig/templates/FeatureFlagsImpl.java.template b/tools/aconfig/templates/FeatureFlagsImpl.java.template
index dafd99e..96de06c 100644
--- a/tools/aconfig/templates/FeatureFlagsImpl.java.template
+++ b/tools/aconfig/templates/FeatureFlagsImpl.java.template
@@ -1,61 +1,33 @@
package {package_name};
-{{ -if is_test_mode }}
-import static java.util.stream.Collectors.toMap;
-
-import java.util.stream.Stream;
-import java.util.HashMap;
-{{ else}}
+{{ if not is_test_mode }}
{{ if is_read_write- }}
import android.provider.DeviceConfig;
-{{ -endif- }}
{{ endif }}
public final class FeatureFlagsImpl implements FeatureFlags \{
- {{ for item in class_elements}}
+{{ for item in class_elements}}
@Override
public boolean {item.method_name}() \{
- {{ -if not is_test_mode- }}
- {{ if item.is_read_write }}
+ {{ -if item.is_read_write }}
return DeviceConfig.getBoolean(
"{item.device_config_namespace}",
"{item.device_config_flag}",
{item.default_value}
);
- {{ else }}
+ {{ else }}
return {item.default_value};
- {{ -endif- }}
- {{ else }}
- return getFlag(Flags.FLAG_{item.flag_name_constant_suffix});
- {{ -endif }}
+ {{ endif- }}
}
- {{ endfor }}
-
- {{ if is_test_mode- }}
- public void setFlag(String flagName, boolean value) \{
- if (!this.mFlagMap.containsKey(flagName)) \{
- throw new IllegalArgumentException("no such flag" + flagName);
- }
- this.mFlagMap.put(flagName, value);
- }
-
- private boolean getFlag(String flagName) \{
- Boolean value = this.mFlagMap.get(flagName);
- if (value == null) \{
- throw new IllegalArgumentException(flagName + " is not set");
- }
- return value;
- }
-
- private HashMap<String, Boolean> mFlagMap = Stream.of(
- {{-for item in class_elements}}
- Flags.FLAG_{item.flag_name_constant_suffix}{{ if not @last }},{{ endif }}
- {{ -endfor }}
- )
- .collect(
- HashMap::new,
- (map, elem) -> map.put(elem, null),
- HashMap::putAll
- );
- {{ -endif }}
+{{ endfor }}
}
-
-
+{{ else }}
+{#- Generate only stub if in test mode #}
+public final class FeatureFlagsImpl implements FeatureFlags \{
+{{ for item in class_elements}}
+ @Override
+ public boolean {item.method_name}() \{
+ throw new UnsupportedOperationException(
+ "Method is not implemented.");
+ }
+{{ endfor }}
+}
+{{ endif }}
diff --git a/tools/aconfig/templates/Flags.java.template b/tools/aconfig/templates/Flags.java.template
index eef98eb..012eba6 100644
--- a/tools/aconfig/templates/Flags.java.template
+++ b/tools/aconfig/templates/Flags.java.template
@@ -1,24 +1,23 @@
package {package_name};
public final class Flags \{
- {{- for item in class_elements}}
+{{- for item in class_elements}}
public static final String FLAG_{item.flag_name_constant_suffix} = "{item.device_config_flag}";
- {{- endfor }}
- {{ for item in class_elements}}
+{{- endfor }}
+{{ for item in class_elements}}
public static boolean {item.method_name}() \{
return FEATURE_FLAGS.{item.method_name}();
}
- {{ endfor }}
- {{ if is_test_mode }}
- public static void setFeatureFlagsImpl(FeatureFlags featureFlags) \{
+{{ endfor }}
+{{ -if is_test_mode }}
+ public static void setFeatureFlags(FeatureFlags featureFlags) \{
Flags.FEATURE_FLAGS = featureFlags;
}
- public static void unsetFeatureFlagsImpl() \{
+ public static void unsetFeatureFlags() \{
Flags.FEATURE_FLAGS = null;
}
- {{ -endif}}
-
+{{ endif}}
private static FeatureFlags FEATURE_FLAGS{{ -if not is_test_mode }} = new FeatureFlagsImpl(){{ -endif- }};
}
diff --git a/tools/aconfig/templates/cpp.template b/tools/aconfig/templates/cpp.template
deleted file mode 100644
index aa36d94..0000000
--- a/tools/aconfig/templates/cpp.template
+++ /dev/null
@@ -1,21 +0,0 @@
-#ifndef {header}_HEADER_H
-#define {header}_HEADER_H
-{{ if readwrite }}
-#include <server_configurable_flags/get_flags.h>
-using namespace server_configurable_flags;
-{{ endif }}
-namespace {cpp_namespace} \{
- {{ for item in class_elements}}
- static const bool {item.flag_name}() \{
- {{ if item.readwrite- }}
- return GetServerConfigurableFlag(
- "{item.device_config_namespace}",
- "{item.device_config_flag}",
- "{item.default_value}") == "true";
- {{ -else- }}
- return {item.default_value};
- {{ -endif }}
- }
- {{ endfor }}
-}
-#endif
diff --git a/tools/aconfig/templates/cpp_exported_header.template b/tools/aconfig/templates/cpp_exported_header.template
new file mode 100644
index 0000000..4d56dbc
--- /dev/null
+++ b/tools/aconfig/templates/cpp_exported_header.template
@@ -0,0 +1,73 @@
+#pragma once
+
+#ifdef __cplusplus
+
+#include <memory>
+
+namespace {cpp_namespace} \{
+
+class flag_provider_interface \{
+public:
+ virtual ~flag_provider_interface() = default;
+ {{ for item in class_elements}}
+ virtual bool {item.flag_name}() = 0;
+
+ {{ if for_test }}
+ virtual void {item.flag_name}(bool val) = 0;
+ {{ -endif }}
+ {{ endfor }}
+
+ {{ if for_test }}
+ virtual void reset_flags() \{}
+ {{ -endif }}
+};
+
+extern std::unique_ptr<flag_provider_interface> provider_;
+
+{{ for item in class_elements}}
+inline bool {item.flag_name}() \{
+ {{ if for_test }}
+ return provider_->{item.flag_name}();
+ {{ -else- }}
+ {{ if not item.readwrite- }}
+ return {item.default_value};
+ {{ -else- }}
+ return provider_->{item.flag_name}();
+ {{ -endif }}
+ {{ -endif }}
+}
+
+{{ if for_test }}
+inline void {item.flag_name}(bool val) \{
+ provider_->{item.flag_name}(val);
+}
+{{ -endif }}
+{{ endfor }}
+
+{{ if for_test }}
+inline void reset_flags() \{
+ return provider_->reset_flags();
+}
+{{ -endif }}
+
+}
+
+extern "C" \{
+#endif // __cplusplus
+
+{{ for item in class_elements }}
+bool {header}_{item.flag_name}();
+
+{{ if for_test }}
+void set_{header}_{item.flag_name}(bool val);
+{{ -endif }}
+{{ endfor - }}
+
+{{ if for_test }}
+void {header}_reset_flags();
+{{ -endif }}
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
diff --git a/tools/aconfig/templates/cpp_source_file.template b/tools/aconfig/templates/cpp_source_file.template
new file mode 100644
index 0000000..f373bc6
--- /dev/null
+++ b/tools/aconfig/templates/cpp_source_file.template
@@ -0,0 +1,98 @@
+#include "{header}.h"
+{{ if readwrite }}
+#include <server_configurable_flags/get_flags.h>
+{{ endif }}
+
+namespace {cpp_namespace} \{
+
+{{ if for_test }}
+ class flag_provider : public flag_provider_interface \{
+ private:
+ std::unordered_map<std::string, bool> overrides_;
+
+ public:
+ flag_provider()
+ : overrides_()
+ \{}
+
+ {{ for item in class_elements}}
+ virtual bool {item.flag_name}() override \{
+ auto it = overrides_.find("{item.flag_name}");
+ if (it != overrides_.end()) \{
+ return it->second;
+ } else \{
+ {{ if item.readwrite- }}
+ return server_configurable_flags::GetServerConfigurableFlag(
+ "aconfig_flags.{item.device_config_namespace}",
+ "{item.device_config_flag}",
+ "{item.default_value}") == "true";
+ {{ -else- }}
+ return {item.default_value};
+ {{ -endif }}
+ }
+ }
+
+ virtual void {item.flag_name}(bool val) override \{
+ overrides_["{item.flag_name}"] = val;
+ }
+ {{ endfor }}
+
+ virtual void reset_flags() override \{
+ overrides_.clear();
+ }
+ };
+
+{{ -else- }}
+
+ class flag_provider : public flag_provider_interface \{
+ public:
+ {{ for item in class_elements}}
+ virtual bool {item.flag_name}() override \{
+ {{ if item.readwrite- }}
+ return server_configurable_flags::GetServerConfigurableFlag(
+ "aconfig_flags.{item.device_config_namespace}",
+ "{item.device_config_flag}",
+ "{item.default_value}") == "true";
+ {{ -else- }}
+ return {item.default_value};
+ {{ -endif }}
+ }
+ {{ endfor }}
+ };
+
+
+{{ -endif }}
+
+
+std::unique_ptr<flag_provider_interface> provider_ =
+ std::make_unique<flag_provider>();
+
+}
+
+
+{{ for item in class_elements}}
+bool {header}_{item.flag_name}() \{
+ {{ if for_test }}
+ return {cpp_namespace}::{item.flag_name}();
+ {{ -else- }}
+ {{ if not item.readwrite- }}
+ return {item.default_value};
+ {{ -else- }}
+ return {cpp_namespace}::{item.flag_name}();
+ {{ -endif }}
+ {{ -endif }}
+}
+
+{{ if for_test }}
+void set_{header}_{item.flag_name}(bool val) \{
+ {cpp_namespace}::{item.flag_name}(val);
+}
+{{ -endif }}
+{{ endfor -}}
+
+{{ if for_test }}
+void {header}_reset_flags() \{
+ {cpp_namespace}::reset_flags();
+}
+{{ -endif }}
+
diff --git a/tools/aconfig/templates/rust.template b/tools/aconfig/templates/rust.template
deleted file mode 100644
index 960c494..0000000
--- a/tools/aconfig/templates/rust.template
+++ /dev/null
@@ -1,29 +0,0 @@
-{{- for mod in modules -}}
-pub mod {mod} \{
-{{ endfor -}}
-{{- for flag in template_flags -}}
-{{- if flag.is_read_only_disabled -}}
-#[inline(always)]
-pub const fn r#{flag.name}() -> bool \{
- false
-}
-
-{{ endif -}}
-{{- if flag.is_read_only_enabled -}}
-#[inline(always)]
-pub const fn r#{flag.name}() -> bool \{
- true
-}
-
-{{ endif -}}
-{{- if flag.is_read_write -}}
-#[inline(always)]
-pub fn r#{flag.name}() -> bool \{
- flags_rust::GetServerConfigurableFlag("{flag.device_config_namespace}", "{flag.device_config_flag}", "false") == "true"
-}
-
-{{ endif -}}
-{{- endfor -}}
-{{- for mod in modules -}}
-}
-{{ endfor -}}
diff --git a/tools/aconfig/templates/rust_prod.template b/tools/aconfig/templates/rust_prod.template
new file mode 100644
index 0000000..e22ad6f
--- /dev/null
+++ b/tools/aconfig/templates/rust_prod.template
@@ -0,0 +1,38 @@
+//! codegenerated rust flag lib
+
+/// flag provider
+pub struct FlagProvider;
+
+impl FlagProvider \{
+
+ {{ for flag in template_flags }}
+ /// query flag {flag.name}
+ pub fn {flag.name}(&self) -> bool \{
+ {{ if flag.readwrite -}}
+ flags_rust::GetServerConfigurableFlag(
+ "aconfig_flags.{flag.device_config_namespace}",
+ "{flag.device_config_flag}",
+ "{flag.default_value}") == "true"
+ {{ -else- }}
+ {flag.default_value}
+ {{ -endif }}
+ }
+ {{ endfor }}
+
+}
+
+/// flag provider
+pub static PROVIDER: FlagProvider = FlagProvider;
+
+{{ for flag in template_flags }}
+/// query flag {flag.name}
+#[inline(always)]
+{{ if flag.readwrite -}}
+pub fn {flag.name}() -> bool \{
+ PROVIDER.{flag.name}()
+{{ -else- }}
+pub fn {flag.name}() -> bool \{
+ {flag.default_value}
+{{ -endif }}
+}
+{{ endfor }}
diff --git a/tools/aconfig/templates/rust_test.template b/tools/aconfig/templates/rust_test.template
new file mode 100644
index 0000000..fd1229b
--- /dev/null
+++ b/tools/aconfig/templates/rust_test.template
@@ -0,0 +1,61 @@
+//! codegenerated rust flag lib
+
+use std::collections::BTreeMap;
+use std::sync::Mutex;
+
+/// flag provider
+pub struct FlagProvider \{
+ overrides: BTreeMap<&'static str, bool>,
+}
+
+impl FlagProvider \{
+ {{ for flag in template_flags }}
+ /// query flag {flag.name}
+ pub fn {flag.name}(&self) -> bool \{
+ self.overrides.get("{flag.name}").copied().unwrap_or(
+ {{ if flag.readwrite -}}
+ flags_rust::GetServerConfigurableFlag(
+ "aconfig_flags.{flag.device_config_namespace}",
+ "{flag.device_config_flag}",
+ "{flag.default_value}") == "true"
+ {{ -else- }}
+ {flag.default_value}
+ {{ -endif }}
+ )
+ }
+
+ /// set flag {flag.name}
+ pub fn set_{flag.name}(&mut self, val: bool) \{
+ self.overrides.insert("{flag.name}", val);
+ }
+ {{ endfor }}
+
+ /// clear all flag overrides
+ pub fn reset_flags(&mut self) \{
+ self.overrides.clear();
+ }
+}
+
+/// flag provider
+pub static PROVIDER: Mutex<FlagProvider> = Mutex::new(
+ FlagProvider \{overrides: BTreeMap::new()}
+);
+
+{{ for flag in template_flags }}
+/// query flag {flag.name}
+#[inline(always)]
+pub fn {flag.name}() -> bool \{
+ PROVIDER.lock().unwrap().{flag.name}()
+}
+
+/// set flag {flag.name}
+#[inline(always)]
+pub fn set_{flag.name}(val: bool) \{
+ PROVIDER.lock().unwrap().set_{flag.name}(val);
+}
+{{ endfor }}
+
+/// clear all flag override
+pub fn reset_flags() \{
+ PROVIDER.lock().unwrap().reset_flags()
+}
diff --git a/tools/aconfig/tests/AconfigHostTest.java b/tools/aconfig/tests/AconfigHostTest.java
new file mode 100644
index 0000000..ea71b7e
--- /dev/null
+++ b/tools/aconfig/tests/AconfigHostTest.java
@@ -0,0 +1,88 @@
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+
+import com.android.aconfig.test.FakeFeatureFlagsImpl;
+import com.android.aconfig.test.FeatureFlags;
+import com.android.aconfig.test.FeatureFlagsImpl;
+import com.android.aconfig.test.Flags;
+
+@RunWith(JUnit4.class)
+public final class AconfigHostTest {
+ @Test
+ public void testThrowsExceptionIfFlagNotSet() {
+ assertThrows(NullPointerException.class, () -> Flags.disabledRo());
+ FakeFeatureFlagsImpl featureFlags = new FakeFeatureFlagsImpl();
+ assertThrows(IllegalArgumentException.class, () -> featureFlags.disabledRo());
+ }
+
+ @Test
+ public void testSetFlagInFakeFeatureFlagsImpl() {
+ FakeFeatureFlagsImpl featureFlags = new FakeFeatureFlagsImpl();
+ featureFlags.setFlag(Flags.FLAG_ENABLED_RW, true);
+ assertTrue(featureFlags.enabledRw());
+ featureFlags.setFlag(Flags.FLAG_ENABLED_RW, false);
+ assertFalse(featureFlags.enabledRw());
+
+ //Set Flags
+ assertThrows(NullPointerException.class, () -> Flags.enabledRw());
+ Flags.setFeatureFlags(featureFlags);
+ featureFlags.setFlag(Flags.FLAG_ENABLED_RW, true);
+ assertTrue(Flags.enabledRw());
+ Flags.unsetFeatureFlags();
+ }
+
+ @Test
+ public void testSetFlagWithRandomName() {
+ FakeFeatureFlagsImpl featureFlags = new FakeFeatureFlagsImpl();
+ assertThrows(IllegalArgumentException.class,
+ () -> featureFlags.setFlag("Randome_name", true));
+ }
+
+ @Test
+ public void testResetFlagsInFakeFeatureFlagsImpl() {
+ FakeFeatureFlagsImpl featureFlags = new FakeFeatureFlagsImpl();
+ featureFlags.setFlag(Flags.FLAG_ENABLED_RO, true);
+ assertTrue(featureFlags.enabledRo());
+ featureFlags.resetAll();
+ assertThrows(IllegalArgumentException.class, () -> featureFlags.enabledRo());
+
+ // Set value after reset
+ featureFlags.setFlag(Flags.FLAG_ENABLED_RO, false);
+ assertFalse(featureFlags.enabledRo());
+ }
+
+ @Test
+ public void testFlagsSetFeatureFlags() {
+ FakeFeatureFlagsImpl featureFlags = new FakeFeatureFlagsImpl();
+ featureFlags.setFlag(Flags.FLAG_ENABLED_RW, true);
+ assertThrows(NullPointerException.class, () -> Flags.enabledRw());
+ Flags.setFeatureFlags(featureFlags);
+ assertTrue(Flags.enabledRw());
+ Flags.unsetFeatureFlags();
+ }
+
+ @Test
+ public void testFlagsUnsetFeatureFlags() {
+ FakeFeatureFlagsImpl featureFlags = new FakeFeatureFlagsImpl();
+ featureFlags.setFlag(Flags.FLAG_ENABLED_RW, true);
+ assertThrows(NullPointerException.class, () -> Flags.enabledRw());
+ Flags.setFeatureFlags(featureFlags);
+ assertTrue(Flags.enabledRw());
+
+ Flags.unsetFeatureFlags();
+ assertThrows(NullPointerException.class, () -> Flags.enabledRw());
+ }
+
+ @Test
+ public void testFeatureFlagsImplNotImpl() {
+ FeatureFlags featureFlags = new FeatureFlagsImpl();
+ assertThrows(UnsupportedOperationException.class,
+ () -> featureFlags.enabledRw());
+ }
+}
diff --git a/tools/aconfig/tests/AconfigTest.java b/tools/aconfig/tests/AconfigTest.java
index 778a4c6..958b02e 100644
--- a/tools/aconfig/tests/AconfigTest.java
+++ b/tools/aconfig/tests/AconfigTest.java
@@ -1,37 +1,67 @@
+import static com.android.aconfig.test.Flags.FLAG_DISABLED_RO;
+import static com.android.aconfig.test.Flags.FLAG_DISABLED_RW;
+import static com.android.aconfig.test.Flags.FLAG_ENABLED_FIXED_RO;
+import static com.android.aconfig.test.Flags.FLAG_ENABLED_RO;
+import static com.android.aconfig.test.Flags.FLAG_ENABLED_RW;
import static com.android.aconfig.test.Flags.disabledRo;
import static com.android.aconfig.test.Flags.disabledRw;
+import static com.android.aconfig.test.Flags.enabledFixedRo;
import static com.android.aconfig.test.Flags.enabledRo;
import static com.android.aconfig.test.Flags.enabledRw;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
+import com.android.aconfig.test.FakeFeatureFlagsImpl;
+import com.android.aconfig.test.FeatureFlags;
+
@RunWith(JUnit4.class)
public final class AconfigTest {
@Test
public void testDisabledReadOnlyFlag() {
+ assertEquals("com.android.aconfig.test.disabled_ro", FLAG_DISABLED_RO);
assertFalse(disabledRo());
}
@Test
public void testEnabledReadOnlyFlag() {
+ assertEquals("com.android.aconfig.test.disabled_rw", FLAG_DISABLED_RW);
// TODO: change to assertTrue(enabledRo()) when the build supports reading tests/*.values
// (currently all flags are assigned the default READ_ONLY + DISABLED)
assertFalse(enabledRo());
}
@Test
+ public void testEnabledFixedReadOnlyFlag() {
+ assertEquals("com.android.aconfig.test.enabled_fixed_ro", FLAG_ENABLED_FIXED_RO);
+ // TODO: change to assertTrue(enabledFixedRo()) when the build supports reading tests/*.values
+ // (currently all flags are assigned the default READ_ONLY + DISABLED)
+ assertFalse(enabledFixedRo());
+ }
+
+ @Test
public void testDisabledReadWriteFlag() {
+ assertEquals("com.android.aconfig.test.enabled_ro", FLAG_ENABLED_RO);
assertFalse(disabledRw());
}
@Test
public void testEnabledReadWriteFlag() {
+ assertEquals("com.android.aconfig.test.enabled_rw", FLAG_ENABLED_RW);
// TODO: change to assertTrue(enabledRw()) when the build supports reading tests/*.values
// (currently all flags are assigned the default READ_ONLY + DISABLED)
assertFalse(enabledRw());
}
+
+ @Test
+ public void testFakeFeatureFlagsImplImpled() {
+ FakeFeatureFlagsImpl fakeFeatureFlags = new FakeFeatureFlagsImpl();
+ fakeFeatureFlags.setFlag(FLAG_ENABLED_RW, false);
+ assertFalse(fakeFeatureFlags.enabledRw());
+ }
}
diff --git a/tools/aconfig/tests/aconfig_prod_mode_test.rs b/tools/aconfig/tests/aconfig_prod_mode_test.rs
new file mode 100644
index 0000000..708604b
--- /dev/null
+++ b/tools/aconfig/tests/aconfig_prod_mode_test.rs
@@ -0,0 +1,8 @@
+#[test]
+fn test_flags() {
+ assert!(!aconfig_test_rust_library::disabled_ro());
+ assert!(!aconfig_test_rust_library::disabled_rw());
+ // TODO: Fix template to not default both disabled and enabled to false
+ assert!(!aconfig_test_rust_library::enabled_ro());
+ assert!(!aconfig_test_rust_library::enabled_rw());
+}
diff --git a/tools/aconfig/tests/aconfig_test.cpp b/tools/aconfig/tests/aconfig_test.cpp
new file mode 100644
index 0000000..10de347
--- /dev/null
+++ b/tools/aconfig/tests/aconfig_test.cpp
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2023 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 "com_android_aconfig_test.h"
+#include "gtest/gtest.h"
+
+TEST(AconfigTest, TestDisabledReadOnlyFlag) {
+ ASSERT_FALSE(com_android_aconfig_test_disabled_ro());
+}
+
+TEST(AconfigTest, TestEnabledReadOnlyFlag) {
+ // TODO: change to assertTrue(enabledRo()) when the build supports reading tests/*.values
+ // (currently all flags are assigned the default READ_ONLY + DISABLED)
+ ASSERT_FALSE(com_android_aconfig_test_enabled_ro());
+}
+
+TEST(AconfigTest, TestDisabledReadWriteFlag) {
+ ASSERT_FALSE(com_android_aconfig_test_disabled_rw());
+}
+
+TEST(AconfigTest, TestEnabledReadWriteFlag) {
+ // TODO: change to assertTrue(enabledRo()) when the build supports reading tests/*.values
+ // (currently all flags are assigned the default READ_ONLY + DISABLED)
+ ASSERT_FALSE(com_android_aconfig_test_enabled_rw());
+}
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
diff --git a/tools/aconfig/tests/aconfig_test_mode_test.rs b/tools/aconfig/tests/aconfig_test_mode_test.rs
new file mode 100644
index 0000000..7d40a44
--- /dev/null
+++ b/tools/aconfig/tests/aconfig_test_mode_test.rs
@@ -0,0 +1,23 @@
+#[test]
+fn test_flags() {
+ assert!(!aconfig_test_rust_library::disabled_ro());
+ assert!(!aconfig_test_rust_library::disabled_rw());
+ // TODO: Fix template to not default both disabled and enabled to false
+ assert!(!aconfig_test_rust_library::enabled_ro());
+ assert!(!aconfig_test_rust_library::enabled_rw());
+
+ aconfig_test_rust_library::set_disabled_ro(true);
+ assert!(aconfig_test_rust_library::disabled_ro());
+ aconfig_test_rust_library::set_disabled_rw(true);
+ assert!(aconfig_test_rust_library::disabled_rw());
+ aconfig_test_rust_library::set_enabled_ro(true);
+ assert!(aconfig_test_rust_library::enabled_ro());
+ aconfig_test_rust_library::set_enabled_rw(true);
+ assert!(aconfig_test_rust_library::enabled_rw());
+
+ aconfig_test_rust_library::reset_flags();
+ assert!(!aconfig_test_rust_library::disabled_ro());
+ assert!(!aconfig_test_rust_library::disabled_rw());
+ assert!(!aconfig_test_rust_library::enabled_ro());
+ assert!(!aconfig_test_rust_library::enabled_rw());
+}
diff --git a/tools/aconfig/tests/first.values b/tools/aconfig/tests/first.values
index e524404..a450f78 100644
--- a/tools/aconfig/tests/first.values
+++ b/tools/aconfig/tests/first.values
@@ -16,3 +16,9 @@
state: ENABLED
permission: READ_WRITE
}
+flag_value {
+ package: "com.android.aconfig.test"
+ name: "enabled_fixed_ro"
+ state: ENABLED
+ permission: READ_ONLY
+}
diff --git a/tools/aconfig/tests/test.aconfig b/tools/aconfig/tests/test.aconfig
index a8f6652..aaa6df5 100644
--- a/tools/aconfig/tests/test.aconfig
+++ b/tools/aconfig/tests/test.aconfig
@@ -2,6 +2,28 @@
# This flag's final value is calculated from:
# - test.aconfig: DISABLED + READ_WRITE (default)
+# - first.values: DISABLED + READ_WRITE
+# - second.values: ENABLED + READ_ONLY
+flag {
+ name: "enabled_ro"
+ namespace: "aconfig_test"
+ description: "This flag is ENABLED + READ_ONLY"
+ bug: "abc"
+}
+
+# This flag's final value is calculated from:
+# - test.aconfig: DISABLED + READ_WRITE (default)
+# - first.values: ENABLED + READ_WRITE
+flag {
+ name: "enabled_rw"
+ namespace: "aconfig_test"
+ description: "This flag is ENABLED + READ_WRITE"
+ # for bug fields, the empty string is a discouraged but valid value
+ bug: ""
+}
+
+# This flag's final value is calculated from:
+# - test.aconfig: DISABLED + READ_WRITE (default)
# - first.values: DISABLED + READ_ONLY
flag {
name: "disabled_ro"
@@ -19,24 +41,13 @@
bug: "456"
}
-# This flag's final value is calculated from:
-# - test.aconfig: DISABLED + READ_WRITE (default)
-# - first.values: DISABLED + READ_WRITE
-# - second.values: ENABLED + READ_ONLY
+# This flag's final value calculated from:
+# - test.aconfig: DISABLED + READ_ONLY
+# - first.values: ENABLED + READ_ONLY
flag {
- name: "enabled_ro"
+ name: "enabled_fixed_ro"
namespace: "aconfig_test"
- description: "This flag is ENABLED + READ_ONLY"
- bug: "789"
- bug: "abc"
-}
-
-# This flag's final value is calculated from:
-# - test.aconfig: DISABLED + READ_WRITE (default)
-# - first.values: ENABLED + READ_WRITE
-flag {
- name: "enabled_rw"
- namespace: "aconfig_test"
- description: "This flag is ENABLED + READ_WRITE"
- # no bug field: bug is not mandatory
+ description: "This flag is fixed READ_ONLY + ENABLED"
+ bug: ""
+ is_fixed_read_only: true
}
diff --git a/tools/buildinfo.sh b/tools/buildinfo.sh
index c2e36df..0ed9453 100755
--- a/tools/buildinfo.sh
+++ b/tools/buildinfo.sh
@@ -7,9 +7,9 @@
if [ "$BOARD_USE_VBMETA_DIGTEST_IN_FINGERPRINT" = "true" ] ; then
echo "ro.build.legacy.id=$BUILD_ID"
else
- echo "ro.build.id=$BUILD_ID"
+ echo "ro.build.id?=$BUILD_ID"
fi
-echo "ro.build.display.id=$BUILD_DISPLAY_ID"
+echo "ro.build.display.id?=$BUILD_DISPLAY_ID"
echo "ro.build.version.incremental=$BUILD_NUMBER"
echo "ro.build.version.sdk=$PLATFORM_SDK_VERSION"
echo "ro.build.version.preview_sdk=$PLATFORM_PREVIEW_SDK_VERSION"
@@ -28,7 +28,9 @@
echo "ro.build.type=$TARGET_BUILD_TYPE"
echo "ro.build.user=$BUILD_USERNAME"
echo "ro.build.host=$BUILD_HOSTNAME"
-echo "ro.build.tags=$BUILD_VERSION_TAGS"
+# TODO: Remove any tag-related optional property declarations once the goals
+# from go/arc-android-sigprop-changes have been achieved.
+echo "ro.build.tags?=$BUILD_VERSION_TAGS"
echo "ro.build.flavor=$TARGET_BUILD_FLAVOR"
# These values are deprecated, use "ro.product.cpu.abilist"
@@ -49,7 +51,7 @@
echo "ro.build.product=$TARGET_DEVICE"
echo "# Do not try to parse description or thumbprint"
-echo "ro.build.description=$PRIVATE_BUILD_DESC"
+echo "ro.build.description?=$PRIVATE_BUILD_DESC"
if [ -n "$BUILD_THUMBPRINT" ] ; then
echo "ro.build.thumbprint=$BUILD_THUMBPRINT"
fi
diff --git a/tools/list_files.py b/tools/list_files.py
index 3afa81f..4f666aa 100644
--- a/tools/list_files.py
+++ b/tools/list_files.py
@@ -18,6 +18,7 @@
from glob import glob
from pathlib import Path
from os.path import join, relpath
+from itertools import chain
import argparse
class FileLister:
@@ -27,7 +28,8 @@
self.folder_dir = args.dir
self.extensions = [e if e.startswith(".") else "." + e for e in args.extensions]
self.root = args.root
- self.files_list = list()
+ self.files_list : List[str] = list()
+ self.classes = args.classes
def get_files(self) -> None:
"""Get all files directory in the input directory including the files in the subdirectories
@@ -61,6 +63,26 @@
def list(self) -> None:
self.get_files()
self.files_list = [f for f in self.files_list if not self.extensions or Path(f).suffix in self.extensions]
+
+ # If files_list is as below:
+ # A/B/C.java
+ # A/B/D.java
+ # A/B/E.txt
+ # --classes flag converts files_list in the following format:
+ # A/B/C.class
+ # A/B/C$*.class
+ # A/B/D.class
+ # A/B/D$*.class
+ # Additional `$*`-suffixed line is appended after each line
+ # to take multiple top level classes in a single java file into account.
+ # Note that non-java files in files_list are filtered out.
+ if self.classes:
+ self.files_list = list(chain.from_iterable([
+ (class_files := str(Path(ff).with_suffix(".class")),
+ class_files.replace(".class", "$*.class"))
+ for ff in self.files_list if ff.endswith(".java")
+ ]))
+
self.write()
def write(self) -> None:
@@ -95,6 +117,10 @@
help="optional directory to replace the root directories of output.")
parser.add_argument('--extensions', nargs='*', default=list(), dest='extensions',
help="Extensions to include in the output. If not set, all files are included")
+ parser.add_argument('--classes', dest='classes', action=argparse.BooleanOptionalAction,
+ help="Optional flag. If passed, outputs a list of pattern of class files \
+ that will be produced by compiling java files in the input dir. \
+ Non-java files in the input directory will be ignored.")
args = parser.parse_args()
diff --git a/tools/releasetools/Android.bp b/tools/releasetools/Android.bp
index 7a2dcb7..bd347a1 100644
--- a/tools/releasetools/Android.bp
+++ b/tools/releasetools/Android.bp
@@ -165,10 +165,10 @@
"ota_utils_lib",
],
required: [
+ "apexd_host",
"brillo_update_payload",
"checkvintf",
"generate_gki_certificate",
- "minigzip",
"lz4",
"toybox",
"unpack_bootimg",
@@ -244,7 +244,6 @@
"bsdiff",
"generate_gki_certificate",
"imgdiff",
- "minigzip",
"lz4",
"mkbootfs",
"signapk",
@@ -310,7 +309,6 @@
"deapexer",
"generate_gki_certificate",
"imgdiff",
- "minigzip",
"lz4",
"mkbootfs",
"signapk",
@@ -347,6 +345,7 @@
},
srcs: [
"merge_ota.py",
+ "ota_signing_utils.py",
],
libs: [
"ota_metadata_proto",
@@ -496,6 +495,26 @@
}
python_binary_host {
+ name: "ota_from_raw_img",
+ srcs: [
+ "ota_from_raw_img.py",
+ "ota_signing_utils.py",
+ ],
+ main: "ota_from_raw_img.py",
+ defaults: [
+ "releasetools_binary_defaults",
+ ],
+ required: [
+ "delta_generator",
+ ],
+ libs: [
+ "ota_metadata_proto",
+ "releasetools_common",
+ "ota_utils_lib",
+ ],
+}
+
+python_binary_host {
name: "ota_package_parser",
defaults: ["releasetools_binary_defaults"],
srcs: [
@@ -593,6 +612,7 @@
"sign_target_files_apks.py",
"validate_target_files.py",
"merge_ota.py",
+ "ota_signing_utils.py",
":releasetools_merge_sources",
":releasetools_merge_tests",
@@ -624,6 +644,7 @@
},
},
required: [
+ "apexd_host",
"deapexer",
],
}
diff --git a/tools/releasetools/add_img_to_target_files.py b/tools/releasetools/add_img_to_target_files.py
index 465d222..31f8736 100644
--- a/tools/releasetools/add_img_to_target_files.py
+++ b/tools/releasetools/add_img_to_target_files.py
@@ -517,12 +517,14 @@
return img.name
-def AddCustomImages(output_zip, partition_name):
- """Adds and signs custom images in IMAGES/.
+def AddCustomImages(output_zip, partition_name, image_list):
+ """Adds and signs avb custom images as needed in IMAGES/.
Args:
output_zip: The output zip file (needs to be already open), or None to
write images to OPTIONS.input_tmp/.
+ partition_name: The custom image partition name.
+ image_list: The image list of the custom image partition.
Uses the image under IMAGES/ if it already exists. Otherwise looks for the
image under PREBUILT_IMAGES/, signs it as needed, and returns the image name.
@@ -531,19 +533,20 @@
AssertionError: If image can't be found.
"""
+ builder = None
key_path = OPTIONS.info_dict.get("avb_{}_key_path".format(partition_name))
- algorithm = OPTIONS.info_dict.get("avb_{}_algorithm".format(partition_name))
- extra_args = OPTIONS.info_dict.get(
- "avb_{}_add_hashtree_footer_args".format(partition_name))
- partition_size = OPTIONS.info_dict.get(
- "avb_{}_partition_size".format(partition_name))
+ if key_path is not None:
+ algorithm = OPTIONS.info_dict.get("avb_{}_algorithm".format(partition_name))
+ extra_args = OPTIONS.info_dict.get(
+ "avb_{}_add_hashtree_footer_args".format(partition_name))
+ partition_size = OPTIONS.info_dict.get(
+ "avb_{}_partition_size".format(partition_name))
- builder = verity_utils.CreateCustomImageBuilder(
- OPTIONS.info_dict, partition_name, partition_size,
- key_path, algorithm, extra_args)
+ builder = verity_utils.CreateCustomImageBuilder(
+ OPTIONS.info_dict, partition_name, partition_size,
+ key_path, algorithm, extra_args)
- for img_name in OPTIONS.info_dict.get(
- "avb_{}_image_list".format(partition_name)).split():
+ for img_name in image_list:
custom_image = OutputFile(
output_zip, OPTIONS.input_tmp, "IMAGES", img_name)
if os.path.exists(custom_image.name):
@@ -684,34 +687,6 @@
return img.name
-def AddPartitionTable(output_zip):
- """Create a partition table image and store it in output_zip."""
-
- img = OutputFile(
- output_zip, OPTIONS.input_tmp, "IMAGES", "partition-table.img")
- bpt = OutputFile(
- output_zip, OPTIONS.input_tmp, "META", "partition-table.bpt")
-
- # use BPTTOOL from environ, or "bpttool" if empty or not set.
- bpttool = os.getenv("BPTTOOL") or "bpttool"
- cmd = [bpttool, "make_table", "--output_json", bpt.name,
- "--output_gpt", img.name]
- input_files_str = OPTIONS.info_dict["board_bpt_input_files"]
- input_files = input_files_str.split()
- for i in input_files:
- cmd.extend(["--input", i])
- disk_size = OPTIONS.info_dict.get("board_bpt_disk_size")
- if disk_size:
- cmd.extend(["--disk_size", disk_size])
- args = OPTIONS.info_dict.get("board_bpt_make_table_args")
- if args:
- cmd.extend(shlex.split(args))
- common.RunAndCheckOutput(cmd)
-
- img.Write()
- bpt.Write()
-
-
def AddCache(output_zip):
"""Create an empty cache image and store it in output_zip."""
@@ -1087,10 +1062,6 @@
banner("cache")
AddCache(output_zip)
- if OPTIONS.info_dict.get("board_bpt_enable") == "true":
- banner("partition-table")
- AddPartitionTable(output_zip)
-
add_partition("dtbo",
OPTIONS.info_dict.get("has_dtbo") == "true", AddDtbo, [])
add_partition("pvmfw",
@@ -1098,18 +1069,29 @@
# Custom images.
custom_partitions = OPTIONS.info_dict.get(
- "avb_custom_images_partition_list", "").strip().split()
+ "custom_images_partition_list", "").strip().split()
for partition_name in custom_partitions:
partition_name = partition_name.strip()
banner("custom images for " + partition_name)
- partitions[partition_name] = AddCustomImages(output_zip, partition_name)
+ image_list = OPTIONS.info_dict.get(
+ "{}_image_list".format(partition_name)).split()
+ partitions[partition_name] = AddCustomImages(output_zip, partition_name, image_list)
+
+ avb_custom_partitions = OPTIONS.info_dict.get(
+ "avb_custom_images_partition_list", "").strip().split()
+ for partition_name in avb_custom_partitions:
+ partition_name = partition_name.strip()
+ banner("avb custom images for " + partition_name)
+ image_list = OPTIONS.info_dict.get(
+ "avb_{}_image_list".format(partition_name)).split()
+ partitions[partition_name] = AddCustomImages(output_zip, partition_name, image_list)
if OPTIONS.info_dict.get("avb_enable") == "true":
# vbmeta_partitions includes the partitions that should be included into
# top-level vbmeta.img, which are the ones that are not included in any
# chained VBMeta image plus the chained VBMeta images themselves.
- # Currently custom_partitions are all chained to VBMeta image.
- vbmeta_partitions = common.AVB_PARTITIONS[:] + tuple(custom_partitions)
+ # Currently avb_custom_partitions are all chained to VBMeta image.
+ vbmeta_partitions = common.AVB_PARTITIONS[:] + tuple(avb_custom_partitions)
vbmeta_system = OPTIONS.info_dict.get("avb_vbmeta_system", "").strip()
if vbmeta_system:
diff --git a/tools/releasetools/build_image.py b/tools/releasetools/build_image.py
index 11bd784..8c6d597 100755
--- a/tools/releasetools/build_image.py
+++ b/tools/releasetools/build_image.py
@@ -683,7 +683,9 @@
d = {}
TryParseFingerprint(glob_dict)
- d["timestamp"] = FIXED_FILE_TIMESTAMP
+ # Set fixed timestamp for building the OTA package.
+ if "use_fixed_timestamp" in glob_dict:
+ d["timestamp"] = FIXED_FILE_TIMESTAMP
if "build.prop" in glob_dict:
timestamp = glob_dict["build.prop"].GetProp("ro.build.date.utc")
if timestamp:
diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py
index 091121f..ec53a47 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -96,7 +96,6 @@
self.cache_size = None
self.stash_threshold = 0.8
self.logfile = None
- self.host_tools = {}
self.sepolicy_name = 'sepolicy.apex'
@@ -225,23 +224,15 @@
logging.config.dictConfig(config)
-def SetHostToolLocation(tool_name, location):
- OPTIONS.host_tools[tool_name] = location
-
-
def FindHostToolPath(tool_name):
"""Finds the path to the host tool.
Args:
tool_name: name of the tool to find
Returns:
- path to the tool if found under either one of the host_tools map or under
- the same directory as this binary is located at. If not found, tool_name
- is returned.
+ path to the tool if found under the same directory as this binary is located at. If not found,
+ tool_name is returned.
"""
- if tool_name in OPTIONS.host_tools:
- return OPTIONS.host_tools[tool_name]
-
my_dir = os.path.dirname(os.path.realpath(sys.argv[0]))
tool_path = os.path.join(my_dir, tool_name)
if os.path.exists(tool_path):
@@ -459,6 +450,10 @@
return system_prop and system_prop.GetProp("ro.build.version.release") == "11"
@property
+ def vabc_compression_param(self):
+ return self.get("virtual_ab_compression_method", "")
+
+ @property
def vendor_api_level(self):
vendor_prop = self.info_dict.get("vendor.build.prop")
if not vendor_prop:
@@ -985,7 +980,7 @@
each of the variables.
ramdisk_format: If name is "boot", the format of ramdisk inside the
boot image. Otherwise, its value is ignored.
- Use lz4 to decompress by default. If its value is gzip, use minigzip.
+ Use lz4 to decompress by default. If its value is gzip, use gzip.
"""
def __init__(self, input_file, name, placeholder_values=None):
@@ -1429,7 +1424,7 @@
if os.path.exists(new_path):
return new_path
raise ExternalError(
- "Failed to find {}".format(new_path))
+ "Failed to find {}".format(path))
if not split_args:
return split_args
@@ -1638,9 +1633,9 @@
p2 = Run(["lz4", "-l", "-12", "--favor-decSpeed"], stdin=p1.stdout,
stdout=ramdisk_img.file.fileno())
elif ramdisk_format == RamdiskFormat.GZ:
- p2 = Run(["minigzip"], stdin=p1.stdout, stdout=ramdisk_img.file.fileno())
+ p2 = Run(["gzip"], stdin=p1.stdout, stdout=ramdisk_img.file.fileno())
else:
- raise ValueError("Only support lz4 or minigzip ramdisk format.")
+ raise ValueError("Only support lz4 or gzip ramdisk format.")
p2.wait()
p1.wait()
@@ -2120,20 +2115,33 @@
# According to https://stackoverflow.com/questions/434641/how-do-i-set-permissions-attributes-on-a-file-in-a-zip-file-using-pythons-zip/6297838#6297838
# higher bits of |external_attr| are unix file permission and types
unix_filetype = info.external_attr >> 16
+ file_perm = unix_filetype & 0o777
def CheckMask(a, mask):
return (a & mask) == mask
def IsSymlink(a):
return CheckMask(a, stat.S_IFLNK)
+
+ def IsDir(a):
+ return CheckMask(a, stat.S_IFDIR)
# python3.11 zipfile implementation doesn't handle symlink correctly
if not IsSymlink(unix_filetype):
- return input_zip.extract(info, dirname)
+ target = input_zip.extract(info, dirname)
+ # We want to ensure that the file is at least read/writable by owner and readable by all users
+ if IsDir(unix_filetype):
+ os.chmod(target, file_perm | 0o755)
+ else:
+ os.chmod(target, file_perm | 0o644)
+ return target
if dirname is None:
dirname = os.getcwd()
target = os.path.join(dirname, info.filename)
os.makedirs(os.path.dirname(target), exist_ok=True)
+ if os.path.exists(target):
+ os.unlink(target)
os.symlink(input_zip.read(info).decode(), target)
+ return target
def UnzipToDir(filename, dirname, patterns=None):
@@ -2425,8 +2433,9 @@
apk_name, proc.returncode, stdoutdata, stderrdata))
for line in stdoutdata.split("\n"):
- # Looking for lines such as sdkVersion:'23' or sdkVersion:'M'.
- m = re.match(r'sdkVersion:\'([^\']*)\'', line)
+ # Due to ag/24161708, looking for lines such as minSdkVersion:'23',minSdkVersion:'M'
+ # or sdkVersion:'23', sdkVersion:'M'.
+ m = re.match(r'(?:minSdkVersion|sdkVersion):\'([^\']*)\'', line)
if m:
return m.group(1)
raise ExternalError("No minSdkVersion returned by aapt2")
@@ -4075,7 +4084,7 @@
Get build.prop from ramdisk within the boot image
Args:
- boot_img: the boot image file. Ramdisk must be compressed with lz4 or minigzip format.
+ boot_img: the boot image file. Ramdisk must be compressed with lz4 or gzip format.
Return:
An extracted file that stores properties in the boot image.
@@ -4094,11 +4103,11 @@
elif ramdisk_format == RamdiskFormat.GZ:
with open(ramdisk, 'rb') as input_stream:
with open(uncompressed_ramdisk, 'wb') as output_stream:
- p2 = Run(['minigzip', '-d'], stdin=input_stream.fileno(),
+ p2 = Run(['gzip', '-d'], stdin=input_stream.fileno(),
stdout=output_stream.fileno())
p2.wait()
else:
- logger.error('Only support lz4 or minigzip ramdisk format.')
+ logger.error('Only support lz4 or gzip ramdisk format.')
return None
abs_uncompressed_ramdisk = os.path.abspath(uncompressed_ramdisk)
diff --git a/tools/releasetools/img_from_target_files.py b/tools/releasetools/img_from_target_files.py
index fa53ad2..5412b2a 100755
--- a/tools/releasetools/img_from_target_files.py
+++ b/tools/releasetools/img_from_target_files.py
@@ -65,6 +65,7 @@
OPTIONS.build_super = None
OPTIONS.sparse_userimages = None
OPTIONS.use_fastboot_info = False
+OPTIONS.build_super_image = None
def LoadOptions(input_file):
"""Loads information from input_file to OPTIONS.
@@ -174,7 +175,13 @@
input_tmp = common.UnzipTemp(input_file)
super_file = common.MakeTempFile('super_', '.img')
- BuildSuperImage(input_tmp, super_file)
+
+ # Allow overriding the BUILD_SUPER_IMAGE binary
+ if OPTIONS.build_super_image:
+ command = [OPTIONS.build_super_image, input_tmp, super_file]
+ common.RunAndCheckOutput(command)
+ else:
+ BuildSuperImage(input_tmp, super_file)
logger.info('Writing super.img to archive...')
with zipfile.ZipFile(
@@ -231,6 +238,8 @@
OPTIONS.bootable_only = True
elif o == '--additional':
OPTIONS.additional_entries.append(a)
+ elif o == '--build_super_image':
+ OPTIONS.build_super_image = a
else:
return False
return True
@@ -240,6 +249,7 @@
extra_long_opts=[
'additional=',
'bootable_zip',
+ 'build_super_image=',
],
extra_option_handler=option_handler)
if len(args) != 2:
diff --git a/tools/releasetools/merge/merge_meta.py b/tools/releasetools/merge/merge_meta.py
index b61f039..81c3510 100644
--- a/tools/releasetools/merge/merge_meta.py
+++ b/tools/releasetools/merge/merge_meta.py
@@ -124,10 +124,10 @@
merged_meta_dir=merged_meta_dir,
file_name=file_name)
- MergeUpdateEngineConfig(
- framework_meta_dir,
- vendor_meta_dir, merged_meta_dir,
- )
+ if OPTIONS.merged_misc_info.get('ab_update') == 'true':
+ MergeUpdateEngineConfig(
+ framework_meta_dir,
+ vendor_meta_dir, merged_meta_dir)
# Write the now-finalized OPTIONS.merged_misc_info.
merge_utils.WriteSortedData(
diff --git a/tools/releasetools/merge/merge_utils.py b/tools/releasetools/merge/merge_utils.py
index b5683a8..d446fc0 100644
--- a/tools/releasetools/merge/merge_utils.py
+++ b/tools/releasetools/merge/merge_utils.py
@@ -217,7 +217,7 @@
# Partitions that are grabbed from the framework partial build by default.
_FRAMEWORK_PARTITIONS = {
- 'system', 'product', 'system_ext', 'system_other', 'root', 'system_dlkm',
+ 'system', 'product', 'system_ext', 'system_other', 'root',
'vbmeta_system', 'pvmfw'
}
diff --git a/tools/releasetools/merge_ota.py b/tools/releasetools/merge_ota.py
index 441312c..24d9ea9 100644
--- a/tools/releasetools/merge_ota.py
+++ b/tools/releasetools/merge_ota.py
@@ -14,7 +14,6 @@
import argparse
import logging
-import shlex
import struct
import sys
import update_payload
@@ -31,6 +30,7 @@
from payload_signer import PayloadSigner
from ota_utils import PayloadGenerator, METADATA_PROTO_NAME, FinalizeMetadata
+from ota_signing_utils import AddSigningArgumentParse
logger = logging.getLogger(__name__)
@@ -126,7 +126,7 @@
ExtendPartitionUpdates(output_manifest.partitions, manifest.partitions)
try:
MergeDynamicPartitionMetadata(
- output_manifest.dynamic_partition_metadata, manifest.dynamic_partition_metadata)
+ output_manifest.dynamic_partition_metadata, manifest.dynamic_partition_metadata)
except DuplicatePartitionError:
logger.error(
"OTA %s has duplicate partition with some of the previous OTAs", payload.name)
@@ -190,6 +190,7 @@
f"OTA {partition_to_ota[part].name} and {payload.name} have duplicating partition {part}")
partition_to_ota[part] = payload
+
def ApexInfo(file_paths):
if len(file_paths) > 1:
logger.info("More than one target file specified, will ignore "
@@ -201,33 +202,19 @@
return apex_info_bytes
return None
-def ParseSignerArgs(args):
- if args is None:
- return None
- return shlex.split(args)
def main(argv):
parser = argparse.ArgumentParser(description='Merge multiple partial OTAs')
parser.add_argument('packages', type=str, nargs='+',
help='Paths to OTA packages to merge')
- parser.add_argument('--package_key', type=str,
- help='Paths to private key for signing payload')
- parser.add_argument('--search_path', type=str,
- help='Search path for framework/signapk.jar')
- parser.add_argument('--payload_signer', type=str,
- help='Path to custom payload signer')
- parser.add_argument('--payload_signer_args', type=ParseSignerArgs,
- help='Arguments for payload signer if necessary')
- parser.add_argument('--payload_signer_maximum_signature_size', type=str,
- help='Maximum signature size (in bytes) that would be '
- 'generated by the given payload signer')
parser.add_argument('--output', type=str,
help='Paths to output merged ota', required=True)
parser.add_argument('--metadata_ota', type=str,
help='Output zip will use build metadata from this OTA package, if unspecified, use the last OTA package in merge list')
- parser.add_argument('--private_key_suffix', type=str,
- help='Suffix to be appended to package_key path', default=".pk8")
- parser.add_argument('-v', action="store_true", help="Enable verbose logging", dest="verbose")
+ parser.add_argument('-v', action="store_true",
+ help="Enable verbose logging", dest="verbose")
+ AddSigningArgumentParse(parser)
+
parser.epilog = ('This tool can also be used to resign a regular OTA. For a single regular OTA, '
'apex_info.pb will be written to output. When merging multiple OTAs, '
'apex_info.pb will not be written.')
@@ -301,8 +288,6 @@
return 0
-
-
if __name__ == '__main__':
logging.basicConfig()
sys.exit(main(sys.argv))
diff --git a/tools/releasetools/ota_from_raw_img.py b/tools/releasetools/ota_from_raw_img.py
new file mode 100644
index 0000000..37504d1
--- /dev/null
+++ b/tools/releasetools/ota_from_raw_img.py
@@ -0,0 +1,113 @@
+#!/usr/bin/env python
+#
+# 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.
+
+"""
+Given a series of .img files, produces an OTA package that installs thoese images
+"""
+
+import sys
+import os
+import argparse
+import subprocess
+import tempfile
+import logging
+import zipfile
+
+import common
+from payload_signer import PayloadSigner
+from ota_utils import PayloadGenerator
+from ota_signing_utils import AddSigningArgumentParse
+
+
+logger = logging.getLogger(__name__)
+
+
+def ResolveBinaryPath(filename, search_path):
+ if not search_path:
+ return filename
+ if not os.path.exists(search_path):
+ return filename
+ path = os.path.join(search_path, "bin", filename)
+ if os.path.exists(path):
+ return path
+ path = os.path.join(search_path, filename)
+ if os.path.exists(path):
+ return path
+ return path
+
+
+def main(argv):
+ parser = argparse.ArgumentParser(
+ prog=argv[0], description="Given a series of .img files, produces a full OTA package that installs thoese images")
+ parser.add_argument("images", nargs="+", type=str,
+ help="List of images to generate OTA")
+ parser.add_argument("--partition_names", nargs='+', type=str,
+ help="Partition names to install the images, default to basename of the image(no file name extension)")
+ parser.add_argument('--output', type=str,
+ help='Paths to output merged ota', required=True)
+ parser.add_argument('--max_timestamp', type=int,
+ help='Maximum build timestamp allowed to install this OTA')
+ parser.add_argument("-v", action="store_true",
+ help="Enable verbose logging", dest="verbose")
+ AddSigningArgumentParse(parser)
+
+ args = parser.parse_args(argv[1:])
+ if args.verbose:
+ logger.setLevel(logging.INFO)
+ logger.info(args)
+ if not args.partition_names:
+ args.partition_names = [os.path.os.path.splitext(os.path.basename(path))[
+ 0] for path in args.images]
+ with tempfile.NamedTemporaryFile() as unsigned_payload:
+ cmd = [ResolveBinaryPath("delta_generator", args.search_path)]
+ cmd.append("--partition_names=" + ",".join(args.partition_names))
+ cmd.append("--new_partitions=" + ",".join(args.images))
+ cmd.append("--out_file=" + unsigned_payload.name)
+ if args.max_timestamp:
+ cmd.append("--max_timestamp=" + str(args.max_timestamp))
+ logger.info("Running %s", cmd)
+
+ subprocess.run(cmd)
+ generator = PayloadGenerator()
+ generator.payload_file = unsigned_payload.name
+ logger.info("Payload size: %d", os.path.getsize(generator.payload_file))
+
+ # Get signing keys
+ key_passwords = common.GetKeyPasswords([args.package_key])
+
+ if args.package_key:
+ logger.info("Signing payload...")
+ # TODO: remove OPTIONS when no longer used as fallback in payload_signer
+ common.OPTIONS.payload_signer_args = None
+ common.OPTIONS.payload_signer_maximum_signature_size = None
+ signer = PayloadSigner(args.package_key, args.private_key_suffix,
+ key_passwords[args.package_key],
+ payload_signer=args.payload_signer,
+ payload_signer_args=args.payload_signer_args,
+ payload_signer_maximum_signature_size=args.payload_signer_maximum_signature_size)
+ generator.payload_file = unsigned_payload.name
+ generator.Sign(signer)
+
+ logger.info("Payload size: %d", os.path.getsize(generator.payload_file))
+
+ logger.info("Writing to %s", args.output)
+ with zipfile.ZipFile(args.output, "w") as zfp:
+ generator.WriteToZip(zfp)
+
+
+if __name__ == "__main__":
+ logging.basicConfig()
+ main(sys.argv)
diff --git a/tools/releasetools/ota_from_target_files.py b/tools/releasetools/ota_from_target_files.py
index f3e6f1e..56ec929 100755
--- a/tools/releasetools/ota_from_target_files.py
+++ b/tools/releasetools/ota_from_target_files.py
@@ -147,7 +147,7 @@
A/B OTA specific options
--disable_fec_computation
- Disable the on device FEC data computation for incremental updates.
+ Disable the on device FEC data computation for incremental updates. OTA will be larger but installation will be faster.
--include_secondary
Additionally include the payload for secondary slot images (default:
@@ -224,7 +224,7 @@
wait time in recovery.
--enable_vabc_xor
- Enable the VABC xor feature. Will reduce space requirements for OTA
+ Enable the VABC xor feature. Will reduce space requirements for OTA, but OTA installation will be slower.
--force_minor_version
Override the update_engine minor version for delta generation.
@@ -233,7 +233,10 @@
A colon ':' separated list of compressors. Allowed values are bz2 and brotli.
--enable_zucchini
- Whether to enable to zucchini feature. Will generate smaller OTA but uses more memory.
+ Whether to enable to zucchini feature. Will generate smaller OTA but uses more memory, OTA generation will take longer.
+
+ --enable_puffdiff
+ Whether to enable to puffdiff feature. Will generate smaller OTA but uses more memory, OTA generation will take longer.
--enable_lz4diff
Whether to enable lz4diff feature. Will generate smaller OTA for EROFS but
@@ -244,7 +247,9 @@
older SPL.
--vabc_compression_param
- Compression algorithm to be used for VABC. Available options: gz, brotli, none
+ Compression algorithm to be used for VABC. Available options: gz, lz4, zstd, brotli, none.
+ Compression level can be specified by appending ",$LEVEL" to option.
+ e.g. --vabc_compression_param=gz,9 specifies level 9 compression with gz algorithm
--security_patch_level
Override the security patch level in target files
@@ -269,7 +274,7 @@
import care_map_pb2
import common
import ota_utils
-from ota_utils import (UNZIP_PATTERN, FinalizeMetadata, GetPackageMetadata,
+from ota_utils import (VABC_COMPRESSION_PARAM_SUPPORT, FinalizeMetadata, GetPackageMetadata,
PayloadGenerator, SECURITY_PATCH_LEVEL_PROP_NAME, ExtractTargetFiles, CopyTargetFilesDir)
from common import DoesInputFileContain, IsSparseImage
import target_files_diff
@@ -320,6 +325,7 @@
OPTIONS.force_minor_version = None
OPTIONS.compressor_types = None
OPTIONS.enable_zucchini = True
+OPTIONS.enable_puffdiff = None
OPTIONS.enable_lz4diff = False
OPTIONS.vabc_compression_param = None
OPTIONS.security_patch_level = None
@@ -456,48 +462,51 @@
target_file = common.MakeTempFile(prefix="targetfiles-", suffix=".zip")
target_zip = zipfile.ZipFile(target_file, 'w', allowZip64=True)
- with zipfile.ZipFile(input_file, 'r', allowZip64=True) as input_zip:
- infolist = input_zip.infolist()
+ fileslist = []
+ for (root, dirs, files) in os.walk(input_file):
+ root = root.lstrip(input_file).lstrip("/")
+ fileslist.extend([os.path.join(root, d) for d in dirs])
+ fileslist.extend([os.path.join(root, d) for d in files])
- input_tmp = common.UnzipTemp(input_file, UNZIP_PATTERN)
- for info in infolist:
- unzipped_file = os.path.join(input_tmp, *info.filename.split('/'))
- if info.filename == 'IMAGES/system_other.img':
+ input_tmp = input_file
+ for filename in fileslist:
+ unzipped_file = os.path.join(input_tmp, *filename.split('/'))
+ if filename == 'IMAGES/system_other.img':
common.ZipWrite(target_zip, unzipped_file, arcname='IMAGES/system.img')
# Primary images and friends need to be skipped explicitly.
- elif info.filename in ('IMAGES/system.img',
- 'IMAGES/system.map'):
+ elif filename in ('IMAGES/system.img',
+ 'IMAGES/system.map'):
pass
# Copy images that are not in SECONDARY_PAYLOAD_SKIPPED_IMAGES.
- elif info.filename.startswith(('IMAGES/', 'RADIO/')):
- image_name = os.path.basename(info.filename)
+ elif filename.startswith(('IMAGES/', 'RADIO/')):
+ image_name = os.path.basename(filename)
if image_name not in ['{}.img'.format(partition) for partition in
SECONDARY_PAYLOAD_SKIPPED_IMAGES]:
- common.ZipWrite(target_zip, unzipped_file, arcname=info.filename)
+ common.ZipWrite(target_zip, unzipped_file, arcname=filename)
# Skip copying the postinstall config if requested.
- elif skip_postinstall and info.filename == POSTINSTALL_CONFIG:
+ elif skip_postinstall and filename == POSTINSTALL_CONFIG:
pass
- elif info.filename.startswith('META/'):
+ elif filename.startswith('META/'):
# Remove the unnecessary partitions for secondary images from the
# ab_partitions file.
- if info.filename == AB_PARTITIONS:
+ if filename == AB_PARTITIONS:
with open(unzipped_file) as f:
partition_list = f.read().splitlines()
partition_list = [partition for partition in partition_list if partition
and partition not in SECONDARY_PAYLOAD_SKIPPED_IMAGES]
- common.ZipWriteStr(target_zip, info.filename,
+ common.ZipWriteStr(target_zip, filename,
'\n'.join(partition_list))
# Remove the unnecessary partitions from the dynamic partitions list.
- elif (info.filename == 'META/misc_info.txt' or
- info.filename == DYNAMIC_PARTITION_INFO):
+ elif (filename == 'META/misc_info.txt' or
+ filename == DYNAMIC_PARTITION_INFO):
modified_info = GetInfoForSecondaryImages(unzipped_file)
- common.ZipWriteStr(target_zip, info.filename, modified_info)
+ common.ZipWriteStr(target_zip, filename, modified_info)
else:
- common.ZipWrite(target_zip, unzipped_file, arcname=info.filename)
+ common.ZipWrite(target_zip, unzipped_file, arcname=filename)
common.ZipClose(target_zip)
@@ -863,6 +872,10 @@
if not source_info.is_vabc or not target_info.is_vabc:
logger.info("Either source or target does not support VABC, disabling.")
OPTIONS.disable_vabc = True
+ if source_info.vabc_compression_param != target_info.vabc_compression_param:
+ logger.info("Source build and target build use different compression methods {} vs {}, default to source builds parameter {}".format(
+ source_info.vabc_compression_param, target_info.vabc_compression_param, source_info.vabc_compression_param))
+ OPTIONS.vabc_compression_param = source_info.vabc_compression_param
# Virtual AB Compression was introduced in Androd S.
# Later, we backported VABC to Android R. But verity support was not
@@ -877,6 +890,22 @@
"META/ab_partitions.txt is required for ab_update."
target_info = common.BuildInfo(OPTIONS.info_dict, OPTIONS.oem_dicts)
source_info = None
+ if target_info.vabc_compression_param:
+ minimum_api_level_required = VABC_COMPRESSION_PARAM_SUPPORT[
+ target_info.vabc_compression_param]
+ if target_info.vendor_api_level < minimum_api_level_required:
+ logger.warning(
+ "This full OTA is configured to use VABC compression algorithm"
+ " {}, which is supported since"
+ " Android API level {}, but device is "
+ "launched with {} . If this full OTA is"
+ " served to a device running old build, OTA might fail due to "
+ "unsupported compression parameter. For safety, gz is used because "
+ "it's supported since day 1.".format(
+ target_info.vabc_compression_param,
+ minimum_api_level_required,
+ target_info.vendor_api_level))
+ OPTIONS.vabc_compression_param = "gz"
if OPTIONS.partial == []:
logger.info(
@@ -994,6 +1023,9 @@
additional_args += ["--enable_zucchini=" +
str(OPTIONS.enable_zucchini).lower()]
+ if OPTIONS.enable_puffdiff is not None:
+ additional_args += ["--enable_puffdiff=" +
+ str(OPTIONS.enable_puffdiff).lower()]
if not ota_utils.IsLz4diffCompatible(source_file, target_file):
logger.warning(
@@ -1193,11 +1225,20 @@
elif o == "--enable_zucchini":
assert a.lower() in ["true", "false"]
OPTIONS.enable_zucchini = a.lower() != "false"
+ elif o == "--enable_puffdiff":
+ assert a.lower() in ["true", "false"]
+ OPTIONS.enable_puffdiff = a.lower() != "false"
elif o == "--enable_lz4diff":
assert a.lower() in ["true", "false"]
OPTIONS.enable_lz4diff = a.lower() != "false"
elif o == "--vabc_compression_param":
+ words = a.split(",")
+ assert len(words) >= 1 and len(words) <= 2
OPTIONS.vabc_compression_param = a.lower()
+ if len(words) == 2:
+ if not words[1].isdigit():
+ raise ValueError("Cannot parse value %r for option $COMPRESSION_LEVEL - only "
+ "integers are allowed." % words[1])
elif o == "--security_patch_level":
OPTIONS.security_patch_level = a
elif o in ("--max_threads"):
@@ -1254,6 +1295,7 @@
"force_minor_version=",
"compressor_types=",
"enable_zucchini=",
+ "enable_puffdiff=",
"enable_lz4diff=",
"vabc_compression_param=",
"security_patch_level=",
diff --git a/tools/releasetools/ota_signing_utils.py b/tools/releasetools/ota_signing_utils.py
new file mode 100644
index 0000000..60c8c94
--- /dev/null
+++ b/tools/releasetools/ota_signing_utils.py
@@ -0,0 +1,38 @@
+# 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 shlex
+
+
+def ParseSignerArgs(args):
+ if args is None:
+ return None
+ return shlex.split(args)
+
+
+def AddSigningArgumentParse(parser: argparse.ArgumentParser):
+ parser.add_argument('--package_key', type=str,
+ help='Paths to private key for signing payload')
+ parser.add_argument('--search_path', '--path', type=str,
+ help='Search path for framework/signapk.jar')
+ parser.add_argument('--payload_signer', type=str,
+ help='Path to custom payload signer')
+ parser.add_argument('--payload_signer_args', type=ParseSignerArgs,
+ help='Arguments for payload signer if necessary')
+ parser.add_argument('--payload_signer_maximum_signature_size', type=str,
+ help='Maximum signature size (in bytes) that would be '
+ 'generated by the given payload signer')
+ parser.add_argument('--private_key_suffix', type=str,
+ help='Suffix to be appended to package_key path', default=".pk8")
diff --git a/tools/releasetools/ota_utils.py b/tools/releasetools/ota_utils.py
index 68c6887..9b3367e 100644
--- a/tools/releasetools/ota_utils.py
+++ b/tools/releasetools/ota_utils.py
@@ -51,6 +51,19 @@
TARGET_FILES_IMAGES_SUBDIR = ["IMAGES", "PREBUILT_IMAGES", "RADIO"]
+# Key is the compression algorithm, value is minimum API level required to
+# use this compression algorithm for VABC OTA on device.
+VABC_COMPRESSION_PARAM_SUPPORT = {
+ "gz": 31,
+ "brotli": 31,
+ "none": 31,
+ # lz4 support is added in Android U
+ "lz4": 34,
+ # zstd support is added in Android V
+ "zstd": 35,
+}
+
+
def FinalizeMetadata(metadata, input_file, output_file, needed_property_files=None, package_key=None, pw=None):
"""Finalizes the metadata and signs an A/B OTA package.
@@ -727,6 +740,7 @@
logger.info("target files %s is already extracted", path)
return path
extracted_dir = common.MakeTempDir("target_files")
+ logger.info(f"Extracting target files {path} to {extracted_dir}")
common.UnzipToDir(path, extracted_dir, UNZIP_PATTERN + [""])
for subdir in TARGET_FILES_IMAGES_SUBDIR:
image_dir = os.path.join(extracted_dir, subdir)
@@ -850,7 +864,7 @@
cmd.extend(["--dynamic_partition_info_file", dynamic_partition_info])
apex_info = os.path.join(
- target_dir, "META", "apex_info.pb")
+ target_dir, "META", "apex_info.pb")
if os.path.exists(apex_info):
cmd.extend(["--apex_info_file", apex_info])
@@ -883,30 +897,7 @@
"""
assert isinstance(payload_signer, PayloadSigner)
- # 1. Generate hashes of the payload and metadata files.
- payload_sig_file = common.MakeTempFile(prefix="sig-", suffix=".bin")
- metadata_sig_file = common.MakeTempFile(prefix="sig-", suffix=".bin")
- cmd = ["brillo_update_payload", "hash",
- "--unsigned_payload", self.payload_file,
- "--signature_size", str(payload_signer.maximum_signature_size),
- "--metadata_hash_file", metadata_sig_file,
- "--payload_hash_file", payload_sig_file]
- self._Run(cmd)
-
- # 2. Sign the hashes.
- signed_payload_sig_file = payload_signer.SignHashFile(payload_sig_file)
- signed_metadata_sig_file = payload_signer.SignHashFile(metadata_sig_file)
-
- # 3. Insert the signatures back into the payload file.
- signed_payload_file = common.MakeTempFile(prefix="signed-payload-",
- suffix=".bin")
- cmd = ["brillo_update_payload", "sign",
- "--unsigned_payload", self.payload_file,
- "--payload", signed_payload_file,
- "--signature_size", str(payload_signer.maximum_signature_size),
- "--metadata_signature_file", signed_metadata_sig_file,
- "--payload_signature_file", signed_payload_sig_file]
- self._Run(cmd)
+ signed_payload_file = payload_signer.SignPayload(self.payload_file)
self.payload_file = signed_payload_file
@@ -920,9 +911,9 @@
# 4. Dump the signed payload properties.
properties_file = common.MakeTempFile(prefix="payload-properties-",
suffix=".txt")
- cmd = ["brillo_update_payload", "properties",
- "--payload", self.payload_file,
- "--properties_file", properties_file]
+ cmd = ["delta_generator",
+ "--in_file=" + self.payload_file,
+ "--properties_file=" + properties_file]
self._Run(cmd)
if self.secondary:
diff --git a/tools/releasetools/payload_signer.py b/tools/releasetools/payload_signer.py
index 9933aef..bbd2896 100644
--- a/tools/releasetools/payload_signer.py
+++ b/tools/releasetools/payload_signer.py
@@ -95,11 +95,11 @@
# 1. Generate hashes of the payload and metadata files.
payload_sig_file = common.MakeTempFile(prefix="sig-", suffix=".bin")
metadata_sig_file = common.MakeTempFile(prefix="sig-", suffix=".bin")
- cmd = ["brillo_update_payload", "hash",
- "--unsigned_payload", unsigned_payload,
- "--signature_size", str(self.maximum_signature_size),
- "--metadata_hash_file", metadata_sig_file,
- "--payload_hash_file", payload_sig_file]
+ cmd = ["delta_generator",
+ "--in_file=" + unsigned_payload,
+ "--signature_size=" + str(self.maximum_signature_size),
+ "--out_metadata_hash_file=" + metadata_sig_file,
+ "--out_hash_file=" + payload_sig_file]
self._Run(cmd)
# 2. Sign the hashes.
@@ -109,16 +109,15 @@
# 3. Insert the signatures back into the payload file.
signed_payload_file = common.MakeTempFile(prefix="signed-payload-",
suffix=".bin")
- cmd = ["brillo_update_payload", "sign",
- "--unsigned_payload", unsigned_payload,
- "--payload", signed_payload_file,
- "--signature_size", str(self.maximum_signature_size),
- "--metadata_signature_file", signed_metadata_sig_file,
- "--payload_signature_file", signed_payload_sig_file]
+ cmd = ["delta_generator",
+ "--in_file=" + unsigned_payload,
+ "--out_file=" + signed_payload_file,
+ "--signature_size=" + str(self.maximum_signature_size),
+ "--metadata_signature_file=" + signed_metadata_sig_file,
+ "--payload_signature_file=" + signed_payload_sig_file]
self._Run(cmd)
return signed_payload_file
-
def SignHashFile(self, in_file):
"""Signs the given input file. Returns the output filename."""
out_file = common.MakeTempFile(prefix="signed-", suffix=".bin")
diff --git a/tools/releasetools/sign_target_files_apks.py b/tools/releasetools/sign_target_files_apks.py
index 8291448..2b45825 100755
--- a/tools/releasetools/sign_target_files_apks.py
+++ b/tools/releasetools/sign_target_files_apks.py
@@ -1234,11 +1234,11 @@
vendor_misc_info["no_recovery"] = "true" # recovery
vendor_misc_info["avb_enable"] = "false" # vbmeta
- vendor_misc_info["board_bpt_enable"] = "false" # partition-table
vendor_misc_info["has_dtbo"] = "false" # dtbo
vendor_misc_info["has_pvmfw"] = "false" # pvmfw
- vendor_misc_info["avb_custom_images_partition_list"] = "" # custom images
+ vendor_misc_info["avb_custom_images_partition_list"] = "" # avb custom images
vendor_misc_info["avb_building_vbmeta_image"] = "false" # skip building vbmeta
+ vendor_misc_info["custom_images_partition_list"] = "" # custom images
vendor_misc_info["use_dynamic_partitions"] = "false" # super_empty
vendor_misc_info["build_super_partition"] = "false" # super split
vendor_misc_info["avb_vbmeta_system"] = "" # skip building vbmeta_system
diff --git a/tools/releasetools/test_common.py b/tools/releasetools/test_common.py
index 2dfd8c7..86fb480 100644
--- a/tools/releasetools/test_common.py
+++ b/tools/releasetools/test_common.py
@@ -1642,6 +1642,7 @@
'gki_signing_algorithm': 'SHA256_RSA4096',
'gki_signing_signature_args': '--prop foo:bar',
}
+ common.OPTIONS.search_path = None
test_file = tempfile.NamedTemporaryFile()
self.assertRaises(common.ExternalError, common._GenerateGkiCertificate,
test_file.name, 'generic_kernel')
diff --git a/tools/sbom/Android.bp b/tools/sbom/Android.bp
index 4837dde..519251e 100644
--- a/tools/sbom/Android.bp
+++ b/tools/sbom/Android.bp
@@ -53,5 +53,27 @@
libs: [
"sbom_lib",
],
+ version: {
+ py3: {
+ embedded_launcher: true,
+ },
+ },
+ test_suites: ["general-tests"],
+}
+
+python_test_host {
+ name: "sbom_data_test",
+ main: "sbom_data_test.py",
+ srcs: [
+ "sbom_data_test.py",
+ ],
+ libs: [
+ "sbom_lib",
+ ],
+ version: {
+ py3: {
+ embedded_launcher: true,
+ },
+ },
test_suites: ["general-tests"],
}
diff --git a/tools/sbom/sbom_data.py b/tools/sbom/sbom_data.py
index ea38e36..71f8660 100644
--- a/tools/sbom/sbom_data.py
+++ b/tools/sbom/sbom_data.py
@@ -133,7 +133,7 @@
checksums = []
for file in self.files:
if file.id in package.file_ids:
- checksums.append(file.checksum)
+ checksums.append(file.checksum.split(': ')[1])
checksums.sort()
h = hashlib.sha1()
h.update(''.join(checksums).encode(encoding='utf-8'))
diff --git a/tools/sbom/sbom_data_test.py b/tools/sbom/sbom_data_test.py
new file mode 100644
index 0000000..69bc9d2
--- /dev/null
+++ b/tools/sbom/sbom_data_test.py
@@ -0,0 +1,139 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2023 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 hashlib
+import unittest
+import sbom_data
+
+BUILD_FINGER_PRINT = 'build_finger_print'
+SUPPLIER_GOOGLE = 'Organization: Google'
+SUPPLIER_UPSTREAM = 'Organization: upstream'
+
+SPDXID_PREBUILT_PACKAGE1 = 'SPDXRef-PREBUILT-package1'
+SPDXID_SOURCE_PACKAGE1 = 'SPDXRef-SOURCE-package1'
+SPDXID_UPSTREAM_PACKAGE1 = 'SPDXRef-UPSTREAM-package1'
+
+SPDXID_FILE1 = 'SPDXRef-file1'
+SPDXID_FILE2 = 'SPDXRef-file2'
+SPDXID_FILE3 = 'SPDXRef-file3'
+SPDXID_FILE4 = 'SPDXRef-file4'
+
+
+class SBOMDataTest(unittest.TestCase):
+
+ def setUp(self):
+ # SBOM of a product
+ self.sbom_doc = sbom_data.Document(name='test doc',
+ namespace='http://www.google.com/sbom/spdx/android',
+ creators=[SUPPLIER_GOOGLE],
+ created='2023-03-31T22:17:58Z',
+ describes=sbom_data.SPDXID_PRODUCT)
+ self.sbom_doc.add_external_ref(
+ sbom_data.DocumentExternalReference(id='DocumentRef-external_doc_ref',
+ uri='external_doc_uri',
+ checksum='SHA1: 1234567890'))
+ self.sbom_doc.add_package(
+ sbom_data.Package(id=sbom_data.SPDXID_PRODUCT,
+ name=sbom_data.PACKAGE_NAME_PRODUCT,
+ download_location=sbom_data.VALUE_NONE,
+ supplier=SUPPLIER_GOOGLE,
+ version=BUILD_FINGER_PRINT,
+ files_analyzed=True,
+ verification_code='',
+ file_ids=[SPDXID_FILE1, SPDXID_FILE2, SPDXID_FILE3, SPDXID_FILE4]))
+
+ self.sbom_doc.add_package(
+ sbom_data.Package(id=sbom_data.SPDXID_PLATFORM,
+ name=sbom_data.PACKAGE_NAME_PLATFORM,
+ download_location=sbom_data.VALUE_NONE,
+ supplier=SUPPLIER_GOOGLE,
+ version=BUILD_FINGER_PRINT,
+ ))
+
+ self.sbom_doc.add_package(
+ sbom_data.Package(id=SPDXID_PREBUILT_PACKAGE1,
+ name='Prebuilt package1',
+ download_location=sbom_data.VALUE_NONE,
+ supplier=SUPPLIER_GOOGLE,
+ version=BUILD_FINGER_PRINT,
+ ))
+
+ self.sbom_doc.add_package(
+ sbom_data.Package(id=SPDXID_SOURCE_PACKAGE1,
+ name='Source package1',
+ download_location=sbom_data.VALUE_NONE,
+ supplier=SUPPLIER_GOOGLE,
+ version=BUILD_FINGER_PRINT,
+ external_refs=[sbom_data.PackageExternalRef(
+ category=sbom_data.PackageExternalRefCategory.SECURITY,
+ type=sbom_data.PackageExternalRefType.cpe22Type,
+ locator='cpe:/a:jsoncpp_project:jsoncpp:1.9.4')]
+ ))
+
+ self.sbom_doc.add_package(
+ sbom_data.Package(id=SPDXID_UPSTREAM_PACKAGE1,
+ name='Upstream package1',
+ supplier=SUPPLIER_UPSTREAM,
+ version='1.1',
+ ))
+
+ self.sbom_doc.add_relationship(sbom_data.Relationship(id1=SPDXID_SOURCE_PACKAGE1,
+ relationship=sbom_data.RelationshipType.VARIANT_OF,
+ id2=SPDXID_UPSTREAM_PACKAGE1))
+
+ self.sbom_doc.files.append(
+ sbom_data.File(id=SPDXID_FILE1, name='/bin/file1',
+ checksum='SHA1: 356a192b7913b04c54574d18c28d46e6395428ab')) # sha1 hash of 1
+ self.sbom_doc.files.append(
+ sbom_data.File(id=SPDXID_FILE2, name='/bin/file2',
+ checksum='SHA1: da4b9237bacccdf19c0760cab7aec4a8359010b0')) # sha1 hash of 2
+ self.sbom_doc.files.append(
+ sbom_data.File(id=SPDXID_FILE3, name='/bin/file3',
+ checksum='SHA1: 77de68daecd823babbb58edb1c8e14d7106e83bb')) # sha1 hash of 3
+ self.sbom_doc.files.append(
+ sbom_data.File(id=SPDXID_FILE4, name='file4.a',
+ checksum='SHA1: 1b6453892473a467d07372d45eb05abc2031647a')) # sha1 of 4
+
+ self.sbom_doc.add_relationship(sbom_data.Relationship(id1=SPDXID_FILE1,
+ relationship=sbom_data.RelationshipType.GENERATED_FROM,
+ id2=sbom_data.SPDXID_PLATFORM))
+ self.sbom_doc.add_relationship(sbom_data.Relationship(id1=SPDXID_FILE2,
+ relationship=sbom_data.RelationshipType.GENERATED_FROM,
+ id2=SPDXID_PREBUILT_PACKAGE1))
+ self.sbom_doc.add_relationship(sbom_data.Relationship(id1=SPDXID_FILE3,
+ relationship=sbom_data.RelationshipType.GENERATED_FROM,
+ id2=SPDXID_SOURCE_PACKAGE1
+ ))
+ self.sbom_doc.add_relationship(sbom_data.Relationship(id1=SPDXID_FILE1,
+ relationship=sbom_data.RelationshipType.STATIC_LINK,
+ id2=SPDXID_FILE4
+ ))
+
+ def test_package_verification_code(self):
+ checksums = []
+ for file in self.sbom_doc.files:
+ checksums.append(file.checksum.split(': ')[1])
+ checksums.sort()
+ h = hashlib.sha1()
+ h.update(''.join(checksums).encode(encoding='utf-8'))
+ expected_package_verification_code = h.hexdigest()
+
+ self.sbom_doc.generate_packages_verification_code()
+ self.assertEqual(expected_package_verification_code, self.sbom_doc.packages[0].verification_code)
+
+
+if __name__ == '__main__':
+ unittest.main(verbosity=2)
diff --git a/tools/zipalign/Android.bp b/tools/zipalign/Android.bp
index 0e1d58e..8be7e25 100644
--- a/tools/zipalign/Android.bp
+++ b/tools/zipalign/Android.bp
@@ -70,6 +70,7 @@
"libgmock",
],
data: [
+ "tests/data/apkWithUncompressedSharedLibs.zip",
"tests/data/archiveWithOneDirectoryEntry.zip",
"tests/data/diffOrders.zip",
"tests/data/holes.zip",
diff --git a/tools/zipalign/ZipAlign.cpp b/tools/zipalign/ZipAlign.cpp
index 23840e3..f32f90b 100644
--- a/tools/zipalign/ZipAlign.cpp
+++ b/tools/zipalign/ZipAlign.cpp
@@ -17,6 +17,7 @@
#include "ZipFile.h"
#include <stdio.h>
+#include <string.h>
#include <stdlib.h>
#include <unistd.h>
@@ -36,17 +37,14 @@
}
static int getAlignment(bool pageAlignSharedLibs, int defaultAlignment,
- ZipEntry* pEntry) {
-
- static const int kPageAlignment = 4096;
-
+ ZipEntry* pEntry, int pageSize) {
if (!pageAlignSharedLibs) {
return defaultAlignment;
}
const char* ext = strrchr(pEntry->getFileName(), '.');
if (ext && strcmp(ext, ".so") == 0) {
- return kPageAlignment;
+ return pageSize;
}
return defaultAlignment;
@@ -56,7 +54,7 @@
* Copy all entries from "pZin" to "pZout", aligning as needed.
*/
static int copyAndAlign(ZipFile* pZin, ZipFile* pZout, int alignment, bool zopfli,
- bool pageAlignSharedLibs)
+ bool pageAlignSharedLibs, int pageSize)
{
int numEntries = pZin->getNumEntries();
ZipEntry* pEntry;
@@ -84,7 +82,8 @@
status = pZout->add(pZin, pEntry, padding, &pNewEntry);
}
} else {
- const int alignTo = getAlignment(pageAlignSharedLibs, alignment, pEntry);
+ const int alignTo = getAlignment(pageAlignSharedLibs, alignment, pEntry,
+ pageSize);
//printf("--- %s: orig at %ld(+%d) len=%ld, adding pad=%d\n",
// pEntry->getFileName(), (long) pEntry->getFileOffset(),
@@ -107,7 +106,7 @@
* output file exists and "force" wasn't specified.
*/
int process(const char* inFileName, const char* outFileName,
- int alignment, bool force, bool zopfli, bool pageAlignSharedLibs)
+ int alignment, bool force, bool zopfli, bool pageAlignSharedLibs, int pageSize)
{
ZipFile zin, zout;
@@ -127,7 +126,7 @@
}
if (zin.open(inFileName, ZipFile::kOpenReadOnly) != OK) {
- fprintf(stderr, "Unable to open '%s' as zip archive\n", inFileName);
+ fprintf(stderr, "Unable to open '%s' as zip archive: %s\n", inFileName, strerror(errno));
return 1;
}
if (zout.open(outFileName,
@@ -138,7 +137,8 @@
return 1;
}
- int result = copyAndAlign(&zin, &zout, alignment, zopfli, pageAlignSharedLibs);
+ int result = copyAndAlign(&zin, &zout, alignment, zopfli, pageAlignSharedLibs,
+ pageSize);
if (result != 0) {
printf("zipalign: failed rewriting '%s' to '%s'\n",
inFileName, outFileName);
@@ -150,7 +150,7 @@
* Verify the alignment of a zip archive.
*/
int verify(const char* fileName, int alignment, bool verbose,
- bool pageAlignSharedLibs)
+ bool pageAlignSharedLibs, int pageSize)
{
ZipFile zipFile;
bool foundBad = false;
@@ -181,7 +181,8 @@
continue;
} else {
off_t offset = pEntry->getFileOffset();
- const int alignTo = getAlignment(pageAlignSharedLibs, alignment, pEntry);
+ const int alignTo = getAlignment(pageAlignSharedLibs, alignment, pEntry,
+ pageSize);
if ((offset % alignTo) != 0) {
if (verbose) {
printf("%8jd %s (BAD - %jd)\n",
diff --git a/tools/zipalign/ZipAlignMain.cpp b/tools/zipalign/ZipAlignMain.cpp
index 53fc8d4..2f24403 100644
--- a/tools/zipalign/ZipAlignMain.cpp
+++ b/tools/zipalign/ZipAlignMain.cpp
@@ -34,15 +34,18 @@
fprintf(stderr, "Zip alignment utility\n");
fprintf(stderr, "Copyright (C) 2009 The Android Open Source Project\n\n");
fprintf(stderr,
- "Usage: zipalign [-f] [-p] [-v] [-z] <align> infile.zip outfile.zip\n"
- " zipalign -c [-p] [-v] <align> infile.zip\n\n" );
+ "Usage: zipalign [-f] [-p] [-P <pagesize_kb>] [-v] [-z] <align> infile.zip outfile.zip\n"
+ " zipalign -c [-p] [-P <pagesize_kb>] [-v] <align> infile.zip\n\n" );
fprintf(stderr,
" <align>: alignment in bytes, e.g. '4' provides 32-bit alignment\n");
fprintf(stderr, " -c: check alignment only (does not modify file)\n");
fprintf(stderr, " -f: overwrite existing outfile.zip\n");
- fprintf(stderr, " -p: page-align uncompressed .so files\n");
+ fprintf(stderr, " -p: 4kb page-align uncompressed .so files\n");
fprintf(stderr, " -v: verbose output\n");
fprintf(stderr, " -z: recompress using Zopfli\n");
+ fprintf(stderr, " -P <pagesize_kb>: Align uncompressed .so files to the specified\n");
+ fprintf(stderr, " page size. Valid values for <pagesize_kb> are 4, 16\n");
+ fprintf(stderr, " and 64. '-P' cannot be used in combination with '-p'.\n");
}
@@ -57,12 +60,16 @@
bool verbose = false;
bool zopfli = false;
bool pageAlignSharedLibs = false;
+ int pageSize = 4096;
+ bool legacyPageAlignmentFlag = false; // -p
+ bool pageAlignmentFlag = false; // -P <pagesize_kb>
int result = 1;
int alignment;
char* endp;
int opt;
- while ((opt = getopt(argc, argv, "fcpvz")) != -1) {
+
+ while ((opt = getopt(argc, argv, "fcpvzP:")) != -1) {
switch (opt) {
case 'c':
check = true;
@@ -77,7 +84,29 @@
zopfli = true;
break;
case 'p':
+ legacyPageAlignmentFlag = true;
pageAlignSharedLibs = true;
+ pageSize = 4096;
+ break;
+ case 'P':
+ pageAlignmentFlag = true;
+ pageAlignSharedLibs = true;
+
+ if (!optarg) {
+ fprintf(stderr, "ERROR: -P requires an argument\n");
+ wantUsage = true;
+ goto bail;
+ }
+
+ pageSize = atoi(optarg);
+ if (pageSize != 4 && pageSize != 16 && pageSize != 64) {
+ fprintf(stderr, "ERROR: Invalid argument for -P: %s\n", optarg);
+ wantUsage = true;
+ goto bail;
+ }
+
+ pageSize *= 1024; // Convert from kB to bytes.
+
break;
default:
fprintf(stderr, "ERROR: unknown flag -%c\n", opt);
@@ -86,6 +115,13 @@
}
}
+ if (legacyPageAlignmentFlag && pageAlignmentFlag) {
+ fprintf(stderr, "ERROR: Invalid options: '-P <pagesize_kb>' and '-p'"
+ "cannot be used in combination.\n");
+ wantUsage = true;
+ goto bail;
+ }
+
if (!((check && (argc - optind) == 2) || (!check && (argc - optind) == 3))) {
wantUsage = true;
goto bail;
@@ -100,14 +136,15 @@
if (check) {
/* check existing archive for correct alignment */
- result = verify(argv[optind + 1], alignment, verbose, pageAlignSharedLibs);
+ result = verify(argv[optind + 1], alignment, verbose, pageAlignSharedLibs, pageSize);
} else {
/* create the new archive */
- result = process(argv[optind + 1], argv[optind + 2], alignment, force, zopfli, pageAlignSharedLibs);
+ result = process(argv[optind + 1], argv[optind + 2], alignment, force, zopfli,
+ pageAlignSharedLibs, pageSize);
/* trust, but verify */
if (result == 0) {
- result = verify(argv[optind + 2], alignment, verbose, pageAlignSharedLibs);
+ result = verify(argv[optind + 2], alignment, verbose, pageAlignSharedLibs, pageSize);
}
}
diff --git a/tools/zipalign/include/ZipAlign.h b/tools/zipalign/include/ZipAlign.h
index ab36086..85dda14 100644
--- a/tools/zipalign/include/ZipAlign.h
+++ b/tools/zipalign/include/ZipAlign.h
@@ -25,24 +25,28 @@
* - force : Overwrite output if it exists, fail otherwise.
* - zopfli : Recompress compressed entries with more efficient algorithm.
* Copy compressed entries as-is, and unaligned, otherwise.
- * - pageAlignSharedLibs: Align .so files to 4096 and other files to
+ * - pageAlignSharedLibs: Align .so files to @pageSize and other files to
* alignTo, or all files to alignTo if false..
+ * - pageSize: Specifies the page size of the target device. This is used
+ * to correctly page-align shared libraries.
*
* Returns 0 on success.
*/
int process(const char* input, const char* output, int alignTo, bool force,
- bool zopfli, bool pageAlignSharedLibs);
+ bool zopfli, bool pageAlignSharedLibs, int pageSize);
/*
* Verify the alignment of a zip archive.
* - alignTo: Alignment (in bytes) for uncompressed entries.
- * - pageAlignSharedLibs: Align .so files to 4096 and other files to
+ * - pageAlignSharedLibs: Align .so files to @pageSize and other files to
* alignTo, or all files to alignTo if false..
+ * - pageSize: Specifies the page size of the target device. This is used
+ * to correctly page-align shared libraries.
*
* Returns 0 on success.
*/
int verify(const char* fileName, int alignTo, bool verbose,
- bool pageAlignSharedLibs);
+ bool pageAlignSharedLibs, int pageSize);
} // namespace android
diff --git a/tools/zipalign/tests/data/apkWithUncompressedSharedLibs.zip b/tools/zipalign/tests/data/apkWithUncompressedSharedLibs.zip
new file mode 100644
index 0000000..930e3b5
--- /dev/null
+++ b/tools/zipalign/tests/data/apkWithUncompressedSharedLibs.zip
Binary files differ
diff --git a/tools/zipalign/tests/src/align_test.cpp b/tools/zipalign/tests/src/align_test.cpp
index a8433fa..07ad7cc 100644
--- a/tools/zipalign/tests/src/align_test.cpp
+++ b/tools/zipalign/tests/src/align_test.cpp
@@ -48,11 +48,12 @@
TEST(Align, Unaligned) {
const std::string src = GetTestPath("unaligned.zip");
const std::string dst = GetTempPath("unaligned_out.zip");
+ int pageSize = 4096;
- int processed = process(src.c_str(), dst.c_str(), 4, true, false, 4096);
+ int processed = process(src.c_str(), dst.c_str(), 4, true, false, false, pageSize);
ASSERT_EQ(0, processed);
- int verified = verify(dst.c_str(), 4, true, false);
+ int verified = verify(dst.c_str(), 4, true, false, pageSize);
ASSERT_EQ(0, verified);
}
@@ -60,18 +61,19 @@
const std::string src = GetTestPath("unaligned.zip");
const std::string tmp = GetTempPath("da_aligned.zip");
const std::string dst = GetTempPath("da_d_aligner.zip");
+ int pageSize = 4096;
- int processed = process(src.c_str(), tmp.c_str(), 4, true, false, 4096);
+ int processed = process(src.c_str(), tmp.c_str(), 4, true, false, false, pageSize);
ASSERT_EQ(0, processed);
- int verified = verify(tmp.c_str(), 4, true, false);
+ int verified = verify(tmp.c_str(), 4, true, false, pageSize);
ASSERT_EQ(0, verified);
// Align the result of the previous run. Essentially double aligning.
- processed = process(tmp.c_str(), dst.c_str(), 4, true, false, 4096);
+ processed = process(tmp.c_str(), dst.c_str(), 4, true, false, false, pageSize);
ASSERT_EQ(0, processed);
- verified = verify(dst.c_str(), 4, true, false);
+ verified = verify(dst.c_str(), 4, true, false, pageSize);
ASSERT_EQ(0, verified);
// Nothing should have changed between tmp and dst.
@@ -90,11 +92,12 @@
TEST(Align, Holes) {
const std::string src = GetTestPath("holes.zip");
const std::string dst = GetTempPath("holes_out.zip");
+ int pageSize = 4096;
- int processed = process(src.c_str(), dst.c_str(), 4, true, false, 4096);
+ int processed = process(src.c_str(), dst.c_str(), 4, true, false, true, pageSize);
ASSERT_EQ(0, processed);
- int verified = verify(dst.c_str(), 4, false, true);
+ int verified = verify(dst.c_str(), 4, false, true, pageSize);
ASSERT_EQ(0, verified);
}
@@ -102,28 +105,85 @@
TEST(Align, DifferenteOrders) {
const std::string src = GetTestPath("diffOrders.zip");
const std::string dst = GetTempPath("diffOrders_out.zip");
+ int pageSize = 4096;
- int processed = process(src.c_str(), dst.c_str(), 4, true, false, 4096);
+ int processed = process(src.c_str(), dst.c_str(), 4, true, false, true, pageSize);
ASSERT_EQ(0, processed);
- int verified = verify(dst.c_str(), 4, false, true);
+ int verified = verify(dst.c_str(), 4, false, true, pageSize);
ASSERT_EQ(0, verified);
}
TEST(Align, DirectoryEntryDoNotRequireAlignment) {
const std::string src = GetTestPath("archiveWithOneDirectoryEntry.zip");
- int verified = verify(src.c_str(), 4, false, true);
+ int pageSize = 4096;
+ int verified = verify(src.c_str(), 4, false, true, pageSize);
ASSERT_EQ(0, verified);
}
TEST(Align, DirectoryEntry) {
const std::string src = GetTestPath("archiveWithOneDirectoryEntry.zip");
const std::string dst = GetTempPath("archiveWithOneDirectoryEntry_out.zip");
+ int pageSize = 4096;
- int processed = process(src.c_str(), dst.c_str(), 4, true, false, 4096);
+ int processed = process(src.c_str(), dst.c_str(), 4, true, false, true, pageSize);
ASSERT_EQ(0, processed);
ASSERT_EQ(true, sameContent(src, dst));
- int verified = verify(dst.c_str(), 4, false, true);
+ int verified = verify(dst.c_str(), 4, false, true, pageSize);
+ ASSERT_EQ(0, verified);
+}
+
+class UncompressedSharedLibsTest : public ::testing::Test {
+ protected:
+ static void SetUpTestSuite() {
+ src = GetTestPath("apkWithUncompressedSharedLibs.zip");
+ dst = GetTempPath("apkWithUncompressedSharedLibs_out.zip");
+ }
+
+ static std::string src;
+ static std::string dst;
+};
+
+std::string UncompressedSharedLibsTest::src;
+std::string UncompressedSharedLibsTest::dst;
+
+TEST_F(UncompressedSharedLibsTest, Unaligned) {
+ int pageSize = 4096;
+
+ int processed = process(src.c_str(), dst.c_str(), 4, true, false, false, pageSize);
+ ASSERT_EQ(0, processed);
+
+ int verified = verify(dst.c_str(), 4, true, true, pageSize);
+ ASSERT_NE(0, verified); // .so's not page-aligned
+}
+
+TEST_F(UncompressedSharedLibsTest, AlignedPageSize4kB) {
+ int pageSize = 4096;
+
+ int processed = process(src.c_str(), dst.c_str(), 4, true, false, true, pageSize);
+ ASSERT_EQ(0, processed);
+
+ int verified = verify(dst.c_str(), 4, true, true, pageSize);
+ ASSERT_EQ(0, verified);
+}
+
+TEST_F(UncompressedSharedLibsTest, AlignedPageSize16kB) {
+ int pageSize = 16384;
+
+ int processed = process(src.c_str(), dst.c_str(), 4, true, false, true, pageSize);
+ ASSERT_EQ(0, processed);
+
+ int verified = verify(dst.c_str(), 4, true, true, pageSize);
+ ASSERT_EQ(0, verified);
+}
+
+TEST_F(UncompressedSharedLibsTest, AlignedPageSize64kB) {
+ int pageSize = 65536;
+
+ int processed = process(src.c_str(), dst.c_str(), 4, true, false, true, pageSize);
+ ASSERT_EQ(0, processed);
+
+ int verified = verify(dst.c_str(), 4, true, true, pageSize);
ASSERT_EQ(0, verified);
}