Merge "Propagate libpower no lock during binder transaction flag to soong" into main
diff --git a/core/Makefile b/core/Makefile
index f38f3a0..9845437 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -4369,7 +4369,7 @@
INSTALLED_PVMFW_EMBEDDED_AVBKEY_TARGET := $(PRODUCT_OUT)/pvmfw_embedded.avbpubkey
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_EMBEDDED_AVBKEY := $(call module-target-built-files,pvmfw_embedded_key_pub_bin)
INTERNAL_PVMFW_SYMBOL := $(TARGET_OUT_EXECUTABLES_UNSTRIPPED)/pvmfw
$(call declare-1p-container,$(INSTALLED_PVMFWIMAGE_TARGET),)
@@ -7605,6 +7605,7 @@
sdk_dep_file := $(sdk_dir)/sdk_deps.mk
ATREE_FILES :=
+include development/build/tools/sdk-preprocess-files.mk
-include $(sdk_dep_file)
# if we don't have a real list, then use "everything"
diff --git a/core/android_soong_config_vars.mk b/core/android_soong_config_vars.mk
index ee4c8e4..274a7de 100644
--- a/core/android_soong_config_vars.mk
+++ b/core/android_soong_config_vars.mk
@@ -116,8 +116,10 @@
$(call add_soong_config_var_value,ANDROID,release_package_libandroid_runtime_punch_holes,$(RELEASE_PACKAGE_LIBANDROID_RUNTIME_PUNCH_HOLES))
$(call add_soong_config_var_value,ANDROID,release_selinux_data_data_ignore,$(RELEASE_SELINUX_DATA_DATA_IGNORE))
-
-$(call add_soong_config_var_value,ANDROID,release_write_appcompat_override_system_properties,$(RELEASE_WRITE_APPCOMPAT_OVERRIDE_SYSTEM_PROPERTIES))
+ifneq (,$(filter eng userdebug,$(TARGET_BUILD_VARIANT)))
+ # write appcompat system properties on userdebug and eng builds
+ $(call add_soong_config_var_value,ANDROID,release_write_appcompat_override_system_properties,true)
+endif
# Enable system_server optimizations by default unless explicitly set or if
# there may be dependent runtime jars.
diff --git a/core/base_rules.mk b/core/base_rules.mk
index 9c7e906..86028a9 100644
--- a/core/base_rules.mk
+++ b/core/base_rules.mk
@@ -768,6 +768,10 @@
$(LOCAL_BUILT_MODULE):$(dir)/$(my_installed_module_stem)))) \
$(eval my_compat_dist_config_$(suite) := ))
+ifneq (,$(LOCAL_SOONG_CLASSES_JAR))
+ $(foreach suite, $(LOCAL_COMPATIBILITY_SUITE), \
+ $(eval my_compat_api_map_$(suite) += $(LOCAL_SOONG_CLASSES_JAR)))
+endif
# Auto-generate build config.
ifeq (,$(test_config))
@@ -821,6 +825,12 @@
$(foreach dir, $(call compatibility_suite_dirs,$(suite)), \
$(s):$(dir)/$(n)))))
+ $(foreach suite, $(LOCAL_COMPATIBILITY_SUITE), \
+ $(eval my_compat_api_map_$(suite) += $(foreach f, $(LOCAL_COMPATIBILITY_SUPPORT_FILES), \
+ $(eval p := $(subst :,$(space),$(f))) \
+ $(eval s := $(word 1,$(p))) \
+ $(if $(filter %.apk,$(s)) $(filter %.jar,$(s)),$(s),))))
+
ifneq (,$(test_config))
$(foreach suite, $(LOCAL_COMPATIBILITY_SUITE), \
$(eval my_compat_dist_config_$(suite) += $(foreach dir, $(call compatibility_suite_dirs,$(suite)), \
@@ -863,7 +873,9 @@
$(call filter-copy-pair,$(src_path),$(call append-path,$(dir),$(file)),$(my_installed_test_data)))) \
$(eval my_compat_dist_test_data_$(suite) += \
$(foreach dir, $(call compatibility_suite_dirs,$(suite),$(arch_dir)), \
- $(filter $(my_installed_test_data),$(call append-path,$(dir),$(file)))))))
+ $(filter $(my_installed_test_data),$(call append-path,$(dir),$(file))))) \
+ $(eval my_compat_api_map_$(suite) += \
+ $(if $(filter %.apk,$(src_path)) $(filter %.jar,$(src_path)),$(src_path),))))
endif
else
ifneq ($(my_test_data_file_pairs),)
@@ -873,7 +885,9 @@
$(eval file := $(word 2,$(parts))) \
$(foreach suite, $(LOCAL_COMPATIBILITY_SUITE), \
$(eval my_compat_dist_$(suite) += $(foreach dir, $(call compatibility_suite_dirs,$(suite),$(arch_dir)), \
- $(src_path):$(call append-path,$(dir),$(file))))))
+ $(src_path):$(call append-path,$(dir),$(file)))) \
+ $(eval my_compat_api_map_$(suite) += \
+ $(if $(filter %.apk,$(src_path)) $(filter %.jar,$(src_path)),$(src_path),))))
endif
endif
@@ -885,7 +899,8 @@
$(call create-suite-dependencies)
$(foreach suite, $(LOCAL_COMPATIBILITY_SUITE), \
$(eval my_compat_dist_config_$(suite) := ) \
- $(eval my_compat_dist_test_data_$(suite) := ))
+ $(eval my_compat_dist_test_data_$(suite) := ) \
+ $(eval my_compat_api_map_$(suite) := ))
endif # LOCAL_UNINSTALLABLE_MODULE
@@ -1108,6 +1123,7 @@
$(LOCAL_JNI_SHARED_LIBRARIES)
endif
+ALL_MODULES.$(my_register_name).TEST_MODULE_CONFIG_BASE := $(LOCAL_TEST_MODULE_CONFIG_BASE)
##########################################################################
## When compiling against API imported module, use API import stub
diff --git a/core/check_elf_file.mk b/core/check_elf_file.mk
index b5be81f..ec3c4b0 100644
--- a/core/check_elf_file.mk
+++ b/core/check_elf_file.mk
@@ -7,9 +7,12 @@
#
# Inputs:
# - LOCAL_ALLOW_UNDEFINED_SYMBOLS
+# - LOCAL_IGNORE_MAX_PAGE_SIZE
# - LOCAL_BUILT_MODULE
# - LOCAL_IS_HOST_MODULE
# - LOCAL_MODULE_CLASS
+# - TARGET_CHECK_PREBUILT_MAX_PAGE_SIZE
+# - TARGET_MAX_PAGE_SIZE_SUPPORTED
# - intermediates
# - my_installed_module_stem
# - my_prebuilt_src_file
@@ -26,6 +29,21 @@
# In addition to $(my_check_elf_file_shared_lib_files), some file paths are
# added by `resolve-shared-libs-for-elf-file-check` from `core/main.mk`.
$(check_elf_files_stamp): PRIVATE_SHARED_LIBRARY_FILES := $(my_check_elf_file_shared_lib_files)
+
+# For different page sizes to work, we must support a larger max page size
+# as well as properly reflect page size at runtime. Limit this check, since many
+# devices set the max page size (for future proof) than actually use the
+# larger page size.
+ifeq ($(strip $(TARGET_CHECK_PREBUILT_MAX_PAGE_SIZE)),true)
+ifeq ($(strip $(LOCAL_IGNORE_MAX_PAGE_SIZE)),true)
+$(check_elf_files_stamp): PRIVATE_MAX_PAGE_SIZE :=
+else
+$(check_elf_files_stamp): PRIVATE_MAX_PAGE_SIZE := $(TARGET_MAX_PAGE_SIZE_SUPPORTED)
+endif
+else
+$(check_elf_files_stamp): PRIVATE_MAX_PAGE_SIZE :=
+endif
+
$(check_elf_files_stamp): $(my_prebuilt_src_file) $(my_check_elf_file_shared_lib_files) $(CHECK_ELF_FILE) $(LLVM_READOBJ)
@echo Check prebuilt ELF binary: $<
$(hide) mkdir -p $(dir $@)
@@ -33,6 +51,7 @@
$(hide) $(CHECK_ELF_FILE) \
--skip-bad-elf-magic \
--skip-unknown-elf-machine \
+ $(if $(PRIVATE_MAX_PAGE_SIZE),--max-page-size=$(PRIVATE_MAX_PAGE_SIZE)) \
$(if $(PRIVATE_SONAME),--soname $(PRIVATE_SONAME)) \
$(foreach l,$(PRIVATE_SHARED_LIBRARY_FILES),--shared-lib $(l)) \
$(foreach l,$(PRIVATE_SYSTEM_SHARED_LIBRARIES),--system-shared-lib $(l)) \
diff --git a/core/clear_vars.mk b/core/clear_vars.mk
index fb42878..6192690 100644
--- a/core/clear_vars.mk
+++ b/core/clear_vars.mk
@@ -106,6 +106,7 @@
LOCAL_HEADER_LIBRARIES:=
LOCAL_HOST_PREFIX:=
LOCAL_HOST_REQUIRED_MODULES:=
+LOCAL_IGNORE_MAX_PAGE_SIZE:=
LOCAL_INIT_RC:=
LOCAL_INJECT_BSSL_HASH:=
LOCAL_INSTALLED_MODULE:=
@@ -259,6 +260,7 @@
LOCAL_SOONG_HEADER_JAR :=
LOCAL_SOONG_INSTALL_PAIRS :=
LOCAL_SOONG_INSTALL_SYMLINKS :=
+LOCAL_SOONG_INSTALLED_COMPATIBILITY_SUPPORT_FILES:=
LOCAL_SOONG_INSTALLED_MODULE :=
LOCAL_SOONG_JACOCO_REPORT_CLASSES_JAR :=
LOCAL_SOONG_LICENSE_METADATA :=
@@ -297,6 +299,7 @@
LOCAL_TEST_DATA_BINS:=
LOCAL_TEST_MAINLINE_MODULES:=
LOCAL_TEST_MODULE_TO_PROGUARD_WITH:=
+LOCAL_TEST_MODULE_CONFIG_BASE:=
LOCAL_TIDY:=
LOCAL_TIDY_CHECKS:=
LOCAL_TIDY_FLAGS:=
diff --git a/core/config.mk b/core/config.mk
index ce11b1d..43304d5 100644
--- a/core/config.mk
+++ b/core/config.mk
@@ -419,6 +419,13 @@
endif
.KATI_READONLY := TARGET_MAX_PAGE_SIZE_SUPPORTED
+ifdef PRODUCT_CHECK_PREBUILT_MAX_PAGE_SIZE
+ TARGET_CHECK_PREBUILT_MAX_PAGE_SIZE := $(PRODUCT_CHECK_PREBUILT_MAX_PAGE_SIZE)
+else
+ TARGET_CHECK_PREBUILT_MAX_PAGE_SIZE := false
+endif
+.KATI_READONLY := TARGET_CHECK_PREBUILT_MAX_PAGE_SIZE
+
# Boolean variable determining if AOSP relies on bionic's PAGE_SIZE macro.
ifdef PRODUCT_NO_BIONIC_PAGE_SIZE_MACRO
TARGET_NO_BIONIC_PAGE_SIZE_MACRO := $(PRODUCT_NO_BIONIC_PAGE_SIZE_MACRO)
@@ -1248,14 +1255,12 @@
include $(BUILD_SYSTEM)/dumpvar.mk
-ifneq ($(KEEP_VNDK),true)
ifdef BOARD_VNDK_VERSION
BOARD_VNDK_VERSION=
endif
ifdef PLATFORM_VNDK_VERSION
PLATFORM_VNDK_VERSION=
endif
-endif
ifeq (true,$(FULL_SYSTEM_OPTIMIZE_JAVA))
ifeq (false,$(SYSTEM_OPTIMIZE_JAVA))
diff --git a/core/definitions.mk b/core/definitions.mk
index 40b7980..dde0aa9 100644
--- a/core/definitions.mk
+++ b/core/definitions.mk
@@ -3589,11 +3589,14 @@
$(if $(filter $(suite),$(ALL_COMPATIBILITY_SUITES)),,\
$(eval ALL_COMPATIBILITY_SUITES += $(suite)) \
$(eval COMPATIBILITY.$(suite).FILES :=) \
- $(eval COMPATIBILITY.$(suite).MODULES :=)) \
+ $(eval COMPATIBILITY.$(suite).MODULES :=) \
+ $(eval COMPATIBILITY.$(suite).API_MAP_FILES :=)) \
$(eval COMPATIBILITY.$(suite).FILES += \
$$(foreach f,$$(my_compat_dist_$(suite)),$$(call word-colon,2,$$(f))) \
$$(foreach f,$$(my_compat_dist_config_$(suite)),$$(call word-colon,2,$$(f))) \
$$(my_compat_dist_test_data_$(suite))) \
+ $(eval COMPATIBILITY.$(suite).API_MAP_FILES += $$(my_compat_api_map_$(suite))) \
+ $(eval COMPATIBILITY.$(suite).SOONG_INSTALLED_COMPATIBILITY_SUPPORT_FILES += $(LOCAL_SOONG_INSTALLED_COMPATIBILITY_SUPPORT_FILES)) \
$(eval ALL_COMPATIBILITY_DIST_FILES += $$(my_compat_dist_$(suite))) \
$(eval COMPATIBILITY.$(suite).MODULES += $$(my_register_name))) \
$(eval $(my_all_targets) : \
diff --git a/core/dex_preopt_odex_install.mk b/core/dex_preopt_odex_install.mk
index 151591e..08e2da3 100644
--- a/core/dex_preopt_odex_install.mk
+++ b/core/dex_preopt_odex_install.mk
@@ -202,6 +202,12 @@
endif
ifneq (,$(LOCAL_COMPATIBILITY_SUITE))
LOCAL_ENFORCE_USES_LIBRARIES := false
+
+ # Enable the check for WTS
+ ifneq ($(filter wts,$(LOCAL_COMPATIBILITY_SUITE)),)
+ LOCAL_ENFORCE_USES_LIBRARIES := true
+ endif
+
endif
# Disable the check if the app contains no java code.
diff --git a/core/envsetup.mk b/core/envsetup.mk
index 3271079..c063f60 100644
--- a/core/envsetup.mk
+++ b/core/envsetup.mk
@@ -50,13 +50,6 @@
# Release config
include $(BUILD_SYSTEM)/release_config.mk
-# Set default value of KEEP_VNDK.
-ifeq ($(RELEASE_DEPRECATE_VNDK),true)
- KEEP_VNDK ?= false
-else
- KEEP_VNDK ?= true
-endif
-
# ---------------------------------------------------------------
# Set up version information
include $(BUILD_SYSTEM)/version_util.mk
@@ -82,7 +75,7 @@
# ---------------------------------------------------------------
# The product defaults to generic on hardware
ifeq ($(TARGET_PRODUCT),)
-TARGET_PRODUCT := aosp_arm
+TARGET_PRODUCT := aosp_arm64
endif
diff --git a/core/product.mk b/core/product.mk
index 9a49927..68d7721 100644
--- a/core/product.mk
+++ b/core/product.mk
@@ -32,6 +32,7 @@
# PRODUCT_MAX_PAGE_SIZE_SUPPORTED=65536, the possible values for PAGE_SIZE could be
# 4096, 16384 and 65536.
_product_single_value_vars += PRODUCT_MAX_PAGE_SIZE_SUPPORTED
+_product_single_value_vars += PRODUCT_CHECK_PREBUILT_MAX_PAGE_SIZE
# Boolean variable determining if AOSP relies on bionic's PAGE_SIZE macro.
_product_single_value_vars += PRODUCT_NO_BIONIC_PAGE_SIZE_MACRO
diff --git a/core/release_config.mk b/core/release_config.mk
index 887c78b..2898868 100644
--- a/core/release_config.mk
+++ b/core/release_config.mk
@@ -49,9 +49,6 @@
# If this is a google source tree, restrict it to only the one file
# which has OWNERS control. If it isn't let others define their own.
-# TODO: Remove wildcard for build/release one when all branch manifests
-# have updated.
-_must_protobuf :=
config_map_files := $(wildcard build/release/release_config_map.mk) \
$(wildcard vendor/google_shared/build/release/release_config_map.mk) \
$(if $(wildcard vendor/google/release/release_config_map.mk), \
@@ -64,7 +61,7 @@
) \
)
-protobuf_map_files := $(wildcard build/release/release_config_map.textproto) \
+protobuf_map_files := build/release/release_config_map.textproto \
$(wildcard vendor/google_shared/build/release/release_config_map.textproto) \
$(if $(wildcard vendor/google/release/release_config_map.textproto), \
vendor/google/release/release_config_map.textproto, \
@@ -76,6 +73,9 @@
) \
)
+# Remove support for the legacy approach.
+_must_protobuf := true
+
# PRODUCT_RELEASE_CONFIG_MAPS is set by Soong using an initial run of product
# config to capture only the list of config maps needed by the build.
# Keep them in the order provided, but remove duplicates.
@@ -130,6 +130,7 @@
# Disable the build flag in release-config.
_args += --guard=false
endif
+ _args += --allow-missing=true
_flags_dir:=$(OUT_DIR)/soong/release-config
_flags_file:=$(_flags_dir)/release_config-$(TARGET_PRODUCT)-$(TARGET_RELEASE).vars
# release-config generates $(_flags_varmk)
@@ -139,7 +140,7 @@
ifneq (,$(_final_product_config_pass))
# Save the final version of the config.
$(shell if ! cmp --quiet $(_flags_varmk) $(_flags_file); then cp $(_flags_varmk) $(_flags_file); fi)
- # This will also set _all_release_configs and _used_files for us.
+ # This will also set ALL_RELEASE_CONFIGS_FOR_PRODUCT and _used_files for us.
$(eval include $(_flags_file))
$(KATI_extra_file_deps $(OUT_DIR)/release-config $(protobuf_map_files) $(_flags_file))
else
@@ -155,8 +156,11 @@
$(_flags_dir)/$(_base_all_release).pb:build_flags/all_release_configs.pb \
$(_flags_dir)/$(_base_all_release).textproto:build_flags/all_release_configs.textproto \
$(_flags_dir)/$(_base_all_release).json:build_flags/all_release_configs.json \
+ $(_flags_dir)/inheritance_graph-$(TARGET_PRODUCT).dot:build_flags/inheritance_graph-$(TARGET_PRODUCT).dot \
)
# These are always created, add an empty rule for them to keep ninja happy.
+$(_flags_dir)/inheritance_graph-$(TARGET_PRODUCT).dot:
+ : created by $(OUT_DIR)/release-config
$(_flags_dir)/$(_base_all_release).pb $(_flags_dir)/$(_base_all_release).textproto $(_flags_dir)/$(_base_all_release).json:
: created by $(OUT_DIR)/release-config
_base_all_release :=
@@ -214,9 +218,9 @@
$(error declare-release-config: config $(strip $(1)) must have release config files, override another release config, or both) \
)
$(if $(strip $(4)),$(eval _all_release_configs.$(strip $(1)).ALIAS := true))
- $(eval _all_release_configs := $(sort $(_all_release_configs) $(strip $(1))))
+ $(eval ALL_RELEASE_CONFIGS_FOR_PRODUCT := $(sort $(ALL_RELEASE_CONFIGS_FOR_PRODUCT) $(strip $(1))))
$(if $(strip $(3)), \
- $(if $(filter $(_all_release_configs), $(strip $(3))),
+ $(if $(filter $(ALL_RELEASE_CONFIGS_FOR_PRODUCT), $(strip $(3))),
$(if $(filter $(_all_release_configs.$(strip $(1)).OVERRIDES),$(strip $(3))),,
$(eval _all_release_configs.$(strip $(1)).OVERRIDES := $(_all_release_configs.$(strip $(1)).OVERRIDES) $(strip $(3)))), \
$(error No release config $(strip $(3))) \
@@ -242,13 +246,13 @@
FLAG_DECLARATION_FILES :=
# Verify that all inherited/overridden release configs are declared.
-$(foreach config,$(_all_release_configs),\
+$(foreach config,$(ALL_RELEASE_CONFIGS_FOR_PRODUCT),\
$(foreach r,$(all_release_configs.$(r).OVERRIDES),\
$(if $(strip $(_all_release_configs.$(r).FILES)$(_all_release_configs.$(r).OVERRIDES)),,\
$(error Release config $(config) [declared in: $(_all_release_configs.$(r).DECLARED_IN)] inherits from non-existent $(r).)\
)))
# Verify that alias configs do not have config files.
-$(foreach r,$(_all_release_configs),\
+$(foreach r,$(ALL_RELEASE_CONFIGS_FOR_PRODUCT),\
$(if $(_all_release_configs.$(r).ALIAS),$(if $(_all_release_configs.$(r).FILES),\
$(error Alias release config "$(r)" may not specify release config files $(_all_release_configs.$(r).FILES))\
)))
@@ -263,7 +267,7 @@
# if the variable was completely unset.
TARGET_RELEASE ?= was_unset
ifeq ($(TARGET_RELEASE),was_unset)
- $(error No release config set for target; please set TARGET_RELEASE, or if building on the command line use 'lunch <target>-<release>-<build_type>', where release is one of: $(_all_release_configs))
+ $(error No release config set for target; please set TARGET_RELEASE, or if building on the command line use 'lunch <target>-<release>-<build_type>', where release is one of: $(ALL_RELEASE_CONFIGS_FOR_PRODUCT))
endif
# Instead of leaving this string empty, we want to default to a valid
# setting. Full builds coming through this path is a bug, but in case
@@ -274,8 +278,8 @@
# During pass 1 of product config, using a non-existent release config is not an error.
# We can safely assume that we are doing pass 1 if DUMP_MANY_VARS=="PRODUCT_RELEASE_CONFIG_MAPS".
ifneq (,$(_final_product_config_pass))
- ifeq ($(filter $(_all_release_configs), $(TARGET_RELEASE)),)
- $(error No release config found for TARGET_RELEASE: $(TARGET_RELEASE). Available releases are: $(_all_release_configs))
+ ifeq ($(filter $(ALL_RELEASE_CONFIGS_FOR_PRODUCT), $(TARGET_RELEASE)),)
+ $(error No release config found for TARGET_RELEASE: $(TARGET_RELEASE). Available releases are: $(ALL_RELEASE_CONFIGS_FOR_PRODUCT))
endif
endif
@@ -324,14 +328,13 @@
.KATI_READONLY := TARGET_RELEASE
ifeq (,$(_use_protobuf))
-$(foreach config, $(_all_release_configs), \
+$(foreach config, $(ALL_RELEASE_CONFIGS_FOR_PRODUCT), \
$(eval _all_release_configs.$(config).DECLARED_IN:= ) \
$(eval _all_release_configs.$(config).FILES:= ) \
)
applied_releases:=
# use makefiles
endif
-_all_release_configs:=
config_map_files:=
protobuf_map_files:=
@@ -378,3 +381,4 @@
_can_protobuf :=
_must_protobuf :=
_use_protobuf :=
+
diff --git a/core/soong_config.mk b/core/soong_config.mk
index 7402d2b..4fbff0a 100644
--- a/core/soong_config.mk
+++ b/core/soong_config.mk
@@ -144,8 +144,6 @@
$(call add_json_list, NativeCoveragePaths, $(NATIVE_COVERAGE_PATHS))
$(call add_json_list, NativeCoverageExcludePaths, $(NATIVE_COVERAGE_EXCLUDE_PATHS))
-$(call add_json_bool, SamplingPGO, $(filter true,$(SAMPLING_PGO)))
-
$(call add_json_bool, ArtUseReadBarrier, $(call invert_bool,$(filter false,$(PRODUCT_ART_USE_READ_BARRIER))))
$(call add_json_str, BtConfigIncludeDir, $(BOARD_BLUETOOTH_BDROID_BUILDCFG_INCLUDE_DIR))
$(call add_json_list, DeviceKernelHeaders, $(TARGET_DEVICE_KERNEL_HEADERS) $(TARGET_BOARD_KERNEL_HEADERS) $(TARGET_PRODUCT_KERNEL_HEADERS))
@@ -204,9 +202,6 @@
$(call add_json_bool, Uml, $(filter true,$(TARGET_USER_MODE_LINUX)))
$(call add_json_str, VendorPath, $(TARGET_COPY_OUT_VENDOR))
$(call add_json_str, OdmPath, $(TARGET_COPY_OUT_ODM))
-$(call add_json_str, VendorDlkmPath, $(TARGET_COPY_OUT_VENDOR_DLKM))
-$(call add_json_str, OdmDlkmPath, $(TARGET_COPY_OUT_ODM_DLKM))
-$(call add_json_str, SystemDlkmPath, $(TARGET_COPY_OUT_SYSTEM_DLKM))
$(call add_json_str, ProductPath, $(TARGET_COPY_OUT_PRODUCT))
$(call add_json_str, SystemExtPath, $(TARGET_COPY_OUT_SYSTEM_EXT))
$(call add_json_bool, MinimizeJavaDebugInfo, $(filter true,$(PRODUCT_MINIMIZE_JAVA_DEBUG_INFO)))
@@ -287,7 +282,7 @@
$(call add_json_bool, BoardMoveRecoveryResourcesToVendorBoot, $(filter true,$(BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT)))
$(call add_json_str, PrebuiltHiddenApiDir, $(BOARD_PREBUILT_HIDDENAPI_DIR))
-$(call add_json_str, ShippingApiLevel, $(PRODUCT_SHIPPING_API_LEVEL))
+$(call add_json_str, Shipping_api_level, $(PRODUCT_SHIPPING_API_LEVEL))
$(call add_json_list, BuildBrokenPluginValidation, $(BUILD_BROKEN_PLUGIN_VALIDATION))
$(call add_json_bool, BuildBrokenClangProperty, $(filter true,$(BUILD_BROKEN_CLANG_PROPERTY)))
@@ -332,73 +327,10 @@
$(call add_json_bool, ReleaseDefaultModuleBuildFromSource, $(RELEASE_DEFAULT_MODULE_BUILD_FROM_SOURCE))
-$(call add_json_bool, KeepVndk, $(filter true,$(KEEP_VNDK)))
-
$(call add_json_bool, CheckVendorSeappViolations, $(filter true,$(CHECK_VENDOR_SEAPP_VIOLATIONS)))
$(call add_json_bool, BuildIgnoreApexContributionContents, $(PRODUCT_BUILD_IGNORE_APEX_CONTRIBUTION_CONTENTS))
-$(call add_json_map, PartitionVarsForBazelMigrationOnlyDoNotUse)
- $(call add_json_str, ProductDirectory, $(dir $(INTERNAL_PRODUCT)))
-
- $(call add_json_map,PartitionQualifiedVariables)
- $(foreach image_type,SYSTEM VENDOR CACHE USERDATA PRODUCT SYSTEM_EXT OEM ODM VENDOR_DLKM ODM_DLKM SYSTEM_DLKM, \
- $(call add_json_map,$(call to-lower,$(image_type))) \
- $(call add_json_bool, BuildingImage, $(filter true,$(BUILDING_$(image_type)_IMAGE))) \
- $(call add_json_str, BoardErofsCompressor, $(BOARD_$(image_type)IMAGE_EROFS_COMPRESSOR)) \
- $(call add_json_str, BoardErofsCompressHints, $(BOARD_$(image_type)IMAGE_EROFS_COMPRESS_HINTS)) \
- $(call add_json_str, BoardErofsPclusterSize, $(BOARD_$(image_type)IMAGE_EROFS_PCLUSTER_SIZE)) \
- $(call add_json_str, BoardExtfsInodeCount, $(BOARD_$(image_type)IMAGE_EXTFS_INODE_COUNT)) \
- $(call add_json_str, BoardExtfsRsvPct, $(BOARD_$(image_type)IMAGE_EXTFS_RSV_PCT)) \
- $(call add_json_str, BoardF2fsSloadCompressFlags, $(BOARD_$(image_type)IMAGE_F2FS_SLOAD_COMPRESS_FLAGS)) \
- $(call add_json_str, BoardFileSystemCompress, $(BOARD_$(image_type)IMAGE_FILE_SYSTEM_COMPRESS)) \
- $(call add_json_str, BoardFileSystemType, $(BOARD_$(image_type)IMAGE_FILE_SYSTEM_TYPE)) \
- $(call add_json_str, BoardJournalSize, $(BOARD_$(image_type)IMAGE_JOURNAL_SIZE)) \
- $(call add_json_str, BoardPartitionReservedSize, $(BOARD_$(image_type)IMAGE_PARTITION_RESERVED_SIZE)) \
- $(call add_json_str, BoardPartitionSize, $(BOARD_$(image_type)IMAGE_PARTITION_SIZE)) \
- $(call add_json_str, BoardSquashfsBlockSize, $(BOARD_$(image_type)IMAGE_SQUASHFS_BLOCK_SIZE)) \
- $(call add_json_str, BoardSquashfsCompressor, $(BOARD_$(image_type)IMAGE_SQUASHFS_COMPRESSOR)) \
- $(call add_json_str, BoardSquashfsCompressorOpt, $(BOARD_$(image_type)IMAGE_SQUASHFS_COMPRESSOR_OPT)) \
- $(call add_json_str, BoardSquashfsDisable4kAlign, $(BOARD_$(image_type)IMAGE_SQUASHFS_DISABLE_4K_ALIGN)) \
- $(call add_json_str, ProductBaseFsPath, $(PRODUCT_$(image_type)_BASE_FS_PATH)) \
- $(call add_json_str, ProductHeadroom, $(PRODUCT_$(image_type)_HEADROOM)) \
- $(call add_json_str, ProductVerityPartition, $(PRODUCT_$(image_type)_VERITY_PARTITION)) \
- $(call add_json_str, BoardAvbAddHashtreeFooterArgs, $(BOARD_AVB_$(image_type)_ADD_HASHTREE_FOOTER_ARGS)) \
- $(call add_json_str, BoardAvbKeyPath, $(BOARD_AVB_$(image_type)_KEY_PATH)) \
- $(call add_json_str, BoardAvbAlgorithm, $(BOARD_AVB_$(image_type)_ALGORITHM)) \
- $(call add_json_str, BoardAvbRollbackIndex, $(BOARD_AVB_$(image_type)_ROLLBACK_INDEX)) \
- $(call add_json_str, BoardAvbRollbackIndexLocation, $(BOARD_AVB_$(image_type)_ROLLBACK_INDEX_LOCATION)) \
- $(call end_json_map) \
- )
- $(call end_json_map)
-
- $(call add_json_bool, TargetUserimagesUseExt2, $(filter true,$(TARGET_USERIMAGES_USE_EXT2)))
- $(call add_json_bool, TargetUserimagesUseExt3, $(filter true,$(TARGET_USERIMAGES_USE_EXT3)))
- $(call add_json_bool, TargetUserimagesUseExt4, $(filter true,$(TARGET_USERIMAGES_USE_EXT4)))
-
- $(call add_json_bool, TargetUserimagesSparseExtDisabled, $(filter true,$(TARGET_USERIMAGES_SPARSE_EXT_DISABLED)))
- $(call add_json_bool, TargetUserimagesSparseErofsDisabled, $(filter true,$(TARGET_USERIMAGES_SPARSE_EROFS_DISABLED)))
- $(call add_json_bool, TargetUserimagesSparseSquashfsDisabled, $(filter true,$(TARGET_USERIMAGES_SPARSE_SQUASHFS_DISABLED)))
- $(call add_json_bool, TargetUserimagesSparseF2fsDisabled, $(filter true,$(TARGET_USERIMAGES_SPARSE_F2FS_DISABLED)))
-
- $(call add_json_str, BoardErofsCompressor, $(BOARD_EROFS_COMPRESSOR))
- $(call add_json_str, BoardErofsCompressorHints, $(BOARD_EROFS_COMPRESS_HINTS))
- $(call add_json_str, BoardErofsPclusterSize, $(BOARD_EROFS_PCLUSTER_SIZE))
- $(call add_json_str, BoardErofsShareDupBlocks, $(BOARD_EROFS_SHARE_DUP_BLOCKS))
- $(call add_json_str, BoardErofsUseLegacyCompression, $(BOARD_EROFS_USE_LEGACY_COMPRESSION))
- $(call add_json_str, BoardExt4ShareDupBlocks, $(BOARD_EXT4_SHARE_DUP_BLOCKS))
- $(call add_json_str, BoardFlashLogicalBlockSize, $(BOARD_FLASH_LOGICAL_BLOCK_SIZE))
- $(call add_json_str, BoardFlashEraseBlockSize, $(BOARD_FLASH_ERASE_BLOCK_SIZE))
-
- $(call add_json_bool, BoardUsesRecoveryAsBoot, $(filter true,$(BOARD_USES_RECOVERY_AS_BOOT)))
- $(call add_json_bool, ProductUseDynamicPartitionSize, $(filter true,$(PRODUCT_USE_DYNAMIC_PARTITION_SIZE)))
- $(call add_json_bool, CopyImagesForTargetFilesZip, $(filter true,$(COPY_IMAGES_FOR_TARGET_FILES_ZIP)))
-
- $(call add_json_bool, BoardAvbEnable, $(filter true,$(BOARD_AVB_ENABLE)))
-
- $(call add_json_list, ProductPackages, $(sort $(PRODUCT_PACKAGES)))
-$(call end_json_map)
-
$(call add_json_bool, BuildFromSourceStub, $(findstring true,$(PRODUCT_BUILD_FROM_SOURCE_STUB) $(BUILD_FROM_SOURCE_STUB)))
$(call add_json_bool, HiddenapiExportableStubs, $(filter true,$(PRODUCT_HIDDEN_API_EXPORTABLE_STUBS)))
diff --git a/core/tasks/device-tests.mk b/core/tasks/device-tests.mk
index 4167a7e..5850c4e 100644
--- a/core/tasks/device-tests.mk
+++ b/core/tasks/device-tests.mk
@@ -27,9 +27,9 @@
$(device-tests-zip) : PRIVATE_device_tests_list := $(PRODUCT_OUT)/device-tests_list
$(device-tests-zip) : PRIVATE_HOST_SHARED_LIBS := $(my_host_shared_lib_for_device_tests)
$(device-tests-zip) : PRIVATE_device_host_shared_libs_zip := $(device_tests_host_shared_libs_zip)
-$(device-tests-zip) : $(COMPATIBILITY.device-tests.FILES) $(my_host_shared_lib_for_device_tests) $(SOONG_ZIP)
+$(device-tests-zip) : $(COMPATIBILITY.device-tests.FILES) $(COMPATIBILITY.device-tests.SOONG_INSTALLED_COMPATIBILITY_SUPPORT_FILES) $(my_host_shared_lib_for_device_tests) $(SOONG_ZIP)
rm -f $@-shared-libs.list
- echo $(sort $(COMPATIBILITY.device-tests.FILES)) | tr " " "\n" > $@.list
+ echo $(sort $(COMPATIBILITY.device-tests.FILES) $(COMPATIBILITY.device-tests.SOONG_INSTALLED_COMPATIBILITY_SUPPORT_FILES)) | tr " " "\n" > $@.list
grep $(HOST_OUT_TESTCASES) $@.list > $@-host.list || true
grep -e .*\\.config$$ $@-host.list > $@-host-test-configs.list || true
$(hide) for shared_lib in $(PRIVATE_HOST_SHARED_LIBS); do \
diff --git a/core/tasks/general-tests.mk b/core/tasks/general-tests.mk
index cae71e4..d6fc072 100644
--- a/core/tasks/general-tests.mk
+++ b/core/tasks/general-tests.mk
@@ -47,11 +47,11 @@
$(general_tests_zip) : PRIVATE_TOOLS := $(general_tests_tools)
$(general_tests_zip) : PRIVATE_INTERMEDIATES_DIR := $(intermediates_dir)
$(general_tests_zip) : PRIVATE_general_tests_configs_zip := $(general_tests_configs_zip)
-$(general_tests_zip) : $(COMPATIBILITY.general-tests.FILES) $(general_tests_tools) $(SOONG_ZIP)
+$(general_tests_zip) : $(COMPATIBILITY.general-tests.FILES) $(COMPATIBILITY.general-tests.SOONG_INSTALLED_COMPATIBILITY_SUPPORT_FILES) $(general_tests_tools) $(SOONG_ZIP)
rm -rf $(PRIVATE_INTERMEDIATES_DIR)
rm -f $@ $(PRIVATE_general_tests_list_zip)
mkdir -p $(PRIVATE_INTERMEDIATES_DIR) $(PRIVATE_INTERMEDIATES_DIR)/tools
- echo $(sort $(COMPATIBILITY.general-tests.FILES)) | tr " " "\n" > $(PRIVATE_INTERMEDIATES_DIR)/list
+ echo $(sort $(COMPATIBILITY.general-tests.FILES) $(COMPATIBILITY.general-tests.SOONG_INSTALLED_COMPATIBILITY_SUPPORT_FILES)) | tr " " "\n" > $(PRIVATE_INTERMEDIATES_DIR)/list
find $(PRIVATE_KERNEL_LTP_HOST_OUT) >> $(PRIVATE_INTERMEDIATES_DIR)/list
grep $(HOST_OUT_TESTCASES) $(PRIVATE_INTERMEDIATES_DIR)/list > $(PRIVATE_INTERMEDIATES_DIR)/host.list || true
grep $(TARGET_OUT_TESTCASES) $(PRIVATE_INTERMEDIATES_DIR)/list > $(PRIVATE_INTERMEDIATES_DIR)/target.list || true
diff --git a/core/tasks/module-info.mk b/core/tasks/module-info.mk
index daa7089..7593668 100644
--- a/core/tasks/module-info.mk
+++ b/core/tasks/module-info.mk
@@ -49,6 +49,7 @@
$(call write-optional-json-list, "supported_variants", $(sort $(ALL_MODULES.$(m).SUPPORTED_VARIANTS))) \
$(call write-optional-json-list, "host_dependencies", $(sort $(ALL_MODULES.$(m).HOST_REQUIRED_FROM_TARGET))) \
$(call write-optional-json-list, "target_dependencies", $(sort $(ALL_MODULES.$(m).TARGET_REQUIRED_FROM_HOST))) \
+ $(call write-optional-json-bool, "test_module_config_base", $(ALL_MODULES.$(m).TEST_MODULE_CONFIG_BASE)) \
'}')'\n}\n' >> $@.tmp
$(PRIVATE_MERGE_JSON_OBJECTS) -o $@ $(PRIVATE_SOONG_MODULE_INFO) $@.tmp
rm $@.tmp
diff --git a/envsetup.sh b/envsetup.sh
index 647c106..352d664 100644
--- a/envsetup.sh
+++ b/envsetup.sh
@@ -385,6 +385,7 @@
complete -F _bazel__complete -o nospace b
fi
complete -F _lunch lunch
+ complete -F _lunch_completion lunch2
complete -F _complete_android_module_names pathmod
complete -F _complete_android_module_names gomod
@@ -496,9 +497,18 @@
return 1
fi
+ _lunch_meat $product $release $variant
+}
+
+function _lunch_meat()
+{
+ local product=$1
+ local release=$2
+ local variant=$3
+
TARGET_PRODUCT=$product \
- TARGET_BUILD_VARIANT=$variant \
TARGET_RELEASE=$release \
+ TARGET_BUILD_VARIANT=$variant \
build_build_var_cache
if [ $? -ne 0 ]
then
@@ -519,14 +529,11 @@
set_stuff_for_environment
[[ -n "${ANDROID_QUIET_BUILD:-}" ]] || printconfig
- if [ "${TARGET_BUILD_VARIANT}" = "userdebug" ] && [[ -z "${ANDROID_QUIET_BUILD}" ]]; then
- echo
- echo "Want FASTER LOCAL BUILDS? Use -eng instead of -userdebug (however for" \
- "performance benchmarking continue to use userdebug)"
- fi
- if [ $used_lunch_menu -eq 1 ]; then
- echo
- echo "Hint: next time you can simply run 'lunch $selection'"
+ if [[ -z "${ANDROID_QUIET_BUILD}" ]]; then
+ local spam_for_lunch=$(gettop)/build/make/tools/envsetup/spam_for_lunch
+ if [[ -x $spam_for_lunch ]]; then
+ $spam_for_lunch
+ fi
fi
destroy_build_var_cache
@@ -553,6 +560,112 @@
return 0
}
+function _lunch_usage()
+{
+ (
+ echo "The lunch command selects the configuration to use for subsequent"
+ echo "Android builds."
+ echo
+ echo "Usage: lunch TARGET_PRODUCT [TARGET_RELEASE [TARGET_BUILD_VARIANT]]"
+ echo
+ echo " Choose the product, release and variant to use. If not"
+ echo " supplied, TARGET_RELEASE will be 'trunk_staging' and"
+ echo " TARGET_BUILD_VARIANT will be 'eng'"
+ echo
+ echo
+ echo "Usage: lunch TARGET_PRODUCT-TARGET_RELEASE-TARGET_BUILD_VARIANT"
+ echo
+ echo " Chose the product, release and variant to use. This"
+ echo " legacy format is maintained for compatibility."
+ echo
+ echo
+ echo "Note that the previous interactive menu and list of hard-coded"
+ echo "list of curated targets has been removed. If you would like the"
+ echo "list of products, release configs for a particular product, or"
+ echo "variants, run list_products, list_release_configs, list_variants"
+ echo "respectively."
+ echo
+ ) 1>&2
+}
+
+function lunch2()
+{
+ if [[ $# -eq 1 && $1 = "--help" ]]; then
+ _lunch_usage
+ return 0
+ fi
+ if [[ $# -eq 0 ]]; then
+ echo "No target specified. See lunch --help" 1>&2
+ return 1
+ fi
+ if [[ $# -gt 3 ]]; then
+ echo "Too many parameters given. See lunch --help" 1>&2
+ return 1
+ fi
+
+ local product release variant
+
+ # Handle the legacy format
+ local legacy=$(echo $1 | grep "-")
+ if [[ $# -eq 1 && -n $legacy ]]; then
+ IFS="-" read -r product release variant <<< "$1"
+ if [[ -z "$product" ]] || [[ -z "$release" ]] || [[ -z "$variant" ]]; then
+ echo "Invalid lunch combo: $1" 1>&2
+ echo "Valid combos must be of the form <product>-<release>-<variant> when using" 1>&2
+ echo "the legacy format. Run 'lunch --help' for usage." 1>&2
+ return 1
+ fi
+ fi
+
+ # Handle the new format.
+ if [[ -z $legacy ]]; then
+ product=$1
+ release=$2
+ if [[ -z $release ]]; then
+ release=trunk_staging
+ fi
+ variant=$3
+ if [[ -z $variant ]]; then
+ variant=eng
+ fi
+ fi
+
+ # Validate the selection and set all the environment stuff
+ _lunch_meat $product $release $variant
+}
+
+unset ANDROID_LUNCH_COMPLETION_PRODUCT_CACHE
+unset ANDROID_LUNCH_COMPLETION_CHOSEN_PRODUCT
+unset ANDROID_LUNCH_COMPLETION_RELEASE_CACHE
+# Tab completion for lunch.
+function _lunch_completion()
+{
+ # Available products
+ if [[ $COMP_CWORD -eq 1 ]] ; then
+ if [[ -z $ANDROID_LUNCH_COMPLETION_PRODUCT_CACHE ]]; then
+ ANDROID_LUNCH_COMPLETION_PRODUCT_CACHE=$(list_products)
+ fi
+ COMPREPLY=( $(compgen -W "${ANDROID_LUNCH_COMPLETION_PRODUCT_CACHE}" -- "${COMP_WORDS[COMP_CWORD]}") )
+ fi
+
+ # Available release configs
+ if [[ $COMP_CWORD -eq 2 ]] ; then
+ if [[ -z $ANDROID_LUNCH_COMPLETION_RELEASE_CACHE || $ANDROID_LUNCH_COMPLETION_CHOSEN_PRODUCT != ${COMP_WORDS[1]} ]] ; then
+ ANDROID_LUNCH_COMPLETION_RELEASE_CACHE=$(list_releases ${COMP_WORDS[1]})
+ ANDROID_LUNCH_COMPLETION_CHOSEN_PRODUCT=${COMP_WORDS[1]}
+ fi
+ COMPREPLY=( $(compgen -W "${ANDROID_LUNCH_COMPLETION_RELEASE_CACHE}" -- "${COMP_WORDS[COMP_CWORD]}") )
+ fi
+
+ # Available variants
+ if [[ $COMP_CWORD -eq 3 ]] ; then
+ COMPREPLY=(user userdebug eng)
+ fi
+
+ return 0
+}
+
+
# Configures the build to build unbundled apps.
# Run tapas with one or more app names (from LOCAL_PACKAGE_NAME)
function tapas()
diff --git a/target/product/aosp_arm64.mk b/target/product/aosp_arm64.mk
index 364fed4..7a9325d 100644
--- a/target/product/aosp_arm64.mk
+++ b/target/product/aosp_arm64.mk
@@ -44,7 +44,7 @@
$(call inherit-product, $(SRC_TARGET_DIR)/product/telephony_system_ext.mk)
# pKVM
-$(call inherit-product, packages/modules/Virtualization/apex/product_packages.mk)
+$(call inherit-product-if-exists, packages/modules/Virtualization/apex/product_packages.mk)
#
# All components inherited here go to product image
diff --git a/target/product/generic_system.mk b/target/product/generic_system.mk
index 9748c7c..4793657 100644
--- a/target/product/generic_system.mk
+++ b/target/product/generic_system.mk
@@ -146,3 +146,6 @@
$(TARGET_COPY_OUT_SYSTEM)/ \
$(call require-artifacts-in-path, $(_my_paths), $(_my_allowed_list))
+
+# Product config map to toggle between sources and prebuilts of required mainline modules
+PRODUCT_RELEASE_CONFIG_MAPS += $(wildcard vendor/google_shared/build/release/gms_mainline/required/release_config_map.textproto)
diff --git a/target/product/gsi_release.mk b/target/product/gsi_release.mk
index 5044a39..da1284e 100644
--- a/target/product/gsi_release.mk
+++ b/target/product/gsi_release.mk
@@ -58,9 +58,6 @@
device/generic/common/overlays/overlay-config.xml:$(TARGET_COPY_OUT_SYSTEM_EXT)/overlay/config/config.xml
endif
-# b/308878144 no more VNDK on 24Q1 and beyond
-KEEP_VNDK ?= false
-
# Support additional VNDK snapshots
PRODUCT_EXTRA_VNDK_VERSIONS := \
30 \
diff --git a/tools/aconfig/.editorconfig b/tools/aconfig/.editorconfig
new file mode 100644
index 0000000..cc5985f
--- /dev/null
+++ b/tools/aconfig/.editorconfig
@@ -0,0 +1,9 @@
+# EditorConfig is awesome: https://EditorConfig.org
+
+# top-most EditorConfig file
+root = true
+
+[*.java]
+indent_style = tab
+indent_size = 4
+
diff --git a/tools/aconfig/TEST_MAPPING b/tools/aconfig/TEST_MAPPING
index 421e94a..448d8cf 100644
--- a/tools/aconfig/TEST_MAPPING
+++ b/tools/aconfig/TEST_MAPPING
@@ -94,12 +94,16 @@
{
// aconfig_storage read api cpp integration tests
"name": "aconfig_storage_read_api.test.cpp"
+ },
+ {
+ // aconfig_storage file cpp integration tests
+ "name": "aconfig_storage_file.test.cpp"
}
],
"postsubmit": [
{
- // aconfig_storage file cpp integration tests
- "name": "aconfig_storage_file.test.cpp"
+ // aconfig_storage read api java integration tests
+ "name": "aconfig_storage_read_api.test.java"
}
]
}
diff --git a/tools/aconfig/aconfig_storage_read_api/Android.bp b/tools/aconfig/aconfig_storage_read_api/Android.bp
index 9b84254..3b124b1 100644
--- a/tools/aconfig/aconfig_storage_read_api/Android.bp
+++ b/tools/aconfig/aconfig_storage_read_api/Android.bp
@@ -111,3 +111,28 @@
"liblog",
],
}
+
+rust_ffi_shared {
+ name: "libaconfig_storage_read_api_rust_jni",
+ crate_name: "aconfig_storage_read_api_rust_jni",
+ srcs: ["srcs/lib.rs"],
+ rustlibs: [
+ "libaconfig_storage_read_api",
+ "libanyhow",
+ "libjni",
+ ],
+ prefer_rlib: true,
+}
+
+java_library {
+ name: "libaconfig_storage_read_api_java",
+ srcs: [
+ "srcs/**/*.java",
+ ],
+ required: ["libaconfig_storage_read_api_rust_jni"],
+ min_sdk_version: "UpsideDownCake",
+ apex_available: [
+ "//apex_available:anyapex",
+ "//apex_available:platform",
+ ],
+}
diff --git a/tools/aconfig/aconfig_storage_read_api/srcs/android/aconfig/storage/AconfigStorageReadAPI.java b/tools/aconfig/aconfig_storage_read_api/srcs/android/aconfig/storage/AconfigStorageReadAPI.java
new file mode 100644
index 0000000..406ff24
--- /dev/null
+++ b/tools/aconfig/aconfig_storage_read_api/srcs/android/aconfig/storage/AconfigStorageReadAPI.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2024 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.aconfig.storage;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.MappedByteBuffer;
+import java.nio.channels.FileChannel;
+import java.nio.channels.FileChannel.MapMode;
+
+import android.aconfig.storage.PackageReadContext;
+import android.aconfig.storage.FlagReadContext;
+
+import dalvik.annotation.optimization.FastNative;
+
+public class AconfigStorageReadAPI {
+
+ // Storage file dir on device
+ private static final String STORAGEDIR = "/metadata/aconfig";
+
+ // Stoarge file type
+ public enum StorageFileType {
+ PACKAGE_MAP,
+ FLAG_MAP,
+ FLAG_VAL,
+ FLAG_INFO
+ }
+
+ // Map a storage file given file path
+ public static MappedByteBuffer mapStorageFile(String file) throws IOException {
+ FileInputStream stream = new FileInputStream(file);
+ FileChannel channel = stream.getChannel();
+ return channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());
+ }
+
+ // Map a storage file given container and file type
+ public static MappedByteBuffer getMappedFile(
+ String container,
+ StorageFileType type) throws IOException{
+ switch (type) {
+ case PACKAGE_MAP:
+ return mapStorageFile(STORAGEDIR + "/maps/" + container + ".package.map");
+ case FLAG_MAP:
+ return mapStorageFile(STORAGEDIR + "/maps/" + container + ".flag.map");
+ case FLAG_VAL:
+ return mapStorageFile(STORAGEDIR + "/boot/" + container + ".val");
+ case FLAG_INFO:
+ return mapStorageFile(STORAGEDIR + "/boot/" + container + ".info");
+ default:
+ throw new IOException("Invalid storage file type");
+ }
+ }
+
+ // JNI interface to get package read context
+ // @param mappedFile: memory mapped package map file
+ // @param packageName: package name
+ // @throws IOException if the passed in file is not a valid package map file
+ @FastNative
+ private static native ByteBuffer getPackageReadContextImpl(
+ ByteBuffer mappedFile, String packageName) throws IOException;
+
+ // API to get package read context
+ // @param mappedFile: memory mapped package map file
+ // @param packageName: package name
+ // @throws IOException if the passed in file is not a valid package map file
+ static public PackageReadContext getPackageReadContext (
+ ByteBuffer mappedFile, String packageName) throws IOException {
+ ByteBuffer buffer = getPackageReadContextImpl(mappedFile, packageName);
+ buffer.order(ByteOrder.LITTLE_ENDIAN);
+ return new PackageReadContext(buffer.getInt(), buffer.getInt(4));
+ }
+
+ // JNI interface to get flag read context
+ // @param mappedFile: memory mapped flag map file
+ // @param packageId: package id to represent a specific package, obtained from
+ // package map file
+ // @param flagName: flag name
+ // @throws IOException if the passed in file is not a valid flag map file
+ @FastNative
+ private static native ByteBuffer getFlagReadContextImpl(
+ ByteBuffer mappedFile, int packageId, String flagName) throws IOException;
+
+ // API to get flag read context
+ // @param mappedFile: memory mapped flag map file
+ // @param packageId: package id to represent a specific package, obtained from
+ // package map file
+ // @param flagName: flag name
+ // @throws IOException if the passed in file is not a valid flag map file
+ public static FlagReadContext getFlagReadContext(
+ ByteBuffer mappedFile, int packageId, String flagName) throws IOException {
+ ByteBuffer buffer = getFlagReadContextImpl(mappedFile, packageId, flagName);
+ buffer.order(ByteOrder.LITTLE_ENDIAN);
+ return new FlagReadContext(buffer.getInt(), buffer.getInt(4));
+ }
+
+ // JNI interface to get boolean flag value
+ // @param mappedFile: memory mapped flag value file
+ // @param flagIndex: flag global index in the flag value array
+ // @throws IOException if the passed in file is not a valid flag value file or the
+ // flag index went over the file boundary.
+ @FastNative
+ public static native boolean getBooleanFlagValue(
+ ByteBuffer mappedFile, int flagIndex) throws IOException;
+
+ static {
+ System.loadLibrary("aconfig_storage_read_api_rust_jni");
+ }
+}
diff --git a/tools/aconfig/aconfig_storage_read_api/srcs/android/aconfig/storage/FlagReadContext.java b/tools/aconfig/aconfig_storage_read_api/srcs/android/aconfig/storage/FlagReadContext.java
new file mode 100644
index 0000000..60559a9
--- /dev/null
+++ b/tools/aconfig/aconfig_storage_read_api/srcs/android/aconfig/storage/FlagReadContext.java
@@ -0,0 +1,47 @@
+package android.aconfig.storage;
+/*
+ * Copyright (C) 2024 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.
+ */
+
+public class FlagReadContext {
+ public StoredFlagType mFlagType;
+ public int mFlagIndex;
+
+ public FlagReadContext(int flagType,
+ int flagIndex) {
+ mFlagType = StoredFlagType.fromInteger(flagType);
+ mFlagIndex = flagIndex;
+ }
+
+ // Flag type enum, consistent with the definition in aconfig_storage_file/src/lib.rs
+ public enum StoredFlagType {
+ ReadWriteBoolean,
+ ReadOnlyBoolean,
+ FixedReadOnlyBoolean;
+
+ public static StoredFlagType fromInteger(int x) {
+ switch(x) {
+ case 0:
+ return ReadWriteBoolean;
+ case 1:
+ return ReadOnlyBoolean;
+ case 2:
+ return FixedReadOnlyBoolean;
+ default:
+ return null;
+ }
+ }
+ }
+}
diff --git a/tools/aconfig/aconfig_storage_read_api/srcs/android/aconfig/storage/PackageReadContext.java b/tools/aconfig/aconfig_storage_read_api/srcs/android/aconfig/storage/PackageReadContext.java
new file mode 100644
index 0000000..b781d9b
--- /dev/null
+++ b/tools/aconfig/aconfig_storage_read_api/srcs/android/aconfig/storage/PackageReadContext.java
@@ -0,0 +1,27 @@
+package android.aconfig.storage;
+/*
+ * Copyright (C) 2024 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.
+ */
+
+public class PackageReadContext {
+ public int mPackageId;
+ public int mBooleanStartIndex;
+
+ public PackageReadContext(int packageId,
+ int booleanStartIndex) {
+ mPackageId = packageId;
+ mBooleanStartIndex = booleanStartIndex;
+ }
+}
diff --git a/tools/aconfig/aconfig_storage_read_api/srcs/lib.rs b/tools/aconfig/aconfig_storage_read_api/srcs/lib.rs
new file mode 100644
index 0000000..304a059
--- /dev/null
+++ b/tools/aconfig/aconfig_storage_read_api/srcs/lib.rs
@@ -0,0 +1,160 @@
+//! aconfig storage read api java rust interlop
+
+use aconfig_storage_read_api::flag_table_query::find_flag_read_context;
+use aconfig_storage_read_api::flag_value_query::find_boolean_flag_value;
+use aconfig_storage_read_api::package_table_query::find_package_read_context;
+use aconfig_storage_read_api::{FlagReadContext, PackageReadContext};
+
+use anyhow::Result;
+use jni::objects::{JByteBuffer, JClass, JString};
+use jni::sys::{jboolean, jint};
+use jni::JNIEnv;
+
+/// Call rust find package read context
+fn get_package_read_context_java(
+ env: &mut JNIEnv,
+ file: JByteBuffer,
+ package: JString,
+) -> Result<Option<PackageReadContext>> {
+ // SAFETY:
+ // The safety here is ensured as the package name is guaranteed to be a java string
+ let package_name: String = unsafe { env.get_string_unchecked(&package)?.into() };
+ let buffer_ptr = env.get_direct_buffer_address(&file)?;
+ let buffer_size = env.get_direct_buffer_capacity(&file)?;
+ // SAFETY:
+ // The safety here is ensured as only non null MemoryMappedBuffer will be passed in,
+ // so the conversion to slice is guaranteed to be valid
+ let buffer = unsafe { std::slice::from_raw_parts(buffer_ptr, buffer_size) };
+ Ok(find_package_read_context(buffer, &package_name)?)
+}
+
+/// Get package read context JNI
+#[no_mangle]
+#[allow(unused)]
+pub extern "system" fn Java_android_aconfig_storage_AconfigStorageReadAPI_getPackageReadContextImpl<
+ 'local,
+>(
+ mut env: JNIEnv<'local>,
+ class: JClass<'local>,
+ file: JByteBuffer<'local>,
+ package: JString<'local>,
+) -> JByteBuffer<'local> {
+ let mut package_id = -1;
+ let mut boolean_start_index = -1;
+
+ match get_package_read_context_java(&mut env, file, package) {
+ Ok(context_opt) => {
+ if let Some(context) = context_opt {
+ package_id = context.package_id as i32;
+ boolean_start_index = context.boolean_start_index as i32;
+ }
+ }
+ Err(errmsg) => {
+ env.throw(("java/io/IOException", errmsg.to_string())).expect("failed to throw");
+ }
+ }
+
+ let mut bytes = Vec::new();
+ bytes.extend_from_slice(&package_id.to_le_bytes());
+ bytes.extend_from_slice(&boolean_start_index.to_le_bytes());
+ let (addr, len) = {
+ let buf = bytes.leak();
+ (buf.as_mut_ptr(), buf.len())
+ };
+ // SAFETY:
+ // The safety here is ensured as the content is ensured to be valid
+ unsafe { env.new_direct_byte_buffer(addr, len).expect("failed to create byte buffer") }
+}
+
+/// Call rust find flag read context
+fn get_flag_read_context_java(
+ env: &mut JNIEnv,
+ file: JByteBuffer,
+ package_id: jint,
+ flag: JString,
+) -> Result<Option<FlagReadContext>> {
+ // SAFETY:
+ // The safety here is ensured as the flag name is guaranteed to be a java string
+ let flag_name: String = unsafe { env.get_string_unchecked(&flag)?.into() };
+ let buffer_ptr = env.get_direct_buffer_address(&file)?;
+ let buffer_size = env.get_direct_buffer_capacity(&file)?;
+ // SAFETY:
+ // The safety here is ensured as only non null MemoryMappedBuffer will be passed in,
+ // so the conversion to slice is guaranteed to be valid
+ let buffer = unsafe { std::slice::from_raw_parts(buffer_ptr, buffer_size) };
+ Ok(find_flag_read_context(buffer, package_id as u32, &flag_name)?)
+}
+
+/// Get flag read context JNI
+#[no_mangle]
+#[allow(unused)]
+pub extern "system" fn Java_android_aconfig_storage_AconfigStorageReadAPI_getFlagReadContextImpl<
+ 'local,
+>(
+ mut env: JNIEnv<'local>,
+ class: JClass<'local>,
+ file: JByteBuffer<'local>,
+ package_id: jint,
+ flag: JString<'local>,
+) -> JByteBuffer<'local> {
+ let mut flag_type = -1;
+ let mut flag_index = -1;
+
+ match get_flag_read_context_java(&mut env, file, package_id, flag) {
+ Ok(context_opt) => {
+ if let Some(context) = context_opt {
+ flag_type = context.flag_type as i32;
+ flag_index = context.flag_index as i32;
+ }
+ }
+ Err(errmsg) => {
+ env.throw(("java/io/IOException", errmsg.to_string())).expect("failed to throw");
+ }
+ }
+
+ let mut bytes = Vec::new();
+ bytes.extend_from_slice(&flag_type.to_le_bytes());
+ bytes.extend_from_slice(&flag_index.to_le_bytes());
+ let (addr, len) = {
+ let buf = bytes.leak();
+ (buf.as_mut_ptr(), buf.len())
+ };
+ // SAFETY:
+ // The safety here is ensured as the content is ensured to be valid
+ unsafe { env.new_direct_byte_buffer(addr, len).expect("failed to create byte buffer") }
+}
+
+/// Call rust find boolean flag value
+fn get_boolean_flag_value_java(
+ env: &mut JNIEnv,
+ file: JByteBuffer,
+ flag_index: jint,
+) -> Result<bool> {
+ let buffer_ptr = env.get_direct_buffer_address(&file)?;
+ let buffer_size = env.get_direct_buffer_capacity(&file)?;
+ // SAFETY:
+ // The safety here is ensured as only non null MemoryMappedBuffer will be passed in,
+ // so the conversion to slice is guaranteed to be valid
+ let buffer = unsafe { std::slice::from_raw_parts(buffer_ptr, buffer_size) };
+ Ok(find_boolean_flag_value(buffer, flag_index as u32)?)
+}
+
+/// Get flag value JNI
+#[no_mangle]
+#[allow(unused)]
+pub extern "system" fn Java_android_aconfig_storage_AconfigStorageReadAPI_getBooleanFlagValue<
+ 'local,
+>(
+ mut env: JNIEnv<'local>,
+ class: JClass<'local>,
+ file: JByteBuffer<'local>,
+ flag_index: jint,
+) -> jboolean {
+ match get_boolean_flag_value_java(&mut env, file, flag_index) {
+ Ok(value) => value as u8,
+ Err(errmsg) => {
+ env.throw(("java/io/IOException", errmsg.to_string())).expect("failed to throw");
+ 0u8
+ }
+ }
+}
diff --git a/tools/aconfig/aconfig_storage_read_api/tests/Android.bp b/tools/aconfig/aconfig_storage_read_api/tests/Android.bp
index 98944d6..ed0c728 100644
--- a/tools/aconfig/aconfig_storage_read_api/tests/Android.bp
+++ b/tools/aconfig/aconfig_storage_read_api/tests/Android.bp
@@ -1,7 +1,16 @@
+filegroup {
+ name: "read_api_test_storage_files",
+ srcs: ["package.map",
+ "flag.map",
+ "flag.val",
+ "flag.info"
+ ],
+}
+
rust_test {
name: "aconfig_storage_read_api.test.rust",
srcs: [
- "storage_read_api_test.rs"
+ "storage_read_api_test.rs",
],
rustlibs: [
"libanyhow",
@@ -10,10 +19,7 @@
"librand",
],
data: [
- "package.map",
- "flag.map",
- "flag.val",
- "flag.info",
+ ":read_api_test_storage_files",
],
test_suites: ["general-tests"],
}
@@ -30,10 +36,7 @@
"liblog",
],
data: [
- "package.map",
- "flag.map",
- "flag.val",
- "flag.info",
+ ":read_api_test_storage_files",
],
test_suites: [
"device-tests",
diff --git a/tools/aconfig/aconfig_storage_read_api/tests/java/AconfigStorageReadAPITest.java b/tools/aconfig/aconfig_storage_read_api/tests/java/AconfigStorageReadAPITest.java
new file mode 100644
index 0000000..a26b257
--- /dev/null
+++ b/tools/aconfig/aconfig_storage_read_api/tests/java/AconfigStorageReadAPITest.java
@@ -0,0 +1,213 @@
+/*
+ * Copyright (C) 2024 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.aconfig.storage.test;
+
+import java.io.IOException;
+import java.nio.MappedByteBuffer;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import android.aconfig.storage.AconfigStorageReadAPI;
+import android.aconfig.storage.PackageReadContext;
+import android.aconfig.storage.FlagReadContext;
+import android.aconfig.storage.FlagReadContext.StoredFlagType;
+
+@RunWith(JUnit4.class)
+public class AconfigStorageReadAPITest{
+
+ private String mStorageDir = "/data/local/tmp/aconfig_java_api_test";
+
+ @Test
+ public void testPackageContextQuery() {
+ MappedByteBuffer packageMap = null;
+ try {
+ packageMap = AconfigStorageReadAPI.mapStorageFile(
+ mStorageDir + "/maps/mockup.package.map");
+ } catch(IOException ex){
+ assertTrue(ex.toString(), false);
+ }
+ assertTrue(packageMap != null);
+
+ try {
+ PackageReadContext context = AconfigStorageReadAPI.getPackageReadContext(
+ packageMap, "com.android.aconfig.storage.test_1");
+ assertEquals(context.mPackageId, 0);
+ assertEquals(context.mBooleanStartIndex, 0);
+
+ context = AconfigStorageReadAPI.getPackageReadContext(
+ packageMap, "com.android.aconfig.storage.test_2");
+ assertEquals(context.mPackageId, 1);
+ assertEquals(context.mBooleanStartIndex, 3);
+
+ context = AconfigStorageReadAPI.getPackageReadContext(
+ packageMap, "com.android.aconfig.storage.test_4");
+ assertEquals(context.mPackageId, 2);
+ assertEquals(context.mBooleanStartIndex, 6);
+ } catch (IOException ex) {
+ assertTrue(ex.toString(), false);
+ }
+ }
+
+ @Test
+ public void testNonExistPackageContextQuery() {
+ MappedByteBuffer packageMap = null;
+ try {
+ packageMap = AconfigStorageReadAPI.mapStorageFile(
+ mStorageDir + "/maps/mockup.package.map");
+ } catch(IOException ex){
+ assertTrue(ex.toString(), false);
+ }
+ assertTrue(packageMap != null);
+
+ try {
+ PackageReadContext context = AconfigStorageReadAPI.getPackageReadContext(
+ packageMap, "unknown");
+ assertEquals(context.mPackageId, -1);
+ assertEquals(context.mBooleanStartIndex, -1);
+ } catch(IOException ex){
+ assertTrue(ex.toString(), false);
+ }
+ }
+
+ @Test
+ public void testFlagContextQuery() {
+ MappedByteBuffer flagMap = null;
+ try {
+ flagMap = AconfigStorageReadAPI.mapStorageFile(
+ mStorageDir + "/maps/mockup.flag.map");
+ } catch(IOException ex){
+ assertTrue(ex.toString(), false);
+ }
+ assertTrue(flagMap!= null);
+
+ class Baseline {
+ public int mPackageId;
+ public String mFlagName;
+ public StoredFlagType mFlagType;
+ public int mFlagIndex;
+
+ public Baseline(int packageId,
+ String flagName,
+ StoredFlagType flagType,
+ int flagIndex) {
+ mPackageId = packageId;
+ mFlagName = flagName;
+ mFlagType = flagType;
+ mFlagIndex = flagIndex;
+ }
+ }
+
+ List<Baseline> baselines = new ArrayList();
+ baselines.add(new Baseline(0, "enabled_ro", StoredFlagType.ReadOnlyBoolean, 1));
+ baselines.add(new Baseline(0, "enabled_rw", StoredFlagType.ReadWriteBoolean, 2));
+ baselines.add(new Baseline(2, "enabled_rw", StoredFlagType.ReadWriteBoolean, 1));
+ baselines.add(new Baseline(1, "disabled_rw", StoredFlagType.ReadWriteBoolean, 0));
+ baselines.add(new Baseline(1, "enabled_fixed_ro", StoredFlagType.FixedReadOnlyBoolean, 1));
+ baselines.add(new Baseline(1, "enabled_ro", StoredFlagType.ReadOnlyBoolean, 2));
+ baselines.add(new Baseline(2, "enabled_fixed_ro", StoredFlagType.FixedReadOnlyBoolean, 0));
+ baselines.add(new Baseline(0, "disabled_rw", StoredFlagType.ReadWriteBoolean, 0));
+
+ try {
+ for (Baseline baseline : baselines) {
+ FlagReadContext context = AconfigStorageReadAPI.getFlagReadContext(
+ flagMap, baseline.mPackageId, baseline.mFlagName);
+ assertEquals(context.mFlagType, baseline.mFlagType);
+ assertEquals(context.mFlagIndex, baseline.mFlagIndex);
+ }
+ } catch (IOException ex) {
+ assertTrue(ex.toString(), false);
+ }
+ }
+
+ @Test
+ public void testNonExistFlagContextQuery() {
+ MappedByteBuffer flagMap = null;
+ try {
+ flagMap = AconfigStorageReadAPI.mapStorageFile(
+ mStorageDir + "/maps/mockup.flag.map");
+ } catch(IOException ex){
+ assertTrue(ex.toString(), false);
+ }
+ assertTrue(flagMap!= null);
+
+ try {
+ FlagReadContext context = AconfigStorageReadAPI.getFlagReadContext(
+ flagMap, 0, "unknown");
+ assertEquals(context.mFlagType, null);
+ assertEquals(context.mFlagIndex, -1);
+
+ context = AconfigStorageReadAPI.getFlagReadContext(
+ flagMap, 3, "enabled_ro");
+ assertEquals(context.mFlagType, null);
+ assertEquals(context.mFlagIndex, -1);
+ } catch (IOException ex) {
+ assertTrue(ex.toString(), false);
+ }
+ }
+
+ @Test
+ public void testBooleanFlagValueQuery() {
+ MappedByteBuffer flagVal = null;
+ try {
+ flagVal = AconfigStorageReadAPI.mapStorageFile(
+ mStorageDir + "/boot/mockup.val");
+ } catch (IOException ex) {
+ assertTrue(ex.toString(), false);
+ }
+ assertTrue(flagVal!= null);
+
+ boolean[] baselines = {false, true, true, false, true, true, true, true};
+ for (int i = 0; i < 8; ++i) {
+ try {
+ Boolean value = AconfigStorageReadAPI.getBooleanFlagValue(flagVal, i);
+ assertEquals(value, baselines[i]);
+ } catch (IOException ex) {
+ assertTrue(ex.toString(), false);
+ }
+ }
+ }
+
+ @Test
+ public void testInvalidBooleanFlagValueQuery() {
+ MappedByteBuffer flagVal = null;
+ try {
+ flagVal = AconfigStorageReadAPI.mapStorageFile(
+ mStorageDir + "/boot/mockup.val");
+ } catch (IOException ex) {
+ assertTrue(ex.toString(), false);
+ }
+ assertTrue(flagVal!= null);
+
+ try {
+ Boolean value = AconfigStorageReadAPI.getBooleanFlagValue(flagVal, 9);
+ assertTrue("should throw", false);
+ } catch (IOException ex) {
+ String expectedErrmsg = "invalid storage file byte offset";
+ assertTrue(ex.toString(), ex.toString().contains(expectedErrmsg));
+ }
+ }
+ }
diff --git a/tools/aconfig/aconfig_storage_read_api/tests/java/Android.bp b/tools/aconfig/aconfig_storage_read_api/tests/java/Android.bp
new file mode 100644
index 0000000..d94b2b4
--- /dev/null
+++ b/tools/aconfig/aconfig_storage_read_api/tests/java/Android.bp
@@ -0,0 +1,21 @@
+android_test {
+ name: "aconfig_storage_read_api.test.java",
+ srcs: ["AconfigStorageReadAPITest.java"],
+ static_libs: [
+ "androidx.test.rules",
+ "libaconfig_storage_read_api_java",
+ "junit",
+ ],
+ jni_libs: [
+ "libaconfig_storage_read_api_rust_jni",
+ ],
+ data: [
+ ":read_api_test_storage_files",
+ ],
+ platform_apis: true,
+ certificate: "platform",
+ test_suites: [
+ "general-tests",
+ ],
+ team: "trendy_team_android_core_experiments",
+}
diff --git a/tools/aconfig/aconfig_storage_read_api/tests/java/AndroidManifest.xml b/tools/aconfig/aconfig_storage_read_api/tests/java/AndroidManifest.xml
new file mode 100644
index 0000000..78bfb37
--- /dev/null
+++ b/tools/aconfig/aconfig_storage_read_api/tests/java/AndroidManifest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2024 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="android.aconfig_storage.test">
+ <application>
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.aconfig_storage.test" />
+
+</manifest>
diff --git a/tools/aconfig/aconfig_storage_read_api/tests/java/AndroidTest.xml b/tools/aconfig/aconfig_storage_read_api/tests/java/AndroidTest.xml
new file mode 100644
index 0000000..99c9e25
--- /dev/null
+++ b/tools/aconfig/aconfig_storage_read_api/tests/java/AndroidTest.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2024 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.
+-->
+
+<configuration description="Config for aconfig storage read java api tests">
+ <!-- Need root to start virtualizationservice -->
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
+
+ <!-- Prepare test directories. -->
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+ <option name="throw-if-cmd-fail" value="true" />
+ <option name="run-command" value="mkdir -p /data/local/tmp/aconfig_java_api" />
+ <option name="teardown-command" value="rm -rf /data/local/tmp/aconfig_java_api" />
+ </target_preparer>
+
+ <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
+ <option name="test-file-name" value="aconfig_storage_read_api.test.java.apk" />
+ </target_preparer>
+
+ <target_preparer class="com.android.tradefed.targetprep.DisableSELinuxTargetPreparer" />
+
+ <!-- Test data files -->
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="cleanup" value="true" />
+ <option name="abort-on-push-failure" value="true" />
+ <option name="push-file" key="package.map"
+ value="/data/local/tmp/aconfig_java_api_test/maps/mockup.package.map" />
+ <option name="push-file" key="flag.map"
+ value="/data/local/tmp/aconfig_java_api_test/maps/mockup.flag.map" />
+ <option name="push-file" key="flag.val"
+ value="/data/local/tmp/aconfig_java_api_test/boot/mockup.val" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
+ <option name="package" value="android.aconfig_storage.test" />
+ <option name="runtime-hint" value="1m" />
+ </test>
+</configuration>
diff --git a/tools/check_elf_file.py b/tools/check_elf_file.py
index 51ec23b..1fd7950 100755
--- a/tools/check_elf_file.py
+++ b/tools/check_elf_file.py
@@ -67,7 +67,7 @@
ELF = collections.namedtuple(
'ELF',
- ('dt_soname', 'dt_needed', 'imported', 'exported', 'header'))
+ ('alignments', 'dt_soname', 'dt_needed', 'imported', 'exported', 'header'))
def _get_os_name():
@@ -195,7 +195,8 @@
@classmethod
def _read_llvm_readobj(cls, elf_file_path, header, llvm_readobj):
"""Run llvm-readobj and parse the output."""
- cmd = [llvm_readobj, '--dynamic-table', '--dyn-symbols', elf_file_path]
+ cmd = [llvm_readobj, '--program-headers', '--dynamic-table',
+ '--dyn-symbols', elf_file_path]
out = subprocess.check_output(cmd, text=True)
lines = out.splitlines()
return cls._parse_llvm_readobj(elf_file_path, header, lines)
@@ -205,9 +206,56 @@
def _parse_llvm_readobj(cls, elf_file_path, header, lines):
"""Parse the output of llvm-readobj."""
lines_it = iter(lines)
+ alignments = cls._parse_program_headers(lines_it)
dt_soname, dt_needed = cls._parse_dynamic_table(elf_file_path, lines_it)
imported, exported = cls._parse_dynamic_symbols(lines_it)
- return ELF(dt_soname, dt_needed, imported, exported, header)
+ return ELF(alignments, dt_soname, dt_needed, imported, exported, header)
+
+
+ _PROGRAM_HEADERS_START_PATTERN = 'ProgramHeaders ['
+ _PROGRAM_HEADERS_END_PATTERN = ']'
+ _PROGRAM_HEADER_START_PATTERN = 'ProgramHeader {'
+ _PROGRAM_HEADER_TYPE_PATTERN = re.compile('^\\s+Type:\\s+(.*)$')
+ _PROGRAM_HEADER_ALIGN_PATTERN = re.compile('^\\s+Alignment:\\s+(.*)$')
+ _PROGRAM_HEADER_END_PATTERN = '}'
+
+
+ @classmethod
+ def _parse_program_headers(cls, lines_it):
+ """Parse the dynamic table section."""
+ alignments = []
+
+ if not cls._find_prefix(cls._PROGRAM_HEADERS_START_PATTERN, lines_it):
+ raise ELFError()
+
+ for line in lines_it:
+ # Parse each program header
+ if line.strip() == cls._PROGRAM_HEADER_START_PATTERN:
+ p_align = None
+ p_type = None
+ for line in lines_it:
+ if line.strip() == cls._PROGRAM_HEADER_END_PATTERN:
+ if not p_align:
+ raise ELFError("Could not parse alignment from program header!")
+ if not p_type:
+ raise ELFError("Could not parse type from program header!")
+
+ if p_type.startswith("PT_LOAD "):
+ alignments.append(int(p_align))
+ break
+
+ match = cls._PROGRAM_HEADER_TYPE_PATTERN.match(line)
+ if match:
+ p_type = match.group(1)
+
+ match = cls._PROGRAM_HEADER_ALIGN_PATTERN.match(line)
+ if match:
+ p_align = match.group(1)
+
+ if line == cls._PROGRAM_HEADERS_END_PATTERN:
+ break
+
+ return alignments
_DYNAMIC_SECTION_START_PATTERN = 'DynamicSection ['
@@ -434,6 +482,24 @@
sys.exit(2)
+ def check_max_page_size(self, max_page_size):
+ for alignment in self._file_under_test.alignments:
+ if alignment % max_page_size != 0:
+ self._error(f'Load segment has alignment {alignment} but '
+ f'{max_page_size} required.')
+ self._note()
+ self._note('Fix suggestions:')
+ self._note(f' use linker flag "-Wl,-z,max-page-size={max_page_size}" '
+ f'when compiling this lib')
+ self._note()
+ self._note('If the fix above doesn\'t work, bypass this check with:')
+ self._note(' Android.bp: ignore_max_page_size: true,')
+ self._note(' Android.mk: LOCAL_IGNORE_MAX_PAGE_SIZE := true')
+ self._note(' Device mk: PRODUCT_CHECK_PREBUILT_MAX_PAGE_SIZE := false')
+
+ # TODO: instead of exiting immediately, we may want to collect the
+ # errors from all checks and emit them at once
+ sys.exit(2)
@staticmethod
def _find_symbol(lib, name, version):
@@ -514,6 +580,8 @@
help='Ignore the input file with unknown machine ID')
parser.add_argument('--allow-undefined-symbols', action='store_true',
help='Ignore unresolved undefined symbols')
+ parser.add_argument('--max-page-size', action='store', type=int,
+ help='Required page size alignment support')
# Other options
parser.add_argument('--llvm-readobj',
@@ -542,6 +610,9 @@
checker.check_dt_needed(args.system_shared_lib)
+ if args.max_page_size:
+ checker.check_max_page_size(args.max_page_size)
+
if not args.allow_undefined_symbols:
checker.check_symbols()
diff --git a/tools/envsetup/run_envsetup_tests b/tools/envsetup/run_envsetup_tests
new file mode 100755
index 0000000..5977448
--- /dev/null
+++ b/tools/envsetup/run_envsetup_tests
@@ -0,0 +1,229 @@
+#!/usr/bin/env python3
+
+# Copyright (C) 2024 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import os
+import pathlib
+import subprocess
+import sys
+
+SOURCE_ENVSETUP="source build/make/envsetup.sh && "
+
+def update_display():
+ sys.stderr.write("passed\n")
+
+def go_to_root():
+ while True:
+ if os.path.exists("build/make/envsetup.sh"):
+ return
+ if os.getcwd() == "/":
+ sys.stderr.write("Can't find root of the source tree\n");
+ print("\nFAILED")
+ sys.exit(1)
+ os.chdir("..")
+
+def is_test(name, thing):
+ if not callable(thing):
+ return False
+ if name == "test":
+ return False
+ return name.startswith("test")
+
+
+def test(shell, command, expected_return, expected_stdout, expected_stderr, expected_env):
+ command += "; _rc=$?"
+ for env in expected_env.keys():
+ command += f"; echo ENV: {env}=\\\"${env}\\\""
+ command += "; exit $_rc"
+
+ cmd = [shell, "-c", command]
+ result = subprocess.run(cmd, capture_output=True, text=True)
+
+ status = True
+
+ if result.returncode != expected_return:
+ print()
+ print(f"Expected return code: {expected_return}")
+ print(f"Actual return code: {result.returncode}")
+ status = False
+
+ printed_stdout = False
+ if expected_stdout and expected_stdout not in result.stdout:
+ print()
+ print(f"Expected stdout to contain:\n{expected_stdout}")
+ print(f"\nActual stdout:\n{result.stdout}")
+ printed_stdout = True
+ status = False
+
+ if expected_stderr and expected_stderr not in result.stderr:
+ print()
+ print(f"Expected stderr to contain:\n{expected_stderr}")
+ print(f"\nActual stderr:\n{result.stderr}")
+ status = False
+
+ env_failure = False
+ for k, v in expected_env.items():
+ if f"{k}=\"{v}\"" not in result.stdout:
+ print()
+ print(f"Expected environment variable {k} to be: {v} --- {k}=\"{v}\"")
+ env_failure = True
+ status = False
+
+ if env_failure and not printed_stdout:
+ print()
+ print("See stdout:")
+ print(result.stdout)
+
+ if not status:
+ print()
+ print("Command to reproduce:")
+ print(command)
+ print()
+
+ return status
+
+NO_LUNCH = {
+ "TARGET_PRODUCT": "",
+ "TARGET_RELEASE": "",
+ "TARGET_BUILD_VARIANT": "",
+}
+
+def test_invalid_lunch_target(shell):
+ return test(shell, SOURCE_ENVSETUP + "lunch invalid-trunk_staging-eng",
+ expected_return=1, expected_stdout=None,
+ expected_stderr="Cannot locate config makefile for product",
+ expected_env=NO_LUNCH)
+
+
+def test_aosp_arm(shell):
+ return test(shell, SOURCE_ENVSETUP + "lunch aosp_arm-trunk_staging-eng",
+ expected_return=0, expected_stdout=None, expected_stderr=None,
+ expected_env={
+ "TARGET_PRODUCT": "aosp_arm",
+ "TARGET_RELEASE": "trunk_staging",
+ "TARGET_BUILD_VARIANT": "eng",
+ })
+
+
+def test_lunch2_empty(shell):
+ return test(shell, SOURCE_ENVSETUP + "lunch2",
+ expected_return=1, expected_stdout=None,
+ expected_stderr="No target specified. See lunch --help",
+ expected_env=NO_LUNCH)
+
+def test_lunch2_four_params(shell):
+ return test(shell, SOURCE_ENVSETUP + "lunch2 a b c d",
+ expected_return=1, expected_stdout=None,
+ expected_stderr="Too many parameters given. See lunch --help",
+ expected_env=NO_LUNCH)
+
+def test_lunch2_aosp_arm(shell):
+ return test(shell, SOURCE_ENVSETUP + "lunch2 aosp_arm",
+ expected_return=0, expected_stdout="=========", expected_stderr=None,
+ expected_env={
+ "TARGET_PRODUCT": "aosp_arm",
+ "TARGET_RELEASE": "trunk_staging",
+ "TARGET_BUILD_VARIANT": "eng",
+ })
+
+def test_lunch2_aosp_arm_trunk_staging(shell):
+ # Somewhat unfortunate because trunk_staging is the only config in
+ # aosp so we can't really test that this isn't just getting the default
+ return test(shell, SOURCE_ENVSETUP + "lunch2 aosp_arm trunk_staging",
+ expected_return=0, expected_stdout="=========", expected_stderr=None,
+ expected_env={
+ "TARGET_PRODUCT": "aosp_arm",
+ "TARGET_RELEASE": "trunk_staging",
+ "TARGET_BUILD_VARIANT": "eng",
+ })
+
+def test_lunch2_aosp_arm_trunk_staging_userdebug(shell):
+ return test(shell, SOURCE_ENVSETUP + "lunch2 aosp_arm trunk_staging userdebug",
+ expected_return=0, expected_stdout="=========", expected_stderr=None,
+ expected_env={
+ "TARGET_PRODUCT": "aosp_arm",
+ "TARGET_RELEASE": "trunk_staging",
+ "TARGET_BUILD_VARIANT": "userdebug",
+ })
+
+def test_list_products(shell):
+ return test(shell, "build/soong/bin/list_products",
+ expected_return=0, expected_stdout="aosp_arm", expected_stderr=None,
+ expected_env=NO_LUNCH)
+
+def test_list_releases_param(shell):
+ return test(shell, "build/soong/bin/list_releases aosp_arm",
+ expected_return=0, expected_stdout="trunk_staging", expected_stderr=None,
+ expected_env=NO_LUNCH)
+
+def test_list_releases_env(shell):
+ return test(shell, "TARGET_PRODUCT=aosp_arm build/soong/bin/list_releases",
+ expected_return=0, expected_stdout="trunk_staging", expected_stderr=None,
+ expected_env=NO_LUNCH)
+
+def test_list_releases_no_product(shell):
+ return test(shell, "build/soong/bin/list_releases",
+ expected_return=1, expected_stdout=None, expected_stderr=None,
+ expected_env=NO_LUNCH)
+
+def test_list_variants(shell):
+ return test(shell, "build/soong/bin/list_variants",
+ expected_return=0, expected_stdout="userdebug", expected_stderr=None,
+ expected_env=NO_LUNCH)
+
+
+def test_get_build_var_in_path(shell):
+ return test(shell, SOURCE_ENVSETUP + "which get_build_var ",
+ expected_return=0, expected_stdout="soong/bin", expected_stderr=None,
+ expected_env=NO_LUNCH)
+
+
+
+TESTS=sorted([(name, thing) for name, thing in locals().items() if is_test(name, thing)])
+
+def main():
+ if any([x.endswith("/soong/bin") for x in os.getenv("PATH").split(":")]):
+ sys.stderr.write("run_envsetup_tests must be run in a shell that has not sourced"
+ + " envsetup.sh\n\nFAILED\n")
+ return 1
+
+ go_to_root()
+
+ tests = TESTS
+ if len(sys.argv) > 1:
+ tests = [(name, func) for name, func in tests if name in sys.argv]
+
+ shells = ["/usr/bin/bash", "/usr/bin/zsh"]
+ total_count = len(tests) * len(shells)
+ index = 1
+ failed_tests = 0
+
+ for name, func in tests:
+ for shell in shells:
+ sys.stdout.write(f"\33[2K\r{index} of {total_count}: {name} in {shell}")
+ passed = func(shell)
+ if not passed:
+ failed_tests += 1
+ index += 1
+
+ if failed_tests > 0:
+ print(f"\n\nFAILED: {failed_tests} of {total_count}")
+ return 1
+ else:
+ print("\n\nSUCCESS")
+ return 0
+
+if __name__ == "__main__":
+ sys.exit(main())
diff --git a/tools/envsetup/spam_for_lunch b/tools/envsetup/spam_for_lunch
new file mode 100755
index 0000000..2e150a6
--- /dev/null
+++ b/tools/envsetup/spam_for_lunch
@@ -0,0 +1,34 @@
+#!/bin/bash
+
+# Copyright 2024, 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 ad is kind of big, so only show it if this appears to be a clean build.
+source $(cd $(dirname $BASH_SOURCE) &> /dev/null && pwd)/../../shell_utils.sh
+if [[ ! -e $(getoutdir)/soong/build.${TARGET_PRODUCT}.ninja ]]; then
+ echo
+ echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
+ echo " Wondering whether to use user, userdebug or eng?"
+ echo
+ echo " user The builds that ship to users. Reduced debugability."
+ echo " userdebug High fidelity to user builds but with some debugging options"
+ echo " enabled. Best suited for performance testing or day-to-day use"
+ echo " with debugging enabled."
+ echo " eng More debugging options enabled and faster build times, but"
+ echo " runtime performance tradeoffs. Best suited for day-to-day"
+ echo " local development when not doing performance testing."
+ echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
+ echo
+fi
+