diff options
98 files changed, 3033 insertions, 1294 deletions
diff --git a/CleanSpec.mk b/CleanSpec.mk index dfc0cd0fff..f8c96ffffe 100644 --- a/CleanSpec.mk +++ b/CleanSpec.mk @@ -779,6 +779,14 @@ $(call add-clean-step, rm -rf $(OUT_DIR)/bazel/output/execroot/__main__/bazel-ou # Clear out rustc compiler intermediates after reverting rust compiler/linker split. $(call add-clean-step, find $(OUT_DIR) -name "*.rsp.whole.a" -print0 | xargs -0 /bin/bash -c 'rm -f $$$${@}; rm -f $$$${@/.rsp.whole.a/.rsp.a}; rm -f $$$${@/.rsp.whole.a/.rsp}') +# Remove obsolete java compilation artifacts +$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/) +$(call add-clean-step, find $(OUT_DIR) -type f -name "*.jar" -print0 | xargs -0 rm -f) + +# Remove obsolete java compilation artifacts +$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/) +$(call add-clean-step, find $(OUT_DIR) -type f -name "*.jar" -print0 | xargs -0 rm -f) + # ************************************************ # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST # ************************************************ diff --git a/METADATA b/METADATA deleted file mode 100644 index 44781a7088..0000000000 --- a/METADATA +++ /dev/null @@ -1,8 +0,0 @@ -third_party { - license_note: "would be NOTICE save for GPL in:\n" - " core/LINUX_KERNEL_COPYING\n" - " tools/droiddoc/templates-pdk/assets/jquery-1.6.2.min.js\n" - " tools/droiddoc/templates-pdk/assets/jquery-history.js\n" - " tools/droiddoc/templates-pdk/assets/jquery-resizable.min.js" - license_type: RESTRICTED -} diff --git a/cogsetup.sh b/cogsetup.sh index 44538f2a65..ef1485d5f2 100644 --- a/cogsetup.sh +++ b/cogsetup.sh @@ -52,7 +52,9 @@ function _setup_cog_env() { # it with this function. If the user is running repo within a Cog workspace, # we'll fail with an error, otherwise, we run the original repo command with # the given args. - ORIG_REPO_PATH=`which repo` + if ! ORIG_REPO_PATH=`which repo`; then + return 0 + fi function repo { if [[ "${PWD}" == /google/cog/* ]]; then echo "\e[01;31mERROR:\e[0mrepo command is disallowed within Cog workspaces." diff --git a/core/Makefile b/core/Makefile index e6a5bc0d4f..4900ac2fdc 100644 --- a/core/Makefile +++ b/core/Makefile @@ -1477,13 +1477,14 @@ boototapackage_4k: $(BUILT_BOOT_OTA_PACKAGE_4K) ifeq ($(BOARD_16K_OTA_MOVE_VENDOR),true) $(eval $(call copy-one-file,$(BUILT_BOOT_OTA_PACKAGE_4K),$(TARGET_OUT_VENDOR)/boot_otas/boot_ota_4k.zip)) $(eval $(call copy-one-file,$(BUILT_BOOT_OTA_PACKAGE_16K),$(TARGET_OUT_VENDOR)/boot_otas/boot_ota_16k.zip)) +ALL_DEFAULT_INSTALLED_MODULES += $(TARGET_OUT_VENDOR)/boot_otas/boot_ota_4k.zip +ALL_DEFAULT_INSTALLED_MODULES += $(TARGET_OUT_VENDOR)/boot_otas/boot_ota_16k.zip else $(eval $(call copy-one-file,$(BUILT_BOOT_OTA_PACKAGE_4K),$(TARGET_OUT)/boot_otas/boot_ota_4k.zip)) $(eval $(call copy-one-file,$(BUILT_BOOT_OTA_PACKAGE_16K),$(TARGET_OUT)/boot_otas/boot_ota_16k.zip)) -endif # BOARD_16K_OTA_MOVE_VENDOR == true - ALL_DEFAULT_INSTALLED_MODULES += $(TARGET_OUT)/boot_otas/boot_ota_4k.zip ALL_DEFAULT_INSTALLED_MODULES += $(TARGET_OUT)/boot_otas/boot_ota_16k.zip +endif # BOARD_16K_OTA_MOVE_VENDOR == true endif @@ -3405,12 +3406,30 @@ endif FULL_SYSTEMIMAGE_DEPS += $(INTERNAL_ROOT_FILES) $(INSTALLED_FILES_FILE_ROOT) -define write-file-lines -$(1): +# Returns a list of EXTRA_INSTALL_ZIPS trios whose primary file is contained within $(1) +# The trios will contain the primary installed file : the directory to unzip the zip to : the zip +define relevant-extra-install-zips +$(strip $(foreach p,$(EXTRA_INSTALL_ZIPS), \ + $(if $(filter $(call word-colon,1,$(p)),$(1)), \ + $(p)))) +endef + +# Writes a text file that contains all of the files that will be inside a partition. +# All the file paths will be relative to the partition's staging directory. +# It will also take into account files inside zips listed in EXTRA_INSTALL_ZIPS. +# +# Arguments: +# $(1): Output file +# $(2): The partition's staging directory +# $(3): Files to include in the partition +define write-partition-file-list +$(1): PRIVATE_RELEVANT_EXTRA_INSTALL_ZIPS := $(call relevant-extra-install-zips,$(filter $(2)/%,$(3))) +$(1): $$(HOST_OUT_EXECUTABLES)/extra_install_zips_file_list $$(foreach p,$$(PRIVATE_RELEVANT_EXTRA_INSTALL_ZIPS),$$(call word-colon,3,$$(p))) @echo Writing $$@ rm -f $$@ echo -n > $$@ - $$(foreach f,$(2),echo "$$(f)" >> $$@$$(newline)) + $$(foreach f,$(subst $(2)/,,$(filter $(2)/%,$(3))),echo "$$(f)" >> $$@$$(newline)) + $$(HOST_OUT_EXECUTABLES)/extra_install_zips_file_list $(2) $$(PRIVATE_RELEVANT_EXTRA_INSTALL_ZIPS) >> $$@ endef # ----------------------------------------------------------------- @@ -3476,7 +3495,7 @@ define build-systemimage-target exit 1 ) endef -$(eval $(call write-file-lines,$(systemimage_intermediates)/file_list.txt,$(subst $(TARGET_OUT)/,,$(filter $(TARGET_OUT)/%,$(FULL_SYSTEMIMAGE_DEPS))))) +$(eval $(call write-partition-file-list,$(systemimage_intermediates)/file_list.txt,$(TARGET_OUT),$(FULL_SYSTEMIMAGE_DEPS))) # Used by soong sandwich to request the staging dir be built $(systemimage_intermediates)/staging_dir.stamp: $(filter $(TARGET_OUT)/%,$(FULL_SYSTEMIMAGE_DEPS)) touch $@ @@ -3593,7 +3612,7 @@ INSTALLED_USERDATAIMAGE_TARGET_DEPS := \ $(INTERNAL_USERIMAGES_DEPS) \ $(INTERNAL_USERDATAIMAGE_FILES) -$(eval $(call write-file-lines,$(userdataimage_intermediates)/file_list.txt,$(subst $(TARGET_OUT_DATA)/,,$(filter $(TARGET_OUT_DATA)/%,$(INSTALLED_USERDATAIMAGE_TARGET_DEPS))))) +$(eval $(call write-partition-file-list,$(userdataimage_intermediates)/file_list.txt,$(TARGET_OUT_DATA),$(INSTALLED_USERDATAIMAGE_TARGET_DEPS))) # Used by soong sandwich to request the staging dir be built $(userdataimage_intermediates)/staging_dir.stamp: $(filter $(TARGET_OUT_DATA)/%,$(INSTALLED_USERDATAIMAGE_TARGET_DEPS)) touch $@ @@ -3649,7 +3668,7 @@ define build-cacheimage-target $(call assert-max-image-size,$(INSTALLED_CACHEIMAGE_TARGET),$(BOARD_CACHEIMAGE_PARTITION_SIZE)) endef -$(eval $(call write-file-lines,$(cacheimage_intermediates)/file_list.txt,$(subst $(TARGET_OUT_CACHE)/,,$(filter $(TARGET_OUT_CACHE)/%,$(INTERNAL_CACHEIMAGE_FILES))))) +$(eval $(call write-partition-file-list,$(cacheimage_intermediates)/file_list.txt,$(TARGET_OUT_CACHE),$(INTERNAL_CACHEIMAGE_FILES))) # Used by soong sandwich to request the staging dir be built $(cacheimage_intermediates)/staging_dir.stamp: $(filter $(TARGET_OUT_CACHE)/%,$(INTERNAL_CACHEIMAGE_FILES)) touch $@ @@ -3736,7 +3755,7 @@ define build-systemotherimage-target $(call assert-max-image-size,$(INSTALLED_SYSTEMOTHERIMAGE_TARGET),$(BOARD_SYSTEMIMAGE_PARTITION_SIZE)) endef -$(eval $(call write-file-lines,$(systemotherimage_intermediates)/file_list.txt,$(subst $(TARGET_OUT_SYSTEM_OTHER)/,,$(filter $(TARGET_OUT_SYSTEM_OTHER)/%,$(INTERNAL_SYSTEMOTHERIMAGE_FILES))))) +$(eval $(call write-partition-file-list,$(systemotherimage_intermediates)/file_list.txt,$(TARGET_OUT_SYSTEM_OTHER),$(INTERNAL_SYSTEMOTHERIMAGE_FILES))) # Used by soong sandwich to request the staging dir be built $(systemotherimage_intermediates)/staging_dir.stamp: $(filter $(TARGET_OUT_SYSTEM_OTHER)/%,$(INTERNAL_SYSTEMOTHERIMAGE_FILES)) touch $@ @@ -3842,7 +3861,7 @@ define build-vendorimage-target $(call assert-max-image-size,$(INSTALLED_VENDORIMAGE_TARGET) $(RECOVERY_FROM_BOOT_PATCH),$(BOARD_VENDORIMAGE_PARTITION_SIZE)) endef -$(eval $(call write-file-lines,$(vendorimage_intermediates)/file_list.txt,$(subst $(TARGET_OUT_VENDOR)/,,$(filter $(TARGET_OUT_VENDOR)/%,$(INTERNAL_VENDORIMAGE_FILES))))) +$(eval $(call write-partition-file-list,$(vendorimage_intermediates)/file_list.txt,$(TARGET_OUT_VENDOR),$(INTERNAL_VENDORIMAGE_FILES))) # Used by soong sandwich to request the staging dir be built $(vendorimage_intermediates)/staging_dir.stamp: $(filter $(TARGET_OUT_VENDOR)/%,$(INTERNAL_VENDORIMAGE_FILES)) touch $@ @@ -3915,7 +3934,7 @@ define build-productimage-target $(call assert-max-image-size,$(INSTALLED_PRODUCTIMAGE_TARGET),$(BOARD_PRODUCTIMAGE_PARTITION_SIZE)) endef -$(eval $(call write-file-lines,$(productimage_intermediates)/file_list.txt,$(subst $(TARGET_OUT_PRODUCT)/,,$(filter $(TARGET_OUT_PRODUCT)/%,$(INTERNAL_PRODUCTIMAGE_FILES))))) +$(eval $(call write-partition-file-list,$(productimage_intermediates)/file_list.txt,$(TARGET_OUT_PRODUCT),$(INTERNAL_PRODUCTIMAGE_FILES))) # Used by soong sandwich to request the staging dir be built $(productimage_intermediates)/staging_dir.stamp: $(filter $(TARGET_OUT_PRODUCT)/%,$(INTERNAL_PRODUCTIMAGE_FILES)) touch $@ @@ -3985,7 +4004,7 @@ define build-system_extimage-target $(call assert-max-image-size,$(INSTALLED_PRODUCT_SERVICESIMAGE_TARGET),$(BOARD_PRODUCT_SERVICESIMAGE_PARTITION_SIZE)) endef -$(eval $(call write-file-lines,$(system_extimage_intermediates)/file_list.txt,$(subst $(TARGET_OUT_SYSTEM_EXT)/,,$(filter $(TARGET_OUT_SYSTEM_EXT)/%,$(INTERNAL_SYSTEM_EXTIMAGE_FILES))))) +$(eval $(call write-partition-file-list,$(system_extimage_intermediates)/file_list.txt,$(TARGET_OUT_SYSTEM_EXT),$(INTERNAL_SYSTEM_EXTIMAGE_FILES))) # Used by soong sandwich to request the staging dir be built $(system_extimage_intermediates)/staging_dir.stamp: $(filter $(TARGET_OUT_SYSTEM_EXT)/%,$(INTERNAL_SYSTEM_EXTIMAGE_FILES)) touch $@ @@ -4074,7 +4093,7 @@ define build-odmimage-target $(call assert-max-image-size,$(INSTALLED_ODMIMAGE_TARGET),$(BOARD_ODMIMAGE_PARTITION_SIZE)) endef -$(eval $(call write-file-lines,$(odmimage_intermediates)/file_list.txt,$(subst $(TARGET_OUT_ODM)/,,$(filter $(TARGET_OUT_ODM)/%,$(INTERNAL_ODMIMAGE_FILES))))) +$(eval $(call write-partition-file-list,$(odmimage_intermediates)/file_list.txt,$(TARGET_OUT_ODM),$(INTERNAL_ODMIMAGE_FILES))) # Used by soong sandwich to request the staging dir be built $(odmimage_intermediates)/staging_dir.stamp: $(filter $(TARGET_OUT_ODM)/%,$(INTERNAL_ODMIMAGE_FILES)) touch $@ @@ -4143,7 +4162,7 @@ define build-vendor_dlkmimage-target $(call assert-max-image-size,$(INSTALLED_VENDOR_DLKMIMAGE_TARGET),$(BOARD_VENDOR_DLKMIMAGE_PARTITION_SIZE)) endef -$(eval $(call write-file-lines,$(vendor_dlkmimage_intermediates)/file_list.txt,$(subst $(TARGET_OUT_VENDOR_DLKM)/,,$(filter $(TARGET_OUT_VENDOR_DLKM)/%,$(INTERNAL_VENDOR_DLKMIMAGE_FILES))))) +$(eval $(call write-partition-file-list,$(vendor_dlkmimage_intermediates)/file_list.txt,$(TARGET_OUT_VENDOR_DLKM),$(INTERNAL_VENDOR_DLKMIMAGE_FILES))) # Used by soong sandwich to request the staging dir be built $(vendor_dlkmimage_intermediates)/staging_dir.stamp: $(filter $(TARGET_OUT_VENDOR_DLKM)/%,$(INTERNAL_VENDOR_DLKMIMAGE_FILES)) touch $@ @@ -4212,7 +4231,7 @@ define build-odm_dlkmimage-target $(call assert-max-image-size,$(INSTALLED_ODM_DLKMIMAGE_TARGET),$(BOARD_ODM_DLKMIMAGE_PARTITION_SIZE)) endef -$(eval $(call write-file-lines,$(odm_dlkmimage_intermediates)/file_list.txt,$(subst $(TARGET_OUT_ODM_DLKM)/,,$(filter $(TARGET_OUT_ODM_DLKM)/%,$(INTERNAL_ODM_DLKMIMAGE_FILES))))) +$(eval $(call write-partition-file-list,$(odm_dlkmimage_intermediates)/file_list.txt,$(TARGET_OUT_ODM_DLKM),$(INTERNAL_ODM_DLKMIMAGE_FILES))) # Used by soong sandwich to request the staging dir be built $(odm_dlkmimage_intermediates)/staging_dir.stamp: $(filter $(TARGET_OUT_ODM_DLKM)/%,$(INTERNAL_ODM_DLKMIMAGE_FILES)) touch $@ @@ -4283,7 +4302,7 @@ define build-system_dlkmimage-target $(call assert-max-image-size,$(INSTALLED_SYSTEM_DLKMIMAGE_TARGET),$(BOARD_SYSTEM_DLKMIMAGE_PARTITION_SIZE)) endef -$(eval $(call write-file-lines,$(system_dlkmimage_intermediates)/file_list.txt,$(subst $(TARGET_OUT_SYSTEM_DLKM)/,,$(filter $(TARGET_OUT_SYSTEM_DLKM)/%,$(INTERNAL_SYSTEM_DLKMIMAGE_FILES))))) +$(eval $(call write-partition-file-list,$(system_dlkmimage_intermediates)/file_list.txt,$(TARGET_OUT_SYSTEM_DLKM),$(INTERNAL_SYSTEM_DLKMIMAGE_FILES))) # Used by soong sandwich to request the staging dir be built $(system_dlkmimage_intermediates)/staging_dir.stamp: $(filter $(TARGET_OUT_SYSTEM_DLKM)/%,$(INTERNAL_SYSTEM_DLKMIMAGE_FILES)) touch $@ @@ -6919,6 +6938,7 @@ PATH=$(INTERNAL_USERIMAGES_BINARY_PATHS):$(dir $(ZIP2ZIP)):$$PATH \ --verbose \ --path $(HOST_OUT) \ $(if $(OEM_OTA_CONFIG), --oem_settings $(OEM_OTA_CONFIG)) \ + $(if $(BOOT_VAR_OTA_CONFIG), --boot_variable_file $(BOOT_VAR_OTA_CONFIG)) \ $(2) \ $(patsubst %.zip,%,$(BUILT_TARGET_FILES_PACKAGE)) $(1) endef diff --git a/core/android_soong_config_vars.mk b/core/android_soong_config_vars.mk index 56da5741e7..ed72fc3a0d 100644 --- a/core/android_soong_config_vars.mk +++ b/core/android_soong_config_vars.mk @@ -38,38 +38,6 @@ $(call add_soong_config_var,ANDROID,TARGET_DYNAMIC_64_32_MEDIASERVER) # PRODUCT_PRECOMPILED_SEPOLICY defaults to true. Explicitly check if it's "false" or not. $(call add_soong_config_var_value,ANDROID,PRODUCT_PRECOMPILED_SEPOLICY,$(if $(filter false,$(PRODUCT_PRECOMPILED_SEPOLICY)),false,true)) -# Default behavior for the tree wrt building modules or using prebuilts. This -# can always be overridden by setting the environment variable -# MODULE_BUILD_FROM_SOURCE. -BRANCH_DEFAULT_MODULE_BUILD_FROM_SOURCE := $(RELEASE_DEFAULT_MODULE_BUILD_FROM_SOURCE) -# TODO(b/301454934): The value from build flag is set to empty when use `False` -# The condition below can be removed after the issue get sorted. -ifeq (,$(BRANCH_DEFAULT_MODULE_BUILD_FROM_SOURCE)) - BRANCH_DEFAULT_MODULE_BUILD_FROM_SOURCE := false -endif - -ifneq (,$(MODULE_BUILD_FROM_SOURCE)) - # Keep an explicit setting. -else ifeq (,$(filter docs sdk win_sdk sdk_addon,$(MAKECMDGOALS))) - MODULE_BUILD_FROM_SOURCE := true -else ifneq (,$(PRODUCT_MODULE_BUILD_FROM_SOURCE)) - # Let products override the branch default. - MODULE_BUILD_FROM_SOURCE := $(PRODUCT_MODULE_BUILD_FROM_SOURCE) -else - MODULE_BUILD_FROM_SOURCE := $(BRANCH_DEFAULT_MODULE_BUILD_FROM_SOURCE) -endif - -ifneq (,$(ART_MODULE_BUILD_FROM_SOURCE)) - # Keep an explicit setting. -else ifneq (,$(findstring .android.art,$(TARGET_BUILD_APPS))) - # Build ART modules from source if they are listed in TARGET_BUILD_APPS. - ART_MODULE_BUILD_FROM_SOURCE := true -else - # Do the same as other modules by default. - ART_MODULE_BUILD_FROM_SOURCE := $(MODULE_BUILD_FROM_SOURCE) -endif - -$(call soong_config_set,art_module,source_build,$(ART_MODULE_BUILD_FROM_SOURCE)) ifdef ART_DEBUG_OPT_FLAG $(call soong_config_set,art_module,art_debug_opt_flag,$(ART_DEBUG_OPT_FLAG)) endif @@ -87,9 +55,10 @@ $(call add_soong_config_var_value,ANDROID,library_linking_strategy,prefer_static endif endif -ifeq (true,$(MODULE_BUILD_FROM_SOURCE)) +# TODO(b/308187800): some internal modules set `prefer` to true on the prebuilt apex module, +# and set that to false when `ANDROID.module_build_from_source` is true. +# Set this soong config variable to true for now, and cleanup `prefer` as part of b/308187800 $(call add_soong_config_var_value,ANDROID,module_build_from_source,true) -endif # Messaging app vars ifeq (eng,$(TARGET_BUILD_VARIANT)) diff --git a/core/art_config.mk b/core/art_config.mk index 47b4bcfce6..196db4f30b 100644 --- a/core/art_config.mk +++ b/core/art_config.mk @@ -19,8 +19,6 @@ ifeq (,$(filter default true false,$(config_enable_uffd_gc))) endif ENABLE_UFFD_GC := $(config_enable_uffd_gc) -# If the value is "default", it will be mangled by post_process_props.py. -ADDITIONAL_PRODUCT_PROPERTIES += ro.dalvik.vm.enable_uffd_gc=$(config_enable_uffd_gc) # Create APEX_BOOT_JARS_EXCLUDED which is a list of jars to be removed from # ApexBoorJars when built from mainline prebuilts. diff --git a/core/base_rules.mk b/core/base_rules.mk index 4c9281492a..9c7e906671 100644 --- a/core/base_rules.mk +++ b/core/base_rules.mk @@ -393,8 +393,8 @@ endif logtags_sources := $(filter %.logtags,$(LOCAL_SRC_FILES)) $(LOCAL_LOGTAGS_FILES) -ifneq ($(strip $(logtags_sources)),) -event_log_tags := $(foreach f,$(addprefix $(LOCAL_PATH)/,$(logtags_sources)),$(call clean-path,$(f))) +ifneq ($(strip $(logtags_sources) $(LOCAL_SOONG_LOGTAGS_FILES)),) +event_log_tags := $(foreach f,$(LOCAL_SOONG_LOGTAGS_FILES) $(addprefix $(LOCAL_PATH)/,$(logtags_sources)),$(call clean-path,$(f))) else event_log_tags := endif @@ -716,6 +716,14 @@ else test_config := $(wildcard $(LOCAL_PATH)/AndroidTest.xml) endif +ifeq ($(EXCLUDE_MCTS),true) + ifneq (,$(test_config)) + ifneq (,$(filter mcts-%,$(LOCAL_COMPATIBILITY_SUITE))) + LOCAL_COMPATIBILITY_SUITE := $(filter-out cts,$(LOCAL_COMPATIBILITY_SUITE)) + endif + endif +endif + ifneq (true,$(LOCAL_UNINSTALLABLE_MODULE)) # If we are building a native test or benchmark and its stem variants are not defined, diff --git a/core/binary.mk b/core/binary.mk index b17ab00aad..f86b5a464e 100644 --- a/core/binary.mk +++ b/core/binary.mk @@ -1196,6 +1196,17 @@ ifneq ($(filter hwaddress,$(my_sanitize)),) endif ################################################################### +## When compiling a memtag_stack enabled target, use the .memtag_stack variant +## of any static dependencies (where they exist). +################################################################## +ifneq ($(filter memtag_stack,$(my_sanitize)),) + my_whole_static_libraries := $(call use_soong_sanitized_static_libraries,\ + $(my_whole_static_libraries),memtag_stack) + my_static_libraries := $(call use_soong_sanitized_static_libraries,\ + $(my_static_libraries),memtag_stack) +endif + +################################################################### ## When compiling against API imported module, use API import stub ## libraries. ################################################################## diff --git a/core/board_config.mk b/core/board_config.mk index 633303f01a..e184601008 100644 --- a/core/board_config.mk +++ b/core/board_config.mk @@ -274,7 +274,7 @@ endif ifneq ($(MALLOC_IMPL),) $(warning *** Unsupported option MALLOC_IMPL defined by board config: $(board_config_mk).) - $(error Use `MALLOC_SVELTE := true` to configure jemalloc for low-memory) + $(error Use `MALLOC_LOW_MEMORY := true` to use low-memory allocator config) endif board_config_mk := diff --git a/core/clear_vars.mk b/core/clear_vars.mk index 5481d50713..fb42878584 100644 --- a/core/clear_vars.mk +++ b/core/clear_vars.mk @@ -264,6 +264,7 @@ LOCAL_SOONG_JACOCO_REPORT_CLASSES_JAR := LOCAL_SOONG_LICENSE_METADATA := LOCAL_SOONG_LINK_TYPE := LOCAL_SOONG_LINT_REPORTS := +LOCAL_SOONG_LOGTAGS_FILES := LOCAL_SOONG_MODULE_INFO_JSON := LOCAL_SOONG_MODULE_TYPE := LOCAL_SOONG_PROGUARD_DICT := diff --git a/core/config.mk b/core/config.mk index 584259457c..ce11b1d558 100644 --- a/core/config.mk +++ b/core/config.mk @@ -509,7 +509,6 @@ include $(BUILD_SYSTEM)/combo/javac.mk ifeq ($(CALLED_FROM_SETUP),true) include $(BUILD_SYSTEM)/ccache.mk -include $(BUILD_SYSTEM)/goma.mk include $(BUILD_SYSTEM)/rbe.mk endif @@ -1232,6 +1231,8 @@ BUILD_WARNING_BAD_OPTIONAL_USES_LIBS_ALLOWLIST := LegacyCamera Gallery2 # in the source tree. dont_bother_goals := out product-graph +include $(BUILD_SYSTEM)/sysprop_config.mk + # Make ANDROID Soong config variables visible to Android.mk files, for # consistency with those defined in BoardConfig.mk files. include $(BUILD_SYSTEM)/android_soong_config_vars.mk diff --git a/core/dex_preopt.mk b/core/dex_preopt.mk index 08311ca481..26b8b17a49 100644 --- a/core/dex_preopt.mk +++ b/core/dex_preopt.mk @@ -123,22 +123,28 @@ $(boot_zip): $(bootclasspath_jars) $(system_server_jars) $(SOONG_ZIP) $(MERGE_ZI $(call dist-for-goals, droidcore, $(boot_zip)) -ifneq (,$(filter true,$(ART_MODULE_BUILD_FROM_SOURCE) $(MODULE_BUILD_FROM_SOURCE))) # Build the system_server.zip which contains the Apex system server jars and standalone system server jars +system_server_dex2oat_dir := $(SOONG_OUT_DIR)/system_server_dexjars system_server_zip := $(PRODUCT_OUT)/system_server.zip +# non_updatable_system_server_jars contains jars in /system and /system_ext that are not part of an apex. +non_updatable_system_server_jars := \ + $(foreach m,$(PRODUCT_SYSTEM_SERVER_JARS),\ + $(system_server_dex2oat_dir)/$(call word-colon,2,$(m)).jar) + apex_system_server_jars := \ $(foreach m,$(PRODUCT_APEX_SYSTEM_SERVER_JARS),\ - $(PRODUCT_OUT)/apex/$(call word-colon,1,$(m))/javalib/$(call word-colon,2,$(m)).jar) + $(system_server_dex2oat_dir)/$(call word-colon,2,$(m)).jar) apex_standalone_system_server_jars := \ $(foreach m,$(PRODUCT_APEX_STANDALONE_SYSTEM_SERVER_JARS),\ - $(PRODUCT_OUT)/apex/$(call word-colon,1,$(m))/javalib/$(call word-colon,2,$(m)).jar) + $(system_server_dex2oat_dir)/$(call word-colon,2,$(m)).jar) standalone_system_server_jars := \ $(foreach m,$(PRODUCT_STANDALONE_SYSTEM_SERVER_JARS),\ - $(PRODUCT_OUT)/apex/$(call word-colon,1,$(m))/javalib/$(call word-colon,2,$(m)).jar) + $(system_server_dex2oat_dir)/$(call word-colon,2,$(m)).jar) -$(system_server_zip): PRIVATE_SYSTEM_SERVER_JARS := $(system_server_jars) +$(system_server_zip): PRIVATE_SYSTEM_SERVER_DEX2OAT_DIR := $(system_server_dex2oat_dir) +$(system_server_zip): PRIVATE_SYSTEM_SERVER_JARS := $(non_updatable_system_server_jars) $(system_server_zip): PRIVATE_APEX_SYSTEM_SERVER_JARS := $(apex_system_server_jars) $(system_server_zip): PRIVATE_APEX_STANDALONE_SYSTEM_SERVER_JARS := $(apex_standalone_system_server_jars) $(system_server_zip): PRIVATE_STANDALONE_SYSTEM_SERVER_JARS := $(standalone_system_server_jars) @@ -146,14 +152,13 @@ $(system_server_zip): $(system_server_jars) $(apex_system_server_jars) $(apex_st @echo "Create system server package: $@" rm -f $@ $(SOONG_ZIP) -o $@ \ - -C $(PRODUCT_OUT) $(addprefix -f ,$(PRIVATE_SYSTEM_SERVER_JARS)) \ - -C $(PRODUCT_OUT) $(addprefix -f ,$(PRIVATE_APEX_SYSTEM_SERVER_JARS)) \ - -C $(PRODUCT_OUT) $(addprefix -f ,$(PRIVATE_APEX_STANDALONE_SYSTEM_SERVER_JARS)) \ - -C $(PRODUCT_OUT) $(addprefix -f ,$(PRIVATE_STANDALONE_SYSTEM_SERVER_JARS)) + -C $(PRIVATE_SYSTEM_SERVER_DEX2OAT_DIR) $(addprefix -f ,$(PRIVATE_SYSTEM_SERVER_JARS)) \ + -C $(PRIVATE_SYSTEM_SERVER_DEX2OAT_DIR) $(addprefix -f ,$(PRIVATE_APEX_SYSTEM_SERVER_JARS)) \ + -C $(PRIVATE_SYSTEM_SERVER_DEX2OAT_DIR) $(addprefix -f ,$(PRIVATE_APEX_STANDALONE_SYSTEM_SERVER_JARS)) \ + -C $(PRIVATE_SYSTEM_SERVER_DEX2OAT_DIR) $(addprefix -f ,$(PRIVATE_STANDALONE_SYSTEM_SERVER_JARS)) $(call dist-for-goals, droidcore, $(system_server_zip)) -endif #ART_MODULE_BUILD_FROM_SOURCE || MODULE_BUILD_FROM_SOURCE endif #PRODUCT_USES_DEFAULT_ART_CONFIG endif #WITH_DEXPREOPT_ART_BOOT_IMG_ONLY endif #WITH_DEXPREOPT diff --git a/core/goma.mk b/core/goma.mk deleted file mode 100644 index 2b51d8be44..0000000000 --- a/core/goma.mk +++ /dev/null @@ -1,34 +0,0 @@ -# -# Copyright (C) 2015 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. -# - -# Notice: this works only with Google's Goma build infrastructure. -ifneq ($(filter-out false,$(USE_GOMA)),) - ifdef GOMA_DIR - goma_dir := $(GOMA_DIR) - else - goma_dir := $(HOME)/goma - endif - GOMA_CC := $(goma_dir)/gomacc - - # Append gomacc to existing *_WRAPPER variables so it's possible to - # use both ccache and gomacc. - CC_WRAPPER := $(strip $(CC_WRAPPER) $(GOMA_CC)) - CXX_WRAPPER := $(strip $(CXX_WRAPPER) $(GOMA_CC)) - # b/143658984: goma can't handle the --system argument to javac - #JAVAC_WRAPPER := $(strip $(JAVAC_WRAPPER) $(GOMA_CC)) - - goma_dir := -endif diff --git a/core/main.mk b/core/main.mk index 8182740321..d700fcb231 100644 --- a/core/main.mk +++ b/core/main.mk @@ -113,37 +113,8 @@ ifdef TARGET_ARCH_SUITE # $(error TARGET_ARCH_SUITE is not supported in kati/make builds) endif -# ADDITIONAL_<partition>_PROPERTIES are properties that are determined by the -# build system itself. Don't let it be defined from outside of the core build -# system like Android.mk or <product>.mk files. -_additional_prop_var_names := \ - ADDITIONAL_SYSTEM_PROPERTIES \ - ADDITIONAL_VENDOR_PROPERTIES \ - ADDITIONAL_ODM_PROPERTIES \ - ADDITIONAL_PRODUCT_PROPERTIES - -$(foreach name, $(_additional_prop_var_names),\ - $(if $($(name)),\ - $(error $(name) must not set before here. $($(name)))\ - ,)\ - $(eval $(name) :=)\ -) -_additional_prop_var_names := - $(KATI_obsolete_var ADDITIONAL_BUILD_PROPERTIES, Please use ADDITIONAL_SYSTEM_PROPERTIES) -# -# ----------------------------------------------------------------- -# Add the product-defined properties to the build properties. -ifneq ($(BOARD_PROPERTY_OVERRIDES_SPLIT_ENABLED), true) - ADDITIONAL_SYSTEM_PROPERTIES += $(PRODUCT_PROPERTY_OVERRIDES) -else - ifndef BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE - ADDITIONAL_SYSTEM_PROPERTIES += $(PRODUCT_PROPERTY_OVERRIDES) - endif -endif - - # Bring in standard build system definitions. include $(BUILD_SYSTEM)/definitions.mk @@ -175,178 +146,8 @@ endif # PDK builds are no longer supported, this is always platform TARGET_BUILD_JAVA_SUPPORT_LEVEL :=$= platform -# ----------------------------------------------------------------- - -ADDITIONAL_SYSTEM_PROPERTIES += ro.treble.enabled=${PRODUCT_FULL_TREBLE} - $(KATI_obsolete_var PRODUCT_FULL_TREBLE,\ Code should be written to work regardless of a device being Treble) - -# Set ro.llndk.api_level to show the maximum vendor API level that the LLNDK in -# the system partition supports. -ifdef RELEASE_BOARD_API_LEVEL -ADDITIONAL_SYSTEM_PROPERTIES += ro.llndk.api_level=$(RELEASE_BOARD_API_LEVEL) -endif - -# Sets ro.actionable_compatible_property.enabled to know on runtime whether the -# allowed list of actionable compatible properties is enabled or not. -ADDITIONAL_SYSTEM_PROPERTIES += ro.actionable_compatible_property.enabled=true - -# Add the system server compiler filter if they are specified for the product. -ifneq (,$(PRODUCT_SYSTEM_SERVER_COMPILER_FILTER)) -ADDITIONAL_PRODUCT_PROPERTIES += dalvik.vm.systemservercompilerfilter=$(PRODUCT_SYSTEM_SERVER_COMPILER_FILTER) -endif - -# Add the 16K developer option if it is defined for the product. -ifeq ($(PRODUCT_16K_DEVELOPER_OPTION),true) -ADDITIONAL_PRODUCT_PROPERTIES += ro.product.build.16k_page.enabled=true -else -ADDITIONAL_PRODUCT_PROPERTIES += ro.product.build.16k_page.enabled=false -endif - -# Enable core platform API violation warnings on userdebug and eng builds. -ifneq ($(TARGET_BUILD_VARIANT),user) -ADDITIONAL_SYSTEM_PROPERTIES += persist.debug.dalvik.vm.core_platform_api_policy=just-warn -endif - -# Define ro.sanitize.<name> properties for all global sanitizers. -ADDITIONAL_SYSTEM_PROPERTIES += $(foreach s,$(SANITIZE_TARGET),ro.sanitize.$(s)=true) - -# Sets the default value of ro.postinstall.fstab.prefix to /system. -# Device board config should override the value to /product when needed by: -# -# PRODUCT_PRODUCT_PROPERTIES += ro.postinstall.fstab.prefix=/product -# -# It then uses ${ro.postinstall.fstab.prefix}/etc/fstab.postinstall to -# mount system_other partition. -ADDITIONAL_SYSTEM_PROPERTIES += ro.postinstall.fstab.prefix=/system - -# Add cpu properties for bionic and ART. -ADDITIONAL_VENDOR_PROPERTIES += ro.bionic.arch=$(TARGET_ARCH) -ADDITIONAL_VENDOR_PROPERTIES += ro.bionic.cpu_variant=$(TARGET_CPU_VARIANT_RUNTIME) -ADDITIONAL_VENDOR_PROPERTIES += ro.bionic.2nd_arch=$(TARGET_2ND_ARCH) -ADDITIONAL_VENDOR_PROPERTIES += ro.bionic.2nd_cpu_variant=$(TARGET_2ND_CPU_VARIANT_RUNTIME) - -ADDITIONAL_VENDOR_PROPERTIES += persist.sys.dalvik.vm.lib.2=libart.so -ADDITIONAL_VENDOR_PROPERTIES += dalvik.vm.isa.$(TARGET_ARCH).variant=$(DEX2OAT_TARGET_CPU_VARIANT_RUNTIME) -ifneq ($(DEX2OAT_TARGET_INSTRUCTION_SET_FEATURES),) - ADDITIONAL_VENDOR_PROPERTIES += dalvik.vm.isa.$(TARGET_ARCH).features=$(DEX2OAT_TARGET_INSTRUCTION_SET_FEATURES) -endif - -ifdef TARGET_2ND_ARCH - ADDITIONAL_VENDOR_PROPERTIES += dalvik.vm.isa.$(TARGET_2ND_ARCH).variant=$($(TARGET_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_CPU_VARIANT_RUNTIME) - ifneq ($($(TARGET_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_INSTRUCTION_SET_FEATURES),) - ADDITIONAL_VENDOR_PROPERTIES += dalvik.vm.isa.$(TARGET_2ND_ARCH).features=$($(TARGET_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_INSTRUCTION_SET_FEATURES) - endif -endif - -# Although these variables are prefixed with TARGET_RECOVERY_, they are also needed under charger -# mode (via libminui). -ifdef TARGET_RECOVERY_DEFAULT_ROTATION -ADDITIONAL_VENDOR_PROPERTIES += \ - ro.minui.default_rotation=$(TARGET_RECOVERY_DEFAULT_ROTATION) -endif -ifdef TARGET_RECOVERY_OVERSCAN_PERCENT -ADDITIONAL_VENDOR_PROPERTIES += \ - ro.minui.overscan_percent=$(TARGET_RECOVERY_OVERSCAN_PERCENT) -endif -ifdef TARGET_RECOVERY_PIXEL_FORMAT -ADDITIONAL_VENDOR_PROPERTIES += \ - ro.minui.pixel_format=$(TARGET_RECOVERY_PIXEL_FORMAT) -endif - -ifdef PRODUCT_USE_DYNAMIC_PARTITIONS -ADDITIONAL_VENDOR_PROPERTIES += \ - ro.boot.dynamic_partitions=$(PRODUCT_USE_DYNAMIC_PARTITIONS) -endif - -ifdef PRODUCT_RETROFIT_DYNAMIC_PARTITIONS -ADDITIONAL_VENDOR_PROPERTIES += \ - ro.boot.dynamic_partitions_retrofit=$(PRODUCT_RETROFIT_DYNAMIC_PARTITIONS) -endif - -ifdef PRODUCT_SHIPPING_API_LEVEL -ADDITIONAL_VENDOR_PROPERTIES += \ - ro.product.first_api_level=$(PRODUCT_SHIPPING_API_LEVEL) -endif - -ifdef PRODUCT_SHIPPING_VENDOR_API_LEVEL -ADDITIONAL_VENDOR_PROPERTIES += \ - ro.vendor.api_level=$(PRODUCT_SHIPPING_VENDOR_API_LEVEL) -endif - -ifneq ($(TARGET_BUILD_VARIANT),user) - ifdef PRODUCT_SET_DEBUGFS_RESTRICTIONS - ADDITIONAL_VENDOR_PROPERTIES += \ - ro.product.debugfs_restrictions.enabled=$(PRODUCT_SET_DEBUGFS_RESTRICTIONS) - endif -endif - -# Vendors with GRF must define BOARD_SHIPPING_API_LEVEL for the vendor API level. -# This must not be defined for the non-GRF devices. -# The values of the GRF properties will be verified by post_process_props.py -ifdef BOARD_SHIPPING_API_LEVEL -ADDITIONAL_VENDOR_PROPERTIES += \ - ro.board.first_api_level=$(BOARD_SHIPPING_API_LEVEL) -endif - -# Build system set BOARD_API_LEVEL to show the api level of the vendor API surface. -# This must not be altered outside of build system. -ifdef BOARD_API_LEVEL -ADDITIONAL_VENDOR_PROPERTIES += \ - ro.board.api_level=$(BOARD_API_LEVEL) -endif -# RELEASE_BOARD_API_LEVEL_FROZEN is true when the vendor API surface is frozen. -ifdef RELEASE_BOARD_API_LEVEL_FROZEN -ADDITIONAL_VENDOR_PROPERTIES += \ - ro.board.api_frozen=$(RELEASE_BOARD_API_LEVEL_FROZEN) -endif - -# Set build prop. This prop is read by ota_from_target_files when generating OTA, -# to decide if VABC should be disabled. -ifeq ($(BOARD_DONT_USE_VABC_OTA),true) -ADDITIONAL_VENDOR_PROPERTIES += \ - ro.vendor.build.dont_use_vabc=true -endif - -# Set the flag in vendor. So VTS would know if the new fingerprint format is in use when -# the system images are replaced by GSI. -ifeq ($(BOARD_USE_VBMETA_DIGTEST_IN_FINGERPRINT),true) -ADDITIONAL_VENDOR_PROPERTIES += \ - ro.vendor.build.fingerprint_has_digest=1 -endif - -ADDITIONAL_VENDOR_PROPERTIES += \ - ro.vendor.build.security_patch=$(VENDOR_SECURITY_PATCH) \ - ro.product.board=$(TARGET_BOOTLOADER_BOARD_NAME) \ - ro.board.platform=$(TARGET_BOARD_PLATFORM) \ - ro.hwui.use_vulkan=$(TARGET_USES_VULKAN) - -ifdef TARGET_SCREEN_DENSITY -ADDITIONAL_VENDOR_PROPERTIES += \ - ro.sf.lcd_density=$(TARGET_SCREEN_DENSITY) -endif - -ifdef AB_OTA_UPDATER -ADDITIONAL_VENDOR_PROPERTIES += \ - ro.build.ab_update=$(AB_OTA_UPDATER) -endif - -ADDITIONAL_PRODUCT_PROPERTIES += ro.build.characteristics=$(TARGET_AAPT_CHARACTERISTICS) - -ifeq ($(AB_OTA_UPDATER),true) -ADDITIONAL_PRODUCT_PROPERTIES += ro.product.ab_ota_partitions=$(subst $(space),$(comma),$(sort $(AB_OTA_PARTITIONS))) -ADDITIONAL_VENDOR_PROPERTIES += ro.vendor.build.ab_ota_partitions=$(subst $(space),$(comma),$(sort $(AB_OTA_PARTITIONS))) -endif - -# Set this property for VTS to skip large page size tests on unsupported devices. -ADDITIONAL_PRODUCT_PROPERTIES += \ - ro.product.cpu.pagesize.max=$(TARGET_MAX_PAGE_SIZE_SUPPORTED) - -ifeq ($(PRODUCT_NO_BIONIC_PAGE_SIZE_MACRO),true) -ADDITIONAL_PRODUCT_PROPERTIES += ro.product.build.no_bionic_page_size_macro=true -endif - # ----------------------------------------------------------------- ### ### In this section we set up the things that are different @@ -359,66 +160,15 @@ ifneq ($(filter sdk sdk_addon,$(MAKECMDGOALS)),) is_sdk_build := true endif -## user/userdebug ## - -user_variant := $(filter user userdebug,$(TARGET_BUILD_VARIANT)) -enable_target_debugging := true tags_to_install := -ifneq (,$(user_variant)) - # Target is secure in user builds. - ADDITIONAL_SYSTEM_PROPERTIES += ro.secure=1 - ADDITIONAL_SYSTEM_PROPERTIES += security.perf_harden=1 - - ifeq ($(user_variant),user) - ADDITIONAL_SYSTEM_PROPERTIES += ro.adb.secure=1 - endif - ifeq ($(user_variant),userdebug) - # Pick up some extra useful tools - tags_to_install += debug - else - # Disable debugging in plain user builds. - enable_target_debugging := - endif - - # Disallow mock locations by default for user builds - ADDITIONAL_SYSTEM_PROPERTIES += ro.allow.mock.location=0 - -else # !user_variant - # Turn on checkjni for non-user builds. - ADDITIONAL_SYSTEM_PROPERTIES += ro.kernel.android.checkjni=1 - # Set device insecure for non-user builds. - ADDITIONAL_SYSTEM_PROPERTIES += ro.secure=0 - # Allow mock locations by default for non user builds - ADDITIONAL_SYSTEM_PROPERTIES += ro.allow.mock.location=1 -endif # !user_variant - -ifeq (true,$(strip $(enable_target_debugging))) - # Target is more debuggable and adbd is on by default - ADDITIONAL_SYSTEM_PROPERTIES += ro.debuggable=1 - # Enable Dalvik lock contention logging. - ADDITIONAL_SYSTEM_PROPERTIES += dalvik.vm.lockprof.threshold=500 -else # !enable_target_debugging - # Target is less debuggable and adbd is off by default - ADDITIONAL_SYSTEM_PROPERTIES += ro.debuggable=0 -endif # !enable_target_debugging - -## eng ## +ifeq ($(TARGET_BUILD_VARIANT),userdebug) +# Pick up some extra useful tools +tags_to_install := debug +endif ifeq ($(TARGET_BUILD_VARIANT),eng) tags_to_install := debug eng -ifneq ($(filter ro.setupwizard.mode=ENABLED, $(call collapse-pairs, $(ADDITIONAL_SYSTEM_PROPERTIES))),) - # Don't require the setup wizard on eng builds - ADDITIONAL_SYSTEM_PROPERTIES := $(filter-out ro.setupwizard.mode=%,\ - $(call collapse-pairs, $(ADDITIONAL_SYSTEM_PROPERTIES))) \ - ro.setupwizard.mode=OPTIONAL -endif -ifndef is_sdk_build - # To speedup startup of non-preopted builds, don't verify or compile the boot image. - ADDITIONAL_SYSTEM_PROPERTIES += dalvik.vm.image-dex2oat-filter=extract -endif -# b/323566535 -ADDITIONAL_SYSTEM_PROPERTIES += init.svc_debug.no_fatal.zygote=true endif ## asan ## @@ -454,18 +204,11 @@ endif # TODO: this should be eng I think. Since the sdk is built from the eng # variant. tags_to_install := debug eng -ADDITIONAL_SYSTEM_PROPERTIES += xmpp.auto-presence=true -ADDITIONAL_SYSTEM_PROPERTIES += ro.config.nocheckin=yes else # !sdk endif BUILD_WITHOUT_PV := true -ADDITIONAL_SYSTEM_PROPERTIES += net.bt.name=Android - -# This property is set by flashing debug boot image, so default to false. -ADDITIONAL_SYSTEM_PROPERTIES += ro.force.debuggable=0 - # ------------------------------------------------------------ # Define a function that, given a list of module tags, returns # non-empty if that module should be installed in /system. @@ -506,10 +249,6 @@ include $(BUILD_SYSTEM)/dex_preopt.mk # Strip and readonly a few more variables so they won't be modified. $(readonly-final-product-vars) -ADDITIONAL_SYSTEM_PROPERTIES := $(strip $(ADDITIONAL_SYSTEM_PROPERTIES)) -.KATI_READONLY := ADDITIONAL_SYSTEM_PROPERTIES -ADDITIONAL_PRODUCT_PROPERTIES := $(strip $(ADDITIONAL_PRODUCT_PROPERTIES)) -.KATI_READONLY := ADDITIONAL_PRODUCT_PROPERTIES ifneq ($(PRODUCT_ENFORCE_RRO_TARGETS),) ENFORCE_RRO_SOURCES := @@ -537,7 +276,7 @@ FULL_BUILD := true # Include all of the makefiles in the system # -subdir_makefiles := $(SOONG_OUT_DIR)/installs-$(TARGET_PRODUCT).mk $(SOONG_ANDROID_MK) +subdir_makefiles := $(SOONG_ANDROID_MK) # Android.mk files are only used on Linux builds, Mac only supports Android.bp ifeq ($(HOST_OS),linux) subdir_makefiles += $(file <$(OUT_DIR)/.module_paths/Android.mk.list) @@ -548,6 +287,8 @@ subdir_makefiles_total := $(words int $(subdir_makefiles) post finish) $(foreach mk,$(subdir_makefiles),$(info [$(call inc_and_print,subdir_makefiles_inc)/$(subdir_makefiles_total)] including $(mk) ...)$(eval include $(mk))) +include $(SOONG_OUT_DIR)/installs-$(TARGET_PRODUCT).mk + # For an unbundled image, we can skip blueprint_tools because unbundled image # aims to remove a large number framework projects from the manifest, the # sources or dependencies for these tools may be missing from the tree. diff --git a/core/product.mk b/core/product.mk index f8634efd25..0a761fb44e 100644 --- a/core/product.mk +++ b/core/product.mk @@ -418,8 +418,9 @@ _product_single_value_vars += PRODUCT_INSTALL_DEBUG_POLICY_TO_SYSTEM_EXT # /system/etc/security/fsverity/BuildManifest.apk _product_single_value_vars += PRODUCT_FSVERITY_GENERATE_METADATA -# If true, sets the default for MODULE_BUILD_FROM_SOURCE. This overrides -# BRANCH_DEFAULT_MODULE_BUILD_FROM_SOURCE but not an explicitly set value. +# If true, this builds the mainline modules from source. This overrides any +# prebuilts selected via RELEASE_APEX_CONTRIBUTIONS_* build flags for the +# current release config. _product_single_value_vars += PRODUCT_MODULE_BUILD_FROM_SOURCE # If true, installs a full version of com.android.virt APEX. diff --git a/core/product_config.mk b/core/product_config.mk index 4eeac9546c..f21c1c4188 100644 --- a/core/product_config.mk +++ b/core/product_config.mk @@ -314,6 +314,14 @@ endif ifeq (true,$(PRODUCT_MODULE_BUILD_FROM_SOURCE)) ignore_apex_contributions := true endif +ifneq ($(EMMA_INSTRUMENT)$(EMMA_INSTRUMENT_STATIC)$(EMMA_INSTRUMENT_FRAMEWORK)$(CLANG_COVERAGE)$(NATIVE_COVERAGE_PATHS),) +# Coverage builds for TARGET_RELEASE=foo should always build from source, +# even if TARGET_RELEASE=foo uses prebuilt mainline modules. +# This is necessary because the checked-in prebuilts were generated with +# instrumentation turned off. + ignore_apex_contributions := true +endif + ifeq (true, $(ignore_apex_contributions)) PRODUCT_BUILD_IGNORE_APEX_CONTRIBUTION_CONTENTS := true endif diff --git a/core/product_config.rbc b/core/product_config.rbc index 921f06805c..59e2c95903 100644 --- a/core/product_config.rbc +++ b/core/product_config.rbc @@ -351,6 +351,7 @@ def _percolate_inherited(configs, cfg_name, cfg, children_names): if cfg.get(attr, "") == "": cfg[attr] = value percolated_attrs[attr] = True + child_cfg.pop(attr) for attr in _options.trace_variables: if attr in percolated_attrs: @@ -360,7 +361,7 @@ def __move_items(to_list, from_cfg, attr): value = from_cfg.get(attr, []) if value: to_list.extend(value) - from_cfg[attr] = [] + from_cfg.pop(attr) def _indirect(pcm_name): """Returns configuration item for the inherited module.""" diff --git a/core/proguard/kotlin.flags b/core/proguard/kotlin.flags index 70dbaa7e81..ef6bf0e9e3 100644 --- a/core/proguard/kotlin.flags +++ b/core/proguard/kotlin.flags @@ -10,7 +10,9 @@ # Kotlin DebugMetadata has no value in release builds, these two rules, will # allow AppReduce to strip out DebutMetadata. --checkdiscard interface kotlin.coroutines.jvm.internal.DebugMetadata +# TODO(b/302383328): Restore the below checkdiscard after resolving transitive +# inclusion of kotlin-stdlib from androidx.annotation library deps. +# -checkdiscard interface kotlin.coroutines.jvm.internal.DebugMetadata -assumenosideeffects class kotlin.coroutines.jvm.internal.DebugMetadataKt { *** getDebugMetadataAnnotation(...); } diff --git a/core/release_config.mk b/core/release_config.mk index 3e51af5a44..97c8dd3571 100644 --- a/core/release_config.mk +++ b/core/release_config.mk @@ -41,6 +41,7 @@ # 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), \ @@ -53,12 +54,85 @@ config_map_files := $(wildcard build/release/release_config_map.mk) \ ) \ ) +protobuf_map_files := $(wildcard 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, \ + $(sort \ + $(wildcard device/*/release/release_config_map.textproto) \ + $(wildcard device/*/*/release/release_config_map.textproto) \ + $(wildcard vendor/*/release/release_config_map.textproto) \ + $(wildcard vendor/*/*/release/release_config_map.textproto) \ + ) \ + ) + # 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. +# Treat .mk and .textproto as equal for duplicate elimination, but force +# protobuf if any PRODUCT_RELEASE_CONFIG_MAPS specify .textproto. $(foreach map,$(PRODUCT_RELEASE_CONFIG_MAPS), \ - $(if $(filter $(map),$(config_map_files)),,$(eval config_map_files += $(map))) \ + $(if $(filter $(basename $(map)),$(basename $(config_map_files))),, \ + $(eval config_map_files += $(map))) \ + $(if $(filter $(basename $(map)).textproto,$(map)),$(eval _must_protobuf := true)) \ +) + + +# If we are missing the textproto version of any of $(config_map_files), we cannot use protobuf. +_can_protobuf := true +$(foreach map,$(config_map_files), \ + $(if $(wildcard $(basename $(map)).textproto),,$(eval _can_protobuf :=)) \ ) +# If we are missing the mk version of any of $(protobuf_map_files), we must use protobuf. +$(foreach map,$(protobuf_map_files), \ + $(if $(wildcard $(basename $(map)).mk),,$(eval _must_protobuf := true)) \ +) + +ifneq (,$(_must_protobuf)) + ifeq (,$(_can_protobuf)) + # We must use protobuf, but we cannot use protobuf. + $(error release config is a mixture of .scl and .textproto) + endif +endif + +_use_protobuf := +ifneq (,$(_must_protobuf)) + _use_protobuf := true +else + ifneq ($(_can_protobuf),) + # Determine the default + $(foreach map,$(config_map_files), \ + $(if $(wildcard $(dir $(map))/build_config/DEFAULT=proto),$(eval _use_protobuf := true)) \ + $(if $(wildcard $(dir $(map))/build_config/DEFAULT=make),$(eval _use_protobuf := )) \ + ) + # Update for this specific release config only (no inheritance). + $(foreach map,$(config_map_files), \ + $(if $(wildcard $(dir $(map))/build_config/$(TARGET_RELEASE)=proto),$(eval _use_protobuf := true)) \ + $(if $(wildcard $(dir $(map))/build_config/$(TARGET_RELEASE)=make),$(eval _use_protobuf := )) \ + ) + endif +endif + +ifneq (,$(_use_protobuf)) + # The .textproto files are the canonical source of truth. + _args := $(foreach map,$(config_map_files), --map $(map) ) + ifneq (,$(_must_protobuf)) + # Disable the build flag in release-config. + _args += --guard=false + endif + _flags_file:=$(OUT_DIR)/soong/release-config/release_config-$(TARGET_PRODUCT)-$(TARGET_RELEASE).mk + $(KATI_shell_no_rerun $(OUT_DIR)/release-config $(_args) >$(OUT_DIR)/release-config.out 2>&1 && touch -t 200001010000 $(OUT_DIR)/release-config.out $(_flags_file)) + $(if $(filter-out 0,$(.SHELLSTATUS)),$(error release-config failed to run)) + # This will also set _all_release_configs for us. + $(eval include $(OUT_DIR)/soong/release-config/release_config-$(TARGET_PRODUCT)-$(TARGET_RELEASE).mk) + $(KATI_extra_file_deps $(OUT_DIR)/release-config $(config_map_files)) + ifeq (,$(_must_protobuf)$(RELEASE_BUILD_FLAGS_IN_PROTOBUF)) + _use_protobuf := + endif +endif +ifeq (,$(_use_protobuf)) + # The .mk files are the canonical source of truth. + # Declare an alias release-config # @@ -144,6 +218,9 @@ $(foreach r,$(_all_release_configs),\ $(error Alias release config "$(r)" may not specify release config files $(_all_release_configs.$(r).FILES))\ ))) +# Use makefiles +endif + ifeq ($(TARGET_RELEASE),) # We allow some internal paths to explicitly set TARGET_RELEASE to the # empty string. For the most part, 'make' treats unset and empty string as @@ -167,6 +244,7 @@ ifneq (PRODUCT_RELEASE_CONFIG_MAPS,$(DUMP_MANY_VARS)) endif endif +ifeq (,$(_use_protobuf)) # Choose flag files # Don't sort this, use it in the order they gave us. # Do allow duplicate entries, retaining only the first usage. @@ -196,6 +274,9 @@ define _apply-release-config-overrides $(error invalid use of apply-release-config-overrides) endef +# use makefiles +endif + # TODO: Remove this check after enough people have sourced lunch that we don't # need to worry about it trying to do get_build_vars TARGET_RELEASE. Maybe after ~9/2023 ifneq ($(CALLED_FROM_SETUP),true) @@ -207,15 +288,20 @@ TARGET_RELEASE:= endif .KATI_READONLY := TARGET_RELEASE +ifeq (,$(_use_protobuf)) $(foreach config, $(_all_release_configs), \ $(eval _all_release_configs.$(config).DECLARED_IN:= ) \ $(eval _all_release_configs.$(config).FILES:= ) \ ) +applied_releases:= +# use makefiles +endif _all_release_configs:= config_map_files:= -applied_releases:= +protobuf_map_files:= +ifeq (,$(_use_protobuf)) # ----------------------------------------------------------------- # Flag declarations and values # ----------------------------------------------------------------- @@ -252,3 +338,8 @@ filename_to_starlark:= # outside of the source tree. $(call run-starlark,$(OUT_DIR)/release_config_entrypoint.scl,$(OUT_DIR)/release_config_entrypoint.scl,--allow_external_entrypoint) +# use makefiles +endif +_can_protobuf := +_must_protobuf := +_use_protobuf := diff --git a/core/soong_config.mk b/core/soong_config.mk index 534270e308..acd213c776 100644 --- a/core/soong_config.mk +++ b/core/soong_config.mk @@ -154,7 +154,7 @@ $(call add_json_list, ExtraVndkVersions, $(PRODUCT_EXTRA_VNDK_VE $(call add_json_list, DeviceSystemSdkVersions, $(BOARD_SYSTEMSDK_VERSIONS)) $(call add_json_str, RecoverySnapshotVersion, $(RECOVERY_SNAPSHOT_VERSION)) $(call add_json_list, Platform_systemsdk_versions, $(PLATFORM_SYSTEMSDK_VERSIONS)) -$(call add_json_bool, Malloc_not_svelte, $(call invert_bool,$(filter true,$(MALLOC_SVELTE)))) +$(call add_json_bool, Malloc_low_memory, $(findstring true,$(MALLOC_SVELTE) $(MALLOC_LOW_MEMORY))) $(call add_json_bool, Malloc_zero_contents, $(call invert_bool,$(filter false,$(MALLOC_ZERO_CONTENTS)))) $(call add_json_bool, Malloc_pattern_fill_contents, $(MALLOC_PATTERN_FILL_CONTENTS)) $(call add_json_str, Override_rs_driver, $(OVERRIDE_RS_DRIVER)) diff --git a/core/sysprop_config.mk b/core/sysprop_config.mk new file mode 100644 index 0000000000..a019a7d2c3 --- /dev/null +++ b/core/sysprop_config.mk @@ -0,0 +1,278 @@ +# ADDITIONAL_<partition>_PROPERTIES are properties that are determined by the +# build system itself. Don't let it be defined from outside of the core build +# system like Android.mk or <product>.mk files. +_additional_prop_var_names := \ + ADDITIONAL_SYSTEM_PROPERTIES \ + ADDITIONAL_VENDOR_PROPERTIES \ + ADDITIONAL_ODM_PROPERTIES \ + ADDITIONAL_PRODUCT_PROPERTIES + +$(foreach name, $(_additional_prop_var_names),\ + $(if $($(name)),\ + $(error $(name) must not set before here. $($(name)))\ + ,)\ + $(eval $(name) :=)\ +) +_additional_prop_var_names := + +# +# ----------------------------------------------------------------- +# Add the product-defined properties to the build properties. +ifneq ($(BOARD_PROPERTY_OVERRIDES_SPLIT_ENABLED), true) + ADDITIONAL_SYSTEM_PROPERTIES += $(PRODUCT_PROPERTY_OVERRIDES) +else + ifndef BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE + ADDITIONAL_SYSTEM_PROPERTIES += $(PRODUCT_PROPERTY_OVERRIDES) + endif +endif + +ADDITIONAL_SYSTEM_PROPERTIES += ro.treble.enabled=${PRODUCT_FULL_TREBLE} + +# Set ro.llndk.api_level to show the maximum vendor API level that the LLNDK in +# the system partition supports. +ifdef RELEASE_BOARD_API_LEVEL +ADDITIONAL_SYSTEM_PROPERTIES += ro.llndk.api_level=$(RELEASE_BOARD_API_LEVEL) +endif + +# Sets ro.actionable_compatible_property.enabled to know on runtime whether the +# allowed list of actionable compatible properties is enabled or not. +ADDITIONAL_SYSTEM_PROPERTIES += ro.actionable_compatible_property.enabled=true + +# Add the system server compiler filter if they are specified for the product. +ifneq (,$(PRODUCT_SYSTEM_SERVER_COMPILER_FILTER)) +ADDITIONAL_PRODUCT_PROPERTIES += dalvik.vm.systemservercompilerfilter=$(PRODUCT_SYSTEM_SERVER_COMPILER_FILTER) +endif + +# Add the 16K developer option if it is defined for the product. +ifeq ($(PRODUCT_16K_DEVELOPER_OPTION),true) +ADDITIONAL_PRODUCT_PROPERTIES += ro.product.build.16k_page.enabled=true +else +ADDITIONAL_PRODUCT_PROPERTIES += ro.product.build.16k_page.enabled=false +endif + +# Enable core platform API violation warnings on userdebug and eng builds. +ifneq ($(TARGET_BUILD_VARIANT),user) +ADDITIONAL_SYSTEM_PROPERTIES += persist.debug.dalvik.vm.core_platform_api_policy=just-warn +endif + +# Define ro.sanitize.<name> properties for all global sanitizers. +ADDITIONAL_SYSTEM_PROPERTIES += $(foreach s,$(SANITIZE_TARGET),ro.sanitize.$(s)=true) + +# Sets the default value of ro.postinstall.fstab.prefix to /system. +# Device board config should override the value to /product when needed by: +# +# PRODUCT_PRODUCT_PROPERTIES += ro.postinstall.fstab.prefix=/product +# +# It then uses ${ro.postinstall.fstab.prefix}/etc/fstab.postinstall to +# mount system_other partition. +ADDITIONAL_SYSTEM_PROPERTIES += ro.postinstall.fstab.prefix=/system + +# Add cpu properties for bionic and ART. +ADDITIONAL_VENDOR_PROPERTIES += ro.bionic.arch=$(TARGET_ARCH) +ADDITIONAL_VENDOR_PROPERTIES += ro.bionic.cpu_variant=$(TARGET_CPU_VARIANT_RUNTIME) +ADDITIONAL_VENDOR_PROPERTIES += ro.bionic.2nd_arch=$(TARGET_2ND_ARCH) +ADDITIONAL_VENDOR_PROPERTIES += ro.bionic.2nd_cpu_variant=$(TARGET_2ND_CPU_VARIANT_RUNTIME) + +ADDITIONAL_VENDOR_PROPERTIES += persist.sys.dalvik.vm.lib.2=libart.so +ADDITIONAL_VENDOR_PROPERTIES += dalvik.vm.isa.$(TARGET_ARCH).variant=$(DEX2OAT_TARGET_CPU_VARIANT_RUNTIME) +ifneq ($(DEX2OAT_TARGET_INSTRUCTION_SET_FEATURES),) + ADDITIONAL_VENDOR_PROPERTIES += dalvik.vm.isa.$(TARGET_ARCH).features=$(DEX2OAT_TARGET_INSTRUCTION_SET_FEATURES) +endif + +ifdef TARGET_2ND_ARCH + ADDITIONAL_VENDOR_PROPERTIES += dalvik.vm.isa.$(TARGET_2ND_ARCH).variant=$($(TARGET_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_CPU_VARIANT_RUNTIME) + ifneq ($($(TARGET_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_INSTRUCTION_SET_FEATURES),) + ADDITIONAL_VENDOR_PROPERTIES += dalvik.vm.isa.$(TARGET_2ND_ARCH).features=$($(TARGET_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_INSTRUCTION_SET_FEATURES) + endif +endif + +# Although these variables are prefixed with TARGET_RECOVERY_, they are also needed under charger +# mode (via libminui). +ifdef TARGET_RECOVERY_DEFAULT_ROTATION +ADDITIONAL_VENDOR_PROPERTIES += \ + ro.minui.default_rotation=$(TARGET_RECOVERY_DEFAULT_ROTATION) +endif +ifdef TARGET_RECOVERY_OVERSCAN_PERCENT +ADDITIONAL_VENDOR_PROPERTIES += \ + ro.minui.overscan_percent=$(TARGET_RECOVERY_OVERSCAN_PERCENT) +endif +ifdef TARGET_RECOVERY_PIXEL_FORMAT +ADDITIONAL_VENDOR_PROPERTIES += \ + ro.minui.pixel_format=$(TARGET_RECOVERY_PIXEL_FORMAT) +endif + +ifdef PRODUCT_USE_DYNAMIC_PARTITIONS +ADDITIONAL_VENDOR_PROPERTIES += \ + ro.boot.dynamic_partitions=$(PRODUCT_USE_DYNAMIC_PARTITIONS) +endif + +ifdef PRODUCT_RETROFIT_DYNAMIC_PARTITIONS +ADDITIONAL_VENDOR_PROPERTIES += \ + ro.boot.dynamic_partitions_retrofit=$(PRODUCT_RETROFIT_DYNAMIC_PARTITIONS) +endif + +ifdef PRODUCT_SHIPPING_API_LEVEL +ADDITIONAL_VENDOR_PROPERTIES += \ + ro.product.first_api_level=$(PRODUCT_SHIPPING_API_LEVEL) +endif + +ifdef PRODUCT_SHIPPING_VENDOR_API_LEVEL +ADDITIONAL_VENDOR_PROPERTIES += \ + ro.vendor.api_level=$(PRODUCT_SHIPPING_VENDOR_API_LEVEL) +endif + +ifneq ($(TARGET_BUILD_VARIANT),user) + ifdef PRODUCT_SET_DEBUGFS_RESTRICTIONS + ADDITIONAL_VENDOR_PROPERTIES += \ + ro.product.debugfs_restrictions.enabled=$(PRODUCT_SET_DEBUGFS_RESTRICTIONS) + endif +endif + +# Vendors with GRF must define BOARD_SHIPPING_API_LEVEL for the vendor API level. +# This must not be defined for the non-GRF devices. +# The values of the GRF properties will be verified by post_process_props.py +ifdef BOARD_SHIPPING_API_LEVEL +ADDITIONAL_VENDOR_PROPERTIES += \ + ro.board.first_api_level=$(BOARD_SHIPPING_API_LEVEL) +endif + +# Build system set BOARD_API_LEVEL to show the api level of the vendor API surface. +# This must not be altered outside of build system. +ifdef BOARD_API_LEVEL +ADDITIONAL_VENDOR_PROPERTIES += \ + ro.board.api_level=$(BOARD_API_LEVEL) +endif +# RELEASE_BOARD_API_LEVEL_FROZEN is true when the vendor API surface is frozen. +ifdef RELEASE_BOARD_API_LEVEL_FROZEN +ADDITIONAL_VENDOR_PROPERTIES += \ + ro.board.api_frozen=$(RELEASE_BOARD_API_LEVEL_FROZEN) +endif + +# Set build prop. This prop is read by ota_from_target_files when generating OTA, +# to decide if VABC should be disabled. +ifeq ($(BOARD_DONT_USE_VABC_OTA),true) +ADDITIONAL_VENDOR_PROPERTIES += \ + ro.vendor.build.dont_use_vabc=true +endif + +# Set the flag in vendor. So VTS would know if the new fingerprint format is in use when +# the system images are replaced by GSI. +ifeq ($(BOARD_USE_VBMETA_DIGTEST_IN_FINGERPRINT),true) +ADDITIONAL_VENDOR_PROPERTIES += \ + ro.vendor.build.fingerprint_has_digest=1 +endif + +ADDITIONAL_VENDOR_PROPERTIES += \ + ro.vendor.build.security_patch=$(VENDOR_SECURITY_PATCH) \ + ro.product.board=$(TARGET_BOOTLOADER_BOARD_NAME) \ + ro.board.platform=$(TARGET_BOARD_PLATFORM) \ + ro.hwui.use_vulkan=$(TARGET_USES_VULKAN) + +ifdef TARGET_SCREEN_DENSITY +ADDITIONAL_VENDOR_PROPERTIES += \ + ro.sf.lcd_density=$(TARGET_SCREEN_DENSITY) +endif + +ifdef AB_OTA_UPDATER +ADDITIONAL_VENDOR_PROPERTIES += \ + ro.build.ab_update=$(AB_OTA_UPDATER) +endif + +ADDITIONAL_PRODUCT_PROPERTIES += ro.build.characteristics=$(TARGET_AAPT_CHARACTERISTICS) + +ifeq ($(AB_OTA_UPDATER),true) +ADDITIONAL_PRODUCT_PROPERTIES += ro.product.ab_ota_partitions=$(subst $(space),$(comma),$(sort $(AB_OTA_PARTITIONS))) +ADDITIONAL_VENDOR_PROPERTIES += ro.vendor.build.ab_ota_partitions=$(subst $(space),$(comma),$(sort $(AB_OTA_PARTITIONS))) +endif + +# Set this property for VTS to skip large page size tests on unsupported devices. +ADDITIONAL_PRODUCT_PROPERTIES += \ + ro.product.cpu.pagesize.max=$(TARGET_MAX_PAGE_SIZE_SUPPORTED) + +ifeq ($(PRODUCT_NO_BIONIC_PAGE_SIZE_MACRO),true) +ADDITIONAL_PRODUCT_PROPERTIES += ro.product.build.no_bionic_page_size_macro=true +endif + +user_variant := $(filter user userdebug,$(TARGET_BUILD_VARIANT)) +enable_target_debugging := true +ifneq (,$(user_variant)) + # Target is secure in user builds. + ADDITIONAL_SYSTEM_PROPERTIES += ro.secure=1 + ADDITIONAL_SYSTEM_PROPERTIES += security.perf_harden=1 + + ifeq ($(user_variant),user) + ADDITIONAL_SYSTEM_PROPERTIES += ro.adb.secure=1 + endif + + ifneq ($(user_variant),userdebug) + # Disable debugging in plain user builds. + enable_target_debugging := + endif + + # Disallow mock locations by default for user builds + ADDITIONAL_SYSTEM_PROPERTIES += ro.allow.mock.location=0 + +else # !user_variant + # Turn on checkjni for non-user builds. + ADDITIONAL_SYSTEM_PROPERTIES += ro.kernel.android.checkjni=1 + # Set device insecure for non-user builds. + ADDITIONAL_SYSTEM_PROPERTIES += ro.secure=0 + # Allow mock locations by default for non user builds + ADDITIONAL_SYSTEM_PROPERTIES += ro.allow.mock.location=1 +endif # !user_variant + +ifeq (true,$(strip $(enable_target_debugging))) + # Target is more debuggable and adbd is on by default + ADDITIONAL_SYSTEM_PROPERTIES += ro.debuggable=1 + # Enable Dalvik lock contention logging. + ADDITIONAL_SYSTEM_PROPERTIES += dalvik.vm.lockprof.threshold=500 +else # !enable_target_debugging + # Target is less debuggable and adbd is off by default + ADDITIONAL_SYSTEM_PROPERTIES += ro.debuggable=0 +endif # !enable_target_debugging + +ifneq ($(filter sdk sdk_addon,$(MAKECMDGOALS)),) +_is_sdk_build := true +endif + +ifeq ($(TARGET_BUILD_VARIANT),eng) +ifneq ($(filter ro.setupwizard.mode=ENABLED, $(call collapse-pairs, $(ADDITIONAL_SYSTEM_PROPERTIES))),) + # Don't require the setup wizard on eng builds + ADDITIONAL_SYSTEM_PROPERTIES := $(filter-out ro.setupwizard.mode=%,\ + $(call collapse-pairs, $(ADDITIONAL_SYSTEM_PROPERTIES))) \ + ro.setupwizard.mode=OPTIONAL +endif +ifndef _is_sdk_build + # To speedup startup of non-preopted builds, don't verify or compile the boot image. + ADDITIONAL_SYSTEM_PROPERTIES += dalvik.vm.image-dex2oat-filter=extract +endif +# b/323566535 +ADDITIONAL_SYSTEM_PROPERTIES += init.svc_debug.no_fatal.zygote=true +endif + +ifdef _is_sdk_build +ADDITIONAL_SYSTEM_PROPERTIES += xmpp.auto-presence=true +ADDITIONAL_SYSTEM_PROPERTIES += ro.config.nocheckin=yes +endif + +_is_sdk_build := + +ADDITIONAL_SYSTEM_PROPERTIES += net.bt.name=Android + +# This property is set by flashing debug boot image, so default to false. +ADDITIONAL_SYSTEM_PROPERTIES += ro.force.debuggable=0 + +config_enable_uffd_gc := \ + $(firstword $(OVERRIDE_ENABLE_UFFD_GC) $(PRODUCT_ENABLE_UFFD_GC) default) + +# If the value is "default", it will be mangled by post_process_props.py. +ADDITIONAL_PRODUCT_PROPERTIES += ro.dalvik.vm.enable_uffd_gc=$(config_enable_uffd_gc) + +ADDITIONAL_SYSTEM_PROPERTIES := $(strip $(ADDITIONAL_SYSTEM_PROPERTIES)) +ADDITIONAL_PRODUCT_PROPERTIES := $(strip $(ADDITIONAL_PRODUCT_PROPERTIES)) +ADDITIONAL_VENDOR_PROPERTIES := $(strip $(ADDITIONAL_VENDOR_PROPERTIES)) + +.KATI_READONLY += \ + ADDITIONAL_SYSTEM_PROPERTIES \ + ADDITIONAL_PRODUCT_PROPERTIES \ + ADDITIONAL_VENDOR_PROPERTIES diff --git a/core/tasks/meta-lic.mk b/core/tasks/meta-lic.mk index 99ecd83fa1..2126bd02ba 100644 --- a/core/tasks/meta-lic.mk +++ b/core/tasks/meta-lic.mk @@ -30,6 +30,23 @@ $(eval $(call declare-1p-copy-files,device/google_car/common,)) $(eval $(call declare-1p-copy-files,device/google/atv,atv-component-overrides.xml)) $(eval $(call declare-1p-copy-files,device/google/atv,tv_core_hardware.xml)) +# Moved here from device/google/barbet/Android.mk +$(eval $(call declare-copy-files-license-metadata,device/google/barbet,default-permissions.xml,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,)) +$(eval $(call declare-copy-files-license-metadata,device/google/barbet,libnfc-nci.conf,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,)) +$(eval $(call declare-copy-files-license-metadata,device/google/barbet,fstab.postinstall,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,)) +$(eval $(call declare-copy-files-license-metadata,device/google/barbet,ueventd.rc,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,)) +$(eval $(call declare-copy-files-license-metadata,device/google/barbet,wpa_supplicant.conf,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,)) +$(eval $(call declare-copy-files-license-metadata,device/google/barbet,hals.conf,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,)) +$(eval $(call declare-copy-files-license-metadata,device/google/barbet,media_profiles_V1_0.xml,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,)) +$(eval $(call declare-copy-files-license-metadata,device/google/barbet,media_codecs_performance.xml,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,)) +$(eval $(call declare-copy-files-license-metadata,device/google/barbet,device_state_configuration.xml,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,)) +$(eval $(call declare-copy-files-license-metadata,device/google/barbet,task_profiles.json,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,)) +$(eval $(call declare-copy-files-license-metadata,device/google/barbet,p2p_supplicant.conf,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,)) +$(eval $(call declare-copy-files-license-metadata,device/google/barbet,wpa_supplicant.conf,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,)) +$(eval $(call declare-copy-files-license-metadata,device/google/barbet,wpa_supplicant_overlay.conf,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,)) + +$(eval $(call declare-1p-copy-files,device/google/barbet,audio_policy_configuration.xml)) + # Moved here from device/google/coral/Android.mk $(eval $(call declare-copy-files-license-metadata,device/google/coral,default-permissions.xml,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,)) $(eval $(call declare-copy-files-license-metadata,device/google/coral,libnfc-nci.conf,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,)) @@ -49,9 +66,64 @@ $(eval $(call declare-copy-files-license-metadata,device/google/coral,display_19 $(eval $(call declare-1p-copy-files,device/google/coral,audio_policy_configuration.xml)) $(eval $(call declare-1p-copy-files,device/google/coral,display_19260504575090817.xml)) +# Moved here from device/google/gs101/Android.mk +$(eval $(call declare-copy-files-license-metadata,device/google/gs101,default-permissions.xml,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,)) +$(eval $(call declare-copy-files-license-metadata,device/google/gs101,libnfc-nci.conf,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,)) +$(eval $(call declare-copy-files-license-metadata,device/google/gs101,fstab.postinstall,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,)) +$(eval $(call declare-copy-files-license-metadata,device/google/gs101,ueventd.rc,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,)) +$(eval $(call declare-copy-files-license-metadata,device/google/gs101,wpa_supplicant.conf,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,)) +$(eval $(call declare-copy-files-license-metadata,device/google/gs101,hals.conf,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,)) +$(eval $(call declare-copy-files-license-metadata,device/google/gs101,media_profiles_V1_0.xml,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,)) +$(eval $(call declare-copy-files-license-metadata,device/google/gs101,media_codecs_performance.xml,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,)) +$(eval $(call declare-copy-files-license-metadata,device/google/gs101,device_state_configuration.xml,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,)) +$(eval $(call declare-copy-files-license-metadata,device/google/gs101,task_profiles.json,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,)) +$(eval $(call declare-copy-files-license-metadata,device/google/gs101,p2p_supplicant_overlay.conf,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,)) +$(eval $(call declare-copy-files-license-metadata,device/google/gs101,wpa_supplicant.conf,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,)) +$(eval $(call declare-copy-files-license-metadata,device/google/gs101,wpa_supplicant_overlay.conf,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,)) + +$(eval $(call declare-1p-copy-files,device/google/gs101,audio_policy_configuration.xml)) + +# Move here from device/google/raviole/Android.mk +$(eval $(call declare-copy-files-license-metadata,device/google/raviole,default-permissions.xml,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,)) +$(eval $(call declare-copy-files-license-metadata,device/google/raviole,libnfc-nci-raven.conf,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,)) +$(eval $(call declare-copy-files-license-metadata,device/google/raviole,libnfc-nci.conf,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,)) +$(eval $(call declare-copy-files-license-metadata,device/google/raviole,fstab.postinstall,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,)) +$(eval $(call declare-copy-files-license-metadata,device/google/raviole,ueventd.rc,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,)) +$(eval $(call declare-copy-files-license-metadata,device/google/raviole,wpa_supplicant.conf,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,)) +$(eval $(call declare-copy-files-license-metadata,device/google/raviole,hals.conf,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,)) +$(eval $(call declare-copy-files-license-metadata,device/google/raviole,media_profiles_V1_0.xml,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,)) +$(eval $(call declare-copy-files-license-metadata,device/google/raviole,media_codecs_performance.xml,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,)) +$(eval $(call declare-copy-files-license-metadata,device/google/raviole,device_state_configuration.xml,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,)) +$(eval $(call declare-copy-files-license-metadata,device/google/raviole,task_profiles.json,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,)) +$(eval $(call declare-copy-files-license-metadata,device/google/raviole,p2p_supplicant.conf,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,)) +$(eval $(call declare-copy-files-license-metadata,device/google/raviole,wpa_supplicant.conf,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,)) +$(eval $(call declare-copy-files-license-metadata,device/google/raviole,wpa_supplicant_overlay.conf,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,)) + +$(eval $(call declare-1p-copy-files,device/google/raviole,audio_policy_configuration.xml)) + +# Moved here from device/google/redfin/Android.mk +$(eval $(call declare-copy-files-license-metadata,device/google/redfin,default-permissions.xml,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,)) +$(eval $(call declare-copy-files-license-metadata,device/google/redfin,libnfc-nci.conf,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,)) +$(eval $(call declare-copy-files-license-metadata,device/google/redfin,fstab.postinstall,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,)) +$(eval $(call declare-copy-files-license-metadata,device/google/redfin,ueventd.rc,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,)) +$(eval $(call declare-copy-files-license-metadata,device/google/redfin,wpa_supplicant.conf,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,)) +$(eval $(call declare-copy-files-license-metadata,device/google/redfin,hals.conf,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,)) +$(eval $(call declare-copy-files-license-metadata,device/google/redfin,media_profiles_V1_0.xml,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,)) +$(eval $(call declare-copy-files-license-metadata,device/google/redfin,media_codecs_performance.xml,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,)) +$(eval $(call declare-copy-files-license-metadata,device/google/redfin,device_state_configuration.xml,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,)) +$(eval $(call declare-copy-files-license-metadata,device/google/redfin,task_profiles.json,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,)) +$(eval $(call declare-copy-files-license-metadata,device/google/redfin,p2p_supplicant.conf,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,)) +$(eval $(call declare-copy-files-license-metadata,device/google/redfin,wpa_supplicant.conf,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,)) +$(eval $(call declare-copy-files-license-metadata,device/google/redfin,wpa_supplicant_overlay.conf,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,)) + +$(eval $(call declare-1p-copy-files,device/google/redfin,audio_policy_configuration.xml)) + # Moved here from device/sample/Android.mk $(eval $(call declare-1p-copy-files,device/sample,)) +# Moved here from device/google/trout/Android.mk +$(eval $(call declare-1p-copy-files,device/google/trout,)) + # Moved here from frameworks/av/media/Android.mk $(eval $(call declare-1p-copy-files,frameworks/av/media/libeffects,audio_effects.conf)) $(eval $(call declare-1p-copy-files,frameworks/av/media/libeffects,audio_effects.xml)) diff --git a/core/tasks/sdk-addon.mk b/core/tasks/sdk-addon.mk index 7acac72f1d..2fd4ce9ec7 100644 --- a/core/tasks/sdk-addon.mk +++ b/core/tasks/sdk-addon.mk @@ -126,7 +126,7 @@ $(full_target_img): PRIVATE_STAGING_DIR := $(call append-path,$(staging),$(addon $(full_target_img): $(full_target) $(addon_img_source_prop) | $(SOONG_ZIP) @echo Packaging SDK Addon System-Image: $@ $(hide) mkdir -p $(dir $@) - cp -R $(PRODUCT_OUT)/data $(PRIVATE_STAGING_DIR)/data + cp -R $(PRODUCT_OUT)/data $(PRIVATE_STAGING_DIR) $(hide) $(SOONG_ZIP) -o $@ -C $(dir $(PRIVATE_STAGING_DIR)) -D $(PRIVATE_STAGING_DIR) diff --git a/envsetup.sh b/envsetup.sh index ab43ada1f6..50fec5146a 100644 --- a/envsetup.sh +++ b/envsetup.sh @@ -1112,8 +1112,8 @@ function run_tool_with_logging() { local tool_binary="$1" shift - # If logging is not enabled or the logger is not configured, run the original command and return. - if [[ "${ANDROID_ENABLE_TOOL_LOGGING}" != "true" ]] || [[ -z "${ANDROID_TOOL_LOGGER}" ]]; then + # If the logger is not configured, run the original command and return. + if [[ -z "${ANDROID_TOOL_LOGGER}" ]]; then "${tool_binary}" "${@}" return $? fi @@ -1134,8 +1134,9 @@ function run_tool_with_logging() { --tool_tag "${tool_tag}" \ --start_timestamp "${start_time}" \ --end_timestamp "$(date +%s.%N)" \ - --tool_args \""${@}"\" \ + --tool_args "$*" \ --exit_code "${exit_code}" \ + ${ANDROID_TOOL_LOGGER_EXTRA_ARGS} \ > /dev/null 2>&1 & exit ${exit_code} ' SIGINT SIGTERM SIGQUIT EXIT diff --git a/target/board/ndk/BoardConfig.mk b/target/board/ndk/BoardConfig.mk index b485f8b79e..d5399b226b 100644 --- a/target/board/ndk/BoardConfig.mk +++ b/target/board/ndk/BoardConfig.mk @@ -15,6 +15,6 @@ TARGET_ARCH_SUITE := ndk -MALLOC_SVELTE := true +MALLOC_LOW_MEMORY := true USE_SAFESTACK := false diff --git a/target/product/aosp_arm64.mk b/target/product/aosp_arm64.mk index d9446153c4..364fed4efc 100644 --- a/target/product/aosp_arm64.mk +++ b/target/product/aosp_arm64.mk @@ -55,7 +55,8 @@ $(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_product.mk) # All components inherited here go to vendor or vendor_boot image # $(call inherit-product, $(SRC_TARGET_DIR)/board/generic_arm64/device.mk) -$(call inherit-product, $(SRC_TARGET_DIR)/product/non_ab_device.mk) +AB_OTA_UPDATER := true +AB_OTA_PARTITIONS ?= system # # Special settings for GSI releasing diff --git a/target/product/aosp_x86_64.mk b/target/product/aosp_x86_64.mk index 4344f50cae..595940d9d1 100644 --- a/target/product/aosp_x86_64.mk +++ b/target/product/aosp_x86_64.mk @@ -57,7 +57,8 @@ $(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_product.mk) # All components inherited here go to vendor image # $(call inherit-product, $(SRC_TARGET_DIR)/board/generic_x86_64/device.mk) -$(call inherit-product, $(SRC_TARGET_DIR)/product/non_ab_device.mk) +AB_OTA_UPDATER := true +AB_OTA_PARTITIONS ?= system # # Special settings for GSI releasing diff --git a/target/product/base_system.mk b/target/product/base_system.mk index 57e8275270..22284b1c18 100644 --- a/target/product/base_system.mk +++ b/target/product/base_system.mk @@ -486,6 +486,11 @@ PRODUCT_COPY_FILES += $(call add-to-product-copy-files-if-exists,\ # Enable dirty image object binning to reduce dirty pages in the image. PRODUCT_PACKAGES += dirty-image-objects +# Enable go/perfetto-persistent-tracing for eng builds +ifneq (,$(filter eng, $(TARGET_BUILD_VARIANT))) + PRODUCT_PRODUCT_PROPERTIES += persist.debug.perfetto.persistent_sysui_tracing_for_bugreport=1 +endif + $(call inherit-product, $(SRC_TARGET_DIR)/product/runtime_libart.mk) # Ensure all trunk-stable flags are available. diff --git a/target/product/go_defaults.mk b/target/product/go_defaults.mk index b7174868ee..a10cfa858f 100644 --- a/target/product/go_defaults.mk +++ b/target/product/go_defaults.mk @@ -17,6 +17,8 @@ # Inherit common Android Go defaults. $(call inherit-product, build/make/target/product/go_defaults_common.mk) +PRODUCT_RELEASE_CONFIG_MAPS += $(wildcard vendor/google/release/go_devices/release_config_map.mk) + # Add the system properties. TARGET_SYSTEM_PROP += \ build/make/target/board/go_defaults.prop diff --git a/target/product/handheld_system.mk b/target/product/handheld_system.mk index bf9aa418f9..3c401f399b 100644 --- a/target/product/handheld_system.mk +++ b/target/product/handheld_system.mk @@ -82,8 +82,9 @@ PRODUCT_SYSTEM_SERVER_APPS += \ KeyChain \ Telecom \ +PRODUCT_PACKAGES += framework-audio_effects.xml + PRODUCT_COPY_FILES += \ - frameworks/av/media/libeffects/data/audio_effects.xml:system/etc/audio_effects.xml \ frameworks/native/data/etc/android.software.window_magnification.xml:$(TARGET_COPY_OUT_SYSTEM)/etc/permissions/android.software.window_magnification.xml \ PRODUCT_VENDOR_PROPERTIES += \ diff --git a/target/product/module_arm64.mk b/target/product/module_arm64.mk index 634a03dca1..d6487ca56b 100644 --- a/target/product/module_arm64.mk +++ b/target/product/module_arm64.mk @@ -21,3 +21,4 @@ PRODUCT_NAME := module_arm64 PRODUCT_DEVICE := module_arm64 PRODUCT_NO_BIONIC_PAGE_SIZE_MACRO := true +PRODUCT_MAX_PAGE_SIZE_SUPPORTED := 16384 diff --git a/target/product/module_arm64only.mk b/target/product/module_arm64only.mk index 822ac247c0..137701a441 100644 --- a/target/product/module_arm64only.mk +++ b/target/product/module_arm64only.mk @@ -21,3 +21,4 @@ PRODUCT_NAME := module_arm64only PRODUCT_DEVICE := module_arm64only PRODUCT_NO_BIONIC_PAGE_SIZE_MACRO := true +PRODUCT_MAX_PAGE_SIZE_SUPPORTED := 16384 diff --git a/target/product/module_common.mk b/target/product/module_common.mk index bf146a0d2f..da4ea23ad9 100644 --- a/target/product/module_common.mk +++ b/target/product/module_common.mk @@ -24,8 +24,9 @@ $(call inherit-product, $(SRC_TARGET_DIR)/product/memtag-common.mk) # uses -DENFORCE_VINTF_MANIFEST. See b/185759877 PRODUCT_SHIPPING_API_LEVEL := 29 -# Builds using a module product should build modules from source, even if -# BRANCH_DEFAULT_MODULE_BUILD_FROM_SOURCE says otherwise. +# If true, this builds the mainline modules from source. This overrides any +# prebuilts selected via RELEASE_APEX_CONTRIBUTIONS_* build flags for the +# current release config. PRODUCT_MODULE_BUILD_FROM_SOURCE := true # Build sdk from source if the branch is not using slim manifests. diff --git a/target/product/module_x86_64.mk b/target/product/module_x86_64.mk index 9bd0264f36..e182bf6578 100644 --- a/target/product/module_x86_64.mk +++ b/target/product/module_x86_64.mk @@ -21,3 +21,4 @@ PRODUCT_NAME := module_x86_64 PRODUCT_DEVICE := module_x86_64 PRODUCT_NO_BIONIC_PAGE_SIZE_MACRO := true +PRODUCT_MAX_PAGE_SIZE_SUPPORTED := 16384 diff --git a/target/product/module_x86_64only.mk b/target/product/module_x86_64only.mk index 056fb9097c..fa4a04d7e8 100644 --- a/target/product/module_x86_64only.mk +++ b/target/product/module_x86_64only.mk @@ -21,3 +21,4 @@ PRODUCT_NAME := module_x86_64only PRODUCT_DEVICE := module_x86_64only PRODUCT_NO_BIONIC_PAGE_SIZE_MACRO := true +PRODUCT_MAX_PAGE_SIZE_SUPPORTED := 16384 diff --git a/teams/Android.bp b/teams/Android.bp index a02a57392c..b3a5752749 100644 --- a/teams/Android.bp +++ b/teams/Android.bp @@ -4337,37 +4337,57 @@ team { } team { - name: "trendy_team_media_framework_drm", + name: "trendy_team_media_framework_drm", - // go/trendy/manage/engineers/5311752690335744 - trendy_team_id: "5311752690335744", + // go/trendy/manage/engineers/5311752690335744 + trendy_team_id: "5311752690335744", } team { - name: "trendy_team_media_framework_audio", + name: "trendy_team_media_framework_audio", - // go/trendy/manage/engineers/5823575353065472 - trendy_team_id: "5823575353065472", + // go/trendy/manage/engineers/5823575353065472 + trendy_team_id: "5823575353065472", } team { - name: "trendy_team_ar_sensors_context_hub", + name: "trendy_team_pixel_pearl", - // go/trendy/manage/engineers/4776371090259968 - trendy_team_id: "4776371090259968", + // go/trendy/manage/engineers/6326219602231296 + trendy_team_id: "6326219602231296", } +team { + name: "trendy_team_ar_sensors_context_hub", + + // go/trendy/manage/engineers/4776371090259968 + trendy_team_id: "4776371090259968", +} team { - name: "trendy_team_media_codec_framework", + name: "trendy_team_media_codec_framework", - // go/trendy/manage/engineers/4943966050844672 - trendy_team_id: "4943966050844672", + // go/trendy/manage/engineers/4943966050844672 + trendy_team_id: "4943966050844672", +} + +team { + name: "trendy_team_android_platform_performance_testing", + + // go/trendy/manage/engineers/5810097836621824 + trendy_team_id: "5810097836621824", +} + +team { + name: "trendy_team_adte", + + // go/trendy/manage/engineers/5551098528825344 + trendy_team_id: "5551098528825344", } team { - name: "trendy_team_android_platform_performance_testing", + name: "trendy_team_incremental", - // go/trendy/manage/engineers/5810097836621824 - trendy_team_id: "5810097836621824", + // go/trendy/manage/engineers/5955405559201792 + trendy_team_id: "5955405559201792", } diff --git a/tests/Android.bp b/tests/Android.bp index d3964e5aee..39debf5c6d 100644 --- a/tests/Android.bp +++ b/tests/Android.bp @@ -29,6 +29,7 @@ python_test_host { }, data: [ ":envsetup_minimum.zip", + ":tool_event_logger", ], test_suites: [ "general-tests", diff --git a/tests/run.rbc b/tests/run.rbc index 85d6c09bc5..221b40f04d 100644 --- a/tests/run.rbc +++ b/tests/run.rbc @@ -26,6 +26,7 @@ load(":product.rbc", "init") load(":board.rbc", board_init = "init") load(":board_input_vars.rbc", board_input_vars_init = "init") load("//build/make/tests/single_value_inheritance:test.rbc", test_single_value_inheritance = "test") +load("//build/make/tests/single_value_inheritance_2:test.rbc", test_single_value_inheritance_2 = "test") load("//build/make/tests/artifact_path_requirements:test.rbc", test_artifact_path_requirements = "test") load("//build/make/tests/prefixed_sort_order:test.rbc", test_prefixed_sort_order = "test") load("//build/make/tests/inherits_in_regular_variables:test.rbc", test_inherits_in_regular_variables = "test") @@ -181,6 +182,7 @@ assert_eq("f", cfg["BAZ"]) assert_eq("", g.get("NEWVAR")) test_single_value_inheritance() +test_single_value_inheritance_2() test_artifact_path_requirements() test_prefixed_sort_order() test_inherits_in_regular_variables() diff --git a/tests/run_tool_with_logging_test.py b/tests/run_tool_with_logging_test.py index 1eb78f14ba..18abd8e54f 100644 --- a/tests/run_tool_with_logging_test.py +++ b/tests/run_tool_with_logging_test.py @@ -13,20 +13,22 @@ # limitations under the License. import dataclasses +import glob from importlib import resources import logging import os from pathlib import Path import re +import shutil import signal import stat import subprocess +import sys import tempfile import textwrap import time import unittest import zipfile -import sys EXII_RETURN_CODE = 0 INTERRUPTED_RETURN_CODE = 130 @@ -40,7 +42,7 @@ class RunToolWithLoggingTest(unittest.TestCase): # Configure to print logging to stdout. logging.basicConfig(filename=None, level=logging.DEBUG) console = logging.StreamHandler(sys.stdout) - logging.getLogger('').addHandler(console) + logging.getLogger("").addHandler(console) def setUp(self): super().setUp() @@ -49,7 +51,7 @@ class RunToolWithLoggingTest(unittest.TestCase): os.chdir(self.working_dir.name) # Extract envsetup.zip which contains the envsetup.sh and other dependent # scripts required to set up the build environments. - with resources.files("testdata").joinpath("envsetup.zip").open('rb') as p: + with resources.files("testdata").joinpath("envsetup.zip").open("rb") as p: with zipfile.ZipFile(p, "r") as zip_f: zip_f.extractall() @@ -57,37 +59,10 @@ class RunToolWithLoggingTest(unittest.TestCase): self.working_dir.cleanup() super().tearDown() - def test_does_not_log_when_logging_disabled(self): - test_tool = TestScript.create(self.working_dir) - test_logger = TestScript.create(self.working_dir) - - self._run_script_and_wait(f""" - ANDROID_ENABLE_TOOL_LOGGING=false - ANDROID_TOOL_LOGGER="{test_logger.executable}" - run_tool_with_logging "FAKE_TOOL" {test_tool.executable} arg1 arg2 - """) - - test_tool.assert_called_once_with_args("arg1 arg2") - test_logger.assert_not_called() - - def test_does_not_log_when_logger_var_unset(self): - test_tool = TestScript.create(self.working_dir) - test_logger = TestScript.create(self.working_dir) - - self._run_script_and_wait(f""" - unset ANDROID_ENABLE_TOOL_LOGGING - ANDROID_TOOL_LOGGER="{test_logger.executable}" - run_tool_with_logging "FAKE_TOOL" {test_tool.executable} arg1 arg2 - """) - - test_tool.assert_called_once_with_args("arg1 arg2") - test_logger.assert_not_called() - def test_does_not_log_when_logger_var_empty(self): test_tool = TestScript.create(self.working_dir) self._run_script_and_wait(f""" - ANDROID_ENABLE_TOOL_LOGGING=true ANDROID_TOOL_LOGGER="" run_tool_with_logging "FAKE_TOOL" {test_tool.executable} arg1 arg2 """) @@ -98,7 +73,6 @@ class RunToolWithLoggingTest(unittest.TestCase): test_tool = TestScript.create(self.working_dir) self._run_script_and_wait(f""" - ANDROID_ENABLE_TOOL_LOGGING=true unset ANDROID_TOOL_LOGGER run_tool_with_logging "FAKE_TOOL" {test_tool.executable} arg1 arg2 """) @@ -110,7 +84,6 @@ class RunToolWithLoggingTest(unittest.TestCase): test_logger = TestScript.create(self.working_dir) self._run_script_and_wait(f""" - ANDROID_ENABLE_TOOL_LOGGING=true ANDROID_TOOL_LOGGER="{test_logger.executable}" run_tool_with_logging "FAKE_TOOL" {test_tool.executable} arg1 arg2 """) @@ -118,7 +91,7 @@ class RunToolWithLoggingTest(unittest.TestCase): test_tool.assert_called_once_with_args("arg1 arg2") expected_logger_args = ( "--tool_tag FAKE_TOOL --start_timestamp \d+\.\d+ --end_timestamp" - ' \d+\.\d+ --tool_args "arg1 arg2" --exit_code 0' + " \d+\.\d+ --tool_args arg1 arg2 --exit_code 0" ) test_logger.assert_called_once_with_args(expected_logger_args) @@ -128,7 +101,6 @@ class RunToolWithLoggingTest(unittest.TestCase): run_tool_with_logging_stdout, run_tool_with_logging_stderr = ( self._run_script_and_wait(f""" - ANDROID_ENABLE_TOOL_LOGGING=true ANDROID_TOOL_LOGGER="{test_logger.executable}" run_tool_with_logging "FAKE_TOOL" {test_tool.executable} arg1 arg2 """) @@ -136,7 +108,6 @@ class RunToolWithLoggingTest(unittest.TestCase): run_tool_without_logging_stdout, run_tool_without_logging_stderr = ( self._run_script_and_wait(f""" - ANDROID_ENABLE_TOOL_LOGGING=true ANDROID_TOOL_LOGGER="{test_logger.executable}" {test_tool.executable} arg1 arg2 """) @@ -154,7 +125,6 @@ class RunToolWithLoggingTest(unittest.TestCase): test_logger = TestScript.create(self.working_dir, "echo 'logger called'") run_tool_with_logging_output, _ = self._run_script_and_wait(f""" - ANDROID_ENABLE_TOOL_LOGGING=true ANDROID_TOOL_LOGGER="{test_logger.executable}" run_tool_with_logging "FAKE_TOOL" {test_tool.executable} arg1 arg2 """) @@ -168,7 +138,6 @@ class RunToolWithLoggingTest(unittest.TestCase): ) _, err = self._run_script_and_wait(f""" - ANDROID_ENABLE_TOOL_LOGGING=true ANDROID_TOOL_LOGGER="{test_logger.executable}" run_tool_with_logging "FAKE_TOOL" {test_tool.executable} arg1 arg2 """) @@ -180,7 +149,6 @@ class RunToolWithLoggingTest(unittest.TestCase): test_logger = TestScript.create(self.working_dir) process = self._run_script_in_build_env(f""" - ANDROID_ENABLE_TOOL_LOGGING=true ANDROID_TOOL_LOGGER="{test_logger.executable}" run_tool_with_logging "FAKE_TOOL" {test_tool.executable} arg1 arg2 """) @@ -196,7 +164,7 @@ class RunToolWithLoggingTest(unittest.TestCase): expected_logger_args = ( "--tool_tag FAKE_TOOL --start_timestamp \d+\.\d+ --end_timestamp" - ' \d+\.\d+ --tool_args "arg1 arg2" --exit_code 130' + " \d+\.\d+ --tool_args arg1 arg2 --exit_code 130" ) test_logger.assert_called_once_with_args(expected_logger_args) @@ -205,9 +173,8 @@ class RunToolWithLoggingTest(unittest.TestCase): test_logger = TestScript.create(self.working_dir) self._run_script_and_wait(f""" - ANDROID_ENABLE_TOOL_LOGGING=false + ANDROID_TOOL_LOGGER="" ANDROID_TOOL_LOGGER="{test_logger.executable}" - ANDROID_ENABLE_TOOL_LOGGING=true run_tool_with_logging "FAKE_TOOL" {test_tool.executable} arg1 arg2 """) @@ -218,14 +185,43 @@ class RunToolWithLoggingTest(unittest.TestCase): test_logger = TestScript.create(self.working_dir) self._run_script_and_wait(f""" - ANDROID_ENABLE_TOOL_LOGGING=true ANDROID_TOOL_LOGGER="{test_logger.executable}" - ANDROID_ENABLE_TOOL_LOGGING=false + ANDROID_TOOL_LOGGER="" run_tool_with_logging "FAKE_TOOL" {test_tool.executable} arg1 arg2 """) test_logger.assert_not_called() + def test_integration_tool_event_logger_dry_run(self): + test_tool = TestScript.create(self.working_dir) + logger_path = self._import_logger() + + self._run_script_and_wait(f""" + TMPDIR="{self.working_dir.name}" + ANDROID_TOOL_LOGGER="{logger_path}" + ANDROID_TOOL_LOGGER_EXTRA_ARGS="--dry_run" + run_tool_with_logging "FAKE_TOOL" {test_tool.executable} arg1 arg2 + """) + + self._assert_logger_dry_run() + + def _import_logger(self) -> Path: + logger = "tool_event_logger" + logger_path = Path(self.working_dir.name).joinpath(logger) + with resources.as_file(resources.files("testdata").joinpath(logger)) as p: + shutil.copy(p, logger_path) + Path.chmod(logger_path, 0o755) + return logger_path + + def _assert_logger_dry_run(self): + log_files = glob.glob(self.working_dir.name + "/tool_event_logger_*/*.log") + self.assertEqual(len(log_files), 1) + + with open(log_files[0], "r") as f: + lines = f.readlines() + self.assertEqual(len(lines), 1) + self.assertIn("dry run", lines[0]) + def _create_build_env_script(self) -> str: return f""" source {Path(self.working_dir.name).joinpath("build/make/envsetup.sh")} @@ -248,7 +244,7 @@ class RunToolWithLoggingTest(unittest.TestCase): stderr=subprocess.PIPE, text=True, start_new_session=True, - executable='/bin/bash' + executable="/bin/bash", ) def _wait_for_process( @@ -301,7 +297,7 @@ class TestScript: """) f.write(executable_contents.encode("utf-8")) - os.chmod(f.name, os.stat(f.name).st_mode | stat.S_IEXEC) + Path.chmod(f.name, os.stat(f.name).st_mode | stat.S_IEXEC) return TestScript(executable, output_file) diff --git a/tests/single_value_inheritance_2/a.rbc b/tests/single_value_inheritance_2/a.rbc new file mode 100644 index 0000000000..fe186c7e84 --- /dev/null +++ b/tests/single_value_inheritance_2/a.rbc @@ -0,0 +1,20 @@ +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +load("//build/make/core:product_config.rbc", "rblf") + +def init(g, handle): + cfg = rblf.cfg(handle) + + cfg["PRODUCT_ENABLE_UFFD_GC"] = "true" diff --git a/tests/single_value_inheritance_2/b.rbc b/tests/single_value_inheritance_2/b.rbc new file mode 100644 index 0000000000..7d95749aa4 --- /dev/null +++ b/tests/single_value_inheritance_2/b.rbc @@ -0,0 +1,20 @@ +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +load("//build/make/core:product_config.rbc", "rblf") + +def init(g, handle): + cfg = rblf.cfg(handle) + + cfg["PRODUCT_ENABLE_UFFD_GC"] = "default" diff --git a/tests/single_value_inheritance_2/c.rbc b/tests/single_value_inheritance_2/c.rbc new file mode 100644 index 0000000000..e90e37d318 --- /dev/null +++ b/tests/single_value_inheritance_2/c.rbc @@ -0,0 +1,21 @@ +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +load("//build/make/core:product_config.rbc", "rblf") +load(":b.rbc", _b_init = "init") + +def init(g, handle): + cfg = rblf.cfg(handle) + + rblf.inherit(handle, "test/b", _b_init) diff --git a/tests/single_value_inheritance_2/d.rbc b/tests/single_value_inheritance_2/d.rbc new file mode 100644 index 0000000000..3a88c2c17f --- /dev/null +++ b/tests/single_value_inheritance_2/d.rbc @@ -0,0 +1,23 @@ +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +load("//build/make/core:product_config.rbc", "rblf") +load(":c.rbc", _c_init = "init") +load(":a.rbc", _a_init = "init") + +def init(g, handle): + cfg = rblf.cfg(handle) + + rblf.inherit(handle, "test/a", _a_init) + rblf.inherit(handle, "test/c", _c_init) diff --git a/tests/single_value_inheritance_2/product.rbc b/tests/single_value_inheritance_2/product.rbc new file mode 100644 index 0000000000..c47664db16 --- /dev/null +++ b/tests/single_value_inheritance_2/product.rbc @@ -0,0 +1,23 @@ +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +load("//build/make/core:product_config.rbc", "rblf") +load(":b.rbc", _b_init = "init") +load(":d.rbc", _d_init = "init") + +def init(g, handle): + cfg = rblf.cfg(handle) + + rblf.inherit(handle, "test/b", _b_init) + rblf.inherit(handle, "test/d", _d_init) diff --git a/tests/single_value_inheritance_2/test.rbc b/tests/single_value_inheritance_2/test.rbc new file mode 100644 index 0000000000..fa93aaa51e --- /dev/null +++ b/tests/single_value_inheritance_2/test.rbc @@ -0,0 +1,40 @@ +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +load("//build/make/core:product_config.rbc", "rblf") +load("//build/make/tests/input_variables.rbc", input_variables_init = "init") +load(":product.rbc", "init") + + +def assert_eq(expected, actual): + if expected != actual: + fail("Expected '%s', got '%s'" % (expected, actual)) + +# This test is testing that single value variables are "stolen" when processing the inheritance +# graph. i.e. if you have a graph like this: +# +# B A +# |\ | +# | C | +# \ \| +# \ D +# \| +# E +# +# The same variable is defined in both A and B. In D, the value from A is chosen because it comes +# alphabetically before C. But then in E, the value from D is chosen instead of the value from B, +# because the value of B was "stolen" and sucked into C, leaving B with no value set. +def test(): + (globals, globals_base) = rblf.product_configuration("test/device", init, input_variables_init) + assert_eq("true", globals["PRODUCTS.test/device.mk.PRODUCT_ENABLE_UFFD_GC"]) diff --git a/tools/Android.bp b/tools/Android.bp index 0a55ed4b85..59831a61ec 100644 --- a/tools/Android.bp +++ b/tools/Android.bp @@ -115,3 +115,11 @@ python_binary_host { }, }, } + +python_binary_host { + name: "merge-event-log-tags", + srcs: [ + "event_log_tags.py", + "merge-event-log-tags.py", + ], +} diff --git a/tools/aconfig/TEST_MAPPING b/tools/aconfig/TEST_MAPPING index b7ff8eff17..421e94a8a6 100644 --- a/tools/aconfig/TEST_MAPPING +++ b/tools/aconfig/TEST_MAPPING @@ -97,5 +97,9 @@ } ], "postsubmit": [ + { + // aconfig_storage file cpp integration tests + "name": "aconfig_storage_file.test.cpp" + } ] } diff --git a/tools/aconfig/aconfig/Android.bp b/tools/aconfig/aconfig/Android.bp index 00a6feedc0..68521af91f 100644 --- a/tools/aconfig/aconfig/Android.bp +++ b/tools/aconfig/aconfig/Android.bp @@ -161,6 +161,9 @@ cc_test { shared_libs: [ "server_configurable_flags", ], + defaults: [ + "aconfig_lib_cc_static_link.defaults", + ], test_suites: ["general-tests"], } @@ -176,6 +179,9 @@ cc_test { shared_libs: [ "server_configurable_flags", ], + defaults: [ + "aconfig_lib_cc_static_link.defaults", + ], test_suites: ["general-tests"], } @@ -199,6 +205,9 @@ cc_test { shared_libs: [ "server_configurable_flags", ], + defaults: [ + "aconfig_lib_cc_static_link.defaults", + ], test_suites: ["general-tests"], } */ @@ -215,6 +224,9 @@ cc_test { shared_libs: [ "server_configurable_flags", ], + defaults: [ + "aconfig_lib_cc_static_link.defaults", + ], test_suites: ["general-tests"], } diff --git a/tools/aconfig/aconfig/src/codegen/cpp.rs b/tools/aconfig/aconfig/src/codegen/cpp.rs index cd71b10d52..e743b2fc59 100644 --- a/tools/aconfig/aconfig/src/codegen/cpp.rs +++ b/tools/aconfig/aconfig/src/codegen/cpp.rs @@ -16,6 +16,7 @@ use anyhow::{ensure, Result}; use serde::Serialize; +use std::collections::HashMap; use std::path::PathBuf; use tinytemplate::TinyTemplate; @@ -29,13 +30,15 @@ pub fn generate_cpp_code<I>( package: &str, parsed_flags_iter: I, codegen_mode: CodegenMode, + flag_ids: HashMap<String, u16>, + allow_instrumentation: bool, ) -> Result<Vec<OutputFile>> where I: Iterator<Item = ProtoParsedFlag>, { let mut readwrite_count = 0; let class_elements: Vec<ClassElement> = parsed_flags_iter - .map(|pf| create_class_element(package, &pf, &mut readwrite_count)) + .map(|pf| create_class_element(package, &pf, flag_ids.clone(), &mut readwrite_count)) .collect(); let readwrite = readwrite_count > 0; let has_fixed_read_only = class_elements.iter().any(|item| item.is_fixed_read_only); @@ -53,6 +56,7 @@ where readwrite_count, is_test_mode: codegen_mode == CodegenMode::Test, class_elements, + allow_instrumentation, }; let files = [ @@ -96,6 +100,7 @@ pub struct Context<'a> { pub readwrite_count: i32, pub is_test_mode: bool, pub class_elements: Vec<ClassElement>, + pub allow_instrumentation: bool, } #[derive(Serialize)] @@ -106,11 +111,18 @@ pub struct ClassElement { pub default_value: String, pub flag_name: String, pub flag_macro: String, + pub flag_offset: u16, pub device_config_namespace: String, pub device_config_flag: String, + pub container: String, } -fn create_class_element(package: &str, pf: &ProtoParsedFlag, rw_count: &mut i32) -> ClassElement { +fn create_class_element( + package: &str, + pf: &ProtoParsedFlag, + flag_ids: HashMap<String, u16>, + rw_count: &mut i32, +) -> ClassElement { ClassElement { readwrite_idx: if pf.permission() == ProtoFlagPermission::READ_WRITE { let index = *rw_count; @@ -128,9 +140,11 @@ fn create_class_element(package: &str, pf: &ProtoParsedFlag, rw_count: &mut i32) }, flag_name: pf.name().to_string(), flag_macro: pf.name().to_uppercase(), + flag_offset: *flag_ids.get(pf.name()).expect("values checked at flag parse time"), 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"), + container: pf.container().to_string(), } } @@ -1162,18 +1176,27 @@ bool com_android_aconfig_test_enabled_ro() { return true; } "#; + use crate::commands::assign_flag_ids; fn test_generate_cpp_code( parsed_flags: ProtoParsedFlags, mode: CodegenMode, expected_header: &str, expected_src: &str, + allow_instrumentation: bool, ) { let modified_parsed_flags = crate::commands::modify_parsed_flags_based_on_mode(parsed_flags, mode).unwrap(); - let generated = - generate_cpp_code(crate::test::TEST_PACKAGE, modified_parsed_flags.into_iter(), mode) - .unwrap(); + let flag_ids = + assign_flag_ids(crate::test::TEST_PACKAGE, modified_parsed_flags.iter()).unwrap(); + let generated = generate_cpp_code( + crate::test::TEST_PACKAGE, + modified_parsed_flags.into_iter(), + mode, + flag_ids, + allow_instrumentation, + ) + .unwrap(); let mut generated_files_map = HashMap::new(); for file in generated { generated_files_map.insert( @@ -1211,6 +1234,7 @@ bool com_android_aconfig_test_enabled_ro() { CodegenMode::Production, EXPORTED_PROD_HEADER_EXPECTED, PROD_SOURCE_FILE_EXPECTED, + false, ); } @@ -1222,6 +1246,7 @@ bool com_android_aconfig_test_enabled_ro() { CodegenMode::Test, EXPORTED_TEST_HEADER_EXPECTED, TEST_SOURCE_FILE_EXPECTED, + false, ); } @@ -1233,6 +1258,7 @@ bool com_android_aconfig_test_enabled_ro() { CodegenMode::Exported, EXPORTED_EXPORTED_HEADER_EXPECTED, EXPORTED_SOURCE_FILE_EXPECTED, + false, ); } @@ -1244,6 +1270,7 @@ bool com_android_aconfig_test_enabled_ro() { CodegenMode::ForceReadOnly, EXPORTED_FORCE_READ_ONLY_HEADER_EXPECTED, FORCE_READ_ONLY_SOURCE_FILE_EXPECTED, + false, ); } @@ -1255,6 +1282,7 @@ bool com_android_aconfig_test_enabled_ro() { CodegenMode::Production, READ_ONLY_EXPORTED_PROD_HEADER_EXPECTED, READ_ONLY_PROD_SOURCE_FILE_EXPECTED, + false, ); } } diff --git a/tools/aconfig/aconfig/src/codegen/java.rs b/tools/aconfig/aconfig/src/codegen/java.rs index 18a4be5094..3360ddd68b 100644 --- a/tools/aconfig/aconfig/src/codegen/java.rs +++ b/tools/aconfig/aconfig/src/codegen/java.rs @@ -64,20 +64,27 @@ where include_str!("../../templates/FeatureFlags.java.template"), )?; template.add_template( + "CustomFeatureFlags.java", + include_str!("../../templates/CustomFeatureFlags.java.template"), + )?; + template.add_template( "FakeFeatureFlagsImpl.java", include_str!("../../templates/FakeFeatureFlagsImpl.java.template"), )?; let path: PathBuf = package.split('.').collect(); - ["Flags.java", "FeatureFlags.java", "FeatureFlagsImpl.java", "FakeFeatureFlagsImpl.java"] - .iter() - .map(|file| { - Ok(OutputFile { - contents: template.render(file, &context)?.into(), - path: path.join(file), - }) - }) - .collect::<Result<Vec<OutputFile>>>() + [ + "Flags.java", + "FeatureFlags.java", + "FeatureFlagsImpl.java", + "CustomFeatureFlags.java", + "FakeFeatureFlagsImpl.java", + ] + .iter() + .map(|file| { + Ok(OutputFile { contents: template.render(file, &context)?.into(), path: path.join(file) }) + }) + .collect::<Result<Vec<OutputFile>>>() } fn gen_flags_by_namespace(flags: &[FlagElement]) -> Vec<NamespaceFlags> { @@ -292,76 +299,82 @@ mod tests { } "#; - const EXPECTED_FAKEFEATUREFLAGSIMPL_CONTENT: &str = r#" + const EXPECTED_CUSTOMFEATUREFLAGS_CONTENT: &str = r#" package com.android.aconfig.test; + // TODO(b/303773055): Remove the annotation after access issue is resolved. import android.compat.annotation.UnsupportedAppUsage; import java.util.Arrays; - import java.util.HashMap; import java.util.HashSet; - import java.util.Map; + import java.util.List; import java.util.Set; + import java.util.function.BiPredicate; + import java.util.function.Predicate; + /** @hide */ - public class FakeFeatureFlagsImpl implements FeatureFlags { - public FakeFeatureFlagsImpl() { - resetAll(); + public class CustomFeatureFlags implements FeatureFlags { + + private BiPredicate<String, Predicate<FeatureFlags>> mGetValueImpl; + + public CustomFeatureFlags(BiPredicate<String, Predicate<FeatureFlags>> getValueImpl) { + mGetValueImpl = getValueImpl; } + @Override @UnsupportedAppUsage public boolean disabledRo() { - return getValue(Flags.FLAG_DISABLED_RO); + return getValue(Flags.FLAG_DISABLED_RO, + FeatureFlags::disabledRo); } @Override @UnsupportedAppUsage public boolean disabledRw() { - return getValue(Flags.FLAG_DISABLED_RW); + return getValue(Flags.FLAG_DISABLED_RW, + FeatureFlags::disabledRw); } @Override @UnsupportedAppUsage public boolean disabledRwExported() { - return getValue(Flags.FLAG_DISABLED_RW_EXPORTED); + return getValue(Flags.FLAG_DISABLED_RW_EXPORTED, + FeatureFlags::disabledRwExported); } @Override @UnsupportedAppUsage public boolean disabledRwInOtherNamespace() { - return getValue(Flags.FLAG_DISABLED_RW_IN_OTHER_NAMESPACE); + return getValue(Flags.FLAG_DISABLED_RW_IN_OTHER_NAMESPACE, + FeatureFlags::disabledRwInOtherNamespace); } @Override @UnsupportedAppUsage public boolean enabledFixedRo() { - return getValue(Flags.FLAG_ENABLED_FIXED_RO); + return getValue(Flags.FLAG_ENABLED_FIXED_RO, + FeatureFlags::enabledFixedRo); } @Override @UnsupportedAppUsage public boolean enabledFixedRoExported() { - return getValue(Flags.FLAG_ENABLED_FIXED_RO_EXPORTED); + return getValue(Flags.FLAG_ENABLED_FIXED_RO_EXPORTED, + FeatureFlags::enabledFixedRoExported); } @Override @UnsupportedAppUsage public boolean enabledRo() { - return getValue(Flags.FLAG_ENABLED_RO); + return getValue(Flags.FLAG_ENABLED_RO, + FeatureFlags::enabledRo); } @Override @UnsupportedAppUsage public boolean enabledRoExported() { - return getValue(Flags.FLAG_ENABLED_RO_EXPORTED); + return getValue(Flags.FLAG_ENABLED_RO_EXPORTED, + FeatureFlags::enabledRoExported); } @Override @UnsupportedAppUsage public boolean enabledRw() { - return getValue(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); - } + return getValue(Flags.FLAG_ENABLED_RW, + FeatureFlags::enabledRw); } + public boolean isFlagReadOnlyOptimized(String flagName) { if (mReadOnlyFlagsSet.contains(flagName) && isOptimizationEnabled()) { @@ -369,30 +382,30 @@ mod tests { } return false; } + @com.android.aconfig.annotations.AssumeTrueForR8 private boolean isOptimizationEnabled() { return false; } - private boolean getValue(String flagName) { - Boolean value = this.mFlagMap.get(flagName); - if (value == null) { - throw new IllegalArgumentException(flagName + " is not set"); - } - return value; + + protected boolean getValue(String flagName, Predicate<FeatureFlags> getter) { + return mGetValueImpl.test(flagName, getter); } - private Map<String, Boolean> mFlagMap = new HashMap<>( - Map.ofEntries( - Map.entry(Flags.FLAG_DISABLED_RO, false), - Map.entry(Flags.FLAG_DISABLED_RW, false), - Map.entry(Flags.FLAG_DISABLED_RW_EXPORTED, false), - Map.entry(Flags.FLAG_DISABLED_RW_IN_OTHER_NAMESPACE, false), - Map.entry(Flags.FLAG_ENABLED_FIXED_RO, false), - Map.entry(Flags.FLAG_ENABLED_FIXED_RO_EXPORTED, false), - Map.entry(Flags.FLAG_ENABLED_RO, false), - Map.entry(Flags.FLAG_ENABLED_RO_EXPORTED, false), - Map.entry(Flags.FLAG_ENABLED_RW, false) - ) - ); + + public List<String> getFlagNames() { + return Arrays.asList( + Flags.FLAG_DISABLED_RO, + Flags.FLAG_DISABLED_RW, + Flags.FLAG_DISABLED_RW_EXPORTED, + Flags.FLAG_DISABLED_RW_IN_OTHER_NAMESPACE, + Flags.FLAG_ENABLED_FIXED_RO, + Flags.FLAG_ENABLED_FIXED_RO_EXPORTED, + Flags.FLAG_ENABLED_RO, + Flags.FLAG_ENABLED_RO_EXPORTED, + Flags.FLAG_ENABLED_RW + ); + } + private Set<String> mReadOnlyFlagsSet = new HashSet<>( Arrays.asList( Flags.FLAG_DISABLED_RO, @@ -406,6 +419,58 @@ mod tests { } "#; + const EXPECTED_FAKEFEATUREFLAGSIMPL_CONTENT: &str = r#" + package com.android.aconfig.test; + + import java.util.HashMap; + import java.util.Map; + import java.util.function.Predicate; + + /** @hide */ + public class FakeFeatureFlagsImpl extends CustomFeatureFlags { + private final Map<String, Boolean> mFlagMap = new HashMap<>(); + private final FeatureFlags mDefaults; + + public FakeFeatureFlagsImpl() { + this(null); + } + + public FakeFeatureFlagsImpl(FeatureFlags defaults) { + super(null); + mDefaults = defaults; + // Initialize the map with null values + for (String flagName : getFlagNames()) { + mFlagMap.put(flagName, null); + } + } + + @Override + protected boolean getValue(String flagName, Predicate<FeatureFlags> getter) { + Boolean value = this.mFlagMap.get(flagName); + if (value != null) { + return value; + } + if (mDefaults != null) { + return getter.test(mDefaults); + } + throw new IllegalArgumentException(flagName + " is not set"); + } + + 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); + } + } + } + "#; + #[test] fn test_generate_java_code_production() { let parsed_flags = crate::test::parse_test_flags(); @@ -549,6 +614,10 @@ mod tests { ("com/android/aconfig/test/FeatureFlagsImpl.java", expect_featureflagsimpl_content), ("com/android/aconfig/test/FeatureFlags.java", EXPECTED_FEATUREFLAGS_COMMON_CONTENT), ( + "com/android/aconfig/test/CustomFeatureFlags.java", + EXPECTED_CUSTOMFEATUREFLAGS_CONTENT, + ), + ( "com/android/aconfig/test/FakeFeatureFlagsImpl.java", EXPECTED_FAKEFEATUREFLAGSIMPL_CONTENT, ), @@ -671,55 +740,53 @@ mod tests { } }"#; - let expect_fake_feature_flags_impl_content = r#" + let expect_custom_feature_flags_content = r#" package com.android.aconfig.test; + import java.util.Arrays; - import java.util.HashMap; import java.util.HashSet; - import java.util.Map; + import java.util.List; import java.util.Set; + import java.util.function.BiPredicate; + import java.util.function.Predicate; + /** @hide */ - public class FakeFeatureFlagsImpl implements FeatureFlags { - public FakeFeatureFlagsImpl() { - resetAll(); + public class CustomFeatureFlags implements FeatureFlags { + + private BiPredicate<String, Predicate<FeatureFlags>> mGetValueImpl; + + public CustomFeatureFlags(BiPredicate<String, Predicate<FeatureFlags>> getValueImpl) { + mGetValueImpl = getValueImpl; } + @Override public boolean disabledRwExported() { - return getValue(Flags.FLAG_DISABLED_RW_EXPORTED); + return getValue(Flags.FLAG_DISABLED_RW_EXPORTED, + FeatureFlags::disabledRwExported); } @Override public boolean enabledFixedRoExported() { - return getValue(Flags.FLAG_ENABLED_FIXED_RO_EXPORTED); + return getValue(Flags.FLAG_ENABLED_FIXED_RO_EXPORTED, + FeatureFlags::enabledFixedRoExported); } @Override public boolean enabledRoExported() { - return getValue(Flags.FLAG_ENABLED_RO_EXPORTED); + return getValue(Flags.FLAG_ENABLED_RO_EXPORTED, + FeatureFlags::enabledRoExported); } - 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); - } + + protected boolean getValue(String flagName, Predicate<FeatureFlags> getter) { + return mGetValueImpl.test(flagName, getter); } - private boolean getValue(String flagName) { - Boolean value = this.mFlagMap.get(flagName); - if (value == null) { - throw new IllegalArgumentException(flagName + " is not set"); - } - return value; + + public List<String> getFlagNames() { + return Arrays.asList( + Flags.FLAG_DISABLED_RW_EXPORTED, + Flags.FLAG_ENABLED_FIXED_RO_EXPORTED, + Flags.FLAG_ENABLED_RO_EXPORTED + ); } - private Map<String, Boolean> mFlagMap = new HashMap<>( - Map.ofEntries( - Map.entry(Flags.FLAG_DISABLED_RW_EXPORTED, false), - Map.entry(Flags.FLAG_ENABLED_FIXED_RO_EXPORTED, false), - Map.entry(Flags.FLAG_ENABLED_RO_EXPORTED, false) - ) - ); + private Set<String> mReadOnlyFlagsSet = new HashSet<>( Arrays.asList( "" @@ -733,8 +800,12 @@ mod tests { ("com/android/aconfig/test/FeatureFlags.java", expect_feature_flags_content), ("com/android/aconfig/test/FeatureFlagsImpl.java", expect_feature_flags_impl_content), ( + "com/android/aconfig/test/CustomFeatureFlags.java", + expect_custom_feature_flags_content, + ), + ( "com/android/aconfig/test/FakeFeatureFlagsImpl.java", - expect_fake_feature_flags_impl_content, + EXPECTED_FAKEFEATUREFLAGSIMPL_CONTENT, ), ]); @@ -854,6 +925,10 @@ mod tests { ("com/android/aconfig/test/FeatureFlags.java", EXPECTED_FEATUREFLAGS_COMMON_CONTENT), ("com/android/aconfig/test/FeatureFlagsImpl.java", expect_featureflagsimpl_content), ( + "com/android/aconfig/test/CustomFeatureFlags.java", + EXPECTED_CUSTOMFEATUREFLAGS_CONTENT, + ), + ( "com/android/aconfig/test/FakeFeatureFlagsImpl.java", EXPECTED_FAKEFEATUREFLAGSIMPL_CONTENT, ), @@ -1020,61 +1095,64 @@ mod tests { private static FeatureFlags FEATURE_FLAGS = new FeatureFlagsImpl(); }"#; - let expect_fakefeatureflags_content = r#" + let expect_customfeatureflags_content = r#" package com.android.aconfig.test; + // TODO(b/303773055): Remove the annotation after access issue is resolved. import android.compat.annotation.UnsupportedAppUsage; import java.util.Arrays; - import java.util.HashMap; import java.util.HashSet; - import java.util.Map; + import java.util.List; import java.util.Set; + import java.util.function.BiPredicate; + import java.util.function.Predicate; + /** @hide */ - public class FakeFeatureFlagsImpl implements FeatureFlags { - public FakeFeatureFlagsImpl() { - resetAll(); + public class CustomFeatureFlags implements FeatureFlags { + + private BiPredicate<String, Predicate<FeatureFlags>> mGetValueImpl; + + public CustomFeatureFlags(BiPredicate<String, Predicate<FeatureFlags>> getValueImpl) { + mGetValueImpl = getValueImpl; } + @Override @UnsupportedAppUsage public boolean disabledRo() { - return getValue(Flags.FLAG_DISABLED_RO); + return getValue(Flags.FLAG_DISABLED_RO, + FeatureFlags::disabledRo); } @Override @UnsupportedAppUsage public boolean disabledRw() { - return getValue(Flags.FLAG_DISABLED_RW); + return getValue(Flags.FLAG_DISABLED_RW, + FeatureFlags::disabledRw); } @Override @UnsupportedAppUsage public boolean disabledRwInOtherNamespace() { - return getValue(Flags.FLAG_DISABLED_RW_IN_OTHER_NAMESPACE); + return getValue(Flags.FLAG_DISABLED_RW_IN_OTHER_NAMESPACE, + FeatureFlags::disabledRwInOtherNamespace); } @Override @UnsupportedAppUsage public boolean enabledFixedRo() { - return getValue(Flags.FLAG_ENABLED_FIXED_RO); + return getValue(Flags.FLAG_ENABLED_FIXED_RO, + FeatureFlags::enabledFixedRo); } @Override @UnsupportedAppUsage public boolean enabledRo() { - return getValue(Flags.FLAG_ENABLED_RO); + return getValue(Flags.FLAG_ENABLED_RO, + FeatureFlags::enabledRo); } @Override @UnsupportedAppUsage public boolean enabledRw() { - return getValue(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); - } + return getValue(Flags.FLAG_ENABLED_RW, + FeatureFlags::enabledRw); } + public boolean isFlagReadOnlyOptimized(String flagName) { if (mReadOnlyFlagsSet.contains(flagName) && isOptimizationEnabled()) { @@ -1082,27 +1160,27 @@ mod tests { } return false; } + @com.android.aconfig.annotations.AssumeTrueForR8 private boolean isOptimizationEnabled() { return false; } - private boolean getValue(String flagName) { - Boolean value = this.mFlagMap.get(flagName); - if (value == null) { - throw new IllegalArgumentException(flagName + " is not set"); - } - return value; + + protected boolean getValue(String flagName, Predicate<FeatureFlags> getter) { + return mGetValueImpl.test(flagName, getter); } - private Map<String, Boolean> mFlagMap = new HashMap<>( - Map.ofEntries( - Map.entry(Flags.FLAG_DISABLED_RO, false), - Map.entry(Flags.FLAG_DISABLED_RW, false), - Map.entry(Flags.FLAG_DISABLED_RW_IN_OTHER_NAMESPACE, false), - Map.entry(Flags.FLAG_ENABLED_FIXED_RO, false), - Map.entry(Flags.FLAG_ENABLED_RO, false), - Map.entry(Flags.FLAG_ENABLED_RW, false) - ) - ); + + public List<String> getFlagNames() { + return Arrays.asList( + Flags.FLAG_DISABLED_RO, + Flags.FLAG_DISABLED_RW, + Flags.FLAG_DISABLED_RW_IN_OTHER_NAMESPACE, + Flags.FLAG_ENABLED_FIXED_RO, + Flags.FLAG_ENABLED_RO, + Flags.FLAG_ENABLED_RW + ); + } + private Set<String> mReadOnlyFlagsSet = new HashSet<>( Arrays.asList( Flags.FLAG_DISABLED_RO, @@ -1116,11 +1194,16 @@ mod tests { ); } "#; + let mut file_set = HashMap::from([ ("com/android/aconfig/test/Flags.java", expect_flags_content), ("com/android/aconfig/test/FeatureFlagsImpl.java", expect_featureflagsimpl_content), ("com/android/aconfig/test/FeatureFlags.java", expect_featureflags_content), - ("com/android/aconfig/test/FakeFeatureFlagsImpl.java", expect_fakefeatureflags_content), + ("com/android/aconfig/test/CustomFeatureFlags.java", expect_customfeatureflags_content), + ( + "com/android/aconfig/test/FakeFeatureFlagsImpl.java", + EXPECTED_FAKEFEATUREFLAGSIMPL_CONTENT, + ), ]); for file in generated_files { diff --git a/tools/aconfig/aconfig/src/commands.rs b/tools/aconfig/aconfig/src/commands.rs index ad96bb88a5..6945fd4649 100644 --- a/tools/aconfig/aconfig/src/commands.rs +++ b/tools/aconfig/aconfig/src/commands.rs @@ -202,7 +202,11 @@ pub fn create_java_lib(mut input: Input, codegen_mode: CodegenMode) -> Result<Ve generate_java_code(&package, modified_parsed_flags.into_iter(), codegen_mode) } -pub fn create_cpp_lib(mut input: Input, codegen_mode: CodegenMode) -> Result<Vec<OutputFile>> { +pub fn create_cpp_lib( + mut input: Input, + codegen_mode: CodegenMode, + allow_instrumentation: bool, +) -> Result<Vec<OutputFile>> { // TODO(327420679): Enable export mode for native flag library ensure!( codegen_mode != CodegenMode::Exported, @@ -214,8 +218,14 @@ pub fn create_cpp_lib(mut input: Input, codegen_mode: CodegenMode) -> Result<Vec bail!("no parsed flags, or the parsed flags use different packages"); }; let package = package.to_string(); - let _flag_ids = assign_flag_ids(&package, modified_parsed_flags.iter())?; - generate_cpp_code(&package, modified_parsed_flags.into_iter(), codegen_mode) + let flag_ids = assign_flag_ids(&package, modified_parsed_flags.iter())?; + generate_cpp_code( + &package, + modified_parsed_flags.into_iter(), + codegen_mode, + flag_ids, + allow_instrumentation, + ) } pub fn create_rust_lib(mut input: Input, codegen_mode: CodegenMode) -> Result<OutputFile> { diff --git a/tools/aconfig/aconfig/src/main.rs b/tools/aconfig/aconfig/src/main.rs index 69f54581cd..72be1c9896 100644 --- a/tools/aconfig/aconfig/src/main.rs +++ b/tools/aconfig/aconfig/src/main.rs @@ -83,6 +83,12 @@ fn cli() -> Command { .long("mode") .value_parser(EnumValueParser::<CodegenMode>::new()) .default_value("production"), + ) + .arg( + Arg::new("allow-instrumentation") + .long("allow-instrumentation") + .value_parser(clap::value_parser!(bool)) + .default_value("false"), ), ) .subcommand( @@ -241,8 +247,10 @@ fn main() -> Result<()> { Some(("create-cpp-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_cpp_lib(cache, *mode).context("failed to create cpp lib")?; + let allow_instrumentation = + get_required_arg::<bool>(sub_matches, "allow-instrumentation")?; + let generated_files = commands::create_cpp_lib(cache, *mode, *allow_instrumentation) + .context("failed to create cpp lib")?; let dir = PathBuf::from(get_required_arg::<String>(sub_matches, "out")?); generated_files .iter() diff --git a/tools/aconfig/aconfig/templates/CustomFeatureFlags.java.template b/tools/aconfig/aconfig/templates/CustomFeatureFlags.java.template new file mode 100644 index 0000000000..b82b9cb827 --- /dev/null +++ b/tools/aconfig/aconfig/templates/CustomFeatureFlags.java.template @@ -0,0 +1,70 @@ +package {package_name}; + +{{ if not library_exported- }} +// TODO(b/303773055): Remove the annotation after access issue is resolved. +import android.compat.annotation.UnsupportedAppUsage; +{{ -endif }} +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.function.BiPredicate; +import java.util.function.Predicate; + +/** @hide */ +public class CustomFeatureFlags implements FeatureFlags \{ + + private BiPredicate<String, Predicate<FeatureFlags>> mGetValueImpl; + + public CustomFeatureFlags(BiPredicate<String, Predicate<FeatureFlags>> getValueImpl) \{ + mGetValueImpl = getValueImpl; + } + +{{ -for item in flag_elements}} + @Override +{{ if not library_exported }} @UnsupportedAppUsage{{ -endif }} + public boolean {item.method_name}() \{ + return getValue(Flags.FLAG_{item.flag_name_constant_suffix}, + FeatureFlags::{item.method_name}); + } +{{ endfor }} + +{{ -if not library_exported }} + public boolean isFlagReadOnlyOptimized(String flagName) \{ + if (mReadOnlyFlagsSet.contains(flagName) && + isOptimizationEnabled()) \{ + return true; + } + return false; + } + + @com.android.aconfig.annotations.AssumeTrueForR8 + private boolean isOptimizationEnabled() \{ + return false; + } +{{ -endif }} + + protected boolean getValue(String flagName, Predicate<FeatureFlags> getter) \{ + return mGetValueImpl.test(flagName, getter); + } + + public List<String> getFlagNames() \{ + return Arrays.asList( + {{ -for item in flag_elements }} + Flags.FLAG_{item.flag_name_constant_suffix} + {{ -if not @last }},{{ endif }} + {{ -endfor }} + ); + } + + private Set<String> mReadOnlyFlagsSet = new HashSet<>( + Arrays.asList( + {{ -for item in flag_elements }} + {{ -if not item.is_read_write }} + Flags.FLAG_{item.flag_name_constant_suffix}, + {{ -endif }} + {{ -endfor }} + ""{# The empty string here is to resolve the ending comma #} + ) + ); +} diff --git a/tools/aconfig/aconfig/templates/FakeFeatureFlagsImpl.java.template b/tools/aconfig/aconfig/templates/FakeFeatureFlagsImpl.java.template index 177e711e77..290d2c4b24 100644 --- a/tools/aconfig/aconfig/templates/FakeFeatureFlagsImpl.java.template +++ b/tools/aconfig/aconfig/templates/FakeFeatureFlagsImpl.java.template @@ -1,27 +1,39 @@ package {package_name}; -{{ if not library_exported- }} -// TODO(b/303773055): Remove the annotation after access issue is resolved. -import android.compat.annotation.UnsupportedAppUsage; -{{ -endif }} -import java.util.Arrays; + import java.util.HashMap; -import java.util.HashSet; import java.util.Map; -import java.util.Set; +import java.util.function.Predicate; /** @hide */ -public class FakeFeatureFlagsImpl implements FeatureFlags \{ +public class FakeFeatureFlagsImpl extends CustomFeatureFlags \{ + private final Map<String, Boolean> mFlagMap = new HashMap<>(); + private final FeatureFlags mDefaults; + public FakeFeatureFlagsImpl() \{ - resetAll(); + this(null); + } + + public FakeFeatureFlagsImpl(FeatureFlags defaults) \{ + super(null); + mDefaults = defaults; + // Initialize the map with null values + for (String flagName : getFlagNames()) \{ + mFlagMap.put(flagName, null); + } } -{{ for item in flag_elements}} @Override -{{ if not library_exported }} @UnsupportedAppUsage{{ -endif }} - public boolean {item.method_name}() \{ - return getValue(Flags.FLAG_{item.flag_name_constant_suffix}); + protected boolean getValue(String flagName, Predicate<FeatureFlags> getter) \{ + Boolean value = this.mFlagMap.get(flagName); + if (value != null) \{ + return value; + } + if (mDefaults != null) \{ + return getter.test(mDefaults); + } + throw new IllegalArgumentException(flagName + " is not set"); } -{{ endfor}} + public void setFlag(String flagName, boolean value) \{ if (!this.mFlagMap.containsKey(flagName)) \{ throw new IllegalArgumentException("no such flag " + flagName); @@ -34,46 +46,4 @@ public class FakeFeatureFlagsImpl implements FeatureFlags \{ entry.setValue(null); } } -{{ if not library_exported }} - public boolean isFlagReadOnlyOptimized(String flagName) \{ - if (mReadOnlyFlagsSet.contains(flagName) && - isOptimizationEnabled()) \{ - return true; - } - return false; - } - - @com.android.aconfig.annotations.AssumeTrueForR8 - private boolean isOptimizationEnabled() \{ - return false; - } -{{ -endif }} - private boolean getValue(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.ofEntries( - {{ -for item in flag_elements }} - Map.entry(Flags.FLAG_{item.flag_name_constant_suffix}, false) - {{ -if not @last }},{{ endif }} - {{ -endfor }} - ) - ); - - private Set<String> mReadOnlyFlagsSet = new HashSet<>( - Arrays.asList( - {{ -for item in flag_elements }} - {{ -if not item.is_read_write }} - Flags.FLAG_{item.flag_name_constant_suffix}, - {{ -endif }} - {{ -endfor }} - ""{# The empty string here is to resolve the ending comma #} - ) - ); } diff --git a/tools/aconfig/aconfig/templates/cpp_source_file.template b/tools/aconfig/aconfig/templates/cpp_source_file.template index 4bcd1b7581..4c098c5b41 100644 --- a/tools/aconfig/aconfig/templates/cpp_source_file.template +++ b/tools/aconfig/aconfig/templates/cpp_source_file.template @@ -1,5 +1,15 @@ #include "{header}.h" +{{ if allow_instrumentation }} +#include <sys/stat.h> +#include "aconfig_storage/aconfig_storage_read_api.hpp" +#include <android/log.h> + +#define ALOGI(msg, ...) \ + __android_log_print(ANDROID_LOG_INFO, "AconfigTestMission1", (msg), __VA_ARGS__) + +{{ endif }} + {{ if readwrite- }} #include <server_configurable_flags/get_flags.h> {{ endif }} @@ -97,6 +107,62 @@ bool {header}_{item.flag_name}() \{ {{ -if item.readwrite }} return {cpp_namespace}::{item.flag_name}(); {{ -else }} + {{ if allow_instrumentation }} + auto result = + {{ if item.is_fixed_read_only }} + {package_macro}_{item.flag_macro} + {{ else }} + {item.default_value} + {{ endif }}; + + struct stat buffer; + if (stat("/metadata/aconfig_test_missions/mission_1", &buffer) != 0) \{ + return result; + } + + auto package_map_file = aconfig_storage::get_mapped_file( + "{item.container}", + aconfig_storage::StorageFileType::package_map); + if (!package_map_file.ok()) \{ + ALOGI("error: failed to get package map file: %s", package_map_file.error().message().c_str()); + return result; + } + + auto package_read_context = aconfig_storage::get_package_read_context( + **package_map_file, "{package}"); + if (!package_read_context.ok()) \{ + ALOGI("error: failed to get package read context: %s", package_map_file.error().message().c_str()); + return result; + } + + delete *package_map_file; + + auto flag_val_map = aconfig_storage::get_mapped_file( + "{item.container}", + aconfig_storage::StorageFileType::flag_val); + if (!flag_val_map.ok()) \{ + ALOGI("error: failed to get flag val map: %s", package_map_file.error().message().c_str()); + return result; + } + + auto value = aconfig_storage::get_boolean_flag_value( + **flag_val_map, + package_read_context->boolean_start_index + {item.flag_offset}); + if (!value.ok()) \{ + ALOGI("error: failed to get flag val: %s", package_map_file.error().message().c_str()); + return result; + } + + delete *flag_val_map; + + if (*value != result) \{ + ALOGI("error: new storage value '%d' does not match current value '%d'", *value, result); + } else \{ + ALOGI("success: new storage value was '%d, legacy storage was '%d'", *value, result); + } + + return result; + {{ else }} {{ -if item.is_fixed_read_only }} return {package_macro}_{item.flag_macro}; {{ -else }} @@ -104,6 +170,7 @@ bool {header}_{item.flag_name}() \{ {{ -endif }} {{ -endif }} {{ -endif }} + {{ -endif }} } {{ -if is_test_mode }} @@ -119,3 +186,4 @@ void {header}_reset_flags() \{ } {{ -endif }} + diff --git a/tools/aconfig/aconfig_device_paths/Android.bp b/tools/aconfig/aconfig_device_paths/Android.bp index 21aa9a9e08..2c771e09f5 100644 --- a/tools/aconfig/aconfig_device_paths/Android.bp +++ b/tools/aconfig/aconfig_device_paths/Android.bp @@ -36,3 +36,16 @@ rust_library { host_supported: true, defaults: ["libaconfig_device_paths.defaults"], } + +genrule { + name: "libaconfig_java_device_paths_src", + srcs: ["src/DevicePathsTemplate.java"], + out: ["DevicePaths.java"], + tool_files: ["partition_aconfig_flags_paths.txt"], + cmd: "sed -e '/TEMPLATE/{r$(location partition_aconfig_flags_paths.txt)' -e 'd}' $(in) > $(out)" +} + +java_library { + name: "aconfig_device_paths_java", + srcs: [":libaconfig_java_device_paths_src"], +} diff --git a/tools/aconfig/aconfig_device_paths/partition_aconfig_flags_paths.txt b/tools/aconfig/aconfig_device_paths/partition_aconfig_flags_paths.txt index 3d2deb2375..140cd21ac8 100644 --- a/tools/aconfig/aconfig_device_paths/partition_aconfig_flags_paths.txt +++ b/tools/aconfig/aconfig_device_paths/partition_aconfig_flags_paths.txt @@ -1,6 +1,4 @@ -[ - "/system/etc/aconfig_flags.pb", - "/system_ext/etc/aconfig_flags.pb", - "/product/etc/aconfig_flags.pb", - "/vendor/etc/aconfig_flags.pb", -] +"/system/etc/aconfig_flags.pb", +"/system_ext/etc/aconfig_flags.pb", +"/product/etc/aconfig_flags.pb", +"/vendor/etc/aconfig_flags.pb", diff --git a/tools/aconfig/aconfig_device_paths/src/DevicePathsTemplate.java b/tools/aconfig/aconfig_device_paths/src/DevicePathsTemplate.java new file mode 100644 index 0000000000..f27b9bd360 --- /dev/null +++ b/tools/aconfig/aconfig_device_paths/src/DevicePathsTemplate.java @@ -0,0 +1,68 @@ +/* + * 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; + +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * @hide + */ +public class DevicePaths { + static final String[] PATHS = { + TEMPLATE + }; + + private static final String APEX_DIR = "/apex"; + private static final String APEX_ACONFIG_PATH_SUFFIX = "/etc/aconfig_flags.pb"; + + + /** + * Returns the list of all on-device aconfig protos paths. + * @hide + */ + public List<String> parsedFlagsProtoPaths() { + ArrayList<String> paths = new ArrayList(Arrays.asList(PATHS)); + + File apexDirectory = new File(APEX_DIR); + if (!apexDirectory.isDirectory()) { + return paths; + } + + File[] subdirs = apexDirectory.listFiles(); + if (subdirs == null) { + return paths; + } + + for (File prefix : subdirs) { + // For each mainline modules, there are two directories, one <modulepackage>/, + // and one <modulepackage>@<versioncode>/. Just read the former. + if (prefix.getAbsolutePath().contains("@")) { + continue; + } + + File protoPath = new File(prefix + APEX_ACONFIG_PATH_SUFFIX); + if (!protoPath.exists()) { + continue; + } + + paths.add(protoPath.getAbsolutePath()); + } + return paths; + } +} diff --git a/tools/aconfig/aconfig_device_paths/src/lib.rs b/tools/aconfig/aconfig_device_paths/src/lib.rs index 7bb62f4247..7480b3002c 100644 --- a/tools/aconfig/aconfig_device_paths/src/lib.rs +++ b/tools/aconfig/aconfig_device_paths/src/lib.rs @@ -21,11 +21,19 @@ use std::path::PathBuf; use std::fs; +fn read_partition_paths() -> Vec<PathBuf> { + include_str!("../partition_aconfig_flags_paths.txt") + .split(',') + .map(|s| s.trim().trim_matches('"')) + .filter(|s| !s.is_empty()) + .map(|s| PathBuf::from(s.to_string())) + .collect() +} + /// Determine all paths that contain an aconfig protobuf file. pub fn parsed_flags_proto_paths() -> Result<Vec<PathBuf>> { - let mut result: Vec<PathBuf> = include!("../partition_aconfig_flags_paths.txt") - .map(|s| PathBuf::from(s.to_string())) - .to_vec(); + let mut result: Vec<PathBuf> = read_partition_paths(); + for dir in fs::read_dir("/apex")? { let dir = dir?; @@ -45,3 +53,23 @@ pub fn parsed_flags_proto_paths() -> Result<Vec<PathBuf>> { Ok(result) } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_read_partition_paths() { + assert_eq!(read_partition_paths().len(), 4); + + assert_eq!( + read_partition_paths(), + vec![ + PathBuf::from("/system/etc/aconfig_flags.pb"), + PathBuf::from("/system_ext/etc/aconfig_flags.pb"), + PathBuf::from("/product/etc/aconfig_flags.pb"), + PathBuf::from("/vendor/etc/aconfig_flags.pb") + ] + ); + } +} diff --git a/tools/aconfig/aconfig_protos/Android.bp b/tools/aconfig/aconfig_protos/Android.bp index 18c545ae96..d24199443c 100644 --- a/tools/aconfig/aconfig_protos/Android.bp +++ b/tools/aconfig/aconfig_protos/Android.bp @@ -17,7 +17,22 @@ java_library { apex_available: [ "com.android.configinfrastructure", "//apex_available:platform", - ] + ], +} + +java_library { + name: "libaconfig_java_proto_nano", + srcs: ["protos/aconfig.proto"], + static_libs: ["libprotobuf-java-nano"], + proto: { + type: "nano", + }, + sdk_version: "current", + min_sdk_version: "UpsideDownCake", + apex_available: [ + "//apex_available:platform", + ], + jarjar_rules: "jarjar-nano-rules.txt", } java_library_host { @@ -58,7 +73,7 @@ rust_defaults { ], proc_macros: [ "libpaste", - ] + ], } rust_library { diff --git a/tools/aconfig/aconfig_protos/jarjar-nano-rules.txt b/tools/aconfig/aconfig_protos/jarjar-nano-rules.txt new file mode 100644 index 0000000000..b58fa64838 --- /dev/null +++ b/tools/aconfig/aconfig_protos/jarjar-nano-rules.txt @@ -0,0 +1 @@ +rule com.google.protobuf.** android.internal.framework.protobuf.@1
\ No newline at end of file diff --git a/tools/aconfig/aconfig_storage_file/Android.bp b/tools/aconfig/aconfig_storage_file/Android.bp index 08c00b0d6d..e066e31ac1 100644 --- a/tools/aconfig/aconfig_storage_file/Android.bp +++ b/tools/aconfig/aconfig_storage_file/Android.bp @@ -12,6 +12,7 @@ rust_defaults { "libtempfile", "libprotobuf", "libclap", + "libcxx", "libaconfig_storage_protos", ], } @@ -77,3 +78,62 @@ cc_library { product_available: true, double_loadable: true, } + +// cxx source codegen from rust api +genrule { + name: "libcxx_aconfig_storage_file_bridge_code", + tools: ["cxxbridge"], + cmd: "$(location cxxbridge) $(in) > $(out)", + srcs: ["src/lib.rs"], + out: ["aconfig_storage/lib.rs.cc"], +} + +// cxx header codegen from rust api +genrule { + name: "libcxx_aconfig_storage_file_bridge_header", + tools: ["cxxbridge"], + cmd: "$(location cxxbridge) $(in) --header > $(out)", + srcs: ["src/lib.rs"], + out: ["aconfig_storage/lib.rs.h"], +} + +// a static cc lib based on generated code +rust_ffi_static { + name: "libaconfig_storage_file_cxx_bridge", + crate_name: "aconfig_storage_file_cxx_bridge", + host_supported: true, + vendor_available: true, + product_available: true, + srcs: ["src/lib.rs"], + defaults: ["aconfig_storage_file.defaults"], + apex_available: [ + "//apex_available:platform", + "//apex_available:anyapex", + ], + min_sdk_version: "29", +} + +// storage file parse api cc interface +cc_library { + name: "libaconfig_storage_file_cc", + srcs: ["aconfig_storage_file.cpp"], + generated_headers: [ + "cxx-bridge-header", + "libcxx_aconfig_storage_file_bridge_header", + ], + generated_sources: ["libcxx_aconfig_storage_file_bridge_code"], + whole_static_libs: ["libaconfig_storage_file_cxx_bridge"], + export_include_dirs: ["include"], + host_supported: true, + vendor_available: true, + product_available: true, + shared_libs: [ + "libbase", + ], + apex_available: [ + "//apex_available:platform", + "//apex_available:anyapex", + ], + min_sdk_version: "29", + double_loadable: true, +} diff --git a/tools/aconfig/aconfig_storage_file/Cargo.toml b/tools/aconfig/aconfig_storage_file/Cargo.toml index 641f481ed3..192dfad40a 100644 --- a/tools/aconfig/aconfig_storage_file/Cargo.toml +++ b/tools/aconfig/aconfig_storage_file/Cargo.toml @@ -13,6 +13,7 @@ protobuf = "3.2.0" tempfile = "3.9.0" thiserror = "1.0.56" clap = { version = "4.1.8", features = ["derive"] } +cxx = "1.0" [[bin]] name = "aconfig-storage" diff --git a/tools/aconfig/aconfig_storage_file/aconfig_storage_file.cpp b/tools/aconfig/aconfig_storage_file/aconfig_storage_file.cpp new file mode 100644 index 0000000000..7af024b39d --- /dev/null +++ b/tools/aconfig/aconfig_storage_file/aconfig_storage_file.cpp @@ -0,0 +1,61 @@ +#include "rust/cxx.h" +#include "aconfig_storage/lib.rs.h" + +#include "aconfig_storage/aconfig_storage_file.hpp" + +using namespace android::base; + +namespace aconfig_storage { + +Result<std::vector<FlagValueSummary>> list_flags( + const std::string& package_map, + const std::string& flag_map, + const std::string& flag_val) { + auto flag_list_cxx = list_flags_cxx(rust::Str(package_map.c_str()), + rust::Str(flag_map.c_str()), + rust::Str(flag_val.c_str())); + if (flag_list_cxx.query_success) { + auto flag_list = std::vector<FlagValueSummary>(); + for (const auto& flag_cxx : flag_list_cxx.flags) { + auto flag = FlagValueSummary(); + flag.package_name = std::string(flag_cxx.package_name); + flag.flag_name = std::string(flag_cxx.flag_name); + flag.flag_value = std::string(flag_cxx.flag_value); + flag.value_type = std::string(flag_cxx.value_type); + flag_list.push_back(flag); + } + return flag_list; + } else { + return Error() << flag_list_cxx.error_message; + } +} + +Result<std::vector<FlagValueAndInfoSummary>> list_flags_with_info( + const std::string& package_map, + const std::string& flag_map, + const std::string& flag_val, + const std::string& flag_info) { + auto flag_list_cxx = list_flags_with_info_cxx(rust::Str(package_map.c_str()), + rust::Str(flag_map.c_str()), + rust::Str(flag_val.c_str()), + rust::Str(flag_info.c_str())); + if (flag_list_cxx.query_success) { + auto flag_list = std::vector<FlagValueAndInfoSummary>(); + for (const auto& flag_cxx : flag_list_cxx.flags) { + auto flag = FlagValueAndInfoSummary(); + flag.package_name = std::string(flag_cxx.package_name); + flag.flag_name = std::string(flag_cxx.flag_name); + flag.flag_value = std::string(flag_cxx.flag_value); + flag.value_type = std::string(flag_cxx.value_type); + flag.is_readwrite = flag_cxx.is_readwrite; + flag.has_server_override = flag_cxx.has_server_override; + flag.has_local_override = flag_cxx.has_local_override; + flag_list.push_back(flag); + } + return flag_list; + } else { + return Error() << flag_list_cxx.error_message; + } +} + +} // namespace aconfig_storage diff --git a/tools/aconfig/aconfig_storage_file/build.rs b/tools/aconfig/aconfig_storage_file/build.rs index 1feeb60677..e0ade2aba0 100644 --- a/tools/aconfig/aconfig_storage_file/build.rs +++ b/tools/aconfig/aconfig_storage_file/build.rs @@ -14,4 +14,6 @@ fn main() { .inputs(proto_files) .cargo_out_dir("aconfig_storage_protos") .run_from_script(); + + let _ = cxx_build::bridge("src/lib.rs"); } diff --git a/tools/aconfig/aconfig_storage_file/include/aconfig_storage/aconfig_storage_file.hpp b/tools/aconfig/aconfig_storage_file/include/aconfig_storage/aconfig_storage_file.hpp new file mode 100644 index 0000000000..9f3cdb046b --- /dev/null +++ b/tools/aconfig/aconfig_storage_file/include/aconfig_storage/aconfig_storage_file.hpp @@ -0,0 +1,48 @@ +#pragma once + +#include <vector> +#include <string> +#include <android-base/result.h> + +namespace aconfig_storage { + +/// Flag value summary for a flag +struct FlagValueSummary { + std::string package_name; + std::string flag_name; + std::string flag_value; + std::string value_type; +}; + +/// List all flag values +/// \input package_map: package map file +/// \input flag_map: flag map file +/// \input flag_val: flag value file +android::base::Result<std::vector<FlagValueSummary>> list_flags( + const std::string& package_map, + const std::string& flag_map, + const std::string& flag_val); + +/// Flag value and info summary for a flag +struct FlagValueAndInfoSummary { + std::string package_name; + std::string flag_name; + std::string flag_value; + std::string value_type; + bool is_readwrite; + bool has_server_override; + bool has_local_override; +}; + +/// List all flag values with their flag info +/// \input package_map: package map file +/// \input flag_map: flag map file +/// \input flag_val: flag value file +/// \input flag_info: flag info file +android::base::Result<std::vector<FlagValueAndInfoSummary>> list_flags_with_info( + const std::string& package_map, + const std::string& flag_map, + const std::string& flag_val, + const std::string& flag_info); + +}// namespace aconfig_storage diff --git a/tools/aconfig/aconfig_storage_file/protos/aconfig_storage_metadata.proto b/tools/aconfig/aconfig_storage_file/protos/aconfig_storage_metadata.proto index 7de43ca918..e1c1c7ffca 100644 --- a/tools/aconfig/aconfig_storage_file/protos/aconfig_storage_metadata.proto +++ b/tools/aconfig/aconfig_storage_file/protos/aconfig_storage_metadata.proto @@ -27,8 +27,7 @@ message storage_file_info { optional string flag_map = 4; optional string flag_val = 5; optional string flag_info = 6; - optional string local_overrides = 7; - optional int64 timestamp = 8; + optional int64 timestamp = 7; } message storage_files { diff --git a/tools/aconfig/aconfig_storage_file/src/lib.rs b/tools/aconfig/aconfig_storage_file/src/lib.rs index 2acfc7dbc7..26e9c1a3be 100644 --- a/tools/aconfig/aconfig_storage_file/src/lib.rs +++ b/tools/aconfig/aconfig_storage_file/src/lib.rs @@ -278,15 +278,73 @@ pub fn read_file_to_bytes(file_path: &str) -> Result<Vec<u8>, AconfigStorageErro Ok(buffer) } +/// Flag value summary +#[derive(Debug, PartialEq)] +pub struct FlagValueSummary { + pub package_name: String, + pub flag_name: String, + pub flag_value: String, + pub value_type: StoredFlagType, +} + /// List flag values from storage files pub fn list_flags( package_map: &str, flag_map: &str, flag_val: &str, -) -> Result<Vec<(String, String, StoredFlagType, bool)>, AconfigStorageError> { +) -> Result<Vec<FlagValueSummary>, AconfigStorageError> { + let package_table = PackageTable::from_bytes(&read_file_to_bytes(package_map)?)?; + let flag_table = FlagTable::from_bytes(&read_file_to_bytes(flag_map)?)?; + let flag_value_list = FlagValueList::from_bytes(&read_file_to_bytes(flag_val)?)?; + + let mut package_info = vec![("", 0); package_table.header.num_packages as usize]; + for node in package_table.nodes.iter() { + package_info[node.package_id as usize] = (&node.package_name, node.boolean_start_index); + } + + let mut flags = Vec::new(); + for node in flag_table.nodes.iter() { + let (package_name, boolean_start_index) = package_info[node.package_id as usize]; + let flag_index = boolean_start_index + node.flag_index as u32; + let flag_value = flag_value_list.booleans[flag_index as usize]; + flags.push(FlagValueSummary { + package_name: String::from(package_name), + flag_name: node.flag_name.clone(), + flag_value: flag_value.to_string(), + value_type: node.flag_type, + }); + } + + flags.sort_by(|v1, v2| match v1.package_name.cmp(&v2.package_name) { + Ordering::Equal => v1.flag_name.cmp(&v2.flag_name), + other => other, + }); + Ok(flags) +} + +/// Flag value and info summary +#[derive(Debug, PartialEq)] +pub struct FlagValueAndInfoSummary { + pub package_name: String, + pub flag_name: String, + pub flag_value: String, + pub value_type: StoredFlagType, + pub is_readwrite: bool, + pub has_server_override: bool, + pub has_local_override: bool, +} + +/// List flag values and info from storage files +pub fn list_flags_with_info( + package_map: &str, + flag_map: &str, + flag_val: &str, + flag_info: &str, +) -> Result<Vec<FlagValueAndInfoSummary>, AconfigStorageError> { let package_table = PackageTable::from_bytes(&read_file_to_bytes(package_map)?)?; let flag_table = FlagTable::from_bytes(&read_file_to_bytes(flag_map)?)?; let flag_value_list = FlagValueList::from_bytes(&read_file_to_bytes(flag_val)?)?; + let flag_info = FlagInfoList::from_bytes(&read_file_to_bytes(flag_info)?)?; let mut package_info = vec![("", 0); package_table.header.num_packages as usize]; for node in package_table.nodes.iter() { @@ -295,30 +353,159 @@ pub fn list_flags( let mut flags = Vec::new(); for node in flag_table.nodes.iter() { - let (package_name, package_offset) = package_info[node.package_id as usize]; - let flag_offset = package_offset + node.flag_index as u32; - let flag_value = flag_value_list.booleans[flag_offset as usize]; - flags.push(( - String::from(package_name), - node.flag_name.clone(), - node.flag_type, - flag_value, - )); + let (package_name, boolean_start_index) = package_info[node.package_id as usize]; + let flag_index = boolean_start_index + node.flag_index as u32; + let flag_value = flag_value_list.booleans[flag_index as usize]; + let flag_attribute = flag_info.nodes[flag_index as usize].attributes; + flags.push(FlagValueAndInfoSummary { + package_name: String::from(package_name), + flag_name: node.flag_name.clone(), + flag_value: flag_value.to_string(), + value_type: node.flag_type, + is_readwrite: flag_attribute & (FlagInfoBit::IsReadWrite as u8) != 0, + has_server_override: flag_attribute & (FlagInfoBit::HasServerOverride as u8) != 0, + has_local_override: flag_attribute & (FlagInfoBit::HasLocalOverride as u8) != 0, + }); } - flags.sort_by(|v1, v2| match v1.0.cmp(&v2.0) { - Ordering::Equal => v1.1.cmp(&v2.1), + flags.sort_by(|v1, v2| match v1.package_name.cmp(&v2.package_name) { + Ordering::Equal => v1.flag_name.cmp(&v2.flag_name), other => other, }); Ok(flags) } +// *************************************** // +// CC INTERLOP +// *************************************** // + +// Exported rust data structure and methods, c++ code will be generated +#[cxx::bridge] +mod ffi { + /// flag value summary cxx return + pub struct FlagValueSummaryCXX { + pub package_name: String, + pub flag_name: String, + pub flag_value: String, + pub value_type: String, + } + + /// flag value and info summary cxx return + pub struct FlagValueAndInfoSummaryCXX { + pub package_name: String, + pub flag_name: String, + pub flag_value: String, + pub value_type: String, + pub is_readwrite: bool, + pub has_server_override: bool, + pub has_local_override: bool, + } + + /// list flag result cxx return + pub struct ListFlagValueResultCXX { + pub query_success: bool, + pub error_message: String, + pub flags: Vec<FlagValueSummaryCXX>, + } + + /// list flag with info result cxx return + pub struct ListFlagValueAndInfoResultCXX { + pub query_success: bool, + pub error_message: String, + pub flags: Vec<FlagValueAndInfoSummaryCXX>, + } + + // Rust export to c++ + extern "Rust" { + pub fn list_flags_cxx( + package_map: &str, + flag_map: &str, + flag_val: &str, + ) -> ListFlagValueResultCXX; + + pub fn list_flags_with_info_cxx( + package_map: &str, + flag_map: &str, + flag_val: &str, + flag_info: &str, + ) -> ListFlagValueAndInfoResultCXX; + } +} + +/// implement flag value summary cxx return type +impl ffi::FlagValueSummaryCXX { + pub(crate) fn new(summary: FlagValueSummary) -> Self { + Self { + package_name: summary.package_name, + flag_name: summary.flag_name, + flag_value: summary.flag_value, + value_type: format!("{:?}", summary.value_type), + } + } +} + +/// implement flag value and info summary cxx return type +impl ffi::FlagValueAndInfoSummaryCXX { + pub(crate) fn new(summary: FlagValueAndInfoSummary) -> Self { + Self { + package_name: summary.package_name, + flag_name: summary.flag_name, + flag_value: summary.flag_value, + value_type: format!("{:?}", summary.value_type), + is_readwrite: summary.is_readwrite, + has_server_override: summary.has_server_override, + has_local_override: summary.has_local_override, + } + } +} + +/// implement list flag cxx interlop +pub fn list_flags_cxx( + package_map: &str, + flag_map: &str, + flag_val: &str, +) -> ffi::ListFlagValueResultCXX { + match list_flags(package_map, flag_map, flag_val) { + Ok(summary) => ffi::ListFlagValueResultCXX { + query_success: true, + error_message: String::new(), + flags: summary.into_iter().map(ffi::FlagValueSummaryCXX::new).collect(), + }, + Err(errmsg) => ffi::ListFlagValueResultCXX { + query_success: false, + error_message: format!("{:?}", errmsg), + flags: Vec::new(), + }, + } +} + +/// implement list flag with info cxx interlop +pub fn list_flags_with_info_cxx( + package_map: &str, + flag_map: &str, + flag_val: &str, + flag_info: &str, +) -> ffi::ListFlagValueAndInfoResultCXX { + match list_flags_with_info(package_map, flag_map, flag_val, flag_info) { + Ok(summary) => ffi::ListFlagValueAndInfoResultCXX { + query_success: true, + error_message: String::new(), + flags: summary.into_iter().map(ffi::FlagValueAndInfoSummaryCXX::new).collect(), + }, + Err(errmsg) => ffi::ListFlagValueAndInfoResultCXX { + query_success: false, + error_message: format!("{:?}", errmsg), + flags: Vec::new(), + }, + } +} + #[cfg(test)] mod tests { use super::*; use crate::test_utils::{ - create_test_flag_table, create_test_flag_value_list, create_test_package_table, - write_bytes_to_temp_file, + create_test_flag_info_list, create_test_flag_table, create_test_flag_value_list, + create_test_package_table, write_bytes_to_temp_file, }; #[test] @@ -337,54 +524,154 @@ mod tests { let flags = list_flags(&package_table_path, &flag_table_path, &flag_value_list_path).unwrap(); let expected = [ - ( - String::from("com.android.aconfig.storage.test_1"), - String::from("disabled_rw"), - StoredFlagType::ReadWriteBoolean, - false, - ), - ( - String::from("com.android.aconfig.storage.test_1"), - String::from("enabled_ro"), - StoredFlagType::ReadOnlyBoolean, - true, - ), - ( - String::from("com.android.aconfig.storage.test_1"), - String::from("enabled_rw"), - StoredFlagType::ReadWriteBoolean, - true, - ), - ( - String::from("com.android.aconfig.storage.test_2"), - String::from("disabled_rw"), - StoredFlagType::ReadWriteBoolean, - false, - ), - ( - String::from("com.android.aconfig.storage.test_2"), - String::from("enabled_fixed_ro"), - StoredFlagType::FixedReadOnlyBoolean, - true, - ), - ( - String::from("com.android.aconfig.storage.test_2"), - String::from("enabled_ro"), - StoredFlagType::ReadOnlyBoolean, - true, - ), - ( - String::from("com.android.aconfig.storage.test_4"), - String::from("enabled_fixed_ro"), - StoredFlagType::FixedReadOnlyBoolean, - true, - ), - ( - String::from("com.android.aconfig.storage.test_4"), - String::from("enabled_rw"), - StoredFlagType::ReadWriteBoolean, - true, - ), + FlagValueSummary { + package_name: String::from("com.android.aconfig.storage.test_1"), + flag_name: String::from("disabled_rw"), + value_type: StoredFlagType::ReadWriteBoolean, + flag_value: String::from("false"), + }, + FlagValueSummary { + package_name: String::from("com.android.aconfig.storage.test_1"), + flag_name: String::from("enabled_ro"), + value_type: StoredFlagType::ReadOnlyBoolean, + flag_value: String::from("true"), + }, + FlagValueSummary { + package_name: String::from("com.android.aconfig.storage.test_1"), + flag_name: String::from("enabled_rw"), + value_type: StoredFlagType::ReadWriteBoolean, + flag_value: String::from("true"), + }, + FlagValueSummary { + package_name: String::from("com.android.aconfig.storage.test_2"), + flag_name: String::from("disabled_rw"), + value_type: StoredFlagType::ReadWriteBoolean, + flag_value: String::from("false"), + }, + FlagValueSummary { + package_name: String::from("com.android.aconfig.storage.test_2"), + flag_name: String::from("enabled_fixed_ro"), + value_type: StoredFlagType::FixedReadOnlyBoolean, + flag_value: String::from("true"), + }, + FlagValueSummary { + package_name: String::from("com.android.aconfig.storage.test_2"), + flag_name: String::from("enabled_ro"), + value_type: StoredFlagType::ReadOnlyBoolean, + flag_value: String::from("true"), + }, + FlagValueSummary { + package_name: String::from("com.android.aconfig.storage.test_4"), + flag_name: String::from("enabled_fixed_ro"), + value_type: StoredFlagType::FixedReadOnlyBoolean, + flag_value: String::from("true"), + }, + FlagValueSummary { + package_name: String::from("com.android.aconfig.storage.test_4"), + flag_name: String::from("enabled_rw"), + value_type: StoredFlagType::ReadWriteBoolean, + flag_value: String::from("true"), + }, + ]; + assert_eq!(flags, expected); + } + + #[test] + // this test point locks down the flag list with info api + fn test_list_flag_with_info() { + let package_table = + write_bytes_to_temp_file(&create_test_package_table().into_bytes()).unwrap(); + let flag_table = write_bytes_to_temp_file(&create_test_flag_table().into_bytes()).unwrap(); + let flag_value_list = + write_bytes_to_temp_file(&create_test_flag_value_list().into_bytes()).unwrap(); + let flag_info_list = + write_bytes_to_temp_file(&create_test_flag_info_list().into_bytes()).unwrap(); + + let package_table_path = package_table.path().display().to_string(); + let flag_table_path = flag_table.path().display().to_string(); + let flag_value_list_path = flag_value_list.path().display().to_string(); + let flag_info_list_path = flag_info_list.path().display().to_string(); + + let flags = list_flags_with_info( + &package_table_path, + &flag_table_path, + &flag_value_list_path, + &flag_info_list_path, + ) + .unwrap(); + let expected = [ + FlagValueAndInfoSummary { + package_name: String::from("com.android.aconfig.storage.test_1"), + flag_name: String::from("disabled_rw"), + value_type: StoredFlagType::ReadWriteBoolean, + flag_value: String::from("false"), + is_readwrite: true, + has_server_override: false, + has_local_override: false, + }, + FlagValueAndInfoSummary { + package_name: String::from("com.android.aconfig.storage.test_1"), + flag_name: String::from("enabled_ro"), + value_type: StoredFlagType::ReadOnlyBoolean, + flag_value: String::from("true"), + is_readwrite: false, + has_server_override: false, + has_local_override: false, + }, + FlagValueAndInfoSummary { + package_name: String::from("com.android.aconfig.storage.test_1"), + flag_name: String::from("enabled_rw"), + value_type: StoredFlagType::ReadWriteBoolean, + flag_value: String::from("true"), + is_readwrite: true, + has_server_override: false, + has_local_override: false, + }, + FlagValueAndInfoSummary { + package_name: String::from("com.android.aconfig.storage.test_2"), + flag_name: String::from("disabled_rw"), + value_type: StoredFlagType::ReadWriteBoolean, + flag_value: String::from("false"), + is_readwrite: true, + has_server_override: false, + has_local_override: false, + }, + FlagValueAndInfoSummary { + package_name: String::from("com.android.aconfig.storage.test_2"), + flag_name: String::from("enabled_fixed_ro"), + value_type: StoredFlagType::FixedReadOnlyBoolean, + flag_value: String::from("true"), + is_readwrite: false, + has_server_override: false, + has_local_override: false, + }, + FlagValueAndInfoSummary { + package_name: String::from("com.android.aconfig.storage.test_2"), + flag_name: String::from("enabled_ro"), + value_type: StoredFlagType::ReadOnlyBoolean, + flag_value: String::from("true"), + is_readwrite: false, + has_server_override: false, + has_local_override: false, + }, + FlagValueAndInfoSummary { + package_name: String::from("com.android.aconfig.storage.test_4"), + flag_name: String::from("enabled_fixed_ro"), + value_type: StoredFlagType::FixedReadOnlyBoolean, + flag_value: String::from("true"), + is_readwrite: false, + has_server_override: false, + has_local_override: false, + }, + FlagValueAndInfoSummary { + package_name: String::from("com.android.aconfig.storage.test_4"), + flag_name: String::from("enabled_rw"), + value_type: StoredFlagType::ReadWriteBoolean, + flag_value: String::from("true"), + is_readwrite: true, + has_server_override: false, + has_local_override: false, + }, ]; assert_eq!(flags, expected); } diff --git a/tools/aconfig/aconfig_storage_file/src/main.rs b/tools/aconfig/aconfig_storage_file/src/main.rs index b686274a2d..8b9e38da02 100644 --- a/tools/aconfig/aconfig_storage_file/src/main.rs +++ b/tools/aconfig/aconfig_storage_file/src/main.rs @@ -17,8 +17,8 @@ //! `aconfig-storage` is a debugging tool to parse storage files use aconfig_storage_file::{ - list_flags, read_file_to_bytes, AconfigStorageError, FlagInfoList, FlagTable, FlagValueList, - PackageTable, StorageFileType, + list_flags, list_flags_with_info, read_file_to_bytes, AconfigStorageError, FlagInfoList, + FlagTable, FlagValueList, PackageTable, StorageFileType, }; use clap::{builder::ArgAction, Arg, Command}; @@ -45,7 +45,10 @@ fn cli() -> Command { .action(ArgAction::Set), ) .arg(Arg::new("flag-map").long("flag-map").required(true).action(ArgAction::Set)) - .arg(Arg::new("flag-val").long("flag-val").required(true).action(ArgAction::Set)), + .arg(Arg::new("flag-val").long("flag-val").required(true).action(ArgAction::Set)) + .arg( + Arg::new("flag-info").long("flag-info").required(false).action(ArgAction::Set), + ), ) } @@ -87,9 +90,27 @@ fn main() -> Result<(), AconfigStorageError> { let package_map = sub_matches.get_one::<String>("package-map").unwrap(); let flag_map = sub_matches.get_one::<String>("flag-map").unwrap(); let flag_val = sub_matches.get_one::<String>("flag-val").unwrap(); - let flags = list_flags(package_map, flag_map, flag_val)?; - for (package_name, flag_name, flag_type, flag_value) in flags.iter() { - println!("{} {} {:?} {}", package_name, flag_name, flag_type, flag_value); + let flag_info = sub_matches.get_one::<String>("flag-info"); + match flag_info { + Some(info_file) => { + let flags = list_flags_with_info(package_map, flag_map, flag_val, info_file)?; + for flag in flags.iter() { + println!( + "{} {} {} {:?} IsReadWrite: {}, HasServerOverride: {}, HasLocalOverride: {}", + flag.package_name, flag.flag_name, flag.flag_value, flag.value_type, + flag.is_readwrite, flag.has_server_override, flag.has_local_override, + ); + } + } + None => { + let flags = list_flags(package_map, flag_map, flag_val)?; + for flag in flags.iter() { + println!( + "{} {} {} {:?}", + flag.package_name, flag.flag_name, flag.flag_value, flag.value_type, + ); + } + } } } _ => unreachable!(), diff --git a/tools/aconfig/aconfig_storage_file/tests/Android.bp b/tools/aconfig/aconfig_storage_file/tests/Android.bp new file mode 100644 index 0000000000..26b7800877 --- /dev/null +++ b/tools/aconfig/aconfig_storage_file/tests/Android.bp @@ -0,0 +1,23 @@ + +cc_test { + name: "aconfig_storage_file.test.cpp", + team: "trendy_team_android_core_experiments", + srcs: [ + "storage_file_test.cpp", + ], + static_libs: [ + "libgmock", + "libaconfig_storage_file_cc", + "libbase", + ], + data: [ + "package.map", + "flag.map", + "flag.val", + "flag.info", + ], + test_suites: [ + "device-tests", + "general-tests", + ], +} diff --git a/tools/aconfig/aconfig_storage_file/tests/flag.info b/tools/aconfig/aconfig_storage_file/tests/flag.info Binary files differnew file mode 100644 index 0000000000..6223edf369 --- /dev/null +++ b/tools/aconfig/aconfig_storage_file/tests/flag.info diff --git a/tools/aconfig/aconfig_storage_file/tests/flag.map b/tools/aconfig/aconfig_storage_file/tests/flag.map Binary files differnew file mode 100644 index 0000000000..e868f53d7e --- /dev/null +++ b/tools/aconfig/aconfig_storage_file/tests/flag.map diff --git a/tools/aconfig/aconfig_storage_file/tests/flag.val b/tools/aconfig/aconfig_storage_file/tests/flag.val Binary files differnew file mode 100644 index 0000000000..ed203d4d13 --- /dev/null +++ b/tools/aconfig/aconfig_storage_file/tests/flag.val diff --git a/tools/aconfig/aconfig_storage_file/tests/package.map b/tools/aconfig/aconfig_storage_file/tests/package.map Binary files differnew file mode 100644 index 0000000000..6c46a0339c --- /dev/null +++ b/tools/aconfig/aconfig_storage_file/tests/package.map diff --git a/tools/aconfig/aconfig_storage_file/tests/storage_file_test.cpp b/tools/aconfig/aconfig_storage_file/tests/storage_file_test.cpp new file mode 100644 index 0000000000..ebd1dd89bd --- /dev/null +++ b/tools/aconfig/aconfig_storage_file/tests/storage_file_test.cpp @@ -0,0 +1,112 @@ +/* + * 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. + */ + +#include <string> +#include <vector> +#include <android-base/file.h> +#include <android-base/result.h> +#include <gtest/gtest.h> +#include "aconfig_storage/aconfig_storage_file.hpp" + +using namespace android::base; +using namespace aconfig_storage; + +void verify_value(const FlagValueSummary& flag, + const std::string& package_name, + const std::string& flag_name, + const std::string& flag_val, + const std::string& value_type) { + ASSERT_EQ(flag.package_name, package_name); + ASSERT_EQ(flag.flag_name, flag_name); + ASSERT_EQ(flag.flag_value, flag_val); + ASSERT_EQ(flag.value_type, value_type); +} + +void verify_value_info(const FlagValueAndInfoSummary& flag, + const std::string& package_name, + const std::string& flag_name, + const std::string& flag_val, + const std::string& value_type, + bool is_readwrite, + bool has_server_override, + bool has_local_override) { + ASSERT_EQ(flag.package_name, package_name); + ASSERT_EQ(flag.flag_name, flag_name); + ASSERT_EQ(flag.flag_value, flag_val); + ASSERT_EQ(flag.value_type, value_type); + ASSERT_EQ(flag.is_readwrite, is_readwrite); + ASSERT_EQ(flag.has_server_override, has_server_override); + ASSERT_EQ(flag.has_local_override, has_local_override); +} + +TEST(AconfigStorageFileTest, test_list_flag) { + auto const test_dir = GetExecutableDirectory(); + auto const package_map = test_dir + "/package.map"; + auto const flag_map = test_dir + "/flag.map"; + auto const flag_val = test_dir + "/flag.val"; + auto flag_list_result = aconfig_storage::list_flags( + package_map, flag_map, flag_val); + ASSERT_TRUE(flag_list_result.ok()); + + auto const& flag_list = *flag_list_result; + ASSERT_EQ(flag_list.size(), 8); + verify_value(flag_list[0], "com.android.aconfig.storage.test_1", "disabled_rw", + "false", "ReadWriteBoolean"); + verify_value(flag_list[1], "com.android.aconfig.storage.test_1", "enabled_ro", + "true", "ReadOnlyBoolean"); + verify_value(flag_list[2], "com.android.aconfig.storage.test_1", "enabled_rw", + "true", "ReadWriteBoolean"); + verify_value(flag_list[3], "com.android.aconfig.storage.test_2", "disabled_rw", + "false", "ReadWriteBoolean"); + verify_value(flag_list[4], "com.android.aconfig.storage.test_2", "enabled_fixed_ro", + "true", "FixedReadOnlyBoolean"); + verify_value(flag_list[5], "com.android.aconfig.storage.test_2", "enabled_ro", + "true", "ReadOnlyBoolean"); + verify_value(flag_list[6], "com.android.aconfig.storage.test_4", "enabled_fixed_ro", + "true", "FixedReadOnlyBoolean"); + verify_value(flag_list[7], "com.android.aconfig.storage.test_4", "enabled_rw", + "true", "ReadWriteBoolean"); +} + +TEST(AconfigStorageFileTest, test_list_flag_with_info) { + auto const test_dir = GetExecutableDirectory(); + auto const package_map = test_dir + "/package.map"; + auto const flag_map = test_dir + "/flag.map"; + auto const flag_val = test_dir + "/flag.val"; + auto const flag_info = test_dir + "/flag.info"; + auto flag_list_result = aconfig_storage::list_flags_with_info( + package_map, flag_map, flag_val, flag_info); + ASSERT_TRUE(flag_list_result.ok()); + + auto const& flag_list = *flag_list_result; + ASSERT_EQ(flag_list.size(), 8); + verify_value_info(flag_list[0], "com.android.aconfig.storage.test_1", "disabled_rw", + "false", "ReadWriteBoolean", true, false, false); + verify_value_info(flag_list[1], "com.android.aconfig.storage.test_1", "enabled_ro", + "true", "ReadOnlyBoolean", false, false, false); + verify_value_info(flag_list[2], "com.android.aconfig.storage.test_1", "enabled_rw", + "true", "ReadWriteBoolean", true, false, false); + verify_value_info(flag_list[3], "com.android.aconfig.storage.test_2", "disabled_rw", + "false", "ReadWriteBoolean", true, false, false); + verify_value_info(flag_list[4], "com.android.aconfig.storage.test_2", "enabled_fixed_ro", + "true", "FixedReadOnlyBoolean", false, false, false); + verify_value_info(flag_list[5], "com.android.aconfig.storage.test_2", "enabled_ro", + "true", "ReadOnlyBoolean", false, false, false); + verify_value_info(flag_list[6], "com.android.aconfig.storage.test_4", "enabled_fixed_ro", + "true", "FixedReadOnlyBoolean", false, false, false); + verify_value_info(flag_list[7], "com.android.aconfig.storage.test_4", "enabled_rw", + "true", "ReadWriteBoolean", true, false, false); +} diff --git a/tools/aconfig/aconfig_storage_read_api/Android.bp b/tools/aconfig/aconfig_storage_read_api/Android.bp index 946c00bf23..db362944c5 100644 --- a/tools/aconfig/aconfig_storage_read_api/Android.bp +++ b/tools/aconfig/aconfig_storage_read_api/Android.bp @@ -92,18 +92,28 @@ cc_library { static_libs: [ "libaconfig_storage_protos_cc", "libprotobuf-cpp-lite", - "libbase", ], shared_libs: [ "liblog", + "libbase", ], apex_available: [ "//apex_available:platform", "//apex_available:anyapex", ], min_sdk_version: "29", + target: { + linux: { + version_script: "libaconfig_storage_read_api_cc.map", + }, + }, double_loadable: true, - cflags: [ - "-fvisibility=hidden", +} + +cc_defaults { + name: "aconfig_lib_cc_static_link.defaults", + shared_libs: [ + "libaconfig_storage_read_api_cc", + "liblog", ], } diff --git a/tools/aconfig/aconfig_storage_read_api/aconfig_storage_read_api.cpp b/tools/aconfig/aconfig_storage_read_api/aconfig_storage_read_api.cpp index 8fe42ceddc..0aa936a9eb 100644 --- a/tools/aconfig/aconfig_storage_read_api/aconfig_storage_read_api.cpp +++ b/tools/aconfig/aconfig_storage_read_api/aconfig_storage_read_api.cpp @@ -20,6 +20,11 @@ namespace aconfig_storage { static constexpr char kAvailableStorageRecordsPb[] = "/metadata/aconfig/boot/available_storage_file_records.pb"; +/// destructor +MappedStorageFile::~MappedStorageFile() { + munmap(file_ptr, file_size); +} + /// Read aconfig storage records pb file static Result<storage_records_pb> read_storage_records_pb(std::string const& pb_file) { auto records = storage_records_pb(); @@ -68,7 +73,7 @@ static Result<std::string> find_storage_file( namespace private_internal_api { /// Get mapped file implementation. -Result<MappedStorageFile> get_mapped_file_impl( +Result<MappedStorageFile*> get_mapped_file_impl( std::string const& pb_file, std::string const& container, StorageFileType file_type) { @@ -82,7 +87,7 @@ Result<MappedStorageFile> get_mapped_file_impl( } // namespace private internal api /// Map a storage file -Result<MappedStorageFile> map_storage_file(std::string const& file) { +Result<MappedStorageFile*> map_storage_file(std::string const& file) { int fd = open(file.c_str(), O_CLOEXEC | O_NOFOLLOW | O_RDONLY); if (fd == -1) { return ErrnoError() << "failed to open " << file; @@ -99,9 +104,9 @@ Result<MappedStorageFile> map_storage_file(std::string const& file) { return ErrnoError() << "mmap failed"; } - auto mapped_file = MappedStorageFile(); - mapped_file.file_ptr = map_result; - mapped_file.file_size = file_size; + auto mapped_file = new MappedStorageFile(); + mapped_file->file_ptr = map_result; + mapped_file->file_size = file_size; return mapped_file; } @@ -120,7 +125,7 @@ android::base::Result<FlagValueType> map_to_flag_value_type( } /// Get mapped storage file -Result<MappedStorageFile> get_mapped_file( +Result<MappedStorageFile*> get_mapped_file( std::string const& container, StorageFileType file_type) { return private_internal_api::get_mapped_file_impl( diff --git a/tools/aconfig/aconfig_storage_read_api/include/aconfig_storage/aconfig_storage_read_api.hpp b/tools/aconfig/aconfig_storage_read_api/include/aconfig_storage/aconfig_storage_read_api.hpp index 2bd84fcf20..e6d75373a9 100644 --- a/tools/aconfig/aconfig_storage_read_api/include/aconfig_storage/aconfig_storage_read_api.hpp +++ b/tools/aconfig/aconfig_storage_read_api/include/aconfig_storage/aconfig_storage_read_api.hpp @@ -41,6 +41,7 @@ enum FlagInfoBit { struct MappedStorageFile { void* file_ptr; size_t file_size; + virtual ~MappedStorageFile(); }; /// Package read context query result @@ -60,7 +61,7 @@ struct FlagReadContext { /// DO NOT USE APIS IN THE FOLLOWING NAMESPACE DIRECTLY namespace private_internal_api { -android::base::Result<MappedStorageFile> get_mapped_file_impl( +android::base::Result<MappedStorageFile*> get_mapped_file_impl( std::string const& pb_file, std::string const& container, StorageFileType file_type); @@ -68,7 +69,7 @@ android::base::Result<MappedStorageFile> get_mapped_file_impl( } // namespace private_internal_api /// Map a storage file -android::base::Result<MappedStorageFile> map_storage_file( +android::base::Result<MappedStorageFile*> map_storage_file( std::string const& file); @@ -82,7 +83,7 @@ android::base::Result<FlagValueType> map_to_flag_value_type( /// \input container: stoarge container name /// \input file_type: storage file type enum /// \returns a MappedStorageFileQuery -android::base::Result<MappedStorageFile> get_mapped_file( +android::base::Result<MappedStorageFile*> get_mapped_file( std::string const& container, StorageFileType file_type); diff --git a/tools/aconfig/aconfig_storage_read_api/libaconfig_storage_read_api_cc.map b/tools/aconfig/aconfig_storage_read_api/libaconfig_storage_read_api_cc.map new file mode 100644 index 0000000000..7d47e0ba0e --- /dev/null +++ b/tools/aconfig/aconfig_storage_read_api/libaconfig_storage_read_api_cc.map @@ -0,0 +1,11 @@ +LIBACONFIG_STORAGE_READ_API_CC { + # Export everything in the aconfig_storage namespace. This includes both the + # public API and library internals. + global: + extern "C++" { + aconfig_storage::*; + }; + # Hide everything else. + local: + *; +}; diff --git a/tools/aconfig/aconfig_storage_read_api/src/lib.rs b/tools/aconfig/aconfig_storage_read_api/src/lib.rs index e65dcfbc69..e4192066d5 100644 --- a/tools/aconfig/aconfig_storage_read_api/src/lib.rs +++ b/tools/aconfig/aconfig_storage_read_api/src/lib.rs @@ -504,7 +504,7 @@ files {{ let pb_file_path = pb_file.path().display().to_string(); let flag_info_file = unsafe { get_mapped_file(&pb_file_path, "mockup", StorageFileType::FlagInfo).unwrap() }; - let is_rw: Vec<bool> = vec![true, false, true, false, false, false, false, false]; + let is_rw: Vec<bool> = vec![true, false, true, true, false, false, false, true]; for (offset, expected_value) in is_rw.into_iter().enumerate() { let attribute = get_flag_attribute(&flag_info_file, FlagValueType::Boolean, offset as u32).unwrap(); diff --git a/tools/aconfig/aconfig_storage_read_api/tests/flag.info b/tools/aconfig/aconfig_storage_read_api/tests/flag.info Binary files differindex 820d839363..6223edf369 100644 --- a/tools/aconfig/aconfig_storage_read_api/tests/flag.info +++ b/tools/aconfig/aconfig_storage_read_api/tests/flag.info diff --git a/tools/aconfig/aconfig_storage_read_api/tests/storage_read_api_test.cpp b/tools/aconfig/aconfig_storage_read_api/tests/storage_read_api_test.cpp index b499c1c279..5393c49a7d 100644 --- a/tools/aconfig/aconfig_storage_read_api/tests/storage_read_api_test.cpp +++ b/tools/aconfig/aconfig_storage_read_api/tests/storage_read_api_test.cpp @@ -16,6 +16,7 @@ #include <string> #include <vector> +#include <memory> #include <cstdio> #include <sys/stat.h> @@ -111,18 +112,19 @@ TEST_F(AconfigStorageTest, test_storage_version_query) { /// Negative test to lock down the error when mapping none exist storage files TEST_F(AconfigStorageTest, test_none_exist_storage_file_mapping) { - auto mapped_file = private_api::get_mapped_file_impl( + auto mapped_file_result = private_api::get_mapped_file_impl( storage_record_pb, "vendor", api::StorageFileType::package_map); - ASSERT_FALSE(mapped_file.ok()); - ASSERT_EQ(mapped_file.error().message(), + ASSERT_FALSE(mapped_file_result.ok()); + ASSERT_EQ(mapped_file_result.error().message(), "Unable to find storage files for container vendor"); } /// Test to lock down storage package context query api TEST_F(AconfigStorageTest, test_package_context_query) { - auto mapped_file = private_api::get_mapped_file_impl( + auto mapped_file_result = private_api::get_mapped_file_impl( storage_record_pb, "mockup", api::StorageFileType::package_map); - ASSERT_TRUE(mapped_file.ok()); + ASSERT_TRUE(mapped_file_result.ok()); + auto mapped_file = std::unique_ptr<api::MappedStorageFile>(*mapped_file_result); auto context = api::get_package_read_context( *mapped_file, "com.android.aconfig.storage.test_1"); @@ -148,9 +150,10 @@ TEST_F(AconfigStorageTest, test_package_context_query) { /// Test to lock down when querying none exist package TEST_F(AconfigStorageTest, test_none_existent_package_context_query) { - auto mapped_file = private_api::get_mapped_file_impl( + auto mapped_file_result = private_api::get_mapped_file_impl( storage_record_pb, "mockup", api::StorageFileType::package_map); - ASSERT_TRUE(mapped_file.ok()); + ASSERT_TRUE(mapped_file_result.ok()); + auto mapped_file = std::unique_ptr<api::MappedStorageFile>(*mapped_file_result); auto context = api::get_package_read_context( *mapped_file, "com.android.aconfig.storage.test_3"); @@ -160,9 +163,10 @@ TEST_F(AconfigStorageTest, test_none_existent_package_context_query) { /// Test to lock down storage flag context query api TEST_F(AconfigStorageTest, test_flag_context_query) { - auto mapped_file = private_api::get_mapped_file_impl( + auto mapped_file_result = private_api::get_mapped_file_impl( storage_record_pb, "mockup", api::StorageFileType::flag_map); - ASSERT_TRUE(mapped_file.ok()); + ASSERT_TRUE(mapped_file_result.ok()); + auto mapped_file = std::unique_ptr<api::MappedStorageFile>(*mapped_file_result); auto baseline = std::vector<std::tuple<int, std::string, api::StoredFlagType, int>>{ {0, "enabled_ro", api::StoredFlagType::ReadOnlyBoolean, 1}, @@ -185,9 +189,10 @@ TEST_F(AconfigStorageTest, test_flag_context_query) { /// Test to lock down when querying none exist flag TEST_F(AconfigStorageTest, test_none_existent_flag_context_query) { - auto mapped_file = private_api::get_mapped_file_impl( + auto mapped_file_result = private_api::get_mapped_file_impl( storage_record_pb, "mockup", api::StorageFileType::flag_map); - ASSERT_TRUE(mapped_file.ok()); + ASSERT_TRUE(mapped_file_result.ok()); + auto mapped_file = std::unique_ptr<api::MappedStorageFile>(*mapped_file_result); auto context = api::get_flag_read_context(*mapped_file, 0, "none_exist"); ASSERT_TRUE(context.ok()); @@ -200,9 +205,10 @@ TEST_F(AconfigStorageTest, test_none_existent_flag_context_query) { /// Test to lock down storage flag value query api TEST_F(AconfigStorageTest, test_boolean_flag_value_query) { - auto mapped_file = private_api::get_mapped_file_impl( + auto mapped_file_result = private_api::get_mapped_file_impl( storage_record_pb, "mockup", api::StorageFileType::flag_val); - ASSERT_TRUE(mapped_file.ok()); + ASSERT_TRUE(mapped_file_result.ok()); + auto mapped_file = std::unique_ptr<api::MappedStorageFile>(*mapped_file_result); auto expected_value = std::vector<bool>{ false, true, true, false, true, true, true, true}; @@ -215,9 +221,10 @@ TEST_F(AconfigStorageTest, test_boolean_flag_value_query) { /// Negative test to lock down the error when querying flag value out of range TEST_F(AconfigStorageTest, test_invalid_boolean_flag_value_query) { - auto mapped_file = private_api::get_mapped_file_impl( + auto mapped_file_result = private_api::get_mapped_file_impl( storage_record_pb, "mockup", api::StorageFileType::flag_val); - ASSERT_TRUE(mapped_file.ok()); + ASSERT_TRUE(mapped_file_result.ok()); + auto mapped_file = std::unique_ptr<api::MappedStorageFile>(*mapped_file_result); auto value = api::get_boolean_flag_value(*mapped_file, 8); ASSERT_FALSE(value.ok()); @@ -227,12 +234,13 @@ TEST_F(AconfigStorageTest, test_invalid_boolean_flag_value_query) { /// Test to lock down storage flag info query api TEST_F(AconfigStorageTest, test_boolean_flag_info_query) { - auto mapped_file = private_api::get_mapped_file_impl( + auto mapped_file_result = private_api::get_mapped_file_impl( storage_record_pb, "mockup", api::StorageFileType::flag_info); - ASSERT_TRUE(mapped_file.ok()); + ASSERT_TRUE(mapped_file_result.ok()); + auto mapped_file = std::unique_ptr<api::MappedStorageFile>(*mapped_file_result); auto expected_value = std::vector<bool>{ - true, false, true, false, false, false, false, false}; + true, false, true, true, false, false, false, true}; for (int index = 0; index < 8; ++index) { auto attribute = api::get_flag_attribute(*mapped_file, api::FlagValueType::Boolean, index); ASSERT_TRUE(attribute.ok()); @@ -245,9 +253,10 @@ TEST_F(AconfigStorageTest, test_boolean_flag_info_query) { /// Negative test to lock down the error when querying flag info out of range TEST_F(AconfigStorageTest, test_invalid_boolean_flag_info_query) { - auto mapped_file = private_api::get_mapped_file_impl( + auto mapped_file_result = private_api::get_mapped_file_impl( storage_record_pb, "mockup", api::StorageFileType::flag_info); - ASSERT_TRUE(mapped_file.ok()); + ASSERT_TRUE(mapped_file_result.ok()); + auto mapped_file = std::unique_ptr<api::MappedStorageFile>(*mapped_file_result); auto attribute = api::get_flag_attribute(*mapped_file, api::FlagValueType::Boolean, 8); ASSERT_FALSE(attribute.ok()); diff --git a/tools/aconfig/aconfig_storage_read_api/tests/storage_read_api_test.rs b/tools/aconfig/aconfig_storage_read_api/tests/storage_read_api_test.rs index ce9c0186dd..ecba573d82 100644 --- a/tools/aconfig/aconfig_storage_read_api/tests/storage_read_api_test.rs +++ b/tools/aconfig/aconfig_storage_read_api/tests/storage_read_api_test.rs @@ -188,7 +188,7 @@ files {{ // The safety here is ensured as the test process will not write to temp storage file let flag_info_file = unsafe { get_mapped_file(&pb_file_path, "mockup", StorageFileType::FlagInfo).unwrap() }; - let is_rw: Vec<bool> = vec![true, false, true, false, false, false, false, false]; + let is_rw: Vec<bool> = vec![true, false, true, true, false, false, false, true]; for (offset, expected_value) in is_rw.into_iter().enumerate() { let attribute = get_flag_attribute(&flag_info_file, FlagValueType::Boolean, offset as u32).unwrap(); diff --git a/tools/aconfig/aconfig_storage_write_api/aconfig_storage_write_api.cpp b/tools/aconfig/aconfig_storage_write_api/aconfig_storage_write_api.cpp index cd57f4fb29..f529f7954c 100644 --- a/tools/aconfig/aconfig_storage_write_api/aconfig_storage_write_api.cpp +++ b/tools/aconfig/aconfig_storage_write_api/aconfig_storage_write_api.cpp @@ -18,7 +18,7 @@ using namespace android::base; namespace aconfig_storage { /// Map a storage file -Result<MutableMappedStorageFile> map_mutable_storage_file(std::string const& file) { +Result<MutableMappedStorageFile*> map_mutable_storage_file(std::string const& file) { struct stat file_stat; if (stat(file.c_str(), &file_stat) < 0) { return ErrnoError() << "stat failed"; @@ -41,9 +41,9 @@ Result<MutableMappedStorageFile> map_mutable_storage_file(std::string const& fil return ErrnoError() << "mmap failed"; } - auto mapped_file = MutableMappedStorageFile(); - mapped_file.file_ptr = map_result; - mapped_file.file_size = file_size; + auto mapped_file = new MutableMappedStorageFile(); + mapped_file->file_ptr = map_result; + mapped_file->file_size = file_size; return mapped_file; } diff --git a/tools/aconfig/aconfig_storage_write_api/include/aconfig_storage/aconfig_storage_write_api.hpp b/tools/aconfig/aconfig_storage_write_api/include/aconfig_storage/aconfig_storage_write_api.hpp index 7148396b82..ff06cbc6de 100644 --- a/tools/aconfig/aconfig_storage_write_api/include/aconfig_storage/aconfig_storage_write_api.hpp +++ b/tools/aconfig/aconfig_storage_write_api/include/aconfig_storage/aconfig_storage_write_api.hpp @@ -11,13 +11,10 @@ using namespace android::base; namespace aconfig_storage { /// Mapped flag value file -struct MutableMappedStorageFile{ - void* file_ptr; - size_t file_size; -}; +struct MutableMappedStorageFile : MappedStorageFile {}; /// Map a storage file -Result<MutableMappedStorageFile> map_mutable_storage_file( +Result<MutableMappedStorageFile*> map_mutable_storage_file( std::string const& file); /// Set boolean flag value diff --git a/tools/aconfig/aconfig_storage_write_api/tests/storage_write_api_test.cpp b/tools/aconfig/aconfig_storage_write_api/tests/storage_write_api_test.cpp index bd39e9e1de..54373798c9 100644 --- a/tools/aconfig/aconfig_storage_write_api/tests/storage_write_api_test.cpp +++ b/tools/aconfig/aconfig_storage_write_api/tests/storage_write_api_test.cpp @@ -78,15 +78,12 @@ TEST_F(AconfigStorageTest, test_non_writable_storage_file_mapping) { TEST_F(AconfigStorageTest, test_boolean_flag_value_update) { auto mapped_file_result = api::map_mutable_storage_file(flag_val); ASSERT_TRUE(mapped_file_result.ok()); + auto mapped_file = std::unique_ptr<api::MutableMappedStorageFile>(*mapped_file_result); - auto mapped_file = *mapped_file_result; for (int offset = 0; offset < 8; ++offset) { - auto update_result = api::set_boolean_flag_value(mapped_file, offset, true); + auto update_result = api::set_boolean_flag_value(*mapped_file, offset, true); ASSERT_TRUE(update_result.ok()); - auto ro_mapped_file = api::MappedStorageFile(); - ro_mapped_file.file_ptr = mapped_file.file_ptr; - ro_mapped_file.file_size = mapped_file.file_size; - auto value = api::get_boolean_flag_value(ro_mapped_file, offset); + auto value = api::get_boolean_flag_value(*mapped_file, offset); ASSERT_TRUE(value.ok()); ASSERT_TRUE(*value); } @@ -96,9 +93,8 @@ TEST_F(AconfigStorageTest, test_boolean_flag_value_update) { TEST_F(AconfigStorageTest, test_invalid_boolean_flag_value_update) { auto mapped_file_result = api::map_mutable_storage_file(flag_val); ASSERT_TRUE(mapped_file_result.ok()); - auto mapped_file = *mapped_file_result; - - auto update_result = api::set_boolean_flag_value(mapped_file, 8, true); + auto mapped_file = std::unique_ptr<api::MutableMappedStorageFile>(*mapped_file_result); + auto update_result = api::set_boolean_flag_value(*mapped_file, 8, true); ASSERT_FALSE(update_result.ok()); ASSERT_EQ(update_result.error().message(), std::string("InvalidStorageFileOffset(Flag value offset goes beyond the end of the file.)")); @@ -108,27 +104,22 @@ TEST_F(AconfigStorageTest, test_invalid_boolean_flag_value_update) { TEST_F(AconfigStorageTest, test_flag_has_server_override_update) { auto mapped_file_result = api::map_mutable_storage_file(flag_info); ASSERT_TRUE(mapped_file_result.ok()); - auto mapped_file = *mapped_file_result; + auto mapped_file = std::unique_ptr<api::MutableMappedStorageFile>(*mapped_file_result); for (int offset = 0; offset < 8; ++offset) { auto update_result = api::set_flag_has_server_override( - mapped_file, api::FlagValueType::Boolean, offset, true); + *mapped_file, api::FlagValueType::Boolean, offset, true); ASSERT_TRUE(update_result.ok()) << update_result.error(); - auto ro_mapped_file = api::MappedStorageFile(); - ro_mapped_file.file_ptr = mapped_file.file_ptr; - ro_mapped_file.file_size = mapped_file.file_size; auto attribute = api::get_flag_attribute( - ro_mapped_file, api::FlagValueType::Boolean, offset); + *mapped_file, api::FlagValueType::Boolean, offset); ASSERT_TRUE(attribute.ok()); ASSERT_TRUE(*attribute & api::FlagInfoBit::HasServerOverride); update_result = api::set_flag_has_server_override( - mapped_file, api::FlagValueType::Boolean, offset, false); + *mapped_file, api::FlagValueType::Boolean, offset, false); ASSERT_TRUE(update_result.ok()); - ro_mapped_file.file_ptr = mapped_file.file_ptr; - ro_mapped_file.file_size = mapped_file.file_size; attribute = api::get_flag_attribute( - ro_mapped_file, api::FlagValueType::Boolean, offset); + *mapped_file, api::FlagValueType::Boolean, offset); ASSERT_TRUE(attribute.ok()); ASSERT_FALSE(*attribute & api::FlagInfoBit::HasServerOverride); } @@ -138,27 +129,22 @@ TEST_F(AconfigStorageTest, test_flag_has_server_override_update) { TEST_F(AconfigStorageTest, test_flag_has_local_override_update) { auto mapped_file_result = api::map_mutable_storage_file(flag_info); ASSERT_TRUE(mapped_file_result.ok()); - auto mapped_file = *mapped_file_result; + auto mapped_file = std::unique_ptr<api::MutableMappedStorageFile>(*mapped_file_result); for (int offset = 0; offset < 8; ++offset) { auto update_result = api::set_flag_has_local_override( - mapped_file, api::FlagValueType::Boolean, offset, true); + *mapped_file, api::FlagValueType::Boolean, offset, true); ASSERT_TRUE(update_result.ok()); - auto ro_mapped_file = api::MappedStorageFile(); - ro_mapped_file.file_ptr = mapped_file.file_ptr; - ro_mapped_file.file_size = mapped_file.file_size; auto attribute = api::get_flag_attribute( - ro_mapped_file, api::FlagValueType::Boolean, offset); + *mapped_file, api::FlagValueType::Boolean, offset); ASSERT_TRUE(attribute.ok()); ASSERT_TRUE(*attribute & api::FlagInfoBit::HasLocalOverride); update_result = api::set_flag_has_local_override( - mapped_file, api::FlagValueType::Boolean, offset, false); + *mapped_file, api::FlagValueType::Boolean, offset, false); ASSERT_TRUE(update_result.ok()); - ro_mapped_file.file_ptr = mapped_file.file_ptr; - ro_mapped_file.file_size = mapped_file.file_size; attribute = api::get_flag_attribute( - ro_mapped_file, api::FlagValueType::Boolean, offset); + *mapped_file, api::FlagValueType::Boolean, offset); ASSERT_TRUE(attribute.ok()); ASSERT_FALSE(*attribute & api::FlagInfoBit::HasLocalOverride); } diff --git a/tools/aconfig/aflags/src/aconfig_storage_source.rs b/tools/aconfig/aflags/src/aconfig_storage_source.rs index a3ca221d9e..c21c5424bb 100644 --- a/tools/aconfig/aflags/src/aconfig_storage_source.rs +++ b/tools/aconfig/aflags/src/aconfig_storage_source.rs @@ -27,13 +27,13 @@ impl FlagSource for AconfigStorageSource { let container = file_info.container.ok_or(anyhow!("storage file is missing container"))?; - for (package, name, _flag_type, val) in + for listed_flag in aconfig_storage_file::list_flags(&package_map, &flag_map, &flag_val)? { result.push(Flag { - name: name.to_string(), - package: package.to_string(), - value: FlagValue::try_from(val.to_string().as_str())?, + name: listed_flag.flag_name, + package: listed_flag.package_name, + value: FlagValue::try_from(listed_flag.flag_value.as_str())?, container: container.to_string(), // TODO(b/324436145): delete namespace field once DeviceConfig isn't in CLI. diff --git a/tools/aconfig/aflags/src/main.rs b/tools/aconfig/aflags/src/main.rs index 4ce0d35ba1..516b773eaa 100644 --- a/tools/aconfig/aflags/src/main.rs +++ b/tools/aconfig/aflags/src/main.rs @@ -33,12 +33,12 @@ enum FlagPermission { ReadWrite, } -impl ToString for FlagPermission { - fn to_string(&self) -> String { - match &self { - Self::ReadOnly => "read-only".into(), - Self::ReadWrite => "read-write".into(), - } +impl std::fmt::Display for FlagPermission { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", match &self { + Self::ReadOnly => "read-only", + Self::ReadWrite => "read-write", + }) } } @@ -48,12 +48,12 @@ enum ValuePickedFrom { Server, } -impl ToString for ValuePickedFrom { - fn to_string(&self) -> String { - match &self { - Self::Default => "default".into(), - Self::Server => "server".into(), - } +impl std::fmt::Display for ValuePickedFrom { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", match &self { + Self::Default => "default", + Self::Server => "server", + }) } } @@ -75,12 +75,12 @@ impl TryFrom<&str> for FlagValue { } } -impl ToString for FlagValue { - fn to_string(&self) -> String { - match &self { - Self::Enabled => "enabled".into(), - Self::Disabled => "disabled".into(), - } +impl std::fmt::Display for FlagValue { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", match &self { + Self::Enabled => "enabled", + Self::Disabled => "disabled", + }) } } @@ -103,7 +103,7 @@ impl Flag { fn display_staged_value(&self) -> String { match self.staged_value { - Some(v) => format!("(->{})", v.to_string()), + Some(v) => format!("(->{})", v), None => "-".to_string(), } } diff --git a/tools/check-flagged-apis/check-flagged-apis.sh b/tools/check-flagged-apis/check-flagged-apis.sh index cd37a2d52e..d9934a11fe 100755 --- a/tools/check-flagged-apis/check-flagged-apis.sh +++ b/tools/check-flagged-apis/check-flagged-apis.sh @@ -20,18 +20,36 @@ source $(cd $(dirname $BASH_SOURCE) &> /dev/null && pwd)/../../shell_utils.sh require_top +PUBLIC_XML_VERSIONS=out/target/common/obj/PACKAGING/api_versions_public_generated-api-versions.xml +SYSTEM_XML_VERSIONS=out/target/common/obj/PACKAGING/api_versions_system_generated-api-versions.xml +SYSTEM_SERVER_XML_VERSONS=out/target/common/obj/PACKAGING/api_versions_system_server_complete_generated-api-versions.xml +MODULE_LIB_XML_VERSIONS=out/target/common/obj/PACKAGING/api_versions_module_lib_complete_generated-api-versions.xml + function m() { $(gettop)/build/soong/soong_ui.bash --build-mode --all-modules --dir="$(pwd)" "$@" } function build() { - m sdk dist && m \ + m \ check-flagged-apis \ all_aconfig_declarations \ frameworks-base-api-current.txt \ frameworks-base-api-system-current.txt \ frameworks-base-api-system-server-current.txt \ - frameworks-base-api-module-lib-current.txt + frameworks-base-api-module-lib-current.txt \ + $PUBLIC_XML_VERSIONS \ + $SYSTEM_XML_VERSIONS \ + $SYSTEM_SERVER_XML_VERSONS \ + $MODULE_LIB_XML_VERSIONS +} + +function aninja() { + local T="$(gettop)" + (\cd "${T}" && prebuilts/build-tools/linux-x86/bin/ninja -f out/combined-${TARGET_PRODUCT}.ninja "$@") +} + +function path_to_api_signature_file { + aninja -t query device_"$1"_all_targets | grep -A1 -e input: | tail -n1 } function run() { @@ -39,33 +57,33 @@ function run() { echo "# current" check-flagged-apis \ - --api-signature $(gettop)/out/target/product/mainline_x86/obj/ETC/frameworks-base-api-current.txt_intermediates/frameworks-base-api-current.txt \ + --api-signature $(path_to_api_signature_file "frameworks-base-api-current.txt") \ --flag-values $(gettop)/out/soong/.intermediates/all_aconfig_declarations.pb \ - --api-versions $(gettop)/out/dist/data/api-versions.xml + --api-versions $PUBLIC_XML_VERSIONS (( errors += $? )) echo echo "# system-current" check-flagged-apis \ - --api-signature $(gettop)/out/target/product/mainline_x86/obj/ETC/frameworks-base-api-system-current.txt_intermediates/frameworks-base-api-system-current.txt \ + --api-signature $(path_to_api_signature_file "frameworks-base-api-system-current.txt") \ --flag-values $(gettop)/out/soong/.intermediates/all_aconfig_declarations.pb \ - --api-versions $(gettop)/out/dist/system-data/api-versions.xml + --api-versions $SYSTEM_XML_VERSIONS (( errors += $? )) echo echo "# system-server-current" check-flagged-apis \ - --api-signature $(gettop)/out/target/product/mainline_x86/obj/ETC/frameworks-base-api-system-server-current.txt_intermediates/frameworks-base-api-system-server-current.txt \ + --api-signature $(path_to_api_signature_file "frameworks-base-api-system-server-current.txt") \ --flag-values $(gettop)/out/soong/.intermediates/all_aconfig_declarations.pb \ - --api-versions $(gettop)/out/dist/system-server-data/api-versions.xml + --api-versions $SYSTEM_SERVER_XML_VERSONS (( errors += $? )) echo echo "# module-lib" check-flagged-apis \ - --api-signature $(gettop)/out/target/product/mainline_x86/obj/ETC/frameworks-base-api-module-lib-current.txt_intermediates/frameworks-base-api-module-lib-current.txt \ + --api-signature $(path_to_api_signature_file "frameworks-base-api-module-lib-current.txt") \ --flag-values $(gettop)/out/soong/.intermediates/all_aconfig_declarations.pb \ - --api-versions $(gettop)/out/dist/module-lib-data/api-versions.xml + --api-versions $MODULE_LIB_XML_VERSIONS (( errors += $? )) return $errors diff --git a/tools/check-flagged-apis/src/com/android/checkflaggedapis/CheckFlaggedApisTest.kt b/tools/check-flagged-apis/src/com/android/checkflaggedapis/CheckFlaggedApisTest.kt index 5d87a4c754..111ea91f85 100644 --- a/tools/check-flagged-apis/src/com/android/checkflaggedapis/CheckFlaggedApisTest.kt +++ b/tools/check-flagged-apis/src/com/android/checkflaggedapis/CheckFlaggedApisTest.kt @@ -16,6 +16,8 @@ package com.android.checkflaggedapis import android.aconfig.Aconfig +import android.aconfig.Aconfig.flag_state.DISABLED +import android.aconfig.Aconfig.flag_state.ENABLED import java.io.ByteArrayInputStream import java.io.ByteArrayOutputStream import java.io.InputStream @@ -28,9 +30,15 @@ private val API_SIGNATURE = """ // Signature format: 2.0 package android { - public final class Clazz { - ctor public Clazz(); + @FlaggedApi("android.flag.foo") public final class Clazz { + ctor @FlaggedApi("android.flag.foo") public Clazz(); field @FlaggedApi("android.flag.foo") public static final int FOO = 1; // 0x1 + method @FlaggedApi("android.flag.foo") public int getErrorCode(); + method @FlaggedApi("android.flag.foo") public boolean setData(int, int[][], @NonNull android.util.Utility<T, U>); + method @FlaggedApi("android.flag.foo") public boolean setVariableData(int, android.util.Atom...); + method @FlaggedApi("android.flag.foo") public boolean innerClassArg(android.Clazz.Builder); + } + @FlaggedApi("android.flag.bar") public static class Clazz.Builder { } } """ @@ -41,15 +49,26 @@ private val API_VERSIONS = <?xml version="1.0" encoding="utf-8"?> <api version="3"> <class name="android/Clazz" since="1"> + <extends name="java/lang/Object"/> <method name="<init>()V"/> <field name="FOO"/> + <method name="getErrorCode()I"/> + <method name="setData(I[[ILandroid/util/Utility;)Z"/> + <method name="setVariableData(I[Landroid/util/Atom;)Z"/> + <method name="innerClassArg(Landroid/Clazz${"$"}Builder;)"/> + </class> + <class name="android/Clazz${"$"}Builder" since="2"> + <extends name="java/lang/Object"/> </class> </api> """ .trim() -private fun generateFlagsProto(fooState: Aconfig.flag_state): InputStream { - val parsed_flag = +private fun generateFlagsProto( + fooState: Aconfig.flag_state, + barState: Aconfig.flag_state +): InputStream { + val fooFlag = Aconfig.parsed_flag .newBuilder() .setPackage("android.flag") @@ -57,9 +76,18 @@ private fun generateFlagsProto(fooState: Aconfig.flag_state): InputStream { .setState(fooState) .setPermission(Aconfig.flag_permission.READ_ONLY) .build() - val parsed_flags = Aconfig.parsed_flags.newBuilder().addParsedFlag(parsed_flag).build() + val barFlag = + Aconfig.parsed_flag + .newBuilder() + .setPackage("android.flag") + .setName("bar") + .setState(barState) + .setPermission(Aconfig.flag_permission.READ_ONLY) + .build() + val flags = + Aconfig.parsed_flags.newBuilder().addParsedFlag(fooFlag).addParsedFlag(barFlag).build() val binaryProto = ByteArrayOutputStream() - parsed_flags.writeTo(binaryProto) + flags.writeTo(binaryProto) return ByteArrayInputStream(binaryProto.toByteArray()) } @@ -67,45 +95,246 @@ private fun generateFlagsProto(fooState: Aconfig.flag_state): InputStream { class CheckFlaggedApisTest { @Test fun testParseApiSignature() { - val expected = setOf(Pair(Symbol("android.Clazz.FOO"), Flag("android.flag.foo"))) + val expected = + setOf( + Pair( + Symbol.createClass("android/Clazz", "java/lang/Object", setOf()), + Flag("android.flag.foo")), + Pair(Symbol.createMethod("android/Clazz", "Clazz()"), Flag("android.flag.foo")), + Pair(Symbol.createField("android/Clazz", "FOO"), Flag("android.flag.foo")), + Pair(Symbol.createMethod("android/Clazz", "getErrorCode()"), Flag("android.flag.foo")), + Pair( + Symbol.createMethod("android/Clazz", "setData(I[[ILandroid/util/Utility;)"), + Flag("android.flag.foo")), + Pair( + Symbol.createMethod("android/Clazz", "setVariableData(I[Landroid/util/Atom;)"), + Flag("android.flag.foo")), + Pair( + Symbol.createMethod("android/Clazz", "innerClassArg(Landroid/Clazz/Builder;)"), + Flag("android.flag.foo")), + Pair( + Symbol.createClass("android/Clazz/Builder", "java/lang/Object", setOf()), + Flag("android.flag.bar")), + ) val actual = parseApiSignature("in-memory", API_SIGNATURE.byteInputStream()) assertEquals(expected, actual) } @Test fun testParseFlagValues() { - val expected: Map<Flag, Boolean> = mapOf(Flag("android.flag.foo") to true) - val actual = parseFlagValues(generateFlagsProto(Aconfig.flag_state.ENABLED)) + val expected: Map<Flag, Boolean> = + mapOf(Flag("android.flag.foo") to true, Flag("android.flag.bar") to true) + val actual = parseFlagValues(generateFlagsProto(ENABLED, ENABLED)) assertEquals(expected, actual) } @Test fun testParseApiVersions() { - val expected: Set<Symbol> = setOf(Symbol("android.Clazz.FOO")) + val expected: Set<Symbol> = + setOf( + Symbol.createClass("android/Clazz", "java/lang/Object", setOf()), + Symbol.createMethod("android/Clazz", "Clazz()"), + Symbol.createField("android/Clazz", "FOO"), + Symbol.createMethod("android/Clazz", "getErrorCode()"), + Symbol.createMethod("android/Clazz", "setData(I[[ILandroid/util/Utility;)"), + Symbol.createMethod("android/Clazz", "setVariableData(I[Landroid/util/Atom;)"), + Symbol.createMethod("android/Clazz", "innerClassArg(Landroid/Clazz/Builder;)"), + Symbol.createClass("android/Clazz/Builder", "java/lang/Object", setOf()), + ) val actual = parseApiVersions(API_VERSIONS.byteInputStream()) assertEquals(expected, actual) } @Test + fun testParseApiVersionsNestedClasses() { + val apiVersions = + """ + <?xml version="1.0" encoding="utf-8"?> + <api version="3"> + <class name="android/Clazz${'$'}Foo${'$'}Bar" since="1"> + <extends name="java/lang/Object"/> + <method name="<init>()V"/> + </class> + </api> + """ + .trim() + val expected: Set<Symbol> = + setOf( + Symbol.createClass("android/Clazz/Foo/Bar", "java/lang/Object", setOf()), + Symbol.createMethod("android/Clazz/Foo/Bar", "Bar()"), + ) + val actual = parseApiVersions(apiVersions.byteInputStream()) + assertEquals(expected, actual) + } + + @Test fun testFindErrorsNoErrors() { val expected = setOf<ApiError>() val actual = findErrors( parseApiSignature("in-memory", API_SIGNATURE.byteInputStream()), - parseFlagValues(generateFlagsProto(Aconfig.flag_state.ENABLED)), + parseFlagValues(generateFlagsProto(ENABLED, ENABLED)), parseApiVersions(API_VERSIONS.byteInputStream())) assertEquals(expected, actual) } @Test + fun testFindErrorsVerifyImplements() { + val apiSignature = + """ + // Signature format: 2.0 + package android { + @FlaggedApi("android.flag.foo") public final class Clazz implements android.Interface { + method @FlaggedApi("android.flag.foo") public boolean foo(); + method @FlaggedApi("android.flag.foo") public boolean bar(); + } + public interface Interface { + method public boolean bar(); + } + } + """ + .trim() + + val apiVersions = + """ + <?xml version="1.0" encoding="utf-8"?> + <api version="3"> + <class name="android/Clazz" since="1"> + <extends name="java/lang/Object"/> + <implements name="android/Interface"/> + <method name="foo()Z"/> + </class> + <class name="android/Interface" since="1"> + <method name="bar()Z"/> + </class> + </api> + """ + .trim() + + val expected = setOf<ApiError>() + val actual = + findErrors( + parseApiSignature("in-memory", apiSignature.byteInputStream()), + parseFlagValues(generateFlagsProto(ENABLED, ENABLED)), + parseApiVersions(apiVersions.byteInputStream())) + assertEquals(expected, actual) + } + + @Test + fun testFindErrorsVerifySuperclass() { + val apiSignature = + """ + // Signature format: 2.0 + package android { + @FlaggedApi("android.flag.foo") public final class C extends android.B { + method @FlaggedApi("android.flag.foo") public boolean c(); + method @FlaggedApi("android.flag.foo") public boolean b(); + method @FlaggedApi("android.flag.foo") public boolean a(); + } + public final class B extends android.A { + method public boolean b(); + } + public final class A { + method public boolean a(); + } + } + """ + .trim() + + val apiVersions = + """ + <?xml version="1.0" encoding="utf-8"?> + <api version="3"> + <class name="android/C" since="1"> + <extends name="android/B"/> + <method name="c()Z"/> + </class> + <class name="android/B" since="1"> + <extends name="android/A"/> + <method name="b()Z"/> + </class> + <class name="android/A" since="1"> + <method name="a()Z"/> + </class> + </api> + """ + .trim() + + val expected = setOf<ApiError>() + val actual = + findErrors( + parseApiSignature("in-memory", apiSignature.byteInputStream()), + parseFlagValues(generateFlagsProto(ENABLED, ENABLED)), + parseApiVersions(apiVersions.byteInputStream())) + assertEquals(expected, actual) + } + + @Test + fun testNestedFlagsOuterFlagWins() { + val apiSignature = + """ + // Signature format: 2.0 + package android { + @FlaggedApi("android.flag.foo") public final class A { + method @FlaggedApi("android.flag.bar") public boolean method(); + } + @FlaggedApi("android.flag.bar") public final class B { + method @FlaggedApi("android.flag.foo") public boolean method(); + } + } + """ + .trim() + + val apiVersions = + """ + <?xml version="1.0" encoding="utf-8"?> + <api version="3"> + <class name="android/B" since="1"> + <extends name="java/lang/Object"/> + </class> + </api> + """ + .trim() + + val expected = setOf<ApiError>() + val actual = + findErrors( + parseApiSignature("in-memory", apiSignature.byteInputStream()), + parseFlagValues(generateFlagsProto(DISABLED, ENABLED)), + parseApiVersions(apiVersions.byteInputStream())) + assertEquals(expected, actual) + } + + @Test fun testFindErrorsDisabledFlaggedApiIsPresent() { val expected = setOf<ApiError>( - DisabledFlaggedApiIsPresentError(Symbol("android.Clazz.FOO"), Flag("android.flag.foo"))) + DisabledFlaggedApiIsPresentError( + Symbol.createClass("android/Clazz", "java/lang/Object", setOf()), + Flag("android.flag.foo")), + DisabledFlaggedApiIsPresentError( + Symbol.createMethod("android/Clazz", "Clazz()"), Flag("android.flag.foo")), + DisabledFlaggedApiIsPresentError( + Symbol.createField("android/Clazz", "FOO"), Flag("android.flag.foo")), + DisabledFlaggedApiIsPresentError( + Symbol.createMethod("android/Clazz", "getErrorCode()"), Flag("android.flag.foo")), + DisabledFlaggedApiIsPresentError( + Symbol.createMethod("android/Clazz", "setData(I[[ILandroid/util/Utility;)"), + Flag("android.flag.foo")), + DisabledFlaggedApiIsPresentError( + Symbol.createMethod("android/Clazz", "setVariableData(I[Landroid/util/Atom;)"), + Flag("android.flag.foo")), + DisabledFlaggedApiIsPresentError( + Symbol.createMethod("android/Clazz", "innerClassArg(Landroid/Clazz/Builder;)"), + Flag("android.flag.foo")), + DisabledFlaggedApiIsPresentError( + Symbol.createClass("android/Clazz/Builder", "java/lang/Object", setOf()), + Flag("android.flag.bar")), + ) val actual = findErrors( parseApiSignature("in-memory", API_SIGNATURE.byteInputStream()), - parseFlagValues(generateFlagsProto(Aconfig.flag_state.DISABLED)), + parseFlagValues(generateFlagsProto(DISABLED, DISABLED)), parseApiVersions(API_VERSIONS.byteInputStream())) assertEquals(expected, actual) } diff --git a/tools/check-flagged-apis/src/com/android/checkflaggedapis/Main.kt b/tools/check-flagged-apis/src/com/android/checkflaggedapis/Main.kt index 84564ba34c..a277ce815f 100644 --- a/tools/check-flagged-apis/src/com/android/checkflaggedapis/Main.kt +++ b/tools/check-flagged-apis/src/com/android/checkflaggedapis/Main.kt @@ -19,7 +19,10 @@ package com.android.checkflaggedapis import android.aconfig.Aconfig import com.android.tools.metalava.model.BaseItemVisitor +import com.android.tools.metalava.model.ClassItem import com.android.tools.metalava.model.FieldItem +import com.android.tools.metalava.model.Item +import com.android.tools.metalava.model.MethodItem import com.android.tools.metalava.model.text.ApiFile import com.github.ajalt.clikt.core.CliktCommand import com.github.ajalt.clikt.core.ProgramResult @@ -38,34 +41,61 @@ import org.w3c.dom.Node * a Java symbol slightly differently. To keep things consistent, all parsed APIs are converted to * Symbols. * - * All parts of the fully qualified name of the Symbol are separated by a dot, e.g.: + * Symbols are encoded using the format similar to the one described in section 4.3.2 of the JVM + * spec [1], that is, "package.class.inner-class.method(int, int[], android.util.Clazz)" is + * represented as * <pre> - * package.class.inner-class.field - * </pre> + * package.class.inner-class.method(II[Landroid/util/Clazz;) + * <pre> + * + * Where possible, the format has been simplified (to make translation of the + * various input formats easier): for instance, only / is used as delimiter (# + * and $ are never used). + * + * 1. https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.3.2 */ -@JvmInline -internal value class Symbol(val name: String) { +internal sealed class Symbol { companion object { - private val FORBIDDEN_CHARS = listOf('/', '#', '$') + private val FORBIDDEN_CHARS = listOf('#', '$', '.') + + fun createClass(clazz: String, superclass: String?, interfaces: Set<String>): Symbol { + return ClassSymbol( + toInternalFormat(clazz), + superclass?.let { toInternalFormat(it) }, + interfaces.map { toInternalFormat(it) }.toSet()) + } + + fun createField(clazz: String, field: String): Symbol { + require(!field.contains("(") && !field.contains(")")) + return MemberSymbol(toInternalFormat(clazz), toInternalFormat(field)) + } - /** Create a new Symbol from a String that may include delimiters other than dot. */ - fun create(name: String): Symbol { - var sanitizedName = name + fun createMethod(clazz: String, method: String): Symbol { + return MemberSymbol(toInternalFormat(clazz), toInternalFormat(method)) + } + + protected fun toInternalFormat(name: String): String { + var internalName = name for (ch in FORBIDDEN_CHARS) { - sanitizedName = sanitizedName.replace(ch, '.') + internalName = internalName.replace(ch, '/') } - return Symbol(sanitizedName) + return internalName } } - init { - require(!name.isEmpty()) { "empty string" } - for (ch in FORBIDDEN_CHARS) { - require(!name.contains(ch)) { "$name: contains $ch" } - } - } + abstract fun toPrettyString(): String +} - override fun toString(): String = name.toString() +internal data class ClassSymbol( + val clazz: String, + val superclass: String?, + val interfaces: Set<String> +) : Symbol() { + override fun toPrettyString(): String = "$clazz" +} + +internal data class MemberSymbol(val clazz: String, val member: String) : Symbol() { + override fun toPrettyString(): String = "$clazz/$member" } /** @@ -91,7 +121,7 @@ internal data class EnabledFlaggedApiNotPresentError( override val flag: Flag ) : ApiError() { override fun toString(): String { - return "error: enabled @FlaggedApi not present in built artifact: symbol=$symbol flag=$flag" + return "error: enabled @FlaggedApi not present in built artifact: symbol=${symbol.toPrettyString()} flag=$flag" } } @@ -100,14 +130,14 @@ internal data class DisabledFlaggedApiIsPresentError( override val flag: Flag ) : ApiError() { override fun toString(): String { - return "error: disabled @FlaggedApi is present in built artifact: symbol=$symbol flag=$flag" + return "error: disabled @FlaggedApi is present in built artifact: symbol=${symbol.toPrettyString()} flag=$flag" } } internal data class UnknownFlagError(override val symbol: Symbol, override val flag: Flag) : ApiError() { override fun toString(): String { - return "error: unknown flag: symbol=$symbol flag=$flag" + return "error: unknown flag: symbol=${symbol.toPrettyString()} flag=$flag" } } @@ -167,22 +197,51 @@ The tool will exit with a non-zero exit code if any flagged APIs are found to be } internal fun parseApiSignature(path: String, input: InputStream): Set<Pair<Symbol, Flag>> { - // TODO(334870672): add support for classes and metods val output = mutableSetOf<Pair<Symbol, Flag>>() val visitor = object : BaseItemVisitor() { + override fun visitClass(cls: ClassItem) { + getFlagOrNull(cls)?.let { flag -> + val symbol = + Symbol.createClass( + cls.baselineElementId(), + cls.superClass()?.baselineElementId(), + cls.allInterfaces() + .map { it.baselineElementId() } + .filter { it != cls.baselineElementId() } + .toSet()) + output.add(Pair(symbol, flag)) + } + } + override fun visitField(field: FieldItem) { - val flag = - field.modifiers - .findAnnotation("android.annotation.FlaggedApi") - ?.findAttribute("value") - ?.value - ?.value() as? String - if (flag != null) { - val symbol = Symbol.create(field.baselineElementId()) - output.add(Pair(symbol, Flag(flag))) + getFlagOrNull(field)?.let { flag -> + val symbol = + Symbol.createField(field.containingClass().baselineElementId(), field.name()) + output.add(Pair(symbol, flag)) + } + } + + override fun visitMethod(method: MethodItem) { + getFlagOrNull(method)?.let { flag -> + val methodName = buildString { + append(method.name()) + append("(") + method.parameters().joinTo(this, separator = "") { it.type().internalName() } + append(")") + } + val symbol = Symbol.createMethod(method.containingClass().qualifiedName(), methodName) + output.add(Pair(symbol, flag)) } } + + private fun getFlagOrNull(item: Item): Flag? { + return item.modifiers + .findAnnotation("android.annotation.FlaggedApi") + ?.findAttribute("value") + ?.value + ?.let { Flag(it.value() as String) } + } } val codebase = ApiFile.parseApi(path, input) codebase.accept(visitor) @@ -203,16 +262,78 @@ internal fun parseApiVersions(input: InputStream): Set<Symbol> { val factory = DocumentBuilderFactory.newInstance() val parser = factory.newDocumentBuilder() val document = parser.parse(input) + + val classes = document.getElementsByTagName("class") + // ktfmt doesn't understand the `..<` range syntax; explicitly call .rangeUntil instead + for (i in 0.rangeUntil(classes.getLength())) { + val cls = classes.item(i) + val className = + requireNotNull(cls.getAttribute("name")) { + "Bad XML: <class> element without name attribute" + } + var superclass: String? = null + val interfaces = mutableSetOf<String>() + val children = cls.getChildNodes() + for (j in 0.rangeUntil(children.getLength())) { + val child = children.item(j) + when (child.getNodeName()) { + "extends" -> { + superclass = + requireNotNull(child.getAttribute("name")) { + "Bad XML: <extends> element without name attribute" + } + } + "implements" -> { + val interfaceName = + requireNotNull(child.getAttribute("name")) { + "Bad XML: <implements> element without name attribute" + } + interfaces.add(interfaceName) + } + } + } + output.add(Symbol.createClass(className, superclass, interfaces)) + } + val fields = document.getElementsByTagName("field") // ktfmt doesn't understand the `..<` range syntax; explicitly call .rangeUntil instead for (i in 0.rangeUntil(fields.getLength())) { val field = fields.item(i) - val fieldName = field.getAttribute("name") + val fieldName = + requireNotNull(field.getAttribute("name")) { + "Bad XML: <field> element without name attribute" + } val className = - requireNotNull(field.getParentNode()) { "Bad XML: top level <field> element" } - .getAttribute("name") - output.add(Symbol.create("$className.$fieldName")) + requireNotNull(field.getParentNode()?.getAttribute("name")) { + "Bad XML: top level <field> element" + } + output.add(Symbol.createField(className, fieldName)) } + + val methods = document.getElementsByTagName("method") + // ktfmt doesn't understand the `..<` range syntax; explicitly call .rangeUntil instead + for (i in 0.rangeUntil(methods.getLength())) { + val method = methods.item(i) + val methodSignature = + requireNotNull(method.getAttribute("name")) { + "Bad XML: <method> element without name attribute" + } + val methodSignatureParts = methodSignature.split(Regex("\\(|\\)")) + if (methodSignatureParts.size != 3) { + throw Exception("Bad XML: method signature '$methodSignature'") + } + var (methodName, methodArgs, _) = methodSignatureParts + val packageAndClassName = + requireNotNull(method.getParentNode()?.getAttribute("name")) { + "Bad XML: top level <method> element, or <class> element missing name attribute" + } + .replace("$", "/") + if (methodName == "<init>") { + methodName = packageAndClassName.split("/").last() + } + output.add(Symbol.createMethod(packageAndClassName, "$methodName($methodArgs)")) + } + return output } @@ -229,15 +350,88 @@ internal fun findErrors( flags: Map<Flag, Boolean>, symbolsInOutput: Set<Symbol> ): Set<ApiError> { + fun Set<Symbol>.containsSymbol(symbol: Symbol): Boolean { + // trivial case: the symbol is explicitly listed in api-versions.xml + if (contains(symbol)) { + return true + } + + // non-trivial case: the symbol could be part of the surrounding class' + // super class or interfaces + val (className, memberName) = + when (symbol) { + is ClassSymbol -> return false + is MemberSymbol -> { + Pair(symbol.clazz, symbol.member) + } + } + val clazz = find { it is ClassSymbol && it.clazz == className } as? ClassSymbol? + if (clazz == null) { + return false + } + + for (interfaceName in clazz.interfaces) { + // createMethod is the same as createField, except it allows parenthesis + val interfaceSymbol = Symbol.createMethod(interfaceName, memberName) + if (contains(interfaceSymbol)) { + return true + } + } + + if (clazz.superclass != null) { + val superclassSymbol = Symbol.createMethod(clazz.superclass, memberName) + return containsSymbol(superclassSymbol) + } + + return false + } + + /** + * Returns whether the given flag is enabled for the given symbol. + * + * A flagged member inside a flagged class is ignored (and the flag value considered disabled) if + * the class' flag is disabled. + * + * @param symbol the symbol to check + * @param flag the flag to check + * @return whether the flag is enabled for the given symbol + */ + fun isFlagEnabledForSymbol(symbol: Symbol, flag: Flag): Boolean { + when (symbol) { + is ClassSymbol -> return flags.getValue(flag) + is MemberSymbol -> { + val memberFlagValue = flags.getValue(flag) + if (!memberFlagValue) { + return false + } + // Special case: if the MemberSymbol's flag is enabled, but the outer + // ClassSymbol's flag (if the class is flagged) is disabled, consider + // the MemberSymbol's flag as disabled: + // + // @FlaggedApi(this-flag-is-disabled) Clazz { + // @FlaggedApi(this-flag-is-enabled) method(); // The Clazz' flag "wins" + // } + // + // Note: the current implementation does not handle nested classes. + val classFlagValue = + flaggedSymbolsInSource + .find { it.first.toPrettyString() == symbol.clazz } + ?.let { flags.getValue(it.second) } + ?: true + return classFlagValue + } + } + } + val errors = mutableSetOf<ApiError>() for ((symbol, flag) in flaggedSymbolsInSource) { try { - if (flags.getValue(flag)) { - if (!symbolsInOutput.contains(symbol)) { + if (isFlagEnabledForSymbol(symbol, flag)) { + if (!symbolsInOutput.containsSymbol(symbol)) { errors.add(EnabledFlaggedApiNotPresentError(symbol, flag)) } } else { - if (symbolsInOutput.contains(symbol)) { + if (symbolsInOutput.containsSymbol(symbol)) { errors.add(DisabledFlaggedApiIsPresentError(symbol, flag)) } } diff --git a/tools/fs_config/Android.bp b/tools/fs_config/Android.bp index bd9543a2e2..6aa528963d 100644 --- a/tools/fs_config/Android.bp +++ b/tools/fs_config/Android.bp @@ -258,3 +258,173 @@ prebuilt_etc { system_ext_specific: true, src: ":group_gen_system_ext", } + +fs_config_cmd = "$(location fs_config_generator) fsconfig " + + "--aid-header $(location :android_filesystem_config_header) " + + "--capability-header $(location :linux_capability_header) " + + "--out_file $(out) " +fs_config_cmd_dirs = fs_config_cmd + "--dirs " +fs_config_cmd_files = fs_config_cmd + "--files " + +genrule_defaults { + name: "fs_config_defaults", + tools: ["fs_config_generator"], + srcs: [ + ":android_filesystem_config_header", + ":linux_capability_header", + ":target_fs_config_gen", + ], + out: ["out"], +} + +genrule { + name: "fs_config_dirs_system_gen", + defaults: ["fs_config_defaults"], + cmd: fs_config_cmd_dirs + + "--partition system " + + "--all-partitions vendor,oem,odm,vendor_dlkm,odm_dlkm,system_dlkm " + + "$(locations :target_fs_config_gen)", +} + +prebuilt_etc { + name: "fs_config_dirs_system", + filename: "fs_config_dirs", + src: ":fs_config_dirs_system_gen", +} + +genrule { + name: "fs_config_files_system_gen", + defaults: ["fs_config_defaults"], + cmd: fs_config_cmd_files + + "--partition system " + + "--all-partitions vendor,oem,odm,vendor_dlkm,odm_dlkm,system_dlkm " + + "$(locations :target_fs_config_gen)", +} + +prebuilt_etc { + name: "fs_config_files_system", + filename: "fs_config_files", + src: ":fs_config_files_system_gen", +} + +genrule { + name: "fs_config_dirs_system_ext_gen", + defaults: ["fs_config_defaults"], + cmd: fs_config_cmd_dirs + + "--partition system_ext " + + "$(locations :target_fs_config_gen)", +} + +prebuilt_etc { + name: "fs_config_dirs_system_ext", + filename: "fs_config_dirs", + src: ":fs_config_dirs_system_ext_gen", + system_ext_specific: true, +} + +genrule { + name: "fs_config_files_system_ext_gen", + defaults: ["fs_config_defaults"], + cmd: fs_config_cmd_files + + "--partition system_ext " + + "$(locations :target_fs_config_gen)", +} + +prebuilt_etc { + name: "fs_config_files_system_ext", + filename: "fs_config_files", + src: ":fs_config_files_system_ext_gen", + system_ext_specific: true, +} + +genrule { + name: "fs_config_dirs_product_gen", + defaults: ["fs_config_defaults"], + cmd: fs_config_cmd_dirs + + "--partition product " + + "$(locations :target_fs_config_gen)", +} + +prebuilt_etc { + name: "fs_config_dirs_product", + filename: "fs_config_dirs", + src: ":fs_config_dirs_product_gen", + product_specific: true, +} + +genrule { + name: "fs_config_files_product_gen", + defaults: ["fs_config_defaults"], + cmd: fs_config_cmd_files + + "--partition product " + + "$(locations :target_fs_config_gen)", +} + +prebuilt_etc { + name: "fs_config_files_product", + filename: "fs_config_files", + src: ":fs_config_files_product_gen", + product_specific: true, +} + +genrule { + name: "fs_config_dirs_vendor_gen", + defaults: ["fs_config_defaults"], + cmd: fs_config_cmd_dirs + + "--partition vendor " + + "$(locations :target_fs_config_gen)", +} + +prebuilt_etc { + name: "fs_config_dirs_vendor", + filename: "fs_config_dirs", + src: ":fs_config_dirs_vendor_gen", + vendor: true, +} + +genrule { + name: "fs_config_files_vendor_gen", + defaults: ["fs_config_defaults"], + cmd: fs_config_cmd_files + + "--partition vendor " + + "$(locations :target_fs_config_gen)", +} + +prebuilt_etc { + name: "fs_config_files_vendor", + filename: "fs_config_files", + src: ":fs_config_files_vendor_gen", + vendor: true, +} + +genrule { + name: "fs_config_dirs_odm_gen", + defaults: ["fs_config_defaults"], + cmd: fs_config_cmd_dirs + + "--partition odm " + + "$(locations :target_fs_config_gen)", +} + +prebuilt_etc { + name: "fs_config_dirs_odm", + filename: "fs_config_dirs", + src: ":fs_config_dirs_odm_gen", + device_specific: true, +} + +genrule { + name: "fs_config_files_odm_gen", + defaults: ["fs_config_defaults"], + cmd: fs_config_cmd_files + + "--partition odm " + + "$(locations :target_fs_config_gen)", +} + +prebuilt_etc { + name: "fs_config_files_odm", + filename: "fs_config_files", + src: ":fs_config_files_odm_gen", + device_specific: true, +} + +// TODO(jiyong): add fs_config for oem, system_dlkm, vendor_dlkm, odm_dlkm partitions diff --git a/tools/fs_config/Android.mk b/tools/fs_config/Android.mk index c36c3aa6a2..e4c362630f 100644 --- a/tools/fs_config/Android.mk +++ b/tools/fs_config/Android.mk @@ -24,23 +24,8 @@ ifneq ($(wildcard $(TARGET_DEVICE_DIR)/android_filesystem_config.h),) $(error Using $(TARGET_DEVICE_DIR)/android_filesystem_config.h is deprecated, please use TARGET_FS_CONFIG_GEN instead) endif -system_android_filesystem_config := system/core/libcutils/include/private/android_filesystem_config.h -system_capability_header := bionic/libc/kernel/uapi/linux/capability.h - -# Use snapshots if exist -vendor_android_filesystem_config := $(strip \ - $(if $(filter-out current,$(BOARD_VNDK_VERSION)), \ - $(SOONG_VENDOR_$(BOARD_VNDK_VERSION)_SNAPSHOT_DIR)/include/$(system_android_filesystem_config))) -ifeq (,$(wildcard $(vendor_android_filesystem_config))) -vendor_android_filesystem_config := $(system_android_filesystem_config) -endif - -vendor_capability_header := $(strip \ - $(if $(filter-out current,$(BOARD_VNDK_VERSION)), \ - $(SOONG_VENDOR_$(BOARD_VNDK_VERSION)_SNAPSHOT_DIR)/include/$(system_capability_header))) -ifeq (,$(wildcard $(vendor_capability_header))) -vendor_capability_header := $(system_capability_header) -endif +android_filesystem_config := system/core/libcutils/include/private/android_filesystem_config.h +capability_header := bionic/libc/kernel/uapi/linux/capability.h # List of supported vendor, oem, odm, vendor_dlkm, odm_dlkm, and system_dlkm Partitions fs_config_generate_extra_partition_list := $(strip \ @@ -85,58 +70,6 @@ LOCAL_REQUIRED_MODULES := \ include $(BUILD_PHONY_PACKAGE) ################################## -# Generate the system_ext/etc/fs_config_dirs binary file for the target if the -# system_ext partition is generated. Add fs_config_dirs or fs_config_dirs_system_ext -# to PRODUCT_PACKAGES in the device make file to enable. -include $(CLEAR_VARS) - -LOCAL_MODULE := fs_config_dirs_system_ext -LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 -LOCAL_LICENSE_CONDITIONS := notice -LOCAL_NOTICE_FILE := build/soong/licenses/LICENSE -LOCAL_REQUIRED_MODULES := $(if $(BOARD_USES_SYSTEM_EXTIMAGE)$(BOARD_SYSTEM_EXTIMAGE_FILE_SYSTEM_TYPE),_fs_config_dirs_system_ext) -include $(BUILD_PHONY_PACKAGE) - -################################## -# Generate the system_ext/etc/fs_config_files binary file for the target if the -# system_ext partition is generated. Add fs_config_files or fs_config_files_system_ext -# to PRODUCT_PACKAGES in the device make file to enable. -include $(CLEAR_VARS) - -LOCAL_MODULE := fs_config_files_system_ext -LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 -LOCAL_LICENSE_CONDITIONS := notice -LOCAL_NOTICE_FILE := build/soong/licenses/LICENSE -LOCAL_REQUIRED_MODULES := $(if $(BOARD_USES_SYSTEM_EXTIMAGE)$(BOARD_SYSTEM_EXTIMAGE_FILE_SYSTEM_TYPE),_fs_config_files_system_ext) -include $(BUILD_PHONY_PACKAGE) - -################################## -# Generate the product/etc/fs_config_dirs binary file for the target if the -# product partition is generated. Add fs_config_dirs or fs_config_dirs_product -# to PRODUCT_PACKAGES in the device make file to enable. -include $(CLEAR_VARS) - -LOCAL_MODULE := fs_config_dirs_product -LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 -LOCAL_LICENSE_CONDITIONS := notice -LOCAL_NOTICE_FILE := build/soong/licenses/LICENSE -LOCAL_REQUIRED_MODULES := $(if $(BOARD_USES_PRODUCTIMAGE)$(BOARD_PRODUCTIMAGE_FILE_SYSTEM_TYPE),_fs_config_dirs_product) -include $(BUILD_PHONY_PACKAGE) - -################################## -# Generate the product/etc/fs_config_files binary file for the target if the -# product partition is generated. Add fs_config_files or fs_config_files_product -# to PRODUCT_PACKAGES in the device make file to enable. -include $(CLEAR_VARS) - -LOCAL_MODULE := fs_config_files_product -LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 -LOCAL_LICENSE_CONDITIONS := notice -LOCAL_NOTICE_FILE := build/soong/licenses/LICENSE -LOCAL_REQUIRED_MODULES := $(if $(BOARD_USES_PRODUCTIMAGE)$(BOARD_PRODUCTIMAGE_FILE_SYSTEM_TYPE),_fs_config_files_product) -include $(BUILD_PHONY_PACKAGE) - -################################## # Generate the <p>/etc/fs_config_dirs binary files for all enabled partitions # excluding /system, /system_ext and /product. Add fs_config_dirs_nonsystem to # PRODUCT_PACKAGES in the device make file to enable. @@ -146,7 +79,7 @@ LOCAL_MODULE := fs_config_dirs_nonsystem LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 LOCAL_LICENSE_CONDITIONS := notice LOCAL_NOTICE_FILE := build/soong/licenses/LICENSE -LOCAL_REQUIRED_MODULES := $(foreach t,$(fs_config_generate_extra_partition_list),_fs_config_dirs_$(t)) +LOCAL_REQUIRED_MODULES := $(foreach t,$(fs_config_generate_extra_partition_list),fs_config_dirs_$(t)) include $(BUILD_PHONY_PACKAGE) ################################## @@ -159,122 +92,9 @@ LOCAL_MODULE := fs_config_files_nonsystem LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 LOCAL_LICENSE_CONDITIONS := notice LOCAL_NOTICE_FILE := build/soong/licenses/LICENSE -LOCAL_REQUIRED_MODULES := $(foreach t,$(fs_config_generate_extra_partition_list),_fs_config_files_$(t)) +LOCAL_REQUIRED_MODULES := $(foreach t,$(fs_config_generate_extra_partition_list),fs_config_files_$(t)) include $(BUILD_PHONY_PACKAGE) -################################## -# Generate the system/etc/fs_config_dirs binary file for the target -# Add fs_config_dirs or fs_config_dirs_system to PRODUCT_PACKAGES in -# the device make file to enable -include $(CLEAR_VARS) - -LOCAL_MODULE := fs_config_dirs_system -LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 -LOCAL_LICENSE_CONDITIONS := notice -LOCAL_NOTICE_FILE := build/soong/licenses/LICENSE -LOCAL_MODULE_CLASS := ETC -LOCAL_INSTALLED_MODULE_STEM := fs_config_dirs -include $(BUILD_SYSTEM)/base_rules.mk -$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_FS_HDR := $(system_android_filesystem_config) -$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_CAP_HDR := $(system_capability_header) -$(LOCAL_BUILT_MODULE): PRIVATE_PARTITION_LIST := $(fs_config_generate_extra_partition_list) -$(LOCAL_BUILT_MODULE): PRIVATE_TARGET_FS_CONFIG_GEN := $(TARGET_FS_CONFIG_GEN) -$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/fs_config_generator.py $(TARGET_FS_CONFIG_GEN) $(system_android_filesystem_config) $(system_capability_header) - @mkdir -p $(dir $@) - $< fsconfig \ - --aid-header $(PRIVATE_ANDROID_FS_HDR) \ - --capability-header $(PRIVATE_ANDROID_CAP_HDR) \ - --partition system \ - --all-partitions "$(subst $(space),$(comma),$(PRIVATE_PARTITION_LIST))" \ - --dirs \ - --out_file $@ \ - $(or $(PRIVATE_TARGET_FS_CONFIG_GEN),/dev/null) - -################################## -# Generate the system/etc/fs_config_files binary file for the target -# Add fs_config_files or fs_config_files_system to PRODUCT_PACKAGES in -# the device make file to enable -include $(CLEAR_VARS) - -LOCAL_MODULE := fs_config_files_system -LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 -LOCAL_LICENSE_CONDITIONS := notice -LOCAL_NOTICE_FILE := build/soong/licenses/LICENSE -LOCAL_MODULE_CLASS := ETC -LOCAL_INSTALLED_MODULE_STEM := fs_config_files -include $(BUILD_SYSTEM)/base_rules.mk -$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_FS_HDR := $(system_android_filesystem_config) -$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_CAP_HDR := $(system_capability_header) -$(LOCAL_BUILT_MODULE): PRIVATE_PARTITION_LIST := $(fs_config_generate_extra_partition_list) -$(LOCAL_BUILT_MODULE): PRIVATE_TARGET_FS_CONFIG_GEN := $(TARGET_FS_CONFIG_GEN) -$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/fs_config_generator.py $(TARGET_FS_CONFIG_GEN) $(system_android_filesystem_config) $(system_capability_header) - @mkdir -p $(dir $@) - $< fsconfig \ - --aid-header $(PRIVATE_ANDROID_FS_HDR) \ - --capability-header $(PRIVATE_ANDROID_CAP_HDR) \ - --partition system \ - --all-partitions "$(subst $(space),$(comma),$(PRIVATE_PARTITION_LIST))" \ - --files \ - --out_file $@ \ - $(or $(PRIVATE_TARGET_FS_CONFIG_GEN),/dev/null) - -ifneq ($(filter vendor,$(fs_config_generate_extra_partition_list)),) -################################## -# Generate the vendor/etc/fs_config_dirs binary file for the target -# Add fs_config_dirs or fs_config_dirs_nonsystem to PRODUCT_PACKAGES -# in the device make file to enable -include $(CLEAR_VARS) - -LOCAL_MODULE := _fs_config_dirs_vendor -LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 -LOCAL_LICENSE_CONDITIONS := notice -LOCAL_NOTICE_FILE := build/soong/licenses/LICENSE -LOCAL_MODULE_CLASS := ETC -LOCAL_INSTALLED_MODULE_STEM := fs_config_dirs -LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/etc -include $(BUILD_SYSTEM)/base_rules.mk -$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_FS_HDR := $(vendor_android_filesystem_config) -$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_CAP_HDR := $(vendor_capability_header) -$(LOCAL_BUILT_MODULE): PRIVATE_TARGET_FS_CONFIG_GEN := $(TARGET_FS_CONFIG_GEN) -$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/fs_config_generator.py $(TARGET_FS_CONFIG_GEN) $(vendor_android_filesystem_config) $(vendor_capability_header) - @mkdir -p $(dir $@) - $< fsconfig \ - --aid-header $(PRIVATE_ANDROID_FS_HDR) \ - --capability-header $(PRIVATE_ANDROID_CAP_HDR) \ - --partition vendor \ - --dirs \ - --out_file $@ \ - $(or $(PRIVATE_TARGET_FS_CONFIG_GEN),/dev/null) - -################################## -# Generate the vendor/etc/fs_config_files binary file for the target -# Add fs_config_files or fs_config_files_nonsystem to PRODUCT_PACKAGES -# in the device make file to enable -include $(CLEAR_VARS) - -LOCAL_MODULE := _fs_config_files_vendor -LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 -LOCAL_LICENSE_CONDITIONS := notice -LOCAL_NOTICE_FILE := build/soong/licenses/LICENSE -LOCAL_MODULE_CLASS := ETC -LOCAL_INSTALLED_MODULE_STEM := fs_config_files -LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/etc -include $(BUILD_SYSTEM)/base_rules.mk -$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_FS_HDR := $(vendor_android_filesystem_config) -$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_CAP_HDR := $(vendor_capability_header) -$(LOCAL_BUILT_MODULE): PRIVATE_TARGET_FS_CONFIG_GEN := $(TARGET_FS_CONFIG_GEN) -$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/fs_config_generator.py $(TARGET_FS_CONFIG_GEN) $(vendor_android_filesystem_config) $(vendor_capability_header) - @mkdir -p $(dir $@) - $< fsconfig \ - --aid-header $(PRIVATE_ANDROID_FS_HDR) \ - --capability-header $(PRIVATE_ANDROID_CAP_HDR) \ - --partition vendor \ - --files \ - --out_file $@ \ - $(or $(PRIVATE_TARGET_FS_CONFIG_GEN),/dev/null) - -endif - ifneq ($(filter oem,$(fs_config_generate_extra_partition_list)),) ################################## # Generate the oem/etc/fs_config_dirs binary file for the target @@ -282,7 +102,7 @@ ifneq ($(filter oem,$(fs_config_generate_extra_partition_list)),) # in the device make file to enable include $(CLEAR_VARS) -LOCAL_MODULE := _fs_config_dirs_oem +LOCAL_MODULE := fs_config_dirs_oem LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 LOCAL_LICENSE_CONDITIONS := notice LOCAL_NOTICE_FILE := build/soong/licenses/LICENSE @@ -290,10 +110,10 @@ LOCAL_MODULE_CLASS := ETC LOCAL_INSTALLED_MODULE_STEM := fs_config_dirs LOCAL_MODULE_PATH := $(TARGET_OUT_OEM)/etc include $(BUILD_SYSTEM)/base_rules.mk -$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_FS_HDR := $(system_android_filesystem_config) -$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_CAP_HDR := $(system_capability_header) +$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_FS_HDR := $(android_filesystem_config) +$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_CAP_HDR := $(capability_header) $(LOCAL_BUILT_MODULE): PRIVATE_TARGET_FS_CONFIG_GEN := $(TARGET_FS_CONFIG_GEN) -$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/fs_config_generator.py $(TARGET_FS_CONFIG_GEN) $(system_android_filesystem_config) $(system_capability_header) +$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/fs_config_generator.py $(TARGET_FS_CONFIG_GEN) $(android_filesystem_config) $(capability_header) @mkdir -p $(dir $@) $< fsconfig \ --aid-header $(PRIVATE_ANDROID_FS_HDR) \ @@ -309,7 +129,7 @@ $(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/fs_config_generator.py $(TARGET_FS_CONFIG_G # in the device make file to enable include $(CLEAR_VARS) -LOCAL_MODULE := _fs_config_files_oem +LOCAL_MODULE := fs_config_files_oem LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 LOCAL_LICENSE_CONDITIONS := notice LOCAL_NOTICE_FILE := build/soong/licenses/LICENSE @@ -317,10 +137,10 @@ LOCAL_MODULE_CLASS := ETC LOCAL_INSTALLED_MODULE_STEM := fs_config_files LOCAL_MODULE_PATH := $(TARGET_OUT_OEM)/etc include $(BUILD_SYSTEM)/base_rules.mk -$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_FS_HDR := $(system_android_filesystem_config) -$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_CAP_HDR := $(system_capability_header) +$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_FS_HDR := $(android_filesystem_config) +$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_CAP_HDR := $(capability_header) $(LOCAL_BUILT_MODULE): PRIVATE_TARGET_FS_CONFIG_GEN := $(TARGET_FS_CONFIG_GEN) -$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/fs_config_generator.py $(TARGET_FS_CONFIG_GEN) $(system_android_filesystem_config) $(system_capability_header) +$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/fs_config_generator.py $(TARGET_FS_CONFIG_GEN) $(android_filesystem_config) $(capability_header) @mkdir -p $(dir $@) $< fsconfig \ --aid-header $(PRIVATE_ANDROID_FS_HDR) \ @@ -332,63 +152,6 @@ $(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/fs_config_generator.py $(TARGET_FS_CONFIG_G endif -ifneq ($(filter odm,$(fs_config_generate_extra_partition_list)),) -################################## -# Generate the odm/etc/fs_config_dirs binary file for the target -# Add fs_config_dirs or fs_config_dirs_nonsystem to PRODUCT_PACKAGES -# in the device make file to enable -include $(CLEAR_VARS) - -LOCAL_MODULE := _fs_config_dirs_odm -LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 -LOCAL_LICENSE_CONDITIONS := notice -LOCAL_NOTICE_FILE := build/soong/licenses/LICENSE -LOCAL_MODULE_CLASS := ETC -LOCAL_INSTALLED_MODULE_STEM := fs_config_dirs -LOCAL_MODULE_PATH := $(TARGET_OUT_ODM)/etc -include $(BUILD_SYSTEM)/base_rules.mk -$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_FS_HDR := $(vendor_android_filesystem_config) -$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_CAP_HDR := $(vendor_capability_header) -$(LOCAL_BUILT_MODULE): PRIVATE_TARGET_FS_CONFIG_GEN := $(TARGET_FS_CONFIG_GEN) -$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/fs_config_generator.py $(TARGET_FS_CONFIG_GEN) $(vendor_android_filesystem_config) $(vendor_capability_header) - @mkdir -p $(dir $@) - $< fsconfig \ - --aid-header $(PRIVATE_ANDROID_FS_HDR) \ - --capability-header $(PRIVATE_ANDROID_CAP_HDR) \ - --partition odm \ - --dirs \ - --out_file $@ \ - $(or $(PRIVATE_TARGET_FS_CONFIG_GEN),/dev/null) - -################################## -# Generate the odm/etc/fs_config_files binary file for the target -# Add fs_config_files or fs_config_files_nonsystem to PRODUCT_PACKAGES -# in the device make file to enable -include $(CLEAR_VARS) - -LOCAL_MODULE := _fs_config_files_odm -LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 -LOCAL_LICENSE_CONDITIONS := notice -LOCAL_NOTICE_FILE := build/soong/licenses/LICENSE -LOCAL_MODULE_CLASS := ETC -LOCAL_INSTALLED_MODULE_STEM := fs_config_files -LOCAL_MODULE_PATH := $(TARGET_OUT_ODM)/etc -include $(BUILD_SYSTEM)/base_rules.mk -$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_FS_HDR := $(vendor_android_filesystem_config) -$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_CAP_HDR := $(vendor_capability_header) -$(LOCAL_BUILT_MODULE): PRIVATE_TARGET_FS_CONFIG_GEN := $(TARGET_FS_CONFIG_GEN) -$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/fs_config_generator.py $(TARGET_FS_CONFIG_GEN) $(vendor_android_filesystem_config) $(vendor_capability_header) - @mkdir -p $(dir $@) - $< fsconfig \ - --aid-header $(PRIVATE_ANDROID_FS_HDR) \ - --capability-header $(PRIVATE_ANDROID_CAP_HDR) \ - --partition odm \ - --files \ - --out_file $@ \ - $(or $(PRIVATE_TARGET_FS_CONFIG_GEN),/dev/null) - -endif - ifneq ($(filter vendor_dlkm,$(fs_config_generate_extra_partition_list)),) ################################## # Generate the vendor_dlkm/etc/fs_config_dirs binary file for the target @@ -396,7 +159,7 @@ ifneq ($(filter vendor_dlkm,$(fs_config_generate_extra_partition_list)),) # the device make file to enable include $(CLEAR_VARS) -LOCAL_MODULE := _fs_config_dirs_vendor_dlkm +LOCAL_MODULE := fs_config_dirs_vendor_dlkm LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 LOCAL_LICENSE_CONDITIONS := notice LOCAL_NOTICE_FILE := build/soong/licenses/LICENSE @@ -404,10 +167,10 @@ LOCAL_MODULE_CLASS := ETC LOCAL_INSTALLED_MODULE_STEM := fs_config_dirs LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_DLKM)/etc include $(BUILD_SYSTEM)/base_rules.mk -$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_FS_HDR := $(vendor_android_filesystem_config) -$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_CAP_HDR := $(vendor_capability_header) +$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_FS_HDR := $(android_filesystem_config) +$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_CAP_HDR := $(capability_header) $(LOCAL_BUILT_MODULE): PRIVATE_TARGET_FS_CONFIG_GEN := $(TARGET_FS_CONFIG_GEN) -$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/fs_config_generator.py $(TARGET_FS_CONFIG_GEN) $(vendor_android_filesystem_config) $(vendor_capability_header) +$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/fs_config_generator.py $(TARGET_FS_CONFIG_GEN) $(android_filesystem_config) $(capability_header) @mkdir -p $(dir $@) $< fsconfig \ --aid-header $(PRIVATE_ANDROID_FS_HDR) \ @@ -423,7 +186,7 @@ $(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/fs_config_generator.py $(TARGET_FS_CONFIG_G # the device make file to enable include $(CLEAR_VARS) -LOCAL_MODULE := _fs_config_files_vendor_dlkm +LOCAL_MODULE := fs_config_files_vendor_dlkm LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 LOCAL_LICENSE_CONDITIONS := notice LOCAL_NOTICE_FILE := build/soong/licenses/LICENSE @@ -431,10 +194,10 @@ LOCAL_MODULE_CLASS := ETC LOCAL_INSTALLED_MODULE_STEM := fs_config_files LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_DLKM)/etc include $(BUILD_SYSTEM)/base_rules.mk -$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_FS_HDR := $(vendor_android_filesystem_config) -$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_CAP_HDR := $(vendor_capability_header) +$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_FS_HDR := $(android_filesystem_config) +$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_CAP_HDR := $(capability_header) $(LOCAL_BUILT_MODULE): PRIVATE_TARGET_FS_CONFIG_GEN := $(TARGET_FS_CONFIG_GEN) -$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/fs_config_generator.py $(TARGET_FS_CONFIG_GEN) $(vendor_android_filesystem_config) $(vendor_capability_header) +$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/fs_config_generator.py $(TARGET_FS_CONFIG_GEN) $(android_filesystem_config) $(capability_header) @mkdir -p $(dir $@) $< fsconfig \ --aid-header $(PRIVATE_ANDROID_FS_HDR) \ @@ -453,7 +216,7 @@ ifneq ($(filter odm_dlkm,$(fs_config_generate_extra_partition_list)),) # in the device make file to enable include $(CLEAR_VARS) -LOCAL_MODULE := _fs_config_dirs_odm_dlkm +LOCAL_MODULE := fs_config_dirs_odm_dlkm LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 LOCAL_LICENSE_CONDITIONS := notice LOCAL_NOTICE_FILE := build/soong/licenses/LICENSE @@ -461,10 +224,10 @@ LOCAL_MODULE_CLASS := ETC LOCAL_INSTALLED_MODULE_STEM := fs_config_dirs LOCAL_MODULE_PATH := $(TARGET_OUT_ODM_DLKM)/etc include $(BUILD_SYSTEM)/base_rules.mk -$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_FS_HDR := $(vendor_android_filesystem_config) -$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_CAP_HDR := $(vendor_capability_header) +$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_FS_HDR := $(android_filesystem_config) +$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_CAP_HDR := $(capability_header) $(LOCAL_BUILT_MODULE): PRIVATE_TARGET_FS_CONFIG_GEN := $(TARGET_FS_CONFIG_GEN) -$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/fs_config_generator.py $(TARGET_FS_CONFIG_GEN) $(vendor_android_filesystem_config) $(vendor_capability_header) +$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/fs_config_generator.py $(TARGET_FS_CONFIG_GEN) $(android_filesystem_config) $(capability_header) @mkdir -p $(dir $@) $< fsconfig \ --aid-header $(PRIVATE_ANDROID_FS_HDR) \ @@ -480,7 +243,7 @@ $(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/fs_config_generator.py $(TARGET_FS_CONFIG_G # in the device make file to enable include $(CLEAR_VARS) -LOCAL_MODULE := _fs_config_files_odm_dlkm +LOCAL_MODULE := fs_config_files_odm_dlkm LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 LOCAL_LICENSE_CONDITIONS := notice LOCAL_NOTICE_FILE := build/soong/licenses/LICENSE @@ -488,10 +251,10 @@ LOCAL_MODULE_CLASS := ETC LOCAL_INSTALLED_MODULE_STEM := fs_config_files LOCAL_MODULE_PATH := $(TARGET_OUT_ODM_DLKM)/etc include $(BUILD_SYSTEM)/base_rules.mk -$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_FS_HDR := $(vendor_android_filesystem_config) -$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_CAP_HDR := $(vendor_capability_header) +$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_FS_HDR := $(android_filesystem_config) +$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_CAP_HDR := $(capability_header) $(LOCAL_BUILT_MODULE): PRIVATE_TARGET_FS_CONFIG_GEN := $(TARGET_FS_CONFIG_GEN) -$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/fs_config_generator.py $(TARGET_FS_CONFIG_GEN) $(vendor_android_filesystem_config) $(vendor_capability_header) +$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/fs_config_generator.py $(TARGET_FS_CONFIG_GEN) $(android_filesystem_config) $(capability_header) @mkdir -p $(dir $@) $< fsconfig \ --aid-header $(PRIVATE_ANDROID_FS_HDR) \ @@ -510,7 +273,7 @@ ifneq ($(filter system_dlkm,$(fs_config_generate_extra_partition_list)),) # in the device make file to enable include $(CLEAR_VARS) -LOCAL_MODULE := _fs_config_dirs_system_dlkm +LOCAL_MODULE := fs_config_dirs_system_dlkm LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 LOCAL_LICENSE_CONDITIONS := notice LOCAL_NOTICE_FILE := build/soong/licenses/LICENSE @@ -518,10 +281,10 @@ LOCAL_MODULE_CLASS := ETC LOCAL_INSTALLED_MODULE_STEM := fs_config_dirs LOCAL_MODULE_PATH := $(TARGET_OUT_SYSTEM_DLKM)/etc include $(BUILD_SYSTEM)/base_rules.mk -$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_FS_HDR := $(vendor_android_filesystem_config) -$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_CAP_HDR := $(vendor_capability_header) +$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_FS_HDR := $(android_filesystem_config) +$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_CAP_HDR := $(capability_header) $(LOCAL_BUILT_MODULE): PRIVATE_TARGET_FS_CONFIG_GEN := $(TARGET_FS_CONFIG_GEN) -$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/fs_config_generator.py $(TARGET_FS_CONFIG_GEN) $(vendor_android_filesystem_config) $(vendor_capability_header) +$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/fs_config_generator.py $(TARGET_FS_CONFIG_GEN) $(android_filesystem_config) $(capability_header) @mkdir -p $(dir $@) $< fsconfig \ --aid-header $(PRIVATE_ANDROID_FS_HDR) \ @@ -537,7 +300,7 @@ $(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/fs_config_generator.py $(TARGET_FS_CONFIG_G # in the device make file to enable include $(CLEAR_VARS) -LOCAL_MODULE := _fs_config_files_system_dlkm +LOCAL_MODULE := fs_config_files_system_dlkm LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 LOCAL_LICENSE_CONDITIONS := notice LOCAL_NOTICE_FILE := build/soong/licenses/LICENSE @@ -545,10 +308,10 @@ LOCAL_MODULE_CLASS := ETC LOCAL_INSTALLED_MODULE_STEM := fs_config_files LOCAL_MODULE_PATH := $(TARGET_OUT_SYSTEM_DLKM)/etc include $(BUILD_SYSTEM)/base_rules.mk -$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_FS_HDR := $(vendor_android_filesystem_config) -$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_CAP_HDR := $(vendor_capability_header) +$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_FS_HDR := $(android_filesystem_config) +$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_CAP_HDR := $(capability_header) $(LOCAL_BUILT_MODULE): PRIVATE_TARGET_FS_CONFIG_GEN := $(TARGET_FS_CONFIG_GEN) -$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/fs_config_generator.py $(TARGET_FS_CONFIG_GEN) $(vendor_android_filesystem_config) $(vendor_capability_header) +$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/fs_config_generator.py $(TARGET_FS_CONFIG_GEN) $(android_filesystem_config) $(capability_header) @mkdir -p $(dir $@) $< fsconfig \ --aid-header $(PRIVATE_ANDROID_FS_HDR) \ @@ -560,118 +323,6 @@ $(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/fs_config_generator.py $(TARGET_FS_CONFIG_G endif -ifneq ($(BOARD_USES_PRODUCTIMAGE)$(BOARD_PRODUCTIMAGE_FILE_SYSTEM_TYPE),) -################################## -# Generate the product/etc/fs_config_dirs binary file for the target -# Add fs_config_dirs or fs_config_dirs_product to PRODUCT_PACKAGES in -# the device make file to enable -include $(CLEAR_VARS) - -LOCAL_MODULE := _fs_config_dirs_product -LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 -LOCAL_LICENSE_CONDITIONS := notice -LOCAL_NOTICE_FILE := build/soong/licenses/LICENSE -LOCAL_MODULE_CLASS := ETC -LOCAL_INSTALLED_MODULE_STEM := fs_config_dirs -LOCAL_MODULE_PATH := $(TARGET_OUT_PRODUCT)/etc -include $(BUILD_SYSTEM)/base_rules.mk -$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_FS_HDR := $(system_android_filesystem_config) -$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_CAP_HDR := $(system_capability_header) -$(LOCAL_BUILT_MODULE): PRIVATE_TARGET_FS_CONFIG_GEN := $(TARGET_FS_CONFIG_GEN) -$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/fs_config_generator.py $(TARGET_FS_CONFIG_GEN) $(system_android_filesystem_config) $(system_capability_header) - @mkdir -p $(dir $@) - $< fsconfig \ - --aid-header $(PRIVATE_ANDROID_FS_HDR) \ - --capability-header $(PRIVATE_ANDROID_CAP_HDR) \ - --partition product \ - --dirs \ - --out_file $@ \ - $(or $(PRIVATE_TARGET_FS_CONFIG_GEN),/dev/null) - -################################## -# Generate the product/etc/fs_config_files binary file for the target -# Add fs_config_files or fs_config_files_product to PRODUCT_PACKAGES in -# the device make file to enable -include $(CLEAR_VARS) - -LOCAL_MODULE := _fs_config_files_product -LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 -LOCAL_LICENSE_CONDITIONS := notice -LOCAL_NOTICE_FILE := build/soong/licenses/LICENSE -LOCAL_MODULE_CLASS := ETC -LOCAL_INSTALLED_MODULE_STEM := fs_config_files -LOCAL_MODULE_PATH := $(TARGET_OUT_PRODUCT)/etc -include $(BUILD_SYSTEM)/base_rules.mk -$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_FS_HDR := $(system_android_filesystem_config) -$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_CAP_HDR := $(system_capability_header) -$(LOCAL_BUILT_MODULE): PRIVATE_TARGET_FS_CONFIG_GEN := $(TARGET_FS_CONFIG_GEN) -$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/fs_config_generator.py $(TARGET_FS_CONFIG_GEN) $(system_android_filesystem_config) $(system_capability_header) - @mkdir -p $(dir $@) - $< fsconfig \ - --aid-header $(PRIVATE_ANDROID_FS_HDR) \ - --capability-header $(PRIVATE_ANDROID_CAP_HDR) \ - --partition product \ - --files \ - --out_file $@ \ - $(or $(PRIVATE_TARGET_FS_CONFIG_GEN),/dev/null) -endif - -ifneq ($(BOARD_USES_SYSTEM_EXTIMAGE)$(BOARD_SYSTEM_EXTIMAGE_FILE_SYSTEM_TYPE),) -################################## -# Generate the system_ext/etc/fs_config_dirs binary file for the target -# Add fs_config_dirs or fs_config_dirs_system_ext to PRODUCT_PACKAGES in -# the device make file to enable -include $(CLEAR_VARS) - -LOCAL_MODULE := _fs_config_dirs_system_ext -LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 -LOCAL_LICENSE_CONDITIONS := notice -LOCAL_NOTICE_FILE := build/soong/licenses/LICENSE -LOCAL_MODULE_CLASS := ETC -LOCAL_INSTALLED_MODULE_STEM := fs_config_dirs -LOCAL_MODULE_PATH := $(TARGET_OUT_SYSTEM_EXT)/etc -include $(BUILD_SYSTEM)/base_rules.mk -$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_FS_HDR := $(system_android_filesystem_config) -$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_CAP_HDR := $(system_capability_header) -$(LOCAL_BUILT_MODULE): PRIVATE_TARGET_FS_CONFIG_GEN := $(TARGET_FS_CONFIG_GEN) -$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/fs_config_generator.py $(TARGET_FS_CONFIG_GEN) $(system_android_filesystem_config) $(system_capability_header) - @mkdir -p $(dir $@) - $< fsconfig \ - --aid-header $(PRIVATE_ANDROID_FS_HDR) \ - --capability-header $(PRIVATE_ANDROID_CAP_HDR) \ - --partition system_ext \ - --dirs \ - --out_file $@ \ - $(or $(PRIVATE_TARGET_FS_CONFIG_GEN),/dev/null) - -################################## -# Generate the system_ext/etc/fs_config_files binary file for the target -# Add fs_config_files or fs_config_files_system_ext to PRODUCT_PACKAGES in -# the device make file to enable -include $(CLEAR_VARS) - -LOCAL_MODULE := _fs_config_files_system_ext -LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 -LOCAL_LICENSE_CONDITIONS := notice -LOCAL_NOTICE_FILE := build/soong/licenses/LICENSE -LOCAL_MODULE_CLASS := ETC -LOCAL_INSTALLED_MODULE_STEM := fs_config_files -LOCAL_MODULE_PATH := $(TARGET_OUT_SYSTEM_EXT)/etc -include $(BUILD_SYSTEM)/base_rules.mk -$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_FS_HDR := $(system_android_filesystem_config) -$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_CAP_HDR := $(system_capability_header) -$(LOCAL_BUILT_MODULE): PRIVATE_TARGET_FS_CONFIG_GEN := $(TARGET_FS_CONFIG_GEN) -$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/fs_config_generator.py $(TARGET_FS_CONFIG_GEN) $(system_android_filesystem_config) $(system_capability_header) - @mkdir -p $(dir $@) - $< fsconfig \ - --aid-header $(PRIVATE_ANDROID_FS_HDR) \ - --capability-header $(PRIVATE_ANDROID_CAP_HDR) \ - --partition system_ext \ - --files \ - --out_file $@ \ - $(or $(PRIVATE_TARGET_FS_CONFIG_GEN),/dev/null) -endif - -system_android_filesystem_config := -system_capability_header := +android_filesystem_config := +capability_header := fs_config_generate_extra_partition_list := diff --git a/tools/lunchable b/tools/lunchable new file mode 100755 index 0000000000..fce2c2719d --- /dev/null +++ b/tools/lunchable @@ -0,0 +1,72 @@ +#!/bin/bash + +# TODO: Currently only checks trunk_staging. Should check trunk_staging first, +# then use the product-specfic releases. Only applies to -c though. + +function Help() { +cat <<@EOF@ +Usage: lunchable [options] + +Lists products that have no functioning lunch combo. + +options: +-c prints all failing lunch combos for all targets; +-w why? Prints the error message after each failed lunch combo. Only + works with -c + +@EOF@ +} + +complete=0 +why=0 +while getopts "cwh" option; do + case $option in + c) + complete=1;; + w) + why=1;; + h) + Help + exit;; + esac +done + +# Getting all named products can fail if we haven't lunched anything +source $(pwd)/build/envsetup.sh &> /dev/null +all_named_products=( $(get_build_var all_named_products 2> /dev/null) ) +if [[ $? -ne 0 ]]; then + echo "get_build_var all_named_products failed. Lunch something first?" >&2 + exit 1 +fi +total_products=${#all_named_products[@]} +current_product=0 + +for product in "${all_named_products[@]}"; do + (( current_product += 1 )) + single_pass=0 + printf " Checking ${current_product}/${total_products} \r" >&2 + for release in trunk_staging; do + for variant in eng user userdebug; do + lunchcombo="${product}-${release}-${variant}" + lunch_error="$(lunch $lunchcombo 2>&1 > /dev/null)" + if [[ $? -ne 0 ]]; then + # Lunch failed + if [[ $complete -eq 1 ]]; then + echo -e "${product} : ${lunchcombo}" + if [[ $why -eq 1 ]]; then + echo -e "$(sed 's/^/ /g' <<<$lunch_error)" + fi + fi + elif [[ $complete -ne 1 ]]; then + single_pass=1 + break # skip variant + fi + done + if [[ $single_pass -eq 1 ]]; then + break # skip release + fi + done + if [[ $complete -eq 0 ]] && [[ $single_pass -eq 0 ]]; then + echo "${product}" + fi +done diff --git a/tools/releasetools/Android.bp b/tools/releasetools/Android.bp index 9385f0ccab..9b134f22d4 100644 --- a/tools/releasetools/Android.bp +++ b/tools/releasetools/Android.bp @@ -632,7 +632,6 @@ python_defaults { data: [ "testdata/**/*", ":com.android.apex.compressed.v1", - ":com.android.apex.compressed.v1_original", ":com.android.apex.vendor.foo.with_vintf" ], target: { diff --git a/tools/releasetools/create_brick_ota.py b/tools/releasetools/create_brick_ota.py index 9e040a53d4..bf50f71049 100644 --- a/tools/releasetools/create_brick_ota.py +++ b/tools/releasetools/create_brick_ota.py @@ -45,10 +45,10 @@ def CreateBrickOta(product_name: str, output_path: Path, extra_wipe_partitions: partitions_to_wipe = PARTITIONS_TO_WIPE if extra_wipe_partitions is not None: partitions_to_wipe = PARTITIONS_TO_WIPE + extra_wipe_partitions.split(",") - ota_metadata = ["ota-type=BRICK", "post-timestamp=9999999999", - "pre-device=" + product_name] - if serialno is not None: - ota_metadata.append("serialno=" + serialno) + ota_metadata = ["ota-type=BRICK", "post-timestamp=9999999999", + "pre-device=" + product_name] + if serialno is not None: + ota_metadata.append("serialno=" + serialno) # recovery requiers product name to be a | separated list product_name = product_name.replace(",", "|") with zipfile.ZipFile(output_path, "w") as zfp: diff --git a/tools/releasetools/ota_utils.py b/tools/releasetools/ota_utils.py index 048a497585..81b53dce36 100644 --- a/tools/releasetools/ota_utils.py +++ b/tools/releasetools/ota_utils.py @@ -1111,9 +1111,10 @@ def CopyTargetFilesDir(input_dir): relative_path = path.removeprefix(input_dir).removeprefix("/") if not Fnmatch(relative_path, UNZIP_PATTERN): continue - if filename.endswith(".prop") or filename == "prop.default" or "/etc/vintf/" in relative_path: - target_path = os.path.join( - output_dir, relative_path) - os.makedirs(os.path.dirname(target_path), exist_ok=True) - shutil.copy(path, target_path) + target_path = os.path.join( + output_dir, relative_path) + if os.path.exists(target_path): + continue + os.makedirs(os.path.dirname(target_path), exist_ok=True) + shutil.copy(path, target_path) return output_dir diff --git a/tools/whichgit b/tools/whichgit index 8cf84f5629..55c8c6fb5a 100755 --- a/tools/whichgit +++ b/tools/whichgit @@ -1,6 +1,7 @@ #!/usr/bin/env python3 import argparse +import itertools import os import subprocess import sys @@ -10,15 +11,34 @@ def get_build_var(var): check=True, capture_output=True, text=True).stdout.strip() +def get_all_modules(): + product_out = subprocess.run(["build/soong/soong_ui.bash", "--dumpvar-mode", "--abs", "PRODUCT_OUT"], + check=True, capture_output=True, text=True).stdout.strip() + result = subprocess.run(["cat", product_out + "/all_modules.txt"], check=True, capture_output=True, text=True) + return result.stdout.strip().split("\n") + + +def batched(iterable, n): + # introduced in itertools 3.12, could delete once that's universally available + if n < 1: + raise ValueError('n must be at least one') + it = iter(iterable) + while batch := tuple(itertools.islice(it, n)): + yield batch + + def get_sources(modules): - result = subprocess.run(["./prebuilts/build-tools/linux-x86/bin/ninja", "-f", - "out/combined-" + os.environ["TARGET_PRODUCT"] + ".ninja", - "-t", "inputs", "-d", ] + modules, - stderr=subprocess.STDOUT, stdout=subprocess.PIPE, check=False, text=True) - if result.returncode != 0: - sys.stderr.write(result.stdout) - sys.exit(1) - return set([f for f in result.stdout.split("\n") if not f.startswith("out/")]) + sources = set() + for module_group in batched(modules, 40_000): + result = subprocess.run(["./prebuilts/build-tools/linux-x86/bin/ninja", "-f", + "out/combined-" + os.environ["TARGET_PRODUCT"] + ".ninja", + "-t", "inputs", "-d", ] + list(module_group), + stderr=subprocess.STDOUT, stdout=subprocess.PIPE, check=False, text=True) + if result.returncode != 0: + sys.stderr.write(result.stdout) + sys.exit(1) + sources.update(set([f for f in result.stdout.split("\n") if not f.startswith("out/")])) + return sources def m_nothing(): @@ -57,13 +77,13 @@ def main(argv): # Argument parsing ap = argparse.ArgumentParser(description="List the required git projects for the given modules") ap.add_argument("--products", nargs="*", - help="The TARGET_PRODUCT to check. If not provided just uses whatever has" - + " already been built") + help="One or more TARGET_PRODUCT to check, or \"*\" for all. If not provided" + + "just uses whatever has already been built") ap.add_argument("--variants", nargs="*", help="The TARGET_BUILD_VARIANTS to check. If not provided just uses whatever has" + " already been built, or eng if --products is supplied") ap.add_argument("--modules", nargs="*", - help="The build modules to check, or droid if not supplied") + help="The build modules to check, or \"*\" for all, or droid if not supplied") ap.add_argument("--why", nargs="*", help="Also print the input files used in these projects, or \"*\" for all") ap.add_argument("--unused", help="List the unused git projects for the given modules rather than" @@ -72,22 +92,33 @@ def main(argv): modules = args.modules if args.modules else ["droid"] + match args.products: + case ["*"]: + products = get_build_var("all_named_products").split(" ") + case _: + products = args.products + # Get the list of sources for all of the requested build combos - if not args.products and not args.variants: + if not products and not args.variants: + m_nothing() + if args.modules == ["*"]: + modules = get_all_modules() sources = get_sources(modules) else: - if not args.products: + if not products: sys.stderr.write("Error: --products must be supplied if --variants is supplied") sys.exit(1) sources = set() build_num = 1 - for product in args.products: + for product in products: os.environ["TARGET_PRODUCT"] = product variants = args.variants if args.variants else ["user", "userdebug", "eng"] for variant in variants: - sys.stderr.write(f"Analyzing build {build_num} of {len(args.products)*len(variants)}\r") + sys.stderr.write(f"Analyzing build {build_num} of {len(products)*len(variants)}\r") os.environ["TARGET_BUILD_VARIANT"] = variant m_nothing() + if args.modules == ["*"]: + modules = get_all_modules() sources.update(get_sources(modules)) build_num += 1 sys.stderr.write("\n\n") |