Merge "aflags: only permit enable/disable with root access." into main
diff --git a/core/Makefile b/core/Makefile
index f132db3..93f88c0 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -5061,9 +5061,12 @@
check_vintf_all_deps :=
# -----------------------------------------------------------------
-# Activate vendor APEXes for checkvintf
+# Activate APEXes for checkvintf
apex_dirs := \
+ $(TARGET_OUT)/apex/% \
+ $(TARGET_OUT_PRODUCT)/apex/% \
+ $(TARGET_OUT_SYSTEM_EXT)/apex/% \
$(TARGET_OUT_VENDOR)/apex/% \
apex_files := $(sort $(filter $(apex_dirs), $(INTERNAL_ALLIMAGES_FILES)))
@@ -5079,7 +5082,10 @@
@echo $(PRIVATE_APEX_FILES) > /dev/null
@rm -rf $(APEX_OUT)
@mkdir -p $(APEX_OUT)
- $< --vendor_path $(TARGET_OUT_VENDOR) \
+ $< --system_path $(TARGET_OUT) \
+ --system_ext_path $(TARGET_OUT_SYSTEM_EXT) \
+ --product_path $(TARGET_OUT_PRODUCT) \
+ --vendor_path $(TARGET_OUT_VENDOR) \
--apex_path $(APEX_OUT)
apex_files :=
@@ -5087,14 +5093,14 @@
# The build system only writes VINTF metadata to */etc/vintf paths. Legacy paths aren't needed here
# because they are only used for prebuilt images.
-# APEX files in /vendor/apex can have VINTF fragments as well.
+# APEX files in /$partition/apex can have VINTF fragments as well.
check_vintf_common_srcs_patterns := \
$(TARGET_OUT)/etc/vintf/% \
$(TARGET_OUT_VENDOR)/etc/vintf/% \
$(TARGET_OUT_ODM)/etc/vintf/% \
$(TARGET_OUT_PRODUCT)/etc/vintf/% \
$(TARGET_OUT_SYSTEM_EXT)/etc/vintf/% \
- $(TARGET_OUT_VENDOR)/apex/% \
+ $(apex_dirs)
check_vintf_common_srcs := $(sort $(filter $(check_vintf_common_srcs_patterns),$(INTERNAL_ALLIMAGES_FILES)))
check_vintf_common_srcs_patterns :=
@@ -5112,15 +5118,17 @@
# -- Check system and system_ext manifests / matrices including fragments (excluding other framework manifests / matrices, e.g. product);
ifdef BUILDING_SYSTEM_IMAGE
check_vintf_system_deps := $(filter $(TARGET_OUT)/etc/vintf/% \
- $(TARGET_OUT_SYSTEM_EXT)/etc/vintf/%, \
+ $(TARGET_OUT_SYSTEM_EXT)/etc/vintf/% \
+ $(TARGET_OUT)/apex/% \
+ $(TARGET_OUT_SYSTEM_EXT)/apex/%, \
$(check_vintf_common_srcs))
ifneq ($(check_vintf_system_deps),)
check_vintf_has_system := true
check_vintf_system_log := $(intermediates)/check_vintf_system.log
check_vintf_all_deps += $(check_vintf_system_log)
-$(check_vintf_system_log): $(HOST_OUT_EXECUTABLES)/checkvintf $(check_vintf_system_deps)
- @( $< --check-one --dirmap /system:$(TARGET_OUT) > $@ 2>&1 ) || ( cat $@ && exit 1 )
+$(check_vintf_system_log): $(HOST_OUT_EXECUTABLES)/checkvintf $(check_vintf_system_deps) $(APEX_INFO_FILE)
+ @( $< --check-one --dirmap /system:$(TARGET_OUT) --dirmap /apex:$(APEX_OUT) > $@ 2>&1 ) || ( cat $@ && exit 1 )
$(call declare-1p-target,$(check_vintf_system_log))
check_vintf_system_log :=
@@ -5129,10 +5137,11 @@
vintffm_log := $(intermediates)/vintffm.log
endif
check_vintf_all_deps += $(vintffm_log)
-$(vintffm_log): $(HOST_OUT_EXECUTABLES)/vintffm $(check_vintf_system_deps)
+$(vintffm_log): $(HOST_OUT_EXECUTABLES)/vintffm $(check_vintf_system_deps) $(APEX_INFO_FILE)
@( $< --check --dirmap /system:$(TARGET_OUT) \
--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 )
$(call declare-1p-target,$(vintffm_log))
@@ -5922,6 +5931,9 @@
ifeq ($(TARGET_OTA_ALLOW_NON_AB),true)
$(hide) echo "allow_non_ab=true" >> $@
endif
+ifeq ($(BOARD_NON_AB_OTA_DISABLE_COMPRESSION),true)
+ $(hide) echo "board_non_ab_ota_disable_compression=true" >> $@
+endif
ifdef BOARD_PREBUILT_DTBOIMAGE
$(hide) echo "has_dtbo=true" >> $@
ifeq ($(BOARD_AVB_ENABLE),true)
diff --git a/core/android_soong_config_vars.mk b/core/android_soong_config_vars.mk
index 82e8baa..ac586c5 100644
--- a/core/android_soong_config_vars.mk
+++ b/core/android_soong_config_vars.mk
@@ -37,7 +37,12 @@
# Default behavior for the tree wrt building modules or using prebuilts. This
# can always be overridden by setting the environment variable
# MODULE_BUILD_FROM_SOURCE.
-BRANCH_DEFAULT_MODULE_BUILD_FROM_SOURCE := true
+BRANCH_DEFAULT_MODULE_BUILD_FROM_SOURCE := $(RELEASE_DEFAULT_MODULE_BUILD_FROM_SOURCE)
+# TODO(b/301454934): The value from build flag is set to empty when use `False`
+# The condition below can be removed after the issue get sorted.
+ifeq (,$(BRANCH_DEFAULT_MODULE_BUILD_FROM_SOURCE))
+ BRANCH_DEFAULT_MODULE_BUILD_FROM_SOURCE := false
+endif
ifneq ($(SANITIZE_TARGET)$(EMMA_INSTRUMENT_FRAMEWORK),)
# Always use sources when building the framework with Java coverage or
@@ -46,6 +51,18 @@
BRANCH_DEFAULT_MODULE_BUILD_FROM_SOURCE := true
endif
+ifneq ($(CLANG_COVERAGE)$(NATIVE_COVERAGE_PATHS),)
+ # Always use sources when building with clang coverage and native coverage.
+ # It is possible that there are certain situations when building with coverage
+ # would work with prebuilts, e.g. when the coverage is not being applied to
+ # modules for which we provide prebuilts. Unfortunately, determining that
+ # would require embedding knowledge of which coverage paths affect which
+ # modules here. That would duplicate a lot of information, add yet another
+ # location module authors have to update and complicate the logic here.
+ # For nowe we will just always build from sources when doing coverage builds.
+ BRANCH_DEFAULT_MODULE_BUILD_FROM_SOURCE := true
+endif
+
# ART does not provide linux_bionic variants needed for products that
# set HOST_CROSS_OS=linux_bionic.
ifeq (linux_bionic,${HOST_CROSS_OS})
@@ -117,6 +134,7 @@
rkpd \
uwb \
wifi \
+ mediaprovider \
$(foreach m, $(INDIVIDUALLY_TOGGLEABLE_PREBUILT_MODULES),\
$(if $(call soong_config_get,$(m)_module,source_build),,\
@@ -144,8 +162,8 @@
SYSTEMUI_OPTIMIZE_JAVA ?= true
$(call add_soong_config_var,ANDROID,SYSTEMUI_OPTIMIZE_JAVA)
-# Disable Compose in SystemUI by default.
-SYSTEMUI_USE_COMPOSE ?= false
+# Enable Compose in SystemUI by default.
+SYSTEMUI_USE_COMPOSE ?= true
$(call add_soong_config_var,ANDROID,SYSTEMUI_USE_COMPOSE)
ifdef PRODUCT_AVF_ENABLED
diff --git a/core/board_config.mk b/core/board_config.mk
index 77489c6..25e0643 100644
--- a/core/board_config.mk
+++ b/core/board_config.mk
@@ -949,6 +949,11 @@
endif
endif
+# For Non A/B full OTA, disable brotli compression.
+ifeq ($(TARGET_OTA_ALLOW_NON_AB),true)
+ BOARD_NON_AB_OTA_DISABLE_COMPRESSION := true
+endif
+
# Quick check for building generic OTA packages. Currently it only supports A/B OTAs.
ifeq ($(PRODUCT_BUILD_GENERIC_OTA_PACKAGE),true)
ifneq ($(AB_OTA_UPDATER),true)
diff --git a/core/config.mk b/core/config.mk
index dbee0a0..546858a 100644
--- a/core/config.mk
+++ b/core/config.mk
@@ -1273,7 +1273,7 @@
endif
ifeq (true,$(FULL_SYSTEM_OPTIMIZE_JAVA))
-ifeq (,$(SYSTEM_OPTIMIZE_JAVA))
+ifeq (false,$(SYSTEM_OPTIMIZE_JAVA))
$(error SYSTEM_OPTIMIZE_JAVA must be enabled when FULL_SYSTEM_OPTIMIZE_JAVA is enabled)
endif
endif
diff --git a/core/tasks/cts.mk b/core/tasks/cts.mk
index 91cb2c9..b9f0988 100644
--- a/core/tasks/cts.mk
+++ b/core/tasks/cts.mk
@@ -144,30 +144,30 @@
$(call generate-coverage-report-cts,"CTS System API Coverage Report - XML",\
$(PRIVATE_TEST_CASES),xml)
-$(cts-verifier-coverage-report): PRIVATE_TEST_CASES := $(cts_verifier_apk)
+$(cts-verifier-coverage-report): PRIVATE_TEST_CASES := $(foreach c, $(cts_verifier_apk) $(verifier-dir), $(c))
$(cts-verifier-coverage-report): PRIVATE_CTS_API_COVERAGE_EXE := $(cts_api_coverage_exe)
$(cts-verifier-coverage-report): PRIVATE_DEXDEPS_EXE := $(dexdeps_exe)
$(cts-verifier-coverage-report): PRIVATE_API_XML_DESC := $(api_xml_description)
$(cts-verifier-coverage-report): PRIVATE_NAPI_XML_DESC := $(napi_xml_description)
-$(cts-verifier-coverage-report) : $(cts_verifier_apk) $(cts_api_coverage_dependencies) | $(ACP)
+$(cts-verifier-coverage-report) : $(cts_verifier_apk) $(verifier-zip) $(cts_api_coverage_dependencies) | $(ACP)
$(call generate-coverage-report-cts,"CTS Verifier API Coverage Report",\
$(PRIVATE_TEST_CASES),html)
-$(cts-combined-coverage-report): PRIVATE_TEST_CASES := $(foreach c, $(cts_verifier_apk) $(COMPATIBILITY_TESTCASES_OUT_cts), $(c))
+$(cts-combined-coverage-report): PRIVATE_TEST_CASES := $(foreach c, $(cts_verifier_apk) $(COMPATIBILITY_TESTCASES_OUT_cts) $(verifier-dir), $(c))
$(cts-combined-coverage-report): PRIVATE_CTS_API_COVERAGE_EXE := $(cts_api_coverage_exe)
$(cts-combined-coverage-report): PRIVATE_DEXDEPS_EXE := $(dexdeps_exe)
$(cts-combined-coverage-report): PRIVATE_API_XML_DESC := $(api_xml_description)
$(cts-combined-coverage-report): PRIVATE_NAPI_XML_DESC := $(napi_xml_description)
-$(cts-combined-coverage-report) : $(android_cts_zip) $(cts_verifier_apk) $(cts_api_coverage_dependencies) | $(ACP)
+$(cts-combined-coverage-report) : $(android_cts_zip) $(cts_verifier_apk) $(verifier-zip) $(cts_api_coverage_dependencies) | $(ACP)
$(call generate-coverage-report-cts,"CTS Combined API Coverage Report",\
$(PRIVATE_TEST_CASES),html)
-$(cts-combined-xml-coverage-report): PRIVATE_TEST_CASES := $(foreach c, $(cts_verifier_apk) $(COMPATIBILITY_TESTCASES_OUT_cts), $(c))
+$(cts-combined-xml-coverage-report): PRIVATE_TEST_CASES := $(foreach c, $(cts_verifier_apk) $(COMPATIBILITY_TESTCASES_OUT_cts) $(verifier-dir), $(c))
$(cts-combined-xml-coverage-report): PRIVATE_CTS_API_COVERAGE_EXE := $(cts_api_coverage_exe)
$(cts-combined-xml-coverage-report): PRIVATE_DEXDEPS_EXE := $(dexdeps_exe)
$(cts-combined-xml-coverage-report): PRIVATE_API_XML_DESC := $(api_xml_description)
$(cts-combined-xml-coverage-report): PRIVATE_NAPI_XML_DESC := $(napi_xml_description)
-$(cts-combined-xml-coverage-report) : $(android_cts_zip) $(cts_verifier_apk) $(cts_api_coverage_dependencies) | $(ACP)
+$(cts-combined-xml-coverage-report) : $(android_cts_zip) $(cts_verifier_apk) $(verifier-zip) $(cts_api_coverage_dependencies) | $(ACP)
$(call generate-coverage-report-cts,"CTS Combined API Coverage Report - XML",\
$(PRIVATE_TEST_CASES),xml)
@@ -236,3 +236,8 @@
cts_api_coverage_exe :=
cts_verifier_apk :=
android_cts_zip :=
+cts-dir :=
+verifier-dir-name :=
+verifier-dir :=
+verifier-zip-name :=
+verifier-zip :=
diff --git a/target/product/base_system.mk b/target/product/base_system.mk
index b8aeb38..3d057e2 100644
--- a/target/product/base_system.mk
+++ b/target/product/base_system.mk
@@ -94,15 +94,16 @@
ExtShared \
flags_health_check \
framework-graphics \
+ framework-location \
framework-minus-apex \
framework-minus-apex-install-dependencies \
- framework-res \
framework-sysconfig.xml \
fsck.erofs \
fsck_msdos \
fsverity-release-cert-der \
fs_config_files_system \
fs_config_dirs_system \
+ gpu_counter_producer \
group_system \
gsid \
gsi_tool \
@@ -238,10 +239,12 @@
perfetto \
ping \
ping6 \
+ pintool \
platform.xml \
pm \
preinstalled-packages-asl-files.xml \
preinstalled-packages-platform.xml \
+ preinstalled-packages-strict-signature.xml \
printflags \
privapp-permissions-platform.xml \
prng_seeder \
@@ -262,6 +265,7 @@
services \
settings \
SettingsProvider \
+ sfdo \
sgdisk \
Shell \
shell_and_utilities_system \
@@ -284,7 +288,6 @@
uncrypt \
usbd \
vdc \
- viewcompiler \
voip-common \
vold \
watchdogd \
@@ -415,7 +418,6 @@
unwind_info \
unwind_reg_info \
unwind_symbols \
- viewcompiler \
tzdata_host \
tzdata_host_tzdata_apex \
tzlookup.xml_host_tzdata_apex \
@@ -440,6 +442,7 @@
adevice_fingerprint \
arping \
dmuserd \
+ evemu-record \
idlcli \
init-debug.rc \
iotop \
diff --git a/target/product/base_vendor.mk b/target/product/base_vendor.mk
index a0c5929..ec3de75 100644
--- a/target/product/base_vendor.mk
+++ b/target/product/base_vendor.mk
@@ -51,7 +51,6 @@
dumpsys_vendor \
fs_config_files_nonsystem \
fs_config_dirs_nonsystem \
- gpu_counter_producer \
gralloc.default \
group_odm \
group_vendor \
diff --git a/target/product/default_art_config.mk b/target/product/default_art_config.mk
index d13a4c4..4a968d7 100644
--- a/target/product/default_art_config.mk
+++ b/target/product/default_art_config.mk
@@ -50,6 +50,7 @@
PRODUCT_BOOT_JARS += \
framework-minus-apex \
framework-graphics \
+ framework-location \
ext \
telephony-common \
voip-common \
diff --git a/target/product/gsi/current.txt b/target/product/gsi/current.txt
index 80aecb7..f771916 100644
--- a/target/product/gsi/current.txt
+++ b/target/product/gsi/current.txt
@@ -24,7 +24,7 @@
VNDK-SP: android.hardware.common-V2-ndk.so
VNDK-SP: android.hardware.common.fmq-V1-ndk.so
VNDK-SP: android.hardware.graphics.allocator-V2-ndk.so
-VNDK-SP: android.hardware.graphics.common-V4-ndk.so
+VNDK-SP: android.hardware.graphics.common-V5-ndk.so
VNDK-SP: android.hardware.graphics.common@1.0.so
VNDK-SP: android.hardware.graphics.common@1.1.so
VNDK-SP: android.hardware.graphics.common@1.2.so
@@ -60,8 +60,8 @@
VNDK-SP: libutilscallstack.so
VNDK-SP: libz.so
VNDK-core: android.frameworks.cameraservice.common-V1-ndk.so
-VNDK-core: android.frameworks.cameraservice.device-V1-ndk.so
-VNDK-core: android.frameworks.cameraservice.service-V1-ndk.so
+VNDK-core: android.frameworks.cameraservice.device-V2-ndk.so
+VNDK-core: android.frameworks.cameraservice.service-V2-ndk.so
VNDK-core: android.hardware.audio.common@2.0.so
VNDK-core: android.hardware.configstore-utils.so
VNDK-core: android.hardware.configstore@1.0.so
@@ -138,6 +138,7 @@
VNDK-core: libxml2.so
VNDK-core: libyuv.so
VNDK-core: libziparchive.so
+VNDK-core: server_configurable_flags.so
VNDK-private: libblas.so
VNDK-private: libcompiler_rt.so
VNDK-private: libft2.so
@@ -208,3 +209,4 @@
VNDK-product: libyuv.so
VNDK-product: libz.so
VNDK-product: libziparchive.so
+VNDK-product: server_configurable_flags.so
diff --git a/target/product/gsi_release.mk b/target/product/gsi_release.mk
index a581324..2e37366 100644
--- a/target/product/gsi_release.mk
+++ b/target/product/gsi_release.mk
@@ -31,11 +31,7 @@
PRODUCT_ARTIFACT_PATH_REQUIREMENT_ALLOWED_LIST += \
system/etc/init/config \
system/product/% \
- system/system_ext/% \
- system/lib/vndk-29 \
- system/lib/vndk-sp-29 \
- system/lib64/vndk-29 \
- system/lib64/vndk-sp-29
+ system/system_ext/%
# GSI should always support up-to-date platform features.
# Keep this value at the latest API level to ensure latest build system
diff --git a/target/product/handheld_system.mk b/target/product/handheld_system.mk
index b5292d2..bf9aa41 100644
--- a/target/product/handheld_system.mk
+++ b/target/product/handheld_system.mk
@@ -74,6 +74,7 @@
VpnDialogs \
vr \
+PRODUCT_PACKAGES += $(RELEASE_PACKAGE_VIRTUAL_CAMERA)
PRODUCT_SYSTEM_SERVER_APPS += \
FusedLocation \
diff --git a/target/product/sysconfig/preinstalled-packages-platform-aosp-product.xml b/target/product/sysconfig/preinstalled-packages-platform-aosp-product.xml
index 1295e1c..d3e2808 100644
--- a/target/product/sysconfig/preinstalled-packages-platform-aosp-product.xml
+++ b/target/product/sysconfig/preinstalled-packages-platform-aosp-product.xml
@@ -27,5 +27,6 @@
<install-in user-type="FULL" />
<install-in user-type="PROFILE" />
<do-not-install-in user-type="android.os.usertype.profile.CLONE" />
+ <do-not-install-in user-type="android.os.usertype.profile.PRIVATE" />
</install-in-user-type>
</config>
diff --git a/target/product/sysconfig/preinstalled-packages-platform-generic-system.xml b/target/product/sysconfig/preinstalled-packages-platform-generic-system.xml
index e2482e1..ef8056f 100644
--- a/target/product/sysconfig/preinstalled-packages-platform-generic-system.xml
+++ b/target/product/sysconfig/preinstalled-packages-platform-generic-system.xml
@@ -24,6 +24,7 @@
<install-in user-type="FULL" />
<install-in user-type="PROFILE" />
<do-not-install-in user-type="android.os.usertype.profile.CLONE" />
+ <do-not-install-in user-type="android.os.usertype.profile.PRIVATE" />
</install-in-user-type>
</config>
diff --git a/target/product/sysconfig/preinstalled-packages-platform-handheld-product.xml b/target/product/sysconfig/preinstalled-packages-platform-handheld-product.xml
index 54add22..536c35b 100644
--- a/target/product/sysconfig/preinstalled-packages-platform-handheld-product.xml
+++ b/target/product/sysconfig/preinstalled-packages-platform-handheld-product.xml
@@ -29,6 +29,7 @@
<install-in user-type="FULL" />
<install-in user-type="PROFILE" />
<do-not-install-in user-type="android.os.usertype.profile.CLONE" />
+ <do-not-install-in user-type="android.os.usertype.profile.PRIVATE" />
</install-in-user-type>
<!-- Camera (Camera2) -->
@@ -42,6 +43,7 @@
<install-in-user-type package="com.android.deskclock">
<install-in user-type="FULL" />
<do-not-install-in user-type="android.os.usertype.profile.CLONE" />
+ <do-not-install-in user-type="android.os.usertype.profile.PRIVATE" />
</install-in-user-type>
<!-- Contacts -->
@@ -56,6 +58,7 @@
<install-in user-type="FULL" />
<install-in user-type="PROFILE" />
<do-not-install-in user-type="android.os.usertype.profile.CLONE" />
+ <do-not-install-in user-type="android.os.usertype.profile.PRIVATE" />
</install-in-user-type>
<!-- Search (QuickSearchBox) TODO(b/258055479) -->
@@ -64,6 +67,7 @@
<install-in user-type="FULL" />
<install-in user-type="PROFILE" />
<do-not-install-in user-type="android.os.usertype.profile.CLONE" />
+ <do-not-install-in user-type="android.os.usertype.profile.PRIVATE" />
</install-in-user-type>
<!-- WallpaperCropper -->
diff --git a/target/product/sysconfig/preinstalled-packages-platform-telephony-product.xml b/target/product/sysconfig/preinstalled-packages-platform-telephony-product.xml
index cc1c135..67a2a01 100644
--- a/target/product/sysconfig/preinstalled-packages-platform-telephony-product.xml
+++ b/target/product/sysconfig/preinstalled-packages-platform-telephony-product.xml
@@ -24,6 +24,7 @@
<install-in user-type="FULL" />
<install-in user-type="PROFILE" />
<do-not-install-in user-type="android.os.usertype.profile.CLONE" />
+ <do-not-install-in user-type="android.os.usertype.profile.PRIVATE" />
</install-in-user-type>
</config>
diff --git a/tools/aconfig/aconfig_protos/protos/aconfig.proto b/tools/aconfig/aconfig_protos/protos/aconfig.proto
index 8833722..9d1b8cb 100644
--- a/tools/aconfig/aconfig_protos/protos/aconfig.proto
+++ b/tools/aconfig/aconfig_protos/protos/aconfig.proto
@@ -22,16 +22,38 @@
// This protobuf file defines messages used to represent and manage flags in the "aconfig" system
// The following format requirements apply across various message fields:
-// # name: a lowercase string in snake_case format, no consecutive underscores, and no leading digit
-// For example adjust_rate is a valid name, while AdjustRate, adjust__rate, and
-// 2adjust_rate are invalid
//
-// # namespace: a lowercase string in snake_case format, no consecutive underscores, and no leading
-// digit. For example android_bar_system
+// # name: name of the flag
//
-// # package: lowercase strings in snake_case format, delimited by dots, no consecutive underscores
-// and no leading digit in each string. For example com.android.mypackage is a valid name
-// while com.android.myPackage, com.android.1mypackage are invalid
+// format: a lowercase string in snake_case format, no consecutive underscores, and no leading
+// digit. For example adjust_rate is a valid name, while AdjustRate, adjust__rate, and
+// adjust_rate are invalid
+//
+// # namespace: namespace the flag belongs to
+//
+// format: a lowercase string in snake_case format, no consecutive underscores, and no leading
+// digit. For example android_bar_system
+//
+// # package: package to which the flag belongs
+//
+// format: lowercase strings in snake_case format, delimited by dots, no consecutive underscores
+// and no leading digit in each string. For example com.android.mypackage is a valid name
+// while com.android.myPackage, com.android.1mypackage are invalid
+//
+// # container: container as software built in its entirety using the same build environment and
+// always installed as a single unit
+//
+// For example the following are all separate containers:
+// * the system partition
+// * the vendor partition
+// * apexes: each APEX is its own container
+// * APKs: for APKs which are released independently via Play, each APK is its own container.
+// If an APK is released as part of a Mainline module, or as part of the system partition
+// via OTA, then they are part of the apex or the system partition container
+//
+// format: lowercase strings in snake_case format, delimited by dots if multiple, no consecutive
+// underscores or leading digits in each string. The recommended container values are the
+// partition names or the module names
// messages used in both aconfig input and output
@@ -98,6 +120,7 @@
repeated flag_declaration flag = 2;
// Container the flag belongs to (optional)
+ // See # container for format detail
optional string container = 3;
};
@@ -160,6 +183,7 @@
optional bool is_exported = 10;
// Container the flag belongs to (optional)
+ // See # container for format detail
optional string container = 11;
// Additional information about the flag, including its purpose and form factors (optional)
diff --git a/tools/aconfig/aconfig_storage_file/Android.bp b/tools/aconfig/aconfig_storage_file/Android.bp
index 6be3c19..2a606bf 100644
--- a/tools/aconfig/aconfig_storage_file/Android.bp
+++ b/tools/aconfig/aconfig_storage_file/Android.bp
@@ -6,10 +6,13 @@
name: "aconfig_storage_file.defaults",
edition: "2021",
lints: "none",
- srcs: ["src/lib.rs"],
rustlibs: [
"libanyhow",
"libthiserror",
+ "libtempfile",
+ "libprotobuf",
+ "libclap",
+ "libaconfig_storage_protos",
],
}
@@ -18,10 +21,41 @@
crate_name: "aconfig_storage_file",
host_supported: true,
defaults: ["aconfig_storage_file.defaults"],
+ srcs: ["src/lib.rs"],
+}
+
+rust_binary_host {
+ name: "aconfig-storage",
+ defaults: ["aconfig_storage_file.defaults"],
+ srcs: ["src/main.rs"],
+ rustlibs: ["libaconfig_storage_file"],
}
rust_test_host {
name: "aconfig_storage_file.test",
test_suites: ["general-tests"],
defaults: ["aconfig_storage_file.defaults"],
+ srcs: ["src/lib.rs"],
+}
+
+rust_protobuf {
+ name: "libaconfig_storage_protos",
+ protos: ["protos/aconfig_storage_metadata.proto"],
+ crate_name: "aconfig_storage_protos",
+ source_stem: "aconfig_storage_protos",
+ host_supported: true,
+}
+
+cc_library_static {
+ name: "libaconfig_storage_protos_cc",
+ proto: {
+ export_proto_headers: true,
+ type: "lite",
+ },
+ srcs: ["protos/aconfig_storage_metadata.proto"],
+ apex_available: [
+ "//apex_available:platform",
+ "//apex_available:anyapex",
+ ],
+ host_supported: true,
}
diff --git a/tools/aconfig/aconfig_storage_file/Cargo.toml b/tools/aconfig/aconfig_storage_file/Cargo.toml
index c4e2670..641f481 100644
--- a/tools/aconfig/aconfig_storage_file/Cargo.toml
+++ b/tools/aconfig/aconfig_storage_file/Cargo.toml
@@ -9,12 +9,14 @@
[dependencies]
anyhow = "1.0.69"
-memmap2 = "0.8.0"
protobuf = "3.2.0"
-once_cell = "1.19.0"
tempfile = "3.9.0"
-cxx = "1.0"
thiserror = "1.0.56"
+clap = { version = "4.1.8", features = ["derive"] }
+
+[[bin]]
+name = "aconfig-storage"
+path = "src/main.rs"
[build-dependencies]
protobuf-codegen = "3.2.0"
diff --git a/tools/aconfig/aconfig_storage_file/build.rs b/tools/aconfig/aconfig_storage_file/build.rs
new file mode 100644
index 0000000..1feeb60
--- /dev/null
+++ b/tools/aconfig/aconfig_storage_file/build.rs
@@ -0,0 +1,17 @@
+use protobuf_codegen::Codegen;
+
+fn main() {
+ let proto_files = vec!["protos/aconfig_storage_metadata.proto"];
+
+ // tell cargo to only re-run the build script if any of the proto files has changed
+ for path in &proto_files {
+ println!("cargo:rerun-if-changed={}", path);
+ }
+
+ Codegen::new()
+ .pure()
+ .include("protos")
+ .inputs(proto_files)
+ .cargo_out_dir("aconfig_storage_protos")
+ .run_from_script();
+}
diff --git a/tools/aconfig/aconfig_storage_read_api/protos/aconfig_storage_metadata.proto b/tools/aconfig/aconfig_storage_file/protos/aconfig_storage_metadata.proto
similarity index 100%
rename from tools/aconfig/aconfig_storage_read_api/protos/aconfig_storage_metadata.proto
rename to tools/aconfig/aconfig_storage_file/protos/aconfig_storage_metadata.proto
diff --git a/tools/aconfig/aconfig_storage_file/src/flag_table.rs b/tools/aconfig/aconfig_storage_file/src/flag_table.rs
index 61cf371..d6e5c62 100644
--- a/tools/aconfig/aconfig_storage_file/src/flag_table.rs
+++ b/tools/aconfig/aconfig_storage_file/src/flag_table.rs
@@ -20,9 +20,10 @@
use crate::AconfigStorageError::{self, BytesParseFail};
use crate::{get_bucket_index, read_str_from_bytes, read_u16_from_bytes, read_u32_from_bytes};
use anyhow::anyhow;
+use std::fmt;
/// Flag table header struct
-#[derive(PartialEq, Debug)]
+#[derive(PartialEq)]
pub struct FlagTableHeader {
pub version: u32,
pub container: String,
@@ -32,6 +33,23 @@
pub node_offset: u32,
}
+/// Implement debug print trait for header
+impl fmt::Debug for FlagTableHeader {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ writeln!(
+ f,
+ "Version: {}, Container: {}, File Size: {}",
+ self.version, self.container, self.file_size
+ )?;
+ writeln!(
+ f,
+ "Num of Flags: {}, Bucket Offset:{}, Node Offset: {}",
+ self.num_flags, self.bucket_offset, self.node_offset
+ )?;
+ Ok(())
+ }
+}
+
impl FlagTableHeader {
/// Serialize to bytes
pub fn as_bytes(&self) -> Vec<u8> {
@@ -62,7 +80,7 @@
}
/// Flag table node struct
-#[derive(PartialEq, Debug, Clone)]
+#[derive(PartialEq, Clone)]
pub struct FlagTableNode {
pub package_id: u32,
pub flag_name: String,
@@ -71,6 +89,18 @@
pub next_offset: Option<u32>,
}
+/// Implement debug print trait for node
+impl fmt::Debug for FlagTableNode {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ writeln!(
+ f,
+ "Package Id: {}, Flag: {}, Type: {}, Offset: {}, Next: {:?}",
+ self.package_id, self.flag_name, self.flag_type, self.flag_id, self.next_offset
+ )?;
+ Ok(())
+ }
+}
+
impl FlagTableNode {
/// Serialize to bytes
pub fn as_bytes(&self) -> Vec<u8> {
@@ -108,13 +138,28 @@
}
}
-#[derive(PartialEq, Debug)]
+#[derive(PartialEq)]
pub struct FlagTable {
pub header: FlagTableHeader,
pub buckets: Vec<Option<u32>>,
pub nodes: Vec<FlagTableNode>,
}
+/// Implement debug print trait for flag table
+impl fmt::Debug for FlagTable {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ writeln!(f, "Header:")?;
+ write!(f, "{:?}", self.header)?;
+ writeln!(f, "Buckets:")?;
+ writeln!(f, "{:?}", self.buckets)?;
+ writeln!(f, "Nodes:")?;
+ for node in self.nodes.iter() {
+ write!(f, "{:?}", node)?;
+ }
+ Ok(())
+ }
+}
+
/// Flag table struct
impl FlagTable {
/// Serialize to bytes
@@ -156,60 +201,7 @@
#[cfg(test)]
mod tests {
use super::*;
-
- impl FlagTableNode {
- // create test baseline, syntactic sugar
- fn new_expected(
- package_id: u32,
- flag_name: &str,
- flag_type: u16,
- flag_id: u16,
- next_offset: Option<u32>,
- ) -> Self {
- Self { package_id, flag_name: flag_name.to_string(), flag_type, flag_id, next_offset }
- }
- }
-
- pub fn create_test_flag_table() -> FlagTable {
- let header = FlagTableHeader {
- version: 1234,
- container: String::from("system"),
- file_size: 320,
- num_flags: 8,
- bucket_offset: 30,
- node_offset: 98,
- };
- let buckets: Vec<Option<u32>> = vec![
- Some(98),
- Some(124),
- None,
- None,
- None,
- Some(177),
- None,
- Some(203),
- None,
- Some(261),
- None,
- None,
- None,
- None,
- None,
- Some(293),
- None,
- ];
- let nodes = vec![
- FlagTableNode::new_expected(0, "enabled_ro", 1, 1, None),
- FlagTableNode::new_expected(0, "enabled_rw", 1, 2, Some(150)),
- FlagTableNode::new_expected(1, "disabled_ro", 1, 0, None),
- FlagTableNode::new_expected(2, "enabled_ro", 1, 1, None),
- FlagTableNode::new_expected(1, "enabled_fixed_ro", 1, 1, Some(235)),
- FlagTableNode::new_expected(1, "enabled_ro", 1, 2, None),
- FlagTableNode::new_expected(2, "enabled_fixed_ro", 1, 0, None),
- FlagTableNode::new_expected(0, "disabled_rw", 1, 0, None),
- ];
- FlagTable { header, buckets, nodes }
- }
+ use crate::test_utils::create_test_flag_table;
#[test]
// this test point locks down the table serialization
diff --git a/tools/aconfig/aconfig_storage_file/src/flag_value.rs b/tools/aconfig/aconfig_storage_file/src/flag_value.rs
index 62e94ef..021546c 100644
--- a/tools/aconfig/aconfig_storage_file/src/flag_value.rs
+++ b/tools/aconfig/aconfig_storage_file/src/flag_value.rs
@@ -19,9 +19,10 @@
use crate::AconfigStorageError;
use crate::{read_str_from_bytes, read_u32_from_bytes, read_u8_from_bytes};
+use std::fmt;
/// Flag value header struct
-#[derive(PartialEq, Debug)]
+#[derive(PartialEq)]
pub struct FlagValueHeader {
pub version: u32,
pub container: String,
@@ -30,6 +31,23 @@
pub boolean_value_offset: u32,
}
+/// Implement debug print trait for header
+impl fmt::Debug for FlagValueHeader {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ writeln!(
+ f,
+ "Version: {}, Container: {}, File Size: {}",
+ self.version, self.container, self.file_size
+ )?;
+ writeln!(
+ f,
+ "Num of Flags: {}, Value Offset:{}",
+ self.num_flags, self.boolean_value_offset
+ )?;
+ Ok(())
+ }
+}
+
impl FlagValueHeader {
/// Serialize to bytes
pub fn as_bytes(&self) -> Vec<u8> {
@@ -58,12 +76,23 @@
}
/// Flag value list struct
-#[derive(PartialEq, Debug)]
+#[derive(PartialEq)]
pub struct FlagValueList {
pub header: FlagValueHeader,
pub booleans: Vec<bool>,
}
+/// Implement debug print trait for flag value
+impl fmt::Debug for FlagValueList {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ writeln!(f, "Header:")?;
+ write!(f, "{:?}", self.header)?;
+ writeln!(f, "Values:")?;
+ writeln!(f, "{:?}", self.booleans)?;
+ Ok(())
+ }
+}
+
impl FlagValueList {
/// Serialize to bytes
pub fn as_bytes(&self) -> Vec<u8> {
@@ -89,18 +118,7 @@
#[cfg(test)]
mod tests {
use super::*;
-
- pub fn create_test_flag_value_list() -> FlagValueList {
- let header = FlagValueHeader {
- version: 1234,
- container: String::from("system"),
- file_size: 34,
- num_flags: 8,
- boolean_value_offset: 26,
- };
- let booleans: Vec<bool> = vec![false, true, false, false, true, true, false, true];
- FlagValueList { header, booleans }
- }
+ use crate::test_utils::create_test_flag_value_list;
#[test]
// this test point locks down the value list serialization
diff --git a/tools/aconfig/aconfig_storage_file/src/lib.rs b/tools/aconfig/aconfig_storage_file/src/lib.rs
index e06e149..202f6a4 100644
--- a/tools/aconfig/aconfig_storage_file/src/lib.rs
+++ b/tools/aconfig/aconfig_storage_file/src/lib.rs
@@ -35,10 +35,16 @@
pub mod flag_table;
pub mod flag_value;
pub mod package_table;
+pub mod protos;
+
+#[cfg(test)]
+mod test_utils;
use anyhow::anyhow;
use std::collections::hash_map::DefaultHasher;
+use std::fs::File;
use std::hash::{Hash, Hasher};
+use std::io::Read;
pub use crate::flag_table::{FlagTable, FlagTableHeader, FlagTableNode};
pub use crate::flag_value::{FlagValueHeader, FlagValueList};
@@ -72,7 +78,9 @@
"package_map" => Ok(Self::PackageMap),
"flag_map" => Ok(Self::FlagMap),
"flag_val" => Ok(Self::FlagVal),
- _ => Err(anyhow!("Invalid storage file to create")),
+ _ => Err(anyhow!(
+ "Invalid storage file type, valid types are package_map|flag_map|flag_val]"
+ )),
}
}
}
@@ -166,4 +174,88 @@
#[error("invalid storage file byte offset")]
InvalidStorageFileOffset(#[source] anyhow::Error),
+
+ #[error("failed to create file")]
+ FileCreationFail(#[source] anyhow::Error),
+}
+
+/// Read in storage file as bytes
+pub fn read_file_to_bytes(file_path: &str) -> Result<Vec<u8>, AconfigStorageError> {
+ let mut file = File::open(file_path).map_err(|errmsg| {
+ AconfigStorageError::FileReadFail(anyhow!("Failed to open file {}: {}", file_path, errmsg))
+ })?;
+ let mut buffer = Vec::new();
+ file.read_to_end(&mut buffer).map_err(|errmsg| {
+ AconfigStorageError::FileReadFail(anyhow!(
+ "Failed to read 4 bytes from file {}: {}",
+ file_path,
+ errmsg
+ ))
+ })?;
+ Ok(buffer)
+}
+
+/// List flag values from storage files
+pub fn list_flags(
+ package_map: &str,
+ flag_map: &str,
+ flag_val: &str,
+) -> Result<Vec<(String, bool)>, AconfigStorageError> {
+ let package_table = PackageTable::from_bytes(&read_file_to_bytes(package_map)?)?;
+ let flag_table = FlagTable::from_bytes(&read_file_to_bytes(flag_map)?)?;
+ let flag_value_list = FlagValueList::from_bytes(&read_file_to_bytes(flag_val)?)?;
+
+ let mut package_info = vec![("", 0); package_table.header.num_packages as usize];
+ for node in package_table.nodes.iter() {
+ package_info[node.package_id as usize] = (&node.package_name, node.boolean_offset);
+ }
+
+ let mut flags = Vec::new();
+ for node in flag_table.nodes.iter() {
+ let (package_name, package_offset) = package_info[node.package_id as usize];
+ let full_flag_name = String::from(package_name) + "/" + &node.flag_name;
+ let flag_offset = package_offset + node.flag_id as u32;
+ let flag_value = flag_value_list.booleans[flag_offset as usize];
+ flags.push((full_flag_name, flag_value));
+ }
+
+ flags.sort_by(|v1, v2| v1.0.cmp(&v2.0));
+ Ok(flags)
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use crate::test_utils::{
+ create_test_flag_table, create_test_flag_value_list, create_test_package_table,
+ write_bytes_to_temp_file,
+ };
+
+ #[test]
+ // this test point locks down the flag list api
+ fn test_list_flag() {
+ let package_table =
+ write_bytes_to_temp_file(&create_test_package_table().as_bytes()).unwrap();
+ let flag_table = write_bytes_to_temp_file(&create_test_flag_table().as_bytes()).unwrap();
+ let flag_value_list =
+ write_bytes_to_temp_file(&create_test_flag_value_list().as_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 flags =
+ list_flags(&package_table_path, &flag_table_path, &flag_value_list_path).unwrap();
+ let expected = [
+ (String::from("com.android.aconfig.storage.test_1/disabled_rw"), false),
+ (String::from("com.android.aconfig.storage.test_1/enabled_ro"), true),
+ (String::from("com.android.aconfig.storage.test_1/enabled_rw"), false),
+ (String::from("com.android.aconfig.storage.test_2/disabled_ro"), false),
+ (String::from("com.android.aconfig.storage.test_2/enabled_fixed_ro"), true),
+ (String::from("com.android.aconfig.storage.test_2/enabled_ro"), true),
+ (String::from("com.android.aconfig.storage.test_4/enabled_fixed_ro"), false),
+ (String::from("com.android.aconfig.storage.test_4/enabled_ro"), true),
+ ];
+ assert_eq!(flags, expected);
+ }
}
diff --git a/tools/aconfig/aconfig_storage_file/src/main.rs b/tools/aconfig/aconfig_storage_file/src/main.rs
new file mode 100644
index 0000000..b5e6158
--- /dev/null
+++ b/tools/aconfig/aconfig_storage_file/src/main.rs
@@ -0,0 +1,94 @@
+/*
+ * 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.
+ */
+
+//! `aconfig-storage` is a debugging tool to parse storage files
+
+use aconfig_storage_file::{
+ list_flags, read_file_to_bytes, AconfigStorageError, FlagTable, FlagValueList, PackageTable,
+ StorageFileSelection,
+};
+
+use clap::{builder::ArgAction, Arg, Command};
+
+fn cli() -> Command {
+ Command::new("aconfig-storage")
+ .subcommand_required(true)
+ .subcommand(
+ Command::new("print")
+ .arg(Arg::new("file").long("file").required(true).action(ArgAction::Set))
+ .arg(
+ Arg::new("type")
+ .long("type")
+ .required(true)
+ .value_parser(|s: &str| StorageFileSelection::try_from(s)),
+ ),
+ )
+ .subcommand(
+ Command::new("list")
+ .arg(
+ Arg::new("package-map")
+ .long("package-map")
+ .required(true)
+ .action(ArgAction::Set),
+ )
+ .arg(Arg::new("flag-map").long("flag-map").required(true).action(ArgAction::Set))
+ .arg(Arg::new("flag-val").long("flag-val").required(true).action(ArgAction::Set)),
+ )
+}
+
+fn print_storage_file(
+ file_path: &str,
+ file_type: &StorageFileSelection,
+) -> Result<(), AconfigStorageError> {
+ let bytes = read_file_to_bytes(file_path)?;
+ match file_type {
+ StorageFileSelection::PackageMap => {
+ let package_table = PackageTable::from_bytes(&bytes)?;
+ println!("{:?}", package_table);
+ }
+ StorageFileSelection::FlagMap => {
+ let flag_table = FlagTable::from_bytes(&bytes)?;
+ println!("{:?}", flag_table);
+ }
+ StorageFileSelection::FlagVal => {
+ let flag_value = FlagValueList::from_bytes(&bytes)?;
+ println!("{:?}", flag_value);
+ }
+ }
+ Ok(())
+}
+
+fn main() -> Result<(), AconfigStorageError> {
+ let matches = cli().get_matches();
+ match matches.subcommand() {
+ Some(("print", sub_matches)) => {
+ let file_path = sub_matches.get_one::<String>("file").unwrap();
+ let file_type = sub_matches.get_one::<StorageFileSelection>("type").unwrap();
+ print_storage_file(file_path, file_type)?
+ }
+ Some(("list", sub_matches)) => {
+ let package_map = sub_matches.get_one::<String>("package-map").unwrap();
+ let flag_map = sub_matches.get_one::<String>("flag-map").unwrap();
+ let flag_val = sub_matches.get_one::<String>("flag-val").unwrap();
+ let flags = list_flags(package_map, flag_map, flag_val)?;
+ for flag in flags.iter() {
+ println!("{}: {}", flag.0, flag.1);
+ }
+ }
+ _ => unreachable!(),
+ }
+ Ok(())
+}
diff --git a/tools/aconfig/aconfig_storage_file/src/package_table.rs b/tools/aconfig/aconfig_storage_file/src/package_table.rs
index 1c21179..f7435b0 100644
--- a/tools/aconfig/aconfig_storage_file/src/package_table.rs
+++ b/tools/aconfig/aconfig_storage_file/src/package_table.rs
@@ -20,9 +20,10 @@
use crate::AconfigStorageError::{self, BytesParseFail};
use crate::{get_bucket_index, read_str_from_bytes, read_u32_from_bytes};
use anyhow::anyhow;
+use std::fmt;
/// Package table header struct
-#[derive(PartialEq, Debug)]
+#[derive(PartialEq)]
pub struct PackageTableHeader {
pub version: u32,
pub container: String,
@@ -32,6 +33,23 @@
pub node_offset: u32,
}
+/// Implement debug print trait for header
+impl fmt::Debug for PackageTableHeader {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ writeln!(
+ f,
+ "Version: {}, Container: {}, File Size: {}",
+ self.version, self.container, self.file_size
+ )?;
+ writeln!(
+ f,
+ "Num of Packages: {}, Bucket Offset:{}, Node Offset: {}",
+ self.num_packages, self.bucket_offset, self.node_offset
+ )?;
+ Ok(())
+ }
+}
+
impl PackageTableHeader {
/// Serialize to bytes
pub fn as_bytes(&self) -> Vec<u8> {
@@ -62,7 +80,7 @@
}
/// Package table node struct
-#[derive(PartialEq, Debug)]
+#[derive(PartialEq)]
pub struct PackageTableNode {
pub package_name: String,
pub package_id: u32,
@@ -72,6 +90,18 @@
pub next_offset: Option<u32>,
}
+/// Implement debug print trait for node
+impl fmt::Debug for PackageTableNode {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ writeln!(
+ f,
+ "Package: {}, Id: {}, Offset: {}, Next: {:?}",
+ self.package_name, self.package_id, self.boolean_offset, self.next_offset
+ )?;
+ Ok(())
+ }
+}
+
impl PackageTableNode {
/// Serialize to bytes
pub fn as_bytes(&self) -> Vec<u8> {
@@ -109,13 +139,28 @@
}
/// Package table struct
-#[derive(PartialEq, Debug)]
+#[derive(PartialEq)]
pub struct PackageTable {
pub header: PackageTableHeader,
pub buckets: Vec<Option<u32>>,
pub nodes: Vec<PackageTableNode>,
}
+/// Implement debug print trait for package table
+impl fmt::Debug for PackageTable {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ writeln!(f, "Header:")?;
+ write!(f, "{:?}", self.header)?;
+ writeln!(f, "Buckets:")?;
+ writeln!(f, "{:?}", self.buckets)?;
+ writeln!(f, "Nodes:")?;
+ for node in self.nodes.iter() {
+ write!(f, "{:?}", node)?;
+ }
+ Ok(())
+ }
+}
+
impl PackageTable {
/// Serialize to bytes
pub fn as_bytes(&self) -> Vec<u8> {
@@ -156,38 +201,7 @@
#[cfg(test)]
mod tests {
use super::*;
-
- pub fn create_test_package_table() -> PackageTable {
- let header = PackageTableHeader {
- version: 1234,
- container: String::from("system"),
- file_size: 208,
- num_packages: 3,
- bucket_offset: 30,
- node_offset: 58,
- };
- let buckets: Vec<Option<u32>> = vec![Some(58), None, None, Some(108), None, None, None];
- let first_node = PackageTableNode {
- package_name: String::from("com.android.aconfig.storage.test_2"),
- package_id: 1,
- boolean_offset: 3,
- next_offset: None,
- };
- let second_node = PackageTableNode {
- package_name: String::from("com.android.aconfig.storage.test_1"),
- package_id: 0,
- boolean_offset: 0,
- next_offset: Some(158),
- };
- let third_node = PackageTableNode {
- package_name: String::from("com.android.aconfig.storage.test_4"),
- package_id: 2,
- boolean_offset: 6,
- next_offset: None,
- };
- let nodes = vec![first_node, second_node, third_node];
- PackageTable { header, buckets, nodes }
- }
+ use crate::test_utils::create_test_package_table;
#[test]
// this test point locks down the table serialization
diff --git a/tools/aconfig/aconfig_storage_read_api/src/protos.rs b/tools/aconfig/aconfig_storage_file/src/protos.rs
similarity index 78%
rename from tools/aconfig/aconfig_storage_read_api/src/protos.rs
rename to tools/aconfig/aconfig_storage_file/src/protos.rs
index 37df3e1..8b86205 100644
--- a/tools/aconfig/aconfig_storage_read_api/src/protos.rs
+++ b/tools/aconfig/aconfig_storage_file/src/protos.rs
@@ -49,8 +49,11 @@
pub use auto_generated::*;
use anyhow::Result;
+use protobuf::Message;
+use std::io::Write;
+use tempfile::NamedTempFile;
-pub mod storage_files {
+pub mod storage_record_pb {
use super::*;
use anyhow::ensure;
@@ -80,15 +83,28 @@
}
Ok(())
}
+
+ pub fn get_binary_proto_from_text_proto(text_proto: &str) -> Result<Vec<u8>> {
+ let storage_files: ProtoStorageFiles = protobuf::text_format::parse_from_str(text_proto)?;
+ let mut binary_proto = Vec::new();
+ storage_files.write_to_vec(&mut binary_proto)?;
+ Ok(binary_proto)
+ }
+
+ pub fn write_proto_to_temp_file(text_proto: &str) -> Result<NamedTempFile> {
+ let bytes = get_binary_proto_from_text_proto(text_proto).unwrap();
+ let mut file = NamedTempFile::new()?;
+ let _ = file.write_all(&bytes);
+ Ok(file)
+ }
}
#[cfg(test)]
mod tests {
use super::*;
- use crate::test_utils::get_binary_storage_proto_bytes;
#[test]
- fn test_parse_storage_files() {
+ fn test_parse_storage_record_pb() {
let text_proto = r#"
files {
version: 0
@@ -107,8 +123,9 @@
timestamp: 54321
}
"#;
- let binary_proto_bytes = get_binary_storage_proto_bytes(text_proto).unwrap();
- let storage_files = storage_files::try_from_binary_proto(&binary_proto_bytes).unwrap();
+ let binary_proto_bytes =
+ storage_record_pb::get_binary_proto_from_text_proto(text_proto).unwrap();
+ let storage_files = storage_record_pb::try_from_binary_proto(&binary_proto_bytes).unwrap();
assert_eq!(storage_files.files.len(), 2);
let system_file = &storage_files.files[0];
assert_eq!(system_file.version(), 0);
@@ -127,7 +144,7 @@
}
#[test]
- fn test_parse_invalid_storage_files() {
+ fn test_parse_invalid_storage_record_pb() {
let text_proto = r#"
files {
version: 0
@@ -138,8 +155,9 @@
timestamp: 12345
}
"#;
- let binary_proto_bytes = get_binary_storage_proto_bytes(text_proto).unwrap();
- let err = storage_files::try_from_binary_proto(&binary_proto_bytes).unwrap_err();
+ let binary_proto_bytes =
+ storage_record_pb::get_binary_proto_from_text_proto(text_proto).unwrap();
+ let err = storage_record_pb::try_from_binary_proto(&binary_proto_bytes).unwrap_err();
assert_eq!(
format!("{:?}", err),
"invalid storage file record: missing package map file for container system"
@@ -155,8 +173,9 @@
timestamp: 12345
}
"#;
- let binary_proto_bytes = get_binary_storage_proto_bytes(text_proto).unwrap();
- let err = storage_files::try_from_binary_proto(&binary_proto_bytes).unwrap_err();
+ let binary_proto_bytes =
+ storage_record_pb::get_binary_proto_from_text_proto(text_proto).unwrap();
+ let err = storage_record_pb::try_from_binary_proto(&binary_proto_bytes).unwrap_err();
assert_eq!(
format!("{:?}", err),
"invalid storage file record: missing flag map file for container system"
@@ -172,8 +191,9 @@
timestamp: 12345
}
"#;
- let binary_proto_bytes = get_binary_storage_proto_bytes(text_proto).unwrap();
- let err = storage_files::try_from_binary_proto(&binary_proto_bytes).unwrap_err();
+ let binary_proto_bytes =
+ storage_record_pb::get_binary_proto_from_text_proto(text_proto).unwrap();
+ let err = storage_record_pb::try_from_binary_proto(&binary_proto_bytes).unwrap_err();
assert_eq!(
format!("{:?}", err),
"invalid storage file record: missing flag val file for container system"
diff --git a/tools/aconfig/aconfig_storage_file/src/test_utils.rs b/tools/aconfig/aconfig_storage_file/src/test_utils.rs
new file mode 100644
index 0000000..7780044
--- /dev/null
+++ b/tools/aconfig/aconfig_storage_file/src/test_utils.rs
@@ -0,0 +1,130 @@
+/*
+ * 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.
+ */
+
+use crate::flag_table::{FlagTable, FlagTableHeader, FlagTableNode};
+use crate::flag_value::{FlagValueHeader, FlagValueList};
+use crate::package_table::{PackageTable, PackageTableHeader, PackageTableNode};
+use crate::AconfigStorageError;
+
+use anyhow::anyhow;
+use std::io::Write;
+use tempfile::NamedTempFile;
+
+pub(crate) fn create_test_package_table() -> PackageTable {
+ let header = PackageTableHeader {
+ version: 1234,
+ container: String::from("system"),
+ file_size: 208,
+ num_packages: 3,
+ bucket_offset: 30,
+ node_offset: 58,
+ };
+ let buckets: Vec<Option<u32>> = vec![Some(58), None, None, Some(108), None, None, None];
+ let first_node = PackageTableNode {
+ package_name: String::from("com.android.aconfig.storage.test_2"),
+ package_id: 1,
+ boolean_offset: 3,
+ next_offset: None,
+ };
+ let second_node = PackageTableNode {
+ package_name: String::from("com.android.aconfig.storage.test_1"),
+ package_id: 0,
+ boolean_offset: 0,
+ next_offset: Some(158),
+ };
+ let third_node = PackageTableNode {
+ package_name: String::from("com.android.aconfig.storage.test_4"),
+ package_id: 2,
+ boolean_offset: 6,
+ next_offset: None,
+ };
+ let nodes = vec![first_node, second_node, third_node];
+ PackageTable { header, buckets, nodes }
+}
+
+impl FlagTableNode {
+ // create test baseline, syntactic sugar
+ fn new_expected(
+ package_id: u32,
+ flag_name: &str,
+ flag_type: u16,
+ flag_id: u16,
+ next_offset: Option<u32>,
+ ) -> Self {
+ Self { package_id, flag_name: flag_name.to_string(), flag_type, flag_id, next_offset }
+ }
+}
+
+pub(crate) fn create_test_flag_table() -> FlagTable {
+ let header = FlagTableHeader {
+ version: 1234,
+ container: String::from("system"),
+ file_size: 320,
+ num_flags: 8,
+ bucket_offset: 30,
+ node_offset: 98,
+ };
+ let buckets: Vec<Option<u32>> = vec![
+ Some(98),
+ Some(124),
+ None,
+ None,
+ None,
+ Some(177),
+ None,
+ Some(203),
+ None,
+ Some(261),
+ None,
+ None,
+ None,
+ None,
+ None,
+ Some(293),
+ None,
+ ];
+ let nodes = vec![
+ FlagTableNode::new_expected(0, "enabled_ro", 1, 1, None),
+ FlagTableNode::new_expected(0, "enabled_rw", 1, 2, Some(150)),
+ FlagTableNode::new_expected(1, "disabled_ro", 1, 0, None),
+ FlagTableNode::new_expected(2, "enabled_ro", 1, 1, None),
+ FlagTableNode::new_expected(1, "enabled_fixed_ro", 1, 1, Some(235)),
+ FlagTableNode::new_expected(1, "enabled_ro", 1, 2, None),
+ FlagTableNode::new_expected(2, "enabled_fixed_ro", 1, 0, None),
+ FlagTableNode::new_expected(0, "disabled_rw", 1, 0, None),
+ ];
+ FlagTable { header, buckets, nodes }
+}
+
+pub(crate) fn create_test_flag_value_list() -> FlagValueList {
+ let header = FlagValueHeader {
+ version: 1234,
+ container: String::from("system"),
+ file_size: 34,
+ num_flags: 8,
+ boolean_value_offset: 26,
+ };
+ let booleans: Vec<bool> = vec![false, true, false, false, true, true, false, true];
+ FlagValueList { header, booleans }
+}
+
+pub(crate) fn write_bytes_to_temp_file(bytes: &[u8]) -> Result<NamedTempFile, AconfigStorageError> {
+ let mut file = NamedTempFile::new().map_err(|_| {
+ AconfigStorageError::FileCreationFail(anyhow!("Failed to create temp file"))
+ })?;
+ let _ = file.write_all(&bytes);
+ Ok(file)
+}
diff --git a/tools/aconfig/aconfig_storage_read_api/Android.bp b/tools/aconfig/aconfig_storage_read_api/Android.bp
index 5f4329c..721f9a5 100644
--- a/tools/aconfig/aconfig_storage_read_api/Android.bp
+++ b/tools/aconfig/aconfig_storage_read_api/Android.bp
@@ -9,9 +9,7 @@
srcs: ["src/lib.rs"],
rustlibs: [
"libanyhow",
- "libaconfig_storage_protos",
"libonce_cell",
- "libprotobuf",
"libtempfile",
"libmemmap2",
"libcxx",
@@ -38,28 +36,6 @@
],
}
-rust_protobuf {
- name: "libaconfig_storage_protos",
- protos: ["protos/aconfig_storage_metadata.proto"],
- crate_name: "aconfig_storage_protos",
- source_stem: "aconfig_storage_protos",
- host_supported: true,
-}
-
-cc_library_static {
- name: "libaconfig_storage_protos_cc",
- proto: {
- export_proto_headers: true,
- type: "lite",
- },
- srcs: ["protos/aconfig_storage_metadata.proto"],
- apex_available: [
- "//apex_available:platform",
- "//apex_available:anyapex",
- ],
- host_supported: true,
-}
-
// cxx source codegen from rust api
genrule {
name: "libcxx_aconfig_storage_read_api_bridge_code",
diff --git a/tools/aconfig/aconfig_storage_read_api/Cargo.toml b/tools/aconfig/aconfig_storage_read_api/Cargo.toml
index 4c65d40..30a4298 100644
--- a/tools/aconfig/aconfig_storage_read_api/Cargo.toml
+++ b/tools/aconfig/aconfig_storage_read_api/Cargo.toml
@@ -10,7 +10,6 @@
[dependencies]
anyhow = "1.0.69"
memmap2 = "0.8.0"
-protobuf = "3.2.0"
once_cell = "1.19.0"
tempfile = "3.9.0"
cxx = "1.0"
diff --git a/tools/aconfig/aconfig_storage_read_api/build.rs b/tools/aconfig/aconfig_storage_read_api/build.rs
index 894b71c..7b1aa53 100644
--- a/tools/aconfig/aconfig_storage_read_api/build.rs
+++ b/tools/aconfig/aconfig_storage_read_api/build.rs
@@ -1,20 +1,4 @@
-use protobuf_codegen::Codegen;
-
fn main() {
- let proto_files = vec!["protos/aconfig_storage_metadata.proto"];
-
- // tell cargo to only re-run the build script if any of the proto files has changed
- for path in &proto_files {
- println!("cargo:rerun-if-changed={}", path);
- }
-
- Codegen::new()
- .pure()
- .include("protos")
- .inputs(proto_files)
- .cargo_out_dir("aconfig_storage_protos")
- .run_from_script();
-
let _ = cxx_build::bridge("src/lib.rs");
println!("cargo:rerun-if-changed=src/lib.rs");
}
diff --git a/tools/aconfig/aconfig_storage_read_api/src/lib.rs b/tools/aconfig/aconfig_storage_read_api/src/lib.rs
index 0da81dd..3958b2e 100644
--- a/tools/aconfig/aconfig_storage_read_api/src/lib.rs
+++ b/tools/aconfig/aconfig_storage_read_api/src/lib.rs
@@ -38,14 +38,13 @@
pub mod flag_value_query;
pub mod mapped_file;
pub mod package_table_query;
-pub mod protos;
#[cfg(test)]
mod test_utils;
-pub use crate::protos::ProtoStorageFiles;
pub use aconfig_storage_file::{
- read_u32_from_bytes, AconfigStorageError, StorageFileSelection, FILE_VERSION,
+ protos::ProtoStorageFiles, read_u32_from_bytes, AconfigStorageError, StorageFileSelection,
+ FILE_VERSION,
};
pub use flag_table_query::FlagOffset;
pub use package_table_query::PackageOffset;
@@ -380,7 +379,8 @@
#[cfg(test)]
mod tests {
use super::*;
- use crate::test_utils::{write_storage_text_to_temp_file, TestStorageFileSet};
+ use crate::test_utils::TestStorageFileSet;
+ use aconfig_storage_file::protos::storage_record_pb::write_proto_to_temp_file;
fn create_test_storage_files(read_only: bool) -> TestStorageFileSet {
TestStorageFileSet::new(
@@ -410,7 +410,7 @@
ro_files.package_map.name, ro_files.flag_map.name, ro_files.flag_val.name
);
- let file = write_storage_text_to_temp_file(&text_proto).unwrap();
+ let file = write_proto_to_temp_file(&text_proto).unwrap();
let file_full_path = file.path().display().to_string();
let package_offset = get_package_offset_impl(
&file_full_path,
@@ -461,7 +461,7 @@
ro_files.package_map.name, ro_files.flag_map.name, ro_files.flag_val.name
);
- let file = write_storage_text_to_temp_file(&text_proto).unwrap();
+ let file = write_proto_to_temp_file(&text_proto).unwrap();
let file_full_path = file.path().display().to_string();
let baseline = vec![
(0, "enabled_ro", 1u16),
@@ -500,7 +500,7 @@
ro_files.package_map.name, ro_files.flag_map.name, ro_files.flag_val.name
);
- let file = write_storage_text_to_temp_file(&text_proto).unwrap();
+ let file = write_proto_to_temp_file(&text_proto).unwrap();
let file_full_path = file.path().display().to_string();
let baseline: Vec<bool> = vec![false; 8];
for (offset, expected_value) in baseline.into_iter().enumerate() {
diff --git a/tools/aconfig/aconfig_storage_read_api/src/mapped_file.rs b/tools/aconfig/aconfig_storage_read_api/src/mapped_file.rs
index d8f2570..e94c56f 100644
--- a/tools/aconfig/aconfig_storage_read_api/src/mapped_file.rs
+++ b/tools/aconfig/aconfig_storage_read_api/src/mapped_file.rs
@@ -23,13 +23,13 @@
use memmap2::Mmap;
use once_cell::sync::Lazy;
-use crate::protos::{
- storage_files::try_from_binary_proto, ProtoStorageFileInfo, ProtoStorageFiles,
-};
use crate::AconfigStorageError::{
self, FileReadFail, MapFileFail, ProtobufParseFail, StorageFileNotFound,
};
use crate::StorageFileSelection;
+use aconfig_storage_file::protos::{
+ storage_record_pb::try_from_binary_proto, ProtoStorageFileInfo, ProtoStorageFiles,
+};
/// Cache for already mapped files
static ALL_MAPPED_FILES: Lazy<Mutex<HashMap<String, MappedStorageFileSet>>> = Lazy::new(|| {
@@ -148,7 +148,8 @@
#[cfg(test)]
mod tests {
use super::*;
- use crate::test_utils::{write_storage_text_to_temp_file, TestStorageFileSet};
+ use crate::test_utils::TestStorageFileSet;
+ use aconfig_storage_file::protos::storage_record_pb::write_proto_to_temp_file;
#[test]
fn test_find_storage_file_location() {
@@ -170,7 +171,7 @@
timestamp: 54321
}
"#;
- let file = write_storage_text_to_temp_file(text_proto).unwrap();
+ let file = write_proto_to_temp_file(&text_proto).unwrap();
let file_full_path = file.path().display().to_string();
let file_info = find_container_storage_location(&file_full_path, "system").unwrap();
assert_eq!(file_info.version(), 0);
@@ -235,7 +236,7 @@
ro_files.package_map.name, ro_files.flag_map.name, ro_files.flag_val.name
);
- let file = write_storage_text_to_temp_file(&text_proto).unwrap();
+ let file = write_proto_to_temp_file(&text_proto).unwrap();
let file_full_path = file.path().display().to_string();
map_and_verify(
&file_full_path,
@@ -264,7 +265,7 @@
rw_files.package_map.name, ro_files.flag_map.name, ro_files.flag_val.name
);
- let file = write_storage_text_to_temp_file(&text_proto).unwrap();
+ let file = write_proto_to_temp_file(&text_proto).unwrap();
let file_full_path = file.path().display().to_string();
let error = map_container_storage_files(&file_full_path, "system").unwrap_err();
assert_eq!(
@@ -289,7 +290,7 @@
ro_files.package_map.name, rw_files.flag_map.name, ro_files.flag_val.name
);
- let file = write_storage_text_to_temp_file(&text_proto).unwrap();
+ let file = write_proto_to_temp_file(&text_proto).unwrap();
let file_full_path = file.path().display().to_string();
let error = map_container_storage_files(&file_full_path, "system").unwrap_err();
assert_eq!(
@@ -314,7 +315,7 @@
ro_files.package_map.name, ro_files.flag_map.name, rw_files.flag_val.name
);
- let file = write_storage_text_to_temp_file(&text_proto).unwrap();
+ let file = write_proto_to_temp_file(&text_proto).unwrap();
let file_full_path = file.path().display().to_string();
let error = map_container_storage_files(&file_full_path, "system").unwrap_err();
assert_eq!(
diff --git a/tools/aconfig/aconfig_storage_read_api/src/test_utils.rs b/tools/aconfig/aconfig_storage_read_api/src/test_utils.rs
index 588ecba..cc5938d 100644
--- a/tools/aconfig/aconfig_storage_read_api/src/test_utils.rs
+++ b/tools/aconfig/aconfig_storage_read_api/src/test_utils.rs
@@ -14,27 +14,10 @@
* limitations under the License.
*/
-use crate::protos::ProtoStorageFiles;
use anyhow::Result;
-use protobuf::Message;
use std::fs;
-use std::io::Write;
use tempfile::NamedTempFile;
-pub(crate) fn get_binary_storage_proto_bytes(text_proto: &str) -> Result<Vec<u8>> {
- let storage_files: ProtoStorageFiles = protobuf::text_format::parse_from_str(text_proto)?;
- let mut binary_proto = Vec::new();
- storage_files.write_to_vec(&mut binary_proto)?;
- Ok(binary_proto)
-}
-
-pub(crate) fn write_storage_text_to_temp_file(text_proto: &str) -> Result<NamedTempFile> {
- let bytes = get_binary_storage_proto_bytes(text_proto).unwrap();
- let mut file = NamedTempFile::new()?;
- let _ = file.write_all(&bytes);
- Ok(file)
-}
-
fn set_file_read_only(file: &NamedTempFile) {
let mut perms = fs::metadata(file.path()).unwrap().permissions();
if !perms.readonly() {
diff --git a/tools/aconfig/aflags/src/device_config_source.rs b/tools/aconfig/aflags/src/device_config_source.rs
index 1cea6ed..2589f3d 100644
--- a/tools/aconfig/aflags/src/device_config_source.rs
+++ b/tools/aconfig/aflags/src/device_config_source.rs
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-use crate::{Flag, FlagPermission, FlagSource, ValuePickedFrom};
+use crate::{Flag, FlagPermission, FlagSource, FlagValue, ValuePickedFrom};
use aconfig_protos::ProtoFlagPermission as ProtoPermission;
use aconfig_protos::ProtoFlagState as ProtoState;
use aconfig_protos::ProtoParsedFlag;
@@ -40,10 +40,9 @@
};
let value = match flag.state() {
- ProtoState::ENABLED => "true",
- ProtoState::DISABLED => "false",
- }
- .to_string();
+ ProtoState::ENABLED => FlagValue::Enabled,
+ ProtoState::DISABLED => FlagValue::Disabled,
+ };
let permission = match flag.permission() {
ProtoPermission::READ_ONLY => FlagPermission::ReadOnly,
@@ -86,14 +85,16 @@
Ok(flags.values().cloned().collect())
}
-fn parse_device_config(raw: &str) -> Result<HashMap<String, String>> {
+fn parse_device_config(raw: &str) -> Result<HashMap<String, FlagValue>> {
let mut flags = HashMap::new();
let regex = Regex::new(r"(?m)^([[[:alnum:]]_]+/[[[:alnum:]]_\.]+)=(true|false)$")?;
for capture in regex.captures_iter(raw) {
let key =
capture.get(1).ok_or(anyhow!("invalid device_config output"))?.as_str().to_string();
- let value = capture.get(2).ok_or(anyhow!("invalid device_config output"))?.as_str();
- flags.insert(key, value.to_string());
+ let value = FlagValue::try_from(
+ capture.get(2).ok_or(anyhow!("invalid device_config output"))?.as_str(),
+ )?;
+ flags.insert(key, value);
}
Ok(flags)
}
@@ -112,24 +113,24 @@
Ok(str::from_utf8(&output.stdout)?.to_string())
}
-fn read_device_config_flags() -> Result<HashMap<String, String>> {
+fn read_device_config_flags() -> Result<HashMap<String, FlagValue>> {
let list_output = read_device_config_output(&["list"])?;
parse_device_config(&list_output)
}
-fn reconcile(pb_flags: &[Flag], dc_flags: HashMap<String, String>) -> Vec<Flag> {
+fn reconcile(pb_flags: &[Flag], dc_flags: HashMap<String, FlagValue>) -> Vec<Flag> {
pb_flags
.iter()
.map(|f| {
dc_flags
.get(&format!("{}/{}.{}", f.namespace, f.package, f.name))
.map(|value| {
- if value.eq(&f.value) {
+ if *value == f.value {
Flag { value_picked_from: ValuePickedFrom::Default, ..f.clone() }
} else {
Flag {
value_picked_from: ValuePickedFrom::Server,
- value: value.to_string(),
+ value: *value,
..f.clone()
}
}
@@ -167,9 +168,9 @@
namespace_two/android.flag_two=nonsense
"#;
let expected = HashMap::from([
- ("namespace_one/com.foo.bar.flag_one".to_string(), "true".to_string()),
- ("namespace_one/com.foo.bar.flag_two".to_string(), "false".to_string()),
- ("namespace_two/android.flag_one".to_string(), "true".to_string()),
+ ("namespace_one/com.foo.bar.flag_one".to_string(), FlagValue::Enabled),
+ ("namespace_one/com.foo.bar.flag_two".to_string(), FlagValue::Disabled),
+ ("namespace_two/android.flag_one".to_string(), FlagValue::Enabled),
]);
let actual = parse_device_config(input).unwrap();
assert_eq!(expected, actual);
diff --git a/tools/aconfig/aflags/src/main.rs b/tools/aconfig/aflags/src/main.rs
index 037bbd0..febd567 100644
--- a/tools/aconfig/aflags/src/main.rs
+++ b/tools/aconfig/aflags/src/main.rs
@@ -52,13 +52,40 @@
}
}
+#[derive(Clone, Copy, PartialEq, Eq, Debug)]
+enum FlagValue {
+ Enabled,
+ Disabled,
+}
+
+impl TryFrom<&str> for FlagValue {
+ type Error = anyhow::Error;
+
+ fn try_from(value: &str) -> std::result::Result<Self, Self::Error> {
+ match value {
+ "true" | "enabled" => Ok(Self::Enabled),
+ "false" | "disabled" => Ok(Self::Disabled),
+ _ => Err(anyhow!("cannot convert string '{}' to FlagValue", value)),
+ }
+ }
+}
+
+impl ToString for FlagValue {
+ fn to_string(&self) -> String {
+ match &self {
+ Self::Enabled => "enabled".into(),
+ Self::Disabled => "disabled".into(),
+ }
+ }
+}
+
#[derive(Clone)]
struct Flag {
namespace: String,
name: String,
package: String,
container: String,
- value: String,
+ value: FlagValue,
permission: FlagPermission,
value_picked_from: ValuePickedFrom,
}
@@ -116,32 +143,28 @@
}
struct PaddingInfo {
- longest_package_col: usize,
- longest_name_col: usize,
+ longest_flag_col: usize,
longest_val_col: usize,
longest_value_picked_from_col: usize,
longest_permission_col: usize,
}
fn format_flag_row(flag: &Flag, info: &PaddingInfo) -> String {
- let pkg = &flag.package;
- let p0 = info.longest_package_col + 1;
-
- let name = &flag.name;
- let p1 = info.longest_name_col + 1;
+ let full_name = flag.qualified_name();
+ let p0 = info.longest_flag_col + 1;
let val = flag.value.to_string();
- let p2 = info.longest_val_col + 1;
+ let p1 = info.longest_val_col + 1;
let value_picked_from = flag.value_picked_from.to_string();
- let p3 = info.longest_value_picked_from_col + 1;
+ let p2 = info.longest_value_picked_from_col + 1;
let perm = flag.permission.to_string();
- let p4 = info.longest_permission_col + 1;
+ let p3 = info.longest_permission_col + 1;
let container = &flag.container;
- format!("{pkg:p0$}{name:p1$}{val:p2$}{value_picked_from:p3$}{perm:p4$}{container}\n")
+ format!("{full_name:p0$}{val:p1$}{value_picked_from:p2$}{perm:p3$}{container}\n")
}
fn set_flag(qualified_name: &str, value: &str) -> Result<()> {
@@ -163,8 +186,7 @@
fn list() -> Result<String> {
let flags = DeviceConfigSource::list_flags()?;
let padding_info = PaddingInfo {
- longest_package_col: flags.iter().map(|f| f.package.len()).max().unwrap_or(0),
- longest_name_col: flags.iter().map(|f| f.name.len()).max().unwrap_or(0),
+ longest_flag_col: flags.iter().map(|f| f.qualified_name().len()).max().unwrap_or(0),
longest_val_col: flags.iter().map(|f| f.value.to_string().len()).max().unwrap_or(0),
longest_value_picked_from_col: flags
.iter()
diff --git a/tools/finalization/finalize-aidl-vndk-sdk-resources.sh b/tools/finalization/finalize-aidl-vndk-sdk-resources.sh
index 37c0011..671b036 100755
--- a/tools/finalization/finalize-aidl-vndk-sdk-resources.sh
+++ b/tools/finalization/finalize-aidl-vndk-sdk-resources.sh
@@ -69,6 +69,33 @@
rm "$tmpfile"
}
+function bumpSdkExtensionsVersion() {
+ local SDKEXT="packages/modules/SdkExtensions/"
+
+ # This used to call bump_sdk.sh utility.
+ # However due to TS, we have to build the gen_sdk with a correct set of settings.
+
+ # "$top/packages/modules/SdkExtensions/gen_sdk/bump_sdk.sh" ${FINAL_MAINLINE_EXTENSION}
+ # Leave the last commit as a set of modified files.
+ # The code to create a finalization topic will pick it up later.
+ # git -C ${SDKEXT} reset HEAD~1
+
+ local sdk="${FINAL_MAINLINE_EXTENSION}"
+ local modules_arg=
+
+ TARGET_PRODUCT=aosp_arm64 \
+ TARGET_RELEASE=fina_1 \
+ TARGET_BUILD_VARIANT=userdebug \
+ DIST_DIR=out/dist \
+ $top/build/soong/soong_ui.bash --make-mode --soong-only gen_sdk
+
+ ANDROID_BUILD_TOP="$top" out/soong/host/linux-x86/bin/gen_sdk \
+ --database ${SDKEXT}/gen_sdk/extensions_db.textpb \
+ --action new_sdk \
+ --sdk "$sdk" \
+ $modules_arg
+}
+
function finalize_aidl_vndk_sdk_resources() {
local top="$(dirname "$0")"/../../../..
source $top/build/make/tools/finalization/environment.sh
@@ -76,9 +103,6 @@
local SDK_CODENAME="public static final int $FINAL_PLATFORM_CODENAME_JAVA = CUR_DEVELOPMENT;"
local SDK_VERSION="public static final int $FINAL_PLATFORM_CODENAME_JAVA = $FINAL_PLATFORM_SDK_VERSION;"
- # default target to modify tree and build SDK
- local m="$top/build/soong/soong_ui.bash --make-mode TARGET_PRODUCT=aosp_arm64 TARGET_BUILD_VARIANT=userdebug DIST_DIR=out/dist"
-
# The full process can be found at (INTERNAL) go/android-sdk-finalization.
# apply droidstubs hack to prevent tools from incrementing an API version
@@ -87,20 +111,12 @@
# bionic/NDK
finalize_bionic_ndk
- # VNDK definitions for new SDK version
- cp "$top/development/vndk/tools/definition-tool/datasets/vndk-lib-extra-list-current.txt" \
- "$top/development/vndk/tools/definition-tool/datasets/vndk-lib-extra-list-$FINAL_PLATFORM_SDK_VERSION.txt"
+ # pre-finalization build target (trunk)
+ local aidl_m="$top/build/soong/soong_ui.bash --make-mode TARGET_PRODUCT=aosp_arm64 TARGET_RELEASE=trunk TARGET_BUILD_VARIANT=userdebug DIST_DIR=out/dist"
+ AIDL_TRANSITIVE_FREEZE=true $aidl_m aidl-freeze-api
- AIDL_TRANSITIVE_FREEZE=true $m aidl-freeze-api create_reference_dumps
-
- # Generate ABI dumps
- ANDROID_BUILD_TOP="$top" out/host/linux-x86/bin/create_reference_dumps
-
- echo "NOTE: THIS INTENTIONALLY MAY FAIL AND REPAIR ITSELF (until 'DONE')"
- # Update new versions of files. See update-vndk-list.sh (which requires envsetup.sh)
- $m check-vndk-list || \
- { cp $top/out/soong/vndk/vndk.libraries.txt $top/build/make/target/product/gsi/current.txt; }
- echo "DONE: THIS INTENTIONALLY MAY FAIL AND REPAIR ITSELF"
+ # TODO(b/309880485)
+ # Add back create_reference_dumps and $top/build/make/target/product/gsi/current.txt
# Finalize SDK
@@ -114,9 +130,6 @@
sed -i -e 's/Pkg\.Revision.*/Pkg\.Revision=${PLATFORM_SDK_VERSION}.0.0/g' $build_tools_source
# build/make
- local version_defaults="$top/build/make/core/version_defaults.mk"
- sed -i -e "s/PLATFORM_SDK_VERSION := .*/PLATFORM_SDK_VERSION := ${FINAL_PLATFORM_SDK_VERSION}/g" $version_defaults
- sed -i -e "s/PLATFORM_VERSION_LAST_STABLE := .*/PLATFORM_VERSION_LAST_STABLE := ${FINAL_PLATFORM_VERSION}/g" $version_defaults
sed -i -e "s/sepolicy_major_vers := .*/sepolicy_major_vers := ${FINAL_PLATFORM_SDK_VERSION}/g" "$top/build/make/core/config.mk"
cp "$top/build/make/target/product/gsi/current.txt" "$top/build/make/target/product/gsi/$FINAL_PLATFORM_SDK_VERSION.txt"
@@ -156,18 +169,14 @@
sed -i -e "/=.*$((${FINAL_PLATFORM_SDK_VERSION}-1)),/a \\ SDK_${FINAL_PLATFORM_CODENAME_JAVA} = ${FINAL_PLATFORM_SDK_VERSION}," "$top/frameworks/base/tools/aapt2/SdkConstants.h"
# Bump Mainline SDK extension version.
- local SDKEXT="packages/modules/SdkExtensions/"
- "$top/packages/modules/SdkExtensions/gen_sdk/bump_sdk.sh" ${FINAL_MAINLINE_EXTENSION}
- # Leave the last commit as a set of modified files.
- # The code to create a finalization topic will pick it up later.
- git -C ${SDKEXT} reset HEAD~1
+ bumpSdkExtensionsVersion
- local version_defaults="$top/build/make/core/version_defaults.mk"
- sed -i -e "s/PLATFORM_SDK_EXTENSION_VERSION := .*/PLATFORM_SDK_EXTENSION_VERSION := ${FINAL_MAINLINE_EXTENSION}/g" $version_defaults
+ # target to build SDK
+ local sdk_m="$top/build/soong/soong_ui.bash --make-mode TARGET_PRODUCT=aosp_arm64 TARGET_RELEASE=fina_1 TARGET_BUILD_VARIANT=userdebug DIST_DIR=out/dist"
# Force update current.txt
- $m clobber
- $m update-api
+ $sdk_m clobber
+ $sdk_m update-api
}
finalize_aidl_vndk_sdk_resources
diff --git a/tools/finalization/finalize-sdk-rel.sh b/tools/finalization/finalize-sdk-rel.sh
index d4ed380..245305b 100755
--- a/tools/finalization/finalize-sdk-rel.sh
+++ b/tools/finalization/finalize-sdk-rel.sh
@@ -33,10 +33,6 @@
# in REL mode, resources would correctly set the resources_sdk_int, no fix required
revert_resources_sdk_int_fix
- # build/make/core/version_defaults.mk
- # Mark all versions "released".
- sed -i 's/\(PLATFORM_VERSION_CODENAME\.[^[:space:]]*\) := [^[:space:]]*/\1 := REL/g' "$top/build/make/core/version_defaults.mk"
-
# cts
echo "$FINAL_PLATFORM_VERSION" > "$top/cts/tests/tests/os/assets/platform_versions.txt"
if [ "$FINAL_PLATFORM_CODENAME" != "$CURRENT_PLATFORM_CODENAME" ]; then
@@ -47,18 +43,19 @@
# system/sepolicy
system/sepolicy/tools/finalize-sdk-rel.sh "$top" "$FINAL_PLATFORM_SDK_VERSION"
- # prebuilts/abi-dumps/ndk
- mkdir -p "$top/prebuilts/abi-dumps/ndk/$FINAL_PLATFORM_SDK_VERSION"
- cp -r "$top/prebuilts/abi-dumps/ndk/current/64/" "$top/prebuilts/abi-dumps/ndk/$FINAL_PLATFORM_SDK_VERSION/"
-
# prebuilts/abi-dumps/platform
mkdir -p "$top/prebuilts/abi-dumps/platform/$FINAL_PLATFORM_SDK_VERSION"
cp -r "$top/prebuilts/abi-dumps/platform/current/64/" "$top/prebuilts/abi-dumps/platform/$FINAL_PLATFORM_SDK_VERSION/"
- if [ "$FINAL_STATE" != "sdk" ] || [ "$FINAL_PLATFORM_CODENAME" == "$CURRENT_PLATFORM_CODENAME" ] ; then
+ # TODO(b/309880485)
+ # uncomment and update
+ # prebuilts/abi-dumps/ndk
+ #mkdir -p "$top/prebuilts/abi-dumps/ndk/$FINAL_PLATFORM_SDK_VERSION"
+ #cp -r "$top/prebuilts/abi-dumps/ndk/current/64/" "$top/prebuilts/abi-dumps/ndk/$FINAL_PLATFORM_SDK_VERSION/"
+ #if [ "$FINAL_STATE" != "sdk" ] || [ "$FINAL_PLATFORM_CODENAME" == "$CURRENT_PLATFORM_CODENAME" ] ; then
# prebuilts/abi-dumps/vndk
- mv "$top/prebuilts/abi-dumps/vndk/$CURRENT_PLATFORM_CODENAME" "$top/prebuilts/abi-dumps/vndk/$FINAL_PLATFORM_SDK_VERSION"
- fi;
+ #mv "$top/prebuilts/abi-dumps/vndk/$CURRENT_PLATFORM_CODENAME" "$top/prebuilts/abi-dumps/vndk/$FINAL_PLATFORM_SDK_VERSION"
+ #fi;
}
finalize_sdk_rel
diff --git a/tools/finalization/localonly-steps.sh b/tools/finalization/localonly-steps.sh
index 7318ca1..bebd563 100755
--- a/tools/finalization/localonly-steps.sh
+++ b/tools/finalization/localonly-steps.sh
@@ -7,17 +7,17 @@
source $top/build/make/tools/finalization/environment.sh
# default target to modify tree and build SDK
- local m="$top/build/soong/soong_ui.bash --make-mode TARGET_PRODUCT=aosp_arm64 TARGET_BUILD_VARIANT=userdebug DIST_DIR=out/dist"
+ local m="$top/build/soong/soong_ui.bash --make-mode TARGET_PRODUCT=aosp_arm64 TARGET_RELEASE=fina_1 TARGET_BUILD_VARIANT=userdebug DIST_DIR=out/dist"
# adb keys
$m adb
LOGNAME=android-eng HOSTNAME=google.com "$top/out/host/linux-x86/bin/adb" keygen "$top/vendor/google/security/adb/${FINAL_PLATFORM_VERSION}.adb_key"
# Build Platform SDKs.
- $top/build/soong/soong_ui.bash --make-mode TARGET_PRODUCT=sdk TARGET_BUILD_VARIANT=userdebug sdk dist sdk_repo DIST_DIR=out/dist
+ $top/build/soong/soong_ui.bash --make-mode TARGET_PRODUCT=sdk TARGET_RELEASE=fina_1 TARGET_BUILD_VARIANT=userdebug sdk dist sdk_repo DIST_DIR=out/dist
# Build Modules SDKs.
- TARGET_BUILD_VARIANT=userdebug UNBUNDLED_BUILD_SDKS_FROM_SOURCE=true DIST_DIR=out/dist "$top/vendor/google/build/mainline_modules_sdks.sh" --build-release=latest
+ TARGET_RELEASE=fina_1 TARGET_BUILD_VARIANT=userdebug UNBUNDLED_BUILD_SDKS_FROM_SOURCE=true DIST_DIR=out/dist "$top/vendor/google/build/mainline_modules_sdks.sh" --build-release=latest
# Update prebuilts.
"$top/prebuilts/build-tools/path/linux-x86/python3" -W ignore::DeprecationWarning "$top/prebuilts/sdk/update_prebuilts.py" --local_mode -f ${FINAL_PLATFORM_SDK_VERSION} -e ${FINAL_MAINLINE_EXTENSION} --bug 1 1
diff --git a/tools/releasetools/check_target_files_vintf.py b/tools/releasetools/check_target_files_vintf.py
index d31f87e..b8dcd84 100755
--- a/tools/releasetools/check_target_files_vintf.py
+++ b/tools/releasetools/check_target_files_vintf.py
@@ -215,7 +215,7 @@
This simulates how apexd activates APEXes.
1. create {inp}/APEX which is treated as a "/apex" on device.
- 2. invoke apexd_host with vendor APEXes.
+ 2. invoke apexd_host with APEXes.
"""
apex_dir = common.MakeTempDir('APEX')
@@ -225,12 +225,13 @@
# Always create /apex directory for dirmap
os.makedirs(apex_dir, exist_ok=True)
- # Invoke apexd_host to activate vendor APEXes for checkvintf
+ # Invoke apexd_host to activate APEXes for checkvintf
apex_host = os.path.join(OPTIONS.search_path, 'bin', 'apexd_host')
cmd = [apex_host, '--tool_path', OPTIONS.search_path]
cmd += ['--apex_path', dirmap['/apex']]
- if '/vendor' in dirmap:
- cmd += ['--vendor_path', dirmap['/vendor']]
+ for p in ['system', 'system_ext', 'product', 'vendor']:
+ if '/' + p in dirmap:
+ cmd += ['--' + p + '_path', dirmap['/' + p]]
common.RunAndCheckOutput(cmd)