Make change and version bump to AP4A.240920.001
Snap for 12391343 from 3884d56713
to 24Q4-release
Change-Id: Iefe81b7715656b82a1962444d19b8137567400e4
This commit is contained in:
@@ -22,6 +22,7 @@ import os
|
|||||||
import pathlib
|
import pathlib
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
from typing import Callable
|
||||||
from build_context import BuildContext
|
from build_context import BuildContext
|
||||||
import optimized_targets
|
import optimized_targets
|
||||||
|
|
||||||
@@ -68,7 +69,7 @@ class BuildPlanner:
|
|||||||
return BuildPlan(set(self.args.extra_targets), set())
|
return BuildPlan(set(self.args.extra_targets), set())
|
||||||
|
|
||||||
build_targets = set()
|
build_targets = set()
|
||||||
packaging_commands = []
|
packaging_commands_getters = []
|
||||||
for target in self.args.extra_targets:
|
for target in self.args.extra_targets:
|
||||||
if self._unused_target_exclusion_enabled(
|
if self._unused_target_exclusion_enabled(
|
||||||
target
|
target
|
||||||
@@ -84,9 +85,11 @@ class BuildPlanner:
|
|||||||
target, self.build_context, self.args
|
target, self.build_context, self.args
|
||||||
)
|
)
|
||||||
build_targets.update(target_optimizer.get_build_targets())
|
build_targets.update(target_optimizer.get_build_targets())
|
||||||
packaging_commands.extend(target_optimizer.get_package_outputs_commands())
|
packaging_commands_getters.append(
|
||||||
|
target_optimizer.get_package_outputs_commands
|
||||||
|
)
|
||||||
|
|
||||||
return BuildPlan(build_targets, packaging_commands)
|
return BuildPlan(build_targets, packaging_commands_getters)
|
||||||
|
|
||||||
def _unused_target_exclusion_enabled(self, target: str) -> bool:
|
def _unused_target_exclusion_enabled(self, target: str) -> bool:
|
||||||
return (
|
return (
|
||||||
@@ -98,7 +101,7 @@ class BuildPlanner:
|
|||||||
@dataclass(frozen=True)
|
@dataclass(frozen=True)
|
||||||
class BuildPlan:
|
class BuildPlan:
|
||||||
build_targets: set[str]
|
build_targets: set[str]
|
||||||
packaging_commands: list[list[str]]
|
packaging_commands_getters: list[Callable[[], list[list[str]]]]
|
||||||
|
|
||||||
|
|
||||||
def build_test_suites(argv: list[str]) -> int:
|
def build_test_suites(argv: list[str]) -> int:
|
||||||
@@ -180,9 +183,10 @@ def execute_build_plan(build_plan: BuildPlan):
|
|||||||
except subprocess.CalledProcessError as e:
|
except subprocess.CalledProcessError as e:
|
||||||
raise BuildFailureError(e.returncode) from e
|
raise BuildFailureError(e.returncode) from e
|
||||||
|
|
||||||
for packaging_command in build_plan.packaging_commands:
|
for packaging_commands_getter in build_plan.packaging_commands_getters:
|
||||||
try:
|
try:
|
||||||
run_command(packaging_command)
|
for packaging_command in packaging_commands_getter():
|
||||||
|
run_command(packaging_command)
|
||||||
except subprocess.CalledProcessError as e:
|
except subprocess.CalledProcessError as e:
|
||||||
raise BuildFailureError(e.returncode) from e
|
raise BuildFailureError(e.returncode) from e
|
||||||
|
|
||||||
|
@@ -276,7 +276,8 @@ class BuildPlannerTest(unittest.TestCase):
|
|||||||
|
|
||||||
build_plan = build_planner.create_build_plan()
|
build_plan = build_planner.create_build_plan()
|
||||||
|
|
||||||
self.assertEqual(len(build_plan.packaging_commands), 0)
|
for packaging_command in self.run_packaging_commands(build_plan):
|
||||||
|
self.assertEqual(len(packaging_command), 0)
|
||||||
|
|
||||||
def test_build_optimization_on_optimizes_target(self):
|
def test_build_optimization_on_optimizes_target(self):
|
||||||
build_targets = {'target_1', 'target_2'}
|
build_targets = {'target_1', 'target_2'}
|
||||||
@@ -306,7 +307,7 @@ class BuildPlannerTest(unittest.TestCase):
|
|||||||
|
|
||||||
build_plan = build_planner.create_build_plan()
|
build_plan = build_planner.create_build_plan()
|
||||||
|
|
||||||
self.assertIn([f'packaging {optimized_target_name}'], build_plan.packaging_commands)
|
self.assertIn(packaging_commands, self.run_packaging_commands(build_plan))
|
||||||
|
|
||||||
def test_individual_build_optimization_off_doesnt_optimize(self):
|
def test_individual_build_optimization_off_doesnt_optimize(self):
|
||||||
build_targets = {'target_1', 'target_2'}
|
build_targets = {'target_1', 'target_2'}
|
||||||
@@ -328,7 +329,8 @@ class BuildPlannerTest(unittest.TestCase):
|
|||||||
|
|
||||||
build_plan = build_planner.create_build_plan()
|
build_plan = build_planner.create_build_plan()
|
||||||
|
|
||||||
self.assertFalse(build_plan.packaging_commands)
|
for packaging_command in self.run_packaging_commands(build_plan):
|
||||||
|
self.assertEqual(len(packaging_command), 0)
|
||||||
|
|
||||||
def test_target_output_used_target_built(self):
|
def test_target_output_used_target_built(self):
|
||||||
build_target = 'test_target'
|
build_target = 'test_target'
|
||||||
@@ -485,6 +487,12 @@ class BuildPlannerTest(unittest.TestCase):
|
|||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def run_packaging_commands(self, build_plan: build_test_suites.BuildPlan):
|
||||||
|
return [
|
||||||
|
packaging_command_getter()
|
||||||
|
for packaging_command_getter in build_plan.packaging_commands_getters
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
def wait_until(
|
def wait_until(
|
||||||
condition_function: Callable[[], bool],
|
condition_function: Callable[[], bool],
|
||||||
|
@@ -121,13 +121,13 @@ class OptimizedBuildTarget(ABC):
|
|||||||
process_result = subprocess.run(
|
process_result = subprocess.run(
|
||||||
args=[
|
args=[
|
||||||
f'{src_top / self._SOONG_UI_BASH_PATH}',
|
f'{src_top / self._SOONG_UI_BASH_PATH}',
|
||||||
'--dumpvar-mode',
|
'--dumpvars-mode',
|
||||||
'--abs',
|
f'--abs-vars={" ".join(soong_vars)}',
|
||||||
soong_vars,
|
|
||||||
],
|
],
|
||||||
env=os.environ,
|
env=os.environ,
|
||||||
check=False,
|
check=False,
|
||||||
capture_output=True,
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
)
|
)
|
||||||
if not process_result.returncode == 0:
|
if not process_result.returncode == 0:
|
||||||
logging.error('soong dumpvars command failed! stderr:')
|
logging.error('soong dumpvars command failed! stderr:')
|
||||||
@@ -142,7 +142,7 @@ class OptimizedBuildTarget(ABC):
|
|||||||
try:
|
try:
|
||||||
return {
|
return {
|
||||||
line.split('=')[0]: line.split('=')[1].strip("'")
|
line.split('=')[0]: line.split('=')[1].strip("'")
|
||||||
for line in process_result.stdout.split('\n')
|
for line in process_result.stdout.strip().split('\n')
|
||||||
}
|
}
|
||||||
except IndexError as e:
|
except IndexError as e:
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
@@ -214,10 +214,13 @@ class GeneralTestsOptimizer(OptimizedBuildTarget):
|
|||||||
normally built.
|
normally built.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# List of modules that are always required to be in general-tests.zip.
|
# List of modules that are built alongside general-tests as dependencies.
|
||||||
_REQUIRED_MODULES = frozenset(
|
_REQUIRED_MODULES = frozenset([
|
||||||
['cts-tradefed', 'vts-tradefed', 'compatibility-host-util']
|
'cts-tradefed',
|
||||||
)
|
'vts-tradefed',
|
||||||
|
'compatibility-host-util',
|
||||||
|
'general-tests-shared-libs',
|
||||||
|
])
|
||||||
|
|
||||||
def get_build_targets_impl(self) -> set[str]:
|
def get_build_targets_impl(self) -> set[str]:
|
||||||
change_info_file_path = os.environ.get('CHANGE_INFO')
|
change_info_file_path = os.environ.get('CHANGE_INFO')
|
||||||
@@ -286,6 +289,10 @@ class GeneralTestsOptimizer(OptimizedBuildTarget):
|
|||||||
host_config_files = []
|
host_config_files = []
|
||||||
target_config_files = []
|
target_config_files = []
|
||||||
for module in self.modules_to_build:
|
for module in self.modules_to_build:
|
||||||
|
# The required modules are handled separately, no need to package.
|
||||||
|
if module in self._REQUIRED_MODULES:
|
||||||
|
continue
|
||||||
|
|
||||||
host_path = host_out_testcases / module
|
host_path = host_out_testcases / module
|
||||||
if os.path.exists(host_path):
|
if os.path.exists(host_path):
|
||||||
host_paths.append(host_path)
|
host_paths.append(host_path)
|
||||||
@@ -303,6 +310,7 @@ class GeneralTestsOptimizer(OptimizedBuildTarget):
|
|||||||
|
|
||||||
zip_commands.extend(
|
zip_commands.extend(
|
||||||
self._get_zip_test_configs_zips_commands(
|
self._get_zip_test_configs_zips_commands(
|
||||||
|
src_top,
|
||||||
dist_dir,
|
dist_dir,
|
||||||
host_out,
|
host_out,
|
||||||
product_out,
|
product_out,
|
||||||
@@ -311,27 +319,27 @@ class GeneralTestsOptimizer(OptimizedBuildTarget):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
zip_command = self._base_zip_command(
|
zip_command = self._base_zip_command(src_top, dist_dir, 'general-tests.zip')
|
||||||
host_out, dist_dir, 'general-tests.zip'
|
|
||||||
)
|
|
||||||
|
|
||||||
# Add host testcases.
|
# Add host testcases.
|
||||||
zip_command.extend(
|
if host_paths:
|
||||||
self._generate_zip_options_for_items(
|
zip_command.extend(
|
||||||
prefix='host',
|
self._generate_zip_options_for_items(
|
||||||
relative_root=f'{src_top / soong_host_out}',
|
prefix='host',
|
||||||
directories=host_paths,
|
relative_root=f'{src_top / soong_host_out}',
|
||||||
)
|
directories=host_paths,
|
||||||
)
|
)
|
||||||
|
)
|
||||||
|
|
||||||
# Add target testcases.
|
# Add target testcases.
|
||||||
zip_command.extend(
|
if target_paths:
|
||||||
self._generate_zip_options_for_items(
|
zip_command.extend(
|
||||||
prefix='target',
|
self._generate_zip_options_for_items(
|
||||||
relative_root=f'{src_top / product_out}',
|
prefix='target',
|
||||||
directories=target_paths,
|
relative_root=f'{src_top / product_out}',
|
||||||
)
|
directories=target_paths,
|
||||||
)
|
)
|
||||||
|
)
|
||||||
|
|
||||||
# TODO(lucafarsi): Push this logic into a general-tests-minimal build command
|
# TODO(lucafarsi): Push this logic into a general-tests-minimal build command
|
||||||
# Add necessary tools. These are also hardcoded in general-tests.mk.
|
# Add necessary tools. These are also hardcoded in general-tests.mk.
|
||||||
@@ -365,6 +373,7 @@ class GeneralTestsOptimizer(OptimizedBuildTarget):
|
|||||||
|
|
||||||
def _get_zip_test_configs_zips_commands(
|
def _get_zip_test_configs_zips_commands(
|
||||||
self,
|
self,
|
||||||
|
src_top: pathlib.Path,
|
||||||
dist_dir: pathlib.Path,
|
dist_dir: pathlib.Path,
|
||||||
host_out: pathlib.Path,
|
host_out: pathlib.Path,
|
||||||
product_out: pathlib.Path,
|
product_out: pathlib.Path,
|
||||||
@@ -428,7 +437,7 @@ class GeneralTestsOptimizer(OptimizedBuildTarget):
|
|||||||
zip_commands = []
|
zip_commands = []
|
||||||
|
|
||||||
tests_config_zip_command = self._base_zip_command(
|
tests_config_zip_command = self._base_zip_command(
|
||||||
host_out, dist_dir, 'general-tests_configs.zip'
|
src_top, dist_dir, 'general-tests_configs.zip'
|
||||||
)
|
)
|
||||||
tests_config_zip_command.extend(
|
tests_config_zip_command.extend(
|
||||||
self._generate_zip_options_for_items(
|
self._generate_zip_options_for_items(
|
||||||
@@ -442,16 +451,14 @@ class GeneralTestsOptimizer(OptimizedBuildTarget):
|
|||||||
self._generate_zip_options_for_items(
|
self._generate_zip_options_for_items(
|
||||||
prefix='target',
|
prefix='target',
|
||||||
relative_root=str(product_out),
|
relative_root=str(product_out),
|
||||||
list_files=[
|
list_files=[f"{product_out / 'target_general-tests_list'}"],
|
||||||
f"{product_out / 'target_general-tests_list'}"
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
zip_commands.append(tests_config_zip_command)
|
zip_commands.append(tests_config_zip_command)
|
||||||
|
|
||||||
tests_list_zip_command = self._base_zip_command(
|
tests_list_zip_command = self._base_zip_command(
|
||||||
host_out, dist_dir, 'general-tests_list.zip'
|
src_top, dist_dir, 'general-tests_list.zip'
|
||||||
)
|
)
|
||||||
tests_list_zip_command.extend(
|
tests_list_zip_command.extend(
|
||||||
self._generate_zip_options_for_items(
|
self._generate_zip_options_for_items(
|
||||||
|
@@ -220,18 +220,6 @@ class GeneralTestsOptimizerTest(fake_filesystem_unittest.TestCase):
|
|||||||
):
|
):
|
||||||
package_commands = optimizer.get_package_outputs_commands()
|
package_commands = optimizer.get_package_outputs_commands()
|
||||||
|
|
||||||
@mock.patch('subprocess.run')
|
|
||||||
def test_no_build_outputs_packaging_fails(self, subprocess_run):
|
|
||||||
subprocess_run.return_value = self._get_soong_vars_output()
|
|
||||||
optimizer = self._create_general_tests_optimizer()
|
|
||||||
|
|
||||||
targets = optimizer.get_build_targets()
|
|
||||||
|
|
||||||
with self.assertRaisesRegex(
|
|
||||||
RuntimeError, 'No items specified to be added to zip'
|
|
||||||
):
|
|
||||||
package_commands = optimizer.get_package_outputs_commands()
|
|
||||||
|
|
||||||
def _create_general_tests_optimizer(self, build_context: BuildContext = None):
|
def _create_general_tests_optimizer(self, build_context: BuildContext = None):
|
||||||
if not build_context:
|
if not build_context:
|
||||||
build_context = self._create_build_context()
|
build_context = self._create_build_context()
|
||||||
@@ -321,7 +309,7 @@ class GeneralTestsOptimizerTest(fake_filesystem_unittest.TestCase):
|
|||||||
"""
|
"""
|
||||||
for command in commands:
|
for command in commands:
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
'/tmp/top/host_out/prebuilts/build-tools/linux-x86/bin/soong_zip',
|
'/tmp/top/prebuilts/build-tools/linux-x86/bin/soong_zip',
|
||||||
command[0],
|
command[0],
|
||||||
)
|
)
|
||||||
self.assertEqual('-d', command[1])
|
self.assertEqual('-d', command[1])
|
||||||
|
@@ -198,3 +198,6 @@ endif
|
|||||||
|
|
||||||
# Add target_use_pan_display flag for hardware/libhardware:gralloc.default
|
# Add target_use_pan_display flag for hardware/libhardware:gralloc.default
|
||||||
$(call soong_config_set_bool,gralloc,target_use_pan_display,$(if $(filter true,$(TARGET_USE_PAN_DISPLAY)),true,false))
|
$(call soong_config_set_bool,gralloc,target_use_pan_display,$(if $(filter true,$(TARGET_USE_PAN_DISPLAY)),true,false))
|
||||||
|
|
||||||
|
# Add use_camera_v4l2_hal flag for hardware/libhardware/modules/camera/3_4:camera.v4l2
|
||||||
|
$(call soong_config_set_bool,camera,use_camera_v4l2_hal,$(if $(filter true,$(USE_CAMERA_V4L2_HAL)),true,false))
|
||||||
|
@@ -18,4 +18,4 @@
|
|||||||
# (like "CRB01"). It must be a single word, and is
|
# (like "CRB01"). It must be a single word, and is
|
||||||
# capitalized by convention.
|
# capitalized by convention.
|
||||||
|
|
||||||
BUILD_ID=AP4A.240919.002
|
BUILD_ID=AP4A.240920.001
|
||||||
|
@@ -357,6 +357,11 @@ ifeq ($(RELEASE_USE_WEBVIEW_BOOTSTRAP_MODULE),true)
|
|||||||
com.android.webview.bootstrap
|
com.android.webview.bootstrap
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifneq (,$(RELEASE_RANGING_STACK))
|
||||||
|
PRODUCT_PACKAGES += \
|
||||||
|
com.android.ranging
|
||||||
|
endif
|
||||||
|
|
||||||
# VINTF data for system image
|
# VINTF data for system image
|
||||||
PRODUCT_PACKAGES += \
|
PRODUCT_PACKAGES += \
|
||||||
system_manifest.xml \
|
system_manifest.xml \
|
||||||
|
@@ -114,6 +114,12 @@ ifeq ($(RELEASE_PACKAGE_PROFILING_MODULE),true)
|
|||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifneq (,$(RELEASE_RANGING_STACK))
|
||||||
|
PRODUCT_APEX_BOOT_JARS += \
|
||||||
|
com.android.uwb:framework-ranging \
|
||||||
|
$(call soong_config_set,bootclasspath,release_ranging_stack,true)
|
||||||
|
endif
|
||||||
|
|
||||||
# List of system_server classpath jars delivered via apex.
|
# List of system_server classpath jars delivered via apex.
|
||||||
# Keep the list sorted by module names and then library names.
|
# Keep the list sorted by module names and then library names.
|
||||||
# Note: For modules available in Q, DO NOT add new entries here.
|
# Note: For modules available in Q, DO NOT add new entries here.
|
||||||
@@ -169,6 +175,11 @@ ifeq ($(RELEASE_PACKAGE_PROFILING_MODULE),true)
|
|||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifneq (,$(RELEASE_RANGING_STACK))
|
||||||
|
PRODUCT_APEX_STANDALONE_SYSTEM_SERVER_JARS += \
|
||||||
|
com.android.uwb:service-ranging
|
||||||
|
endif
|
||||||
|
|
||||||
# Overrides the (apex, jar) pairs above when determining the on-device location. The format is:
|
# Overrides the (apex, jar) pairs above when determining the on-device location. The format is:
|
||||||
# <old_apex>:<old_jar>:<new_apex>:<new_jar>
|
# <old_apex>:<old_jar>:<new_apex>:<new_jar>
|
||||||
PRODUCT_CONFIGURED_JAR_LOCATION_OVERRIDES := \
|
PRODUCT_CONFIGURED_JAR_LOCATION_OVERRIDES := \
|
||||||
|
@@ -68,6 +68,14 @@ aconfig_values {
|
|||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
aconfig_values {
|
||||||
|
name: "aconfig.test.flag.second_values",
|
||||||
|
package: "com.android.aconfig.test",
|
||||||
|
srcs: [
|
||||||
|
"tests/third.values",
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
aconfig_value_set {
|
aconfig_value_set {
|
||||||
name: "aconfig.test.flag.value_set",
|
name: "aconfig.test.flag.value_set",
|
||||||
values: [
|
values: [
|
||||||
|
@@ -283,39 +283,23 @@ public:
|
|||||||
virtual ~flag_provider_interface() = default;
|
virtual ~flag_provider_interface() = default;
|
||||||
|
|
||||||
virtual bool disabled_ro() = 0;
|
virtual bool disabled_ro() = 0;
|
||||||
|
|
||||||
virtual void disabled_ro(bool val) = 0;
|
|
||||||
|
|
||||||
virtual bool disabled_rw() = 0;
|
virtual bool disabled_rw() = 0;
|
||||||
|
|
||||||
virtual void disabled_rw(bool val) = 0;
|
|
||||||
|
|
||||||
virtual bool disabled_rw_exported() = 0;
|
virtual bool disabled_rw_exported() = 0;
|
||||||
|
|
||||||
virtual void disabled_rw_exported(bool val) = 0;
|
|
||||||
|
|
||||||
virtual bool disabled_rw_in_other_namespace() = 0;
|
virtual bool disabled_rw_in_other_namespace() = 0;
|
||||||
|
|
||||||
virtual void disabled_rw_in_other_namespace(bool val) = 0;
|
|
||||||
|
|
||||||
virtual bool enabled_fixed_ro() = 0;
|
virtual bool enabled_fixed_ro() = 0;
|
||||||
|
|
||||||
virtual void enabled_fixed_ro(bool val) = 0;
|
|
||||||
|
|
||||||
virtual bool enabled_fixed_ro_exported() = 0;
|
virtual bool enabled_fixed_ro_exported() = 0;
|
||||||
|
|
||||||
virtual void enabled_fixed_ro_exported(bool val) = 0;
|
|
||||||
|
|
||||||
virtual bool enabled_ro() = 0;
|
virtual bool enabled_ro() = 0;
|
||||||
|
|
||||||
virtual void enabled_ro(bool val) = 0;
|
|
||||||
|
|
||||||
virtual bool enabled_ro_exported() = 0;
|
virtual bool enabled_ro_exported() = 0;
|
||||||
|
|
||||||
virtual void enabled_ro_exported(bool val) = 0;
|
|
||||||
|
|
||||||
virtual bool enabled_rw() = 0;
|
virtual bool enabled_rw() = 0;
|
||||||
|
|
||||||
|
virtual void disabled_ro(bool val) = 0;
|
||||||
|
virtual void disabled_rw(bool val) = 0;
|
||||||
|
virtual void disabled_rw_exported(bool val) = 0;
|
||||||
|
virtual void disabled_rw_in_other_namespace(bool val) = 0;
|
||||||
|
virtual void enabled_fixed_ro(bool val) = 0;
|
||||||
|
virtual void enabled_fixed_ro_exported(bool val) = 0;
|
||||||
|
virtual void enabled_ro(bool val) = 0;
|
||||||
|
virtual void enabled_ro_exported(bool val) = 0;
|
||||||
virtual void enabled_rw(bool val) = 0;
|
virtual void enabled_rw(bool val) = 0;
|
||||||
|
|
||||||
virtual void reset_flags() {}
|
virtual void reset_flags() {}
|
||||||
|
@@ -17,7 +17,7 @@
|
|||||||
use anyhow::{bail, ensure, Context, Result};
|
use anyhow::{bail, ensure, Context, Result};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use protobuf::Message;
|
use protobuf::Message;
|
||||||
use std::collections::{BTreeMap, HashMap};
|
use std::collections::HashMap;
|
||||||
use std::hash::Hasher;
|
use std::hash::Hasher;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
@@ -422,25 +422,32 @@ where
|
|||||||
Ok(flag_ids)
|
Ok(flag_ids)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)] // TODO: b/316357686 - Use fingerprint in codegen to
|
// Creates a fingerprint of the flag names. Sorts the vector.
|
||||||
// protect hardcoded offset reads.
|
pub fn compute_flags_fingerprint(flag_names: &mut Vec<String>) -> Result<u64> {
|
||||||
pub fn compute_flag_offsets_fingerprint(flags_map: &HashMap<String, u16>) -> Result<u64> {
|
flag_names.sort();
|
||||||
|
|
||||||
let mut hasher = SipHasher13::new();
|
let mut hasher = SipHasher13::new();
|
||||||
|
for flag in flag_names {
|
||||||
// Need to sort to ensure the data is added to the hasher in the same order
|
|
||||||
// each run.
|
|
||||||
let sorted_map: BTreeMap<&String, &u16> = flags_map.iter().collect();
|
|
||||||
|
|
||||||
for (flag, offset) in sorted_map {
|
|
||||||
// See https://docs.rs/siphasher/latest/siphasher/#note for use of write
|
|
||||||
// over write_i16. Similarly, use to_be_bytes rather than to_ne_bytes to
|
|
||||||
// ensure consistency.
|
|
||||||
hasher.write(flag.as_bytes());
|
hasher.write(flag.as_bytes());
|
||||||
hasher.write(&offset.to_be_bytes());
|
|
||||||
}
|
}
|
||||||
Ok(hasher.finish())
|
Ok(hasher.finish())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)] // TODO: b/316357686 - Use fingerprint in codegen to
|
||||||
|
// protect hardcoded offset reads.
|
||||||
|
fn compute_fingerprint_from_parsed_flags(flags: ProtoParsedFlags) -> Result<u64> {
|
||||||
|
let separated_flags: Vec<ProtoParsedFlag> = flags.parsed_flag.into_iter().collect::<Vec<_>>();
|
||||||
|
|
||||||
|
// All flags must belong to the same package as the fingerprint is per-package.
|
||||||
|
let Some(_package) = find_unique_package(&separated_flags) else {
|
||||||
|
bail!("No parsed flags, or the parsed flags use different packages.");
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut flag_names =
|
||||||
|
separated_flags.into_iter().map(|flag| flag.name.unwrap()).collect::<Vec<_>>();
|
||||||
|
compute_flags_fingerprint(&mut flag_names)
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
@@ -449,15 +456,46 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_offset_fingerprint() {
|
fn test_offset_fingerprint() {
|
||||||
let parsed_flags = crate::test::parse_test_flags();
|
let parsed_flags = crate::test::parse_test_flags();
|
||||||
let package = find_unique_package(&parsed_flags.parsed_flag).unwrap().to_string();
|
let expected_fingerprint: u64 = 5801144784618221668;
|
||||||
let flag_ids = assign_flag_ids(&package, parsed_flags.parsed_flag.iter()).unwrap();
|
|
||||||
let expected_fingerprint = 10709892481002252132u64;
|
|
||||||
|
|
||||||
let hash_result = compute_flag_offsets_fingerprint(&flag_ids);
|
let hash_result = compute_fingerprint_from_parsed_flags(parsed_flags);
|
||||||
|
|
||||||
assert_eq!(hash_result.unwrap(), expected_fingerprint);
|
assert_eq!(hash_result.unwrap(), expected_fingerprint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_offset_fingerprint_matches_from_package() {
|
||||||
|
let parsed_flags: ProtoParsedFlags = crate::test::parse_test_flags();
|
||||||
|
|
||||||
|
// All test flags are in the same package, so fingerprint from all of them.
|
||||||
|
let result_from_parsed_flags = compute_fingerprint_from_parsed_flags(parsed_flags.clone());
|
||||||
|
|
||||||
|
let mut flag_names_vec = parsed_flags
|
||||||
|
.parsed_flag
|
||||||
|
.clone()
|
||||||
|
.into_iter()
|
||||||
|
.map(|flag| flag.name.unwrap())
|
||||||
|
.map(String::from)
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
let result_from_names = compute_flags_fingerprint(&mut flag_names_vec);
|
||||||
|
|
||||||
|
// Assert the same hash is generated for each case.
|
||||||
|
assert_eq!(result_from_parsed_flags.unwrap(), result_from_names.unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_offset_fingerprint_different_packages_does_not_match() {
|
||||||
|
// Parse flags from two packages.
|
||||||
|
let parsed_flags: ProtoParsedFlags = crate::test::parse_test_flags();
|
||||||
|
let second_parsed_flags = crate::test::parse_second_package_flags();
|
||||||
|
|
||||||
|
let result_from_parsed_flags = compute_fingerprint_from_parsed_flags(parsed_flags).unwrap();
|
||||||
|
let second_result = compute_fingerprint_from_parsed_flags(second_parsed_flags).unwrap();
|
||||||
|
|
||||||
|
// Different flags should have a different fingerprint.
|
||||||
|
assert_ne!(result_from_parsed_flags, second_result);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parse_flags() {
|
fn test_parse_flags() {
|
||||||
let parsed_flags = crate::test::parse_test_flags(); // calls parse_flags
|
let parsed_flags = crate::test::parse_test_flags(); // calls parse_flags
|
||||||
|
@@ -25,12 +25,14 @@ use crate::storage::{
|
|||||||
flag_table::create_flag_table, flag_value::create_flag_value,
|
flag_table::create_flag_table, flag_value::create_flag_value,
|
||||||
package_table::create_package_table,
|
package_table::create_package_table,
|
||||||
};
|
};
|
||||||
use aconfig_protos::{ProtoParsedFlag, ProtoParsedFlags};
|
use aconfig_protos::ProtoParsedFlag;
|
||||||
|
use aconfig_protos::ProtoParsedFlags;
|
||||||
use aconfig_storage_file::StorageFileType;
|
use aconfig_storage_file::StorageFileType;
|
||||||
|
|
||||||
pub struct FlagPackage<'a> {
|
pub struct FlagPackage<'a> {
|
||||||
pub package_name: &'a str,
|
pub package_name: &'a str,
|
||||||
pub package_id: u32,
|
pub package_id: u32,
|
||||||
|
pub fingerprint: u64,
|
||||||
pub flag_names: HashSet<&'a str>,
|
pub flag_names: HashSet<&'a str>,
|
||||||
pub boolean_flags: Vec<&'a ProtoParsedFlag>,
|
pub boolean_flags: Vec<&'a ProtoParsedFlag>,
|
||||||
// The index of the first boolean flag in this aconfig package among all boolean
|
// The index of the first boolean flag in this aconfig package among all boolean
|
||||||
@@ -43,6 +45,7 @@ impl<'a> FlagPackage<'a> {
|
|||||||
FlagPackage {
|
FlagPackage {
|
||||||
package_name,
|
package_name,
|
||||||
package_id,
|
package_id,
|
||||||
|
fingerprint: 0,
|
||||||
flag_names: HashSet::new(),
|
flag_names: HashSet::new(),
|
||||||
boolean_flags: vec![],
|
boolean_flags: vec![],
|
||||||
boolean_start_index: 0,
|
boolean_start_index: 0,
|
||||||
@@ -78,6 +81,8 @@ where
|
|||||||
for p in packages.iter_mut() {
|
for p in packages.iter_mut() {
|
||||||
p.boolean_start_index = boolean_start_index;
|
p.boolean_start_index = boolean_start_index;
|
||||||
boolean_start_index += p.boolean_flags.len() as u32;
|
boolean_start_index += p.boolean_flags.len() as u32;
|
||||||
|
|
||||||
|
// TODO: b/316357686 - Calculate fingerprint and add to package.
|
||||||
}
|
}
|
||||||
|
|
||||||
packages
|
packages
|
||||||
@@ -115,6 +120,8 @@ mod tests {
|
|||||||
use super::*;
|
use super::*;
|
||||||
use crate::Input;
|
use crate::Input;
|
||||||
|
|
||||||
|
use aconfig_protos::ProtoParsedFlags;
|
||||||
|
|
||||||
pub fn parse_all_test_flags() -> Vec<ProtoParsedFlags> {
|
pub fn parse_all_test_flags() -> Vec<ProtoParsedFlags> {
|
||||||
let aconfig_files = [
|
let aconfig_files = [
|
||||||
(
|
(
|
||||||
|
@@ -48,6 +48,7 @@ impl PackageTableNodeWrapper {
|
|||||||
let node = PackageTableNode {
|
let node = PackageTableNode {
|
||||||
package_name: String::from(package.package_name),
|
package_name: String::from(package.package_name),
|
||||||
package_id: package.package_id,
|
package_id: package.package_id,
|
||||||
|
fingerprint: package.fingerprint,
|
||||||
boolean_start_index: package.boolean_start_index,
|
boolean_start_index: package.boolean_start_index,
|
||||||
next_offset: None,
|
next_offset: None,
|
||||||
};
|
};
|
||||||
|
@@ -295,6 +295,24 @@ parsed_flag {
|
|||||||
aconfig_protos::parsed_flags::try_from_binary_proto(&bytes).unwrap()
|
aconfig_protos::parsed_flags::try_from_binary_proto(&bytes).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn parse_second_package_flags() -> ProtoParsedFlags {
|
||||||
|
let bytes = crate::commands::parse_flags(
|
||||||
|
"com.android.aconfig.second_test",
|
||||||
|
Some("system"),
|
||||||
|
vec![Input {
|
||||||
|
source: "tests/test_second_package.aconfig".to_string(),
|
||||||
|
reader: Box::new(include_bytes!("../tests/test_second_package.aconfig").as_slice()),
|
||||||
|
}],
|
||||||
|
vec![Input {
|
||||||
|
source: "tests/third.values".to_string(),
|
||||||
|
reader: Box::new(include_bytes!("../tests/third.values").as_slice()),
|
||||||
|
}],
|
||||||
|
crate::commands::DEFAULT_FLAG_PERMISSION,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
aconfig_protos::parsed_flags::try_from_binary_proto(&bytes).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn first_significant_code_diff(a: &str, b: &str) -> Option<String> {
|
pub fn first_significant_code_diff(a: &str, b: &str) -> Option<String> {
|
||||||
let a = a.lines().map(|line| line.trim_start()).filter(|line| !line.is_empty());
|
let a = a.lines().map(|line| line.trim_start()).filter(|line| !line.is_empty());
|
||||||
let b = b.lines().map(|line| line.trim_start()).filter(|line| !line.is_empty());
|
let b = b.lines().map(|line| line.trim_start()).filter(|line| !line.is_empty());
|
||||||
|
@@ -27,12 +27,13 @@ public:
|
|||||||
{{ -for item in class_elements}}
|
{{ -for item in class_elements}}
|
||||||
virtual bool {item.flag_name}() = 0;
|
virtual bool {item.flag_name}() = 0;
|
||||||
|
|
||||||
{{ -if is_test_mode }}
|
|
||||||
virtual void {item.flag_name}(bool val) = 0;
|
|
||||||
{{ -endif }}
|
|
||||||
{{ -endfor }}
|
{{ -endfor }}
|
||||||
|
|
||||||
{{ -if is_test_mode }}
|
{{ -if is_test_mode }}
|
||||||
|
{{ -for item in class_elements}}
|
||||||
|
virtual void {item.flag_name}(bool val) = 0;
|
||||||
|
{{ -endfor }}
|
||||||
|
|
||||||
virtual void reset_flags() \{}
|
virtual void reset_flags() \{}
|
||||||
{{ -endif }}
|
{{ -endif }}
|
||||||
};
|
};
|
||||||
|
@@ -86,4 +86,4 @@ flag {
|
|||||||
bug: "111"
|
bug: "111"
|
||||||
is_fixed_read_only: true
|
is_fixed_read_only: true
|
||||||
is_exported: true
|
is_exported: true
|
||||||
}
|
}
|
||||||
|
12
tools/aconfig/aconfig/tests/test_second_package.aconfig
Normal file
12
tools/aconfig/aconfig/tests/test_second_package.aconfig
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
package: "com.android.aconfig.second_test"
|
||||||
|
container: "system"
|
||||||
|
|
||||||
|
flag {
|
||||||
|
name: "testing_flag"
|
||||||
|
namespace: "another_namespace"
|
||||||
|
description: "This is a flag for testing."
|
||||||
|
bug: "123"
|
||||||
|
metadata {
|
||||||
|
purpose: PURPOSE_UNSPECIFIED
|
||||||
|
}
|
||||||
|
}
|
6
tools/aconfig/aconfig/tests/third.values
Normal file
6
tools/aconfig/aconfig/tests/third.values
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
flag_value {
|
||||||
|
package: "com.android.aconfig.second_test"
|
||||||
|
name: "testing_flag"
|
||||||
|
state: DISABLED
|
||||||
|
permission: READ_WRITE
|
||||||
|
}
|
@@ -227,7 +227,7 @@ mod tests {
|
|||||||
let bytes = &flag_info_list.into_bytes();
|
let bytes = &flag_info_list.into_bytes();
|
||||||
let mut head = 0;
|
let mut head = 0;
|
||||||
let version = read_u32_from_bytes(bytes, &mut head).unwrap();
|
let version = read_u32_from_bytes(bytes, &mut head).unwrap();
|
||||||
assert_eq!(version, 1);
|
assert_eq!(version, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@@ -253,7 +253,7 @@ mod tests {
|
|||||||
let bytes = &flag_table.into_bytes();
|
let bytes = &flag_table.into_bytes();
|
||||||
let mut head = 0;
|
let mut head = 0;
|
||||||
let version = read_u32_from_bytes(bytes, &mut head).unwrap();
|
let version = read_u32_from_bytes(bytes, &mut head).unwrap();
|
||||||
assert_eq!(version, 1);
|
assert_eq!(version, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@@ -159,7 +159,7 @@ mod tests {
|
|||||||
let bytes = &flag_value_list.into_bytes();
|
let bytes = &flag_value_list.into_bytes();
|
||||||
let mut head = 0;
|
let mut head = 0;
|
||||||
let version = read_u32_from_bytes(bytes, &mut head).unwrap();
|
let version = read_u32_from_bytes(bytes, &mut head).unwrap();
|
||||||
assert_eq!(version, 1);
|
assert_eq!(version, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@@ -58,7 +58,7 @@ use crate::AconfigStorageError::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
/// Storage file version
|
/// Storage file version
|
||||||
pub const FILE_VERSION: u32 = 1;
|
pub const FILE_VERSION: u32 = 2;
|
||||||
|
|
||||||
/// Good hash table prime number
|
/// Good hash table prime number
|
||||||
pub(crate) const HASH_PRIMES: [u32; 29] = [
|
pub(crate) const HASH_PRIMES: [u32; 29] = [
|
||||||
@@ -254,6 +254,16 @@ pub fn read_u32_from_bytes(buf: &[u8], head: &mut usize) -> Result<u32, AconfigS
|
|||||||
Ok(val)
|
Ok(val)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Read and parse bytes as u64
|
||||||
|
pub fn read_u64_from_bytes(buf: &[u8], head: &mut usize) -> Result<u64, AconfigStorageError> {
|
||||||
|
let val =
|
||||||
|
u64::from_le_bytes(buf[*head..*head + 8].try_into().map_err(|errmsg| {
|
||||||
|
BytesParseFail(anyhow!("fail to parse u64 from bytes: {}", errmsg))
|
||||||
|
})?);
|
||||||
|
*head += 8;
|
||||||
|
Ok(val)
|
||||||
|
}
|
||||||
|
|
||||||
/// Read and parse bytes as string
|
/// Read and parse bytes as string
|
||||||
pub(crate) fn read_str_from_bytes(
|
pub(crate) fn read_str_from_bytes(
|
||||||
buf: &[u8],
|
buf: &[u8],
|
||||||
|
@@ -17,7 +17,10 @@
|
|||||||
//! package table module defines the package table file format and methods for serialization
|
//! package table module defines the package table file format and methods for serialization
|
||||||
//! and deserialization
|
//! and deserialization
|
||||||
|
|
||||||
use crate::{get_bucket_index, read_str_from_bytes, read_u32_from_bytes, read_u8_from_bytes};
|
use crate::{
|
||||||
|
get_bucket_index, read_str_from_bytes, read_u32_from_bytes, read_u64_from_bytes,
|
||||||
|
read_u8_from_bytes,
|
||||||
|
};
|
||||||
use crate::{AconfigStorageError, StorageFileType};
|
use crate::{AconfigStorageError, StorageFileType};
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@@ -97,6 +100,7 @@ impl PackageTableHeader {
|
|||||||
pub struct PackageTableNode {
|
pub struct PackageTableNode {
|
||||||
pub package_name: String,
|
pub package_name: String,
|
||||||
pub package_id: u32,
|
pub package_id: u32,
|
||||||
|
pub fingerprint: u64,
|
||||||
// The index of the first boolean flag in this aconfig package among all boolean
|
// The index of the first boolean flag in this aconfig package among all boolean
|
||||||
// flags in this container.
|
// flags in this container.
|
||||||
pub boolean_start_index: u32,
|
pub boolean_start_index: u32,
|
||||||
@@ -108,8 +112,12 @@ impl fmt::Debug for PackageTableNode {
|
|||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
writeln!(
|
writeln!(
|
||||||
f,
|
f,
|
||||||
"Package: {}, Id: {}, Boolean flag start index: {}, Next: {:?}",
|
"Package: {}, Id: {}, Fingerprint: {}, Boolean flag start index: {}, Next: {:?}",
|
||||||
self.package_name, self.package_id, self.boolean_start_index, self.next_offset
|
self.package_name,
|
||||||
|
self.package_id,
|
||||||
|
self.fingerprint,
|
||||||
|
self.boolean_start_index,
|
||||||
|
self.next_offset
|
||||||
)?;
|
)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -123,6 +131,7 @@ impl PackageTableNode {
|
|||||||
result.extend_from_slice(&(name_bytes.len() as u32).to_le_bytes());
|
result.extend_from_slice(&(name_bytes.len() as u32).to_le_bytes());
|
||||||
result.extend_from_slice(name_bytes);
|
result.extend_from_slice(name_bytes);
|
||||||
result.extend_from_slice(&self.package_id.to_le_bytes());
|
result.extend_from_slice(&self.package_id.to_le_bytes());
|
||||||
|
result.extend_from_slice(&self.fingerprint.to_le_bytes());
|
||||||
result.extend_from_slice(&self.boolean_start_index.to_le_bytes());
|
result.extend_from_slice(&self.boolean_start_index.to_le_bytes());
|
||||||
result.extend_from_slice(&self.next_offset.unwrap_or(0).to_le_bytes());
|
result.extend_from_slice(&self.next_offset.unwrap_or(0).to_le_bytes());
|
||||||
result
|
result
|
||||||
@@ -134,6 +143,7 @@ impl PackageTableNode {
|
|||||||
let node = Self {
|
let node = Self {
|
||||||
package_name: read_str_from_bytes(bytes, &mut head)?,
|
package_name: read_str_from_bytes(bytes, &mut head)?,
|
||||||
package_id: read_u32_from_bytes(bytes, &mut head)?,
|
package_id: read_u32_from_bytes(bytes, &mut head)?,
|
||||||
|
fingerprint: read_u64_from_bytes(bytes, &mut head)?,
|
||||||
boolean_start_index: read_u32_from_bytes(bytes, &mut head)?,
|
boolean_start_index: read_u32_from_bytes(bytes, &mut head)?,
|
||||||
next_offset: match read_u32_from_bytes(bytes, &mut head)? {
|
next_offset: match read_u32_from_bytes(bytes, &mut head)? {
|
||||||
0 => None,
|
0 => None,
|
||||||
@@ -251,7 +261,7 @@ mod tests {
|
|||||||
let bytes = &package_table.into_bytes();
|
let bytes = &package_table.into_bytes();
|
||||||
let mut head = 0;
|
let mut head = 0;
|
||||||
let version = read_u32_from_bytes(bytes, &mut head).unwrap();
|
let version = read_u32_from_bytes(bytes, &mut head).unwrap();
|
||||||
assert_eq!(version, 1);
|
assert_eq!(version, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@@ -26,30 +26,33 @@ use tempfile::NamedTempFile;
|
|||||||
|
|
||||||
pub fn create_test_package_table() -> PackageTable {
|
pub fn create_test_package_table() -> PackageTable {
|
||||||
let header = PackageTableHeader {
|
let header = PackageTableHeader {
|
||||||
version: 1,
|
version: 2,
|
||||||
container: String::from("mockup"),
|
container: String::from("mockup"),
|
||||||
file_type: StorageFileType::PackageMap as u8,
|
file_type: StorageFileType::PackageMap as u8,
|
||||||
file_size: 209,
|
file_size: 233,
|
||||||
num_packages: 3,
|
num_packages: 3,
|
||||||
bucket_offset: 31,
|
bucket_offset: 31,
|
||||||
node_offset: 59,
|
node_offset: 59,
|
||||||
};
|
};
|
||||||
let buckets: Vec<Option<u32>> = vec![Some(59), None, None, Some(109), None, None, None];
|
let buckets: Vec<Option<u32>> = vec![Some(59), None, None, Some(117), None, None, None];
|
||||||
let first_node = PackageTableNode {
|
let first_node = PackageTableNode {
|
||||||
package_name: String::from("com.android.aconfig.storage.test_2"),
|
package_name: String::from("com.android.aconfig.storage.test_2"),
|
||||||
package_id: 1,
|
package_id: 1,
|
||||||
|
fingerprint: 0,
|
||||||
boolean_start_index: 3,
|
boolean_start_index: 3,
|
||||||
next_offset: None,
|
next_offset: None,
|
||||||
};
|
};
|
||||||
let second_node = PackageTableNode {
|
let second_node = PackageTableNode {
|
||||||
package_name: String::from("com.android.aconfig.storage.test_1"),
|
package_name: String::from("com.android.aconfig.storage.test_1"),
|
||||||
package_id: 0,
|
package_id: 0,
|
||||||
|
fingerprint: 0,
|
||||||
boolean_start_index: 0,
|
boolean_start_index: 0,
|
||||||
next_offset: Some(159),
|
next_offset: Some(175),
|
||||||
};
|
};
|
||||||
let third_node = PackageTableNode {
|
let third_node = PackageTableNode {
|
||||||
package_name: String::from("com.android.aconfig.storage.test_4"),
|
package_name: String::from("com.android.aconfig.storage.test_4"),
|
||||||
package_id: 2,
|
package_id: 2,
|
||||||
|
fingerprint: 0,
|
||||||
boolean_start_index: 6,
|
boolean_start_index: 6,
|
||||||
next_offset: None,
|
next_offset: None,
|
||||||
};
|
};
|
||||||
@@ -78,7 +81,7 @@ impl FlagTableNode {
|
|||||||
|
|
||||||
pub fn create_test_flag_table() -> FlagTable {
|
pub fn create_test_flag_table() -> FlagTable {
|
||||||
let header = FlagTableHeader {
|
let header = FlagTableHeader {
|
||||||
version: 1,
|
version: 2,
|
||||||
container: String::from("mockup"),
|
container: String::from("mockup"),
|
||||||
file_type: StorageFileType::FlagMap as u8,
|
file_type: StorageFileType::FlagMap as u8,
|
||||||
file_size: 321,
|
file_size: 321,
|
||||||
@@ -120,7 +123,7 @@ pub fn create_test_flag_table() -> FlagTable {
|
|||||||
|
|
||||||
pub fn create_test_flag_value_list() -> FlagValueList {
|
pub fn create_test_flag_value_list() -> FlagValueList {
|
||||||
let header = FlagValueHeader {
|
let header = FlagValueHeader {
|
||||||
version: 1,
|
version: 2,
|
||||||
container: String::from("mockup"),
|
container: String::from("mockup"),
|
||||||
file_type: StorageFileType::FlagVal as u8,
|
file_type: StorageFileType::FlagVal as u8,
|
||||||
file_size: 35,
|
file_size: 35,
|
||||||
@@ -133,7 +136,7 @@ pub fn create_test_flag_value_list() -> FlagValueList {
|
|||||||
|
|
||||||
pub fn create_test_flag_info_list() -> FlagInfoList {
|
pub fn create_test_flag_info_list() -> FlagInfoList {
|
||||||
let header = FlagInfoHeader {
|
let header = FlagInfoHeader {
|
||||||
version: 1,
|
version: 2,
|
||||||
container: String::from("mockup"),
|
container: String::from("mockup"),
|
||||||
file_type: StorageFileType::FlagInfo as u8,
|
file_type: StorageFileType::FlagInfo as u8,
|
||||||
file_size: 35,
|
file_size: 35,
|
||||||
|
@@ -37,6 +37,10 @@ public class ByteBufferReader {
|
|||||||
return Short.toUnsignedInt(mByteBuffer.getShort());
|
return Short.toUnsignedInt(mByteBuffer.getShort());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public long readLong() {
|
||||||
|
return mByteBuffer.getLong();
|
||||||
|
}
|
||||||
|
|
||||||
public int readInt() {
|
public int readInt() {
|
||||||
return this.mByteBuffer.getInt();
|
return this.mByteBuffer.getInt();
|
||||||
}
|
}
|
||||||
|
@@ -118,6 +118,7 @@ public class PackageTable {
|
|||||||
|
|
||||||
private String mPackageName;
|
private String mPackageName;
|
||||||
private int mPackageId;
|
private int mPackageId;
|
||||||
|
private long mFingerprint;
|
||||||
private int mBooleanStartIndex;
|
private int mBooleanStartIndex;
|
||||||
private int mNextOffset;
|
private int mNextOffset;
|
||||||
|
|
||||||
@@ -125,6 +126,7 @@ public class PackageTable {
|
|||||||
Node node = new Node();
|
Node node = new Node();
|
||||||
node.mPackageName = reader.readString();
|
node.mPackageName = reader.readString();
|
||||||
node.mPackageId = reader.readInt();
|
node.mPackageId = reader.readInt();
|
||||||
|
node.mFingerprint = reader.readLong();
|
||||||
node.mBooleanStartIndex = reader.readInt();
|
node.mBooleanStartIndex = reader.readInt();
|
||||||
node.mNextOffset = reader.readInt();
|
node.mNextOffset = reader.readInt();
|
||||||
node.mNextOffset = node.mNextOffset == 0 ? -1 : node.mNextOffset;
|
node.mNextOffset = node.mNextOffset == 0 ? -1 : node.mNextOffset;
|
||||||
@@ -150,6 +152,7 @@ public class PackageTable {
|
|||||||
return Objects.equals(mPackageName, other.mPackageName)
|
return Objects.equals(mPackageName, other.mPackageName)
|
||||||
&& mPackageId == other.mPackageId
|
&& mPackageId == other.mPackageId
|
||||||
&& mBooleanStartIndex == other.mBooleanStartIndex
|
&& mBooleanStartIndex == other.mBooleanStartIndex
|
||||||
|
&& mFingerprint == other.mFingerprint
|
||||||
&& mNextOffset == other.mNextOffset;
|
&& mNextOffset == other.mNextOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,6 +168,10 @@ public class PackageTable {
|
|||||||
return mBooleanStartIndex;
|
return mBooleanStartIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public long getFingerprint() {
|
||||||
|
return mFingerprint;
|
||||||
|
}
|
||||||
|
|
||||||
public int getNextOffset() {
|
public int getNextOffset() {
|
||||||
return mNextOffset;
|
return mNextOffset;
|
||||||
}
|
}
|
||||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -33,7 +33,7 @@ public class FlagTableTest {
|
|||||||
public void testFlagTable_rightHeader() throws Exception {
|
public void testFlagTable_rightHeader() throws Exception {
|
||||||
FlagTable flagTable = FlagTable.fromBytes(TestDataUtils.getTestFlagMapByteBuffer());
|
FlagTable flagTable = FlagTable.fromBytes(TestDataUtils.getTestFlagMapByteBuffer());
|
||||||
FlagTable.Header header = flagTable.getHeader();
|
FlagTable.Header header = flagTable.getHeader();
|
||||||
assertEquals(1, header.getVersion());
|
assertEquals(2, header.getVersion());
|
||||||
assertEquals("mockup", header.getContainer());
|
assertEquals("mockup", header.getContainer());
|
||||||
assertEquals(FileType.FLAG_MAP, header.getFileType());
|
assertEquals(FileType.FLAG_MAP, header.getFileType());
|
||||||
assertEquals(321, header.getFileSize());
|
assertEquals(321, header.getFileSize());
|
||||||
|
@@ -36,7 +36,7 @@ public class FlagValueListTest {
|
|||||||
FlagValueList flagValueList =
|
FlagValueList flagValueList =
|
||||||
FlagValueList.fromBytes(TestDataUtils.getTestFlagValByteBuffer());
|
FlagValueList.fromBytes(TestDataUtils.getTestFlagValByteBuffer());
|
||||||
FlagValueList.Header header = flagValueList.getHeader();
|
FlagValueList.Header header = flagValueList.getHeader();
|
||||||
assertEquals(1, header.getVersion());
|
assertEquals(2, header.getVersion());
|
||||||
assertEquals("mockup", header.getContainer());
|
assertEquals("mockup", header.getContainer());
|
||||||
assertEquals(FileType.FLAG_VAL, header.getFileType());
|
assertEquals(FileType.FLAG_VAL, header.getFileType());
|
||||||
assertEquals(35, header.getFileSize());
|
assertEquals(35, header.getFileSize());
|
||||||
|
@@ -20,7 +20,6 @@ import static org.junit.Assert.assertEquals;
|
|||||||
|
|
||||||
import android.aconfig.storage.FileType;
|
import android.aconfig.storage.FileType;
|
||||||
import android.aconfig.storage.PackageTable;
|
import android.aconfig.storage.PackageTable;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.junit.runners.JUnit4;
|
import org.junit.runners.JUnit4;
|
||||||
@@ -28,42 +27,40 @@ import org.junit.runners.JUnit4;
|
|||||||
@RunWith(JUnit4.class)
|
@RunWith(JUnit4.class)
|
||||||
public class PackageTableTest {
|
public class PackageTableTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testPackageTable_rightHeader() throws Exception {
|
public void testPackageTable_rightHeader() throws Exception {
|
||||||
PackageTable packageTable =
|
PackageTable packageTable = PackageTable.fromBytes(TestDataUtils.getTestPackageMapByteBuffer());
|
||||||
PackageTable.fromBytes(TestDataUtils.getTestPackageMapByteBuffer());
|
PackageTable.Header header = packageTable.getHeader();
|
||||||
PackageTable.Header header = packageTable.getHeader();
|
assertEquals(2, header.getVersion());
|
||||||
assertEquals(1, header.getVersion());
|
assertEquals("mockup", header.getContainer());
|
||||||
assertEquals("mockup", header.getContainer());
|
assertEquals(FileType.PACKAGE_MAP, header.getFileType());
|
||||||
assertEquals(FileType.PACKAGE_MAP, header.getFileType());
|
assertEquals(209, header.getFileSize());
|
||||||
assertEquals(209, header.getFileSize());
|
assertEquals(3, header.getNumPackages());
|
||||||
assertEquals(3, header.getNumPackages());
|
assertEquals(31, header.getBucketOffset());
|
||||||
assertEquals(31, header.getBucketOffset());
|
assertEquals(59, header.getNodeOffset());
|
||||||
assertEquals(59, header.getNodeOffset());
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testPackageTable_rightNode() throws Exception {
|
public void testPackageTable_rightNode() throws Exception {
|
||||||
PackageTable packageTable =
|
PackageTable packageTable = PackageTable.fromBytes(TestDataUtils.getTestPackageMapByteBuffer());
|
||||||
PackageTable.fromBytes(TestDataUtils.getTestPackageMapByteBuffer());
|
|
||||||
|
|
||||||
PackageTable.Node node1 = packageTable.get("com.android.aconfig.storage.test_1");
|
PackageTable.Node node1 = packageTable.get("com.android.aconfig.storage.test_1");
|
||||||
PackageTable.Node node2 = packageTable.get("com.android.aconfig.storage.test_2");
|
PackageTable.Node node2 = packageTable.get("com.android.aconfig.storage.test_2");
|
||||||
PackageTable.Node node4 = packageTable.get("com.android.aconfig.storage.test_4");
|
PackageTable.Node node4 = packageTable.get("com.android.aconfig.storage.test_4");
|
||||||
|
|
||||||
assertEquals("com.android.aconfig.storage.test_1", node1.getPackageName());
|
assertEquals("com.android.aconfig.storage.test_1", node1.getPackageName());
|
||||||
assertEquals("com.android.aconfig.storage.test_2", node2.getPackageName());
|
assertEquals("com.android.aconfig.storage.test_2", node2.getPackageName());
|
||||||
assertEquals("com.android.aconfig.storage.test_4", node4.getPackageName());
|
assertEquals("com.android.aconfig.storage.test_4", node4.getPackageName());
|
||||||
|
|
||||||
assertEquals(0, node1.getPackageId());
|
assertEquals(0, node1.getPackageId());
|
||||||
assertEquals(1, node2.getPackageId());
|
assertEquals(1, node2.getPackageId());
|
||||||
assertEquals(2, node4.getPackageId());
|
assertEquals(2, node4.getPackageId());
|
||||||
|
|
||||||
assertEquals(0, node1.getBooleanStartIndex());
|
assertEquals(0, node1.getBooleanStartIndex());
|
||||||
assertEquals(3, node2.getBooleanStartIndex());
|
assertEquals(3, node2.getBooleanStartIndex());
|
||||||
assertEquals(6, node4.getBooleanStartIndex());
|
assertEquals(6, node4.getBooleanStartIndex());
|
||||||
|
|
||||||
assertEquals(159, node1.getNextOffset());
|
assertEquals(175, node1.getNextOffset());
|
||||||
assertEquals(-1, node2.getNextOffset());
|
assertEquals(-1, node2.getNextOffset());
|
||||||
assertEquals(-1, node4.getNextOffset());
|
assertEquals(-1, node4.getNextOffset());
|
||||||
}
|
}
|
||||||
|
@@ -507,9 +507,9 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
// this test point locks down flag storage file version number query api
|
// this test point locks down flag storage file version number query api
|
||||||
fn test_storage_version_query() {
|
fn test_storage_version_query() {
|
||||||
assert_eq!(get_storage_file_version("./tests/package.map").unwrap(), 1);
|
assert_eq!(get_storage_file_version("./tests/package.map").unwrap(), 2);
|
||||||
assert_eq!(get_storage_file_version("./tests/flag.map").unwrap(), 1);
|
assert_eq!(get_storage_file_version("./tests/flag.map").unwrap(), 2);
|
||||||
assert_eq!(get_storage_file_version("./tests/flag.val").unwrap(), 1);
|
assert_eq!(get_storage_file_version("./tests/flag.val").unwrap(), 2);
|
||||||
assert_eq!(get_storage_file_version("./tests/flag.info").unwrap(), 1);
|
assert_eq!(get_storage_file_version("./tests/flag.info").unwrap(), 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -80,16 +80,16 @@ class AconfigStorageTest : public ::testing::Test {
|
|||||||
TEST_F(AconfigStorageTest, test_storage_version_query) {
|
TEST_F(AconfigStorageTest, test_storage_version_query) {
|
||||||
auto version = api::get_storage_file_version(package_map);
|
auto version = api::get_storage_file_version(package_map);
|
||||||
ASSERT_TRUE(version.ok());
|
ASSERT_TRUE(version.ok());
|
||||||
ASSERT_EQ(*version, 1);
|
ASSERT_EQ(*version, 2);
|
||||||
version = api::get_storage_file_version(flag_map);
|
version = api::get_storage_file_version(flag_map);
|
||||||
ASSERT_TRUE(version.ok());
|
ASSERT_TRUE(version.ok());
|
||||||
ASSERT_EQ(*version, 1);
|
ASSERT_EQ(*version, 2);
|
||||||
version = api::get_storage_file_version(flag_val);
|
version = api::get_storage_file_version(flag_val);
|
||||||
ASSERT_TRUE(version.ok());
|
ASSERT_TRUE(version.ok());
|
||||||
ASSERT_EQ(*version, 1);
|
ASSERT_EQ(*version, 2);
|
||||||
version = api::get_storage_file_version(flag_info);
|
version = api::get_storage_file_version(flag_info);
|
||||||
ASSERT_TRUE(version.ok());
|
ASSERT_TRUE(version.ok());
|
||||||
ASSERT_EQ(*version, 1);
|
ASSERT_EQ(*version, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Negative test to lock down the error when mapping none exist storage files
|
/// Negative test to lock down the error when mapping none exist storage files
|
||||||
|
@@ -200,9 +200,9 @@ mod aconfig_storage_rust_test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_storage_version_query() {
|
fn test_storage_version_query() {
|
||||||
assert_eq!(get_storage_file_version("./package.map").unwrap(), 1);
|
assert_eq!(get_storage_file_version("./package.map").unwrap(), 2);
|
||||||
assert_eq!(get_storage_file_version("./flag.map").unwrap(), 1);
|
assert_eq!(get_storage_file_version("./flag.map").unwrap(), 2);
|
||||||
assert_eq!(get_storage_file_version("./flag.val").unwrap(), 1);
|
assert_eq!(get_storage_file_version("./flag.val").unwrap(), 2);
|
||||||
assert_eq!(get_storage_file_version("./flag.info").unwrap(), 1);
|
assert_eq!(get_storage_file_version("./flag.info").unwrap(), 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -43,7 +43,9 @@ etc/aconfig/flag.val
|
|||||||
etc/aconfig/package.map
|
etc/aconfig/package.map
|
||||||
etc/bpf/uprobestats/BitmapAllocation.o
|
etc/bpf/uprobestats/BitmapAllocation.o
|
||||||
etc/bpf/uprobestats/GenericInstrumentation.o
|
etc/bpf/uprobestats/GenericInstrumentation.o
|
||||||
|
etc/bpf/uprobestats/ProcessManagement.o
|
||||||
etc/init/UprobeStats.rc
|
etc/init/UprobeStats.rc
|
||||||
lib/libuprobestats_client.so
|
lib/libuprobestats_client.so
|
||||||
lib64/libuprobestats_client.so
|
lib64/libuprobestats_client.so
|
||||||
priv-app/DeviceDiagnostics/DeviceDiagnostics.apk
|
priv-app/DeviceDiagnostics/DeviceDiagnostics.apk
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user