Merge "Revert "16k: core: Enable TARGET_NO_BIONIC_PAGE_SIZE_MACRO by default on Android V targets"" into main
diff --git a/core/OWNERS b/core/OWNERS
index 36951a9..1c3d017 100644
--- a/core/OWNERS
+++ b/core/OWNERS
@@ -10,3 +10,6 @@
# For Ravenwood test configs
per-file ravenwood_test_config_template.xml = jsharkey@google.com,omakoto@google.com
+
+# For binary_translation
+per-file berberis_test.mk = levarum@google.com,khim@google.com,dimitry@google.com
diff --git a/core/android_soong_config_vars.mk b/core/android_soong_config_vars.mk
index ca87417..4e42a21 100644
--- a/core/android_soong_config_vars.mk
+++ b/core/android_soong_config_vars.mk
@@ -75,18 +75,6 @@
BRANCH_DEFAULT_MODULE_BUILD_FROM_SOURCE := true
endif
-# TV based devices do not seem to work with prebuilts, so build from source
-# for now and fix in a follow up.
-ifneq (,$(filter tv,$(subst $(comma),$(space),${PRODUCT_CHARACTERISTICS})))
- BRANCH_DEFAULT_MODULE_BUILD_FROM_SOURCE := true
-endif
-
-# ATV based devices do not seem to work with prebuilts, so build from source
-# for now and fix in a follow up.
-ifneq (,${PRODUCT_IS_ATV})
- BRANCH_DEFAULT_MODULE_BUILD_FROM_SOURCE := true
-endif
-
ifneq (,$(MODULE_BUILD_FROM_SOURCE))
# Keep an explicit setting.
else ifeq (,$(filter docs sdk win_sdk sdk_addon,$(MAKECMDGOALS))$(findstring com.google.android.conscrypt,$(PRODUCT_PACKAGES))$(findstring com.google.android.go.conscrypt,$(PRODUCT_PACKAGES)))
diff --git a/core/board_config.mk b/core/board_config.mk
index 4424517..633303f 100644
--- a/core/board_config.mk
+++ b/core/board_config.mk
@@ -992,7 +992,7 @@
# BOARD_API_LEVEL for vendor API surface
ifdef RELEASE_BOARD_API_LEVEL
ifdef BOARD_API_LEVEL
- $(error BOARD_API_LEVEL must not set manully. The build system automatically sets this value.)
+ $(error BOARD_API_LEVEL must not be set manually. The build system automatically sets this value.)
endif
BOARD_API_LEVEL := $(RELEASE_BOARD_API_LEVEL)
.KATI_READONLY := BOARD_API_LEVEL
diff --git a/core/product.mk b/core/product.mk
index 01b5ead..aa9a9a3 100644
--- a/core/product.mk
+++ b/core/product.mk
@@ -456,7 +456,7 @@
_product_single_value_vars += PRODUCT_BUILD_FROM_SOURCE_STUB
-_product_list_vars += PRODUCT_BUILD_IGNORE_APEX_CONTRIBUTION_CONTENTS
+_product_single_value_vars += PRODUCT_BUILD_IGNORE_APEX_CONTRIBUTION_CONTENTS
_product_single_value_vars += PRODUCT_HIDDEN_API_EXPORTABLE_STUBS
diff --git a/core/product_config.mk b/core/product_config.mk
index 4525423..d16c38d 100644
--- a/core/product_config.mk
+++ b/core/product_config.mk
@@ -301,6 +301,23 @@
PRODUCT_INCLUDE_TAGS += com.android.mainline mainline_module_prebuilt_nightly
endif
+# AOSP and Google products currently share the same `apex_contributions` in next.
+# This causes issues when building <aosp_product>-next-userdebug in main.
+# Create a temporary allowlist to ignore the google apexes listed in `contents` of apex_contributions of `next`
+# *for aosp products*.
+# TODO(b/308187268): Remove this denylist mechanism
+# Use PRODUCT_PACKAGES to determine if this is an aosp product. aosp products do not use google signed apexes.
+ignore_apex_contributions :=
+ifeq (,$(findstring com.google.android.conscrypt,$(PRODUCT_PACKAGES))$(findstring com.google.android.go.conscrypt,$(PRODUCT_PACKAGES)))
+ ignore_apex_contributions := true
+endif
+ifeq (true,$(PRODUCT_MODULE_BUILD_FROM_SOURCE))
+ ignore_apex_contributions := true
+endif
+ifeq (true, $(ignore_apex_contributions))
+PRODUCT_BUILD_IGNORE_APEX_CONTRIBUTION_CONTENTS := true
+endif
+
#############################################################################
# Quick check and assign default values
@@ -552,20 +569,27 @@
$(PRODUCT_ENFORCE_RRO_EXEMPTED_TARGETS))
endif
-# Get the board API level.
-board_api_level := $(PLATFORM_SDK_VERSION)
-ifdef BOARD_API_LEVEL
- board_api_level := $(BOARD_API_LEVEL)
-else ifdef BOARD_SHIPPING_API_LEVEL
- # Vendors with GRF must define BOARD_SHIPPING_API_LEVEL for the vendor API level.
- board_api_level := $(BOARD_SHIPPING_API_LEVEL)
-endif
+# This table maps sdk version 35 to vendor api level 202404 and assumes yearly
+# release for the same month.
+define sdk-to-vendor-api-level
+ $(if $(call math_lt_or_eq,$(1),34),$(1),20$(call int_subtract,$(1),11)04)
+endef
-# Calculate the VSR vendor API level.
-VSR_VENDOR_API_LEVEL := $(board_api_level)
-
-ifdef PRODUCT_SHIPPING_API_LEVEL
- VSR_VENDOR_API_LEVEL := $(call math_min,$(PRODUCT_SHIPPING_API_LEVEL),$(board_api_level))
+ifdef PRODUCT_SHIPPING_VENDOR_API_LEVEL
+# Follow the version that is set manually.
+ VSR_VENDOR_API_LEVEL := $(PRODUCT_SHIPPING_VENDOR_API_LEVEL)
+else
+ # VSR API level is the vendor api level of the product shipping API level.
+ VSR_VENDOR_API_LEVEL := $(call sdk-to-vendor-api-level,$(PLATFORM_SDK_VERSION))
+ ifdef PRODUCT_SHIPPING_API_LEVEL
+ VSR_VENDOR_API_LEVEL := $(call sdk-to-vendor-api-level,$(PRODUCT_SHIPPING_API_LEVEL))
+ endif
+ ifdef BOARD_SHIPPING_API_LEVEL
+ # Vendors with GRF must define BOARD_SHIPPING_API_LEVEL for the vendor API level.
+ # In this case, the VSR API level is the minimum of the PRODUCT_SHIPPING_API_LEVEL
+ # and RELEASE_BOARD_API_LEVEL
+ VSR_VENDOR_API_LEVEL := $(call math_min,$(VSR_VENDOR_API_LEVEL),$(RELEASE_BOARD_API_LEVEL))
+ endif
endif
.KATI_READONLY := VSR_VENDOR_API_LEVEL
@@ -580,7 +604,7 @@
# Boolean variable determining if selinux labels of /dev are enforced
CHECK_DEV_TYPE_VIOLATIONS := false
-ifneq ($(call math_gt,$(VSR_VENDOR_API_LEVEL),35),)
+ifneq ($(call math_gt,$(VSR_VENDOR_API_LEVEL),202404),)
CHECK_DEV_TYPE_VIOLATIONS := true
else ifneq ($(PRODUCT_CHECK_DEV_TYPE_VIOLATIONS),)
CHECK_DEV_TYPE_VIOLATIONS := $(PRODUCT_CHECK_DEV_TYPE_VIOLATIONS)
@@ -606,15 +630,6 @@
endif
endef
-ifndef PRODUCT_VIRTUAL_AB_COW_VERSION
- PRODUCT_VIRTUAL_AB_COW_VERSION := 2
- ifdef PRODUCT_SHIPPING_API_LEVEL
- ifeq (true,$(call math_gt_or_eq,$(PRODUCT_SHIPPING_API_LEVEL),34))
- PRODUCT_VIRTUAL_AB_COW_VERSION := 3
- endif
- endif
-endif
-
# Copy and check the value of each PRODUCT_BUILD_*_IMAGE variable
$(foreach image, \
PVMFW \
diff --git a/core/release_config.mk b/core/release_config.mk
index a7b5b3f..3e51af5 100644
--- a/core/release_config.mk
+++ b/core/release_config.mk
@@ -41,8 +41,7 @@
# which has OWNERS control. If it isn't let others define their own.
# TODO: Remove wildcard for build/release one when all branch manifests
# have updated.
-config_map_files := $(wildcard build/trunk_release/release_config_map.mk) \
- $(wildcard build/release/release_config_map.mk) \
+config_map_files := $(wildcard build/release/release_config_map.mk) \
$(wildcard vendor/google_shared/build/release/release_config_map.mk) \
$(if $(wildcard vendor/google/release/release_config_map.mk), \
vendor/google/release/release_config_map.mk, \
diff --git a/core/soong_config.mk b/core/soong_config.mk
index 1e419f3..e382407 100644
--- a/core/soong_config.mk
+++ b/core/soong_config.mk
@@ -339,7 +339,7 @@
$(call add_json_bool, CheckVendorSeappViolations, $(filter true,$(CHECK_VENDOR_SEAPP_VIOLATIONS)))
-$(call add_json_list, BuildIgnoreApexContributionContents, $(sort $(PRODUCT_BUILD_IGNORE_APEX_CONTRIBUTION_CONTENTS)))
+$(call add_json_bool, BuildIgnoreApexContributionContents, $(PRODUCT_BUILD_IGNORE_APEX_CONTRIBUTION_CONTENTS))
$(call add_json_map, PartitionVarsForBazelMigrationOnlyDoNotUse)
$(call add_json_str, ProductDirectory, $(dir $(INTERNAL_PRODUCT)))
diff --git a/core/tasks/berberis_test.mk b/core/tasks/berberis_test.mk
new file mode 100644
index 0000000..8604709
--- /dev/null
+++ b/core/tasks/berberis_test.mk
@@ -0,0 +1,25 @@
+#
+# Copyright (C) 2023 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.
+#
+
+BERBERIS_DIR := frameworks/libs/binary_translation
+
+# Berberis includes some components which may conflict with other packages.
+# Only build it when requested explicitly.
+ifeq ($(BUILD_BERBERIS),true)
+
+include $(BERBERIS_DIR)/tests/run_host_tests.mk
+
+endif # BUILD_BERBERIS
diff --git a/core/tasks/meta-lic.mk b/core/tasks/meta-lic.mk
index dea4892..0348844 100644
--- a/core/tasks/meta-lic.mk
+++ b/core/tasks/meta-lic.mk
@@ -14,6 +14,9 @@
# Declare license metadata for non-module files released with products.
+# Moved here from device/sample/Android.mk
+$(eval $(call declare-1p-copy-files,device/sample,))
+
# Moved here from frameworks/av/media/Android.mk
$(eval $(call declare-1p-copy-files,frameworks/av/media/libeffects,audio_effects.conf))
$(eval $(call declare-1p-copy-files,frameworks/av/media/libeffects,audio_effects.xml))
diff --git a/target/product/base_system.mk b/target/product/base_system.mk
index 884af4f..8dc680b 100644
--- a/target/product/base_system.mk
+++ b/target/product/base_system.mk
@@ -172,7 +172,6 @@
libjpeg \
liblog \
libm.bootstrap \
- libmdnssd \
libmedia \
libmedia_jni \
libmediandk \
diff --git a/target/product/handheld_system_ext.mk b/target/product/handheld_system_ext.mk
index 1218f7a..187b627 100644
--- a/target/product/handheld_system_ext.mk
+++ b/target/product/handheld_system_ext.mk
@@ -29,8 +29,3 @@
StorageManager \
SystemUI \
WallpaperCropper \
-
-# Base modules when shipping api level is less than or equal to 34
-PRODUCT_PACKAGES_SHIPPING_API_LEVEL_34 += \
- hwservicemanager \
- android.hidl.allocator@1.0-service \
diff --git a/target/product/sdk.mk b/target/product/sdk.mk
index 04649a2..1a07363 100644
--- a/target/product/sdk.mk
+++ b/target/product/sdk.mk
@@ -34,6 +34,9 @@
PRODUCT_BUILD_FROM_SOURCE_STUB := true
+# Use sources of mainline modules
+PRODUCT_MODULE_BUILD_FROM_SOURCE := true
+
ifeq ($(WITHOUT_CHECK_API),true)
$(error WITHOUT_CHECK_API cannot be set to true for SDK product builds)
endif
diff --git a/target/product/virtual_ab_ota/android_t_baseline.mk b/target/product/virtual_ab_ota/android_t_baseline.mk
index 418aaa4..af0f7a9 100644
--- a/target/product/virtual_ab_ota/android_t_baseline.mk
+++ b/target/product/virtual_ab_ota/android_t_baseline.mk
@@ -20,3 +20,5 @@
#
# All U+ launching devices should instead use vabc_features.mk.
$(call inherit-product, $(SRC_TARGET_DIR)/product/virtual_ab_ota/vabc_features.mk)
+
+PRODUCT_VIRTUAL_AB_COW_VERSION ?= 2
diff --git a/tools/aconfig/TEST_MAPPING b/tools/aconfig/TEST_MAPPING
index 7651dba..638b92a 100644
--- a/tools/aconfig/TEST_MAPPING
+++ b/tools/aconfig/TEST_MAPPING
@@ -39,6 +39,10 @@
// "name": "aconfig.exported_mode.test.rust"
// },
{
+ // aflags CLI unit tests
+ "name": "aflags.test"
+ },
+ {
// printflags unit tests
"name": "printflags.test"
},
@@ -66,9 +70,7 @@
// test testing filtering logic. Breakage on this test means all tests
// that using the flag macros to do filtering will get affected.
"name": "FlagMacrosTests"
- }
- ],
- "postsubmit": [
+ },
{
// aconfig_storage_write_api unit tests
"name": "aconfig_storage_write_api.test"
@@ -82,21 +84,18 @@
"name": "aconfig_storage_write_api.test.rust"
},
{
- // aconfig_storage write api cpp integration tests
- "name": "aconfig_storage_write_api.test.cpp"
- },
- {
// aconfig_storage read api rust integration tests
"name": "aconfig_storage_read_api.test.rust"
},
{
// aconfig_storage read api cpp integration tests
"name": "aconfig_storage_read_api.test.cpp"
- },
+ }
+ ],
+ "postsubmit": [
{
- // aflags CLI unit tests
- // TODO(b/326062088): add to presubmit once proven in postsubmit.
- "name": "aflags.test"
+ // aconfig_storage write api cpp integration tests
+ "name": "aconfig_storage_write_api.test.cpp"
}
]
}
diff --git a/tools/aconfig/aconfig/src/codegen/java.rs b/tools/aconfig/aconfig/src/codegen/java.rs
index fab2fa3..18a4be5 100644
--- a/tools/aconfig/aconfig/src/codegen/java.rs
+++ b/tools/aconfig/aconfig/src/codegen/java.rs
@@ -181,26 +181,35 @@
/** @hide */
public interface FeatureFlags {
@com.android.aconfig.annotations.AssumeFalseForR8
+ @com.android.aconfig.annotations.AconfigFlagAccessor
@UnsupportedAppUsage
boolean disabledRo();
+ @com.android.aconfig.annotations.AconfigFlagAccessor
@UnsupportedAppUsage
boolean disabledRw();
+ @com.android.aconfig.annotations.AconfigFlagAccessor
@UnsupportedAppUsage
boolean disabledRwExported();
+ @com.android.aconfig.annotations.AconfigFlagAccessor
@UnsupportedAppUsage
boolean disabledRwInOtherNamespace();
@com.android.aconfig.annotations.AssumeTrueForR8
+ @com.android.aconfig.annotations.AconfigFlagAccessor
@UnsupportedAppUsage
boolean enabledFixedRo();
@com.android.aconfig.annotations.AssumeTrueForR8
+ @com.android.aconfig.annotations.AconfigFlagAccessor
@UnsupportedAppUsage
boolean enabledFixedRoExported();
@com.android.aconfig.annotations.AssumeTrueForR8
+ @com.android.aconfig.annotations.AconfigFlagAccessor
@UnsupportedAppUsage
boolean enabledRo();
@com.android.aconfig.annotations.AssumeTrueForR8
+ @com.android.aconfig.annotations.AconfigFlagAccessor
@UnsupportedAppUsage
boolean enabledRoExported();
+ @com.android.aconfig.annotations.AconfigFlagAccessor
@UnsupportedAppUsage
boolean enabledRw();
}
@@ -232,42 +241,51 @@
public static final String FLAG_ENABLED_RW = "com.android.aconfig.test.enabled_rw";
@com.android.aconfig.annotations.AssumeFalseForR8
+ @com.android.aconfig.annotations.AconfigFlagAccessor
@UnsupportedAppUsage
public static boolean disabledRo() {
return FEATURE_FLAGS.disabledRo();
}
+ @com.android.aconfig.annotations.AconfigFlagAccessor
@UnsupportedAppUsage
public static boolean disabledRw() {
return FEATURE_FLAGS.disabledRw();
}
+ @com.android.aconfig.annotations.AconfigFlagAccessor
@UnsupportedAppUsage
public static boolean disabledRwExported() {
return FEATURE_FLAGS.disabledRwExported();
}
+ @com.android.aconfig.annotations.AconfigFlagAccessor
@UnsupportedAppUsage
public static boolean disabledRwInOtherNamespace() {
return FEATURE_FLAGS.disabledRwInOtherNamespace();
}
@com.android.aconfig.annotations.AssumeTrueForR8
+ @com.android.aconfig.annotations.AconfigFlagAccessor
@UnsupportedAppUsage
public static boolean enabledFixedRo() {
return FEATURE_FLAGS.enabledFixedRo();
}
@com.android.aconfig.annotations.AssumeTrueForR8
+ @com.android.aconfig.annotations.AconfigFlagAccessor
@UnsupportedAppUsage
public static boolean enabledFixedRoExported() {
return FEATURE_FLAGS.enabledFixedRoExported();
}
@com.android.aconfig.annotations.AssumeTrueForR8
+ @com.android.aconfig.annotations.AconfigFlagAccessor
@UnsupportedAppUsage
public static boolean enabledRo() {
return FEATURE_FLAGS.enabledRo();
}
@com.android.aconfig.annotations.AssumeTrueForR8
+ @com.android.aconfig.annotations.AconfigFlagAccessor
@UnsupportedAppUsage
public static boolean enabledRoExported() {
return FEATURE_FLAGS.enabledRoExported();
}
+ @com.android.aconfig.annotations.AconfigFlagAccessor
@UnsupportedAppUsage
public static boolean enabledRw() {
return FEATURE_FLAGS.enabledRw();
@@ -458,13 +476,14 @@
other_namespace_is_cached = true;
}
-
@Override
+ @com.android.aconfig.annotations.AconfigFlagAccessor
@UnsupportedAppUsage
public boolean disabledRo() {
return false;
}
@Override
+ @com.android.aconfig.annotations.AconfigFlagAccessor
@UnsupportedAppUsage
public boolean disabledRw() {
if (!aconfig_test_is_cached) {
@@ -473,6 +492,7 @@
return disabledRw;
}
@Override
+ @com.android.aconfig.annotations.AconfigFlagAccessor
@UnsupportedAppUsage
public boolean disabledRwExported() {
if (!aconfig_test_is_cached) {
@@ -481,6 +501,7 @@
return disabledRwExported;
}
@Override
+ @com.android.aconfig.annotations.AconfigFlagAccessor
@UnsupportedAppUsage
public boolean disabledRwInOtherNamespace() {
if (!other_namespace_is_cached) {
@@ -489,26 +510,31 @@
return disabledRwInOtherNamespace;
}
@Override
+ @com.android.aconfig.annotations.AconfigFlagAccessor
@UnsupportedAppUsage
public boolean enabledFixedRo() {
return true;
}
@Override
+ @com.android.aconfig.annotations.AconfigFlagAccessor
@UnsupportedAppUsage
public boolean enabledFixedRoExported() {
return true;
}
@Override
+ @com.android.aconfig.annotations.AconfigFlagAccessor
@UnsupportedAppUsage
public boolean enabledRo() {
return true;
}
@Override
+ @com.android.aconfig.annotations.AconfigFlagAccessor
@UnsupportedAppUsage
public boolean enabledRoExported() {
return true;
}
@Override
+ @com.android.aconfig.annotations.AconfigFlagAccessor
@UnsupportedAppUsage
public boolean enabledRw() {
if (!aconfig_test_is_cached) {
@@ -566,7 +592,6 @@
public static final String FLAG_ENABLED_FIXED_RO_EXPORTED = "com.android.aconfig.test.enabled_fixed_ro_exported";
/** @hide */
public static final String FLAG_ENABLED_RO_EXPORTED = "com.android.aconfig.test.enabled_ro_exported";
-
public static boolean disabledRwExported() {
return FEATURE_FLAGS.disabledRwExported();
}
@@ -623,7 +648,6 @@
}
aconfig_test_is_cached = true;
}
-
@Override
public boolean disabledRwExported() {
if (!aconfig_test_is_cached) {
@@ -631,7 +655,6 @@
}
return disabledRwExported;
}
-
@Override
public boolean enabledFixedRoExported() {
if (!aconfig_test_is_cached) {
@@ -639,7 +662,6 @@
}
return enabledFixedRoExported;
}
-
@Override
public boolean enabledRoExported() {
if (!aconfig_test_is_cached) {
@@ -762,54 +784,63 @@
/** @hide */
public final class FeatureFlagsImpl implements FeatureFlags {
@Override
+ @com.android.aconfig.annotations.AconfigFlagAccessor
@UnsupportedAppUsage
public boolean disabledRo() {
throw new UnsupportedOperationException(
"Method is not implemented.");
}
@Override
+ @com.android.aconfig.annotations.AconfigFlagAccessor
@UnsupportedAppUsage
public boolean disabledRw() {
throw new UnsupportedOperationException(
"Method is not implemented.");
}
@Override
+ @com.android.aconfig.annotations.AconfigFlagAccessor
@UnsupportedAppUsage
public boolean disabledRwExported() {
throw new UnsupportedOperationException(
"Method is not implemented.");
}
@Override
+ @com.android.aconfig.annotations.AconfigFlagAccessor
@UnsupportedAppUsage
public boolean disabledRwInOtherNamespace() {
throw new UnsupportedOperationException(
"Method is not implemented.");
}
@Override
+ @com.android.aconfig.annotations.AconfigFlagAccessor
@UnsupportedAppUsage
public boolean enabledFixedRo() {
throw new UnsupportedOperationException(
"Method is not implemented.");
}
@Override
+ @com.android.aconfig.annotations.AconfigFlagAccessor
@UnsupportedAppUsage
public boolean enabledFixedRoExported() {
throw new UnsupportedOperationException(
"Method is not implemented.");
}
@Override
+ @com.android.aconfig.annotations.AconfigFlagAccessor
@UnsupportedAppUsage
public boolean enabledRo() {
throw new UnsupportedOperationException(
"Method is not implemented.");
}
@Override
+ @com.android.aconfig.annotations.AconfigFlagAccessor
@UnsupportedAppUsage
public boolean enabledRoExported() {
throw new UnsupportedOperationException(
"Method is not implemented.");
}
@Override
+ @com.android.aconfig.annotations.AconfigFlagAccessor
@UnsupportedAppUsage
public boolean enabledRw() {
throw new UnsupportedOperationException(
@@ -862,21 +893,27 @@
/** @hide */
public interface FeatureFlags {
@com.android.aconfig.annotations.AssumeFalseForR8
+ @com.android.aconfig.annotations.AconfigFlagAccessor
@UnsupportedAppUsage
boolean disabledRo();
@com.android.aconfig.annotations.AssumeFalseForR8
+ @com.android.aconfig.annotations.AconfigFlagAccessor
@UnsupportedAppUsage
boolean disabledRw();
@com.android.aconfig.annotations.AssumeFalseForR8
+ @com.android.aconfig.annotations.AconfigFlagAccessor
@UnsupportedAppUsage
boolean disabledRwInOtherNamespace();
@com.android.aconfig.annotations.AssumeTrueForR8
+ @com.android.aconfig.annotations.AconfigFlagAccessor
@UnsupportedAppUsage
boolean enabledFixedRo();
@com.android.aconfig.annotations.AssumeTrueForR8
+ @com.android.aconfig.annotations.AconfigFlagAccessor
@UnsupportedAppUsage
boolean enabledRo();
@com.android.aconfig.annotations.AssumeTrueForR8
+ @com.android.aconfig.annotations.AconfigFlagAccessor
@UnsupportedAppUsage
boolean enabledRw();
}"#;
@@ -888,31 +925,37 @@
/** @hide */
public final class FeatureFlagsImpl implements FeatureFlags {
@Override
+ @com.android.aconfig.annotations.AconfigFlagAccessor
@UnsupportedAppUsage
public boolean disabledRo() {
return false;
}
@Override
+ @com.android.aconfig.annotations.AconfigFlagAccessor
@UnsupportedAppUsage
public boolean disabledRw() {
return false;
}
@Override
+ @com.android.aconfig.annotations.AconfigFlagAccessor
@UnsupportedAppUsage
public boolean disabledRwInOtherNamespace() {
return false;
}
@Override
+ @com.android.aconfig.annotations.AconfigFlagAccessor
@UnsupportedAppUsage
public boolean enabledFixedRo() {
return true;
}
@Override
+ @com.android.aconfig.annotations.AconfigFlagAccessor
@UnsupportedAppUsage
public boolean enabledRo() {
return true;
}
@Override
+ @com.android.aconfig.annotations.AconfigFlagAccessor
@UnsupportedAppUsage
public boolean enabledRw() {
return true;
@@ -938,33 +981,38 @@
public static final String FLAG_ENABLED_RO = "com.android.aconfig.test.enabled_ro";
/** @hide */
public static final String FLAG_ENABLED_RW = "com.android.aconfig.test.enabled_rw";
-
@com.android.aconfig.annotations.AssumeFalseForR8
+ @com.android.aconfig.annotations.AconfigFlagAccessor
@UnsupportedAppUsage
public static boolean disabledRo() {
return FEATURE_FLAGS.disabledRo();
}
@com.android.aconfig.annotations.AssumeFalseForR8
+ @com.android.aconfig.annotations.AconfigFlagAccessor
@UnsupportedAppUsage
public static boolean disabledRw() {
return FEATURE_FLAGS.disabledRw();
}
@com.android.aconfig.annotations.AssumeFalseForR8
+ @com.android.aconfig.annotations.AconfigFlagAccessor
@UnsupportedAppUsage
public static boolean disabledRwInOtherNamespace() {
return FEATURE_FLAGS.disabledRwInOtherNamespace();
}
@com.android.aconfig.annotations.AssumeTrueForR8
+ @com.android.aconfig.annotations.AconfigFlagAccessor
@UnsupportedAppUsage
public static boolean enabledFixedRo() {
return FEATURE_FLAGS.enabledFixedRo();
}
@com.android.aconfig.annotations.AssumeTrueForR8
+ @com.android.aconfig.annotations.AconfigFlagAccessor
@UnsupportedAppUsage
public static boolean enabledRo() {
return FEATURE_FLAGS.enabledRo();
}
@com.android.aconfig.annotations.AssumeTrueForR8
+ @com.android.aconfig.annotations.AconfigFlagAccessor
@UnsupportedAppUsage
public static boolean enabledRw() {
return FEATURE_FLAGS.enabledRw();
diff --git a/tools/aconfig/aconfig/src/storage/flag_table.rs b/tools/aconfig/aconfig/src/storage/flag_table.rs
index 401379b..b339821 100644
--- a/tools/aconfig/aconfig/src/storage/flag_table.rs
+++ b/tools/aconfig/aconfig/src/storage/flag_table.rs
@@ -16,8 +16,10 @@
use crate::commands::assign_flag_ids;
use crate::storage::FlagPackage;
+use aconfig_protos::ProtoFlagPermission;
use aconfig_storage_file::{
- get_table_size, FlagTable, FlagTableHeader, FlagTableNode, StorageFileType, FILE_VERSION,
+ get_table_size, FlagTable, FlagTableHeader, FlagTableNode, StorageFileType, StoredFlagType,
+ FILE_VERSION,
};
use anyhow::{anyhow, Result};
@@ -45,7 +47,7 @@
fn new(
package_id: u32,
flag_name: &str,
- flag_type: u16,
+ flag_type: StoredFlagType,
flag_id: u16,
num_buckets: u32,
) -> Self {
@@ -70,11 +72,14 @@
let fid = flag_ids
.get(pf.name())
.ok_or(anyhow!(format!("missing flag id for {}", pf.name())))?;
- // all flags are boolean value at the moment, thus using the last bit.
- // When more flag value types are supported, flag value type information
- // should come from the parsed flag, and we will set the flag_type bit
- // mask properly.
- let flag_type = 1;
+ let flag_type = if pf.is_fixed_read_only() {
+ StoredFlagType::FixedReadOnlyBoolean
+ } else {
+ match pf.permission() {
+ ProtoFlagPermission::READ_WRITE => StoredFlagType::ReadWriteBoolean,
+ ProtoFlagPermission::READ_ONLY => StoredFlagType::ReadOnlyBoolean,
+ }
+ };
Ok(Self::new(package.package_id, pf.name(), flag_type, *fid, num_buckets))
})
.collect::<Result<Vec<_>>>()
@@ -136,79 +141,18 @@
use super::*;
use crate::storage::{group_flags_by_package, tests::parse_all_test_flags};
- // create test baseline, syntactic sugar
- fn new_expected_node(
- package_id: u32,
- flag_name: &str,
- flag_type: u16,
- flag_id: u16,
- next_offset: Option<u32>,
- ) -> FlagTableNode {
- FlagTableNode {
- package_id,
- flag_name: flag_name.to_string(),
- flag_type,
- flag_id,
- next_offset,
- }
- }
-
- fn create_test_flag_table() -> Result<FlagTable> {
+ fn create_test_flag_table_from_source() -> Result<FlagTable> {
let caches = parse_all_test_flags();
let packages = group_flags_by_package(caches.iter());
- create_flag_table("system", &packages)
+ create_flag_table("mockup", &packages)
}
#[test]
// this test point locks down the table creation and each field
fn test_table_contents() {
- let flag_table = create_test_flag_table();
+ let flag_table = create_test_flag_table_from_source();
assert!(flag_table.is_ok());
-
- let header: &FlagTableHeader = &flag_table.as_ref().unwrap().header;
- let expected_header = FlagTableHeader {
- version: FILE_VERSION,
- container: String::from("system"),
- file_type: StorageFileType::FlagMap as u8,
- file_size: 321,
- num_flags: 8,
- bucket_offset: 31,
- node_offset: 99,
- };
- assert_eq!(header, &expected_header);
-
- let buckets: &Vec<Option<u32>> = &flag_table.as_ref().unwrap().buckets;
- let expected_bucket: Vec<Option<u32>> = vec![
- Some(99),
- Some(125),
- None,
- None,
- None,
- Some(178),
- None,
- Some(204),
- None,
- Some(262),
- None,
- None,
- None,
- None,
- None,
- Some(294),
- None,
- ];
- assert_eq!(buckets, &expected_bucket);
-
- let nodes: &Vec<FlagTableNode> = &flag_table.as_ref().unwrap().nodes;
- assert_eq!(nodes.len(), 8);
-
- assert_eq!(nodes[0], new_expected_node(0, "enabled_ro", 1, 1, None));
- assert_eq!(nodes[1], new_expected_node(0, "enabled_rw", 1, 2, Some(151)));
- assert_eq!(nodes[2], new_expected_node(1, "disabled_ro", 1, 0, None));
- assert_eq!(nodes[3], new_expected_node(2, "enabled_ro", 1, 1, None));
- assert_eq!(nodes[4], new_expected_node(1, "enabled_fixed_ro", 1, 1, Some(236)));
- assert_eq!(nodes[5], new_expected_node(1, "enabled_ro", 1, 2, None));
- assert_eq!(nodes[6], new_expected_node(2, "enabled_fixed_ro", 1, 0, None));
- assert_eq!(nodes[7], new_expected_node(0, "disabled_rw", 1, 0, None));
+ let expected_flag_table = aconfig_storage_file::test_utils::create_test_flag_table();
+ assert_eq!(flag_table.unwrap(), expected_flag_table);
}
}
diff --git a/tools/aconfig/aconfig/src/storage/flag_value.rs b/tools/aconfig/aconfig/src/storage/flag_value.rs
index c5cf215..a37ad9f 100644
--- a/tools/aconfig/aconfig/src/storage/flag_value.rs
+++ b/tools/aconfig/aconfig/src/storage/flag_value.rs
@@ -64,31 +64,19 @@
use super::*;
use crate::storage::{group_flags_by_package, tests::parse_all_test_flags};
- pub fn create_test_flag_value_list() -> Result<FlagValueList> {
+ pub fn create_test_flag_value_list_from_source() -> Result<FlagValueList> {
let caches = parse_all_test_flags();
let packages = group_flags_by_package(caches.iter());
- create_flag_value("system", &packages)
+ create_flag_value("mockup", &packages)
}
#[test]
// this test point locks down the flag value creation and each field
fn test_list_contents() {
- let flag_value_list = create_test_flag_value_list();
+ let flag_value_list = create_test_flag_value_list_from_source();
assert!(flag_value_list.is_ok());
-
- let header: &FlagValueHeader = &flag_value_list.as_ref().unwrap().header;
- let expected_header = FlagValueHeader {
- version: FILE_VERSION,
- container: String::from("system"),
- file_type: StorageFileType::FlagVal as u8,
- file_size: 35,
- num_flags: 8,
- boolean_value_offset: 27,
- };
- assert_eq!(header, &expected_header);
-
- let booleans: &Vec<bool> = &flag_value_list.as_ref().unwrap().booleans;
- let expected_booleans: Vec<bool> = vec![false; header.num_flags as usize];
- assert_eq!(booleans, &expected_booleans);
+ let expected_flag_value_list =
+ aconfig_storage_file::test_utils::create_test_flag_value_list();
+ assert_eq!(flag_value_list.unwrap(), expected_flag_value_list);
}
}
diff --git a/tools/aconfig/aconfig/src/storage/mod.rs b/tools/aconfig/aconfig/src/storage/mod.rs
index 11f1a43..30517de 100644
--- a/tools/aconfig/aconfig/src/storage/mod.rs
+++ b/tools/aconfig/aconfig/src/storage/mod.rs
@@ -122,30 +122,38 @@
"com.android.aconfig.storage.test_1",
"storage_test_1.aconfig",
include_bytes!("../../tests/storage_test_1.aconfig").as_slice(),
+ "storage_test_1.value",
+ include_bytes!("../../tests/storage_test_1.values").as_slice(),
),
(
"com.android.aconfig.storage.test_2",
"storage_test_2.aconfig",
include_bytes!("../../tests/storage_test_2.aconfig").as_slice(),
+ "storage_test_2.value",
+ include_bytes!("../../tests/storage_test_2.values").as_slice(),
),
(
"com.android.aconfig.storage.test_4",
"storage_test_4.aconfig",
include_bytes!("../../tests/storage_test_4.aconfig").as_slice(),
+ "storage_test_4.value",
+ include_bytes!("../../tests/storage_test_4.values").as_slice(),
),
];
-
aconfig_files
.into_iter()
- .map(|(pkg, file, content)| {
+ .map(|(pkg, aconfig_file, aconfig_content, value_file, value_content)| {
let bytes = crate::commands::parse_flags(
pkg,
Some("system"),
vec![Input {
- source: format!("tests/{}", file).to_string(),
- reader: Box::new(content),
+ source: format!("tests/{}", aconfig_file).to_string(),
+ reader: Box::new(aconfig_content),
}],
- vec![],
+ vec![Input {
+ source: format!("tests/{}", value_file).to_string(),
+ reader: Box::new(value_content),
+ }],
crate::commands::DEFAULT_FLAG_PERMISSION,
)
.unwrap();
diff --git a/tools/aconfig/aconfig/src/storage/package_table.rs b/tools/aconfig/aconfig/src/storage/package_table.rs
index 4e3d987..0a3df77 100644
--- a/tools/aconfig/aconfig/src/storage/package_table.rs
+++ b/tools/aconfig/aconfig/src/storage/package_table.rs
@@ -109,56 +109,18 @@
use super::*;
use crate::storage::{group_flags_by_package, tests::parse_all_test_flags};
- pub fn create_test_package_table() -> Result<PackageTable> {
+ pub fn create_test_package_table_from_source() -> Result<PackageTable> {
let caches = parse_all_test_flags();
let packages = group_flags_by_package(caches.iter());
- create_package_table("system", &packages)
+ create_package_table("mockup", &packages)
}
#[test]
// this test point locks down the table creation and each field
fn test_table_contents() {
- let package_table = create_test_package_table();
+ let package_table = create_test_package_table_from_source();
assert!(package_table.is_ok());
-
- let header: &PackageTableHeader = &package_table.as_ref().unwrap().header;
- let expected_header = PackageTableHeader {
- version: FILE_VERSION,
- container: String::from("system"),
- file_type: StorageFileType::PackageMap as u8,
- file_size: 209,
- num_packages: 3,
- bucket_offset: 31,
- node_offset: 59,
- };
- assert_eq!(header, &expected_header);
-
- let buckets: &Vec<Option<u32>> = &package_table.as_ref().unwrap().buckets;
- let expected: Vec<Option<u32>> = vec![Some(59), None, None, Some(109), None, None, None];
- assert_eq!(buckets, &expected);
-
- let nodes: &Vec<PackageTableNode> = &package_table.as_ref().unwrap().nodes;
- assert_eq!(nodes.len(), 3);
- let first_node_expected = PackageTableNode {
- package_name: String::from("com.android.aconfig.storage.test_2"),
- package_id: 1,
- boolean_offset: 3,
- next_offset: None,
- };
- assert_eq!(nodes[0], first_node_expected);
- let second_node_expected = PackageTableNode {
- package_name: String::from("com.android.aconfig.storage.test_1"),
- package_id: 0,
- boolean_offset: 0,
- next_offset: Some(159),
- };
- assert_eq!(nodes[1], second_node_expected);
- let third_node_expected = PackageTableNode {
- package_name: String::from("com.android.aconfig.storage.test_4"),
- package_id: 2,
- boolean_offset: 6,
- next_offset: None,
- };
- assert_eq!(nodes[2], third_node_expected);
+ let expected_package_table = aconfig_storage_file::test_utils::create_test_package_table();
+ assert_eq!(package_table.unwrap(), expected_package_table);
}
}
diff --git a/tools/aconfig/aconfig/templates/FeatureFlags.java.template b/tools/aconfig/aconfig/templates/FeatureFlags.java.template
index 13edcb4..38c8f13 100644
--- a/tools/aconfig/aconfig/templates/FeatureFlags.java.template
+++ b/tools/aconfig/aconfig/templates/FeatureFlags.java.template
@@ -14,6 +14,7 @@
{{ -endif- }}
{{ -endif }}
{{ -if not library_exported }}
+ @com.android.aconfig.annotations.AconfigFlagAccessor
@UnsupportedAppUsage
{{ -endif }}
boolean {item.method_name}();
diff --git a/tools/aconfig/aconfig/templates/FeatureFlagsImpl.java.template b/tools/aconfig/aconfig/templates/FeatureFlagsImpl.java.template
index 12b2fc1..6235e69 100644
--- a/tools/aconfig/aconfig/templates/FeatureFlagsImpl.java.template
+++ b/tools/aconfig/aconfig/templates/FeatureFlagsImpl.java.template
@@ -47,6 +47,7 @@
{{ -for flag in flag_elements }}
@Override
{{ -if not library_exported }}
+ @com.android.aconfig.annotations.AconfigFlagAccessor
@UnsupportedAppUsage
{{ -endif }}
public boolean {flag.method_name}() \{
@@ -68,6 +69,7 @@
{{ for flag in flag_elements }}
@Override
{{ -if not library_exported }}
+ @com.android.aconfig.annotations.AconfigFlagAccessor
@UnsupportedAppUsage
{{ -endif }}
public boolean {flag.method_name}() \{
diff --git a/tools/aconfig/aconfig/templates/Flags.java.template b/tools/aconfig/aconfig/templates/Flags.java.template
index e105991..e2f70b9 100644
--- a/tools/aconfig/aconfig/templates/Flags.java.template
+++ b/tools/aconfig/aconfig/templates/Flags.java.template
@@ -18,6 +18,7 @@
{{ -endif }}
{{ -endif }}
{{ -if not library_exported }}
+ @com.android.aconfig.annotations.AconfigFlagAccessor
@UnsupportedAppUsage
{{ -endif }}
public static boolean {item.method_name}() \{
diff --git a/tools/aconfig/aconfig/tests/storage_test_1.values b/tools/aconfig/aconfig/tests/storage_test_1.values
new file mode 100644
index 0000000..35548ae
--- /dev/null
+++ b/tools/aconfig/aconfig/tests/storage_test_1.values
@@ -0,0 +1,18 @@
+flag_value {
+ package: "com.android.aconfig.storage.test_1"
+ name: "enabled_rw"
+ state: ENABLED
+ permission: READ_WRITE
+}
+flag_value {
+ package: "com.android.aconfig.storage.test_1"
+ name: "disabled_rw"
+ state: DISABLED
+ permission: READ_WRITE
+}
+flag_value {
+ package: "com.android.aconfig.storage.test_1"
+ name: "enabled_ro"
+ state: ENABLED
+ permission: READ_ONLY
+}
diff --git a/tools/aconfig/aconfig/tests/storage_test_2.values b/tools/aconfig/aconfig/tests/storage_test_2.values
new file mode 100644
index 0000000..a7bb0b1
--- /dev/null
+++ b/tools/aconfig/aconfig/tests/storage_test_2.values
@@ -0,0 +1,18 @@
+flag_value {
+ package: "com.android.aconfig.storage.test_2"
+ name: "enabled_ro"
+ state: ENABLED
+ permission: READ_ONLY
+}
+flag_value {
+ package: "com.android.aconfig.storage.test_2"
+ name: "disabled_ro"
+ state: DISABLED
+ permission: READ_ONLY
+}
+flag_value {
+ package: "com.android.aconfig.storage.test_2"
+ name: "enabled_fixed_ro"
+ state: ENABLED
+ permission: READ_ONLY
+}
diff --git a/tools/aconfig/aconfig/tests/storage_test_4.values b/tools/aconfig/aconfig/tests/storage_test_4.values
new file mode 100644
index 0000000..fa21317
--- /dev/null
+++ b/tools/aconfig/aconfig/tests/storage_test_4.values
@@ -0,0 +1,12 @@
+flag_value {
+ package: "com.android.aconfig.storage.test_4"
+ name: "enabled_ro"
+ state: ENABLED
+ permission: READ_ONLY
+}
+flag_value {
+ package: "com.android.aconfig.storage.test_4"
+ name: "enabled_fixed_ro"
+ state: ENABLED
+ permission: READ_ONLY
+}
diff --git a/tools/aconfig/aconfig_storage_file/src/flag_info.rs b/tools/aconfig/aconfig_storage_file/src/flag_info.rs
index c67e70e..3fff263 100644
--- a/tools/aconfig/aconfig_storage_file/src/flag_info.rs
+++ b/tools/aconfig/aconfig_storage_file/src/flag_info.rs
@@ -130,6 +130,11 @@
let node = Self { attributes: read_u8_from_bytes(bytes, &mut head)? };
Ok(node)
}
+
+ /// Create flag info node
+ pub fn create(is_flag_rw: bool) -> Self {
+ Self { attributes: if is_flag_rw { FlagInfoBit::IsReadWrite as u8 } else { 0u8 } }
+ }
}
/// Flag info list struct
@@ -221,7 +226,7 @@
let bytes = &flag_info_list.into_bytes();
let mut head = 0;
let version = read_u32_from_bytes(bytes, &mut head).unwrap();
- assert_eq!(version, 1234)
+ assert_eq!(version, 1);
}
#[test]
diff --git a/tools/aconfig/aconfig_storage_file/src/flag_table.rs b/tools/aconfig/aconfig_storage_file/src/flag_table.rs
index 2e2b857..f41f4ce 100644
--- a/tools/aconfig/aconfig_storage_file/src/flag_table.rs
+++ b/tools/aconfig/aconfig_storage_file/src/flag_table.rs
@@ -21,7 +21,7 @@
get_bucket_index, read_str_from_bytes, read_u16_from_bytes, read_u32_from_bytes,
read_u8_from_bytes,
};
-use crate::{AconfigStorageError, StorageFileType};
+use crate::{AconfigStorageError, StorageFileType, StoredFlagType};
use anyhow::anyhow;
use std::fmt;
@@ -99,7 +99,7 @@
pub struct FlagTableNode {
pub package_id: u32,
pub flag_name: String,
- pub flag_type: u16,
+ pub flag_type: StoredFlagType,
pub flag_id: u16,
pub next_offset: Option<u32>,
}
@@ -109,7 +109,7 @@
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
writeln!(
f,
- "Package Id: {}, Flag: {}, Type: {}, Offset: {}, Next: {:?}",
+ "Package Id: {}, Flag: {}, Type: {:?}, Offset: {}, Next: {:?}",
self.package_id, self.flag_name, self.flag_type, self.flag_id, self.next_offset
)?;
Ok(())
@@ -124,7 +124,7 @@
let name_bytes = self.flag_name.as_bytes();
result.extend_from_slice(&(name_bytes.len() as u32).to_le_bytes());
result.extend_from_slice(name_bytes);
- result.extend_from_slice(&self.flag_type.to_le_bytes());
+ result.extend_from_slice(&(self.flag_type as u16).to_le_bytes());
result.extend_from_slice(&self.flag_id.to_le_bytes());
result.extend_from_slice(&self.next_offset.unwrap_or(0).to_le_bytes());
result
@@ -136,7 +136,7 @@
let node = Self {
package_id: read_u32_from_bytes(bytes, &mut head)?,
flag_name: read_str_from_bytes(bytes, &mut head)?,
- flag_type: read_u16_from_bytes(bytes, &mut head)?,
+ flag_type: StoredFlagType::try_from(read_u16_from_bytes(bytes, &mut head)?)?,
flag_id: read_u16_from_bytes(bytes, &mut head)?,
next_offset: match read_u32_from_bytes(bytes, &mut head)? {
0 => None,
@@ -251,7 +251,7 @@
let bytes = &flag_table.into_bytes();
let mut head = 0;
let version = read_u32_from_bytes(bytes, &mut head).unwrap();
- assert_eq!(version, 1234)
+ assert_eq!(version, 1);
}
#[test]
diff --git a/tools/aconfig/aconfig_storage_file/src/flag_value.rs b/tools/aconfig/aconfig_storage_file/src/flag_value.rs
index 40ccb34..506924b 100644
--- a/tools/aconfig/aconfig_storage_file/src/flag_value.rs
+++ b/tools/aconfig/aconfig_storage_file/src/flag_value.rs
@@ -158,7 +158,7 @@
let bytes = &flag_value_list.into_bytes();
let mut head = 0;
let version = read_u32_from_bytes(bytes, &mut head).unwrap();
- assert_eq!(version, 1234)
+ assert_eq!(version, 1);
}
#[test]
diff --git a/tools/aconfig/aconfig_storage_file/src/lib.rs b/tools/aconfig/aconfig_storage_file/src/lib.rs
index e7fda8a..d14bab6 100644
--- a/tools/aconfig/aconfig_storage_file/src/lib.rs
+++ b/tools/aconfig/aconfig_storage_file/src/lib.rs
@@ -37,11 +37,10 @@
pub mod flag_value;
pub mod package_table;
pub mod protos;
-
-#[cfg(test)]
-mod test_utils;
+pub mod test_utils;
use anyhow::anyhow;
+use std::cmp::Ordering;
use std::collections::hash_map::DefaultHasher;
use std::fs::File;
use std::hash::{Hash, Hasher};
@@ -52,7 +51,7 @@
pub use crate::flag_value::{FlagValueHeader, FlagValueList};
pub use crate::package_table::{PackageTable, PackageTableHeader, PackageTableNode};
-use crate::AconfigStorageError::{BytesParseFail, HashTableSizeLimit};
+use crate::AconfigStorageError::{BytesParseFail, HashTableSizeLimit, InvalidStoredFlagType};
/// Storage file version
pub const FILE_VERSION: u32 = 1;
@@ -83,7 +82,7 @@
"flag_val" => Ok(Self::FlagVal),
"flag_info" => Ok(Self::FlagInfo),
_ => Err(anyhow!(
- "Invalid storage file type, valid types are package_map|flag_map|flag_val"
+ "Invalid storage file type, valid types are package_map|flag_map|flag_val|flag_info"
)),
}
}
@@ -103,6 +102,68 @@
}
}
+/// Flag type enum as stored by storage file
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+pub enum StoredFlagType {
+ ReadWriteBoolean = 0,
+ ReadOnlyBoolean = 1,
+ FixedReadOnlyBoolean = 2,
+}
+
+impl TryFrom<u16> for StoredFlagType {
+ type Error = AconfigStorageError;
+
+ fn try_from(value: u16) -> Result<Self, Self::Error> {
+ match value {
+ x if x == Self::ReadWriteBoolean as u16 => Ok(Self::ReadWriteBoolean),
+ x if x == Self::ReadOnlyBoolean as u16 => Ok(Self::ReadOnlyBoolean),
+ x if x == Self::FixedReadOnlyBoolean as u16 => Ok(Self::FixedReadOnlyBoolean),
+ _ => Err(InvalidStoredFlagType(anyhow!("Invalid stored flag type"))),
+ }
+ }
+}
+
+/// Storage query api error
+#[non_exhaustive]
+#[derive(thiserror::Error, Debug)]
+pub enum AconfigStorageError {
+ #[error("failed to read the file")]
+ FileReadFail(#[source] anyhow::Error),
+
+ #[error("fail to parse protobuf")]
+ ProtobufParseFail(#[source] anyhow::Error),
+
+ #[error("storage files not found for this container")]
+ StorageFileNotFound(#[source] anyhow::Error),
+
+ #[error("fail to map storage file")]
+ MapFileFail(#[source] anyhow::Error),
+
+ #[error("fail to get mapped file")]
+ ObtainMappedFileFail(#[source] anyhow::Error),
+
+ #[error("fail to flush mapped storage file")]
+ MapFlushFail(#[source] anyhow::Error),
+
+ #[error("number of items in hash table exceed limit")]
+ HashTableSizeLimit(#[source] anyhow::Error),
+
+ #[error("failed to parse bytes into data")]
+ BytesParseFail(#[source] anyhow::Error),
+
+ #[error("cannot parse storage files with a higher version")]
+ HigherStorageFileVersion(#[source] anyhow::Error),
+
+ #[error("invalid storage file byte offset")]
+ InvalidStorageFileOffset(#[source] anyhow::Error),
+
+ #[error("failed to create file")]
+ FileCreationFail(#[source] anyhow::Error),
+
+ #[error("invalid stored flag type")]
+ InvalidStoredFlagType(#[source] anyhow::Error),
+}
+
/// Get the right hash table size given number of entries in the table. Use a
/// load factor of 0.5 for performance.
pub fn get_table_size(entries: u32) -> Result<u32, AconfigStorageError> {
@@ -165,44 +226,6 @@
Ok(val)
}
-/// Storage query api error
-#[non_exhaustive]
-#[derive(thiserror::Error, Debug)]
-pub enum AconfigStorageError {
- #[error("failed to read the file")]
- FileReadFail(#[source] anyhow::Error),
-
- #[error("fail to parse protobuf")]
- ProtobufParseFail(#[source] anyhow::Error),
-
- #[error("storage files not found for this container")]
- StorageFileNotFound(#[source] anyhow::Error),
-
- #[error("fail to map storage file")]
- MapFileFail(#[source] anyhow::Error),
-
- #[error("fail to get mapped file")]
- ObtainMappedFileFail(#[source] anyhow::Error),
-
- #[error("fail to flush mapped storage file")]
- MapFlushFail(#[source] anyhow::Error),
-
- #[error("number of items in hash table exceed limit")]
- HashTableSizeLimit(#[source] anyhow::Error),
-
- #[error("failed to parse bytes into data")]
- BytesParseFail(#[source] anyhow::Error),
-
- #[error("cannot parse storage files with a higher version")]
- HigherStorageFileVersion(#[source] anyhow::Error),
-
- #[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| {
@@ -211,7 +234,7 @@
let mut buffer = Vec::new();
file.read_to_end(&mut buffer).map_err(|errmsg| {
AconfigStorageError::FileReadFail(anyhow!(
- "Failed to read 4 bytes from file {}: {}",
+ "Failed to read bytes from file {}: {}",
file_path,
errmsg
))
@@ -224,7 +247,7 @@
package_map: &str,
flag_map: &str,
flag_val: &str,
-) -> Result<Vec<(String, String, bool)>, AconfigStorageError> {
+) -> Result<Vec<(String, String, StoredFlagType, 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)?)?;
@@ -239,10 +262,18 @@
let (package_name, package_offset) = package_info[node.package_id as usize];
let flag_offset = package_offset + node.flag_id as u32;
let flag_value = flag_value_list.booleans[flag_offset as usize];
- flags.push((String::from(package_name), node.flag_name.clone(), flag_value));
+ flags.push((
+ String::from(package_name),
+ node.flag_name.clone(),
+ node.flag_type,
+ flag_value,
+ ));
}
- flags.sort_by(|v1, v2| v1.0.cmp(&v2.0));
+ flags.sort_by(|v1, v2| match v1.0.cmp(&v2.0) {
+ Ordering::Equal => v1.1.cmp(&v2.1),
+ other => other,
+ });
Ok(flags)
}
@@ -270,29 +301,53 @@
let flags =
list_flags(&package_table_path, &flag_table_path, &flag_value_list_path).unwrap();
let expected = [
- (String::from("com.android.aconfig.storage.test_1"), String::from("enabled_ro"), true),
- (String::from("com.android.aconfig.storage.test_1"), String::from("enabled_rw"), false),
(
String::from("com.android.aconfig.storage.test_1"),
String::from("disabled_rw"),
+ StoredFlagType::ReadWriteBoolean,
false,
),
(
+ String::from("com.android.aconfig.storage.test_1"),
+ String::from("enabled_ro"),
+ StoredFlagType::ReadOnlyBoolean,
+ true,
+ ),
+ (
+ String::from("com.android.aconfig.storage.test_1"),
+ String::from("enabled_rw"),
+ StoredFlagType::ReadWriteBoolean,
+ true,
+ ),
+ (
String::from("com.android.aconfig.storage.test_2"),
String::from("disabled_ro"),
+ StoredFlagType::ReadOnlyBoolean,
false,
),
(
String::from("com.android.aconfig.storage.test_2"),
String::from("enabled_fixed_ro"),
+ StoredFlagType::FixedReadOnlyBoolean,
true,
),
- (String::from("com.android.aconfig.storage.test_2"), String::from("enabled_ro"), true),
- (String::from("com.android.aconfig.storage.test_4"), String::from("enabled_ro"), true),
+ (
+ String::from("com.android.aconfig.storage.test_2"),
+ String::from("enabled_ro"),
+ StoredFlagType::ReadOnlyBoolean,
+ true,
+ ),
(
String::from("com.android.aconfig.storage.test_4"),
String::from("enabled_fixed_ro"),
- false,
+ StoredFlagType::FixedReadOnlyBoolean,
+ true,
+ ),
+ (
+ String::from("com.android.aconfig.storage.test_4"),
+ String::from("enabled_ro"),
+ StoredFlagType::ReadOnlyBoolean,
+ 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
index 12e0024..b686274 100644
--- a/tools/aconfig/aconfig_storage_file/src/main.rs
+++ b/tools/aconfig/aconfig_storage_file/src/main.rs
@@ -88,8 +88,8 @@
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);
+ for (package_name, flag_name, flag_type, flag_value) in flags.iter() {
+ println!("{} {} {:?} {}", package_name, flag_name, flag_type, flag_value);
}
}
_ => unreachable!(),
diff --git a/tools/aconfig/aconfig_storage_file/src/package_table.rs b/tools/aconfig/aconfig_storage_file/src/package_table.rs
index e377115..36b0493 100644
--- a/tools/aconfig/aconfig_storage_file/src/package_table.rs
+++ b/tools/aconfig/aconfig_storage_file/src/package_table.rs
@@ -250,7 +250,7 @@
let bytes = &package_table.into_bytes();
let mut head = 0;
let version = read_u32_from_bytes(bytes, &mut head).unwrap();
- assert_eq!(version, 1234)
+ assert_eq!(version, 1);
}
#[test]
diff --git a/tools/aconfig/aconfig_storage_file/src/test_utils.rs b/tools/aconfig/aconfig_storage_file/src/test_utils.rs
index 4641829..c0f647a 100644
--- a/tools/aconfig/aconfig_storage_file/src/test_utils.rs
+++ b/tools/aconfig/aconfig_storage_file/src/test_utils.rs
@@ -18,16 +18,16 @@
use crate::flag_table::{FlagTable, FlagTableHeader, FlagTableNode};
use crate::flag_value::{FlagValueHeader, FlagValueList};
use crate::package_table::{PackageTable, PackageTableHeader, PackageTableNode};
-use crate::{AconfigStorageError, StorageFileType};
+use crate::{AconfigStorageError, StorageFileType, StoredFlagType};
use anyhow::anyhow;
use std::io::Write;
use tempfile::NamedTempFile;
-pub(crate) fn create_test_package_table() -> PackageTable {
+pub fn create_test_package_table() -> PackageTable {
let header = PackageTableHeader {
- version: 1234,
- container: String::from("system"),
+ version: 1,
+ container: String::from("mockup"),
file_type: StorageFileType::PackageMap as u8,
file_size: 209,
num_packages: 3,
@@ -66,14 +66,20 @@
flag_id: u16,
next_offset: Option<u32>,
) -> Self {
- Self { package_id, flag_name: flag_name.to_string(), flag_type, flag_id, next_offset }
+ Self {
+ package_id,
+ flag_name: flag_name.to_string(),
+ flag_type: StoredFlagType::try_from(flag_type).unwrap(),
+ flag_id,
+ next_offset,
+ }
}
}
-pub(crate) fn create_test_flag_table() -> FlagTable {
+pub fn create_test_flag_table() -> FlagTable {
let header = FlagTableHeader {
- version: 1234,
- container: String::from("system"),
+ version: 1,
+ container: String::from("mockup"),
file_type: StorageFileType::FlagMap as u8,
file_size: 321,
num_flags: 8,
@@ -101,44 +107,45 @@
];
let nodes = vec![
FlagTableNode::new_expected(0, "enabled_ro", 1, 1, None),
- FlagTableNode::new_expected(0, "enabled_rw", 1, 2, Some(151)),
+ FlagTableNode::new_expected(0, "enabled_rw", 0, 2, Some(151)),
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(236)),
+ FlagTableNode::new_expected(1, "enabled_fixed_ro", 2, 1, Some(236)),
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),
+ FlagTableNode::new_expected(2, "enabled_fixed_ro", 2, 0, None),
+ FlagTableNode::new_expected(0, "disabled_rw", 0, 0, None),
];
FlagTable { header, buckets, nodes }
}
-pub(crate) fn create_test_flag_value_list() -> FlagValueList {
+pub fn create_test_flag_value_list() -> FlagValueList {
let header = FlagValueHeader {
- version: 1234,
- container: String::from("system"),
+ version: 1,
+ container: String::from("mockup"),
file_type: StorageFileType::FlagVal as u8,
file_size: 35,
num_flags: 8,
boolean_value_offset: 27,
};
- let booleans: Vec<bool> = vec![false, true, false, false, true, true, false, true];
+ let booleans: Vec<bool> = vec![false, true, true, false, true, true, true, true];
FlagValueList { header, booleans }
}
-pub(crate) fn create_test_flag_info_list() -> FlagInfoList {
+pub fn create_test_flag_info_list() -> FlagInfoList {
let header = FlagInfoHeader {
- version: 1234,
- container: String::from("system"),
+ version: 1,
+ container: String::from("mockup"),
file_type: StorageFileType::FlagInfo as u8,
file_size: 35,
num_flags: 8,
boolean_flag_offset: 27,
};
- let nodes: Vec<FlagInfoNode> = vec![FlagInfoNode { attributes: 0 }; 8];
+ let is_flag_rw = [true, false, true, false, false, false, false, false];
+ let nodes = is_flag_rw.iter().map(|&rw| FlagInfoNode::create(rw)).collect();
FlagInfoList { header, nodes }
}
-pub(crate) fn write_bytes_to_temp_file(bytes: &[u8]) -> Result<NamedTempFile, AconfigStorageError> {
+pub 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"))
})?;
diff --git a/tools/aconfig/aconfig_storage_read_api/src/flag_table_query.rs b/tools/aconfig/aconfig_storage_read_api/src/flag_table_query.rs
index 4c19646..a251b41 100644
--- a/tools/aconfig/aconfig_storage_read_api/src/flag_table_query.rs
+++ b/tools/aconfig/aconfig_storage_read_api/src/flag_table_query.rs
@@ -65,66 +65,7 @@
#[cfg(test)]
mod tests {
use super::*;
- use aconfig_storage_file::{FlagTable, StorageFileType};
-
- // create test baseline, syntactic sugar
- fn new_expected_node(
- package_id: u32,
- flag_name: &str,
- flag_type: u16,
- flag_id: u16,
- next_offset: Option<u32>,
- ) -> FlagTableNode {
- FlagTableNode {
- 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: crate::FILE_VERSION,
- container: String::from("system"),
- file_type: StorageFileType::FlagMap as u8,
- file_size: 321,
- num_flags: 8,
- bucket_offset: 31,
- node_offset: 99,
- };
- let buckets: Vec<Option<u32>> = vec![
- Some(99),
- Some(125),
- None,
- None,
- None,
- Some(178),
- None,
- Some(204),
- None,
- Some(262),
- None,
- None,
- None,
- None,
- None,
- Some(294),
- None,
- ];
- let nodes = vec![
- new_expected_node(0, "enabled_ro", 1, 1, None),
- new_expected_node(0, "enabled_rw", 1, 2, Some(151)),
- new_expected_node(1, "disabled_ro", 1, 0, None),
- new_expected_node(2, "enabled_ro", 1, 1, None),
- new_expected_node(1, "enabled_fixed_ro", 1, 1, Some(236)),
- new_expected_node(1, "enabled_ro", 1, 2, None),
- new_expected_node(2, "enabled_fixed_ro", 1, 0, None),
- new_expected_node(0, "disabled_rw", 1, 0, None),
- ];
- FlagTable { header, buckets, nodes }
- }
+ use aconfig_storage_file::test_utils::create_test_flag_table;
#[test]
// this test point locks down table query
diff --git a/tools/aconfig/aconfig_storage_read_api/src/lib.rs b/tools/aconfig/aconfig_storage_read_api/src/lib.rs
index 8a71480..da64cb7 100644
--- a/tools/aconfig/aconfig_storage_read_api/src/lib.rs
+++ b/tools/aconfig/aconfig_storage_read_api/src/lib.rs
@@ -326,7 +326,7 @@
r#"
files {{
version: 0
- container: "system"
+ container: "mockup"
package_map: "{}"
flag_map: "{}"
flag_val: "{}"
@@ -347,7 +347,7 @@
let [_package_map, _flag_map, _flag_val, pb_file] = create_test_storage_files();
let pb_file_path = pb_file.path().display().to_string();
let package_mapped_file = unsafe {
- get_mapped_file(&pb_file_path, "system", StorageFileType::PackageMap).unwrap()
+ get_mapped_file(&pb_file_path, "mockup", StorageFileType::PackageMap).unwrap()
};
let package_offset =
@@ -378,7 +378,7 @@
let [_package_map, _flag_map, _flag_val, pb_file] = create_test_storage_files();
let pb_file_path = pb_file.path().display().to_string();
let flag_mapped_file =
- unsafe { get_mapped_file(&pb_file_path, "system", StorageFileType::FlagMap).unwrap() };
+ unsafe { get_mapped_file(&pb_file_path, "mockup", StorageFileType::FlagMap).unwrap() };
let baseline = vec![
(0, "enabled_ro", 1u16),
@@ -403,8 +403,8 @@
let [_package_map, _flag_map, _flag_val, pb_file] = create_test_storage_files();
let pb_file_path = pb_file.path().display().to_string();
let flag_value_file =
- unsafe { get_mapped_file(&pb_file_path, "system", StorageFileType::FlagVal).unwrap() };
- let baseline: Vec<bool> = vec![false; 8];
+ unsafe { get_mapped_file(&pb_file_path, "mockup", StorageFileType::FlagVal).unwrap() };
+ let baseline: Vec<bool> = vec![false, true, true, false, true, true, true, true];
for (offset, expected_value) in baseline.into_iter().enumerate() {
let flag_value = get_boolean_flag_value(&flag_value_file, offset as u32).unwrap();
assert_eq!(flag_value, expected_value);
diff --git a/tools/aconfig/aconfig_storage_read_api/src/package_table_query.rs b/tools/aconfig/aconfig_storage_read_api/src/package_table_query.rs
index 190de99..d83844e 100644
--- a/tools/aconfig/aconfig_storage_read_api/src/package_table_query.rs
+++ b/tools/aconfig/aconfig_storage_read_api/src/package_table_query.rs
@@ -72,40 +72,7 @@
#[cfg(test)]
mod tests {
use super::*;
- use aconfig_storage_file::{PackageTable, StorageFileType};
-
- pub fn create_test_package_table() -> PackageTable {
- let header = PackageTableHeader {
- version: crate::FILE_VERSION,
- container: String::from("system"),
- file_type: StorageFileType::PackageMap as u8,
- file_size: 209,
- num_packages: 3,
- bucket_offset: 31,
- node_offset: 59,
- };
- let buckets: Vec<Option<u32>> = vec![Some(59), None, None, Some(109), 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(159),
- };
- 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 aconfig_storage_file::test_utils::create_test_package_table;
#[test]
// this test point locks down table query
diff --git a/tools/aconfig/aconfig_storage_read_api/tests/flag.map b/tools/aconfig/aconfig_storage_read_api/tests/flag.map
index 5507894..d26e00f 100644
--- a/tools/aconfig/aconfig_storage_read_api/tests/flag.map
+++ b/tools/aconfig/aconfig_storage_read_api/tests/flag.map
Binary files differ
diff --git a/tools/aconfig/aconfig_storage_read_api/tests/flag.val b/tools/aconfig/aconfig_storage_read_api/tests/flag.val
index 75b8564..ed203d4 100644
--- a/tools/aconfig/aconfig_storage_read_api/tests/flag.val
+++ b/tools/aconfig/aconfig_storage_read_api/tests/flag.val
Binary files differ
diff --git a/tools/aconfig/aconfig_storage_read_api/tests/package.map b/tools/aconfig/aconfig_storage_read_api/tests/package.map
index 02267e5..6c46a03 100644
--- a/tools/aconfig/aconfig_storage_read_api/tests/package.map
+++ b/tools/aconfig/aconfig_storage_read_api/tests/package.map
Binary files differ
diff --git a/tools/aconfig/aconfig_storage_read_api/tests/storage_read_api_test.cpp b/tools/aconfig/aconfig_storage_read_api/tests/storage_read_api_test.cpp
index 1d36aae..539474b 100644
--- a/tools/aconfig/aconfig_storage_read_api/tests/storage_read_api_test.cpp
+++ b/tools/aconfig/aconfig_storage_read_api/tests/storage_read_api_test.cpp
@@ -52,7 +52,7 @@
auto proto = storage_files();
auto* info = proto.add_files();
info->set_version(0);
- info->set_container("system");
+ info->set_container("mockup");
info->set_package_map(package_map);
info->set_flag_map(flag_map);
info->set_flag_val(flag_val);
@@ -113,7 +113,7 @@
/// Test to lock down storage package offset query api
TEST_F(AconfigStorageTest, test_package_offset_query) {
auto mapped_file = private_api::get_mapped_file_impl(
- storage_record_pb, "system", api::StorageFileType::package_map);
+ storage_record_pb, "mockup", api::StorageFileType::package_map);
ASSERT_TRUE(mapped_file.ok());
auto offset = api::get_package_offset(
@@ -141,7 +141,7 @@
/// Test to lock down when querying none exist package
TEST_F(AconfigStorageTest, test_none_existent_package_offset_query) {
auto mapped_file = private_api::get_mapped_file_impl(
- storage_record_pb, "system", api::StorageFileType::package_map);
+ storage_record_pb, "mockup", api::StorageFileType::package_map);
ASSERT_TRUE(mapped_file.ok());
auto offset = api::get_package_offset(
@@ -153,7 +153,7 @@
/// Test to lock down storage flag offset query api
TEST_F(AconfigStorageTest, test_flag_offset_query) {
auto mapped_file = private_api::get_mapped_file_impl(
- storage_record_pb, "system", api::StorageFileType::flag_map);
+ storage_record_pb, "mockup", api::StorageFileType::flag_map);
ASSERT_TRUE(mapped_file.ok());
auto baseline = std::vector<std::tuple<int, std::string, int>>{
@@ -177,7 +177,7 @@
/// Test to lock down when querying none exist flag
TEST_F(AconfigStorageTest, test_none_existent_flag_offset_query) {
auto mapped_file = private_api::get_mapped_file_impl(
- storage_record_pb, "system", api::StorageFileType::flag_map);
+ storage_record_pb, "mockup", api::StorageFileType::flag_map);
ASSERT_TRUE(mapped_file.ok());
auto offset = api::get_flag_offset(*mapped_file, 0, "none_exist");
@@ -192,20 +192,22 @@
/// Test to lock down storage flag value query api
TEST_F(AconfigStorageTest, test_boolean_flag_value_query) {
auto mapped_file = private_api::get_mapped_file_impl(
- storage_record_pb, "system", api::StorageFileType::flag_val);
+ storage_record_pb, "mockup", api::StorageFileType::flag_val);
ASSERT_TRUE(mapped_file.ok());
+ auto expected_value = std::vector<bool>{
+ false, true, true, false, true, true, true, true};
for (int offset = 0; offset < 8; ++offset) {
auto value = api::get_boolean_flag_value(*mapped_file, offset);
ASSERT_TRUE(value.ok());
- ASSERT_FALSE(*value);
+ ASSERT_EQ(*value, expected_value[offset]);
}
}
/// Negative test to lock down the error when querying flag value out of range
TEST_F(AconfigStorageTest, test_invalid_boolean_flag_value_query) {
auto mapped_file = private_api::get_mapped_file_impl(
- storage_record_pb, "system", api::StorageFileType::flag_val);
+ storage_record_pb, "mockup", api::StorageFileType::flag_val);
ASSERT_TRUE(mapped_file.ok());
auto value = api::get_boolean_flag_value(*mapped_file, 8);
diff --git a/tools/aconfig/aconfig_storage_read_api/tests/storage_read_api_test.rs b/tools/aconfig/aconfig_storage_read_api/tests/storage_read_api_test.rs
index afcd5a7..7687d0f 100644
--- a/tools/aconfig/aconfig_storage_read_api/tests/storage_read_api_test.rs
+++ b/tools/aconfig/aconfig_storage_read_api/tests/storage_read_api_test.rs
@@ -24,7 +24,7 @@
r#"
files {{
version: 0
- container: "system"
+ container: "mockup"
package_map: "{}"
flag_map: "{}"
flag_val: "{}"
@@ -61,7 +61,7 @@
// SAFETY:
// The safety here is ensured as the test process will not write to temp storage file
let package_mapped_file = unsafe {
- get_mapped_file(&pb_file_path, "system", StorageFileType::PackageMap).unwrap()
+ get_mapped_file(&pb_file_path, "mockup", StorageFileType::PackageMap).unwrap()
};
let package_offset =
@@ -93,7 +93,7 @@
// SAFETY:
// The safety here is ensured as the test process will not write to temp storage file
let package_mapped_file = unsafe {
- get_mapped_file(&pb_file_path, "system", StorageFileType::PackageMap).unwrap()
+ get_mapped_file(&pb_file_path, "mockup", StorageFileType::PackageMap).unwrap()
};
let package_offset_option =
@@ -108,7 +108,7 @@
// SAFETY:
// The safety here is ensured as the test process will not write to temp storage file
let flag_mapped_file =
- unsafe { get_mapped_file(&pb_file_path, "system", StorageFileType::FlagMap).unwrap() };
+ unsafe { get_mapped_file(&pb_file_path, "mockup", StorageFileType::FlagMap).unwrap() };
let baseline = vec![
(0, "enabled_ro", 1u16),
@@ -134,7 +134,7 @@
// SAFETY:
// The safety here is ensured as the test process will not write to temp storage file
let flag_mapped_file =
- unsafe { get_mapped_file(&pb_file_path, "system", StorageFileType::FlagMap).unwrap() };
+ unsafe { get_mapped_file(&pb_file_path, "mockup", StorageFileType::FlagMap).unwrap() };
let flag_offset_option = get_flag_offset(&flag_mapped_file, 0, "none_exist").unwrap();
assert_eq!(flag_offset_option, None);
@@ -149,8 +149,8 @@
// SAFETY:
// The safety here is ensured as the test process will not write to temp storage file
let flag_value_file =
- unsafe { get_mapped_file(&pb_file_path, "system", StorageFileType::FlagVal).unwrap() };
- let baseline: Vec<bool> = vec![false; 8];
+ unsafe { get_mapped_file(&pb_file_path, "mockup", StorageFileType::FlagVal).unwrap() };
+ let baseline: Vec<bool> = vec![false, true, true, false, true, true, true, true];
for (offset, expected_value) in baseline.into_iter().enumerate() {
let flag_value = get_boolean_flag_value(&flag_value_file, offset as u32).unwrap();
assert_eq!(flag_value, expected_value);
@@ -164,7 +164,7 @@
// SAFETY:
// The safety here is ensured as the test process will not write to temp storage file
let flag_value_file =
- unsafe { get_mapped_file(&pb_file_path, "system", StorageFileType::FlagVal).unwrap() };
+ unsafe { get_mapped_file(&pb_file_path, "mockup", StorageFileType::FlagVal).unwrap() };
let err = get_boolean_flag_value(&flag_value_file, 8u32).unwrap_err();
assert_eq!(
format!("{:?}", err),
diff --git a/tools/aconfig/aconfig_storage_write_api/aconfig_storage_write_api.cpp b/tools/aconfig/aconfig_storage_write_api/aconfig_storage_write_api.cpp
index e863c0e..ea88f05 100644
--- a/tools/aconfig/aconfig_storage_write_api/aconfig_storage_write_api.cpp
+++ b/tools/aconfig/aconfig_storage_write_api/aconfig_storage_write_api.cpp
@@ -62,7 +62,7 @@
}
if ((file_stat.st_mode & (S_IWUSR | S_IWGRP | S_IWOTH)) == 0) {
- return ErrnoError() << "cannot map nonwriteable file";
+ return Error() << "cannot map nonwriteable file";
}
size_t file_size = file_stat.st_size;
@@ -126,4 +126,18 @@
return {};
}
+Result<void> create_flag_info(
+ std::string const& package_map,
+ std::string const& flag_map,
+ std::string const& flag_info_out) {
+ auto creation_cxx = create_flag_info_cxx(
+ rust::Str(package_map.c_str()),
+ rust::Str(flag_map.c_str()),
+ rust::Str(flag_info_out.c_str()));
+ if (creation_cxx.success) {
+ return {};
+ } else {
+ return android::base::Error() << creation_cxx.error_message;
+ }
+}
} // namespace aconfig_storage
diff --git a/tools/aconfig/aconfig_storage_write_api/include/aconfig_storage/aconfig_storage_write_api.hpp b/tools/aconfig/aconfig_storage_write_api/include/aconfig_storage/aconfig_storage_write_api.hpp
index 9e6332a..b652510 100644
--- a/tools/aconfig/aconfig_storage_write_api/include/aconfig_storage/aconfig_storage_write_api.hpp
+++ b/tools/aconfig/aconfig_storage_write_api/include/aconfig_storage/aconfig_storage_write_api.hpp
@@ -34,4 +34,13 @@
uint32_t offset,
bool value);
+/// Create flag info file based on package and flag map
+/// \input package_map: package map file
+/// \input flag_map: flag map file
+/// \input flag_info_out: flag info file to be created
+Result<void> create_flag_info(
+ std::string const& package_map,
+ std::string const& flag_map,
+ std::string const& flag_info_out);
+
} // namespace aconfig_storage
diff --git a/tools/aconfig/aconfig_storage_write_api/src/lib.rs b/tools/aconfig/aconfig_storage_write_api/src/lib.rs
index 5562d6a..678bbd5 100644
--- a/tools/aconfig/aconfig_storage_write_api/src/lib.rs
+++ b/tools/aconfig/aconfig_storage_write_api/src/lib.rs
@@ -23,10 +23,15 @@
#[cfg(test)]
mod test_utils;
-use aconfig_storage_file::AconfigStorageError;
+use aconfig_storage_file::{
+ AconfigStorageError, FlagInfoHeader, FlagInfoList, FlagInfoNode, FlagTable, PackageTable,
+ StorageFileType, StoredFlagType, FILE_VERSION,
+};
use anyhow::anyhow;
use memmap2::MmapMut;
+use std::fs::File;
+use std::io::{Read, Write};
/// Storage file location pb file
pub const STORAGE_LOCATION_FILE: &str = "/metadata/aconfig/persistent_storage_file_records.pb";
@@ -65,6 +70,86 @@
})
}
+/// Read in storage file as bytes
+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 bytes from file {}: {}",
+ file_path,
+ errmsg
+ ))
+ })?;
+ Ok(buffer)
+}
+
+/// Create flag info file given package map file and flag map file
+/// \input package_map: package map file
+/// \input flag_map: flag map file
+/// \output flag_info_out: created flag info file
+pub fn create_flag_info(
+ package_map: &str,
+ flag_map: &str,
+ flag_info_out: &str,
+) -> Result<(), 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)?)?;
+
+ if package_table.header.container != flag_table.header.container {
+ return Err(AconfigStorageError::FileCreationFail(anyhow!(
+ "container for package map {} and flag map {} does not match",
+ package_table.header.container,
+ flag_table.header.container,
+ )));
+ }
+
+ let mut package_offsets = vec![0; package_table.header.num_packages as usize];
+ for node in package_table.nodes.iter() {
+ package_offsets[node.package_id as usize] = node.boolean_offset;
+ }
+
+ let mut is_flag_rw = vec![false; flag_table.header.num_flags as usize];
+ for node in flag_table.nodes.iter() {
+ let flag_offset = package_offsets[node.package_id as usize] + node.flag_id as u32;
+ is_flag_rw[flag_offset as usize] = node.flag_type == StoredFlagType::ReadWriteBoolean;
+ }
+
+ let mut list = FlagInfoList {
+ header: FlagInfoHeader {
+ version: FILE_VERSION,
+ container: flag_table.header.container,
+ file_type: StorageFileType::FlagInfo as u8,
+ file_size: 0,
+ num_flags: flag_table.header.num_flags,
+ boolean_flag_offset: 0,
+ },
+ nodes: is_flag_rw.iter().map(|&rw| FlagInfoNode::create(rw)).collect(),
+ };
+
+ list.header.boolean_flag_offset = list.header.into_bytes().len() as u32;
+ list.header.file_size = list.into_bytes().len() as u32;
+
+ let mut file = File::create(flag_info_out).map_err(|errmsg| {
+ AconfigStorageError::FileCreationFail(anyhow!(
+ "fail to create file {}: {}",
+ flag_info_out,
+ errmsg
+ ))
+ })?;
+ file.write_all(&list.into_bytes()).map_err(|errmsg| {
+ AconfigStorageError::FileCreationFail(anyhow!(
+ "fail to write to file {}: {}",
+ flag_info_out,
+ errmsg
+ ))
+ })?;
+
+ Ok(())
+}
+
// *************************************** //
// CC INTERLOP
// *************************************** //
@@ -78,6 +163,12 @@
pub error_message: String,
}
+ // Flag info file creation return for cc interlop
+ pub struct FlagInfoCreationCXX {
+ pub success: bool,
+ pub error_message: String,
+ }
+
// Rust export to c++
extern "Rust" {
pub fn update_boolean_flag_value_cxx(
@@ -85,6 +176,12 @@
offset: u32,
value: bool,
) -> BooleanFlagValueUpdateCXX;
+
+ pub fn create_flag_info_cxx(
+ package_map: &str,
+ flag_map: &str,
+ flag_info_out: &str,
+ ) -> FlagInfoCreationCXX;
}
}
@@ -104,14 +201,33 @@
}
}
+/// Create flag info file cc interlop
+pub(crate) fn create_flag_info_cxx(
+ package_map: &str,
+ flag_map: &str,
+ flag_info_out: &str,
+) -> ffi::FlagInfoCreationCXX {
+ match create_flag_info(package_map, flag_map, flag_info_out) {
+ Ok(()) => ffi::FlagInfoCreationCXX { success: true, error_message: String::from("") },
+ Err(errmsg) => {
+ ffi::FlagInfoCreationCXX { success: false, error_message: format!("{:?}", errmsg) }
+ }
+ }
+}
+
#[cfg(test)]
mod tests {
use super::*;
use crate::test_utils::copy_to_temp_file;
use aconfig_storage_file::protos::storage_record_pb::write_proto_to_temp_file;
+ use aconfig_storage_file::test_utils::{
+ create_test_flag_info_list, create_test_flag_table, create_test_package_table,
+ write_bytes_to_temp_file,
+ };
use aconfig_storage_read_api::flag_value_query::find_boolean_flag_value;
use std::fs::File;
use std::io::Read;
+ use tempfile::NamedTempFile;
fn get_boolean_flag_value_at_offset(file: &str, offset: u32) -> bool {
let mut f = File::open(&file).unwrap();
@@ -156,4 +272,31 @@
}
}
}
+
+ fn create_empty_temp_file() -> Result<NamedTempFile, AconfigStorageError> {
+ let file = NamedTempFile::new().map_err(|_| {
+ AconfigStorageError::FileCreationFail(anyhow!("Failed to create temp file"))
+ })?;
+ Ok(file)
+ }
+
+ #[test]
+ // this test point locks down the flag info creation
+ fn test_create_flag_info() {
+ let package_table =
+ write_bytes_to_temp_file(&create_test_package_table().into_bytes()).unwrap();
+ let flag_table = write_bytes_to_temp_file(&create_test_flag_table().into_bytes()).unwrap();
+ let flag_info = create_empty_temp_file().unwrap();
+
+ let package_table_path = package_table.path().display().to_string();
+ let flag_table_path = flag_table.path().display().to_string();
+ let flag_info_path = flag_info.path().display().to_string();
+
+ assert!(create_flag_info(&package_table_path, &flag_table_path, &flag_info_path).is_ok());
+
+ let flag_info =
+ FlagInfoList::from_bytes(&read_file_to_bytes(&flag_info_path).unwrap()).unwrap();
+ let expected_flag_info = create_test_flag_info_list();
+ assert_eq!(flag_info, expected_flag_info);
+ }
}
diff --git a/tools/aconfig/aconfig_storage_write_api/tests/Android.bp b/tools/aconfig/aconfig_storage_write_api/tests/Android.bp
index d2a52fe..5b23dbc 100644
--- a/tools/aconfig/aconfig_storage_write_api/tests/Android.bp
+++ b/tools/aconfig/aconfig_storage_write_api/tests/Android.bp
@@ -39,4 +39,5 @@
"device-tests",
"general-tests",
],
+ ldflags: ["-Wl,--allow-multiple-definition"],
}
diff --git a/tools/aconfig/aconfig_storage_write_api/tests/flag.val b/tools/aconfig/aconfig_storage_write_api/tests/flag.val
index 75b8564..ed203d4 100644
--- a/tools/aconfig/aconfig_storage_write_api/tests/flag.val
+++ b/tools/aconfig/aconfig_storage_write_api/tests/flag.val
Binary files differ
diff --git a/tools/aconfig/aconfig_storage_write_api/tests/storage_write_api_test.cpp b/tools/aconfig/aconfig_storage_write_api/tests/storage_write_api_test.cpp
index 3a1c5de..00b737c 100644
--- a/tools/aconfig/aconfig_storage_write_api/tests/storage_write_api_test.cpp
+++ b/tools/aconfig/aconfig_storage_write_api/tests/storage_write_api_test.cpp
@@ -55,7 +55,7 @@
auto proto = storage_files();
auto* info = proto.add_files();
info->set_version(0);
- info->set_container("system");
+ info->set_container("mockup");
info->set_package_map("some_package.map");
info->set_flag_map("some_flag.map");
info->set_flag_val(flag_val);
@@ -97,15 +97,16 @@
TEST_F(AconfigStorageTest, test_non_writable_storage_file_mapping) {
ASSERT_TRUE(chmod(flag_val.c_str(), S_IRUSR | S_IRGRP | S_IROTH) != -1);
auto mapped_file_result = private_api::get_mapped_flag_value_file_impl(
- storage_record_pb, "system");
+ storage_record_pb, "mockup");
ASSERT_FALSE(mapped_file_result.ok());
- ASSERT_EQ(mapped_file_result.error().message(), "cannot map nonwriteable file");
+ auto it = mapped_file_result.error().message().find("cannot map nonwriteable file");
+ ASSERT_TRUE(it != std::string::npos) << mapped_file_result.error().message();
}
/// Test to lock down storage flag value update api
TEST_F(AconfigStorageTest, test_boolean_flag_value_update) {
auto mapped_file_result = private_api::get_mapped_flag_value_file_impl(
- storage_record_pb, "system");
+ storage_record_pb, "mockup");
ASSERT_TRUE(mapped_file_result.ok());
auto mapped_file = *mapped_file_result;
@@ -124,7 +125,7 @@
/// Negative test to lock down the error when querying flag value out of range
TEST_F(AconfigStorageTest, test_invalid_boolean_flag_value_update) {
auto mapped_file_result = private_api::get_mapped_flag_value_file_impl(
- storage_record_pb, "system");
+ storage_record_pb, "mockup");
ASSERT_TRUE(mapped_file_result.ok());
auto mapped_file = *mapped_file_result;
auto update_result = api::set_boolean_flag_value(mapped_file, 8, true);
diff --git a/tools/aconfig/aconfig_storage_write_api/tests/storage_write_api_test.rs b/tools/aconfig/aconfig_storage_write_api/tests/storage_write_api_test.rs
index f6c1bbc..4bda54c 100644
--- a/tools/aconfig/aconfig_storage_write_api/tests/storage_write_api_test.rs
+++ b/tools/aconfig/aconfig_storage_write_api/tests/storage_write_api_test.rs
@@ -15,7 +15,7 @@
r#"
files {{
version: 0
- container: "system"
+ container: "mockup"
package_map: "some_package_map"
flag_map: "some_flag_map"
flag_val: "{}"
@@ -59,7 +59,7 @@
// SAFETY:
// The safety here is ensured as only this single threaded test process will
// write to this file
- let mut file = unsafe { get_mapped_file(&record_pb_path, "system").unwrap() };
+ let mut file = unsafe { get_mapped_file(&record_pb_path, "mockup").unwrap() };
for i in 0..8 {
set_boolean_flag_value(&mut file, i, true).unwrap();
let value = get_boolean_flag_value_at_offset(&flag_value_path, i);
diff --git a/tools/aconfig/aflags/src/aconfig_storage_source.rs b/tools/aconfig/aflags/src/aconfig_storage_source.rs
index 1d73688..a3ca221 100644
--- a/tools/aconfig/aflags/src/aconfig_storage_source.rs
+++ b/tools/aconfig/aflags/src/aconfig_storage_source.rs
@@ -27,7 +27,7 @@
let container =
file_info.container.ok_or(anyhow!("storage file is missing container"))?;
- for (package, name, val) in
+ for (package, name, _flag_type, val) in
aconfig_storage_file::list_flags(&package_map, &flag_map, &flag_val)?
{
result.push(Flag {
diff --git a/tools/finalization/OWNERS b/tools/finalization/OWNERS
index 518b60d..b00b774 100644
--- a/tools/finalization/OWNERS
+++ b/tools/finalization/OWNERS
@@ -1,5 +1,7 @@
include platform/build/soong:/OWNERS
-smoreland@google.com
-alexbuy@google.com
+amhk@google.com
+gurpreetgs@google.com
+michaelwr@google.com
patb@google.com
+smoreland@google.com
zyy@google.com
diff --git a/tools/protos/metadata_file.proto b/tools/protos/metadata_file.proto
index 47562c5..5c89618 100644
--- a/tools/protos/metadata_file.proto
+++ b/tools/protos/metadata_file.proto
@@ -282,7 +282,7 @@
optional string element_id = 3;
}
-// Identifier for a third-package package.
+// Identifier for a third-party package.
// See go/tp-metadata-id.
message Identifier {
// The type of the identifier. Either an "ecosystem" value from
@@ -338,7 +338,19 @@
// - "PrebuiltByAlphabet": This type should be used for archives of primarily
// Google-owned source code (may contain non-Google-owned dependencies),
// which has been built using production Google infrastructure, and copied
- // into third_party.
+ // into Android. The "value" field is the URL of the prebuilt artifact or
+ // the relative path of the artifact to the root of a package.
+ // Example:
+ // identifier {
+ // type: "PrebuiltByAlphabet",
+ // version: "1",
+ // value: "v1/arm84_hdpi.apk",
+ // }
+ // identifier {
+ // type: "PrebuiltByAlphabet",
+ // version: "2",
+ // value: "v2/x86_64_xhdpi.apk",
+ // }
//
// - "LocalSource": The "value" field is the URL identifying where the local
// copy of the package source code can be found.
diff --git a/tools/releasetools/ota_from_target_files.py b/tools/releasetools/ota_from_target_files.py
index c0ff5d2..67438e6 100755
--- a/tools/releasetools/ota_from_target_files.py
+++ b/tools/releasetools/ota_from_target_files.py
@@ -872,6 +872,7 @@
target_info = common.BuildInfo(OPTIONS.info_dict, OPTIONS.oem_dicts)
if OPTIONS.disable_vabc and target_info.is_release_key:
raise ValueError("Disabling VABC on release-key builds is not supported.")
+
ValidateCompressionParam(target_info)
vabc_compression_param = target_info.vabc_compression_param
@@ -907,7 +908,6 @@
logger.info("Source build and target build use different compression methods {} vs {}, default to source builds parameter {}".format(
source_info.vabc_compression_param, target_info.vabc_compression_param, source_info.vabc_compression_param))
vabc_compression_param = source_info.vabc_compression_param
-
# Virtual AB Cow version 3 is introduced in Android U with improved memory
# and install time performance. All OTA's with
# both the source build and target build with VIRTUAL_AB_COW_VERSION = 3
@@ -918,6 +918,7 @@
elif source_info.vabc_cow_version != target_info.vabc_cow_version:
logger.info("Source and Target have different cow VABC_COW_VERSION specified, default to minimum version")
OPTIONS.vabc_cow_version = min(source_info.vabc_cow_version, target_info.vabc_cow_version)
+
# Virtual AB Compression was introduced in Androd S.
# Later, we backported VABC to Android R. But verity support was not
# backported, so if VABC is used and we are on Android R, disable
@@ -930,6 +931,19 @@
assert "ab_partitions" in OPTIONS.info_dict, \
"META/ab_partitions.txt is required for ab_update."
source_info = None
+ if not target_info.vabc_cow_version:
+ OPTIONS.vabc_cow_version = 2
+ elif target_info.vabc_cow_version >= "3" and target_info.vendor_api_level < 35:
+ logger.warning(
+ "This full OTA is configured to use VABC cow version"
+ " 3 which is supported since"
+ " Android API level 35, but device is "
+ "launched with {} . If this full OTA is"
+ " served to a device running old build, OTA might fail due to "
+ "unsupported vabc cow version. For safety, version 2 is used because "
+ "it's supported since day 1.".format(
+ target_info.vendor_api_level))
+ OPTIONS.vabc_cow_version = 2
if OPTIONS.vabc_compression_param is None and vabc_compression_param:
minimum_api_level_required = VABC_COMPRESSION_PARAM_SUPPORT[
vabc_compression_param]