Merge "Fix false positive when checking ELF prebuilts in PRODUCT_COPY_FILES" into main
diff --git a/Changes.md b/Changes.md
index 9f2449c..eddec04 100644
--- a/Changes.md
+++ b/Changes.md
@@ -40,14 +40,8 @@
## Python 2 to 3 migration
-The path set when running builds now makes the `python` executable point to python 3,
-whereas on previous versions it pointed to python 2. If you still have python 2 scripts,
-you can change the shebang line to use `python2` explicitly. This only applies for
-scripts run directly from makefiles, or from soong genrules.
-
-In addition, `python_*` soong modules no longer allow python 2.
-
-Python 2 is slated for complete removal in V.
+Python 2 has been completely removed from the build. Please migrate any remaining usages to
+Python 3, and remove any version-specific properties from bp files.
## Stop referencing sysprop_library directly from cc modules
diff --git a/core/Makefile b/core/Makefile
index c4327fd..a92db6c 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -295,11 +295,6 @@
.PHONY: ndk-docs
endif
-ifeq ($(HOST_OS),linux)
-$(call dist-for-goals,sdk,$(API_FINGERPRINT))
-$(call dist-for-goals,droidcore,$(API_FINGERPRINT))
-endif
-
INSTALLED_RECOVERYIMAGE_TARGET :=
# Build recovery image if
# BUILDING_RECOVERY_IMAGE && !BOARD_USES_RECOVERY_AS_BOOT && !BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT.
@@ -1982,7 +1977,7 @@
installed_system_dlkm_notice_xml_gz := $(TARGET_OUT_SYSTEM_DLKM)/etc/NOTICE.xml.gz
ALL_INSTALLED_NOTICE_FILES := \
- $(if $(USE_SOONG_DEFINED_SYSTEM_IMAGE),,$(installed_notice_html_or_xml_gz)) \
+ $(installed_notice_html_or_xml_gz) \
$(installed_vendor_notice_xml_gz) \
$(installed_product_notice_xml_gz) \
$(installed_system_ext_notice_xml_gz) \
@@ -1993,7 +1988,8 @@
# $1 installed file path, e.g. out/target/product/vsoc_x86_64/system_ext/etc/NOTICE.xml.gz
define is-notice-file
-$(if $(findstring $1,$(ALL_INSTALLED_NOTICE_FILES)),Y)
+$(if $(filter true,$(PRODUCT_USE_SOONG_NOTICE_XML)),, \
+ $(if $(findstring $1,$(ALL_INSTALLED_NOTICE_FILES)),Y))
endef
# Notice files are copied to TARGET_OUT_NOTICE_FILES as a side-effect of their module
@@ -2069,9 +2065,7 @@
endif # PRODUCT_NOTICE_SPLIT
-ifneq ($(USE_SOONG_DEFINED_SYSTEM_IMAGE),true)
ALL_DEFAULT_INSTALLED_MODULES += $(installed_notice_html_or_xml_gz)
-endif
need_vendor_notice:=false
ifeq ($(BUILDING_VENDOR_BOOT_IMAGE),true)
@@ -4464,6 +4458,25 @@
INTERNAL_PVMFW_EMBEDDED_AVBKEY := $(call module-target-built-files,pvmfw_embedded_key_pub_bin)
INTERNAL_PVMFW_SYMBOL := $(TARGET_OUT_EXECUTABLES_UNSTRIPPED)/pvmfw
+# If pvmfw target is not available and there is a prebuilt available use prebuilt
+# NOTE: This is only a temporary feature for x86_64 and is not meant to be supported for long.
+# TODO(b/391333413): Don't allow use of pvmfw prebuilts as soon as it is possible
+ifeq ($(INTERNAL_PVMFWIMAGE_FILES),)
+ifneq ($(PRODUCT_PVMFW_IMAGE_PREBUILT),)
+INTERNAL_PVMFWIMAGE_FILES := $(call module-target-built-files,$(PRODUCT_PVMFW_IMAGE_PREBUILT))
+INTERNAL_PVMFW_SYMBOL :=
+
+ifneq ($(PRODUCT_PVMFW_BIN_PREBUILT),)
+INSTALLED_PVMFW_BINARY_TARGET := $(call module-target-built-files,$(PRODUCT_PVMFW_BIN_PREBUILT))
+endif # PRODUCT_PVMFW_BIN_PREBUILT
+
+ifneq ($(PRODUCT_PVMFW_EMBEDDED_AVBKEY_PREBUILT),)
+INTERNAL_PVMFW_EMBEDDED_AVBKEY := $(call module-target-built-files,$(PRODUCT_PVMFW_EMBEDDED_AVBKEY_PREBUILT))
+endif # PRODUCT_PVMFW_EMBEDDED_AVBKEY_PREBUILT
+
+endif # PRODUCT_PVMFW_IMAGE_PREBUILT
+endif # INTERNAL_PVMFWIMAGE_FILES
+
$(call declare-1p-container,$(INSTALLED_PVMFWIMAGE_TARGET),)
$(call declare-container-license-deps,$(INSTALLED_PVMFWIMAGE_TARGET),$(INTERNAL_PVMFWIMAGE_FILES),$(PRODUCT_OUT)/:/)
diff --git a/core/main.mk b/core/main.mk
index 5ab807e..d670397 100644
--- a/core/main.mk
+++ b/core/main.mk
@@ -45,11 +45,6 @@
$(KATI_obsolete_var BUILD_HOSTNAME,Use BUILD_HOSTNAME_FROM_FILE instead)
$(KATI_obsolete_var FILE_NAME_TAG,https://android.googlesource.com/platform/build/+/master/Changes.md#FILE_NAME_TAG)
-$(BUILD_NUMBER_FILE):
- # empty rule to prevent dangling rule error for a file that is written by soong_ui
-$(BUILD_HOSTNAME_FILE):
- # empty rule to prevent dangling rule error for a file that is written by soong_ui
-
.KATI_RESTAT: $(BUILD_NUMBER_FILE)
.KATI_RESTAT: $(BUILD_HOSTNAME_FILE)
diff --git a/core/ninja_config.mk b/core/ninja_config.mk
index d4b7c6d..a1fff4d 100644
--- a/core/ninja_config.mk
+++ b/core/ninja_config.mk
@@ -19,8 +19,6 @@
build-art% \
build_kernel-nodeps \
clean-oat% \
- continuous_instrumentation_tests \
- continuous_native_tests \
cts \
custom_images \
dicttool_aosp \
diff --git a/core/os_licensing.mk b/core/os_licensing.mk
index d15a3d0..97e55a7 100644
--- a/core/os_licensing.mk
+++ b/core/os_licensing.mk
@@ -17,14 +17,14 @@
$(eval $(call text-notice-rule,$(target_notice_file_txt),"System image",$(system_notice_file_message),$(SYSTEM_NOTICE_DEPS),$(SYSTEM_NOTICE_DEPS)))
-ifneq ($(USE_SOONG_DEFINED_SYSTEM_IMAGE),true)
+ifneq ($(PRODUCT_USE_SOONG_NOTICE_XML),true)
$(installed_notice_html_or_xml_gz): $(target_notice_file_xml_gz)
$(copy-file-to-target)
endif
endif
$(call declare-1p-target,$(target_notice_file_xml_gz))
-ifneq ($(USE_SOONG_DEFINED_SYSTEM_IMAGE),true)
+ifneq ($(PRODUCT_USE_SOONG_NOTICE_XML),true)
$(call declare-1p-target,$(installed_notice_html_or_xml_gz))
endif
endif
@@ -44,12 +44,16 @@
"Notices for files contained in all filesystem images except system/system_ext/product/odm/vendor_dlkm/odm_dlkm in this directory:", \
$(VENDOR_NOTICE_DEPS),$(VENDOR_NOTICE_DEPS)))
+ifneq ($(PRODUCT_USE_SOONG_NOTICE_XML),true)
$(installed_vendor_notice_xml_gz): $(target_vendor_notice_file_xml_gz)
$(copy-file-to-target)
+endif
$(call declare-1p-target,$(target_vendor_notice_file_xml_gz))
+ifneq ($(PRODUCT_USE_SOONG_NOTICE_XML),true)
$(call declare-1p-target,$(installed_vendor_notice_xml_gz))
endif
+endif
.PHONY: odmlicense
odmlicense: $(call corresponding-license-metadata, $(ODM_NOTICE_DEPS)) reportmissinglicenses
@@ -63,12 +67,16 @@
"Notices for files contained in the odm filesystem image in this directory:", \
$(ODM_NOTICE_DEPS),$(ODM_NOTICE_DEPS)))
+ifneq ($(PRODUCT_USE_SOONG_NOTICE_XML),true)
$(installed_odm_notice_xml_gz): $(target_odm_notice_file_xml_gz)
$(copy-file-to-target)
+endif
$(call declare-1p-target,$(target_odm_notice_file_xml_gz))
+ifneq ($(PRODUCT_USE_SOONG_NOTICE_XML),true)
$(call declare-1p-target,$(installed_odm_notice_xml_gz))
endif
+endif
.PHONY: oemlicense
oemlicense: $(call corresponding-license-metadata, $(OEM_NOTICE_DEPS)) reportmissinglicenses
@@ -85,12 +93,16 @@
"Notices for files contained in the product filesystem image in this directory:", \
$(PRODUCT_NOTICE_DEPS),$(PRODUCT_NOTICE_DEPS)))
+ifneq ($(PRODUCT_USE_SOONG_NOTICE_XML),true)
$(installed_product_notice_xml_gz): $(target_product_notice_file_xml_gz)
$(copy-file-to-target)
+endif
$(call declare-1p-target,$(target_product_notice_file_xml_gz))
+ifneq ($(PRODUCT_USE_SOONG_NOTICE_XML),true)
$(call declare-1p-target,$(installed_product_notice_xml_gz))
endif
+endif
.PHONY: systemextlicense
systemextlicense: $(call corresponding-license-metadata, $(SYSTEM_EXT_NOTICE_DEPS)) reportmissinglicenses
@@ -104,12 +116,16 @@
"Notices for files contained in the system_ext filesystem image in this directory:", \
$(SYSTEM_EXT_NOTICE_DEPS),$(SYSTEM_EXT_NOTICE_DEPS)))
+ifneq ($(PRODUCT_USE_SOONG_NOTICE_XML),true)
$(installed_system_ext_notice_xml_gz): $(target_system_ext_notice_file_xml_gz)
$(copy-file-to-target)
+endif
$(call declare-1p-target,$(target_system_ext_notice_file_xml_gz))
+ifneq ($(PRODUCT_USE_SOONG_NOTICE_XML),true)
$(call declare-1p-target,$(installed_system_ext_notice_xml_gz))
endif
+endif
.PHONY: vendor_dlkmlicense
vendor_dlkmlicense: $(call corresponding-license-metadata, $(VENDOR_DLKM_NOTICE_DEPS)) reportmissinglicenses
@@ -123,12 +139,16 @@
"Notices for files contained in the vendor_dlkm filesystem image in this directory:", \
$(VENDOR_DLKM_NOTICE_DEPS),$(VENDOR_DLKM_NOTICE_DEPS)))
+ifneq ($(PRODUCT_USE_SOONG_NOTICE_XML),true)
$(installed_vendor_dlkm_notice_xml_gz): $(target_vendor_dlkm_notice_file_xml_gz)
$(copy-file-to-target)
+endif
$(call declare-1p-target,$(target_vendor_dlkm_notice_file_xml_gz))
+ifneq ($(PRODUCT_USE_SOONG_NOTICE_XML),true)
$(call declare-1p-target,$(installed_vendor_dlkm_notice_xml_gz))
endif
+endif
.PHONY: odm_dlkmlicense
odm_dlkmlicense: $(call corresponding-license-metadata, $(ODM_DLKM_NOTICE_DEPS)) reportmissinglicenses
@@ -142,12 +162,16 @@
"Notices for files contained in the odm_dlkm filesystem image in this directory:", \
$(ODM_DLKM_NOTICE_DEPS),$(ODM_DLKM_NOTICE_DEPS)))
+ifneq ($(PRODUCT_USE_SOONG_NOTICE_XML),true)
$(installed_odm_dlkm_notice_xml_gz): $(target_odm_dlkm_notice_file_xml_gz)
$(copy-file-to-target)
+endif
$(call declare-1p-target,$(target_odm_dlkm_notice_file_xml_gz))
+ifneq ($(PRODUCT_USE_SOONG_NOTICE_XML),true)
$(call declare-1p-target,$(installed_odm_dlkm_notice_xml_gz))
endif
+endif
.PHONY: system_dlkmlicense
system_dlkmlicense: $(call corresponding-license-metadata, $(SYSTEM_DLKM_NOTICE_DEPS)) reportmissinglicenses
@@ -161,11 +185,15 @@
"Notices for files contained in the system_dlkm filesystem image in this directory:", \
$(SYSTEM_DLKM_NOTICE_DEPS),$(SYSTEM_DLKM_NOTICE_DEPS)))
+ifneq ($(PRODUCT_USE_SOONG_NOTICE_XML),true)
$(installed_system_dlkm_notice_xml_gz): $(target_system_dlkm_notice_file_xml_gz)
$(copy-file-to-target)
+endif
$(call declare-1p-target,$(target_system_dlkm_notice_file_xml_gz))
+ifneq ($(PRODUCT_USE_SOONG_NOTICE_XML),true)
$(call declare-1p-target,$(installed_sysetm_dlkm_notice_xml_gz))
endif
+endif
endif # not TARGET_BUILD_APPS
diff --git a/core/product.mk b/core/product.mk
index 8031a34..1fbc3ee 100644
--- a/core/product.mk
+++ b/core/product.mk
@@ -505,6 +505,9 @@
# kati invocation will not be run.
_product_single_value_vars += PRODUCT_SOONG_ONLY
+# If set to true, use NOTICE.xml.gz generated by soong
+_product_single_value_vars += PRODUCT_USE_SOONG_NOTICE_XML
+
.KATI_READONLY := _product_single_value_vars _product_list_vars
_product_var_list :=$= $(_product_single_value_vars) $(_product_list_vars)
diff --git a/core/robolectric_test_config_template.xml b/core/robolectric_test_config_template.xml
index 2e4f700..509ac7b 100644
--- a/core/robolectric_test_config_template.xml
+++ b/core/robolectric_test_config_template.xml
@@ -18,7 +18,6 @@
<option name="test-suite-tag" value="robolectric" />
<option name="test-suite-tag" value="robolectric-tests" />
- <option name="java-folder" value="prebuilts/jdk/jdk21/linux-x86/" />
<option name="exclude-paths" value="java" />
<option name="use-robolectric-resources" value="true" />
diff --git a/core/soong_config.mk b/core/soong_config.mk
index b485285..dcd654d 100644
--- a/core/soong_config.mk
+++ b/core/soong_config.mk
@@ -254,6 +254,8 @@
$(call add_json_bool, UseSoongSystemImage, $(filter true,$(USE_SOONG_DEFINED_SYSTEM_IMAGE)))
$(call add_json_str, ProductSoongDefinedSystemImage, $(PRODUCT_SOONG_DEFINED_SYSTEM_IMAGE))
+$(call add_json_bool, UseSoongNoticeXML, $(filter true,$(PRODUCT_USE_SOONG_NOTICE_XML)))
+
$(call add_json_map, VendorVars)
$(foreach namespace,$(sort $(SOONG_CONFIG_NAMESPACES)),\
$(call add_json_map, $(namespace))\
diff --git a/core/tasks/cts.mk b/core/tasks/cts.mk
index d9f6150..1a55bf4 100644
--- a/core/tasks/cts.mk
+++ b/core/tasks/cts.mk
@@ -98,7 +98,7 @@
api_map_out := $(HOST_OUT)/cts-api-map
cts_jar_files := $(api_map_out)/cts_jar_files.txt
-cts_interactive_jar_files := $(api_map_out)/cts_interactive_jar_files.txt
+cts_v_host_jar_files := $(api_map_out)/cts_v_host_jar_files.txt
cts_all_jar_files := $(api_map_out)/cts_all_jar_files.txt
$(cts_jar_files): PRIVATE_API_MAP_FILES := $(sort $(COMPATIBILITY.cts.API_MAP_FILES))
@@ -106,14 +106,14 @@
mkdir -p $(dir $@)
echo $(PRIVATE_API_MAP_FILES) > $@
-$(cts_interactive_jar_files): PRIVATE_API_MAP_FILES := $(sort $(COMPATIBILITY.cts-interactive.API_MAP_FILES))
-$(cts_interactive_jar_files): $(SOONG_ANDROID_CTS_VERIFIER_APP_LIST)
+$(cts_v_host_jar_files): PRIVATE_API_MAP_FILES := $(sort $(COMPATIBILITY.cts-v-host.API_MAP_FILES))
+$(cts_v_host_jar_files): $(SOONG_ANDROID_CTS_VERIFIER_APP_LIST)
mkdir -p $(dir $@)
cp $< $@
echo $(PRIVATE_API_MAP_FILES) >> $@
$(cts_all_jar_files): PRIVATE_API_MAP_FILES := $(sort $(COMPATIBILITY.cts.API_MAP_FILES) \
- $(COMPATIBILITY.cts-interactive.API_MAP_FILES))
+ $(COMPATIBILITY.cts-v-host.API_MAP_FILES))
$(cts_all_jar_files): $(SOONG_ANDROID_CTS_VERIFIER_APP_LIST)
mkdir -p $(dir $@)
cp $< $@
@@ -129,6 +129,13 @@
$(hide) $(ACP) $< $@
system_api_xml_description := $(TARGET_OUT_COMMON_INTERMEDIATES)/system-api.xml
+module_lib_api_xml_description := $(TARGET_OUT_COMMON_INTERMEDIATES)/module-lib-api.xml
+system_service_api_description := $(TARGET_OUT_COMMON_INTERMEDIATES)/system-server-api.xml
+
+combined_api_xml_description := $(api_xml_description) \
+ $(system_api_xml_description) \
+ $(module_lib_api_xml_description) \
+ $(system_service_api_description)
cts-test-coverage-report := $(coverage_out)/test-coverage.html
cts-system-api-coverage-report := $(coverage_out)/system-api-coverage.html
@@ -140,14 +147,14 @@
cts_api_coverage_dependencies := $(cts_api_coverage_exe) $(dexdeps_exe) $(api_xml_description) $(napi_xml_description)
cts_system_api_coverage_dependencies := $(cts_api_coverage_exe) $(dexdeps_exe) $(system_api_xml_description)
-cts-system-api-map-xml-report := $(api_map_out)/cts-system-api-map.xml
-cts-interactive-system-api-map-xml-report := $(api_map_out)/cts-interactive-system-api-map.xml
-cts-combined-system-api-map-xml-report := $(api_map_out)/cts-combined-system-api-map.xml
-cts-combined-system-api-map-html-report := $(api_map_out)/cts-combined-system-api-map.html
+cts-api-map-xml-report := $(api_map_out)/cts-api-map.xml
+cts-v-host-api-map-xml-report := $(api_map_out)/cts-v-host-api-map.xml
+cts-combined-api-map-xml-report := $(api_map_out)/cts-combined-api-map.xml
+cts-combined-api-map-html-report := $(api_map_out)/cts-combined-api-map.html
-cts_system_api_map_dependencies := $(cts_api_map_exe) $(system_api_xml_description) $(cts_jar_files)
-cts_interactive_system_api_map_dependencies := $(cts_api_map_exe) $(system_api_xml_description) $(cts_interactive_jar_files)
-cts_combined_system_api_map_dependencies := $(cts_api_map_exe) $(system_api_xml_description) $(cts_all_jar_files)
+cts_api_map_dependencies := $(cts_api_map_exe) $(combined_api_xml_description) $(cts_jar_files)
+cts_v_host_api_map_dependencies := $(cts_api_map_exe) $(combined_api_xml_description) $(cts_v_host_jar_files)
+cts_combined_api_map_dependencies := $(cts_api_map_exe) $(combined_api_xml_description) $(cts_all_jar_files)
android_cts_zip := $(HOST_OUT)/cts/android-cts.zip
cts_verifier_apk := $(call intermediates-dir-for,APPS,CtsVerifier)/package.apk
@@ -227,42 +234,42 @@
.PHONY: cts-coverage-report-all cts-api-coverage
cts-coverage-report-all: cts-test-coverage cts-verifier-coverage cts-combined-coverage cts-combined-xml-coverage
-$(cts-system-api-map-xml-report): PRIVATE_CTS_API_MAP_EXE := $(cts_api_map_exe)
-$(cts-system-api-map-xml-report): PRIVATE_API_XML_DESC := $(system_api_xml_description)
-$(cts-system-api-map-xml-report): PRIVATE_JAR_FILES := $(cts_jar_files)
-$(cts-system-api-map-xml-report) : $(android_cts_zip) $(cts_system_api_map_dependencies) | $(ACP)
- $(call generate-api-map-report-cts,"CTS System API MAP Report - XML",\
+$(cts-api-map-xml-report): PRIVATE_CTS_API_MAP_EXE := $(cts_api_map_exe)
+$(cts-api-map-xml-report): PRIVATE_API_XML_DESC := $(combined_api_xml_description)
+$(cts-api-map-xml-report): PRIVATE_JAR_FILES := $(cts_jar_files)
+$(cts-api-map-xml-report) : $(android_cts_zip) $(cts_api_map_dependencies) | $(ACP)
+ $(call generate-api-map-report-cts,"CTS API MAP Report - XML",\
$(PRIVATE_JAR_FILES),xml)
-$(cts-interactive-system-api-map-xml-report): PRIVATE_CTS_API_MAP_EXE := $(cts_api_map_exe)
-$(cts-interactive-system-api-map-xml-report): PRIVATE_API_XML_DESC := $(system_api_xml_description)
-$(cts-interactive-system-api-map-xml-report): PRIVATE_JAR_FILES := $(cts_interactive_jar_files)
-$(cts-interactive-system-api-map-xml-report) : $(verifier_zip) $(cts_interactive_system_api_map_dependencies) | $(ACP)
- $(call generate-api-map-report-cts,"CTS Interactive System API MAP Report - XML",\
+$(cts-v-host-api-map-xml-report): PRIVATE_CTS_API_MAP_EXE := $(cts_api_map_exe)
+$(cts-v-host-api-map-xml-report): PRIVATE_API_XML_DESC := $(combined_api_xml_description)
+$(cts-v-host-api-map-xml-report): PRIVATE_JAR_FILES := $(cts_v_host_jar_files)
+$(cts-v-host-api-map-xml-report) : $(verifier_zip) $(cts_v_host_api_map_dependencies) | $(ACP)
+ $(call generate-api-map-report-cts,"CTS-V-HOST API MAP Report - XML",\
$(PRIVATE_JAR_FILES),xml)
-$(cts-combined-system-api-map-xml-report): PRIVATE_CTS_API_MAP_EXE := $(cts_api_map_exe)
-$(cts-combined-system-api-map-xml-report): PRIVATE_API_XML_DESC := $(system_api_xml_description)
-$(cts-combined-system-api-map-xml-report): PRIVATE_JAR_FILES := $(cts_all_jar_files)
-$(cts-combined-system-api-map-xml-report) : $(verifier_zip) $(android_cts_zip) $(cts_combined_system_api_map_dependencies) | $(ACP)
- $(call generate-api-map-report-cts,"CTS Combined System API MAP Report - XML",\
+$(cts-combined-api-map-xml-report): PRIVATE_CTS_API_MAP_EXE := $(cts_api_map_exe)
+$(cts-combined-api-map-xml-report): PRIVATE_API_XML_DESC := $(combined_api_xml_description)
+$(cts-combined-api-map-xml-report): PRIVATE_JAR_FILES := $(cts_all_jar_files)
+$(cts-combined-api-map-xml-report) : $(verifier_zip) $(android_cts_zip) $(cts_combined_api_map_dependencies) | $(ACP)
+ $(call generate-api-map-report-cts,"CTS Combined API MAP Report - XML",\
$(PRIVATE_JAR_FILES),xml)
-$(cts-combined-system-api-map-html-report): PRIVATE_CTS_API_MAP_EXE := $(cts_api_map_exe)
-$(cts-combined-system-api-map-html-report): PRIVATE_API_XML_DESC := $(system_api_xml_description)
-$(cts-combined-system-api-map-html-report): PRIVATE_JAR_FILES := $(cts_all_jar_files)
-$(cts-combined-system-api-map-html-report) : $(verifier_zip) $(android_cts_zip) $(cts_combined_system_api_map_dependencies) | $(ACP)
- $(call generate-api-map-report-cts,"CTS Combined System API MAP Report - HTML",\
+$(cts-combined-api-map-html-report): PRIVATE_CTS_API_MAP_EXE := $(cts_api_map_exe)
+$(cts-combined-api-map-html-report): PRIVATE_API_XML_DESC := $(combined_api_xml_description)
+$(cts-combined-api-map-html-report): PRIVATE_JAR_FILES := $(cts_all_jar_files)
+$(cts-combined-api-map-html-report) : $(verifier_zip) $(android_cts_zip) $(cts_combined_api_map_dependencies) | $(ACP)
+ $(call generate-api-map-report-cts,"CTS Combined API MAP Report - HTML",\
$(PRIVATE_JAR_FILES),html)
-.PHONY: cts-system-api-map-xml
-cts-system-api-map-xml : $(cts-system-api-map-xml-report)
+.PHONY: cts-api-map-xml
+cts-api-map-xml : $(cts-api-map-xml-report)
-.PHONY: cts-interactive-system-api-map-xml
-cts-interactive-system-api-map-xml: $(cts-interactive-system-api-map-xml-report)
+.PHONY: cts-v-host-api-map-xml
+cts-v-host-api-map-xml: $(cts-v-host-api-map-xml-report)
-.PHONY: cts-combined-system-api-map-xml
-cts-combined-system-api-map-xml : $(cts-combined-system-api-map-xml-report)
+.PHONY: cts-combined-api-map-xml
+cts-combined-api-map-xml : $(cts-combined-api-map-xml-report)
.PHONY: cts-api-map-all
@@ -282,13 +289,13 @@
ALL_TARGETS.$(cts-combined-xml-coverage-report).META_LIC:=$(module_license_metadata)
# Put the test api map report in the dist dir if "cts-api-map-all" is among the build goals.
-$(call dist-for-goals, cts-api-map-all, $(cts-combined-system-api-map-xml-report):cts-api-map-report.xml)
-$(call dist-for-goals, cts-api-map-all, $(cts-combined-system-api-map-html-report):cts-api-map-report.html)
+$(call dist-for-goals, cts-api-map-all, $(cts-combined-api-map-xml-report):cts-api-map-report.xml)
+$(call dist-for-goals, cts-api-map-all, $(cts-combined-api-map-html-report):cts-api-map-report.html)
-ALL_TARGETS.$(cts-system-api-map-xml-report).META_LIC:=$(module_license_metadata)
-ALL_TARGETS.$(cts-interactive-system-api-map-xml-report).META_LIC:=$(module_license_metadata)
-ALL_TARGETS.$(cts-combined-system-api-map-xml-report).META_LIC:=$(module_license_metadata)
-ALL_TARGETS.$(cts-combined-system-api-map-html-report).META_LIC:=$(module_license_metadata)
+ALL_TARGETS.$(cts-api-map-xml-report).META_LIC:=$(module_license_metadata)
+ALL_TARGETS.$(cts-v-host-api-map-xml-report).META_LIC:=$(module_license_metadata)
+ALL_TARGETS.$(cts-combined-api-map-xml-report).META_LIC:=$(module_license_metadata)
+ALL_TARGETS.$(cts-combined-api-map-html-report).META_LIC:=$(module_license_metadata)
# Arguments;
# 1 - Name of the report printed out on the screen
@@ -306,29 +313,30 @@
# 3 - Format of the report
define generate-api-map-report-cts
$(hide) mkdir -p $(dir $@)
- $(hide) $(PRIVATE_CTS_API_MAP_EXE) -j 8 -a $(PRIVATE_API_XML_DESC) -i $(2) -f $(3) -o $@
+ $(hide) $(PRIVATE_CTS_API_MAP_EXE) -j 8 -a $(shell echo "$(PRIVATE_API_XML_DESC)" | tr ' ' ',') -i $(2) -f $(3) -o $@
@ echo $(1): file://$$(cd $(dir $@); pwd)/$(notdir $@)
endef
# Reset temp vars
cts_api_coverage_dependencies :=
cts_system_api_coverage_dependencies :=
-cts_system_api_map_dependencies :=
-cts_interactive_system_api_map_dependencies :=
-cts_combined_system_api_map_dependencies :=
+cts_api_map_dependencies :=
+cts_v_host_api_map_dependencies :=
+cts_combined_api_map_dependencies :=
cts-combined-coverage-report :=
cts-combined-xml-coverage-report :=
cts-verifier-coverage-report :=
cts-test-coverage-report :=
cts-system-api-coverage-report :=
cts-system-api-xml-coverage-report :=
-cts-system-api-map-xml-report :=
-cts-interactive-system-api-map-xml-report :=
-cts-combined-system-api-map-xml-report :=
-cts-combined-system-api-map-html-report :=
+cts-api-map-xml-report :=
+cts-v-host-api-map-xml-report :=
+cts-combined-api-map-xml-report :=
+cts-combined-api-map-html-report :=
api_xml_description :=
api_text_description :=
system_api_xml_description :=
+combined_api_xml_description :=
napi_xml_description :=
napi_text_description :=
coverage_out :=
diff --git a/target/product/base_system.mk b/target/product/base_system.mk
index 797a20e..40e2aa1 100644
--- a/target/product/base_system.mk
+++ b/target/product/base_system.mk
@@ -514,6 +514,7 @@
logtagd.rc \
ot-cli-ftd \
ot-ctl \
+ overlay_remounter \
procrank \
profcollectd \
profcollectctl \
diff --git a/target/product/generic/Android.bp b/target/product/generic/Android.bp
index f21e4b3..643f312 100644
--- a/target/product/generic/Android.bp
+++ b/target/product/generic/Android.bp
@@ -376,8 +376,8 @@
"charger",
] + select(release_flag("RELEASE_APPFUNCTION_SIDECAR"), {
true: [
- "com.android.extensions.appfunctions",
- "appfunctions.extension.xml",
+ "com.google.android.appfunctions.sidecar",
+ "appfunctions.sidecar.xml",
],
default: [],
}),
@@ -679,6 +679,7 @@
"logtagd.rc",
"ot-cli-ftd",
"ot-ctl",
+ "overlay_remounter",
"procrank",
"profcollectctl",
"profcollectd",
diff --git a/target/product/generic_system.mk b/target/product/generic_system.mk
index b9a623d..2482afc 100644
--- a/target/product/generic_system.mk
+++ b/target/product/generic_system.mk
@@ -36,11 +36,6 @@
Stk \
Tag \
-ifeq ($(RELEASE_AVATAR_PICKER_APP),true)
- PRODUCT_PACKAGES += \
- AvatarPicker
-endif
-
# OTA support
PRODUCT_PACKAGES += \
recovery-refresh \
diff --git a/target/product/gsi/Android.bp b/target/product/gsi/Android.bp
index a119832..97b3895 100644
--- a/target/product/gsi/Android.bp
+++ b/target/product/gsi/Android.bp
@@ -137,6 +137,7 @@
"Dialer",
"LatinIME",
"apns-full-conf.xml",
+ "frameworks-base-overlays",
],
multilib: {
lib64: {
diff --git a/target/product/handheld_system.mk b/target/product/handheld_system.mk
index 2b055c7..6799066 100644
--- a/target/product/handheld_system.mk
+++ b/target/product/handheld_system.mk
@@ -34,6 +34,7 @@
PRODUCT_PACKAGES += \
android.software.window_magnification.prebuilt.xml \
+ $(if $(RELEASE_AVATAR_PICKER_APP), AvatarPicker,) \
BasicDreams \
BlockedNumberProvider \
BluetoothMidiService \
diff --git a/target/product/runtime_libart.mk b/target/product/runtime_libart.mk
index fa65a4e..71138ac 100644
--- a/target/product/runtime_libart.mk
+++ b/target/product/runtime_libart.mk
@@ -158,15 +158,14 @@
dalvik.vm.minidebuginfo=true \
dalvik.vm.dex2oat-minidebuginfo=true
-# Enable Madvising of the whole art, odex and vdex files to MADV_WILLNEED.
+# Enable Madvising of the whole odex and vdex files to MADV_WILLNEED.
# The size specified here is the size limit of how much of the file
# (in bytes) is madvised.
-# We madvise the whole .art file to MADV_WILLNEED with UINT_MAX limit.
# For odex and vdex files, we limit madvising to 100MB.
+# For art files, we defer to the runtime for default behavior.
PRODUCT_SYSTEM_PROPERTIES += \
dalvik.vm.madvise.vdexfile.size=104857600 \
- dalvik.vm.madvise.odexfile.size=104857600 \
- dalvik.vm.madvise.artfile.size=4294967295
+ dalvik.vm.madvise.odexfile.size=104857600
# Properties for the Unspecialized App Process Pool
PRODUCT_SYSTEM_PROPERTIES += \
diff --git a/teams/OWNERS b/teams/OWNERS
index 85e69f3..02846eb 100644
--- a/teams/OWNERS
+++ b/teams/OWNERS
@@ -1,3 +1,2 @@
dariofreni@google.com
ronish@google.com
-caditya@google.com
diff --git a/tools/aconfig/aconfig/data/Android.bp b/tools/aconfig/aconfig/data/Android.bp
new file mode 100644
index 0000000..1b5eef0
--- /dev/null
+++ b/tools/aconfig/aconfig/data/Android.bp
@@ -0,0 +1,14 @@
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+python_binary_host {
+ name: "convert_finalized_flags_to_proto",
+ srcs: ["convert_finalized_flags_to_proto.py"],
+ libs: ["aconfig_internal_proto_python"],
+ version: {
+ py3: {
+ embedded_launcher: true,
+ },
+ },
+}
diff --git a/tools/aconfig/aconfig/data/convert_finalized_flags_to_proto.py b/tools/aconfig/aconfig/data/convert_finalized_flags_to_proto.py
new file mode 100644
index 0000000..15ff03c
--- /dev/null
+++ b/tools/aconfig/aconfig/data/convert_finalized_flags_to_proto.py
@@ -0,0 +1,83 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2024 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import collections
+import sys
+import os
+
+from io import TextIOWrapper
+from protos import aconfig_internal_pb2
+from typing import Dict, List, Set
+
+def extract_finalized_flags(flag_file: TextIOWrapper):
+ finalized_flags_for_sdk = list()
+
+ for line in f:
+ flag_name = line.strip()
+ if flag_name:
+ finalized_flags_for_sdk.append(flag_name)
+
+ return finalized_flags_for_sdk
+
+def remove_duplicate_flags(all_flags_with_duplicates: Dict[int, List]):
+ result_flags = collections.defaultdict(set)
+
+ for api_level in sorted(all_flags_with_duplicates.keys(), key=int):
+ for flag in all_flags_with_duplicates[api_level]:
+ if not any(flag in value_set for value_set in result_flags.values()):
+ result_flags[api_level].add(flag)
+
+ return result_flags
+
+def build_proto(all_flags: Set):
+ finalized_flags = aconfig_internal_pb2.finalized_flags()
+ for api_level, qualified_name_list in all_flags.items():
+ for qualified_name in qualified_name_list:
+ package_name, flag_name = qualified_name.rsplit('.', 1)
+ finalized_flag = aconfig_internal_pb2.finalized_flag()
+ finalized_flag.name = flag_name
+ finalized_flag.package = package_name
+ finalized_flag.min_sdk = api_level
+ finalized_flags.finalized_flag.append(finalized_flag)
+ return finalized_flags
+
+if __name__ == '__main__':
+ if len(sys.argv) == 1:
+ sys.exit('No prebuilts/sdk directory provided.')
+ all_api_info_dir = sys.argv[1]
+
+ all_flags_with_duplicates = {}
+ for sdk_dir in os.listdir(all_api_info_dir):
+ api_level = sdk_dir.rsplit('/', 1)[0].rstrip('0').rstrip('.')
+
+ # No support for minor versions yet. This also removes non-numeric dirs.
+ # Update once floats are acceptable.
+ if not api_level.isdigit():
+ continue
+
+ flag_file_path = os.path.join(all_api_info_dir, sdk_dir, 'finalized-flags.txt')
+ try:
+ with open(flag_file_path, 'r') as f:
+ finalized_flags_for_sdk = extract_finalized_flags(f)
+ all_flags_with_duplicates[int(api_level)] = finalized_flags_for_sdk
+ except FileNotFoundError:
+ # Either this version is not finalized yet or looking at a
+ # /prebuilts/sdk/version before finalized-flags.txt was introduced.
+ continue
+
+ all_flags = remove_duplicate_flags(all_flags_with_duplicates)
+ finalized_flags = build_proto(all_flags)
+ sys.stdout.buffer.write(finalized_flags.SerializeToString())
diff --git a/tools/aconfig/aconfig/src/codegen/cpp.rs b/tools/aconfig/aconfig/src/codegen/cpp.rs
index d7d77c5..30e1a89 100644
--- a/tools/aconfig/aconfig/src/codegen/cpp.rs
+++ b/tools/aconfig/aconfig/src/codegen/cpp.rs
@@ -31,7 +31,6 @@
parsed_flags_iter: I,
codegen_mode: CodegenMode,
flag_ids: HashMap<String, u16>,
- allow_instrumentation: bool,
) -> Result<Vec<OutputFile>>
where
I: Iterator<Item = ProtoParsedFlag>,
@@ -59,7 +58,6 @@
is_test_mode: codegen_mode == CodegenMode::Test,
class_elements,
container,
- allow_instrumentation,
};
let files = [
@@ -104,7 +102,6 @@
pub is_test_mode: bool,
pub class_elements: Vec<ClassElement>,
pub container: String,
- pub allow_instrumentation: bool,
}
#[derive(Serialize)]
@@ -451,56 +448,6 @@
"#;
- const EXPORTED_EXPORTED_HEADER_EXPECTED: &str = r#"
-#pragma once
-
-#ifdef __cplusplus
-
-#include <memory>
-
-namespace com::android::aconfig::test {
-
-class flag_provider_interface {
-public:
- virtual ~flag_provider_interface() = default;
-
- virtual bool disabled_rw_exported() = 0;
-
- virtual bool enabled_fixed_ro_exported() = 0;
-
- virtual bool enabled_ro_exported() = 0;
-};
-
-extern std::unique_ptr<flag_provider_interface> provider_;
-
-inline bool disabled_rw_exported() {
- return provider_->disabled_rw_exported();
-}
-
-inline bool enabled_fixed_ro_exported() {
- return provider_->enabled_fixed_ro_exported();
-}
-
-inline bool enabled_ro_exported() {
- return provider_->enabled_ro_exported();
-}
-
-}
-
-extern "C" {
-#endif // __cplusplus
-
-bool com_android_aconfig_test_disabled_rw_exported();
-
-bool com_android_aconfig_test_enabled_fixed_ro_exported();
-
-bool com_android_aconfig_test_enabled_ro_exported();
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-"#;
-
const EXPORTED_FORCE_READ_ONLY_HEADER_EXPECTED: &str = r#"
#pragma once
@@ -585,7 +532,13 @@
const PROD_SOURCE_FILE_EXPECTED: &str = r#"
#include "com_android_aconfig_test.h"
-#include <server_configurable_flags/get_flags.h>
+
+#include <unistd.h>
+#include "aconfig_storage/aconfig_storage_read_api.hpp"
+#include <android/log.h>
+#define LOG_TAG "aconfig_cpp_codegen"
+#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
+
#include <vector>
namespace com::android::aconfig::test {
@@ -593,36 +546,116 @@
class flag_provider : public flag_provider_interface {
public:
+ flag_provider()
+ : cache_(4, -1)
+ , boolean_start_index_()
+ , flag_value_file_(nullptr)
+ , package_exists_in_storage_(true) {
+
+ auto package_map_file = aconfig_storage::get_mapped_file(
+ "system",
+ aconfig_storage::StorageFileType::package_map);
+ if (!package_map_file.ok()) {
+ ALOGE("error: failed to get package map file: %s", package_map_file.error().c_str());
+ package_exists_in_storage_ = false;
+ return;
+ }
+
+ auto context = aconfig_storage::get_package_read_context(
+ **package_map_file, "com.android.aconfig.test");
+ if (!context.ok()) {
+ ALOGE("error: failed to get package read context: %s", context.error().c_str());
+ package_exists_in_storage_ = false;
+ return;
+ }
+
+ if (!(context->package_exists)) {
+ package_exists_in_storage_ = false;
+ return;
+ }
+
+ // cache package boolean flag start index
+ boolean_start_index_ = context->boolean_start_index;
+
+ // unmap package map file and free memory
+ delete *package_map_file;
+
+ auto flag_value_file = aconfig_storage::get_mapped_file(
+ "system",
+ aconfig_storage::StorageFileType::flag_val);
+ if (!flag_value_file.ok()) {
+ ALOGE("error: failed to get flag value file: %s", flag_value_file.error().c_str());
+ package_exists_in_storage_ = false;
+ return;
+ }
+
+ // cache flag value file
+ flag_value_file_ = std::unique_ptr<aconfig_storage::MappedStorageFile>(
+ *flag_value_file);
+
+ }
+
+
virtual bool disabled_ro() override {
return false;
}
virtual bool disabled_rw() override {
if (cache_[0] == -1) {
- cache_[0] = server_configurable_flags::GetServerConfigurableFlag(
- "aconfig_flags.aconfig_test",
- "com.android.aconfig.test.disabled_rw",
- "false") == "true";
+ if (!package_exists_in_storage_) {
+ return false;
+ }
+
+ auto value = aconfig_storage::get_boolean_flag_value(
+ *flag_value_file_,
+ boolean_start_index_ + 0);
+
+ if (!value.ok()) {
+ ALOGE("error: failed to read flag value: %s", value.error().c_str());
+ return false;
+ }
+
+ cache_[0] = *value;
}
return cache_[0];
}
virtual bool disabled_rw_exported() override {
if (cache_[1] == -1) {
- cache_[1] = server_configurable_flags::GetServerConfigurableFlag(
- "aconfig_flags.aconfig_test",
- "com.android.aconfig.test.disabled_rw_exported",
- "false") == "true";
+ if (!package_exists_in_storage_) {
+ return false;
+ }
+
+ auto value = aconfig_storage::get_boolean_flag_value(
+ *flag_value_file_,
+ boolean_start_index_ + 1);
+
+ if (!value.ok()) {
+ ALOGE("error: failed to read flag value: %s", value.error().c_str());
+ return false;
+ }
+
+ cache_[1] = *value;
}
return cache_[1];
}
virtual bool disabled_rw_in_other_namespace() override {
if (cache_[2] == -1) {
- cache_[2] = server_configurable_flags::GetServerConfigurableFlag(
- "aconfig_flags.other_namespace",
- "com.android.aconfig.test.disabled_rw_in_other_namespace",
- "false") == "true";
+ if (!package_exists_in_storage_) {
+ return false;
+ }
+
+ auto value = aconfig_storage::get_boolean_flag_value(
+ *flag_value_file_,
+ boolean_start_index_ + 2);
+
+ if (!value.ok()) {
+ ALOGE("error: failed to read flag value: %s", value.error().c_str());
+ return false;
+ }
+
+ cache_[2] = *value;
}
return cache_[2];
}
@@ -645,16 +678,32 @@
virtual bool enabled_rw() override {
if (cache_[3] == -1) {
- cache_[3] = server_configurable_flags::GetServerConfigurableFlag(
- "aconfig_flags.aconfig_test",
- "com.android.aconfig.test.enabled_rw",
- "true") == "true";
+ if (!package_exists_in_storage_) {
+ return true;
+ }
+
+ auto value = aconfig_storage::get_boolean_flag_value(
+ *flag_value_file_,
+ boolean_start_index_ + 7);
+
+ if (!value.ok()) {
+ ALOGE("error: failed to read flag value: %s", value.error().c_str());
+ return true;
+ }
+
+ cache_[3] = *value;
}
return cache_[3];
}
private:
std::vector<int8_t> cache_ = std::vector<int8_t>(4, -1);
+
+ uint32_t boolean_start_index_;
+
+ std::unique_ptr<aconfig_storage::MappedStorageFile> flag_value_file_;
+
+ bool package_exists_in_storage_;
};
std::unique_ptr<flag_provider_interface> provider_ =
@@ -701,7 +750,13 @@
const TEST_SOURCE_FILE_EXPECTED: &str = r#"
#include "com_android_aconfig_test.h"
-#include <server_configurable_flags/get_flags.h>
+
+#include <unistd.h>
+#include "aconfig_storage/aconfig_storage_read_api.hpp"
+#include <android/log.h>
+#define LOG_TAG "aconfig_cpp_codegen"
+#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
+
#include <unordered_map>
#include <string>
@@ -711,10 +766,63 @@
private:
std::unordered_map<std::string, bool> overrides_;
+ uint32_t boolean_start_index_;
+
+ std::unique_ptr<aconfig_storage::MappedStorageFile> flag_value_file_;
+
+ bool package_exists_in_storage_;
+
public:
flag_provider()
: overrides_()
- {}
+ , boolean_start_index_()
+ , flag_value_file_(nullptr)
+ , package_exists_in_storage_(true) {
+
+ auto package_map_file = aconfig_storage::get_mapped_file(
+ "system",
+ aconfig_storage::StorageFileType::package_map);
+
+ if (!package_map_file.ok()) {
+ ALOGE("error: failed to get package map file: %s", package_map_file.error().c_str());
+ package_exists_in_storage_ = false;
+ return;
+ }
+
+ auto context = aconfig_storage::get_package_read_context(
+ **package_map_file, "com.android.aconfig.test");
+
+ if (!context.ok()) {
+ ALOGE("error: failed to get package read context: %s", context.error().c_str());
+ package_exists_in_storage_ = false;
+ return;
+ }
+
+ if (!(context->package_exists)) {
+ package_exists_in_storage_ = false;
+ return;
+ }
+
+ // cache package boolean flag start index
+ boolean_start_index_ = context->boolean_start_index;
+
+ // unmap package map file and free memory
+ delete *package_map_file;
+
+ auto flag_value_file = aconfig_storage::get_mapped_file(
+ "system",
+ aconfig_storage::StorageFileType::flag_val);
+ if (!flag_value_file.ok()) {
+ ALOGE("error: failed to get flag value file: %s", flag_value_file.error().c_str());
+ package_exists_in_storage_ = false;
+ return;
+ }
+
+ // cache flag value file
+ flag_value_file_ = std::unique_ptr<aconfig_storage::MappedStorageFile>(
+ *flag_value_file);
+
+ }
virtual bool disabled_ro() override {
auto it = overrides_.find("disabled_ro");
@@ -734,10 +842,20 @@
if (it != overrides_.end()) {
return it->second;
} else {
- return server_configurable_flags::GetServerConfigurableFlag(
- "aconfig_flags.aconfig_test",
- "com.android.aconfig.test.disabled_rw",
- "false") == "true";
+ if (!package_exists_in_storage_) {
+ return false;
+ }
+
+ auto value = aconfig_storage::get_boolean_flag_value(
+ *flag_value_file_,
+ boolean_start_index_ + 0);
+
+ if (!value.ok()) {
+ ALOGE("error: failed to read flag value: %s", value.error().c_str());
+ return false;
+ } else {
+ return *value;
+ }
}
}
@@ -750,10 +868,20 @@
if (it != overrides_.end()) {
return it->second;
} else {
- return server_configurable_flags::GetServerConfigurableFlag(
- "aconfig_flags.aconfig_test",
- "com.android.aconfig.test.disabled_rw_exported",
- "false") == "true";
+ if (!package_exists_in_storage_) {
+ return false;
+ }
+
+ auto value = aconfig_storage::get_boolean_flag_value(
+ *flag_value_file_,
+ boolean_start_index_ + 1);
+
+ if (!value.ok()) {
+ ALOGE("error: failed to read flag value: %s", value.error().c_str());
+ return false;
+ } else {
+ return *value;
+ }
}
}
@@ -766,10 +894,20 @@
if (it != overrides_.end()) {
return it->second;
} else {
- return server_configurable_flags::GetServerConfigurableFlag(
- "aconfig_flags.other_namespace",
- "com.android.aconfig.test.disabled_rw_in_other_namespace",
- "false") == "true";
+ if (!package_exists_in_storage_) {
+ return false;
+ }
+
+ auto value = aconfig_storage::get_boolean_flag_value(
+ *flag_value_file_,
+ boolean_start_index_ + 2);
+
+ if (!value.ok()) {
+ ALOGE("error: failed to read flag value: %s", value.error().c_str());
+ return false;
+ } else {
+ return *value;
+ }
}
}
@@ -834,10 +972,20 @@
if (it != overrides_.end()) {
return it->second;
} else {
- return server_configurable_flags::GetServerConfigurableFlag(
- "aconfig_flags.aconfig_test",
- "com.android.aconfig.test.enabled_rw",
- "true") == "true";
+ if (!package_exists_in_storage_) {
+ return true;
+ }
+
+ auto value = aconfig_storage::get_boolean_flag_value(
+ *flag_value_file_,
+ boolean_start_index_ + 7);
+
+ if (!value.ok()) {
+ ALOGE("error: failed to read flag value: %s", value.error().c_str());
+ return true;
+ } else {
+ return *value;
+ }
}
}
@@ -942,68 +1090,6 @@
"#;
- const EXPORTED_SOURCE_FILE_EXPECTED: &str = r#"
-#include "com_android_aconfig_test.h"
-#include <server_configurable_flags/get_flags.h>
-#include <vector>
-
-namespace com::android::aconfig::test {
-
- class flag_provider : public flag_provider_interface {
- public:
- virtual bool disabled_rw_exported() override {
- if (cache_[0] == -1) {
- cache_[0] = server_configurable_flags::GetServerConfigurableFlag(
- "aconfig_flags.aconfig_test",
- "com.android.aconfig.test.disabled_rw_exported",
- "false") == "true";
- }
- return cache_[0];
- }
-
- virtual bool enabled_fixed_ro_exported() override {
- if (cache_[1] == -1) {
- cache_[1] = server_configurable_flags::GetServerConfigurableFlag(
- "aconfig_flags.aconfig_test",
- "com.android.aconfig.test.enabled_fixed_ro_exported",
- "false") == "true";
- }
- return cache_[1];
- }
-
- virtual bool enabled_ro_exported() override {
- if (cache_[2] == -1) {
- cache_[2] = server_configurable_flags::GetServerConfigurableFlag(
- "aconfig_flags.aconfig_test",
- "com.android.aconfig.test.enabled_ro_exported",
- "false") == "true";
- }
- return cache_[2];
- }
-
- private:
- std::vector<int8_t> cache_ = std::vector<int8_t>(3, -1);
- };
-
- std::unique_ptr<flag_provider_interface> provider_ =
- std::make_unique<flag_provider>();
-}
-
-bool com_android_aconfig_test_disabled_rw_exported() {
- return com::android::aconfig::test::disabled_rw_exported();
-}
-
-bool com_android_aconfig_test_enabled_fixed_ro_exported() {
- return com::android::aconfig::test::enabled_fixed_ro_exported();
-}
-
-bool com_android_aconfig_test_enabled_ro_exported() {
- return com::android::aconfig::test::enabled_ro_exported();
-}
-
-
-"#;
-
const FORCE_READ_ONLY_SOURCE_FILE_EXPECTED: &str = r#"
#include "com_android_aconfig_test.h"
@@ -1188,7 +1274,6 @@
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();
@@ -1199,7 +1284,6 @@
modified_parsed_flags.into_iter(),
mode,
flag_ids,
- allow_instrumentation,
)
.unwrap();
let mut generated_files_map = HashMap::new();
@@ -1239,7 +1323,6 @@
CodegenMode::Production,
EXPORTED_PROD_HEADER_EXPECTED,
PROD_SOURCE_FILE_EXPECTED,
- false,
);
}
@@ -1251,19 +1334,6 @@
CodegenMode::Test,
EXPORTED_TEST_HEADER_EXPECTED,
TEST_SOURCE_FILE_EXPECTED,
- false,
- );
- }
-
- #[test]
- fn test_generate_cpp_code_for_exported() {
- let parsed_flags = crate::test::parse_test_flags();
- test_generate_cpp_code(
- parsed_flags,
- CodegenMode::Exported,
- EXPORTED_EXPORTED_HEADER_EXPECTED,
- EXPORTED_SOURCE_FILE_EXPECTED,
- false,
);
}
@@ -1275,7 +1345,6 @@
CodegenMode::ForceReadOnly,
EXPORTED_FORCE_READ_ONLY_HEADER_EXPECTED,
FORCE_READ_ONLY_SOURCE_FILE_EXPECTED,
- false,
);
}
@@ -1287,7 +1356,6 @@
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 44bb8aa..8588a72 100644
--- a/tools/aconfig/aconfig/src/codegen/java.rs
+++ b/tools/aconfig/aconfig/src/codegen/java.rs
@@ -74,10 +74,7 @@
};
let mut template = TinyTemplate::new();
template.add_template("Flags.java", include_str!("../../templates/Flags.java.template"))?;
- template.add_template(
- "FeatureFlagsImpl.java",
- include_str!("../../templates/FeatureFlagsImpl.java.template"),
- )?;
+ add_feature_flags_impl_template(&context, &mut template)?;
template.add_template(
"FeatureFlags.java",
include_str!("../../templates/FeatureFlags.java.template"),
@@ -233,6 +230,58 @@
format!("mProperties{}{}", &name[0..1].to_ascii_uppercase(), &name[1..])
}
+fn add_feature_flags_impl_template(
+ context: &Context,
+ template: &mut TinyTemplate,
+) -> Result<(), tinytemplate::error::Error> {
+ if context.is_test_mode {
+ // Test mode has its own template, so use regardless of any other settings.
+ template.add_template(
+ "FeatureFlagsImpl.java",
+ include_str!("../../templates/FeatureFlagsImpl.test_mode.java.template"),
+ )?;
+ return Ok(());
+ }
+
+ match (context.library_exported, context.new_exported, context.allow_instrumentation) {
+ // Exported library with new_exported enabled, use new storage exported template.
+ (true, true, _) => {
+ template.add_template(
+ "FeatureFlagsImpl.java",
+ include_str!("../../templates/FeatureFlagsImpl.exported.java.template"),
+ )?;
+ }
+
+ // Exported library with new_exported NOT enabled, use legacy (device
+ // config) template, because regardless of allow_instrumentation, we use
+ // device config for exported libs if new_exported isn't enabled.
+ // Remove once new_exported is fully rolled out.
+ (true, false, _) => {
+ template.add_template(
+ "FeatureFlagsImpl.java",
+ include_str!("../../templates/FeatureFlagsImpl.java.template"),
+ )?;
+ }
+
+ // New storage internal mode.
+ (false, _, true) => {
+ template.add_template(
+ "FeatureFlagsImpl.java",
+ include_str!("../../templates/FeatureFlagsImpl.new_storage.java.template"),
+ )?;
+ }
+
+ // Device config internal mode. Use legacy (device config) template.
+ (false, _, false) => {
+ template.add_template(
+ "FeatureFlagsImpl.java",
+ include_str!("../../templates/FeatureFlagsImpl.java.template"),
+ )?;
+ }
+ };
+ Ok(())
+}
+
#[cfg(test)]
mod tests {
use super::*;
diff --git a/tools/aconfig/aconfig/src/codegen/mod.rs b/tools/aconfig/aconfig/src/codegen/mod.rs
index 1ea3b37..9ed66db 100644
--- a/tools/aconfig/aconfig/src/codegen/mod.rs
+++ b/tools/aconfig/aconfig/src/codegen/mod.rs
@@ -50,67 +50,6 @@
#[cfg(test)]
mod tests {
use super::*;
- use aconfig_protos::is_valid_container_ident;
-
- #[test]
- fn test_is_valid_name_ident() {
- assert!(is_valid_name_ident("foo"));
- assert!(is_valid_name_ident("foo_bar_123"));
- assert!(is_valid_name_ident("foo_"));
-
- assert!(!is_valid_name_ident(""));
- assert!(!is_valid_name_ident("123_foo"));
- assert!(!is_valid_name_ident("foo-bar"));
- assert!(!is_valid_name_ident("foo-b\u{00e5}r"));
- assert!(!is_valid_name_ident("foo__bar"));
- assert!(!is_valid_name_ident("_foo"));
- }
-
- #[test]
- fn test_is_valid_package_ident() {
- assert!(is_valid_package_ident("foo.bar"));
- assert!(is_valid_package_ident("foo.bar_baz"));
- assert!(is_valid_package_ident("foo.bar.a123"));
-
- assert!(!is_valid_package_ident("foo_bar_123"));
- assert!(!is_valid_package_ident("foo"));
- assert!(!is_valid_package_ident("foo._bar"));
- assert!(!is_valid_package_ident(""));
- assert!(!is_valid_package_ident("123_foo"));
- assert!(!is_valid_package_ident("foo-bar"));
- assert!(!is_valid_package_ident("foo-b\u{00e5}r"));
- assert!(!is_valid_package_ident("foo.bar.123"));
- assert!(!is_valid_package_ident(".foo.bar"));
- assert!(!is_valid_package_ident("foo.bar."));
- assert!(!is_valid_package_ident("."));
- assert!(!is_valid_package_ident(".."));
- assert!(!is_valid_package_ident("foo..bar"));
- assert!(!is_valid_package_ident("foo.__bar"));
- }
-
- #[test]
- fn test_is_valid_container_ident() {
- assert!(is_valid_container_ident("foo.bar"));
- assert!(is_valid_container_ident("foo.bar_baz"));
- assert!(is_valid_container_ident("foo.bar.a123"));
- assert!(is_valid_container_ident("foo"));
- assert!(is_valid_container_ident("foo_bar_123"));
-
- assert!(!is_valid_container_ident(""));
- assert!(!is_valid_container_ident("foo._bar"));
- assert!(!is_valid_container_ident("_foo"));
- assert!(!is_valid_container_ident("123_foo"));
- assert!(!is_valid_container_ident("foo-bar"));
- assert!(!is_valid_container_ident("foo-b\u{00e5}r"));
- assert!(!is_valid_container_ident("foo.bar.123"));
- assert!(!is_valid_container_ident(".foo.bar"));
- assert!(!is_valid_container_ident("foo.bar."));
- assert!(!is_valid_container_ident("."));
- assert!(!is_valid_container_ident(".."));
- assert!(!is_valid_container_ident("foo..bar"));
- assert!(!is_valid_container_ident("foo.__bar"));
- }
-
#[test]
fn test_create_device_config_ident() {
assert_eq!(
diff --git a/tools/aconfig/aconfig/src/codegen/rust.rs b/tools/aconfig/aconfig/src/codegen/rust.rs
index 74da1bc..2ee5f36 100644
--- a/tools/aconfig/aconfig/src/codegen/rust.rs
+++ b/tools/aconfig/aconfig/src/codegen/rust.rs
@@ -31,7 +31,6 @@
flag_ids: HashMap<String, u16>,
parsed_flags_iter: I,
codegen_mode: CodegenMode,
- allow_instrumentation: bool,
) -> Result<OutputFile>
where
I: Iterator<Item = ProtoParsedFlag>,
@@ -46,7 +45,6 @@
template_flags,
modules: package.split('.').map(|s| s.to_string()).collect::<Vec<_>>(),
has_readwrite,
- allow_instrumentation,
container,
};
let mut template = TinyTemplate::new();
@@ -70,7 +68,6 @@
pub template_flags: Vec<TemplateParsedFlag>,
pub modules: Vec<String>,
pub has_readwrite: bool,
- pub allow_instrumentation: bool,
pub container: String,
}
@@ -134,146 +131,6 @@
/// flag provider
pub struct FlagProvider;
- /// flag value cache for disabled_rw
- static CACHED_disabled_rw: LazyLock<bool> = LazyLock::new(|| flags_rust::GetServerConfigurableFlag(
- "aconfig_flags.aconfig_test",
- "com.android.aconfig.test.disabled_rw",
- "false") == "true");
-
- /// flag value cache for disabled_rw_exported
- static CACHED_disabled_rw_exported: LazyLock<bool> = LazyLock::new(|| flags_rust::GetServerConfigurableFlag(
- "aconfig_flags.aconfig_test",
- "com.android.aconfig.test.disabled_rw_exported",
- "false") == "true");
-
- /// flag value cache for disabled_rw_in_other_namespace
- static CACHED_disabled_rw_in_other_namespace: LazyLock<bool> = LazyLock::new(|| flags_rust::GetServerConfigurableFlag(
- "aconfig_flags.other_namespace",
- "com.android.aconfig.test.disabled_rw_in_other_namespace",
- "false") == "true");
-
- /// flag value cache for enabled_rw
- static CACHED_enabled_rw: LazyLock<bool> = LazyLock::new(|| flags_rust::GetServerConfigurableFlag(
- "aconfig_flags.aconfig_test",
- "com.android.aconfig.test.enabled_rw",
- "true") == "true");
-
-impl FlagProvider {
- /// query flag disabled_ro
- pub fn disabled_ro(&self) -> bool {
- false
- }
-
- /// query flag disabled_rw
- pub fn disabled_rw(&self) -> bool {
- *CACHED_disabled_rw
- }
-
- /// query flag disabled_rw_exported
- pub fn disabled_rw_exported(&self) -> bool {
- *CACHED_disabled_rw_exported
- }
-
- /// query flag disabled_rw_in_other_namespace
- pub fn disabled_rw_in_other_namespace(&self) -> bool {
- *CACHED_disabled_rw_in_other_namespace
- }
-
- /// query flag enabled_fixed_ro
- pub fn enabled_fixed_ro(&self) -> bool {
- true
- }
-
- /// query flag enabled_fixed_ro_exported
- pub fn enabled_fixed_ro_exported(&self) -> bool {
- true
- }
-
- /// query flag enabled_ro
- pub fn enabled_ro(&self) -> bool {
- true
- }
-
- /// query flag enabled_ro_exported
- pub fn enabled_ro_exported(&self) -> bool {
- true
- }
-
- /// query flag enabled_rw
- pub fn enabled_rw(&self) -> bool {
- *CACHED_enabled_rw
- }
-}
-
-/// flag provider
-pub static PROVIDER: FlagProvider = FlagProvider;
-
-/// query flag disabled_ro
-#[inline(always)]
-pub fn disabled_ro() -> bool {
- false
-}
-
-/// query flag disabled_rw
-#[inline(always)]
-pub fn disabled_rw() -> bool {
- PROVIDER.disabled_rw()
-}
-
-/// query flag disabled_rw_exported
-#[inline(always)]
-pub fn disabled_rw_exported() -> bool {
- PROVIDER.disabled_rw_exported()
-}
-
-/// query flag disabled_rw_in_other_namespace
-#[inline(always)]
-pub fn disabled_rw_in_other_namespace() -> bool {
- PROVIDER.disabled_rw_in_other_namespace()
-}
-
-/// query flag enabled_fixed_ro
-#[inline(always)]
-pub fn enabled_fixed_ro() -> bool {
- true
-}
-
-/// query flag enabled_fixed_ro_exported
-#[inline(always)]
-pub fn enabled_fixed_ro_exported() -> bool {
- true
-}
-
-/// query flag enabled_ro
-#[inline(always)]
-pub fn enabled_ro() -> bool {
- true
-}
-
-/// query flag enabled_ro_exported
-#[inline(always)]
-pub fn enabled_ro_exported() -> bool {
- true
-}
-
-/// query flag enabled_rw
-#[inline(always)]
-pub fn enabled_rw() -> bool {
- PROVIDER.enabled_rw()
-}
-"#;
-
- const PROD_INSTRUMENTED_EXPECTED: &str = r#"
-//! codegenerated rust flag lib
-use aconfig_storage_read_api::{Mmap, AconfigStorageError, StorageFileType, PackageReadContext, get_mapped_storage_file, get_boolean_flag_value, get_package_read_context};
-use std::path::Path;
-use std::io::Write;
-use std::sync::LazyLock;
-use log::{log, LevelFilter, Level};
-
-/// flag provider
-pub struct FlagProvider;
-
static PACKAGE_OFFSET: LazyLock<Result<Option<u32>, AconfigStorageError>> = LazyLock::new(|| unsafe {
get_mapped_storage_file("system", StorageFileType::PackageMap)
.and_then(|package_map| get_package_read_context(&package_map, "com.android.aconfig.test"))
@@ -557,15 +414,189 @@
const TEST_EXPECTED: &str = r#"
//! codegenerated rust flag lib
-
+use aconfig_storage_read_api::{Mmap, AconfigStorageError, StorageFileType, PackageReadContext, get_mapped_storage_file, get_boolean_flag_value, get_package_read_context};
use std::collections::BTreeMap;
-use std::sync::Mutex;
+use std::path::Path;
+use std::io::Write;
+use std::sync::{LazyLock, Mutex};
+use log::{log, LevelFilter, Level};
/// flag provider
pub struct FlagProvider {
overrides: BTreeMap<&'static str, bool>,
}
+static PACKAGE_OFFSET: LazyLock<Result<Option<u32>, AconfigStorageError>> = LazyLock::new(|| unsafe {
+ get_mapped_storage_file("system", StorageFileType::PackageMap)
+ .and_then(|package_map| get_package_read_context(&package_map, "com.android.aconfig.test"))
+ .map(|context| context.map(|c| c.boolean_start_index))
+});
+
+static FLAG_VAL_MAP: LazyLock<Result<Mmap, AconfigStorageError>> = LazyLock::new(|| unsafe {
+ get_mapped_storage_file("system", StorageFileType::FlagVal)
+});
+
+/// flag value cache for disabled_rw
+static CACHED_disabled_rw: LazyLock<bool> = LazyLock::new(|| {
+ // This will be called multiple times. Subsequent calls after the first are noops.
+ logger::init(
+ logger::Config::default()
+ .with_tag_on_device("aconfig_rust_codegen")
+ .with_max_level(LevelFilter::Info));
+
+ let flag_value_result = FLAG_VAL_MAP
+ .as_ref()
+ .map_err(|err| format!("failed to get flag val map: {err}"))
+ .and_then(|flag_val_map| {
+ PACKAGE_OFFSET
+ .as_ref()
+ .map_err(|err| format!("failed to get package read offset: {err}"))
+ .and_then(|package_offset| {
+ match package_offset {
+ Some(offset) => {
+ get_boolean_flag_value(&flag_val_map, offset + 0)
+ .map_err(|err| format!("failed to get flag: {err}"))
+ },
+ None => {
+ log!(Level::Error, "no context found for package com.android.aconfig.test");
+ Err(format!("failed to flag package com.android.aconfig.test"))
+ }
+ }
+ })
+ });
+
+ match flag_value_result {
+ Ok(flag_value) => {
+ return flag_value;
+ },
+ Err(err) => {
+ log!(Level::Error, "aconfig_rust_codegen: error: {err}");
+ return false;
+ }
+ }
+});
+
+/// flag value cache for disabled_rw_exported
+static CACHED_disabled_rw_exported: LazyLock<bool> = LazyLock::new(|| {
+ // This will be called multiple times. Subsequent calls after the first are noops.
+ logger::init(
+ logger::Config::default()
+ .with_tag_on_device("aconfig_rust_codegen")
+ .with_max_level(LevelFilter::Info));
+
+ let flag_value_result = FLAG_VAL_MAP
+ .as_ref()
+ .map_err(|err| format!("failed to get flag val map: {err}"))
+ .and_then(|flag_val_map| {
+ PACKAGE_OFFSET
+ .as_ref()
+ .map_err(|err| format!("failed to get package read offset: {err}"))
+ .and_then(|package_offset| {
+ match package_offset {
+ Some(offset) => {
+ get_boolean_flag_value(&flag_val_map, offset + 1)
+ .map_err(|err| format!("failed to get flag: {err}"))
+ },
+ None => {
+ log!(Level::Error, "no context found for package com.android.aconfig.test");
+ Err(format!("failed to flag package com.android.aconfig.test"))
+ }
+ }
+ })
+ });
+
+ match flag_value_result {
+ Ok(flag_value) => {
+ return flag_value;
+ },
+ Err(err) => {
+ log!(Level::Error, "aconfig_rust_codegen: error: {err}");
+ return false;
+ }
+ }
+});
+
+/// flag value cache for disabled_rw_in_other_namespace
+static CACHED_disabled_rw_in_other_namespace: LazyLock<bool> = LazyLock::new(|| {
+ // This will be called multiple times. Subsequent calls after the first are noops.
+ logger::init(
+ logger::Config::default()
+ .with_tag_on_device("aconfig_rust_codegen")
+ .with_max_level(LevelFilter::Info));
+
+ let flag_value_result = FLAG_VAL_MAP
+ .as_ref()
+ .map_err(|err| format!("failed to get flag val map: {err}"))
+ .and_then(|flag_val_map| {
+ PACKAGE_OFFSET
+ .as_ref()
+ .map_err(|err| format!("failed to get package read offset: {err}"))
+ .and_then(|package_offset| {
+ match package_offset {
+ Some(offset) => {
+ get_boolean_flag_value(&flag_val_map, offset + 2)
+ .map_err(|err| format!("failed to get flag: {err}"))
+ },
+ None => {
+ log!(Level::Error, "no context found for package com.android.aconfig.test");
+ Err(format!("failed to flag package com.android.aconfig.test"))
+ }
+ }
+ })
+ });
+
+ match flag_value_result {
+ Ok(flag_value) => {
+ return flag_value;
+ },
+ Err(err) => {
+ log!(Level::Error, "aconfig_rust_codegen: error: {err}");
+ return false;
+ }
+ }
+});
+
+
+/// flag value cache for enabled_rw
+static CACHED_enabled_rw: LazyLock<bool> = LazyLock::new(|| {
+ // This will be called multiple times. Subsequent calls after the first are noops.
+ logger::init(
+ logger::Config::default()
+ .with_tag_on_device("aconfig_rust_codegen")
+ .with_max_level(LevelFilter::Info));
+
+ let flag_value_result = FLAG_VAL_MAP
+ .as_ref()
+ .map_err(|err| format!("failed to get flag val map: {err}"))
+ .and_then(|flag_val_map| {
+ PACKAGE_OFFSET
+ .as_ref()
+ .map_err(|err| format!("failed to get package read offset: {err}"))
+ .and_then(|package_offset| {
+ match package_offset {
+ Some(offset) => {
+ get_boolean_flag_value(&flag_val_map, offset + 7)
+ .map_err(|err| format!("failed to get flag: {err}"))
+ },
+ None => {
+ log!(Level::Error, "no context found for package com.android.aconfig.test");
+ Err(format!("failed to flag package com.android.aconfig.test"))
+ }
+ }
+ })
+ });
+
+ match flag_value_result {
+ Ok(flag_value) => {
+ return flag_value;
+ },
+ Err(err) => {
+ log!(Level::Error, "aconfig_rust_codegen: error: {err}");
+ return true;
+ }
+ }
+});
+
impl FlagProvider {
/// query flag disabled_ro
pub fn disabled_ro(&self) -> bool {
@@ -582,10 +613,7 @@
/// query flag disabled_rw
pub fn disabled_rw(&self) -> bool {
self.overrides.get("disabled_rw").copied().unwrap_or(
- flags_rust::GetServerConfigurableFlag(
- "aconfig_flags.aconfig_test",
- "com.android.aconfig.test.disabled_rw",
- "false") == "true"
+ *CACHED_disabled_rw
)
}
@@ -597,10 +625,7 @@
/// query flag disabled_rw_exported
pub fn disabled_rw_exported(&self) -> bool {
self.overrides.get("disabled_rw_exported").copied().unwrap_or(
- flags_rust::GetServerConfigurableFlag(
- "aconfig_flags.aconfig_test",
- "com.android.aconfig.test.disabled_rw_exported",
- "false") == "true"
+ *CACHED_disabled_rw_exported
)
}
@@ -612,10 +637,7 @@
/// query flag disabled_rw_in_other_namespace
pub fn disabled_rw_in_other_namespace(&self) -> bool {
self.overrides.get("disabled_rw_in_other_namespace").copied().unwrap_or(
- flags_rust::GetServerConfigurableFlag(
- "aconfig_flags.other_namespace",
- "com.android.aconfig.test.disabled_rw_in_other_namespace",
- "false") == "true"
+ *CACHED_disabled_rw_in_other_namespace
)
}
@@ -675,10 +697,7 @@
/// query flag enabled_rw
pub fn enabled_rw(&self) -> bool {
self.overrides.get("enabled_rw").copied().unwrap_or(
- flags_rust::GetServerConfigurableFlag(
- "aconfig_flags.aconfig_test",
- "com.android.aconfig.test.enabled_rw",
- "true") == "true"
+ *CACHED_enabled_rw
)
}
@@ -812,74 +831,6 @@
}
"#;
- const EXPORTED_EXPECTED: &str = r#"
-//! codegenerated rust flag lib
-use aconfig_storage_read_api::{Mmap, AconfigStorageError, StorageFileType, PackageReadContext, get_mapped_storage_file, get_boolean_flag_value, get_package_read_context};
-use std::path::Path;
-use std::io::Write;
-use std::sync::LazyLock;
-use log::{log, LevelFilter, Level};
-
-/// flag provider
-pub struct FlagProvider;
-
- /// flag value cache for disabled_rw_exported
- static CACHED_disabled_rw_exported: LazyLock<bool> = LazyLock::new(|| flags_rust::GetServerConfigurableFlag(
- "aconfig_flags.aconfig_test",
- "com.android.aconfig.test.disabled_rw_exported",
- "false") == "true");
-
- /// flag value cache for enabled_fixed_ro_exported
- static CACHED_enabled_fixed_ro_exported: LazyLock<bool> = LazyLock::new(|| flags_rust::GetServerConfigurableFlag(
- "aconfig_flags.aconfig_test",
- "com.android.aconfig.test.enabled_fixed_ro_exported",
- "false") == "true");
-
- /// flag value cache for enabled_ro_exported
- static CACHED_enabled_ro_exported: LazyLock<bool> = LazyLock::new(|| flags_rust::GetServerConfigurableFlag(
- "aconfig_flags.aconfig_test",
- "com.android.aconfig.test.enabled_ro_exported",
- "false") == "true");
-
-impl FlagProvider {
- /// query flag disabled_rw_exported
- pub fn disabled_rw_exported(&self) -> bool {
- *CACHED_disabled_rw_exported
- }
-
- /// query flag enabled_fixed_ro_exported
- pub fn enabled_fixed_ro_exported(&self) -> bool {
- *CACHED_enabled_fixed_ro_exported
- }
-
- /// query flag enabled_ro_exported
- pub fn enabled_ro_exported(&self) -> bool {
- *CACHED_enabled_ro_exported
- }
-}
-
-/// flag provider
-pub static PROVIDER: FlagProvider = FlagProvider;
-
-/// query flag disabled_rw_exported
-#[inline(always)]
-pub fn disabled_rw_exported() -> bool {
- PROVIDER.disabled_rw_exported()
-}
-
-/// query flag enabled_fixed_ro_exported
-#[inline(always)]
-pub fn enabled_fixed_ro_exported() -> bool {
- PROVIDER.enabled_fixed_ro_exported()
-}
-
-/// query flag enabled_ro_exported
-#[inline(always)]
-pub fn enabled_ro_exported() -> bool {
- PROVIDER.enabled_ro_exported()
-}
-"#;
-
const FORCE_READ_ONLY_EXPECTED: &str = r#"
//! codegenerated rust flag lib
use aconfig_storage_read_api::{Mmap, AconfigStorageError, StorageFileType, PackageReadContext, get_mapped_storage_file, get_boolean_flag_value, get_package_read_context};
@@ -964,7 +915,7 @@
"#;
use crate::commands::assign_flag_ids;
- fn test_generate_rust_code(mode: CodegenMode, allow_instrumentation: bool, expected: &str) {
+ fn test_generate_rust_code(mode: CodegenMode, expected: &str) {
let parsed_flags = crate::test::parse_test_flags();
let modified_parsed_flags =
crate::commands::modify_parsed_flags_based_on_mode(parsed_flags, mode).unwrap();
@@ -975,7 +926,6 @@
flag_ids,
modified_parsed_flags.into_iter(),
mode,
- allow_instrumentation,
)
.unwrap();
assert_eq!("src/lib.rs", format!("{}", generated.path.display()));
@@ -990,26 +940,16 @@
#[test]
fn test_generate_rust_code_for_prod() {
- test_generate_rust_code(CodegenMode::Production, false, PROD_EXPECTED);
- }
-
- #[test]
- fn test_generate_rust_code_for_prod_instrumented() {
- test_generate_rust_code(CodegenMode::Production, true, PROD_INSTRUMENTED_EXPECTED);
+ test_generate_rust_code(CodegenMode::Production, PROD_EXPECTED);
}
#[test]
fn test_generate_rust_code_for_test() {
- test_generate_rust_code(CodegenMode::Test, false, TEST_EXPECTED);
- }
-
- #[test]
- fn test_generate_rust_code_for_exported() {
- test_generate_rust_code(CodegenMode::Exported, false, EXPORTED_EXPECTED);
+ test_generate_rust_code(CodegenMode::Test, TEST_EXPECTED);
}
#[test]
fn test_generate_rust_code_for_force_read_only() {
- test_generate_rust_code(CodegenMode::ForceReadOnly, false, FORCE_READ_ONLY_EXPECTED);
+ test_generate_rust_code(CodegenMode::ForceReadOnly, FORCE_READ_ONLY_EXPECTED);
}
}
diff --git a/tools/aconfig/aconfig/src/commands.rs b/tools/aconfig/aconfig/src/commands.rs
index ea1069e..ab726aa 100644
--- a/tools/aconfig/aconfig/src/commands.rs
+++ b/tools/aconfig/aconfig/src/commands.rs
@@ -242,11 +242,7 @@
generate_java_code(&package, modified_parsed_flags.into_iter(), config)
}
-pub fn create_cpp_lib(
- mut input: Input,
- codegen_mode: CodegenMode,
- allow_instrumentation: bool,
-) -> Result<Vec<OutputFile>> {
+pub fn create_cpp_lib(mut input: Input, codegen_mode: CodegenMode) -> Result<Vec<OutputFile>> {
// TODO(327420679): Enable export mode for native flag library
ensure!(
codegen_mode != CodegenMode::Exported,
@@ -259,20 +255,10 @@
};
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,
- flag_ids,
- allow_instrumentation,
- )
+ generate_cpp_code(&package, modified_parsed_flags.into_iter(), codegen_mode, flag_ids)
}
-pub fn create_rust_lib(
- mut input: Input,
- codegen_mode: CodegenMode,
- allow_instrumentation: bool,
-) -> Result<OutputFile> {
+pub fn create_rust_lib(mut input: Input, codegen_mode: CodegenMode) -> Result<OutputFile> {
// // TODO(327420679): Enable export mode for native flag library
ensure!(
codegen_mode != CodegenMode::Exported,
@@ -285,13 +271,7 @@
};
let package = package.to_string();
let flag_ids = assign_flag_ids(&package, modified_parsed_flags.iter())?;
- generate_rust_code(
- &package,
- flag_ids,
- modified_parsed_flags.into_iter(),
- codegen_mode,
- allow_instrumentation,
- )
+ generate_rust_code(&package, flag_ids, modified_parsed_flags.into_iter(), codegen_mode)
}
pub fn create_storage(
diff --git a/tools/aconfig/aconfig/src/main.rs b/tools/aconfig/aconfig/src/main.rs
index e2fa554..ef3b7ab 100644
--- a/tools/aconfig/aconfig/src/main.rs
+++ b/tools/aconfig/aconfig/src/main.rs
@@ -40,9 +40,86 @@
use commands::{Input, OutputFile};
+const HELP_DUMP_CACHE: &str = r#"
+An aconfig cache file, created via `aconfig create-cache`.
+"#;
+
+const HELP_DUMP_FORMAT: &str = r#"
+Change the output format for each flag.
+
+The argument to --format is a format string. Each flag will be a copy of this string, with certain
+placeholders replaced by attributes of the flag. The placeholders are
+
+ {package}
+ {name}
+ {namespace}
+ {description}
+ {bug}
+ {state}
+ {state:bool}
+ {permission}
+ {trace}
+ {trace:paths}
+ {is_fixed_read_only}
+ {is_exported}
+ {container}
+ {metadata}
+ {fully_qualified_name}
+
+Note: the format strings "textproto" and "protobuf" are handled in a special way: they output all
+flag attributes in text or binary protobuf format.
+
+Examples:
+
+ # See which files were read to determine the value of a flag; the files were read in the order
+ # listed.
+ --format='{fully_qualified_name} {trace}'
+
+ # Trace the files read for a specific flag. Useful during debugging.
+ --filter=fully_qualified_name:com.foo.flag_name --format='{trace}'
+
+ # Print a somewhat human readable description of each flag.
+ --format='The flag {name} in package {package} is {state} and has permission {permission}.'
+"#;
+
const HELP_DUMP_FILTER: &str = r#"
-Limit which flags to output. If multiple --filter arguments are provided, the output will be
-limited to flags that match any of the filters.
+Limit which flags to output. If --filter is omitted, all flags will be printed. If multiple
+--filter options are provided, the output will be limited to flags that match any of the filters.
+
+The argument to --filter is a search query. Multiple queries can be AND-ed together by
+concatenating them with a plus sign.
+
+Valid queries are:
+
+ package:<string>
+ name:<string>
+ namespace:<string>
+ bug:<string>
+ state:ENABLED|DISABLED
+ permission:READ_ONLY|READ_WRITE
+ is_fixed_read_only:true|false
+ is_exported:true|false
+ container:<string>
+ fully_qualified_name:<string>
+
+Note: there is currently no support for filtering based on these flag attributes: description,
+trace, metadata.
+
+Examples:
+
+ # Print a single flag:
+ --filter=fully_qualified_name:com.foo.flag_name
+
+ # Print all known information about a single flag:
+ --filter=fully_qualified_name:com.foo.flag_name --format=textproto
+
+ # Print all flags in the com.foo package, and all enabled flags in the com.bar package:
+ --filter=package:com.foo --filter=package.com.bar+state:ENABLED
+"#;
+
+const HELP_DUMP_DEDUP: &str = r#"
+Allow the same flag to be present in multiple cache files; if duplicates are found, collapse into
+a single instance.
"#;
fn cli() -> Command {
@@ -150,22 +227,34 @@
.subcommand(
Command::new("dump-cache")
.alias("dump")
- .arg(Arg::new("cache").long("cache").action(ArgAction::Append))
+ .arg(
+ Arg::new("cache")
+ .long("cache")
+ .action(ArgAction::Append)
+ .long_help(HELP_DUMP_CACHE.trim()),
+ )
.arg(
Arg::new("format")
.long("format")
.value_parser(|s: &str| DumpFormat::try_from(s))
.default_value(
"{fully_qualified_name} [{container}]: {permission} + {state}",
- ),
+ )
+ .long_help(HELP_DUMP_FORMAT.trim()),
)
.arg(
Arg::new("filter")
.long("filter")
.action(ArgAction::Append)
- .help(HELP_DUMP_FILTER.trim()),
+ .long_help(HELP_DUMP_FILTER.trim()),
)
- .arg(Arg::new("dedup").long("dedup").num_args(0).action(ArgAction::SetTrue))
+ .arg(
+ Arg::new("dedup")
+ .long("dedup")
+ .num_args(0)
+ .action(ArgAction::SetTrue)
+ .long_help(HELP_DUMP_DEDUP.trim()),
+ )
.arg(Arg::new("out").long("out").default_value("-")),
)
.subcommand(
@@ -301,10 +390,8 @@
Some(("create-cpp-lib", sub_matches)) => {
let cache = open_single_file(sub_matches, "cache")?;
let mode = get_required_arg::<CodegenMode>(sub_matches, "mode")?;
- 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 generated_files =
+ commands::create_cpp_lib(cache, *mode).context("failed to create cpp lib")?;
let dir = PathBuf::from(get_required_arg::<String>(sub_matches, "out")?);
generated_files
.iter()
@@ -313,10 +400,8 @@
Some(("create-rust-lib", sub_matches)) => {
let cache = open_single_file(sub_matches, "cache")?;
let mode = get_required_arg::<CodegenMode>(sub_matches, "mode")?;
- let allow_instrumentation =
- get_required_arg::<bool>(sub_matches, "allow-instrumentation")?;
- let generated_file = commands::create_rust_lib(cache, *mode, *allow_instrumentation)
- .context("failed to create rust lib")?;
+ let generated_file =
+ commands::create_rust_lib(cache, *mode).context("failed to create rust lib")?;
let dir = PathBuf::from(get_required_arg::<String>(sub_matches, "out")?);
write_output_file_realtive_to_dir(&dir, &generated_file)?;
}
diff --git a/tools/aconfig/aconfig/templates/FeatureFlagsImpl.exported.java.template b/tools/aconfig/aconfig/templates/FeatureFlagsImpl.exported.java.template
new file mode 100644
index 0000000..8b60824
--- /dev/null
+++ b/tools/aconfig/aconfig/templates/FeatureFlagsImpl.exported.java.template
@@ -0,0 +1,44 @@
+package {package_name}; {#- CODEGEN FOR EXPORTED MODE FOR NEW STORAGE #}
+
+import android.os.Build;
+import android.os.flagging.AconfigPackage;
+import android.util.Log;
+/** @hide */
+public final class FeatureFlagsImpl implements FeatureFlags \{
+ private static final String TAG = "FeatureFlagsImplExport";
+ private static volatile boolean isCached = false;
+{{ for flag in flag_elements }}
+ private static boolean {flag.method_name} = false;
+{{ -endfor }} {#- end flag_elements #}
+ private void init() \{
+ try \{
+ AconfigPackage reader = AconfigPackage.load("{package_name}");
+ {{ -for namespace_with_flags in namespace_flags }}
+ {{ -for flag in namespace_with_flags.flags }}
+ {{ -if flag.finalized_sdk_present }}
+ {flag.method_name} = Build.VERSION.SDK_INT >= {flag.finalized_sdk_value} ? true : reader.getBooleanFlagValue("{flag.flag_name}", {flag.default_value});
+ {{ - else }} {#- else finalized_sdk_present #}
+ {flag.method_name} = reader.getBooleanFlagValue("{flag.flag_name}", {flag.default_value});
+ {{ -endif}} {#- end finalized_sdk_present#}
+ {{ -endfor }} {#- end namespace_with_flags.flags #}
+ {{ -endfor }} {#- end namespace_flags #}
+ } catch (Exception e) \{
+ // pass
+ Log.e(TAG, e.toString());
+ } catch (LinkageError e) \{
+ // for mainline module running on older devices.
+ // This should be replaces to version check, after the version bump.
+ Log.e(TAG, e.toString());
+ }
+ isCached = true;
+ }
+{{ -for flag in flag_elements }}
+ @Override
+ public boolean {flag.method_name}() \{
+ if (!isCached) \{
+ init();
+ }
+ return {flag.method_name};
+ }
+{{ endfor }} {#- end flag_elements #}
+}
diff --git a/tools/aconfig/aconfig/templates/FeatureFlagsImpl.java.template b/tools/aconfig/aconfig/templates/FeatureFlagsImpl.java.template
index 5baa475..ea2a2ee 100644
--- a/tools/aconfig/aconfig/templates/FeatureFlagsImpl.java.template
+++ b/tools/aconfig/aconfig/templates/FeatureFlagsImpl.java.template
@@ -8,11 +8,11 @@
import android.os.Build;
{{ if is_platform_container }}
import android.os.flagging.PlatformAconfigPackageInternal;
-{{ -else }}
+{{ -else }} {#- else is_platform_container #}
import android.os.flagging.AconfigPackageInternal;
-{{ -endif }}
+{{ -endif }} {#- end of is_platform_container#}
import android.util.Log;
-{{ -endif }}
+{{ -endif }} {#- end of runtime_lookup_required#}
/** @hide */
public final class FeatureFlagsImpl implements FeatureFlags \{
{{ -if runtime_lookup_required }}
@@ -21,21 +21,21 @@
{{ for flag in flag_elements }}
{{ -if flag.is_read_write }}
private static boolean {flag.method_name} = {flag.default_value};
-{{ -endif }}
+{{ -endif }} {#- end of is_read_write#}
{{ -endfor }}
private void init() \{
try \{
{{ if is_platform_container }}
PlatformAconfigPackageInternal reader = PlatformAconfigPackageInternal.load("{package_name}", {package_fingerprint});
-{{ -else }}
+{{ -else }} {#- else is_platform_container #}
AconfigPackageInternal reader = AconfigPackageInternal.load("{package_name}", {package_fingerprint});
-{{ -endif }}
+{{ -endif }} {#- end of is_platform_container#}
{{ -for namespace_with_flags in namespace_flags }}
{{ -for flag in namespace_with_flags.flags }}
{{ -if flag.is_read_write }}
{flag.method_name} = reader.getBooleanFlagValue({flag.flag_offset});
- {{ -endif }}
+ {{ -endif }} {#- is_read_write#}
{{ -endfor }}
{{ -endfor }}
} catch (Exception e) \{
@@ -58,9 +58,9 @@
init();
}
return {flag.method_name};
-{{ -else }}
+{{ -else }}{#- else is_read_write #}
return {flag.default_value};
-{{ -endif }}
+{{ -endif }} {#- end of is_read_write#}
}
{{ endfor }}
}
@@ -83,9 +83,9 @@
{{ -for flag in namespace_with_flags.flags }}
{{ -if flag.finalized_sdk_present }}
{flag.method_name} = Build.VERSION.SDK_INT >= {flag.finalized_sdk_value} ? true : reader.getBooleanFlagValue("{flag.flag_name}", {flag.default_value});
- {{ - else }}
+ {{ - else }} {#- else finalized_sdk_present #}
{flag.method_name} = reader.getBooleanFlagValue("{flag.flag_name}", {flag.default_value});
- {{ -endif}}
+ {{ -endif}} {#- end of finalized_sdk_present#}
{{ -endfor }}
{{ -endfor }}
} catch (Exception e) \{
@@ -120,7 +120,7 @@
{{ for flag in flag_elements }}
{{ -if flag.is_read_write }}
private static boolean {flag.method_name} = {flag.default_value};
-{{ -endif }}
+{{ -endif }} {#- end of is_read_write#}
{{ -endfor }}
{{ for namespace_with_flags in namespace_flags }}
private void load_overrides_{namespace_with_flags.namespace}() \{
@@ -131,7 +131,7 @@
{{ -if flag.is_read_write }}
{flag.method_name} =
properties.getBoolean(Flags.FLAG_{flag.flag_name_constant_suffix}, {flag.default_value});
-{{ -endif }}
+{{ -endif }} {#- end of is_read_write#}
{{ -endfor }}
} catch (NullPointerException e) \{
throw new RuntimeException(
@@ -166,13 +166,13 @@
{{ if not library_exported- }}
// TODO(b/303773055): Remove the annotation after access issue is resolved.
import android.compat.annotation.UnsupportedAppUsage;
-{{ -endif }}
+{{ -endif }} {#- end of not library_exported#}
{{ -if runtime_lookup_required }}
import android.os.Binder;
import android.provider.DeviceConfig;
import android.provider.DeviceConfig.Properties;
-{{ -endif }}
+{{ -endif }} {#- end of runtime_lookup_required#}
/** @hide */
public final class FeatureFlagsImpl implements FeatureFlags \{
{{ -if runtime_lookup_required }}
@@ -183,7 +183,7 @@
{{ for flag in flag_elements }}
{{- if flag.is_read_write }}
private static boolean {flag.method_name} = {flag.default_value};
-{{ -endif }}
+{{ -endif }} {#- end of is_read_write#}
{{ -endfor }}
{{ for namespace_with_flags in namespace_flags }}
private void load_overrides_{namespace_with_flags.namespace}() \{
@@ -194,7 +194,7 @@
{{ -if flag.is_read_write }}
{flag.method_name} =
properties.getBoolean(Flags.FLAG_{flag.flag_name_constant_suffix}, {flag.default_value});
-{{ -endif }}
+{{ -endif }} {#- end of is_read_write#}
{{ -endfor }}
} catch (NullPointerException e) \{
throw new RuntimeException(
@@ -217,16 +217,16 @@
{{ -if not library_exported }}
@com.android.aconfig.annotations.AconfigFlagAccessor
@UnsupportedAppUsage
-{{ -endif }}
+{{ -endif }}{#- end of not library_exported #}
public boolean {flag.method_name}() \{
{{ -if flag.is_read_write }}
if (!{flag.device_config_namespace}_is_cached) \{
load_overrides_{flag.device_config_namespace}();
}
return {flag.method_name};
-{{ -else }}
+{{ -else }} {#- else is_read_write #}
return {flag.default_value};
-{{ -endif }}
+{{ -endif }}{#- end of is_read_write #}
}
{{ endfor }}
}
diff --git a/tools/aconfig/aconfig/templates/FeatureFlagsImpl.new_storage.java.template b/tools/aconfig/aconfig/templates/FeatureFlagsImpl.new_storage.java.template
new file mode 100644
index 0000000..9492a83
--- /dev/null
+++ b/tools/aconfig/aconfig/templates/FeatureFlagsImpl.new_storage.java.template
@@ -0,0 +1,63 @@
+package {package_name}; {#- CODEGEN FOR INTERNAL MODE FOR NEW STORAGE #}
+// TODO(b/303773055): Remove the annotation after access issue is resolved.
+import android.compat.annotation.UnsupportedAppUsage;
+{{ -if runtime_lookup_required }}
+import android.os.Build;
+{{ if is_platform_container }}
+import android.os.flagging.PlatformAconfigPackageInternal;
+{{ -else }} {#- else is_platform_container #}
+import android.os.flagging.AconfigPackageInternal;
+{{ -endif }} {#- end of is_platform_container#}
+import android.util.Log;
+{{ -endif }} {#- end of runtime_lookup_required#}
+/** @hide */
+public final class FeatureFlagsImpl implements FeatureFlags \{
+{{ -if runtime_lookup_required }}
+ private static final String TAG = "FeatureFlagsImpl";
+ private static volatile boolean isCached = false;
+{{ for flag in flag_elements }}
+{{ -if flag.is_read_write }}
+ private static boolean {flag.method_name} = {flag.default_value};
+{{ -endif }} {#- end of is_read_write#}
+{{ -endfor }} {#- else flag_elements #}
+
+ private void init() \{
+ try \{
+{{ if is_platform_container }}
+ PlatformAconfigPackageInternal reader = PlatformAconfigPackageInternal.load("{package_name}", {package_fingerprint});
+{{ -else }} {#- else is_platform_container #}
+ AconfigPackageInternal reader = AconfigPackageInternal.load("{package_name}", {package_fingerprint});
+{{ -endif }} {#- end of is_platform_container#}
+ {{ -for namespace_with_flags in namespace_flags }}
+ {{ -for flag in namespace_with_flags.flags }}
+ {{ -if flag.is_read_write }}
+ {flag.method_name} = reader.getBooleanFlagValue({flag.flag_offset});
+ {{ -endif }} {#- is_read_write#}
+ {{ -endfor }} {#- else namespace_with_flags.flags #}
+ {{ -endfor }} {#- else namespace_flags #}
+ } catch (Exception e) \{
+ Log.e(TAG, e.toString());
+ } catch (LinkageError e) \{
+ // for mainline module running on older devices.
+ // This should be replaces to version check, after the version bump.
+ Log.e(TAG, e.toString());
+ }
+ isCached = true;
+ }
+{{ -endif }}{#- end of runtime_lookup_required #}
+{{ -for flag in flag_elements }}
+ @Override
+ @com.android.aconfig.annotations.AconfigFlagAccessor
+ @UnsupportedAppUsage
+ public boolean {flag.method_name}() \{
+{{ -if flag.is_read_write }}
+ if (!isCached) \{
+ init();
+ }
+ return {flag.method_name};
+{{ -else }}{#- else is_read_write #}
+ return {flag.default_value};
+{{ -endif }} {#- end of is_read_write#}
+ }
+{{ endfor }} {#- else flag_elements #}
+}
diff --git a/tools/aconfig/aconfig/templates/FeatureFlagsImpl.test_mode.java.template b/tools/aconfig/aconfig/templates/FeatureFlagsImpl.test_mode.java.template
new file mode 100644
index 0000000..8eda263
--- /dev/null
+++ b/tools/aconfig/aconfig/templates/FeatureFlagsImpl.test_mode.java.template
@@ -0,0 +1,14 @@
+package {package_name}; {#- CODEGEN FOR TEST MODE #}
+/** @hide */
+public final class FeatureFlagsImpl implements FeatureFlags \{
+{{ for flag in flag_elements }}
+ @Override
+{{ -if not library_exported }}
+ @com.android.aconfig.annotations.AconfigFlagAccessor
+{{ -endif }}
+ public boolean {flag.method_name}() \{
+ throw new UnsupportedOperationException(
+ "Method is not implemented.");
+ }
+{{ endfor- }}
+}
diff --git a/tools/aconfig/aconfig/templates/cpp_source_file.template b/tools/aconfig/aconfig/templates/cpp_source_file.template
index dc4e435..36ab774 100644
--- a/tools/aconfig/aconfig/templates/cpp_source_file.template
+++ b/tools/aconfig/aconfig/templates/cpp_source_file.template
@@ -1,6 +1,5 @@
#include "{header}.h"
-{{ if allow_instrumentation }}
{{ if readwrite- }}
#include <unistd.h>
#include "aconfig_storage/aconfig_storage_read_api.hpp"
@@ -8,11 +7,7 @@
#define LOG_TAG "aconfig_cpp_codegen"
#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
{{ -endif }}
-{{ endif }}
-{{ if readwrite- }}
-#include <server_configurable_flags/get_flags.h>
-{{ endif }}
{{ if is_test_mode }}
#include <unordered_map>
#include <string>
@@ -29,7 +24,6 @@
private:
std::unordered_map<std::string, bool> overrides_;
- {{ if allow_instrumentation- }}
{{ if readwrite- }}
uint32_t boolean_start_index_;
@@ -37,10 +31,8 @@
bool package_exists_in_storage_;
{{ -endif }}
- {{ -endif }}
public:
- {{ if allow_instrumentation- }}
{{ if readwrite- }}
flag_provider()
: overrides_()
@@ -97,11 +89,6 @@
: overrides_()
\{}
{{ -endif }}
- {{ -else }}
- flag_provider()
- : overrides_()
- \{}
- {{ -endif }}
{{ for item in class_elements }}
virtual bool {item.flag_name}() override \{
@@ -110,7 +97,6 @@
return it->second;
} else \{
{{ if item.readwrite- }}
- {{ if allow_instrumentation- }}
if (!package_exists_in_storage_) \{
return {item.default_value};
}
@@ -126,12 +112,6 @@
return *value;
}
{{ -else }}
- return server_configurable_flags::GetServerConfigurableFlag(
- "aconfig_flags.{item.device_config_namespace}",
- "{item.device_config_flag}",
- "{item.default_value}") == "true";
- {{ -endif }}
- {{ -else }}
return {item.default_value};
{{ -endif }}
}
@@ -153,7 +133,6 @@
public:
{{ if readwrite- }}
- {{ if allow_instrumentation- }}
flag_provider()
: cache_({readwrite_count}, -1)
, boolean_start_index_()
@@ -203,13 +182,11 @@
}
{{ -endif }}
- {{ -endif }}
{{ -for item in class_elements }}
virtual bool {item.flag_name}() override \{
{{ -if item.readwrite }}
if (cache_[{item.readwrite_idx}] == -1) \{
- {{ if allow_instrumentation- }}
if (!package_exists_in_storage_) \{
return {item.default_value};
}
@@ -224,12 +201,6 @@
}
cache_[{item.readwrite_idx}] = *value;
- {{ -else- }}
- cache_[{item.readwrite_idx}] = server_configurable_flags::GetServerConfigurableFlag(
- "aconfig_flags.{item.device_config_namespace}",
- "{item.device_config_flag}",
- "{item.default_value}") == "true";
- {{ -endif }}
}
return cache_[{item.readwrite_idx}];
{{ -else }}
@@ -245,14 +216,13 @@
{{ if readwrite- }}
private:
std::vector<int8_t> cache_ = std::vector<int8_t>({readwrite_count}, -1);
- {{ if allow_instrumentation- }}
+
uint32_t boolean_start_index_;
std::unique_ptr<aconfig_storage::MappedStorageFile> flag_value_file_;
bool package_exists_in_storage_;
{{ -endif }}
- {{ -endif }}
};
diff --git a/tools/aconfig/aconfig/templates/rust.template b/tools/aconfig/aconfig/templates/rust.template
index e9e1032..56323e2 100644
--- a/tools/aconfig/aconfig/templates/rust.template
+++ b/tools/aconfig/aconfig/templates/rust.template
@@ -9,7 +9,6 @@
pub struct FlagProvider;
{{ if has_readwrite- }}
-{{ if allow_instrumentation }}
static PACKAGE_OFFSET: LazyLock<Result<Option<u32>, AconfigStorageError>> = LazyLock::new(|| unsafe \{
get_mapped_storage_file("{container}", StorageFileType::PackageMap)
.and_then(|package_map| get_package_read_context(&package_map, "{package}"))
@@ -19,12 +18,10 @@
static FLAG_VAL_MAP: LazyLock<Result<Mmap, AconfigStorageError>> = LazyLock::new(|| unsafe \{
get_mapped_storage_file("{container}", StorageFileType::FlagVal)
});
-{{ -endif }}
{{ -for flag in template_flags }}
{{ -if flag.readwrite }}
/// flag value cache for {flag.name}
-{{ if allow_instrumentation }}
static CACHED_{flag.name}: LazyLock<bool> = LazyLock::new(|| \{
// This will be called multiple times. Subsequent calls after the first are noops.
@@ -65,12 +62,6 @@
}
});
-{{ else }}
-static CACHED_{flag.name}: LazyLock<bool> = LazyLock::new(|| flags_rust::GetServerConfigurableFlag(
- "aconfig_flags.{flag.device_config_namespace}",
- "{flag.device_config_flag}",
- "{flag.default_value}") == "true");
-{{ endif }}
{{ -endif }}
{{ -endfor }}
{{ -endif }}
diff --git a/tools/aconfig/aconfig/templates/rust_test.template b/tools/aconfig/aconfig/templates/rust_test.template
index d01f40a..139a5ec 100644
--- a/tools/aconfig/aconfig/templates/rust_test.template
+++ b/tools/aconfig/aconfig/templates/rust_test.template
@@ -1,23 +1,81 @@
//! codegenerated rust flag lib
-
+use aconfig_storage_read_api::\{Mmap, AconfigStorageError, StorageFileType, PackageReadContext, get_mapped_storage_file, get_boolean_flag_value, get_package_read_context};
use std::collections::BTreeMap;
-use std::sync::Mutex;
+use std::path::Path;
+use std::io::Write;
+use std::sync::\{LazyLock, Mutex};
+use log::\{log, LevelFilter, Level};
/// flag provider
pub struct FlagProvider \{
overrides: BTreeMap<&'static str, bool>,
}
+{{ if has_readwrite- }}
+static PACKAGE_OFFSET: LazyLock<Result<Option<u32>, AconfigStorageError>> = LazyLock::new(|| unsafe \{
+ get_mapped_storage_file("{container}", StorageFileType::PackageMap)
+ .and_then(|package_map| get_package_read_context(&package_map, "{package}"))
+ .map(|context| context.map(|c| c.boolean_start_index))
+});
+
+static FLAG_VAL_MAP: LazyLock<Result<Mmap, AconfigStorageError>> = LazyLock::new(|| unsafe \{
+ get_mapped_storage_file("{container}", StorageFileType::FlagVal)
+});
+
+{{ -for flag in template_flags }}
+{{ -if flag.readwrite }}
+/// flag value cache for {flag.name}
+static CACHED_{flag.name}: LazyLock<bool> = LazyLock::new(|| \{
+
+ // This will be called multiple times. Subsequent calls after the first are noops.
+ logger::init(
+ logger::Config::default()
+ .with_tag_on_device("aconfig_rust_codegen")
+ .with_max_level(LevelFilter::Info));
+
+ let flag_value_result = FLAG_VAL_MAP
+ .as_ref()
+ .map_err(|err| format!("failed to get flag val map: \{err}"))
+ .and_then(|flag_val_map| \{
+ PACKAGE_OFFSET
+ .as_ref()
+ .map_err(|err| format!("failed to get package read offset: \{err}"))
+ .and_then(|package_offset| \{
+ match package_offset \{
+ Some(offset) => \{
+ get_boolean_flag_value(&flag_val_map, offset + {flag.flag_offset})
+ .map_err(|err| format!("failed to get flag: \{err}"))
+ },
+ None => \{
+ log!(Level::Error, "no context found for package {package}");
+ Err(format!("failed to flag package {package}"))
+ }
+ }
+ })
+ });
+
+ match flag_value_result \{
+ Ok(flag_value) => \{
+ return flag_value;
+ },
+ Err(err) => \{
+ log!(Level::Error, "aconfig_rust_codegen: error: \{err}");
+ return {flag.default_value};
+ }
+ }
+
+});
+{{ -endif }}
+{{ -endfor }}
+{{ -endif }}
+
impl FlagProvider \{
{{ for flag in template_flags }}
/// query flag {flag.name}
pub fn {flag.name}(&self) -> bool \{
self.overrides.get("{flag.name}").copied().unwrap_or(
{{ if flag.readwrite -}}
- flags_rust::GetServerConfigurableFlag(
- "aconfig_flags.{flag.device_config_namespace}",
- "{flag.device_config_flag}",
- "{flag.default_value}") == "true"
+ *CACHED_{flag.name}
{{ -else- }}
{flag.default_value}
{{ -endif }}
diff --git a/tools/aconfig/aconfig_protos/Android.bp b/tools/aconfig/aconfig_protos/Android.bp
index 62a2b64..080688e 100644
--- a/tools/aconfig/aconfig_protos/Android.bp
+++ b/tools/aconfig/aconfig_protos/Android.bp
@@ -98,3 +98,13 @@
test_suites: ["general-tests"],
defaults: ["aconfig_protos.defaults"],
}
+
+// Internal protos
+
+python_library_host {
+ name: "aconfig_internal_proto_python",
+ srcs: ["protos/aconfig_internal.proto"],
+ proto: {
+ canonical_path_from_root: false,
+ },
+}
diff --git a/tools/aconfig/aconfig_protos/src/lib.rs b/tools/aconfig/aconfig_protos/src/lib.rs
index 81bbd7e..64b82d6 100644
--- a/tools/aconfig/aconfig_protos/src/lib.rs
+++ b/tools/aconfig/aconfig_protos/src/lib.rs
@@ -1073,4 +1073,63 @@
// two identical flags with dedup enabled
assert_eq!(first, parsed_flags::merge(vec![first.clone(), first.clone()], true).unwrap());
}
+
+ #[test]
+ fn test_is_valid_name_ident() {
+ assert!(is_valid_name_ident("foo"));
+ assert!(is_valid_name_ident("foo_bar_123"));
+ assert!(is_valid_name_ident("foo_"));
+
+ assert!(!is_valid_name_ident(""));
+ assert!(!is_valid_name_ident("123_foo"));
+ assert!(!is_valid_name_ident("foo-bar"));
+ assert!(!is_valid_name_ident("foo-b\u{00e5}r"));
+ assert!(!is_valid_name_ident("foo__bar"));
+ assert!(!is_valid_name_ident("_foo"));
+ }
+
+ #[test]
+ fn test_is_valid_package_ident() {
+ assert!(is_valid_package_ident("foo.bar"));
+ assert!(is_valid_package_ident("foo.bar_baz"));
+ assert!(is_valid_package_ident("foo.bar.a123"));
+
+ assert!(!is_valid_package_ident("foo_bar_123"));
+ assert!(!is_valid_package_ident("foo"));
+ assert!(!is_valid_package_ident("foo._bar"));
+ assert!(!is_valid_package_ident(""));
+ assert!(!is_valid_package_ident("123_foo"));
+ assert!(!is_valid_package_ident("foo-bar"));
+ assert!(!is_valid_package_ident("foo-b\u{00e5}r"));
+ assert!(!is_valid_package_ident("foo.bar.123"));
+ assert!(!is_valid_package_ident(".foo.bar"));
+ assert!(!is_valid_package_ident("foo.bar."));
+ assert!(!is_valid_package_ident("."));
+ assert!(!is_valid_package_ident(".."));
+ assert!(!is_valid_package_ident("foo..bar"));
+ assert!(!is_valid_package_ident("foo.__bar"));
+ }
+
+ #[test]
+ fn test_is_valid_container_ident() {
+ assert!(is_valid_container_ident("foo.bar"));
+ assert!(is_valid_container_ident("foo.bar_baz"));
+ assert!(is_valid_container_ident("foo.bar.a123"));
+ assert!(is_valid_container_ident("foo"));
+ assert!(is_valid_container_ident("foo_bar_123"));
+
+ assert!(!is_valid_container_ident(""));
+ assert!(!is_valid_container_ident("foo._bar"));
+ assert!(!is_valid_container_ident("_foo"));
+ assert!(!is_valid_container_ident("123_foo"));
+ assert!(!is_valid_container_ident("foo-bar"));
+ assert!(!is_valid_container_ident("foo-b\u{00e5}r"));
+ assert!(!is_valid_container_ident("foo.bar.123"));
+ assert!(!is_valid_container_ident(".foo.bar"));
+ assert!(!is_valid_container_ident("foo.bar."));
+ assert!(!is_valid_container_ident("."));
+ assert!(!is_valid_container_ident(".."));
+ assert!(!is_valid_container_ident("foo..bar"));
+ assert!(!is_valid_container_ident("foo.__bar"));
+ }
}
diff --git a/tools/filelistdiff/allowlist b/tools/filelistdiff/allowlist
index eb78587..d8979d6 100644
--- a/tools/filelistdiff/allowlist
+++ b/tools/filelistdiff/allowlist
@@ -1,5 +1,3 @@
# Known diffs that are installed in either system image with the configuration
# b/353429422
init.environ.rc
-# b/338342381
-etc/NOTICE.xml.gz
diff --git a/tools/ide_query/ide_query.go b/tools/ide_query/ide_query.go
index c7cf5ed..6caa29c 100644
--- a/tools/ide_query/ide_query.go
+++ b/tools/ide_query/ide_query.go
@@ -116,8 +116,8 @@
var targets []string
javaTargetsByFile := findJavaModules(javaFiles, javaModules)
- for _, t := range javaTargetsByFile {
- targets = append(targets, t)
+ for _, target := range javaTargetsByFile {
+ targets = append(targets, javaModules[target].Jars...)
}
ccTargets, err := getCCTargets(ctx, env, ccFiles)
@@ -306,6 +306,10 @@
}
module := modules[name]
+ if len(module.Jars) == 0 {
+ continue
+ }
+
for i, p := range paths {
if slices.Contains(module.Srcs, p) {
ret[p] = name
@@ -317,6 +321,7 @@
break
}
}
+
return ret
}
diff --git a/tools/ide_query/prober_scripts/cpp/general.cc b/tools/ide_query/prober_scripts/cpp/general.cc
index 0f0639b..ac88282 100644
--- a/tools/ide_query/prober_scripts/cpp/general.cc
+++ b/tools/ide_query/prober_scripts/cpp/general.cc
@@ -56,7 +56,7 @@
void TestNavigation() {
std::vector<int> ints;
- // | | ints
+ // ^ ^ ints
// ^
// step
diff --git a/tools/ide_query/prober_scripts/jvm/Foo.java b/tools/ide_query/prober_scripts/jvm/Foo.java
index 9397bc4..2c8ceb6 100644
--- a/tools/ide_query/prober_scripts/jvm/Foo.java
+++ b/tools/ide_query/prober_scripts/jvm/Foo.java
@@ -20,7 +20,7 @@
/** Foo class. */
public final class Foo {
-// | | foo_def
+// ^ ^ foo_def
void testParameterInfo() {
// Test signature help for type parameters.
diff --git a/tools/releasetools/fsverity_metadata_generator.py b/tools/releasetools/fsverity_metadata_generator.py
index fa7cd39..50e23e7 100644
--- a/tools/releasetools/fsverity_metadata_generator.py
+++ b/tools/releasetools/fsverity_metadata_generator.py
@@ -104,16 +104,13 @@
out = subprocess.check_output(cmd, universal_newlines=True).strip()
return bytes(bytearray.fromhex(out))
- def generate(self, input_file, output_file=None):
+ def generate(self, input_file, output_file):
if self._signature != 'none':
if not self._key:
raise RuntimeError("key must be specified.")
if not self._cert:
raise RuntimeError("cert must be specified.")
- if not output_file:
- output_file = input_file + '.fsv_meta'
-
with TempDirectory() as temp_dir:
self._do_generate(input_file, output_file, temp_dir)
@@ -229,6 +226,27 @@
required=True)
args = p.parse_args(sys.argv[1:])
+ output_file = args.output
+ if not output_file:
+ output_file = input_file + '.fsv_meta'
+
+ if output_file != args.input + '.fsv_meta':
+ sys.exit('When generating .fsv_meta files for symlinks, we assume that all fsv_meta files '
+ 'are named the same as the file they protect, just with the .fsv_meta suffix appended. '
+ 'We require that all .fsv_meta files follow this convention regardless of if it\'s a link or '
+ 'not. However {args.input} had a different output file: {args.output}')
+
+ # remove the output file first, as switching between a file and a symlink can be complicated
+ try:
+ os.remove(output_file)
+ except FileNotFoundError:
+ pass
+
+ if os.path.islink(args.input):
+ target = os.readlink(args.input) + '.fsv_meta'
+ os.symlink(target, output_file)
+ sys.exit(0)
+
generator = FSVerityMetadataGenerator(args.fsverity_path)
generator.set_signature(args.signature)
if args.signature == 'none':
@@ -241,4 +259,4 @@
generator.set_cert(args.cert)
generator.set_key_format(args.key_format)
generator.set_hash_alg(args.hash_alg)
- generator.generate(args.input, args.output)
+ generator.generate(args.input, output_file)
diff --git a/tools/releasetools/sign_target_files_apks.py b/tools/releasetools/sign_target_files_apks.py
index 2378539..f1855a5 100755
--- a/tools/releasetools/sign_target_files_apks.py
+++ b/tools/releasetools/sign_target_files_apks.py
@@ -378,6 +378,37 @@
return keys_info
+def GetMicrodroidVbmetaKey(virt_apex_path, avbtool_path):
+ """Extracts the AVB public key from microdroid_vbmeta.img within a virt apex.
+
+ Args:
+ virt_apex_path: The path to the com.android.virt.apex file.
+ avbtool_path: The path to the avbtool executable.
+
+ Returns:
+ The AVB public key (bytes).
+ """
+ # Creates an ApexApkSigner to extract microdroid_vbmeta.img.
+ # No need to set key_passwords/codename_to_api_level_map since
+ # we won't do signing here.
+ apex_signer = apex_utils.ApexApkSigner(
+ virt_apex_path,
+ None, # key_passwords
+ None) # codename_to_api_level_map
+ payload_dir = apex_signer.ExtractApexPayload(virt_apex_path)
+ microdroid_vbmeta_image = os.path.join(
+ payload_dir, 'etc', 'fs', 'microdroid_vbmeta.img')
+
+ # Extracts the avb public key from microdroid_vbmeta.img.
+ with tempfile.NamedTemporaryFile() as microdroid_pubkey:
+ common.RunAndCheckOutput([
+ avbtool_path, 'info_image',
+ '--image', microdroid_vbmeta_image,
+ '--output_pubkey', microdroid_pubkey.name])
+ with open(microdroid_pubkey.name, 'rb') as f:
+ return f.read()
+
+
def GetApkFileInfo(filename, compressed_extension, skipped_prefixes):
"""Returns the APK info based on the given filename.
@@ -879,9 +910,8 @@
# b/384813199: handles the pre-signed com.android.virt.apex in GSI.
if payload_key == 'PRESIGNED':
- with input_tf_zip.open(virt_apex_path) as apex_fp:
- with zipfile.ZipFile(apex_fp) as apex_zip:
- new_pubkey = apex_zip.read('apex_pubkey')
+ new_pubkey = GetMicrodroidVbmetaKey(virt_apex_path,
+ misc_info['avb_avbtool'])
else:
new_pubkey_path = common.ExtractAvbPublicKey(
misc_info['avb_avbtool'], payload_key)
diff --git a/tools/sbom/Android.bp b/tools/sbom/Android.bp
index 4f6d3b7..7e2840f 100644
--- a/tools/sbom/Android.bp
+++ b/tools/sbom/Android.bp
@@ -129,5 +129,7 @@
},
},
libs: [
+ "compliance_metadata",
+ "metadata_file_proto_py",
],
}
diff --git a/tools/sbom/compliance_metadata.py b/tools/sbom/compliance_metadata.py
index 9910217..502c110 100644
--- a/tools/sbom/compliance_metadata.py
+++ b/tools/sbom/compliance_metadata.py
@@ -18,7 +18,7 @@
class MetadataDb:
def __init__(self, db):
- self.conn = sqlite3.connect(':memory')
+ self.conn = sqlite3.connect(':memory:')
self.conn.row_factory = sqlite3.Row
with sqlite3.connect(db) as c:
c.backup(self.conn)
@@ -94,7 +94,7 @@
cursor.close()
rows = []
for m in multi_built_file_modules:
- built_files = m['installed_file'].strip().split(' ')
+ built_files = m['built_file'].strip().split(' ')
for f in built_files:
rows.append((m['module_id'], m['module_name'], m['package'], f))
self.conn.executemany('insert into module_built_file values (?, ?, ?, ?)', rows)
@@ -132,6 +132,21 @@
installed_files_metadata.append(metadata)
return installed_files_metadata
+ def get_installed_file_in_dir(self, dir):
+ dir = dir.removesuffix('/')
+ cursor = self.conn.execute(
+ 'select installed_file, module_path, is_prebuilt_make_module, product_copy_files, '
+ ' kernel_module_copy_files, is_platform_generated, license_text '
+ 'from make_metadata '
+ 'where installed_file like ?', (dir + '/%',))
+ rows = cursor.fetchall()
+ cursor.close()
+ installed_files_metadata = []
+ for row in rows:
+ metadata = dict(zip(row.keys(), row))
+ installed_files_metadata.append(metadata)
+ return installed_files_metadata
+
def get_soong_modules(self):
# Get all records from table modules, which contains metadata of all soong modules
cursor = self.conn.execute('select name, package, package as module_path, module_type as soong_module_type, built_files, installed_files, static_dep_files, whole_static_dep_files from modules')
diff --git a/tools/sbom/gen_notice_xml.py b/tools/sbom/gen_notice_xml.py
index eaa6e5a..8478b1f 100644
--- a/tools/sbom/gen_notice_xml.py
+++ b/tools/sbom/gen_notice_xml.py
@@ -25,6 +25,14 @@
"""
import argparse
+import compliance_metadata
+import google.protobuf.text_format as text_format
+import gzip
+import hashlib
+import metadata_file_pb2
+import os
+import queue
+import xml.sax.saxutils
FILE_HEADER = '''\
@@ -39,7 +47,7 @@
def get_args():
parser = argparse.ArgumentParser()
parser.add_argument('-v', '--verbose', action='store_true', default=False, help='Print more information.')
- parser.add_argument('-d', '--debug', action='store_true', default=True, help='Debug mode')
+ parser.add_argument('-d', '--debug', action='store_true', default=False, help='Debug mode')
parser.add_argument('--output_file', required=True, help='The path of the generated NOTICE.xml.gz file.')
parser.add_argument('--partition', required=True, help='The name of partition for which the NOTICE.xml.gz is generated.')
parser.add_argument('--metadata', required=True, help='The path of compliance metadata DB file.')
@@ -55,27 +63,162 @@
print(i)
-def new_file_name_tag(file_metadata, package_name):
+def new_file_name_tag(file_metadata, package_name, content_id):
file_path = file_metadata['installed_file'].removeprefix(args.product_out)
lib = 'Android'
if package_name:
lib = package_name
- return f'<file-name contentId="" lib="{lib}">{file_path}</file-name>\n'
+ return f'<file-name contentId="{content_id}" lib="{lib}">{file_path}</file-name>\n'
-def new_file_content_tag():
- pass
+def new_file_content_tag(content_id, license_text):
+ escaped_license_text = xml.sax.saxutils.escape(license_text, {'\t': '	', '\n': '
', '\r': '
'})
+ return f'<file-content contentId="{content_id}"><![CDATA[{escaped_license_text}]]></file-content>\n\n'
+def get_metadata_file_path(file_metadata):
+ """Search for METADATA file of a package and return its path."""
+ metadata_path = ''
+ if file_metadata['module_path']:
+ metadata_path = file_metadata['module_path']
+ elif file_metadata['kernel_module_copy_files']:
+ metadata_path = os.path.dirname(file_metadata['kernel_module_copy_files'].split(':')[0])
+
+ while metadata_path and not os.path.exists(metadata_path + '/METADATA'):
+ metadata_path = os.path.dirname(metadata_path)
+
+ return metadata_path
+
+def md5_file_content(filepath):
+ h = hashlib.md5()
+ with open(filepath, 'rb') as f:
+ h.update(f.read())
+ return h.hexdigest()
+
+def get_transitive_static_dep_modules(installed_file_metadata, db):
+ # Find all transitive static dep files of the installed files
+ q = queue.Queue()
+ if installed_file_metadata['static_dep_files']:
+ for f in installed_file_metadata['static_dep_files'].split(' '):
+ q.put(f)
+ if installed_file_metadata['whole_static_dep_files']:
+ for f in installed_file_metadata['whole_static_dep_files'].split(' '):
+ q.put(f)
+
+ static_dep_files = {}
+ while not q.empty():
+ dep_file = q.get()
+ if dep_file in static_dep_files:
+ # It has been processed
+ continue
+
+ soong_module = db.get_soong_module_of_built_file(dep_file)
+ if not soong_module:
+ continue
+
+ static_dep_files[dep_file] = soong_module
+
+ if soong_module['static_dep_files']:
+ for f in soong_module['static_dep_files'].split(' '):
+ if f not in static_dep_files:
+ q.put(f)
+ if soong_module['whole_static_dep_files']:
+ for f in soong_module['whole_static_dep_files'].split(' '):
+ if f not in static_dep_files:
+ q.put(f)
+
+ return static_dep_files.values()
def main():
global args
args = get_args()
log('Args:', vars(args))
- with open(args.output_file, 'w', encoding="utf-8") as notice_xml_file:
+ global db
+ db = compliance_metadata.MetadataDb(args.metadata)
+ if args.debug:
+ db.dump_debug_db(os.path.dirname(args.output_file) + '/compliance-metadata-debug.db')
+
+ # NOTICE.xml
+ notice_xml_file_path = os.path.dirname(args.output_file) + '/NOTICE.xml'
+ with open(notice_xml_file_path, 'w', encoding="utf-8") as notice_xml_file:
notice_xml_file.write(FILE_HEADER)
+
+ all_license_files = {}
+ for metadata in db.get_installed_file_in_dir(args.product_out + '/' + args.partition):
+ soong_module = db.get_soong_module_of_installed_file(metadata['installed_file'])
+ if soong_module:
+ metadata.update(soong_module)
+ else:
+ # For make modules soong_module_type should be empty
+ metadata['soong_module_type'] = ''
+ metadata['static_dep_files'] = ''
+ metadata['whole_static_dep_files'] = ''
+
+ installed_file_metadata_list = [metadata]
+ if args.partition in ('vendor', 'product', 'system_ext'):
+ # For transitive static dependencies of an installed file, make it as if an installed file are
+ # also created from static dependency modules whose licenses are also collected
+ static_dep_modules = get_transitive_static_dep_modules(metadata, db)
+ for dep in static_dep_modules:
+ dep['installed_file'] = metadata['installed_file']
+ installed_file_metadata_list.append(dep)
+
+ for installed_file_metadata in installed_file_metadata_list:
+ package_name = 'Android'
+ licenses = {}
+ if installed_file_metadata['module_path']:
+ metadata_file_path = get_metadata_file_path(installed_file_metadata)
+ if metadata_file_path:
+ proto = metadata_file_pb2.Metadata()
+ with open(metadata_file_path + '/METADATA', 'rt') as f:
+ text_format.Parse(f.read(), proto)
+ if proto.name:
+ package_name = proto.name
+ if proto.third_party and proto.third_party.version:
+ if proto.third_party.version.startswith('v'):
+ package_name = package_name + '_' + proto.third_party.version
+ else:
+ package_name = package_name + '_v_' + proto.third_party.version
+ else:
+ package_name = metadata_file_path
+ if metadata_file_path.startswith('external/'):
+ package_name = metadata_file_path.removeprefix('external/')
+
+ # Every license file is in a <file-content> element
+ licenses = db.get_module_licenses(installed_file_metadata.get('name', ''), installed_file_metadata['module_path'])
+
+ # Installed file is from PRODUCT_COPY_FILES
+ elif metadata['product_copy_files']:
+ licenses['unused_name'] = metadata['license_text']
+
+ # Installed file is generated by the platform in builds
+ elif metadata['is_platform_generated']:
+ licenses['unused_name'] = metadata['license_text']
+
+ if licenses:
+ # Each value is a space separated filepath list
+ for license_files in licenses.values():
+ if not license_files:
+ continue
+ for filepath in license_files.split(' '):
+ if filepath not in all_license_files:
+ all_license_files[filepath] = md5_file_content(filepath)
+ md5 = all_license_files[filepath]
+ notice_xml_file.write(new_file_name_tag(installed_file_metadata, package_name, md5))
+
+ # Licenses
+ processed_md5 = []
+ for filepath, md5 in all_license_files.items():
+ if md5 not in processed_md5:
+ processed_md5.append(md5)
+ with open(filepath, 'rt', errors='backslashreplace') as f:
+ notice_xml_file.write(new_file_content_tag(md5, f.read()))
+
notice_xml_file.write(FILE_FOOTER)
+ # NOTICE.xml.gz
+ with open(notice_xml_file_path, 'rb') as notice_xml_file, gzip.open(args.output_file, 'wb') as gz_file:
+ gz_file.writelines(notice_xml_file)
if __name__ == '__main__':
main()
diff --git a/tools/sbom/gen_sbom.py b/tools/sbom/gen_sbom.py
index 756d9db..77bccbb 100644
--- a/tools/sbom/gen_sbom.py
+++ b/tools/sbom/gen_sbom.py
@@ -92,6 +92,7 @@
'SVN',
'Hg',
'Darcs',
+ 'Piper',
'VCS',
'Archive',
'PrebuiltByAlphabet',
@@ -708,7 +709,10 @@
'installed_file': dep_file,
'is_prebuilt_make_module': False
}
- file_metadata.update(db.get_soong_module_of_built_file(dep_file))
+ soong_module = db.get_soong_module_of_built_file(dep_file)
+ if not soong_module:
+ continue
+ file_metadata.update(soong_module)
if is_source_package(file_metadata) or is_prebuilt_package(file_metadata):
add_package_of_file(file_id, file_metadata, doc, report)
else:
diff --git a/tools/tool_event_logger/OWNERS b/tools/tool_event_logger/OWNERS
index b692c9e..e93d20f 100644
--- a/tools/tool_event_logger/OWNERS
+++ b/tools/tool_event_logger/OWNERS
@@ -1,4 +1,3 @@
include platform/tools/asuite:/OWNERS
zhuoyao@google.com
-hzalek@google.com
\ No newline at end of file