Merge "Implement test discovery agent for test zip discovery" into main
diff --git a/core/Makefile b/core/Makefile
index 638d2b9..f7a4ac0 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -5298,7 +5298,7 @@
--dirmap /system_ext:$(TARGET_OUT_SYSTEM_EXT) \
--dirmap /product:$(TARGET_OUT_PRODUCT) \
--dirmap /apex:$(APEX_OUT) \
- $(VINTF_FRAMEWORK_MANIFEST_FROZEN_DIR) > $@ 2>&1 ) || ( cat $@ && exit 1 )
+ system/libhidl/vintfdata/frozen > $@ 2>&1 ) || ( cat $@ && exit 1 )
$(call declare-1p-target,$(vintffm_log))
@@ -7976,7 +7976,7 @@
# -----------------------------------------------------------------
# Desktop pack recovery image hook.
-ifneq (,$(strip $(PACK_DESKTOP_RECOVERY_IMAGE)))
+ifeq ($(BOARD_USES_DESKTOP_RECOVERY_IMAGE),true)
PACK_RECOVERY_IMAGE_TARGET := $(PRODUCT_OUT)/android-desktop_recovery_image.bin
PACK_RECOVERY_IMAGE_ARGS := --noarchive --recovery
@@ -7997,11 +7997,11 @@
.PHONY: pack-recovery-image
pack-recovery-image: $(PACK_RECOVERY_IMAGE_TARGET)
-endif # PACK_DESKTOP_RECOVERY_IMAGE
+endif # BOARD_USES_DESKTOP_RECOVERY_IMAGE
# -----------------------------------------------------------------
# Desktop pack update image hook.
-ifneq (,$(strip $(PACK_DESKTOP_UPDATE_IMAGE)))
+ifeq ($(BOARD_USES_DESKTOP_UPDATE_IMAGE),true)
PACK_UPDATE_IMAGE_TARGET := $(PRODUCT_OUT)/android-desktop_update_image.bin
PACK_UPDATE_IMAGE_ARGS := --noarchive --update
@@ -8022,7 +8022,7 @@
.PHONY: pack-update-image
pack-update-image: $(PACK_UPDATE_IMAGE_TARGET)
-endif # PACK_DESKTOP_UPDATE_IMAGE
+endif # BOARD_USES_DESKTOP_UPDATE_IMAGE
PACK_MIGRATION_IMAGE_SCRIPT := $(HOST_OUT_EXECUTABLES)/pack_migration_image
diff --git a/core/android_soong_config_vars.mk b/core/android_soong_config_vars.mk
index e162235..35d35cd 100644
--- a/core/android_soong_config_vars.mk
+++ b/core/android_soong_config_vars.mk
@@ -102,6 +102,10 @@
$(call add_soong_config_var_value,ANDROID,avf_microdroid_guest_gki_version,$(PRODUCT_AVF_MICRODROID_GUEST_GKI_VERSION))
endif
+ifdef TARGET_BOOTS_16K
+$(call soong_config_set_bool,ANDROID,target_boots_16k,$(filter true,$(TARGET_BOOTS_16K)))
+endif
+
ifdef PRODUCT_MEMCG_V2_FORCE_ENABLED
$(call add_soong_config_var_value,ANDROID,memcg_v2_force_enabled,$(PRODUCT_MEMCG_V2_FORCE_ENABLED))
endif
@@ -225,10 +229,45 @@
$(call soong_config_set_bool,video_codec,board_use_codec2_hidl_1_2,$(if $(filter true,$(BOARD_USE_CODEC2_HIDL_1_2)),true,false))
$(call soong_config_set_bool,video_codec,board_support_mfc_enc_bt2020,$(if $(filter true,$(BOARD_SUPPORT_MFC_ENC_BT2020)),true,false))
$(call soong_config_set_bool,video_codec,board_support_flexible_p010,$(if $(filter true,$(BOARD_SUPPORT_FLEXIBLE_P010)),true,false))
-$(call soong_config_set,video_codec,board_support_mfc_version,$(BOARD_SUPPORT_MFC_VERSION))
$(call soong_config_set_bool,video_codec,board_use_codec2_aidl,$(if $(BOARD_USE_CODEC2_AIDL),true,false))
$(call soong_config_set,video_codec,board_gpu_type,$(BOARD_GPU_TYPE))
$(call soong_config_set_bool,video_codec,board_use_small_secure_memory,$(if $(filter true,$(BOARD_USE_SMALL_SECURE_MEMORY)),true,false))
-ifneq ($(BOARD_USE_MAX_SECURE_RESOURCE),)
+ifdef BOARD_SUPPORT_MFC_VERSION
+ $(call soong_config_set,video_codec,board_support_mfc_version,$(BOARD_SUPPORT_MFC_VERSION))
+endif
+ifdef BOARD_USE_MAX_SECURE_RESOURCE
$(call soong_config_set,video_codec,board_use_max_secure_resource,$(BOARD_USE_MAX_SECURE_RESOURCE))
endif
+
+# Export related variables to soong for hardware/google/graphics/common/libacryl:libacryl
+ifdef BOARD_LIBACRYL_DEFAULT_COMPOSITOR
+ $(call soong_config_set,acryl,libacryl_default_compositor,$(BOARD_LIBACRYL_DEFAULT_COMPOSITOR))
+endif
+ifdef BOARD_LIBACRYL_DEFAULT_SCALER
+ $(call soong_config_set,acryl,libacryl_default_scaler,$(BOARD_LIBACRYL_DEFAULT_SCALER))
+endif
+ifdef BOARD_LIBACRYL_DEFAULT_BLTER
+ $(call soong_config_set,acryl,libacryl_default_blter,$(BOARD_LIBACRYL_DEFAULT_BLTER))
+endif
+ifdef BOARD_LIBACRYL_G2D_HDR_PLUGIN
+ #BOARD_LIBACRYL_G2D_HDR_PLUGIN is set in each board config
+ $(call soong_config_set_bool,acryl,libacryl_use_g2d_hdr_plugin,true)
+endif
+
+# Export related variables to soong for hardware/google/graphics/common/BoardConfigCFlags.mk
+$(call soong_config_set_bool,google_graphics,hwc_no_support_skip_validate,$(if $(filter true,$(HWC_NO_SUPPORT_SKIP_VALIDATE)),true,false))
+$(call soong_config_set_bool,google_graphics,hwc_support_color_transform,$(if $(filter true,$(HWC_SUPPORT_COLOR_TRANSFORM)),true,false))
+$(call soong_config_set_bool,google_graphics,hwc_support_render_intent,$(if $(filter true,$(HWC_SUPPORT_RENDER_INTENT)),true,false))
+$(call soong_config_set_bool,google_graphics,board_uses_virtual_display,$(if $(filter true,$(BOARD_USES_VIRTUAL_DISPLAY)),true,false))
+$(call soong_config_set_bool,google_graphics,board_uses_dt,$(if $(filter true,$(BOARD_USES_DT)),true,false))
+$(call soong_config_set_bool,google_graphics,board_uses_decon_64bit_address,$(if $(filter true,$(BOARD_USES_DECON_64BIT_ADDRESS)),true,false))
+$(call soong_config_set_bool,google_graphics,board_uses_hdrui_gles_conversion,$(if $(filter true,$(BOARD_USES_HDRUI_GLES_CONVERSION)),true,false))
+$(call soong_config_set_bool,google_graphics,uses_idisplay_intf_sec,$(if $(filter true,$(USES_IDISPLAY_INTF_SEC)),true,false))
+
+# Variables for fs_config
+$(call soong_config_set_bool,fs_config,vendor,$(if $(BOARD_USES_VENDORIMAGE)$(BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE),true,false))
+$(call soong_config_set_bool,fs_config,oem,$(if $(BOARD_USES_OEMIMAGE)$(BOARD_OEMIMAGE_FILE_SYSTEM_TYPE),true,false))
+$(call soong_config_set_bool,fs_config,odm,$(if $(BOARD_USES_ODMIMAGE)$(BOARD_ODMIMAGE_FILE_SYSTEM_TYPE),true,false))
+$(call soong_config_set_bool,fs_config,vendor_dlkm,$(if $(BOARD_USES_VENDOR_DLKMIMAGE)$(BOARD_VENDOR_DLKMIMAGE_FILE_SYSTEM_TYPE),true,false))
+$(call soong_config_set_bool,fs_config,odm_dlkm,$(if $(BOARD_USES_ODM_DLKMIMAGE)$(BOARD_ODM_DLKMIMAGE_FILE_SYSTEM_TYPE),true,false))
+$(call soong_config_set_bool,fs_config,system_dlkm,$(if $(BOARD_USES_SYSTEM_DLKMIMAGE)$(BOARD_SYSTEM_DLKMIMAGE_FILE_SYSTEM_TYPE),true,false))
diff --git a/core/board_config.mk b/core/board_config.mk
index 38baa0a..ea0d022 100644
--- a/core/board_config.mk
+++ b/core/board_config.mk
@@ -924,6 +924,18 @@
endif
.KATI_READONLY := BOARD_USES_PVMFWIMAGE
+BOARD_USES_DESKTOP_RECOVERY_IMAGE :=
+ifeq ($(PRODUCT_BUILD_DESKTOP_RECOVERY_IMAGE),true)
+ BOARD_USES_DESKTOP_RECOVERY_IMAGE := true
+endif
+.KATI_READONLY := BOARD_USES_DESKTOP_RECOVERY_IMAGE
+
+BOARD_USES_DESKTOP_UPDATE_IMAGE :=
+ifeq ($(PRODUCT_BUILD_DESKTOP_UPDATE_IMAGE),true)
+ BOARD_USES_DESKTOP_UPDATE_IMAGE := true
+endif
+.KATI_READONLY := BOARD_USES_DESKTOP_UPDATE_IMAGE
+
###########################################
# Ensure consistency among TARGET_RECOVERY_UPDATER_LIBS, AB_OTA_UPDATER, and PRODUCT_OTA_FORCE_NON_AB_PACKAGE.
TARGET_RECOVERY_UPDATER_LIBS ?=
diff --git a/core/main.mk b/core/main.mk
index 24055e8..2b8c132 100644
--- a/core/main.mk
+++ b/core/main.mk
@@ -83,6 +83,8 @@
-include test/cts-root/tools/build/config.mk
# WVTS-specific config.
-include test/wvts/tools/build/config.mk
+# DTS-specific config.
+-include test/dts/tools/build/config.mk
# Clean rules
@@ -984,7 +986,6 @@
$(foreach vndk_ver,$(PRODUCT_EXTRA_VNDK_VERSIONS),com.android.vndk.v$(vndk_ver)) \
$(filter-out $(LLNDK_MOVED_TO_APEX_LIBRARIES),$(LLNDK_LIBRARIES)) \
llndk.libraries.txt \
- $(if $(DEVICE_MANIFEST_FILE),vendor_manifest.xml) \
$(if $(DEVICE_MANIFEST_SKUS),$(foreach sku, $(DEVICE_MANIFEST_SKUS),vendor_manifest_$(sku).xml)) \
$(if $(ODM_MANIFEST_FILES),odm_manifest.xml) \
$(if $(ODM_MANIFEST_SKUS),$(foreach sku, $(ODM_MANIFEST_SKUS),odm_manifest_$(sku).xml)) \
diff --git a/core/product.mk b/core/product.mk
index 8fc40f8..7cf4ec2 100644
--- a/core/product.mk
+++ b/core/product.mk
@@ -366,6 +366,8 @@
_product_single_value_vars += PRODUCT_BUILD_VBMETA_IMAGE
_product_single_value_vars += PRODUCT_BUILD_SUPER_EMPTY_IMAGE
_product_single_value_vars += PRODUCT_BUILD_PVMFW_IMAGE
+_product_single_value_vars += PRODUCT_BUILD_DESKTOP_RECOVERY_IMAGE
+_product_single_value_vars += PRODUCT_BUILD_DESKTOP_UPDATE_IMAGE
# List of boot jars delivered via updatable APEXes, following the same format as
# PRODUCT_BOOT_JARS.
diff --git a/core/soong_config.mk b/core/soong_config.mk
index a5cbfc9..5bdf0f1 100644
--- a/core/soong_config.mk
+++ b/core/soong_config.mk
@@ -183,11 +183,16 @@
$(call add_json_bool, Uml, $(filter true,$(TARGET_USER_MODE_LINUX)))
$(call add_json_str, VendorPath, $(TARGET_COPY_OUT_VENDOR))
+$(call add_json_str, VendorDlkmPath, $(TARGET_COPY_OUT_VENDOR_DLKM))
$(call add_json_bool, BuildingVendorImage, $(BUILDING_VENDOR_IMAGE))
$(call add_json_str, OdmPath, $(TARGET_COPY_OUT_ODM))
+$(call add_json_bool, BuildingOdmImage, $(BUILDING_ODM_IMAGE))
+$(call add_json_str, OdmDlkmPath, $(TARGET_COPY_OUT_ODM_DLKM))
$(call add_json_str, ProductPath, $(TARGET_COPY_OUT_PRODUCT))
$(call add_json_bool, BuildingProductImage, $(BUILDING_PRODUCT_IMAGE))
$(call add_json_str, SystemExtPath, $(TARGET_COPY_OUT_SYSTEM_EXT))
+$(call add_json_str, SystemDlkmPath, $(TARGET_COPY_OUT_SYSTEM_DLKM))
+$(call add_json_str, OemPath, $(TARGET_COPY_OUT_OEM))
$(call add_json_bool, MinimizeJavaDebugInfo, $(filter true,$(PRODUCT_MINIMIZE_JAVA_DEBUG_INFO)))
$(call add_json_bool, UseGoma, $(filter-out false,$(USE_GOMA)))
@@ -352,6 +357,7 @@
$(call add_json_list, SystemExtPropFiles, $(TARGET_SYSTEM_EXT_PROP))
$(call add_json_list, ProductPropFiles, $(TARGET_PRODUCT_PROP))
$(call add_json_list, OdmPropFiles, $(TARGET_ODM_PROP))
+$(call add_json_list, VendorPropFiles, $(TARGET_VENDOR_PROP))
$(call add_json_str, ExtraAllowedDepsTxt, $(EXTRA_ALLOWED_DEPS_TXT))
@@ -427,6 +433,14 @@
$(call add_json_list, ProductPackages, $(PRODUCT_PACKAGES))
$(call add_json_list, ProductPackagesDebug, $(PRODUCT_PACKAGES_DEBUG))
+ # Used to generate /vendor/linker.config.pb
+ $(call add_json_list, VendorLinkerConfigSrcs, $(PRODUCT_VENDOR_LINKER_CONFIG_FRAGMENTS))
+ $(call add_json_list, ProductLinkerConfigSrcs, $(PRODUCT_PRODUCT_LINKER_CONFIG_FRAGMENTS))
+
+ # Used to generate _dlkm partitions
+ $(call add_json_bool, BuildingSystemDlkmImage, $(BUILDING_SYSTEM_DLKM_IMAGE))
+ $(call add_json_list, SystemKernelModules, $(BOARD_SYSTEM_KERNEL_MODULES))
+
$(call add_json_map, ProductCopyFiles)
$(foreach pair,$(PRODUCT_COPY_FILES),\
$(call add_json_str,$(word 1,$(subst :, ,$(pair))),$(word 2,$(subst :, ,$(pair)))))
@@ -434,6 +448,28 @@
$(call end_json_map)
+# For converting vintf_data
+$(call add_json_list, DeviceMatrixFile, $(DEVICE_MATRIX_FILE))
+$(call add_json_list, ProductManifestFiles, $(PRODUCT_MANIFEST_FILES))
+$(call add_json_list, SystemManifestFile, $(DEVICE_FRAMEWORK_MANIFEST_FILE))
+SYSTEM_EXT_HWSERVICE_FILES :=
+ifeq ($(PRODUCT_HIDL_ENABLED),true)
+ ifneq ($(filter hwservicemanager,$(PRODUCT_PACKAGES)),)
+ SYSTEM_EXT_HWSERVICE_FILES += system/hwservicemanager/hwservicemanager_no_max.xml
+ else
+ $(error If PRODUCT_HIDL_ENABLED is set, hwservicemanager must be added to PRODUCT_PACKAGES explicitly)
+ endif
+else
+ ifneq ($(filter hwservicemanager,$(PRODUCT_PACKAGES)),)
+ SYSTEM_EXT_HWSERVICE_FILES += system/hwservicemanager/hwservicemanager.xml
+ else ifneq ($(filter hwservicemanager,$(PRODUCT_PACKAGES_SHIPPING_API_LEVEL_34)),)
+ SYSTEM_EXT_HWSERVICE_FILES += system/hwservicemanager/hwservicemanager.xml
+ endif
+endif
+$(call add_json_list, SystemExtManifestFiles, $(SYSTEM_EXT_MANIFEST_FILES) $(SYSTEM_EXT_HWSERVICE_FILES))
+$(call add_json_list, DeviceManifestFiles, $(DEVICE_MANIFEST_FILE))
+$(call add_json_list, OdmManifestFiles, $(ODM_MANIFEST_FILES))
+
$(call json_end)
$(file >$(SOONG_VARIABLES).tmp,$(json_contents))
diff --git a/core/soong_extra_config.mk b/core/soong_extra_config.mk
index 00b5c0f..2ff83a1 100644
--- a/core/soong_extra_config.mk
+++ b/core/soong_extra_config.mk
@@ -43,6 +43,7 @@
$(call add_json_list, PRODUCT_PRODUCT_PROPERTIES, $(call collapse-prop-pairs,PRODUCT_PRODUCT_PROPERTIES))
$(call add_json_list, PRODUCT_ODM_PROPERTIES, $(call collapse-prop-pairs,PRODUCT_ODM_PROPERTIES))
$(call add_json_list, PRODUCT_PROPERTY_OVERRIDES, $(call collapse-prop-pairs,PRODUCT_PROPERTY_OVERRIDES))
+$(call add_json_list, PRODUCT_DEFAULT_PROPERTY_OVERRIDES, $(call collapse-prop-pairs,PRODUCT_DEFAULT_PROPERTY_OVERRIDES))
$(call add_json_str, BootloaderBoardName, $(TARGET_BOOTLOADER_BOARD_NAME))
diff --git a/core/tasks/autorepro.mk b/core/tasks/autorepro.mk
new file mode 100644
index 0000000..2f81f9b
--- /dev/null
+++ b/core/tasks/autorepro.mk
@@ -0,0 +1,39 @@
+# Copyright (C) 2022 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+ifneq ($(wildcard test/sts/README-autorepro.md),)
+test_suite_name := autorepro
+test_suite_tradefed := sts-tradefed
+test_suite_readme := test/sts/README-autorepro.md
+autorepro_zip := $(HOST_OUT)/$(test_suite_name)/autorepro.zip
+
+include $(BUILD_SYSTEM)/tasks/tools/compatibility.mk
+
+autorepro_plugin_skel := $(call intermediates-dir-for,ETC,autorepro-plugin-skel.zip)/autorepro-plugin-skel.zip
+
+$(autorepro_zip): AUTOREPRO_ZIP := $(compatibility_zip)
+$(autorepro_zip): AUTOREPRO_PLUGIN_SKEL := $(autorepro_plugin_skel)
+$(autorepro_zip): $(MERGE_ZIPS) $(ZIP2ZIP) $(compatibility_zip) $(autorepro_plugin_skel)
+ rm -f $@ $(AUTOREPRO_ZIP)_filtered
+ $(ZIP2ZIP) -i $(AUTOREPRO_ZIP) -o $(AUTOREPRO_ZIP)_filtered \
+ -x android-autorepro/tools/sts-tradefed-tests.jar \
+ 'android-autorepro/tools/*:autorepro/src/main/resources/sts-tradefed-tools/'
+ $(MERGE_ZIPS) $@ $(AUTOREPRO_ZIP)_filtered $(AUTOREPRO_PLUGIN_SKEL)
+ rm -f $(AUTOREPRO_ZIP)_filtered
+
+.PHONY: autorepro
+autorepro: $(autorepro_zip)
+$(call dist-for-goals, autorepro, $(autorepro_zip))
+
+endif
diff --git a/core/tasks/dts.mk b/core/tasks/dts.mk
new file mode 100644
index 0000000..8f09082
--- /dev/null
+++ b/core/tasks/dts.mk
@@ -0,0 +1,28 @@
+# 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.
+
+# Desktop test suite
+ifneq ($(wildcard test/dts/tools/dts-tradefed/README),)
+test_suite_name := dts
+test_suite_tradefed := dts-tradefed
+test_suite_readme := test/dts/tools/dts-tradefed/README
+test_suite_tools := $(HOST_OUT_JAVA_LIBRARIES)/ats_console_deploy.jar \
+ $(HOST_OUT_JAVA_LIBRARIES)/ats_olc_server_local_mode_deploy.jar
+
+include $(BUILD_SYSTEM)/tasks/tools/compatibility.mk
+
+.PHONY: dts
+dts: $(compatibility_zip) $(compatibility_tests_list_zip)
+$(call dist-for-goals, dts, $(compatibility_zip) $(compatibility_tests_list_zip))
+endif
diff --git a/core/tasks/general-tests-shared-libs.mk b/core/tasks/general-tests-shared-libs.mk
deleted file mode 100644
index 2405140..0000000
--- a/core/tasks/general-tests-shared-libs.mk
+++ /dev/null
@@ -1,52 +0,0 @@
-# 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.
-
-.PHONY: general-tests-shared-libs
-
-intermediates_dir := $(call intermediates-dir-for,PACKAGING,general-tests-shared-libs)
-
-general_tests_shared_libs_zip := $(PRODUCT_OUT)/general-tests_host-shared-libs.zip
-
-# Filter shared entries between general-tests and device-tests's HOST_SHARED_LIBRARY.FILES,
-# to avoid warning about overriding commands.
-my_host_shared_lib_for_general_tests := \
- $(foreach m,$(filter $(COMPATIBILITY.device-tests.HOST_SHARED_LIBRARY.FILES),\
- $(COMPATIBILITY.general-tests.HOST_SHARED_LIBRARY.FILES)),$(call word-colon,2,$(m)))
-my_general_tests_shared_lib_files := \
- $(filter-out $(COMPATIBILITY.device-tests.HOST_SHARED_LIBRARY.FILES),\
- $(COMPATIBILITY.general-tests.HOST_SHARED_LIBRARY.FILES))
-
-my_host_shared_lib_for_general_tests += $(call copy-many-files,$(my_general_tests_shared_lib_files))
-
-$(general_tests_shared_libs_zip) : PRIVATE_INTERMEDIATES_DIR := $(intermediates_dir)
-$(general_tests_shared_libs_zip) : PRIVATE_HOST_SHARED_LIBS := $(my_host_shared_lib_for_general_tests)
-$(general_tests_shared_libs_zip) : PRIVATE_general_host_shared_libs_zip := $(general_tests_shared_libs_zip)
-$(general_tests_shared_libs_zip) : $(my_host_shared_lib_for_general_tests) $(SOONG_ZIP)
- rm -rf $(PRIVATE_INTERMEDIATES_DIR)
- mkdir -p $(PRIVATE_INTERMEDIATES_DIR) $(PRIVATE_INTERMEDIATES_DIR)/tools
- $(hide) for shared_lib in $(PRIVATE_HOST_SHARED_LIBS); do \
- echo $$shared_lib >> $(PRIVATE_INTERMEDIATES_DIR)/shared-libs.list; \
- done
- grep $(HOST_OUT_TESTCASES) $(PRIVATE_INTERMEDIATES_DIR)/shared-libs.list > $(PRIVATE_INTERMEDIATES_DIR)/host-shared-libs.list || true
- $(SOONG_ZIP) -d -o $(PRIVATE_general_host_shared_libs_zip) \
- -P host -C $(HOST_OUT) -l $(PRIVATE_INTERMEDIATES_DIR)/host-shared-libs.list
-
-general-tests-shared-libs: $(general_tests_shared_libs_zip)
-$(call dist-for-goals, general-tests-shared-libs, $(general_tests_shared_libs_zip))
-
-$(call declare-1p-container,$(general_tests_shared_libs_zip),)
-$(call declare-container-license-deps,$(general_tests_shared_libs_zip),$(my_host_shared_lib_for_general_tests),$(PRODUCT_OUT)/:/)
-
-intermediates_dir :=
-general_tests_shared_libs_zip :=
diff --git a/core/tasks/general-tests.mk b/core/tasks/general-tests.mk
index d6fc072..d3e653f 100644
--- a/core/tasks/general-tests.mk
+++ b/core/tasks/general-tests.mk
@@ -37,22 +37,53 @@
.PHONY: vts_kernel_ltp_tests
vts_kernel_ltp_tests: $(copy_ltp_tests)
-general_tests_shared_libs_zip := $(PRODUCT_OUT)/general-tests_host-shared-libs.zip
+# Filter shared entries between general-tests and device-tests's HOST_SHARED_LIBRARY.FILES,
+# to avoid warning about overriding commands.
+my_host_shared_lib_for_general_tests := \
+ $(foreach m,$(filter $(COMPATIBILITY.device-tests.HOST_SHARED_LIBRARY.FILES),\
+ $(COMPATIBILITY.general-tests.HOST_SHARED_LIBRARY.FILES)),$(call word-colon,2,$(m)))
+my_general_tests_shared_lib_files := \
+ $(filter-out $(COMPATIBILITY.device-tests.HOST_SHARED_LIBRARY.FILES),\
+ $(COMPATIBILITY.general-tests.HOST_SHARED_LIBRARY.FILES))
-$(general_tests_zip) : $(general_tests_shared_libs_zip)
+my_host_shared_lib_for_general_tests += $(call copy-many-files,$(my_general_tests_shared_lib_files))
+
+my_general_tests_symlinks := \
+ $(filter-out $(COMPATIBILITY.camera-hal-tests.SYMLINKS),\
+ $(filter-out $(COMPATIBILITY.host-unit-tests.SYMLINKS),\
+ $(COMPATIBILITY.general-tests.SYMLINKS)))
+
+my_symlinks_for_general_tests := $(foreach f,$(my_general_tests_symlinks),\
+ $(strip $(eval _cmf_tuple := $(subst :, ,$(f))) \
+ $(eval _cmf_dep := $(word 1,$(_cmf_tuple))) \
+ $(eval _cmf_src := $(word 2,$(_cmf_tuple))) \
+ $(eval _cmf_dest := $(word 3,$(_cmf_tuple))) \
+ $(call symlink-file,$(_cmf_dep),$(_cmf_src),$(_cmf_dest)) \
+ $(_cmf_dest)))
+
+
$(general_tests_zip) : $(copy_ltp_tests)
$(general_tests_zip) : PRIVATE_KERNEL_LTP_HOST_OUT := $(kernel_ltp_host_out)
$(general_tests_zip) : PRIVATE_general_tests_list_zip := $(general_tests_list_zip)
$(general_tests_zip) : .KATI_IMPLICIT_OUTPUTS := $(general_tests_list_zip) $(general_tests_configs_zip)
$(general_tests_zip) : PRIVATE_TOOLS := $(general_tests_tools)
$(general_tests_zip) : PRIVATE_INTERMEDIATES_DIR := $(intermediates_dir)
+$(general_tests_zip) : PRIVATE_HOST_SHARED_LIBS := $(my_host_shared_lib_for_general_tests)
+$(general_tests_zip) : PRIVATE_SYMLINKS := $(my_symlinks_for_general_tests)
$(general_tests_zip) : PRIVATE_general_tests_configs_zip := $(general_tests_configs_zip)
-$(general_tests_zip) : $(COMPATIBILITY.general-tests.FILES) $(COMPATIBILITY.general-tests.SOONG_INSTALLED_COMPATIBILITY_SUPPORT_FILES) $(general_tests_tools) $(SOONG_ZIP)
+$(general_tests_zip) : $(COMPATIBILITY.general-tests.FILES) $(my_host_shared_lib_for_general_tests) $(COMPATIBILITY.general-tests.SOONG_INSTALLED_COMPATIBILITY_SUPPORT_FILES) $(general_tests_tools) $(my_symlinks_for_general_tests) $(SOONG_ZIP)
rm -rf $(PRIVATE_INTERMEDIATES_DIR)
rm -f $@ $(PRIVATE_general_tests_list_zip)
mkdir -p $(PRIVATE_INTERMEDIATES_DIR) $(PRIVATE_INTERMEDIATES_DIR)/tools
echo $(sort $(COMPATIBILITY.general-tests.FILES) $(COMPATIBILITY.general-tests.SOONG_INSTALLED_COMPATIBILITY_SUPPORT_FILES)) | tr " " "\n" > $(PRIVATE_INTERMEDIATES_DIR)/list
find $(PRIVATE_KERNEL_LTP_HOST_OUT) >> $(PRIVATE_INTERMEDIATES_DIR)/list
+ for symlink in $(PRIVATE_SYMLINKS); do \
+ echo $$symlink >> $(PRIVATE_INTERMEDIATES_DIR)/list; \
+ done
+ $(hide) for shared_lib in $(PRIVATE_HOST_SHARED_LIBS); do \
+ echo $$shared_lib >> $(PRIVATE_INTERMEDIATES_DIR)/shared-libs.list; \
+ done
+ grep $(HOST_OUT_TESTCASES) $(PRIVATE_INTERMEDIATES_DIR)/shared-libs.list > $(PRIVATE_INTERMEDIATES_DIR)/host-shared-libs.list || true
grep $(HOST_OUT_TESTCASES) $(PRIVATE_INTERMEDIATES_DIR)/list > $(PRIVATE_INTERMEDIATES_DIR)/host.list || true
grep $(TARGET_OUT_TESTCASES) $(PRIVATE_INTERMEDIATES_DIR)/list > $(PRIVATE_INTERMEDIATES_DIR)/target.list || true
grep -e .*\\.config$$ $(PRIVATE_INTERMEDIATES_DIR)/host.list > $(PRIVATE_INTERMEDIATES_DIR)/host-test-configs.list || true
@@ -62,6 +93,7 @@
-P host -C $(PRIVATE_INTERMEDIATES_DIR) -D $(PRIVATE_INTERMEDIATES_DIR)/tools \
-P host -C $(HOST_OUT) -l $(PRIVATE_INTERMEDIATES_DIR)/host.list \
-P target -C $(PRODUCT_OUT) -l $(PRIVATE_INTERMEDIATES_DIR)/target.list \
+ -P host -C $(HOST_OUT) -l $(PRIVATE_INTERMEDIATES_DIR)/host-shared-libs.list \
-sha256
$(SOONG_ZIP) -d -o $(PRIVATE_general_tests_configs_zip) \
-P host -C $(HOST_OUT) -l $(PRIVATE_INTERMEDIATES_DIR)/host-test-configs.list \
@@ -82,3 +114,6 @@
general_tests_list_zip :=
general_tests_configs_zip :=
general_tests_shared_libs_zip :=
+my_host_shared_lib_for_general_tests :=
+my_symlinks_for_general_tests :=
+my_general_tests_shared_lib_files :=
\ No newline at end of file
diff --git a/core/tasks/sts-sdk.mk b/core/tasks/sts-sdk.mk
deleted file mode 100644
index 4abbc29..0000000
--- a/core/tasks/sts-sdk.mk
+++ /dev/null
@@ -1,39 +0,0 @@
-# Copyright (C) 2022 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-ifneq ($(wildcard test/sts/README-sts-sdk.md),)
-test_suite_name := sts-sdk
-test_suite_tradefed := sts-tradefed
-test_suite_readme := test/sts/README-sts-sdk.md
-sts_sdk_zip := $(HOST_OUT)/$(test_suite_name)/sts-sdk.zip
-
-include $(BUILD_SYSTEM)/tasks/tools/compatibility.mk
-
-sts_sdk_plugin_skel := $(call intermediates-dir-for,ETC,sts-sdk-plugin-skel.zip)/sts-sdk-plugin-skel.zip
-
-$(sts_sdk_zip): STS_SDK_ZIP := $(compatibility_zip)
-$(sts_sdk_zip): STS_SDK_PLUGIN_SKEL := $(sts_sdk_plugin_skel)
-$(sts_sdk_zip): $(MERGE_ZIPS) $(ZIP2ZIP) $(compatibility_zip) $(sts_sdk_plugin_skel)
- rm -f $@ $(STS_SDK_ZIP)_filtered
- $(ZIP2ZIP) -i $(STS_SDK_ZIP) -o $(STS_SDK_ZIP)_filtered \
- -x android-sts-sdk/tools/sts-tradefed-tests.jar \
- 'android-sts-sdk/tools/*:sts-sdk/src/main/resources/sts-tradefed-tools/'
- $(MERGE_ZIPS) $@ $(STS_SDK_ZIP)_filtered $(STS_SDK_PLUGIN_SKEL)
- rm -f $(STS_SDK_ZIP)_filtered
-
-.PHONY: sts-sdk
-sts-sdk: $(sts_sdk_zip)
-$(call dist-for-goals, sts-sdk, $(sts_sdk_zip))
-
-endif
diff --git a/target/board/Android.mk b/target/board/Android.mk
index 8133af9..36be002 100644
--- a/target/board/Android.mk
+++ b/target/board/Android.mk
@@ -51,29 +51,6 @@
# Copy compatibility metadata to the device.
-# Device Manifest
-ifdef DEVICE_MANIFEST_FILE
-# $(DEVICE_MANIFEST_FILE) can be a list of files
-include $(CLEAR_VARS)
-LOCAL_MODULE := vendor_manifest.xml
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 legacy_not_a_contribution
-LOCAL_LICENSE_CONDITIONS := by_exception_only not_allowed notice
-LOCAL_MODULE_STEM := manifest.xml
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/etc/vintf
-
-GEN := $(local-generated-sources-dir)/manifest.xml
-$(GEN): PRIVATE_DEVICE_MANIFEST_FILE := $(DEVICE_MANIFEST_FILE)
-$(GEN): $(DEVICE_MANIFEST_FILE) $(HOST_OUT_EXECUTABLES)/assemble_vintf
- BOARD_SEPOLICY_VERS=$(BOARD_SEPOLICY_VERS) \
- PRODUCT_ENFORCE_VINTF_MANIFEST=$(PRODUCT_ENFORCE_VINTF_MANIFEST) \
- $(HOST_OUT_EXECUTABLES)/assemble_vintf -o $@ \
- -i $(call normalize-path-list,$(PRIVATE_DEVICE_MANIFEST_FILE))
-
-LOCAL_PREBUILT_MODULE_FILE := $(GEN)
-include $(BUILD_PREBUILT)
-endif
-
# DEVICE_MANIFEST_SKUS: a list of SKUS where DEVICE_MANIFEST_<sku>_FILES is defined.
ifdef DEVICE_MANIFEST_SKUS
@@ -112,30 +89,6 @@
endif # DEVICE_MANIFEST_SKUS
-# ODM manifest
-ifdef ODM_MANIFEST_FILES
-# ODM_MANIFEST_FILES is a list of files that is combined and installed as the default ODM manifest.
-include $(CLEAR_VARS)
-LOCAL_MODULE := odm_manifest.xml
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 legacy_not_a_contribution
-LOCAL_LICENSE_CONDITIONS := by_exception_only not_allowed notice
-LOCAL_MODULE_STEM := manifest.xml
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_RELATIVE_PATH := vintf
-LOCAL_ODM_MODULE := true
-
-GEN := $(local-generated-sources-dir)/manifest.xml
-$(GEN): PRIVATE_SRC_FILES := $(ODM_MANIFEST_FILES)
-$(GEN): $(ODM_MANIFEST_FILES) $(HOST_OUT_EXECUTABLES)/assemble_vintf
- # Set VINTF_IGNORE_TARGET_FCM_VERSION to true because it should only be in device manifest.
- VINTF_IGNORE_TARGET_FCM_VERSION=true \
- $(HOST_OUT_EXECUTABLES)/assemble_vintf -o $@ \
- -i $(call normalize-path-list,$(PRIVATE_SRC_FILES))
-
-LOCAL_PREBUILT_MODULE_FILE := $(GEN)
-include $(BUILD_PREBUILT)
-endif # ODM_MANIFEST_FILES
-
# ODM_MANIFEST_SKUS: a list of SKUS where ODM_MANIFEST_<sku>_FILES are defined.
ifdef ODM_MANIFEST_SKUS
diff --git a/target/product/base_system.mk b/target/product/base_system.mk
index 4a27b7d..8f2f7e3 100644
--- a/target/product/base_system.mk
+++ b/target/product/base_system.mk
@@ -274,7 +274,6 @@
Shell \
shell_and_utilities_system \
sm \
- snapshotctl \
snapuserd \
storaged \
surfaceflinger \
@@ -351,6 +350,11 @@
com.android.ranging
endif
+ifeq ($(RELEASE_MEMORY_MANAGEMENT_DAEMON),true)
+ PRODUCT_PACKAGES += \
+ mm_daemon
+endif
+
# VINTF data for system image
PRODUCT_PACKAGES += \
system_manifest.xml \
@@ -425,6 +429,7 @@
lpdump \
mke2fs \
mkfs.erofs \
+ pbtombstone \
resize2fs \
sgdisk \
sqlite3 \
@@ -492,6 +497,7 @@
record_binder \
servicedispatcher \
showmap \
+ snapshotctl \
sqlite3 \
ss \
start_with_lockagent \
@@ -505,10 +511,6 @@
unwind_reg_info \
unwind_symbols \
-# For Remotely Provisioned Certificate Processor
-PRODUCT_SYSTEM_PROPERTIES += \
- remote_provisioning.use_cert_processor=false
-
# The set of packages whose code can be loaded by the system server.
PRODUCT_SYSTEM_SERVER_APPS += \
SettingsProvider \
diff --git a/target/product/base_vendor.mk b/target/product/base_vendor.mk
index 3f85941..16fc7fd 100644
--- a/target/product/base_vendor.mk
+++ b/target/product/base_vendor.mk
@@ -71,6 +71,8 @@
passwd_odm \
passwd_vendor \
selinux_policy_nonsystem \
+ selinux_policy_vendor \
+ selinux_policy_odm \
shell_and_utilities_vendor \
odm-build.prop \
@@ -104,6 +106,7 @@
# VINTF data for vendor image
PRODUCT_PACKAGES += \
vendor_compatibility_matrix.xml \
+ vendor_manifest.xml \
# Base modules and settings for the debug ramdisk, which is then packed
# into a boot-debug.img and a vendor_boot-debug.img.
diff --git a/target/product/generic/Android.bp b/target/product/generic/Android.bp
index c980959..017f8fb 100644
--- a/target/product/generic/Android.bp
+++ b/target/product/generic/Android.bp
@@ -385,7 +385,6 @@
"android.software.webview.prebuilt.xml", // media_system
"android.software.window_magnification.prebuilt.xml", // handheld_system
"android.system.suspend-service",
- "prebuilt_vintf_manifest",
"apexd",
"appops",
"approved-ogki-builds.xml", // base_system
@@ -530,6 +529,7 @@
"storaged", // base_system
"surfaceflinger", // base_system
"svc", // base_system
+ "system_manifest.xml", // base_system
"task_profiles.json", // base_system
"tc", // base_system
"telecom", // base_system
@@ -563,6 +563,11 @@
"trace_redactor", // base_system (RELEASE_PACKAGE_PROFILING_MODULE)
],
default: [],
+ }) + select(release_flag("RELEASE_MEMORY_MANAGEMENT_DAEMON"), {
+ true: [
+ "mm_daemon", // base_system (RELEASE_MEMORY_MANAGEMENT_DAEMON)
+ ],
+ default: [],
}) + select(product_variable("debuggable"), {
true: [
"adevice_fingerprint",
@@ -863,11 +868,3 @@
},
},
}
-
-prebuilt_etc {
- name: "prebuilt_vintf_manifest",
- src: "manifest.xml",
- filename: "manifest.xml",
- relative_install_path: "vintf",
- no_full_install: true,
-}
diff --git a/target/product/generic/manifest.xml b/target/product/generic/manifest.xml
deleted file mode 100644
index 1df2c0d..0000000
--- a/target/product/generic/manifest.xml
+++ /dev/null
@@ -1,54 +0,0 @@
-<!--
- Input:
- system/libhidl/vintfdata/manifest.xml
--->
-<manifest version="8.0" type="framework">
- <hal format="hidl" max-level="6">
- <name>android.frameworks.displayservice</name>
- <transport>hwbinder</transport>
- <fqname>@1.0::IDisplayService/default</fqname>
- </hal>
- <hal format="hidl" max-level="5">
- <name>android.frameworks.schedulerservice</name>
- <transport>hwbinder</transport>
- <fqname>@1.0::ISchedulingPolicyService/default</fqname>
- </hal>
- <hal format="aidl">
- <name>android.frameworks.sensorservice</name>
- <fqname>ISensorManager/default</fqname>
- </hal>
- <hal format="hidl" max-level="8">
- <name>android.frameworks.sensorservice</name>
- <transport>hwbinder</transport>
- <fqname>@1.0::ISensorManager/default</fqname>
- </hal>
- <hal format="hidl" max-level="8">
- <name>android.hidl.memory</name>
- <transport arch="32+64">passthrough</transport>
- <fqname>@1.0::IMapper/ashmem</fqname>
- </hal>
- <hal format="hidl" max-level="7">
- <name>android.system.net.netd</name>
- <transport>hwbinder</transport>
- <fqname>@1.1::INetd/default</fqname>
- </hal>
- <hal format="hidl" max-level="7">
- <name>android.system.wifi.keystore</name>
- <transport>hwbinder</transport>
- <fqname>@1.0::IKeystore/default</fqname>
- </hal>
- <hal format="native">
- <name>netutils-wrapper</name>
- <version>1.0</version>
- </hal>
- <system-sdk>
- <version>29</version>
- <version>30</version>
- <version>31</version>
- <version>32</version>
- <version>33</version>
- <version>34</version>
- <version>35</version>
- <version>VanillaIceCream</version>
- </system-sdk>
-</manifest>
diff --git a/target/product/virtual_ab_ota/compression.mk b/target/product/virtual_ab_ota/compression.mk
index dc1ee3e..e77c36f 100644
--- a/target/product/virtual_ab_ota/compression.mk
+++ b/target/product/virtual_ab_ota/compression.mk
@@ -18,9 +18,12 @@
PRODUCT_VENDOR_PROPERTIES += ro.virtual_ab.compression.enabled=true
PRODUCT_VENDOR_PROPERTIES += ro.virtual_ab.userspace.snapshots.enabled=true
-PRODUCT_VENDOR_PROPERTIES += ro.virtual_ab.io_uring.enabled=true
PRODUCT_VENDOR_PROPERTIES += ro.virtual_ab.batch_writes=true
+# Optional assignment. On low memory devices, disabling io_uring can relieve cpu and memory
+# pressure during an OTA.
+PRODUCT_VENDOR_PROPERTIES += ro.virtual_ab.io_uring.enabled?=true
+
# Enabling this property, will improve OTA install time
# but will use an additional CPU core
# PRODUCT_VENDOR_PROPERTIES += ro.virtual_ab.compression.threads=true
diff --git a/target/product/virtual_ab_ota/vabc_features.mk b/target/product/virtual_ab_ota/vabc_features.mk
index e2745a1..d092699 100644
--- a/target/product/virtual_ab_ota/vabc_features.mk
+++ b/target/product/virtual_ab_ota/vabc_features.mk
@@ -31,14 +31,15 @@
PRODUCT_VENDOR_PROPERTIES += ro.virtual_ab.compression.enabled=true
PRODUCT_VENDOR_PROPERTIES += ro.virtual_ab.userspace.snapshots.enabled=true
-PRODUCT_VENDOR_PROPERTIES += ro.virtual_ab.io_uring.enabled=true
-PRODUCT_VENDOR_PROPERTIES += ro.virtual_ab.compression.xor.enabled=true
PRODUCT_VENDOR_PROPERTIES += ro.virtual_ab.batch_writes=true
+
+# Optional assignments, low memory devices may benefit from overriding these.
+PRODUCT_VENDOR_PROPERTIES += ro.virtual_ab.io_uring.enabled?=true
+PRODUCT_VENDOR_PROPERTIES += ro.virtual_ab.compression.xor.enabled?=true
+
# Low memory device configurations. If memory usage and cpu utilization is
# a bottleneck during OTA, the below configurations can be added to a
-# device's .mk file improve performance for low mem devices. Disabling
-# ro.virtual_ab.compression.xor.enabled and ro.virtual_ab.io_uring.enabled
-# is also recommended
+# device's .mk file improve performance for low mem devices.
#
# PRODUCT_VENDOR_PROPERTIES += ro.virtual_ab.read_ahead_size=16
# PRODUCT_VENDOR_PROPERTIES += ro.virtual_ab.o_direct.enabled=true
diff --git a/tools/aconfig/aconfig/Android.bp b/tools/aconfig/aconfig/Android.bp
index f4dd103..5e3eb12 100644
--- a/tools/aconfig/aconfig/Android.bp
+++ b/tools/aconfig/aconfig/Android.bp
@@ -68,6 +68,14 @@
],
}
+aconfig_values {
+ name: "aconfig.test.flag.second_values",
+ package: "com.android.aconfig.test",
+ srcs: [
+ "tests/third.values",
+ ],
+}
+
aconfig_value_set {
name: "aconfig.test.flag.value_set",
values: [
diff --git a/tools/aconfig/aconfig/src/codegen/java.rs b/tools/aconfig/aconfig/src/codegen/java.rs
index 47d4042..067a3b4 100644
--- a/tools/aconfig/aconfig/src/codegen/java.rs
+++ b/tools/aconfig/aconfig/src/codegen/java.rs
@@ -501,7 +501,7 @@
modified_parsed_flags.into_iter(),
mode,
flag_ids,
- false,
+ true,
)
.unwrap();
let expect_flags_content = EXPECTED_FLAG_COMMON_CONTENT.to_string()
@@ -561,6 +561,8 @@
+ "flag declaration.",
e
);
+ } catch (SecurityException e) {
+ // for isolated process case, skip loading flag value from the storage, use the default
}
aconfig_test_is_cached = true;
}
@@ -579,6 +581,8 @@
+ "flag declaration.",
e
);
+ } catch (SecurityException e) {
+ // for isolated process case, skip loading flag value from the storage, use the default
}
other_namespace_is_cached = true;
}
@@ -787,6 +791,8 @@
+ "flag declaration.",
e
);
+ } catch (SecurityException e) {
+ // for isolated process case, skip loading flag value from the storage, use the default
}
aconfig_test_is_cached = true;
}
diff --git a/tools/aconfig/aconfig/src/codegen/rust.rs b/tools/aconfig/aconfig/src/codegen/rust.rs
index d318b96..569a34b 100644
--- a/tools/aconfig/aconfig/src/codegen/rust.rs
+++ b/tools/aconfig/aconfig/src/codegen/rust.rs
@@ -297,7 +297,7 @@
},
None => {
log!(Level::Error, "no context found for package com.android.aconfig.test");
- Ok(false)
+ Err(format!("failed to flag package com.android.aconfig.test"))
}
}
})
@@ -309,7 +309,7 @@
},
Err(err) => {
log!(Level::Error, "aconfig_rust_codegen: error: {err}");
- panic!("failed to read flag value: {err}");
+ return false;
}
}
} else {
@@ -344,7 +344,7 @@
},
None => {
log!(Level::Error, "no context found for package com.android.aconfig.test");
- Ok(false)
+ Err(format!("failed to flag package com.android.aconfig.test"))
}
}
})
@@ -356,7 +356,7 @@
},
Err(err) => {
log!(Level::Error, "aconfig_rust_codegen: error: {err}");
- panic!("failed to read flag value: {err}");
+ return false;
}
}
} else {
@@ -391,7 +391,7 @@
},
None => {
log!(Level::Error, "no context found for package com.android.aconfig.test");
- Ok(false)
+ Err(format!("failed to flag package com.android.aconfig.test"))
}
}
})
@@ -403,7 +403,7 @@
},
Err(err) => {
log!(Level::Error, "aconfig_rust_codegen: error: {err}");
- panic!("failed to read flag value: {err}");
+ return false;
}
}
} else {
@@ -439,7 +439,7 @@
},
None => {
log!(Level::Error, "no context found for package com.android.aconfig.test");
- Ok(true)
+ Err(format!("failed to flag package com.android.aconfig.test"))
}
}
})
@@ -451,7 +451,7 @@
},
Err(err) => {
log!(Level::Error, "aconfig_rust_codegen: error: {err}");
- panic!("failed to read flag value: {err}");
+ return true;
}
}
} else {
diff --git a/tools/aconfig/aconfig/src/commands.rs b/tools/aconfig/aconfig/src/commands.rs
index 496876e..0ad3d97 100644
--- a/tools/aconfig/aconfig/src/commands.rs
+++ b/tools/aconfig/aconfig/src/commands.rs
@@ -17,7 +17,7 @@
use anyhow::{bail, ensure, Context, Result};
use itertools::Itertools;
use protobuf::Message;
-use std::collections::{BTreeMap, HashMap};
+use std::collections::HashMap;
use std::hash::Hasher;
use std::io::Read;
use std::path::PathBuf;
@@ -425,23 +425,34 @@
#[allow(dead_code)] // TODO: b/316357686 - Use fingerprint in codegen to
// protect hardcoded offset reads.
-pub fn compute_flag_offsets_fingerprint(flags_map: &HashMap<String, u16>) -> Result<u64> {
+ // Creates a fingerprint of the flag names (which requires sorting the vector).
+ // Fingerprint is used by both codegen and storage files.
+pub fn compute_flags_fingerprint(flag_names: &mut Vec<String>) -> Result<u64> {
+ flag_names.sort();
+
let mut hasher = SipHasher13::new();
-
- // Need to sort to ensure the data is added to the hasher in the same order
- // each run.
- let sorted_map: BTreeMap<&String, &u16> = flags_map.iter().collect();
-
- for (flag, offset) in sorted_map {
- // See https://docs.rs/siphasher/latest/siphasher/#note for use of write
- // over write_i16. Similarly, use to_be_bytes rather than to_ne_bytes to
- // ensure consistency.
+ for flag in flag_names {
hasher.write(flag.as_bytes());
- hasher.write(&offset.to_be_bytes());
}
Ok(hasher.finish())
}
+#[allow(dead_code)] // TODO: b/316357686 - Use fingerprint in codegen to
+ // protect hardcoded offset reads.
+ // Converts ProtoParsedFlags into a vector of strings containing all of the flag
+ // names. Helper fn for creating fingerprint for codegen files. Flags must all
+ // belong to the same package.
+fn extract_flag_names(flags: ProtoParsedFlags) -> Result<Vec<String>> {
+ let separated_flags: Vec<ProtoParsedFlag> = flags.parsed_flag.into_iter().collect::<Vec<_>>();
+
+ // All flags must belong to the same package as the fingerprint is per-package.
+ let Some(_package) = find_unique_package(&separated_flags) else {
+ bail!("No parsed flags, or the parsed flags use different packages.");
+ };
+
+ Ok(separated_flags.into_iter().map(|flag| flag.name.unwrap()).collect::<Vec<_>>())
+}
+
#[cfg(test)]
mod tests {
use super::*;
@@ -450,16 +461,51 @@
#[test]
fn test_offset_fingerprint() {
let parsed_flags = crate::test::parse_test_flags();
- let package = find_unique_package(&parsed_flags.parsed_flag).unwrap().to_string();
- let flag_ids = assign_flag_ids(&package, parsed_flags.parsed_flag.iter()).unwrap();
- let expected_fingerprint = 10709892481002252132u64;
+ let expected_fingerprint: u64 = 5801144784618221668;
- let hash_result = compute_flag_offsets_fingerprint(&flag_ids);
+ let mut extracted_flags = extract_flag_names(parsed_flags).unwrap();
+ let hash_result = compute_flags_fingerprint(&mut extracted_flags);
assert_eq!(hash_result.unwrap(), expected_fingerprint);
}
#[test]
+ fn test_offset_fingerprint_matches_from_package() {
+ let parsed_flags: ProtoParsedFlags = crate::test::parse_test_flags();
+
+ // All test flags are in the same package, so fingerprint from all of them.
+ let mut extracted_flags = extract_flag_names(parsed_flags.clone()).unwrap();
+ let result_from_parsed_flags = compute_flags_fingerprint(&mut extracted_flags);
+
+ let mut flag_names_vec = parsed_flags
+ .parsed_flag
+ .clone()
+ .into_iter()
+ .map(|flag| flag.name.unwrap())
+ .map(String::from)
+ .collect::<Vec<_>>();
+ let result_from_names = compute_flags_fingerprint(&mut flag_names_vec);
+
+ // Assert the same hash is generated for each case.
+ assert_eq!(result_from_parsed_flags.unwrap(), result_from_names.unwrap());
+ }
+
+ #[test]
+ fn test_offset_fingerprint_different_packages_does_not_match() {
+ // Parse flags from two packages.
+ let parsed_flags: ProtoParsedFlags = crate::test::parse_test_flags();
+ let second_parsed_flags = crate::test::parse_second_package_flags();
+
+ let mut extracted_flags = extract_flag_names(parsed_flags).unwrap();
+ let result_from_parsed_flags = compute_flags_fingerprint(&mut extracted_flags).unwrap();
+ let mut second_extracted_flags = extract_flag_names(second_parsed_flags).unwrap();
+ let second_result = compute_flags_fingerprint(&mut second_extracted_flags).unwrap();
+
+ // Different flags should have a different fingerprint.
+ assert_ne!(result_from_parsed_flags, second_result);
+ }
+
+ #[test]
fn test_parse_flags() {
let parsed_flags = crate::test::parse_test_flags(); // calls parse_flags
aconfig_protos::parsed_flags::verify_fields(&parsed_flags).unwrap();
diff --git a/tools/aconfig/aconfig/src/test.rs b/tools/aconfig/aconfig/src/test.rs
index 7409cda..a19b372 100644
--- a/tools/aconfig/aconfig/src/test.rs
+++ b/tools/aconfig/aconfig/src/test.rs
@@ -295,6 +295,24 @@
aconfig_protos::parsed_flags::try_from_binary_proto(&bytes).unwrap()
}
+ pub fn parse_second_package_flags() -> ProtoParsedFlags {
+ let bytes = crate::commands::parse_flags(
+ "com.android.aconfig.second_test",
+ Some("system"),
+ vec![Input {
+ source: "tests/test_second_package.aconfig".to_string(),
+ reader: Box::new(include_bytes!("../tests/test_second_package.aconfig").as_slice()),
+ }],
+ vec![Input {
+ source: "tests/third.values".to_string(),
+ reader: Box::new(include_bytes!("../tests/third.values").as_slice()),
+ }],
+ crate::commands::DEFAULT_FLAG_PERMISSION,
+ )
+ .unwrap();
+ aconfig_protos::parsed_flags::try_from_binary_proto(&bytes).unwrap()
+ }
+
pub fn first_significant_code_diff(a: &str, b: &str) -> Option<String> {
let a = a.lines().map(|line| line.trim_start()).filter(|line| !line.is_empty());
let b = b.lines().map(|line| line.trim_start()).filter(|line| !line.is_empty());
diff --git a/tools/aconfig/aconfig/templates/FeatureFlagsImpl.java.template b/tools/aconfig/aconfig/templates/FeatureFlagsImpl.java.template
index 26d3069..15df902 100644
--- a/tools/aconfig/aconfig/templates/FeatureFlagsImpl.java.template
+++ b/tools/aconfig/aconfig/templates/FeatureFlagsImpl.java.template
@@ -1,5 +1,6 @@
package {package_name};
{{ -if not is_test_mode }}
+{{ -if allow_instrumentation }}
{{ if not library_exported- }}
// TODO(b/303773055): Remove the annotation after access issue is resolved.
import android.compat.annotation.UnsupportedAppUsage;
@@ -73,6 +74,8 @@
+ "flag declaration.",
e
);
+ } catch (SecurityException e) \{
+ // for isolated process case, skip loading flag value from the storage, use the default
}
{namespace_with_flags.namespace}_is_cached = true;
}
@@ -110,6 +113,72 @@
}
{{ endfor }}
}
+
+{{ else }} {#- else for allow_instrumentation is not enabled #}
+{{ if not library_exported- }}
+// TODO(b/303773055): Remove the annotation after access issue is resolved.
+import android.compat.annotation.UnsupportedAppUsage;
+{{ -endif }}
+
+{{ -if runtime_lookup_required }}
+import android.provider.DeviceConfig;
+import android.provider.DeviceConfig.Properties;
+{{ -endif }}
+/** @hide */
+public final class FeatureFlagsImpl implements FeatureFlags \{
+{{ -if runtime_lookup_required }}
+{{ -for namespace_with_flags in namespace_flags }}
+ private static volatile boolean {namespace_with_flags.namespace}_is_cached = false;
+{{ -endfor- }}
+
+{{ for flag in flag_elements }}
+{{- if flag.is_read_write }}
+ private static boolean {flag.method_name} = {flag.default_value};
+{{ -endif }}
+{{ -endfor }}
+{{ for namespace_with_flags in namespace_flags }}
+ private void load_overrides_{namespace_with_flags.namespace}() \{
+ try \{
+ Properties properties = DeviceConfig.getProperties("{namespace_with_flags.namespace}");
+{{ -for flag in namespace_with_flags.flags }}
+{{ -if flag.is_read_write }}
+ {flag.method_name} =
+ properties.getBoolean(Flags.FLAG_{flag.flag_name_constant_suffix}, {flag.default_value});
+{{ -endif }}
+{{ -endfor }}
+ } catch (NullPointerException e) \{
+ throw new RuntimeException(
+ "Cannot read value from namespace {namespace_with_flags.namespace} "
+ + "from DeviceConfig. It could be that the code using flag "
+ + "executed before SettingsProvider initialization. Please use "
+ + "fixed read-only flag by adding is_fixed_read_only: true in "
+ + "flag declaration.",
+ e
+ );
+ }
+ {namespace_with_flags.namespace}_is_cached = true;
+}
+{{ endfor- }}
+{{ -endif }}{#- end of runtime_lookup_required #}
+{{ -for flag in flag_elements }}
+ @Override
+{{ -if not library_exported }}
+ @com.android.aconfig.annotations.AconfigFlagAccessor
+ @UnsupportedAppUsage
+{{ -endif }}
+ 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 }}
+ return {flag.default_value};
+{{ -endif }}
+ }
+{{ endfor }}
+}
+{{ endif}} {#- endif for allow_instrumentation #}
{{ else }} {#- Generate only stub if in test mode #}
/** @hide */
public final class FeatureFlagsImpl implements FeatureFlags \{
diff --git a/tools/aconfig/aconfig/templates/cpp_source_file.template b/tools/aconfig/aconfig/templates/cpp_source_file.template
index eaaf86f..df3b10d 100644
--- a/tools/aconfig/aconfig/templates/cpp_source_file.template
+++ b/tools/aconfig/aconfig/templates/cpp_source_file.template
@@ -92,17 +92,21 @@
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, "{package}");
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;
+ package_exists_in_storage_ = false;
+ return;
}
// cache package boolean flag start index
@@ -116,6 +120,8 @@
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
diff --git a/tools/aconfig/aconfig/templates/rust.template b/tools/aconfig/aconfig/templates/rust.template
index 6456360..d0079d4 100644
--- a/tools/aconfig/aconfig/templates/rust.template
+++ b/tools/aconfig/aconfig/templates/rust.template
@@ -53,7 +53,7 @@
},
None => \{
log!(Level::Error, "no context found for package {package}");
- Ok({flag.default_value})
+ Err(format!("failed to flag package {package}"))
}
}
})
@@ -65,7 +65,7 @@
},
Err(err) => \{
log!(Level::Error, "aconfig_rust_codegen: error: \{err}");
- panic!("failed to read flag value: \{err}");
+ return {flag.default_value};
}
}
} else \{
diff --git a/tools/aconfig/aconfig/tests/test_second_package.aconfig b/tools/aconfig/aconfig/tests/test_second_package.aconfig
new file mode 100644
index 0000000..188bc96
--- /dev/null
+++ b/tools/aconfig/aconfig/tests/test_second_package.aconfig
@@ -0,0 +1,10 @@
+package: "com.android.aconfig.second_test"
+container: "system"
+
+flag {
+ name: "testing_flag"
+ namespace: "another_namespace"
+ description: "This is a flag for testing."
+ bug: "123"
+}
+
diff --git a/tools/aconfig/aconfig/tests/third.values b/tools/aconfig/aconfig/tests/third.values
new file mode 100644
index 0000000..675832a
--- /dev/null
+++ b/tools/aconfig/aconfig/tests/third.values
@@ -0,0 +1,6 @@
+flag_value {
+ package: "com.android.aconfig.second_test"
+ name: "testing_flag"
+ state: DISABLED
+ permission: READ_WRITE
+}
diff --git a/tools/aconfig/aconfig_storage_file/src/lib.rs b/tools/aconfig/aconfig_storage_file/src/lib.rs
index 1d92ba4..5dc5ef7 100644
--- a/tools/aconfig/aconfig_storage_file/src/lib.rs
+++ b/tools/aconfig/aconfig_storage_file/src/lib.rs
@@ -228,10 +228,14 @@
/// Read and parse bytes as u8
pub fn read_u8_from_bytes(buf: &[u8], head: &mut usize) -> Result<u8, AconfigStorageError> {
- let val =
- u8::from_le_bytes(buf[*head..*head + 1].try_into().map_err(|errmsg| {
- BytesParseFail(anyhow!("fail to parse u8 from bytes: {}", errmsg))
- })?);
+ let val = u8::from_le_bytes(
+ buf.get(*head..*head + 1)
+ .ok_or(AconfigStorageError::BytesParseFail(anyhow!(
+ "fail to parse u8 from bytes: access out of bounds"
+ )))?
+ .try_into()
+ .map_err(|errmsg| BytesParseFail(anyhow!("fail to parse u8 from bytes: {}", errmsg)))?,
+ );
*head += 1;
Ok(val)
}
@@ -241,10 +245,16 @@
buf: &[u8],
head: &mut usize,
) -> Result<u16, AconfigStorageError> {
- let val =
- u16::from_le_bytes(buf[*head..*head + 2].try_into().map_err(|errmsg| {
- BytesParseFail(anyhow!("fail to parse u16 from bytes: {}", errmsg))
- })?);
+ let val = u16::from_le_bytes(
+ buf.get(*head..*head + 2)
+ .ok_or(AconfigStorageError::BytesParseFail(anyhow!(
+ "fail to parse u16 from bytes: access out of bounds"
+ )))?
+ .try_into()
+ .map_err(|errmsg| {
+ BytesParseFail(anyhow!("fail to parse u16 from bytes: {}", errmsg))
+ })?,
+ );
*head += 2;
Ok(val)
}
@@ -256,20 +266,32 @@
/// Read and parse bytes as u32
pub fn read_u32_from_bytes(buf: &[u8], head: &mut usize) -> Result<u32, AconfigStorageError> {
- let val =
- u32::from_le_bytes(buf[*head..*head + 4].try_into().map_err(|errmsg| {
- BytesParseFail(anyhow!("fail to parse u32 from bytes: {}", errmsg))
- })?);
+ let val = u32::from_le_bytes(
+ buf.get(*head..*head + 4)
+ .ok_or(AconfigStorageError::BytesParseFail(anyhow!(
+ "fail to parse u32 from bytes: access out of bounds"
+ )))?
+ .try_into()
+ .map_err(|errmsg| {
+ BytesParseFail(anyhow!("fail to parse u32 from bytes: {}", errmsg))
+ })?,
+ );
*head += 4;
Ok(val)
}
// Read and parse bytes as u64
pub fn read_u64_from_bytes(buf: &[u8], head: &mut usize) -> Result<u64, AconfigStorageError> {
- let val =
- u64::from_le_bytes(buf[*head..*head + 8].try_into().map_err(|errmsg| {
- BytesParseFail(anyhow!("fail to parse u64 from bytes: {}", errmsg))
- })?);
+ let val = u64::from_le_bytes(
+ buf.get(*head..*head + 8)
+ .ok_or(AconfigStorageError::BytesParseFail(anyhow!(
+ "fail to parse u64 from bytes: access out of bounds"
+ )))?
+ .try_into()
+ .map_err(|errmsg| {
+ BytesParseFail(anyhow!("fail to parse u64 from bytes: {}", errmsg))
+ })?,
+ );
*head += 8;
Ok(val)
}
@@ -280,8 +302,21 @@
head: &mut usize,
) -> Result<String, AconfigStorageError> {
let num_bytes = read_u32_from_bytes(buf, head)? as usize;
- let val = String::from_utf8(buf[*head..*head + num_bytes].to_vec())
- .map_err(|errmsg| BytesParseFail(anyhow!("fail to parse string from bytes: {}", errmsg)))?;
+ // TODO(opg): Document this limitation and check it when creating files.
+ if num_bytes > 1024 {
+ return Err(AconfigStorageError::BytesParseFail(anyhow!(
+ "fail to parse string from bytes, string is too long (found {}, max is 1024)",
+ num_bytes
+ )));
+ }
+ let val = String::from_utf8(
+ buf.get(*head..*head + num_bytes)
+ .ok_or(AconfigStorageError::BytesParseFail(anyhow!(
+ "fail to parse string from bytes: access out of bounds"
+ )))?
+ .to_vec(),
+ )
+ .map_err(|errmsg| BytesParseFail(anyhow!("fail to parse string from bytes: {}", errmsg)))?;
*head += num_bytes;
Ok(val)
}
@@ -533,6 +568,34 @@
};
#[test]
+ fn test_list_flags_with_missing_files_error() {
+ let flag_list_error = list_flags("does", "not", "exist").unwrap_err();
+ assert_eq!(
+ format!("{:?}", flag_list_error),
+ format!(
+ "FileReadFail(Failed to open file does: No such file or directory (os error 2))"
+ )
+ );
+ }
+
+ #[test]
+ fn test_list_flags_with_invalid_files_error() {
+ let invalid_bytes: [u8; 3] = [0; 3];
+ let package_table = write_bytes_to_temp_file(&invalid_bytes).unwrap();
+ let flag_table = write_bytes_to_temp_file(&invalid_bytes).unwrap();
+ let flag_value_list = write_bytes_to_temp_file(&invalid_bytes).unwrap();
+ let package_table_path = package_table.path().display().to_string();
+ let flag_table_path = flag_table.path().display().to_string();
+ let flag_value_list_path = flag_value_list.path().display().to_string();
+ let flag_list_error =
+ list_flags(&package_table_path, &flag_table_path, &flag_value_list_path).unwrap_err();
+ assert_eq!(
+ format!("{:?}", flag_list_error),
+ format!("BytesParseFail(fail to parse u32 from bytes: access out of bounds)")
+ );
+ }
+
+ #[test]
// this test point locks down the flag list api
fn test_list_flag() {
let package_table =
diff --git a/tools/aconfig/aconfig_storage_file/srcs/android/aconfig/storage/ByteBufferReader.java b/tools/aconfig/aconfig_storage_file/srcs/android/aconfig/storage/ByteBufferReader.java
index 4bea083..9571568 100644
--- a/tools/aconfig/aconfig_storage_file/srcs/android/aconfig/storage/ByteBufferReader.java
+++ b/tools/aconfig/aconfig_storage_file/srcs/android/aconfig/storage/ByteBufferReader.java
@@ -41,8 +41,16 @@
return this.mByteBuffer.getInt();
}
+ public long readLong() {
+ return this.mByteBuffer.getLong();
+ }
+
public String readString() {
int length = readInt();
+ if (length > 1024) {
+ throw new AconfigStorageException(
+ "String length exceeds maximum allowed size (1024 bytes): " + length);
+ }
byte[] bytes = new byte[length];
mByteBuffer.get(bytes, 0, length);
return new String(bytes, StandardCharsets.UTF_8);
diff --git a/tools/aconfig/aconfig_storage_file/srcs/android/aconfig/storage/PackageTable.java b/tools/aconfig/aconfig_storage_file/srcs/android/aconfig/storage/PackageTable.java
index 39b7e59..a45d12a 100644
--- a/tools/aconfig/aconfig_storage_file/srcs/android/aconfig/storage/PackageTable.java
+++ b/tools/aconfig/aconfig_storage_file/srcs/android/aconfig/storage/PackageTable.java
@@ -124,8 +124,10 @@
private String mPackageName;
private int mPackageId;
+ private long mPackageFingerprint;
private int mBooleanStartIndex;
private int mNextOffset;
+ private boolean mHasPackageFingerprint;
private static Node fromBytes(ByteBufferReader reader, int version) {
switch (version) {
@@ -153,9 +155,11 @@
Node node = new Node();
node.mPackageName = reader.readString();
node.mPackageId = reader.readInt();
+ node.mPackageFingerprint = reader.readLong();
node.mBooleanStartIndex = reader.readInt();
node.mNextOffset = reader.readInt();
node.mNextOffset = node.mNextOffset == 0 ? -1 : node.mNextOffset;
+ node.mHasPackageFingerprint = true;
return node;
}
@@ -189,6 +193,10 @@
return mPackageId;
}
+ public long getPackageFingerprint() {
+ return mPackageFingerprint;
+ }
+
public int getBooleanStartIndex() {
return mBooleanStartIndex;
}
@@ -196,5 +204,9 @@
public int getNextOffset() {
return mNextOffset;
}
+
+ public boolean hasPackageFingerprint() {
+ return mHasPackageFingerprint;
+ }
}
}
diff --git a/tools/aconfig/aconfig_storage_file/tests/srcs/PackageTableTest.java b/tools/aconfig/aconfig_storage_file/tests/srcs/PackageTableTest.java
index e7e19d8..dc2ad92 100644
--- a/tools/aconfig/aconfig_storage_file/tests/srcs/PackageTableTest.java
+++ b/tools/aconfig/aconfig_storage_file/tests/srcs/PackageTableTest.java
@@ -17,6 +17,7 @@
package android.aconfig.storage.test;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import android.aconfig.storage.FileType;
import android.aconfig.storage.PackageTable;
@@ -66,5 +67,9 @@
assertEquals(159, node1.getNextOffset());
assertEquals(-1, node2.getNextOffset());
assertEquals(-1, node4.getNextOffset());
+
+ assertFalse(node1.hasPackageFingerprint());
+ assertFalse(node2.hasPackageFingerprint());
+ assertFalse(node4.hasPackageFingerprint());
}
}
diff --git a/tools/aconfig/aconfig_storage_read_api/Android.bp b/tools/aconfig/aconfig_storage_read_api/Android.bp
index 80b8ece..666c5ba 100644
--- a/tools/aconfig/aconfig_storage_read_api/Android.bp
+++ b/tools/aconfig/aconfig_storage_read_api/Android.bp
@@ -154,6 +154,8 @@
java_library {
name: "aconfig_storage_reader_java",
srcs: [
+ "srcs/android/aconfig/storage/AconfigPackageImpl.java",
+ "srcs/android/aconfig/storage/StorageFileProvider.java",
"srcs/android/aconfig/storage/StorageInternalReader.java",
],
libs: [
@@ -175,6 +177,8 @@
java_library {
name: "aconfig_storage_reader_java_none",
srcs: [
+ "srcs/android/aconfig/storage/AconfigPackageImpl.java",
+ "srcs/android/aconfig/storage/StorageFileProvider.java",
"srcs/android/aconfig/storage/StorageInternalReader.java",
],
libs: [
diff --git a/tools/aconfig/aconfig_storage_read_api/srcs/android/aconfig/storage/AconfigPackageImpl.java b/tools/aconfig/aconfig_storage_read_api/srcs/android/aconfig/storage/AconfigPackageImpl.java
new file mode 100644
index 0000000..5d8e7cb
--- /dev/null
+++ b/tools/aconfig/aconfig_storage_read_api/srcs/android/aconfig/storage/AconfigPackageImpl.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.aconfig.storage;
+
+import android.os.StrictMode;
+
+import java.nio.file.Path;
+
+/** @hide */
+public class AconfigPackageImpl {
+ private FlagTable mFlagTable;
+ private FlagValueList mFlagValueList;
+ private PackageTable.Node mPNode;
+
+ /** @hide */
+ public static final int ERROR_NEW_STORAGE_SYSTEM_NOT_FOUND = 1;
+
+ /** @hide */
+ public static final int ERROR_PACKAGE_NOT_FOUND = 2;
+
+ /** @hide */
+ public static final int ERROR_CONTAINER_NOT_FOUND = 3;
+
+ /** @hide */
+ public AconfigPackageImpl() {}
+
+ /** @hide */
+ public int load(String packageName, StorageFileProvider fileProvider) {
+ return init(null, packageName, fileProvider);
+ }
+
+ /** @hide */
+ public int load(String container, String packageName, StorageFileProvider fileProvider) {
+ if (container == null) {
+ return ERROR_CONTAINER_NOT_FOUND;
+ }
+
+ return init(container, packageName, fileProvider);
+ }
+
+ /** @hide */
+ public boolean getBooleanFlagValue(String flagName, boolean defaultValue) {
+ FlagTable.Node fNode = mFlagTable.get(mPNode.getPackageId(), flagName);
+ // no such flag in this package
+ if (fNode == null) return defaultValue;
+ int index = fNode.getFlagIndex() + mPNode.getBooleanStartIndex();
+ return mFlagValueList.getBoolean(index);
+ }
+
+ /** @hide */
+ public boolean getBooleanFlagValue(int index) {
+ return mFlagValueList.getBoolean(index + mPNode.getBooleanStartIndex());
+ }
+
+ /** @hide */
+ public long getPackageFingerprint() {
+ return mPNode.getPackageFingerprint();
+ }
+
+ /** @hide */
+ public boolean hasPackageFingerprint() {
+ return mPNode.hasPackageFingerprint();
+ }
+
+ private int init(String containerName, String packageName, StorageFileProvider fileProvider) {
+ StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
+ String container = containerName;
+ try {
+ // for devices don't have new storage directly return
+ if (!fileProvider.containerFileExists(null)) {
+ return ERROR_NEW_STORAGE_SYSTEM_NOT_FOUND;
+ }
+ PackageTable.Node pNode = null;
+
+ if (container == null) {
+ // Check if the device has flag files on the system partition.
+ // If the device does, search the system partition first.
+ container = "system";
+ if (fileProvider.containerFileExists(container)) {
+ pNode = fileProvider.getPackageTable(container).get(packageName);
+ }
+
+ if (pNode == null) {
+ // Search all package map files if not found in the system partition.
+ for (Path p : fileProvider.listPackageMapFiles()) {
+ PackageTable pTable = StorageFileProvider.getPackageTable(p);
+ pNode = pTable.get(packageName);
+ if (pNode != null) {
+ container = pTable.getHeader().getContainer();
+ break;
+ }
+ }
+ }
+ } else {
+ if (!fileProvider.containerFileExists(container)) {
+ return ERROR_CONTAINER_NOT_FOUND;
+ }
+ pNode = fileProvider.getPackageTable(container).get(packageName);
+ }
+
+ if (pNode == null) {
+ // for the case package is not found in all container, return instead of throwing
+ // error
+ return ERROR_PACKAGE_NOT_FOUND;
+ }
+
+ mFlagTable = fileProvider.getFlagTable(container);
+ mFlagValueList = fileProvider.getFlagValueList(container);
+ mPNode = pNode;
+ } catch (Exception e) {
+ throw e;
+ } finally {
+ StrictMode.setThreadPolicy(oldPolicy);
+ }
+ return 0;
+ }
+}
diff --git a/tools/aconfig/aconfig_storage_read_api/srcs/android/aconfig/storage/StorageFileProvider.java b/tools/aconfig/aconfig_storage_read_api/srcs/android/aconfig/storage/StorageFileProvider.java
new file mode 100644
index 0000000..1f84a51
--- /dev/null
+++ b/tools/aconfig/aconfig_storage_read_api/srcs/android/aconfig/storage/StorageFileProvider.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.aconfig.storage;
+
+import java.io.Closeable;
+import java.nio.MappedByteBuffer;
+import java.nio.channels.FileChannel;
+import java.nio.file.DirectoryStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardOpenOption;
+import java.util.ArrayList;
+import java.util.List;
+
+/** @hide */
+public class StorageFileProvider {
+
+ private static final String DEFAULT_MAP_PATH = "/metadata/aconfig/maps/";
+ private static final String DEFAULT_BOOT_PATH = "/metadata/aconfig/boot/";
+ private static final String PMAP_FILE_EXT = ".package.map";
+ private static final String FMAP_FILE_EXT = ".flag.map";
+ private static final String VAL_FILE_EXT = ".val";
+
+ private final String mMapPath;
+ private final String mBootPath;
+
+ /** @hide */
+ public static StorageFileProvider getDefaultProvider() {
+ return new StorageFileProvider(DEFAULT_MAP_PATH, DEFAULT_BOOT_PATH);
+ }
+
+ /** @hide */
+ public StorageFileProvider(String mapPath, String bootPath) {
+ mMapPath = mapPath;
+ mBootPath = bootPath;
+ }
+
+ /** @hide */
+ public boolean containerFileExists(String container) {
+ if (container == null) {
+ return Files.exists(Paths.get(mMapPath));
+ }
+ return Files.exists(Paths.get(mMapPath, container + PMAP_FILE_EXT));
+ }
+
+ /** @hide */
+ public List<Path> listPackageMapFiles() {
+ List<Path> result = new ArrayList<>();
+ try {
+ DirectoryStream<Path> stream =
+ Files.newDirectoryStream(Paths.get(mMapPath), "*" + PMAP_FILE_EXT);
+ for (Path entry : stream) {
+ result.add(entry);
+ // sb.append(entry. toString());
+ }
+ } catch (Exception e) {
+ throw new AconfigStorageException(
+ String.format("Fail to list map files in path %s", mMapPath), e);
+ }
+
+ return result;
+ }
+
+ /** @hide */
+ public PackageTable getPackageTable(String container) {
+ return getPackageTable(Paths.get(mMapPath, container + PMAP_FILE_EXT));
+ }
+
+ /** @hide */
+ public FlagTable getFlagTable(String container) {
+ return FlagTable.fromBytes(mapStorageFile(Paths.get(mMapPath, container + FMAP_FILE_EXT)));
+ }
+
+ /** @hide */
+ public FlagValueList getFlagValueList(String container) {
+ return FlagValueList.fromBytes(
+ mapStorageFile(Paths.get(mBootPath, container + VAL_FILE_EXT)));
+ }
+
+ /** @hide */
+ public static PackageTable getPackageTable(Path path) {
+ return PackageTable.fromBytes(mapStorageFile(path));
+ }
+
+ // Map a storage file given file path
+ private static MappedByteBuffer mapStorageFile(Path file) {
+ FileChannel channel = null;
+ try {
+ channel = FileChannel.open(file, StandardOpenOption.READ);
+ return channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());
+ } catch (Exception e) {
+ throw new AconfigStorageException(
+ String.format("Fail to mmap storage file %s", file), e);
+ } finally {
+ quietlyDispose(channel);
+ }
+ }
+
+ private static void quietlyDispose(Closeable closable) {
+ try {
+ if (closable != null) {
+ closable.close();
+ }
+ } catch (Exception e) {
+ // no need to care, at least as of now
+ }
+ }
+}
diff --git a/tools/aconfig/aconfig_storage_read_api/tests/java/AconfigPackageImplTest.java b/tools/aconfig/aconfig_storage_read_api/tests/java/AconfigPackageImplTest.java
new file mode 100644
index 0000000..8a72f0a
--- /dev/null
+++ b/tools/aconfig/aconfig_storage_read_api/tests/java/AconfigPackageImplTest.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.aconfig.storage.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.assertTrue;
+
+import android.aconfig.storage.AconfigPackageImpl;
+import android.aconfig.storage.AconfigStorageException;
+import android.aconfig.storage.StorageFileProvider;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class AconfigPackageImplTest {
+
+ private StorageFileProvider pr;
+
+ @Before
+ public void setup() {
+ pr = new StorageFileProvider(TestDataUtils.TESTDATA_PATH, TestDataUtils.TESTDATA_PATH);
+ }
+
+ @Test
+ public void testLoad_onlyPackageName() throws Exception {
+ AconfigPackageImpl p = new AconfigPackageImpl();
+ p.load("com.android.aconfig.storage.test_1", pr);
+ assertNotNull(p);
+ }
+
+ @Test
+ public void testLoad_groupNameFingerprint() throws Exception {
+ AconfigPackageImpl p = new AconfigPackageImpl();
+ p.load("mockup", "com.android.aconfig.storage.test_1", pr);
+ assertNotNull(p);
+ }
+
+ @Test
+ public void testLoad_error() throws Exception {
+ AconfigPackageImpl p = new AconfigPackageImpl();
+ // cannot find package
+ assertEquals(
+ AconfigPackageImpl.ERROR_PACKAGE_NOT_FOUND,
+ p.load("mockup", "com.android.aconfig.storage.test_10", pr));
+ // cannot find package
+ assertEquals(
+ AconfigPackageImpl.ERROR_PACKAGE_NOT_FOUND,
+ p.load("com.android.aconfig.storage.test_10", pr));
+ // cannot find container
+ assertEquals(
+ AconfigPackageImpl.ERROR_CONTAINER_NOT_FOUND,
+ p.load(null, "com.android.aconfig.storage.test_1", pr));
+ assertEquals(
+ AconfigPackageImpl.ERROR_CONTAINER_NOT_FOUND,
+ p.load("test", "com.android.aconfig.storage.test_1", pr));
+
+ // new storage doesn't exist
+ pr = new StorageFileProvider("fake/path/", "fake/path/");
+ assertEquals(
+ AconfigPackageImpl.ERROR_NEW_STORAGE_SYSTEM_NOT_FOUND, p.load("fake_package", pr));
+
+ // file read issue
+ pr = new StorageFileProvider(TestDataUtils.TESTDATA_PATH, "fake/path/");
+ assertThrows(
+ AconfigStorageException.class,
+ () -> p.load("mockup", "com.android.aconfig.storage.test_1", pr));
+ }
+
+ @Test
+ public void testGetBooleanFlagValue_flagName() throws Exception {
+ AconfigPackageImpl p = new AconfigPackageImpl();
+ p.load("mockup", "com.android.aconfig.storage.test_1", pr);
+ assertFalse(p.getBooleanFlagValue("disabled_rw", true));
+ assertTrue(p.getBooleanFlagValue("enabled_ro", false));
+ assertTrue(p.getBooleanFlagValue("enabled_rw", false));
+ assertFalse(p.getBooleanFlagValue("fake", false));
+ }
+
+ @Test
+ public void testGetBooleanFlagValue_index() throws Exception {
+ AconfigPackageImpl p = new AconfigPackageImpl();
+ p.load("mockup", "com.android.aconfig.storage.test_1", pr);
+ assertFalse(p.getBooleanFlagValue(0));
+ assertTrue(p.getBooleanFlagValue(1));
+ assertTrue(p.getBooleanFlagValue(2));
+ }
+
+ @Test
+ public void testHasPackageFingerprint() throws Exception {
+ AconfigPackageImpl p = new AconfigPackageImpl();
+ p.load("mockup", "com.android.aconfig.storage.test_1", pr);
+ assertFalse(p.hasPackageFingerprint());
+ }
+}
diff --git a/tools/aconfig/aconfig_storage_read_api/tests/java/Android.bp b/tools/aconfig/aconfig_storage_read_api/tests/java/Android.bp
index 3d4e9ad..9c88122 100644
--- a/tools/aconfig/aconfig_storage_read_api/tests/java/Android.bp
+++ b/tools/aconfig/aconfig_storage_read_api/tests/java/Android.bp
@@ -22,3 +22,28 @@
],
team: "trendy_team_android_core_experiments",
}
+
+android_test {
+ name: "aconfig_storage_package",
+ team: "trendy_team_android_core_experiments",
+ srcs: [
+ "AconfigPackageImplTest.java",
+ "StorageFileProviderTest.java",
+ "TestDataUtils.java",
+ ],
+ static_libs: [
+ "androidx.test.runner",
+ "junit",
+ "aconfig_storage_reader_java",
+ ],
+ test_config: "AndroidStorageJaveTest.xml",
+ manifest: "AndroidPackageTestManifest.xml",
+ sdk_version: "test_current",
+ data: [
+ ":read_api_test_storage_files",
+ ],
+ test_suites: [
+ "general-tests",
+ ],
+ jarjar_rules: "jarjar.txt",
+}
diff --git a/tools/aconfig/aconfig_storage_read_api/tests/java/AndroidPackageTestManifest.xml b/tools/aconfig/aconfig_storage_read_api/tests/java/AndroidPackageTestManifest.xml
new file mode 100644
index 0000000..5e01879
--- /dev/null
+++ b/tools/aconfig/aconfig_storage_read_api/tests/java/AndroidPackageTestManifest.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2024 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.aconfig.storage.test">
+ <application>
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.aconfig.storage.test" />
+
+</manifest>
diff --git a/tools/aconfig/aconfig_storage_read_api/tests/java/AndroidStorageJaveTest.xml b/tools/aconfig/aconfig_storage_read_api/tests/java/AndroidStorageJaveTest.xml
new file mode 100644
index 0000000..3d5bb8e
--- /dev/null
+++ b/tools/aconfig/aconfig_storage_read_api/tests/java/AndroidStorageJaveTest.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2024 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<configuration description="Test aconfig storage java tests">
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="aconfig_storage_package.apk" />
+ </target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
+ <option name="cleanup" value="true" />
+ <option name="push" value="package.map->/data/local/tmp/aconfig_storage_package/testdata/mockup.package.map" />
+ <option name="push" value="flag.map->/data/local/tmp/aconfig_storage_package/testdata/mockup.flag.map" />
+ <option name="push" value="flag.val->/data/local/tmp/aconfig_storage_package/testdata/mockup.val" />
+ <option name="push" value="flag.info->/data/local/tmp/aconfig_storage_package/testdata/mockup.info" />
+ <option name="post-push" value="chmod +r /data/local/tmp/aconfig_storage_package/testdata/" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.aconfig.storage.test" />
+ <option name="runtime-hint" value="1m" />
+ </test>
+</configuration>
\ No newline at end of file
diff --git a/tools/aconfig/aconfig_storage_read_api/tests/java/StorageFileProviderTest.java b/tools/aconfig/aconfig_storage_read_api/tests/java/StorageFileProviderTest.java
new file mode 100644
index 0000000..ba1ae9e
--- /dev/null
+++ b/tools/aconfig/aconfig_storage_read_api/tests/java/StorageFileProviderTest.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.aconfig.storage.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import android.aconfig.storage.FlagTable;
+import android.aconfig.storage.FlagValueList;
+import android.aconfig.storage.PackageTable;
+import android.aconfig.storage.StorageFileProvider;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.List;
+
+@RunWith(JUnit4.class)
+public class StorageFileProviderTest {
+
+ @Test
+ public void testContainerFileExists() throws Exception {
+ StorageFileProvider p =
+ new StorageFileProvider(TestDataUtils.TESTDATA_PATH, TestDataUtils.TESTDATA_PATH);
+ assertTrue(p.containerFileExists(null));
+ assertTrue(p.containerFileExists("mockup"));
+ assertFalse(p.containerFileExists("fake"));
+ }
+
+ @Test
+ public void testListpackageMapFiles() throws Exception {
+ StorageFileProvider p =
+ new StorageFileProvider(TestDataUtils.TESTDATA_PATH, TestDataUtils.TESTDATA_PATH);
+ // throw new Exception(Environment.getExternalStorageDirectory().getAbsolutePath());
+ List<Path> file = p.listPackageMapFiles();
+ assertEquals(1, file.size());
+ assertTrue(
+ file.get(0)
+ .equals(
+ Paths.get(
+ TestDataUtils.TESTDATA_PATH,
+ TestDataUtils.TEST_PACKAGE_MAP_PATH)));
+ }
+
+ @Test
+ public void testLoadFiles() throws Exception {
+ StorageFileProvider p =
+ new StorageFileProvider(TestDataUtils.TESTDATA_PATH, TestDataUtils.TESTDATA_PATH);
+ PackageTable pt = p.getPackageTable("mockup");
+ assertNotNull(pt);
+ pt =
+ StorageFileProvider.getPackageTable(
+ Paths.get(
+ TestDataUtils.TESTDATA_PATH, TestDataUtils.TEST_PACKAGE_MAP_PATH));
+ assertNotNull(pt);
+ FlagTable f = p.getFlagTable("mockup");
+ assertNotNull(f);
+ FlagValueList v = p.getFlagValueList("mockup");
+ assertNotNull(v);
+ }
+}
diff --git a/tools/aconfig/aconfig_storage_read_api/tests/java/TestDataUtils.java b/tools/aconfig/aconfig_storage_read_api/tests/java/TestDataUtils.java
new file mode 100644
index 0000000..d5cddc7
--- /dev/null
+++ b/tools/aconfig/aconfig_storage_read_api/tests/java/TestDataUtils.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.aconfig.storage.test;
+
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+
+public final class TestDataUtils {
+ public static final String TEST_PACKAGE_MAP_PATH = "mockup.package.map";
+ public static final String TEST_FLAG_MAP_PATH = "mockup.flag.map";
+ public static final String TEST_FLAG_VAL_PATH = "mockup.val";
+ public static final String TEST_FLAG_INFO_PATH = "mockup.info";
+
+ public static final String TESTDATA_PATH =
+ "/data/local/tmp/aconfig_storage_package/testdata/";
+
+ public static ByteBuffer getTestPackageMapByteBuffer() throws Exception {
+ return readFile(TESTDATA_PATH + TEST_PACKAGE_MAP_PATH);
+ }
+
+ public static ByteBuffer getTestFlagMapByteBuffer() throws Exception {
+ return readFile(TESTDATA_PATH + TEST_FLAG_MAP_PATH);
+ }
+
+ public static ByteBuffer getTestFlagValByteBuffer() throws Exception {
+ return readFile(TESTDATA_PATH + TEST_FLAG_VAL_PATH);
+ }
+
+ public static ByteBuffer getTestFlagInfoByteBuffer() throws Exception {
+ return readFile(TESTDATA_PATH + TEST_FLAG_INFO_PATH);
+ }
+
+ private static ByteBuffer readFile(String fileName) throws Exception {
+ InputStream input = new FileInputStream(fileName);
+ return ByteBuffer.wrap(input.readAllBytes());
+ }
+}
diff --git a/tools/aconfig/aconfig_storage_read_api/tests/java/jarjar.txt b/tools/aconfig/aconfig_storage_read_api/tests/java/jarjar.txt
new file mode 100644
index 0000000..24952ec
--- /dev/null
+++ b/tools/aconfig/aconfig_storage_read_api/tests/java/jarjar.txt
@@ -0,0 +1,17 @@
+rule android.aconfig.storage.AconfigStorageException android.aconfig.storage.test.AconfigStorageException
+rule android.aconfig.storage.FlagTable android.aconfig.storage.test.FlagTable
+rule android.aconfig.storage.PackageTable android.aconfig.storage.test.PackageTable
+rule android.aconfig.storage.ByteBufferReader android.aconfig.storage.test.ByteBufferReader
+rule android.aconfig.storage.FlagType android.aconfig.storage.test.FlagType
+rule android.aconfig.storage.SipHasher13 android.aconfig.storage.test.SipHasher13
+rule android.aconfig.storage.FileType android.aconfig.storage.test.FileType
+rule android.aconfig.storage.FlagValueList android.aconfig.storage.test.FlagValueList
+rule android.aconfig.storage.TableUtils android.aconfig.storage.test.TableUtils
+rule android.aconfig.storage.AconfigPackageImpl android.aconfig.storage.test.AconfigPackageImpl
+rule android.aconfig.storage.StorageFileProvider android.aconfig.storage.test.StorageFileProvider
+
+
+rule android.aconfig.storage.FlagTable$* android.aconfig.storage.test.FlagTable$@1
+rule android.aconfig.storage.PackageTable$* android.aconfig.storage.test.PackageTable$@1
+rule android.aconfig.storage.FlagValueList$* android.aconfig.storage.test.FlagValueList@1
+rule android.aconfig.storage.SipHasher13$* android.aconfig.storage.test.SipHasher13@1
diff --git a/tools/aconfig/aflags/src/load_protos.rs b/tools/aconfig/aflags/src/load_protos.rs
index f201d8f..c5ac8ff 100644
--- a/tools/aconfig/aflags/src/load_protos.rs
+++ b/tools/aconfig/aflags/src/load_protos.rs
@@ -51,7 +51,10 @@
let paths = aconfig_device_paths::parsed_flags_proto_paths()?;
for path in paths {
- let bytes = fs::read(path.clone())?;
+ let Ok(bytes) = fs::read(&path) else {
+ eprintln!("warning: failed to read {:?}", path);
+ continue;
+ };
let parsed_flags: ProtoParsedFlags = protobuf::Message::parse_from_bytes(&bytes)?;
for flag in parsed_flags.parsed_flag {
// TODO(b/334954748): enforce one-container-per-flag invariant.
diff --git a/tools/edit_monitor/Android.bp b/tools/edit_monitor/Android.bp
index e613563..b8ac5bf 100644
--- a/tools/edit_monitor/Android.bp
+++ b/tools/edit_monitor/Android.bp
@@ -36,6 +36,7 @@
srcs: [
"daemon_manager.py",
"edit_monitor.py",
+ "utils.py",
],
libs: [
"asuite_cc_client",
@@ -75,6 +76,21 @@
}
python_test_host {
+ name: "edit_monitor_utils_test",
+ main: "utils_test.py",
+ pkg_path: "edit_monitor",
+ srcs: [
+ "utils_test.py",
+ ],
+ libs: [
+ "edit_monitor_lib",
+ ],
+ test_options: {
+ unit_test: true,
+ },
+}
+
+python_test_host {
name: "edit_monitor_integration_test",
main: "edit_monitor_integration_test.py",
pkg_path: "testdata",
diff --git a/tools/edit_monitor/daemon_manager.py b/tools/edit_monitor/daemon_manager.py
index c0a57ab..9a0abb6 100644
--- a/tools/edit_monitor/daemon_manager.py
+++ b/tools/edit_monitor/daemon_manager.py
@@ -28,6 +28,7 @@
from atest.metrics import clearcut_client
from atest.proto import clientanalytics_pb2
+from edit_monitor import utils
from proto import edit_event_pb2
DEFAULT_PROCESS_TERMINATION_TIMEOUT_SECONDS = 5
@@ -79,6 +80,15 @@
def start(self):
"""Writes the pidfile and starts the daemon proces."""
+ if not utils.is_feature_enabled(
+ "edit_monitor",
+ self.user_name,
+ "ENABLE_EDIT_MONITOR",
+ "EDIT_MONITOR_ROLLOUT_PERCENTAGE",
+ ):
+ logging.warning("Edit monitor is disabled, exiting...")
+ return
+
if self.block_sign.exists():
logging.warning("Block sign found, exiting...")
return
diff --git a/tools/edit_monitor/daemon_manager_test.py b/tools/edit_monitor/daemon_manager_test.py
index e132000..407d94e 100644
--- a/tools/edit_monitor/daemon_manager_test.py
+++ b/tools/edit_monitor/daemon_manager_test.py
@@ -81,6 +81,8 @@
# Sets the tempdir under the working dir so any temp files created during
# tests will be cleaned.
tempfile.tempdir = self.working_dir.name
+ self.patch = mock.patch.dict(os.environ, {'ENABLE_EDIT_MONITOR': 'true'})
+ self.patch.start()
def tearDown(self):
# Cleans up any child processes left by the tests.
@@ -88,6 +90,7 @@
self.working_dir.cleanup()
# Restores tempdir.
tempfile.tempdir = self.original_tempdir
+ self.patch.stop()
super().tearDown()
def test_start_success_with_no_existing_instance(self):
@@ -129,6 +132,15 @@
dm = daemon_manager.DaemonManager(TEST_BINARY_FILE)
dm.start()
+
+ # Verify no daemon process is started.
+ self.assertIsNone(dm.daemon_process)
+
+ @mock.patch.dict(os.environ, {'ENABLE_EDIT_MONITOR': 'false'}, clear=True)
+ def test_start_return_directly_if_disabled(self):
+ dm = daemon_manager.DaemonManager(TEST_BINARY_FILE)
+ dm.start()
+
# Verify no daemon process is started.
self.assertIsNone(dm.daemon_process)
@@ -137,6 +149,7 @@
'/google/cog/cloud/user/workspace/edit_monitor'
)
dm.start()
+
# Verify no daemon process is started.
self.assertIsNone(dm.daemon_process)
diff --git a/tools/edit_monitor/edit_monitor_integration_test.py b/tools/edit_monitor/edit_monitor_integration_test.py
index d7dc7f1..5f3d7e5 100644
--- a/tools/edit_monitor/edit_monitor_integration_test.py
+++ b/tools/edit_monitor/edit_monitor_integration_test.py
@@ -15,7 +15,6 @@
"""Integration tests for Edit Monitor."""
import glob
-from importlib import resources
import logging
import os
import pathlib
@@ -27,6 +26,9 @@
import time
import unittest
+from importlib import resources
+from unittest import mock
+
class EditMonitorIntegrationTest(unittest.TestCase):
@@ -46,8 +48,11 @@
)
self.root_monitoring_path.mkdir()
self.edit_monitor_binary_path = self._import_executable("edit_monitor")
+ self.patch = mock.patch.dict(os.environ, {'ENABLE_EDIT_MONITOR': 'true'})
+ self.patch.start()
def tearDown(self):
+ self.patch.stop()
self.working_dir.cleanup()
super().tearDown()
diff --git a/tools/edit_monitor/utils.py b/tools/edit_monitor/utils.py
new file mode 100644
index 0000000..1a3275c
--- /dev/null
+++ b/tools/edit_monitor/utils.py
@@ -0,0 +1,71 @@
+# Copyright 2024, The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import hashlib
+import logging
+import os
+
+
+def is_feature_enabled(
+ feature_name: str,
+ user_name: str,
+ enable_flag: str = None,
+ rollout_flag: str = None,
+) -> bool:
+ """Determine whether the given feature is enabled.
+
+ Whether a given feature is enabled or not depends on two flags: 1) the
+ enable_flag that explicitly enable/disable the feature and 2) the rollout_flag
+ that controls the rollout percentage.
+
+ Args:
+ feature_name: name of the feature.
+ user_name: system user name.
+ enable_flag: name of the env var that enables/disables the feature
+ explicitly.
+ rollout_flg: name of the env var that controls the rollout percentage, the
+ value stored in the env var should be an int between 0 and 100 string
+ """
+ if enable_flag:
+ if os.environ.get(enable_flag, "") == "false":
+ logging.info("feature: %s is disabled", feature_name)
+ return False
+
+ if os.environ.get(enable_flag, "") == "true":
+ logging.info("feature: %s is enabled", feature_name)
+ return True
+
+ if not rollout_flag:
+ return True
+
+ hash_object = hashlib.sha256()
+ hash_object.update((user_name + feature_name).encode("utf-8"))
+ hash_number = int(hash_object.hexdigest(), 16) % 100
+
+ roll_out_percentage = os.environ.get(rollout_flag, "0")
+ try:
+ percentage = int(roll_out_percentage)
+ if percentage < 0 or percentage > 100:
+ logging.warning(
+ "Rollout percentage: %s out of range, disable the feature.",
+ roll_out_percentage,
+ )
+ return False
+ return hash_number < percentage
+ except ValueError:
+ logging.warning(
+ "Invalid rollout percentage: %s, disable the feature.",
+ roll_out_percentage,
+ )
+ return False
diff --git a/tools/edit_monitor/utils_test.py b/tools/edit_monitor/utils_test.py
new file mode 100644
index 0000000..7d7e4b2
--- /dev/null
+++ b/tools/edit_monitor/utils_test.py
@@ -0,0 +1,108 @@
+# Copyright 2024, The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Unittests for edit monitor utils."""
+import os
+import unittest
+from unittest import mock
+
+from edit_monitor import utils
+
+TEST_USER = 'test_user'
+TEST_FEATURE = 'test_feature'
+ENABLE_TEST_FEATURE_FLAG = 'ENABLE_TEST_FEATURE'
+ROLLOUT_TEST_FEATURE_FLAG = 'ROLLOUT_TEST_FEATURE'
+
+
+class EnableFeatureTest(unittest.TestCase):
+
+ def test_feature_enabled_without_flag(self):
+ self.assertTrue(utils.is_feature_enabled(TEST_FEATURE, TEST_USER))
+
+ @mock.patch.dict(os.environ, {ENABLE_TEST_FEATURE_FLAG: 'false'}, clear=True)
+ def test_feature_disabled_with_flag(self):
+ self.assertFalse(
+ utils.is_feature_enabled(
+ TEST_FEATURE, TEST_USER, ENABLE_TEST_FEATURE_FLAG
+ )
+ )
+
+ @mock.patch.dict(os.environ, {ENABLE_TEST_FEATURE_FLAG: 'true'}, clear=True)
+ def test_feature_enabled_with_flag(self):
+ self.assertTrue(
+ utils.is_feature_enabled(
+ TEST_FEATURE, TEST_USER, ENABLE_TEST_FEATURE_FLAG
+ )
+ )
+
+ @mock.patch.dict(
+ os.environ, {ROLLOUT_TEST_FEATURE_FLAG: 'invalid'}, clear=True
+ )
+ def test_feature_disabled_with_invalid_rollout_percentage(self):
+ self.assertFalse(
+ utils.is_feature_enabled(
+ TEST_FEATURE,
+ TEST_USER,
+ ENABLE_TEST_FEATURE_FLAG,
+ ROLLOUT_TEST_FEATURE_FLAG,
+ )
+ )
+
+ @mock.patch.dict(os.environ, {ROLLOUT_TEST_FEATURE_FLAG: '101'}, clear=True)
+ def test_feature_disabled_with_rollout_percentage_too_high(self):
+ self.assertFalse(
+ utils.is_feature_enabled(
+ TEST_FEATURE,
+ TEST_USER,
+ ENABLE_TEST_FEATURE_FLAG,
+ ROLLOUT_TEST_FEATURE_FLAG,
+ )
+ )
+
+ @mock.patch.dict(os.environ, {ROLLOUT_TEST_FEATURE_FLAG: '-1'}, clear=True)
+ def test_feature_disabled_with_rollout_percentage_too_low(self):
+ self.assertFalse(
+ utils.is_feature_enabled(
+ TEST_FEATURE,
+ TEST_USER,
+ ENABLE_TEST_FEATURE_FLAG,
+ ROLLOUT_TEST_FEATURE_FLAG,
+ )
+ )
+
+ @mock.patch.dict(os.environ, {ROLLOUT_TEST_FEATURE_FLAG: '90'}, clear=True)
+ def test_feature_enabled_with_rollout_percentage(self):
+ self.assertTrue(
+ utils.is_feature_enabled(
+ TEST_FEATURE,
+ TEST_USER,
+ ENABLE_TEST_FEATURE_FLAG,
+ ROLLOUT_TEST_FEATURE_FLAG,
+ )
+ )
+
+ @mock.patch.dict(os.environ, {ROLLOUT_TEST_FEATURE_FLAG: '10'}, clear=True)
+ def test_feature_disabled_with_rollout_percentage(self):
+ self.assertFalse(
+ utils.is_feature_enabled(
+ TEST_FEATURE,
+ TEST_USER,
+ ENABLE_TEST_FEATURE_FLAG,
+ ROLLOUT_TEST_FEATURE_FLAG,
+ )
+ )
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tools/fs_config/Android.bp b/tools/fs_config/Android.bp
index 6aa5289..a5b6fd0 100644
--- a/tools/fs_config/Android.bp
+++ b/tools/fs_config/Android.bp
@@ -277,6 +277,7 @@
out: ["out"],
}
+// system
genrule {
name: "fs_config_dirs_system_gen",
defaults: ["fs_config_defaults"],
@@ -307,6 +308,7 @@
src: ":fs_config_files_system_gen",
}
+// system_ext
genrule {
name: "fs_config_dirs_system_ext_gen",
defaults: ["fs_config_defaults"],
@@ -337,6 +339,7 @@
system_ext_specific: true,
}
+// product
genrule {
name: "fs_config_dirs_product_gen",
defaults: ["fs_config_defaults"],
@@ -367,6 +370,7 @@
product_specific: true,
}
+// vendor
genrule {
name: "fs_config_dirs_vendor_gen",
defaults: ["fs_config_defaults"],
@@ -397,6 +401,7 @@
vendor: true,
}
+// odm
genrule {
name: "fs_config_dirs_odm_gen",
defaults: ["fs_config_defaults"],
@@ -427,4 +432,214 @@
device_specific: true,
}
-// TODO(jiyong): add fs_config for oem, system_dlkm, vendor_dlkm, odm_dlkm partitions
+// system_dlkm
+genrule {
+ name: "fs_config_dirs_system_dlkm_gen",
+ defaults: ["fs_config_defaults"],
+ cmd: fs_config_cmd_dirs +
+ "--partition system_dlkm " +
+ "$(locations :target_fs_config_gen)",
+}
+
+prebuilt_etc {
+ name: "fs_config_dirs_system_dlkm",
+ filename: "fs_config_dirs",
+ src: ":fs_config_dirs_system_dlkm_gen",
+ system_dlkm_specific: true,
+}
+
+genrule {
+ name: "fs_config_files_system_dlkm_gen",
+ defaults: ["fs_config_defaults"],
+ cmd: fs_config_cmd_files +
+ "--partition system_dlkm " +
+ "$(locations :target_fs_config_gen)",
+}
+
+prebuilt_etc {
+ name: "fs_config_files_system_dlkm",
+ filename: "fs_config_files",
+ src: ":fs_config_files_system_dlkm_gen",
+ system_dlkm_specific: true,
+}
+
+// vendor_dlkm
+genrule {
+ name: "fs_config_dirs_vendor_dlkm_gen",
+ defaults: ["fs_config_defaults"],
+ cmd: fs_config_cmd_dirs +
+ "--partition vendor_dlkm " +
+ "$(locations :target_fs_config_gen)",
+}
+
+prebuilt_etc {
+ name: "fs_config_dirs_vendor_dlkm",
+ filename: "fs_config_dirs",
+ src: ":fs_config_dirs_vendor_dlkm_gen",
+ vendor_dlkm_specific: true,
+}
+
+genrule {
+ name: "fs_config_files_vendor_dlkm_gen",
+ defaults: ["fs_config_defaults"],
+ cmd: fs_config_cmd_files +
+ "--partition vendor_dlkm " +
+ "$(locations :target_fs_config_gen)",
+}
+
+prebuilt_etc {
+ name: "fs_config_files_vendor_dlkm",
+ filename: "fs_config_files",
+ src: ":fs_config_files_vendor_dlkm_gen",
+ vendor_dlkm_specific: true,
+}
+
+// odm_dlkm
+genrule {
+ name: "fs_config_dirs_odm_dlkm_gen",
+ defaults: ["fs_config_defaults"],
+ cmd: fs_config_cmd_dirs +
+ "--partition odm_dlkm " +
+ "$(locations :target_fs_config_gen)",
+}
+
+prebuilt_etc {
+ name: "fs_config_dirs_odm_dlkm",
+ filename: "fs_config_dirs",
+ src: ":fs_config_dirs_odm_dlkm_gen",
+ odm_dlkm_specific: true,
+}
+
+genrule {
+ name: "fs_config_files_odm_dlkm_gen",
+ defaults: ["fs_config_defaults"],
+ cmd: fs_config_cmd_files +
+ "--partition odm_dlkm " +
+ "$(locations :target_fs_config_gen)",
+}
+
+prebuilt_etc {
+ name: "fs_config_files_odm_dlkm",
+ filename: "fs_config_files",
+ src: ":fs_config_files_odm_dlkm_gen",
+ odm_dlkm_specific: true,
+}
+
+// oem
+genrule {
+ name: "fs_config_dirs_oem_gen",
+ defaults: ["fs_config_defaults"],
+ cmd: fs_config_cmd_dirs +
+ "--partition oem " +
+ "$(locations :target_fs_config_gen)",
+}
+
+prebuilt_etc {
+ name: "fs_config_dirs_oem",
+ filename: "fs_config_dirs",
+ src: ":fs_config_dirs_oem_gen",
+ oem_specific: true,
+}
+
+genrule {
+ name: "fs_config_files_oem_gen",
+ defaults: ["fs_config_defaults"],
+ cmd: fs_config_cmd_files +
+ "--partition oem " +
+ "$(locations :target_fs_config_gen)",
+}
+
+prebuilt_etc {
+ name: "fs_config_files_oem",
+ filename: "fs_config_files",
+ src: ":fs_config_files_oem_gen",
+ oem_specific: true,
+}
+
+// Generate the <p>/etc/fs_config_dirs binary files for each partition.
+// Add fs_config_dirs to PRODUCT_PACKAGES in the device make file to enable.
+phony {
+ name: "fs_config_dirs",
+ required: [
+ "fs_config_dirs_system",
+ "fs_config_dirs_system_ext",
+ "fs_config_dirs_product",
+ "fs_config_dirs_nonsystem",
+ ],
+}
+
+// Generate the <p>/etc/fs_config_files binary files for each partition.
+// Add fs_config_files to PRODUCT_PACKAGES in the device make file to enable.
+phony {
+ name: "fs_config_files",
+ required: [
+ "fs_config_files_system",
+ "fs_config_files_system_ext",
+ "fs_config_files_product",
+ "fs_config_files_nonsystem",
+ ],
+}
+
+// Generate the <p>/etc/fs_config_dirs binary files for all enabled partitions
+// excluding /system, /system_ext and /product. Add fs_config_dirs_nonsystem to
+// PRODUCT_PACKAGES in the device make file to enable.
+phony {
+ name: "fs_config_dirs_nonsystem",
+ required: [] +
+ select(soong_config_variable("fs_config", "vendor"), {
+ true: ["fs_config_dirs_vendor"],
+ default: [],
+ }) +
+ select(soong_config_variable("fs_config", "oem"), {
+ true: ["fs_config_dirs_oem"],
+ default: [],
+ }) +
+ select(soong_config_variable("fs_config", "odm"), {
+ true: ["fs_config_dirs_odm"],
+ default: [],
+ }) +
+ select(soong_config_variable("fs_config", "vendor_dlkm"), {
+ true: ["fs_config_dirs_vendor_dlkm"],
+ default: [],
+ }) +
+ select(soong_config_variable("fs_config", "odm_dlkm"), {
+ true: ["fs_config_dirs_odm_dlkm"],
+ default: [],
+ }) +
+ select(soong_config_variable("fs_config", "system_dlkm"), {
+ true: ["fs_config_dirs_system_dlkm"],
+ default: [],
+ }),
+}
+
+// Generate the <p>/etc/fs_config_files binary files for all enabled partitions
+// excluding /system, /system_ext and /product. Add fs_config_files_nonsystem to
+// PRODUCT_PACKAGES in the device make file to enable.
+phony {
+ name: "fs_config_files_nonsystem",
+ required: [] +
+ select(soong_config_variable("fs_config", "vendor"), {
+ true: ["fs_config_files_vendor"],
+ default: [],
+ }) +
+ select(soong_config_variable("fs_config", "oem"), {
+ true: ["fs_config_files_oem"],
+ default: [],
+ }) +
+ select(soong_config_variable("fs_config", "odm"), {
+ true: ["fs_config_files_odm"],
+ default: [],
+ }) +
+ select(soong_config_variable("fs_config", "vendor_dlkm"), {
+ true: ["fs_config_files_vendor_dlkm"],
+ default: [],
+ }) +
+ select(soong_config_variable("fs_config", "odm_dlkm"), {
+ true: ["fs_config_files_odm_dlkm"],
+ default: [],
+ }) +
+ select(soong_config_variable("fs_config", "system_dlkm"), {
+ true: ["fs_config_files_system_dlkm"],
+ default: [],
+ }),
+}
diff --git a/tools/fs_config/Android.mk b/tools/fs_config/Android.mk
deleted file mode 100644
index e4c3626..0000000
--- a/tools/fs_config/Android.mk
+++ /dev/null
@@ -1,328 +0,0 @@
-# Copyright (C) 2008 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-
-# One can override the default android_filesystem_config.h file by using TARGET_FS_CONFIG_GEN.
-# Set TARGET_FS_CONFIG_GEN to contain a list of intermediate format files
-# for generating the android_filesystem_config.h file.
-#
-# More information can be found in the README
-
-ifneq ($(wildcard $(TARGET_DEVICE_DIR)/android_filesystem_config.h),)
-$(error Using $(TARGET_DEVICE_DIR)/android_filesystem_config.h is deprecated, please use TARGET_FS_CONFIG_GEN instead)
-endif
-
-android_filesystem_config := system/core/libcutils/include/private/android_filesystem_config.h
-capability_header := bionic/libc/kernel/uapi/linux/capability.h
-
-# List of supported vendor, oem, odm, vendor_dlkm, odm_dlkm, and system_dlkm Partitions
-fs_config_generate_extra_partition_list := $(strip \
- $(if $(BOARD_USES_VENDORIMAGE)$(BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE),vendor) \
- $(if $(BOARD_USES_OEMIMAGE)$(BOARD_OEMIMAGE_FILE_SYSTEM_TYPE),oem) \
- $(if $(BOARD_USES_ODMIMAGE)$(BOARD_ODMIMAGE_FILE_SYSTEM_TYPE),odm) \
- $(if $(BOARD_USES_VENDOR_DLKMIMAGE)$(BOARD_VENDOR_DLKMIMAGE_FILE_SYSTEM_TYPE),vendor_dlkm) \
- $(if $(BOARD_USES_ODM_DLKMIMAGE)$(BOARD_ODM_DLKMIMAGE_FILE_SYSTEM_TYPE),odm_dlkm) \
- $(if $(BOARD_USES_SYSTEM_DLKMIMAGE)$(BOARD_SYSTEM_DLKMIMAGE_FILE_SYSTEM_TYPE),system_dlkm) \
-)
-
-##################################
-# Generate the <p>/etc/fs_config_dirs binary files for each partition.
-# Add fs_config_dirs to PRODUCT_PACKAGES in the device make file to enable.
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := fs_config_dirs
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE := build/soong/licenses/LICENSE
-LOCAL_REQUIRED_MODULES := \
- fs_config_dirs_system \
- fs_config_dirs_system_ext \
- fs_config_dirs_product \
- fs_config_dirs_nonsystem
-include $(BUILD_PHONY_PACKAGE)
-
-##################################
-# Generate the <p>/etc/fs_config_files binary files for each partition.
-# Add fs_config_files to PRODUCT_PACKAGES in the device make file to enable.
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := fs_config_files
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE := build/soong/licenses/LICENSE
-LOCAL_REQUIRED_MODULES := \
- fs_config_files_system \
- fs_config_files_system_ext \
- fs_config_files_product \
- fs_config_files_nonsystem
-include $(BUILD_PHONY_PACKAGE)
-
-##################################
-# Generate the <p>/etc/fs_config_dirs binary files for all enabled partitions
-# excluding /system, /system_ext and /product. Add fs_config_dirs_nonsystem to
-# PRODUCT_PACKAGES in the device make file to enable.
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := fs_config_dirs_nonsystem
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE := build/soong/licenses/LICENSE
-LOCAL_REQUIRED_MODULES := $(foreach t,$(fs_config_generate_extra_partition_list),fs_config_dirs_$(t))
-include $(BUILD_PHONY_PACKAGE)
-
-##################################
-# Generate the <p>/etc/fs_config_files binary files for all enabled partitions
-# excluding /system, /system_ext and /product. Add fs_config_files_nonsystem to
-# PRODUCT_PACKAGES in the device make file to enable.
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := fs_config_files_nonsystem
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE := build/soong/licenses/LICENSE
-LOCAL_REQUIRED_MODULES := $(foreach t,$(fs_config_generate_extra_partition_list),fs_config_files_$(t))
-include $(BUILD_PHONY_PACKAGE)
-
-ifneq ($(filter oem,$(fs_config_generate_extra_partition_list)),)
-##################################
-# Generate the oem/etc/fs_config_dirs binary file for the target
-# Add fs_config_dirs or fs_config_dirs_nonsystem to PRODUCT_PACKAGES
-# in the device make file to enable
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := fs_config_dirs_oem
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE := build/soong/licenses/LICENSE
-LOCAL_MODULE_CLASS := ETC
-LOCAL_INSTALLED_MODULE_STEM := fs_config_dirs
-LOCAL_MODULE_PATH := $(TARGET_OUT_OEM)/etc
-include $(BUILD_SYSTEM)/base_rules.mk
-$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_FS_HDR := $(android_filesystem_config)
-$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_CAP_HDR := $(capability_header)
-$(LOCAL_BUILT_MODULE): PRIVATE_TARGET_FS_CONFIG_GEN := $(TARGET_FS_CONFIG_GEN)
-$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/fs_config_generator.py $(TARGET_FS_CONFIG_GEN) $(android_filesystem_config) $(capability_header)
- @mkdir -p $(dir $@)
- $< fsconfig \
- --aid-header $(PRIVATE_ANDROID_FS_HDR) \
- --capability-header $(PRIVATE_ANDROID_CAP_HDR) \
- --partition oem \
- --dirs \
- --out_file $@ \
- $(or $(PRIVATE_TARGET_FS_CONFIG_GEN),/dev/null)
-
-##################################
-# Generate the oem/etc/fs_config_files binary file for the target
-# Add fs_config_files or fs_config_files_nonsystem to PRODUCT_PACKAGES
-# in the device make file to enable
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := fs_config_files_oem
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE := build/soong/licenses/LICENSE
-LOCAL_MODULE_CLASS := ETC
-LOCAL_INSTALLED_MODULE_STEM := fs_config_files
-LOCAL_MODULE_PATH := $(TARGET_OUT_OEM)/etc
-include $(BUILD_SYSTEM)/base_rules.mk
-$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_FS_HDR := $(android_filesystem_config)
-$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_CAP_HDR := $(capability_header)
-$(LOCAL_BUILT_MODULE): PRIVATE_TARGET_FS_CONFIG_GEN := $(TARGET_FS_CONFIG_GEN)
-$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/fs_config_generator.py $(TARGET_FS_CONFIG_GEN) $(android_filesystem_config) $(capability_header)
- @mkdir -p $(dir $@)
- $< fsconfig \
- --aid-header $(PRIVATE_ANDROID_FS_HDR) \
- --capability-header $(PRIVATE_ANDROID_CAP_HDR) \
- --partition oem \
- --files \
- --out_file $@ \
- $(or $(PRIVATE_TARGET_FS_CONFIG_GEN),/dev/null)
-
-endif
-
-ifneq ($(filter vendor_dlkm,$(fs_config_generate_extra_partition_list)),)
-##################################
-# Generate the vendor_dlkm/etc/fs_config_dirs binary file for the target
-# Add fs_config_dirs or fs_config_dirs_nonsystem to PRODUCT_PACKAGES in
-# the device make file to enable
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := fs_config_dirs_vendor_dlkm
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE := build/soong/licenses/LICENSE
-LOCAL_MODULE_CLASS := ETC
-LOCAL_INSTALLED_MODULE_STEM := fs_config_dirs
-LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_DLKM)/etc
-include $(BUILD_SYSTEM)/base_rules.mk
-$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_FS_HDR := $(android_filesystem_config)
-$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_CAP_HDR := $(capability_header)
-$(LOCAL_BUILT_MODULE): PRIVATE_TARGET_FS_CONFIG_GEN := $(TARGET_FS_CONFIG_GEN)
-$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/fs_config_generator.py $(TARGET_FS_CONFIG_GEN) $(android_filesystem_config) $(capability_header)
- @mkdir -p $(dir $@)
- $< fsconfig \
- --aid-header $(PRIVATE_ANDROID_FS_HDR) \
- --capability-header $(PRIVATE_ANDROID_CAP_HDR) \
- --partition vendor_dlkm \
- --dirs \
- --out_file $@ \
- $(or $(PRIVATE_TARGET_FS_CONFIG_GEN),/dev/null)
-
-##################################
-# Generate the vendor_dlkm/etc/fs_config_files binary file for the target
-# Add fs_config_files or fs_config_files_nonsystem to PRODUCT_PACKAGES in
-# the device make file to enable
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := fs_config_files_vendor_dlkm
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE := build/soong/licenses/LICENSE
-LOCAL_MODULE_CLASS := ETC
-LOCAL_INSTALLED_MODULE_STEM := fs_config_files
-LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_DLKM)/etc
-include $(BUILD_SYSTEM)/base_rules.mk
-$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_FS_HDR := $(android_filesystem_config)
-$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_CAP_HDR := $(capability_header)
-$(LOCAL_BUILT_MODULE): PRIVATE_TARGET_FS_CONFIG_GEN := $(TARGET_FS_CONFIG_GEN)
-$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/fs_config_generator.py $(TARGET_FS_CONFIG_GEN) $(android_filesystem_config) $(capability_header)
- @mkdir -p $(dir $@)
- $< fsconfig \
- --aid-header $(PRIVATE_ANDROID_FS_HDR) \
- --capability-header $(PRIVATE_ANDROID_CAP_HDR) \
- --partition vendor_dlkm \
- --files \
- --out_file $@ \
- $(or $(PRIVATE_TARGET_FS_CONFIG_GEN),/dev/null)
-
-endif
-
-ifneq ($(filter odm_dlkm,$(fs_config_generate_extra_partition_list)),)
-##################################
-# Generate the odm_dlkm/etc/fs_config_dirs binary file for the target
-# Add fs_config_dirs or fs_config_dirs_nonsystem to PRODUCT_PACKAGES
-# in the device make file to enable
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := fs_config_dirs_odm_dlkm
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE := build/soong/licenses/LICENSE
-LOCAL_MODULE_CLASS := ETC
-LOCAL_INSTALLED_MODULE_STEM := fs_config_dirs
-LOCAL_MODULE_PATH := $(TARGET_OUT_ODM_DLKM)/etc
-include $(BUILD_SYSTEM)/base_rules.mk
-$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_FS_HDR := $(android_filesystem_config)
-$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_CAP_HDR := $(capability_header)
-$(LOCAL_BUILT_MODULE): PRIVATE_TARGET_FS_CONFIG_GEN := $(TARGET_FS_CONFIG_GEN)
-$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/fs_config_generator.py $(TARGET_FS_CONFIG_GEN) $(android_filesystem_config) $(capability_header)
- @mkdir -p $(dir $@)
- $< fsconfig \
- --aid-header $(PRIVATE_ANDROID_FS_HDR) \
- --capability-header $(PRIVATE_ANDROID_CAP_HDR) \
- --partition odm_dlkm \
- --dirs \
- --out_file $@ \
- $(or $(PRIVATE_TARGET_FS_CONFIG_GEN),/dev/null)
-
-##################################
-# Generate the odm_dlkm/etc/fs_config_files binary file for the target
-# Add fs_config_files or fs_config_files_nonsystem to PRODUCT_PACKAGES
-# in the device make file to enable
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := fs_config_files_odm_dlkm
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE := build/soong/licenses/LICENSE
-LOCAL_MODULE_CLASS := ETC
-LOCAL_INSTALLED_MODULE_STEM := fs_config_files
-LOCAL_MODULE_PATH := $(TARGET_OUT_ODM_DLKM)/etc
-include $(BUILD_SYSTEM)/base_rules.mk
-$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_FS_HDR := $(android_filesystem_config)
-$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_CAP_HDR := $(capability_header)
-$(LOCAL_BUILT_MODULE): PRIVATE_TARGET_FS_CONFIG_GEN := $(TARGET_FS_CONFIG_GEN)
-$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/fs_config_generator.py $(TARGET_FS_CONFIG_GEN) $(android_filesystem_config) $(capability_header)
- @mkdir -p $(dir $@)
- $< fsconfig \
- --aid-header $(PRIVATE_ANDROID_FS_HDR) \
- --capability-header $(PRIVATE_ANDROID_CAP_HDR) \
- --partition odm_dlkm \
- --files \
- --out_file $@ \
- $(or $(PRIVATE_TARGET_FS_CONFIG_GEN),/dev/null)
-
-endif
-
-ifneq ($(filter system_dlkm,$(fs_config_generate_extra_partition_list)),)
-##################################
-# Generate the system_dlkm/etc/fs_config_dirs binary file for the target
-# Add fs_config_dirs or fs_config_dirs_nonsystem to PRODUCT_PACKAGES
-# in the device make file to enable
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := fs_config_dirs_system_dlkm
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE := build/soong/licenses/LICENSE
-LOCAL_MODULE_CLASS := ETC
-LOCAL_INSTALLED_MODULE_STEM := fs_config_dirs
-LOCAL_MODULE_PATH := $(TARGET_OUT_SYSTEM_DLKM)/etc
-include $(BUILD_SYSTEM)/base_rules.mk
-$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_FS_HDR := $(android_filesystem_config)
-$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_CAP_HDR := $(capability_header)
-$(LOCAL_BUILT_MODULE): PRIVATE_TARGET_FS_CONFIG_GEN := $(TARGET_FS_CONFIG_GEN)
-$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/fs_config_generator.py $(TARGET_FS_CONFIG_GEN) $(android_filesystem_config) $(capability_header)
- @mkdir -p $(dir $@)
- $< fsconfig \
- --aid-header $(PRIVATE_ANDROID_FS_HDR) \
- --capability-header $(PRIVATE_ANDROID_CAP_HDR) \
- --partition system_dlkm \
- --dirs \
- --out_file $@ \
- $(or $(PRIVATE_TARGET_FS_CONFIG_GEN),/dev/null)
-
-##################################
-# Generate the system_dlkm/etc/fs_config_files binary file for the target
-# Add fs_config_files or fs_config_files_nonsystem to PRODUCT_PACKAGES
-# in the device make file to enable
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := fs_config_files_system_dlkm
-LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
-LOCAL_LICENSE_CONDITIONS := notice
-LOCAL_NOTICE_FILE := build/soong/licenses/LICENSE
-LOCAL_MODULE_CLASS := ETC
-LOCAL_INSTALLED_MODULE_STEM := fs_config_files
-LOCAL_MODULE_PATH := $(TARGET_OUT_SYSTEM_DLKM)/etc
-include $(BUILD_SYSTEM)/base_rules.mk
-$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_FS_HDR := $(android_filesystem_config)
-$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_CAP_HDR := $(capability_header)
-$(LOCAL_BUILT_MODULE): PRIVATE_TARGET_FS_CONFIG_GEN := $(TARGET_FS_CONFIG_GEN)
-$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/fs_config_generator.py $(TARGET_FS_CONFIG_GEN) $(android_filesystem_config) $(capability_header)
- @mkdir -p $(dir $@)
- $< fsconfig \
- --aid-header $(PRIVATE_ANDROID_FS_HDR) \
- --capability-header $(PRIVATE_ANDROID_CAP_HDR) \
- --partition system_dlkm \
- --files \
- --out_file $@ \
- $(or $(PRIVATE_TARGET_FS_CONFIG_GEN),/dev/null)
-
-endif
-
-android_filesystem_config :=
-capability_header :=
-fs_config_generate_extra_partition_list :=