Merge "Fix error in payload_signer_args passing" into main
diff --git a/Changes.md b/Changes.md
index fc15e60..9f2449c 100644
--- a/Changes.md
+++ b/Changes.md
@@ -43,14 +43,9 @@
The path set when running builds now makes the `python` executable point to python 3,
whereas on previous versions it pointed to python 2. If you still have python 2 scripts,
you can change the shebang line to use `python2` explicitly. This only applies for
-scripts run directly from makefiles, or from soong genrules. This behavior can be
-temporarily overridden by setting the `BUILD_BROKEN_PYTHON_IS_PYTHON2` environment
-variable to `true`. It's only an environment variable and not a product config variable
-because product config sometimes calls python code.
+scripts run directly from makefiles, or from soong genrules.
-In addition, `python_*` soong modules no longer allow python 2. This can be temporarily
-overridden by setting the `BUILD_BROKEN_USES_SOONG_PYTHON2_MODULES` product configuration
-variable to `true`.
+In addition, `python_*` soong modules no longer allow python 2.
Python 2 is slated for complete removal in V.
diff --git a/ci/build_test_suites.py b/ci/build_test_suites.py
index 402880c..933e43e 100644
--- a/ci/build_test_suites.py
+++ b/ci/build_test_suites.py
@@ -20,10 +20,8 @@
import logging
import os
import pathlib
-import re
import subprocess
import sys
-from typing import Callable
from build_context import BuildContext
import optimized_targets
@@ -70,7 +68,7 @@
return BuildPlan(set(self.args.extra_targets), set())
build_targets = set()
- packaging_functions = set()
+ packaging_commands = []
for target in self.args.extra_targets:
if self._unused_target_exclusion_enabled(
target
@@ -86,9 +84,9 @@
target, self.build_context, self.args
)
build_targets.update(target_optimizer.get_build_targets())
- packaging_functions.add(target_optimizer.package_outputs)
+ packaging_commands.extend(target_optimizer.get_package_outputs_commands())
- return BuildPlan(build_targets, packaging_functions)
+ return BuildPlan(build_targets, packaging_commands)
def _unused_target_exclusion_enabled(self, target: str) -> bool:
return (
@@ -100,7 +98,7 @@
@dataclass(frozen=True)
class BuildPlan:
build_targets: set[str]
- packaging_functions: set[Callable[..., None]]
+ packaging_commands: list[list[str]]
def build_test_suites(argv: list[str]) -> int:
@@ -182,8 +180,11 @@
except subprocess.CalledProcessError as e:
raise BuildFailureError(e.returncode) from e
- for packaging_function in build_plan.packaging_functions:
- packaging_function()
+ for packaging_command in build_plan.packaging_commands:
+ try:
+ run_command(packaging_command)
+ except subprocess.CalledProcessError as e:
+ raise BuildFailureError(e.returncode) from e
def get_top() -> pathlib.Path:
diff --git a/ci/build_test_suites_test.py b/ci/build_test_suites_test.py
index f3ff6f4..fd06a3a 100644
--- a/ci/build_test_suites_test.py
+++ b/ci/build_test_suites_test.py
@@ -241,17 +241,17 @@
class TestOptimizedBuildTarget(optimized_targets.OptimizedBuildTarget):
def __init__(
- self, target, build_context, args, output_targets, packaging_outputs
+ self, target, build_context, args, output_targets, packaging_commands
):
super().__init__(target, build_context, args)
self.output_targets = output_targets
- self.packaging_outputs = packaging_outputs
+ self.packaging_commands = packaging_commands
def get_build_targets_impl(self):
return self.output_targets
- def package_outputs_impl(self):
- self.packaging_outputs.add(f'packaging {" ".join(self.output_targets)}')
+ def get_package_outputs_commands_impl(self):
+ return self.packaging_commands
def get_enabled_flag(self):
return f'{self.target}_enabled'
@@ -276,7 +276,7 @@
build_plan = build_planner.create_build_plan()
- self.assertEqual(len(build_plan.packaging_functions), 0)
+ self.assertEqual(len(build_plan.packaging_commands), 0)
def test_build_optimization_on_optimizes_target(self):
build_targets = {'target_1', 'target_2'}
@@ -294,20 +294,19 @@
def test_build_optimization_on_packages_target(self):
build_targets = {'target_1', 'target_2'}
- packaging_outputs = set()
+ optimized_target_name = self.get_optimized_target_name('target_1')
+ packaging_commands = [[f'packaging {optimized_target_name}']]
build_planner = self.create_build_planner(
build_targets=build_targets,
build_context=self.create_build_context(
enabled_build_features=[{'name': self.get_target_flag('target_1')}]
),
- packaging_outputs=packaging_outputs,
+ packaging_commands=packaging_commands,
)
build_plan = build_planner.create_build_plan()
- self.run_packaging_functions(build_plan)
- optimized_target_name = self.get_optimized_target_name('target_1')
- self.assertIn(f'packaging {optimized_target_name}', packaging_outputs)
+ self.assertIn([f'packaging {optimized_target_name}'], build_plan.packaging_commands)
def test_individual_build_optimization_off_doesnt_optimize(self):
build_targets = {'target_1', 'target_2'}
@@ -321,16 +320,15 @@
def test_individual_build_optimization_off_doesnt_package(self):
build_targets = {'target_1', 'target_2'}
- packaging_outputs = set()
+ packaging_commands = [['packaging command']]
build_planner = self.create_build_planner(
build_targets=build_targets,
- packaging_outputs=packaging_outputs,
+ packaging_commands=packaging_commands,
)
build_plan = build_planner.create_build_plan()
- self.run_packaging_functions(build_plan)
- self.assertFalse(packaging_outputs)
+ self.assertFalse(build_plan.packaging_commands)
def test_target_output_used_target_built(self):
build_target = 'test_target'
@@ -408,7 +406,7 @@
target_optimizations: dict[
str, optimized_targets.OptimizedBuildTarget
] = None,
- packaging_outputs: set[str] = set(),
+ packaging_commands: list[list[str]] = [],
) -> build_test_suites.BuildPlanner:
if not build_context:
build_context = self.create_build_context()
@@ -418,7 +416,7 @@
target_optimizations = self.create_target_optimizations(
build_context,
build_targets,
- packaging_outputs,
+ packaging_commands,
)
return build_test_suites.BuildPlanner(
build_context, args, target_optimizations
@@ -450,14 +448,14 @@
self,
build_context: BuildContext,
build_targets: set[str],
- packaging_outputs: set[str] = set(),
+ packaging_commands: list[list[str]] = [],
):
target_optimizations = dict()
for target in build_targets:
target_optimizations[target] = functools.partial(
self.TestOptimizedBuildTarget,
output_targets={self.get_optimized_target_name(target)},
- packaging_outputs=packaging_outputs,
+ packaging_commands=packaging_commands,
)
return target_optimizations
@@ -468,10 +466,6 @@
def get_optimized_target_name(self, target: str):
return f'{target}_optimized'
- def run_packaging_functions(self, build_plan: build_test_suites.BuildPlan):
- for packaging_function in build_plan.packaging_functions:
- packaging_function()
-
def get_test_context(self, target: str):
return {
'testInfos': [
diff --git a/ci/optimized_targets.py b/ci/optimized_targets.py
index fddde17..9143cbf 100644
--- a/ci/optimized_targets.py
+++ b/ci/optimized_targets.py
@@ -52,14 +52,17 @@
self.modules_to_build = {self.target}
return {self.target}
- def package_outputs(self):
+ def get_package_outputs_commands(self) -> list[list[str]]:
features = self.build_context.enabled_build_features
if self.get_enabled_flag() in features:
- return self.package_outputs_impl()
+ return self.get_package_outputs_commands_impl()
- def package_outputs_impl(self):
+ return []
+
+ def get_package_outputs_commands_impl(self) -> list[list[str]]:
raise NotImplementedError(
- f'package_outputs_impl not implemented in {type(self).__name__}'
+ 'get_package_outputs_commands_impl not implemented in'
+ f' {type(self).__name__}'
)
def get_enabled_flag(self):
@@ -86,8 +89,8 @@
def get_build_targets(self):
return {self.target}
- def package_outputs(self):
- pass
+ def get_package_outputs_commands(self):
+ return []
class ChangeInfo:
@@ -114,6 +117,7 @@
return changed_files
+
class GeneralTestsOptimizer(OptimizedBuildTarget):
"""general-tests optimizer
diff --git a/core/Makefile b/core/Makefile
index 43495ed..f376014 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -6462,6 +6462,7 @@
$(INSTALLED_RAMDISK_TARGET) \
$(INSTALLED_DTBIMAGE_TARGET) \
$(INSTALLED_2NDBOOTLOADER_TARGET) \
+ $(INSTALLED_VENDOR_KERNEL_RAMDISK_TARGET) \
$(BUILT_RAMDISK_16K_TARGET) \
$(BUILT_KERNEL_16K_TARGET) \
$(BUILT_BOOTIMAGE_16K_TARGET) \
diff --git a/core/android_soong_config_vars.mk b/core/android_soong_config_vars.mk
index 5fc8fd4..48667ac 100644
--- a/core/android_soong_config_vars.mk
+++ b/core/android_soong_config_vars.mk
@@ -47,6 +47,8 @@
$(call soong_config_set_bool,ANDROID,CLANG_COVERAGE,$(CLANG_COVERAGE))
$(call soong_config_set,ANDROID,SCUDO_ALLOCATION_RING_BUFFER_SIZE,$(PRODUCT_SCUDO_ALLOCATION_RING_BUFFER_SIZE))
+$(call soong_config_set_bool,ANDROID,EMMA_INSTRUMENT,$(if $(filter true,$(EMMA_INSTRUMENT)),true,false))
+
# PRODUCT_PRECOMPILED_SEPOLICY defaults to true. Explicitly check if it's "false" or not.
$(call soong_config_set_bool,ANDROID,PRODUCT_PRECOMPILED_SEPOLICY,$(if $(filter false,$(PRODUCT_PRECOMPILED_SEPOLICY)),false,true))
diff --git a/core/config.mk b/core/config.mk
index 9cefd2c..192c8b2 100644
--- a/core/config.mk
+++ b/core/config.mk
@@ -173,6 +173,7 @@
$(KATI_obsolete_var BUILDING_PVMFW_IMAGE,BUILDING_PVMFW_IMAGE is no longer used)
$(KATI_obsolete_var BOARD_BUILD_SYSTEM_ROOT_IMAGE)
$(KATI_obsolete_var FS_GET_STATS)
+$(KATI_obsolete_var BUILD_BROKEN_USES_SOONG_PYTHON2_MODULES)
# Used to force goals to build. Only use for conditionally defined goals.
.PHONY: FORCE
@@ -363,8 +364,7 @@
# configs, generally for cross-cutting features.
# Build broken variables that should be treated as booleans
-_build_broken_bool_vars := \
- BUILD_BROKEN_USES_SOONG_PYTHON2_MODULES \
+_build_broken_bool_vars :=
# Build broken variables that should be treated as lists
_build_broken_list_vars := \
diff --git a/core/main.mk b/core/main.mk
index 5c280da..80ffec4 100644
--- a/core/main.mk
+++ b/core/main.mk
@@ -289,6 +289,9 @@
$(foreach mk,$(subdir_makefiles),$(info [$(call inc_and_print,subdir_makefiles_inc)/$(subdir_makefiles_total)] including $(mk) ...)$(eval include $(mk)))
+# Build bootloader.img/radio.img, and unpack the partitions.
+include $(BUILD_SYSTEM)/tasks/tools/update_bootloader_radio_image.mk
+
# For an unbundled image, we can skip blueprint_tools because unbundled image
# aims to remove a large number framework projects from the manifest, the
# sources or dependencies for these tools may be missing from the tree.
@@ -297,6 +300,9 @@
checkbuild: blueprint_tests
endif
+# Create necessary directories and symlinks in the root filesystem
+include system/core/rootdir/create_root_structure.mk
+
endif # dont_bother
ifndef subdir_makefiles_total
diff --git a/core/packaging/flags.mk b/core/packaging/flags.mk
index a77956b..4693bcd 100644
--- a/core/packaging/flags.mk
+++ b/core/packaging/flags.mk
@@ -18,7 +18,7 @@
#
# TODO: Should we do all of the images in $(IMAGES_TO_BUILD)?
-_FLAG_PARTITIONS := product system system_ext vendor
+_FLAG_PARTITIONS := product system vendor
# -----------------------------------------------------------------
@@ -28,7 +28,6 @@
# $(1): built aconfig flags file (out)
# $(2): installed aconfig flags file (out)
# $(3): the partition (in)
-# $(4): input aconfig files for the partition (in)
define generate-partition-aconfig-flag-file
$(eval $(strip $(1)): PRIVATE_OUT := $(strip $(1)))
$(eval $(strip $(1)): PRIVATE_IN := $(strip $(4)))
@@ -36,12 +35,14 @@
mkdir -p $$(dir $$(PRIVATE_OUT))
$$(if $$(PRIVATE_IN), \
$$(ACONFIG) dump --dedup --format protobuf --out $$(PRIVATE_OUT) \
- --filter container:$$(strip $(3)) $$(addprefix --cache ,$$(PRIVATE_IN)), \
+ --filter container:$(strip $(3)) \
+ $$(addprefix --cache ,$$(PRIVATE_IN)), \
echo -n > $$(PRIVATE_OUT) \
)
$(call copy-one-file, $(1), $(2))
endef
+
# Create a summary file of build flags for each partition
# $(1): built aconfig flags file (out)
# $(2): installed aconfig flags file (out)
@@ -59,16 +60,22 @@
$(call copy-one-file, $(1), $(2))
endef
-
$(foreach partition, $(_FLAG_PARTITIONS), \
$(eval aconfig_flag_summaries_protobuf.$(partition) := $(PRODUCT_OUT)/$(partition)/etc/aconfig_flags.pb) \
$(eval $(call generate-partition-aconfig-flag-file, \
- $(TARGET_OUT_FLAGS)/$(partition)/aconfig_flags.pb, \
- $(aconfig_flag_summaries_protobuf.$(partition)), \
- $(partition), \
- $(sort $(foreach m,$(call register-names-for-partition, $(partition)), \
+ $(TARGET_OUT_FLAGS)/$(partition)/aconfig_flags.pb, \
+ $(aconfig_flag_summaries_protobuf.$(partition)), \
+ $(partition), \
+ $(sort \
+ $(foreach m, $(call register-names-for-partition, $(partition)), \
$(ALL_MODULES.$(m).ACONFIG_FILES) \
- )), \
+ ) \
+ $(if $(filter system, $(partition)), \
+ $(foreach m, $(call register-names-for-partition, system_ext), \
+ $(ALL_MODULES.$(m).ACONFIG_FILES) \
+ ) \
+ ) \
+ ) \
)) \
)
@@ -175,4 +182,3 @@
$(eval aconfig_storage_flag_map.$(partition):=) \
$(eval aconfig_storage_flag_val.$(partition):=) \
)
-
diff --git a/core/soong_config.mk b/core/soong_config.mk
index a018c9b..1e6388a 100644
--- a/core/soong_config.mk
+++ b/core/soong_config.mk
@@ -236,6 +236,12 @@
$(call add_json_list, TargetFSConfigGen, $(TARGET_FS_CONFIG_GEN))
+# Although USE_SOONG_DEFINED_SYSTEM_IMAGE determines whether to use the system image specified by
+# PRODUCT_SOONG_DEFINED_SYSTEM_IMAGE, PRODUCT_SOONG_DEFINED_SYSTEM_IMAGE is still used to compare
+# installed files between make and soong, regardless of the USE_SOONG_DEFINED_SYSTEM_IMAGE setting.
+$(call add_json_bool, UseSoongSystemImage, $(filter true,$(USE_SOONG_DEFINED_SYSTEM_IMAGE)))
+$(call add_json_str, ProductSoongDefinedSystemImage, $(PRODUCT_SOONG_DEFINED_SYSTEM_IMAGE))
+
$(call add_json_map, VendorVars)
$(foreach namespace,$(sort $(SOONG_CONFIG_NAMESPACES)),\
$(call add_json_map, $(namespace))\
@@ -286,7 +292,6 @@
$(call add_json_bool, GenruleSandboxing, $(if $(GENRULE_SANDBOXING),$(filter true,$(GENRULE_SANDBOXING)),$(if $(filter true,$(BUILD_BROKEN_GENRULE_SANDBOXING)),,true)))
$(call add_json_bool, BuildBrokenEnforceSyspropOwner, $(filter true,$(BUILD_BROKEN_ENFORCE_SYSPROP_OWNER)))
$(call add_json_bool, BuildBrokenTrebleSyspropNeverallow, $(filter true,$(BUILD_BROKEN_TREBLE_SYSPROP_NEVERALLOW)))
-$(call add_json_bool, BuildBrokenUsesSoongPython2Modules, $(filter true,$(BUILD_BROKEN_USES_SOONG_PYTHON2_MODULES)))
$(call add_json_bool, BuildBrokenVendorPropertyNamespace, $(filter true,$(BUILD_BROKEN_VENDOR_PROPERTY_NAMESPACE)))
$(call add_json_bool, BuildBrokenIncorrectPartitionImages, $(filter true,$(BUILD_BROKEN_INCORRECT_PARTITION_IMAGES)))
$(call add_json_list, BuildBrokenInputDirModules, $(BUILD_BROKEN_INPUT_DIR_MODULES))
diff --git a/core/tasks/meta-lic.mk b/core/tasks/meta-lic.mk
index 24adfc8..620b1e2 100644
--- a/core/tasks/meta-lic.mk
+++ b/core/tasks/meta-lic.mk
@@ -225,3 +225,6 @@
# Moved here from hardware/libhardware_legacy/Android.mk
$(eval $(call declare-1p-copy-files,hardware/libhardware_legacy,))
+
+# Moved here from system/core/rootdir/Android.mk
+$(eval $(call declare-1p-copy-files,system/core/rootdir,))
diff --git a/core/tasks/sts-sdk.mk b/core/tasks/sts-sdk.mk
index b8ce5bf..4abbc29 100644
--- a/core/tasks/sts-sdk.mk
+++ b/core/tasks/sts-sdk.mk
@@ -28,8 +28,7 @@
rm -f $@ $(STS_SDK_ZIP)_filtered
$(ZIP2ZIP) -i $(STS_SDK_ZIP) -o $(STS_SDK_ZIP)_filtered \
-x android-sts-sdk/tools/sts-tradefed-tests.jar \
- 'android-sts-sdk/tools/*:plugin/src/main/resources/sts-tradefed-tools/' \
- 'android-sts-sdk/jdk/**/*:plugin/src/main/resources/jdk/'
+ 'android-sts-sdk/tools/*:sts-sdk/src/main/resources/sts-tradefed-tools/'
$(MERGE_ZIPS) $@ $(STS_SDK_ZIP)_filtered $(STS_SDK_PLUGIN_SKEL)
rm -f $(STS_SDK_ZIP)_filtered
diff --git a/core/tasks/tools/update_bootloader_radio_image.mk b/core/tasks/tools/update_bootloader_radio_image.mk
new file mode 100644
index 0000000..0ebf247
--- /dev/null
+++ b/core/tasks/tools/update_bootloader_radio_image.mk
@@ -0,0 +1,17 @@
+# 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.
+
+ifeq ($(USES_DEVICE_GOOGLE_ZUMA),true)
+ -include vendor/google_devices/zuma/prebuilts/misc_bins/update_bootloader_radio_image.mk
+endif
diff --git a/target/product/default_art_config.mk b/target/product/default_art_config.mk
index 1a3f2cf..61d7235 100644
--- a/target/product/default_art_config.mk
+++ b/target/product/default_art_config.mk
@@ -76,6 +76,7 @@
com.android.mediaprovider:framework-mediaprovider \
com.android.mediaprovider:framework-pdf \
com.android.mediaprovider:framework-pdf-v \
+ com.android.mediaprovider:framework-photopicker \
com.android.ondevicepersonalization:framework-ondevicepersonalization \
com.android.os.statsd:framework-statsd \
com.android.permission:framework-permission \
diff --git a/tools/aconfig/aconfig/src/codegen/java.rs b/tools/aconfig/aconfig/src/codegen/java.rs
index dbc4ab5..1ac58c1 100644
--- a/tools/aconfig/aconfig/src/codegen/java.rs
+++ b/tools/aconfig/aconfig/src/codegen/java.rs
@@ -745,10 +745,8 @@
boolean val;
try {
val = reader.getBooleanFlagValue(1);
- if (val == disabledRw) {
- Log.i(TAG, String.format(SUCCESS_LOG, "disabledRw"));
- } else {
- Log.i(TAG, String.format(MISMATCH_LOG, "disabledRw", val, disabledRw));
+ if (val != disabledRw) {
+ Log.w(TAG, String.format(MISMATCH_LOG, "disabledRw", val, disabledRw));
}
if (useNewStorageValueAndDiscardOld) {
@@ -756,10 +754,8 @@
}
val = reader.getBooleanFlagValue(2);
- if (val == disabledRwExported) {
- Log.i(TAG, String.format(SUCCESS_LOG, "disabledRwExported"));
- } else {
- Log.i(TAG, String.format(MISMATCH_LOG, "disabledRwExported", val, disabledRwExported));
+ if (val != disabledRwExported) {
+ Log.w(TAG, String.format(MISMATCH_LOG, "disabledRwExported", val, disabledRwExported));
}
if (useNewStorageValueAndDiscardOld) {
@@ -767,10 +763,8 @@
}
val = reader.getBooleanFlagValue(8);
- if (val == enabledRw) {
- Log.i(TAG, String.format(SUCCESS_LOG, "enabledRw"));
- } else {
- Log.i(TAG, String.format(MISMATCH_LOG, "enabledRw", val, enabledRw));
+ if (val != enabledRw) {
+ Log.w(TAG, String.format(MISMATCH_LOG, "enabledRw", val, enabledRw));
}
if (useNewStorageValueAndDiscardOld) {
@@ -804,10 +798,8 @@
boolean val;
try {
val = reader.getBooleanFlagValue(3);
- if (val == disabledRwInOtherNamespace) {
- Log.i(TAG, String.format(SUCCESS_LOG, "disabledRwInOtherNamespace"));
- } else {
- Log.i(TAG, String.format(MISMATCH_LOG, "disabledRwInOtherNamespace", val, disabledRwInOtherNamespace));
+ if (val != disabledRwInOtherNamespace) {
+ Log.w(TAG, String.format(MISMATCH_LOG, "disabledRwInOtherNamespace", val, disabledRwInOtherNamespace));
}
if (useNewStorageValueAndDiscardOld) {
diff --git a/tools/aconfig/aconfig/src/commands.rs b/tools/aconfig/aconfig/src/commands.rs
index 1a14f64..797a893 100644
--- a/tools/aconfig/aconfig/src/commands.rs
+++ b/tools/aconfig/aconfig/src/commands.rs
@@ -79,8 +79,18 @@
.read_to_string(&mut contents)
.with_context(|| format!("failed to read {}", input.source))?;
- let flag_declarations = aconfig_protos::flag_declarations::try_from_text_proto(&contents)
- .with_context(|| input.error_context())?;
+ let mut flag_declarations =
+ aconfig_protos::flag_declarations::try_from_text_proto(&contents)
+ .with_context(|| input.error_context())?;
+
+ // system_ext flags should be treated as system flags as we are combining /system_ext
+ // and /system as one container
+ // TODO: remove this logic when we start enforcing that system_ext cannot be set as
+ // container in aconfig declaration files.
+ if flag_declarations.container() == "system_ext" {
+ flag_declarations.set_container(String::from("system"));
+ }
+
ensure!(
package == flag_declarations.package(),
"failed to parse {}: expected package {}, got {}",
diff --git a/tools/aconfig/aconfig/templates/FeatureFlagsImpl.java.template b/tools/aconfig/aconfig/templates/FeatureFlagsImpl.java.template
index 9970b1f..bc01aa4 100644
--- a/tools/aconfig/aconfig/templates/FeatureFlagsImpl.java.template
+++ b/tools/aconfig/aconfig/templates/FeatureFlagsImpl.java.template
@@ -90,10 +90,8 @@
{{ -if flag.is_read_write }}
val = reader.getBooleanFlagValue({flag.flag_offset});
- if (val == {flag.method_name}) \{
- Log.i(TAG, String.format(SUCCESS_LOG, "{flag.method_name}"));
- } else \{
- Log.i(TAG, String.format(MISMATCH_LOG, "{flag.method_name}", val, {flag.method_name}));
+ if (val != {flag.method_name}) \{
+ Log.w(TAG, String.format(MISMATCH_LOG, "{flag.method_name}", val, {flag.method_name}));
}
if (useNewStorageValueAndDiscardOld) \{
diff --git a/tools/aconfig/aconfig_device_paths/Android.bp b/tools/aconfig/aconfig_device_paths/Android.bp
index 95cecf4..932dfbf 100644
--- a/tools/aconfig/aconfig_device_paths/Android.bp
+++ b/tools/aconfig/aconfig_device_paths/Android.bp
@@ -51,4 +51,8 @@
static_libs: [
"libaconfig_java_proto_nano",
],
+ sdk_version: "core_platform",
+ apex_available: [
+ "//apex_available:platform",
+ ],
}
diff --git a/tools/aconfig/aconfig_device_paths/src/DeviceProtosTemplate.java b/tools/aconfig/aconfig_device_paths/src/DeviceProtosTemplate.java
index 58c58de..4d41199 100644
--- a/tools/aconfig/aconfig_device_paths/src/DeviceProtosTemplate.java
+++ b/tools/aconfig/aconfig_device_paths/src/DeviceProtosTemplate.java
@@ -29,7 +29,7 @@
* @hide
*/
public class DeviceProtos {
- static final String[] PATHS = {
+ public static final String[] PATHS = {
TEMPLATE
};
@@ -50,10 +50,11 @@
ArrayList<parsed_flag> result = new ArrayList();
for (String path : parsedFlagsProtoPaths()) {
- FileInputStream inputStream = new FileInputStream(path);
- parsed_flags parsedFlags = parsed_flags.parseFrom(inputStream.readAllBytes());
- for (parsed_flag flag : parsedFlags.parsedFlag) {
- result.add(flag);
+ try (FileInputStream inputStream = new FileInputStream(path)) {
+ parsed_flags parsedFlags = parsed_flags.parseFrom(inputStream.readAllBytes());
+ for (parsed_flag flag : parsedFlags.parsedFlag) {
+ result.add(flag);
+ }
}
}
@@ -64,7 +65,7 @@
* Returns the list of all on-device aconfig protos paths.
* @hide
*/
- private static List<String> parsedFlagsProtoPaths() {
+ public static List<String> parsedFlagsProtoPaths() {
ArrayList<String> paths = new ArrayList(Arrays.asList(PATHS));
File apexDirectory = new File(APEX_DIR);
diff --git a/tools/aconfig/aconfig_flags/Android.bp b/tools/aconfig/aconfig_flags/Android.bp
new file mode 100644
index 0000000..e327ced
--- /dev/null
+++ b/tools/aconfig/aconfig_flags/Android.bp
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+
+rust_library {
+ name: "libaconfig_flags",
+ crate_name: "aconfig_flags",
+ srcs: [
+ "src/lib.rs",
+ ],
+ rustlibs: [
+ "libaconfig_flags_rust",
+ ],
+ host_supported: true,
+}
+
+aconfig_declarations {
+ name: "aconfig_flags",
+ package: "com.android.aconfig.flags",
+ container: "system",
+ srcs: ["flags.aconfig"],
+}
+
+rust_aconfig_library {
+ name: "libaconfig_flags_rust",
+ crate_name: "aconfig_flags_rust",
+ aconfig_declarations: "aconfig_flags",
+ host_supported: true,
+}
+
+cc_aconfig_library {
+ name: "libaconfig_flags_cc",
+ aconfig_declarations: "aconfig_flags",
+}
diff --git a/tools/aconfig/aconfig_flags/Cargo.toml b/tools/aconfig/aconfig_flags/Cargo.toml
new file mode 100644
index 0000000..6eb9f14
--- /dev/null
+++ b/tools/aconfig/aconfig_flags/Cargo.toml
@@ -0,0 +1,10 @@
+[package]
+name = "aconfig_flags"
+version = "0.1.0"
+edition = "2021"
+
+[features]
+default = ["cargo"]
+cargo = []
+
+[dependencies]
\ No newline at end of file
diff --git a/tools/aconfig/aconfig_flags/flags.aconfig b/tools/aconfig/aconfig_flags/flags.aconfig
new file mode 100644
index 0000000..db8b1b7
--- /dev/null
+++ b/tools/aconfig/aconfig_flags/flags.aconfig
@@ -0,0 +1,9 @@
+package: "com.android.aconfig.flags"
+container: "system"
+
+flag {
+ name: "enable_only_new_storage"
+ namespace: "core_experiments_team_internal"
+ bug: "312235596"
+ description: "When enabled, aconfig flags are read from the new aconfig storage only."
+}
diff --git a/tools/aconfig/aconfig_flags/src/lib.rs b/tools/aconfig/aconfig_flags/src/lib.rs
new file mode 100644
index 0000000..a607efb
--- /dev/null
+++ b/tools/aconfig/aconfig_flags/src/lib.rs
@@ -0,0 +1,47 @@
+/*
+ * 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_flags` is a crate for reading aconfig flags from Rust
+// When building with the Android tool-chain
+//
+// - the flag functions will read from aconfig_flags_inner
+// - the feature "cargo" will be disabled
+//
+// When building with cargo
+//
+// - the flag functions will all return some trivial value, like true
+// - the feature "cargo" will be enabled
+//
+// This module hides these differences from the rest of aconfig.
+
+/// Module used when building with the Android tool-chain
+#[cfg(not(feature = "cargo"))]
+pub mod auto_generated {
+ /// Returns the value for the enable_only_new_storage flag.
+ pub fn enable_only_new_storage() -> bool {
+ aconfig_flags_rust::enable_only_new_storage()
+ }
+}
+
+/// Module used when building with cargo
+#[cfg(feature = "cargo")]
+pub mod auto_generated {
+ /// Returns a placeholder value for the enable_only_new_storage flag.
+ pub fn enable_only_new_storage() -> bool {
+ // Used only to enable typechecking and testing with cargo
+ true
+ }
+}
diff --git a/tools/aconfig/aflags/Android.bp b/tools/aconfig/aflags/Android.bp
index c48585a..2040cc6 100644
--- a/tools/aconfig/aflags/Android.bp
+++ b/tools/aconfig/aflags/Android.bp
@@ -10,6 +10,7 @@
srcs: ["src/main.rs"],
rustlibs: [
"libaconfig_device_paths",
+ "libaconfig_flags",
"libaconfig_protos",
"libaconfigd_protos",
"libaconfig_storage_read_api",
@@ -24,6 +25,7 @@
rust_binary {
name: "aflags",
+ host_supported: true,
defaults: ["aflags.defaults"],
}
diff --git a/tools/aconfig/aflags/Cargo.toml b/tools/aconfig/aflags/Cargo.toml
index 7dc3436..7efce6d 100644
--- a/tools/aconfig/aflags/Cargo.toml
+++ b/tools/aconfig/aflags/Cargo.toml
@@ -15,3 +15,4 @@
aconfig_storage_read_api = { version = "0.1.0", path = "../aconfig_storage_read_api" }
clap = {version = "4.5.2" }
aconfig_device_paths = { version = "0.1.0", path = "../aconfig_device_paths" }
+aconfig_flags = { version = "0.1.0", path = "../aconfig_flags" }
\ No newline at end of file
diff --git a/tools/aconfig/aflags/src/aconfig_storage_source.rs b/tools/aconfig/aflags/src/aconfig_storage_source.rs
index b2fd3c9..68edf7d 100644
--- a/tools/aconfig/aflags/src/aconfig_storage_source.rs
+++ b/tools/aconfig/aflags/src/aconfig_storage_source.rs
@@ -1,3 +1,4 @@
+use crate::load_protos;
use crate::{Flag, FlagSource};
use crate::{FlagPermission, FlagValue, ValuePickedFrom};
use aconfigd_protos::{
@@ -9,13 +10,18 @@
use anyhow::Result;
use protobuf::Message;
use protobuf::SpecialFields;
+use std::collections::HashMap;
use std::io::{Read, Write};
use std::net::Shutdown;
use std::os::unix::net::UnixStream;
pub struct AconfigStorageSource {}
-fn convert(msg: ProtoFlagQueryReturnMessage) -> Result<Flag> {
+fn load_flag_to_container() -> Result<HashMap<String, String>> {
+ Ok(load_protos::load()?.into_iter().map(|p| (p.qualified_name(), p.container)).collect())
+}
+
+fn convert(msg: ProtoFlagQueryReturnMessage, containers: &HashMap<String, String>) -> Result<Flag> {
let (value, value_picked_from) = match (
&msg.boot_flag_value,
msg.default_flag_value,
@@ -55,15 +61,21 @@
None => return Err(anyhow!("missing permission")),
};
+ let name = msg.flag_name.ok_or(anyhow!("missing flag name"))?;
+ let package = msg.package_name.ok_or(anyhow!("missing package name"))?;
+ let qualified_name = format!("{package}.{name}");
Ok(Flag {
- name: msg.flag_name.ok_or(anyhow!("missing flag name"))?,
- package: msg.package_name.ok_or(anyhow!("missing package name"))?,
+ name,
+ package,
value,
permission,
value_picked_from,
staged_value,
- container: "-".to_string(),
-
+ container: containers
+ .get(&qualified_name)
+ .cloned()
+ .unwrap_or_else(|| "<no container>".to_string())
+ .to_string(),
// TODO: remove once DeviceConfig is not in the CLI.
namespace: "-".to_string(),
})
@@ -114,9 +126,13 @@
impl FlagSource for AconfigStorageSource {
fn list_flags() -> Result<Vec<Flag>> {
+ let containers = load_flag_to_container()?;
read_from_socket()
.map(|query_messages| {
- query_messages.iter().map(|message| convert(message.clone())).collect::<Vec<_>>()
+ query_messages
+ .iter()
+ .map(|message| convert(message.clone(), &containers))
+ .collect::<Vec<_>>()
})?
.into_iter()
.collect()
diff --git a/tools/aconfig/aflags/src/main.rs b/tools/aconfig/aflags/src/main.rs
index d8912a9..a726cc0 100644
--- a/tools/aconfig/aflags/src/main.rs
+++ b/tools/aconfig/aflags/src/main.rs
@@ -164,10 +164,6 @@
enum Command {
/// List all aconfig flags on this device.
List {
- /// Read from the new flag storage.
- #[clap(long)]
- use_new_storage: bool,
-
/// Optionally filter by container name.
#[clap(short = 'c', long = "container")]
container: Option<String>,
@@ -184,6 +180,9 @@
/// <package>.<flag_name>
qualified_name: String,
},
+
+ /// Display which flag storage backs aconfig flags.
+ WhichBacking,
}
struct PaddingInfo {
@@ -282,21 +281,31 @@
Ok(result)
}
+fn display_which_backing() -> String {
+ if aconfig_flags::auto_generated::enable_only_new_storage() {
+ "aconfig_storage".to_string()
+ } else {
+ "device_config".to_string()
+ }
+}
+
fn main() -> Result<()> {
ensure!(nix::unistd::Uid::current().is_root(), "must be root");
let cli = Cli::parse();
let output = match cli.command {
- Command::List { use_new_storage: true, container } => {
- list(FlagSourceType::AconfigStorage, container)
- .map_err(|err| anyhow!("storage may not be enabled: {err}"))
- .map(Some)
- }
- Command::List { use_new_storage: false, container } => {
- list(FlagSourceType::DeviceConfig, container).map(Some)
+ Command::List { container } => {
+ if aconfig_flags::auto_generated::enable_only_new_storage() {
+ list(FlagSourceType::AconfigStorage, container)
+ .map_err(|err| anyhow!("storage may not be enabled: {err}"))
+ .map(Some)
+ } else {
+ list(FlagSourceType::DeviceConfig, container).map(Some)
+ }
}
Command::Enable { qualified_name } => set_flag(&qualified_name, "true").map(|_| None),
Command::Disable { qualified_name } => set_flag(&qualified_name, "false").map(|_| None),
+ Command::WhichBacking => Ok(Some(display_which_backing())),
};
match output {
Ok(Some(text)) => println!("{text}"),
diff --git a/tools/aconfig/fake_device_config/src/android/util/Log.java b/tools/aconfig/fake_device_config/src/android/util/Log.java
index 3e7fd0f..79de680 100644
--- a/tools/aconfig/fake_device_config/src/android/util/Log.java
+++ b/tools/aconfig/fake_device_config/src/android/util/Log.java
@@ -5,6 +5,10 @@
return 0;
}
+ public static int w(String tag, String msg) {
+ return 0;
+ }
+
public static int e(String tag, String msg) {
return 0;
}