Merge "Move the installation rules of device boot images to soong" into main
diff --git a/ci/build_test_suites.py b/ci/build_test_suites.py
index 6e1f88c..75dd9f2 100644
--- a/ci/build_test_suites.py
+++ b/ci/build_test_suites.py
@@ -20,6 +20,7 @@
 import logging
 import os
 import pathlib
+import re
 import subprocess
 import sys
 from typing import Callable
@@ -28,6 +29,7 @@
 
 REQUIRED_ENV_VARS = frozenset(['TARGET_PRODUCT', 'TARGET_RELEASE', 'TOP'])
 SOONG_UI_EXE_REL_PATH = 'build/soong/soong_ui.bash'
+LOG_PATH = 'logs/build_test_suites.log'
 
 
 class Error(Exception):
@@ -51,6 +53,15 @@
   any output zip files needed by the build.
   """
 
+  _DOWNLOAD_OPTS = {
+      'test-config-only-zip',
+      'test-zip-file-filter',
+      'extra-host-shared-lib-zip',
+      'sandbox-tests-zips',
+      'additional-files-filter',
+      'cts-package-name',
+  }
+
   def __init__(
       self,
       build_context: dict[str, any],
@@ -63,12 +74,19 @@
 
   def create_build_plan(self):
 
-    if 'optimized_build' not in self.build_context['enabled_build_features']:
+    if 'optimized_build' not in self.build_context.get(
+        'enabledBuildFeatures', []
+    ):
       return BuildPlan(set(self.args.extra_targets), set())
 
     build_targets = set()
     packaging_functions = set()
     for target in self.args.extra_targets:
+      if self._unused_target_exclusion_enabled(
+          target
+      ) and not self._build_target_used(target):
+        continue
+
       target_optimizer_getter = self.target_optimizations.get(target, None)
       if not target_optimizer_getter:
         build_targets.add(target)
@@ -82,6 +100,60 @@
 
     return BuildPlan(build_targets, packaging_functions)
 
+  def _unused_target_exclusion_enabled(self, target: str) -> bool:
+    return f'{target}_unused_exclusion' in self.build_context.get(
+        'enabledBuildFeatures', []
+    )
+
+  def _build_target_used(self, target: str) -> bool:
+    """Determines whether this target's outputs are used by the test configurations listed in the build context."""
+    file_download_regexes = self._aggregate_file_download_regexes()
+    # For all of a targets' outputs, check if any of the regexes used by tests
+    # to download artifacts would match it. If any of them do then this target
+    # is necessary.
+    for artifact in self._get_target_potential_outputs(target):
+      for regex in file_download_regexes:
+        if re.match(regex, artifact):
+          return True
+    return False
+
+  def _get_target_potential_outputs(self, target: str) -> set[str]:
+    tests_suffix = '-tests'
+    if target.endswith('tests'):
+      tests_suffix = ''
+    # This is a list of all the potential zips output by the test suite targets.
+    # If the test downloads artifacts from any of these zips, we will be
+    # conservative and avoid skipping the tests.
+    return {
+        f'{target}.zip',
+        f'android-{target}.zip',
+        f'android-{target}-verifier.zip',
+        f'{target}{tests_suffix}_list.zip',
+        f'android-{target}{tests_suffix}_list.zip',
+        f'{target}{tests_suffix}_host-shared-libs.zip',
+        f'android-{target}{tests_suffix}_host-shared-libs.zip',
+        f'{target}{tests_suffix}_configs.zip',
+        f'android-{target}{tests_suffix}_configs.zip',
+    }
+
+  def _aggregate_file_download_regexes(self) -> set[re.Pattern]:
+    """Lists out all test config options to specify targets to download.
+
+    These come in the form of regexes.
+    """
+    all_regexes = set()
+    for test_info in self._get_test_infos():
+      for opt in test_info.get('extraOptions', []):
+        # check the known list of options for downloading files.
+        if opt.get('key') in self._DOWNLOAD_OPTS:
+          all_regexes.update(
+              re.compile(value) for value in opt.get('values', [])
+          )
+    return all_regexes
+
+  def _get_test_infos(self):
+    return self.build_context.get('testContext', dict()).get('testInfos', [])
+
 
 @dataclass(frozen=True)
 class BuildPlan:
@@ -154,7 +226,7 @@
 
 
 def empty_build_context():
-  return {'enabled_build_features': []}
+  return {'enabledBuildFeatures': []}
 
 
 def execute_build_plan(build_plan: BuildPlan):
@@ -181,4 +253,12 @@
 
 
 def main(argv):
+  dist_dir = os.environ.get('DIST_DIR')
+  if dist_dir:
+    log_file = pathlib.Path(dist_dir) / LOG_PATH
+    logging.basicConfig(
+        level=logging.DEBUG,
+        format='%(asctime)s %(levelname)s %(message)s',
+        filename=log_file,
+    )
   sys.exit(build_test_suites(argv))
diff --git a/ci/build_test_suites_test.py b/ci/build_test_suites_test.py
index a9ff3fb..7efb154 100644
--- a/ci/build_test_suites_test.py
+++ b/ci/build_test_suites_test.py
@@ -324,6 +324,55 @@
         self.run_packaging_functions(build_plan),
     )
 
+  def test_target_output_used_target_built(self):
+    build_target = 'test_target'
+    build_planner = self.create_build_planner(
+        build_targets={build_target},
+        build_context=self.create_build_context(
+            test_context=self.get_test_context(build_target),
+            enabled_build_features={'test_target_unused_exclusion'},
+        ),
+    )
+
+    build_plan = build_planner.create_build_plan()
+
+    self.assertSetEqual(build_plan.build_targets, {build_target})
+
+  def test_target_regex_used_target_built(self):
+    build_target = 'test_target'
+    test_context = self.get_test_context(build_target)
+    test_context['testInfos'][0]['extraOptions'] = [{
+        'key': 'additional-files-filter',
+        'values': [f'.*{build_target}.*\.zip'],
+    }]
+    build_planner = self.create_build_planner(
+        build_targets={build_target},
+        build_context=self.create_build_context(
+            test_context=test_context,
+            enabled_build_features={'test_target_unused_exclusion'},
+        ),
+    )
+
+    build_plan = build_planner.create_build_plan()
+
+    self.assertSetEqual(build_plan.build_targets, {build_target})
+
+  def test_target_output_not_used_target_not_built(self):
+    build_target = 'test_target'
+    test_context = self.get_test_context(build_target)
+    test_context['testInfos'][0]['extraOptions'] = []
+    build_planner = self.create_build_planner(
+        build_targets={build_target},
+        build_context=self.create_build_context(
+            test_context=test_context,
+            enabled_build_features={'test_target_unused_exclusion'},
+        ),
+    )
+
+    build_plan = build_planner.create_build_plan()
+
+    self.assertSetEqual(build_plan.build_targets, set())
+
   def create_build_planner(
       self,
       build_targets: set[str],
@@ -352,10 +401,10 @@
       test_context: dict[str, any] = {},
   ) -> dict[str, any]:
     build_context = {}
-    build_context['enabled_build_features'] = enabled_build_features
+    build_context['enabledBuildFeatures'] = enabled_build_features
     if optimized_build_enabled:
-      build_context['enabled_build_features'].add('optimized_build')
-    build_context['test_context'] = test_context
+      build_context['enabledBuildFeatures'].add('optimized_build')
+    build_context['testContext'] = test_context
     return build_context
 
   def create_args(
@@ -398,6 +447,25 @@
 
     return output
 
+  def get_test_context(self, target: str):
+    return {
+        'testInfos': [
+            {
+                'name': 'atp_test',
+                'target': 'test_target',
+                'branch': 'branch',
+                'extraOptions': [{
+                    'key': 'additional-files-filter',
+                    'values': [f'{target}.zip'],
+                }],
+                'command': '/tf/command',
+                'extraBuildTargets': [
+                    'extra_build_target',
+                ],
+            },
+        ],
+    }
+
 
 def wait_until(
     condition_function: Callable[[], bool],
diff --git a/ci/optimized_targets.py b/ci/optimized_targets.py
index 224c8c0..6321719 100644
--- a/ci/optimized_targets.py
+++ b/ci/optimized_targets.py
@@ -53,7 +53,7 @@
 
 
 def get_target_optimizer(target, enabled_flag, build_context, optimizer):
-  if enabled_flag in build_context['enabled_build_features']:
+  if enabled_flag in build_context['enabledBuildFeatures']:
     return optimizer
 
   return NullOptimizer(target)
diff --git a/core/android_soong_config_vars.mk b/core/android_soong_config_vars.mk
index 461b284..6954c93 100644
--- a/core/android_soong_config_vars.mk
+++ b/core/android_soong_config_vars.mk
@@ -39,8 +39,14 @@
 
 # For Sanitizers
 $(call soong_config_set_bool,ANDROID,ASAN_ENABLED,$(if $(filter address,$(SANITIZE_TARGET)),true,false))
+$(call soong_config_set_bool,ANDROID,HWASAN_ENABLED,$(if $(filter hwaddress,$(SANITIZE_TARGET)),true,false))
 $(call soong_config_set_bool,ANDROID,SANITIZE_TARGET_SYSTEM_ENABLED,$(if $(filter true,$(SANITIZE_TARGET_SYSTEM)),true,false))
 
+# For init.environ.rc
+$(call soong_config_set_bool,ANDROID,GCOV_COVERAGE,$(NATIVE_COVERAGE))
+$(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))
+
 # 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))
 
@@ -49,6 +55,8 @@
 ifdef ART_DEBUG_OPT_FLAG
 $(call soong_config_set,art_module,art_debug_opt_flag,$(ART_DEBUG_OPT_FLAG))
 endif
+# The default value of ART_BUILD_HOST_DEBUG is true
+$(call soong_config_set_bool,art_module,art_build_host_debug,$(if $(filter false,$(ART_BUILD_HOST_DEBUG)),false,true))
 
 ifdef TARGET_BOARD_AUTO
   $(call add_soong_config_var_value, ANDROID, target_board_auto, $(TARGET_BOARD_AUTO))
diff --git a/core/binary.mk b/core/binary.mk
index 0bc9469..1e98bc0 100644
--- a/core/binary.mk
+++ b/core/binary.mk
@@ -205,8 +205,6 @@
     my_api_level := $(my_ndk_api)
   endif
 
-  my_ndk_source_root := \
-      $(HISTORICAL_NDK_VERSIONS_ROOT)/$(LOCAL_NDK_VERSION)/sources
   my_built_ndk := $(SOONG_OUT_DIR)/ndk
   my_ndk_triple := $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_NDK_TRIPLE)
   my_ndk_sysroot_include := \
@@ -239,16 +237,18 @@
   endif
 
   ifeq (system,$(LOCAL_NDK_STL_VARIANT))
+    my_ndk_source_root := \
+        $(HISTORICAL_NDK_VERSIONS_ROOT)/$(LOCAL_NDK_VERSION)/sources
     my_ndk_stl_include_path := $(my_ndk_source_root)/cxx-stl/system/include
     my_system_shared_libraries += libstdc++
   else ifneq (,$(filter c++_%, $(LOCAL_NDK_STL_VARIANT)))
-    my_ndk_stl_include_path := \
-      $(my_ndk_source_root)/cxx-stl/llvm-libc++/include
-    my_ndk_stl_include_path += \
-      $(my_ndk_source_root)/cxx-stl/llvm-libc++abi/include
+    my_llvm_dir := $(LLVM_PREBUILTS_BASE)/$(BUILD_OS)-x86/$(LLVM_PREBUILTS_VERSION)
+    my_libcxx_arch_dir := $(my_llvm_dir)/android_libc++/ndk/$($(LOCAL_2ND_ARCH_VAR_PREFIX)PREBUILT_LIBCXX_ARCH_DIR)
 
-    my_libcxx_libdir := \
-      $(my_ndk_source_root)/cxx-stl/llvm-libc++/libs/$(my_cpu_variant)
+    # Include the target-specific __config_site file followed by the generic libc++ headers.
+    my_ndk_stl_include_path := $(my_libcxx_arch_dir)/include/c++/v1
+    my_ndk_stl_include_path += $(my_llvm_dir)/include/c++/v1
+    my_libcxx_libdir := $(my_libcxx_arch_dir)/lib
 
     ifeq (c++_static,$(LOCAL_NDK_STL_VARIANT))
       my_ndk_stl_static_lib := \
@@ -258,7 +258,7 @@
       my_ndk_stl_shared_lib_fullpath := $(my_libcxx_libdir)/libc++_shared.so
     endif
 
-    my_ndk_stl_static_lib += $(my_libcxx_libdir)/libunwind.a
+    my_ndk_stl_static_lib += $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_LIBUNWIND)
     my_ldlibs += -ldl
   else # LOCAL_NDK_STL_VARIANT must be none
     # Do nothing.
diff --git a/core/clang/TARGET_arm.mk b/core/clang/TARGET_arm.mk
index f18747a..126482f 100644
--- a/core/clang/TARGET_arm.mk
+++ b/core/clang/TARGET_arm.mk
@@ -4,7 +4,10 @@
 
 $(clang_2nd_arch_prefix)TARGET_LIBPROFILE_RT := $(LLVM_RTLIB_PATH)/libclang_rt.profile-arm-android.a
 $(clang_2nd_arch_prefix)TARGET_LIBCRT_BUILTINS := $(LLVM_RTLIB_PATH)/libclang_rt.builtins-arm-android.a
+$(clang_2nd_arch_prefix)TARGET_LIBUNWIND := $(LLVM_RTLIB_PATH)/arm/libunwind.a
 
 # Address sanitizer clang config
 $(clang_2nd_arch_prefix)ADDRESS_SANITIZER_LINKER := /system/bin/linker_asan
 $(clang_2nd_arch_prefix)ADDRESS_SANITIZER_LINKER_FILE := /system/bin/bootstrap/linker_asan
+
+$(clang_2nd_arch_prefix)PREBUILT_LIBCXX_ARCH_DIR := arm
diff --git a/core/clang/TARGET_arm64.mk b/core/clang/TARGET_arm64.mk
index 42bed0a..e7ab6cb 100644
--- a/core/clang/TARGET_arm64.mk
+++ b/core/clang/TARGET_arm64.mk
@@ -4,7 +4,10 @@
 
 TARGET_LIBPROFILE_RT := $(LLVM_RTLIB_PATH)/libclang_rt.profile-aarch64-android.a
 TARGET_LIBCRT_BUILTINS := $(LLVM_RTLIB_PATH)/libclang_rt.builtins-aarch64-android.a
+TARGET_LIBUNWIND := $(LLVM_RTLIB_PATH)/aarch64/libunwind.a
 
 # Address sanitizer clang config
 ADDRESS_SANITIZER_LINKER := /system/bin/linker_asan64
 ADDRESS_SANITIZER_LINKER_FILE := /system/bin/bootstrap/linker_asan64
+
+PREBUILT_LIBCXX_ARCH_DIR := aarch64
diff --git a/core/clang/TARGET_riscv64.mk b/core/clang/TARGET_riscv64.mk
index cfb5c7d..58c9c7b 100644
--- a/core/clang/TARGET_riscv64.mk
+++ b/core/clang/TARGET_riscv64.mk
@@ -4,7 +4,10 @@
 
 TARGET_LIBPROFILE_RT := $(LLVM_RTLIB_PATH)/libclang_rt.profile-riscv64-android.a
 TARGET_LIBCRT_BUILTINS := $(LLVM_RTLIB_PATH)/libclang_rt.builtins-riscv64-android.a
+TARGET_LIBUNWIND := $(LLVM_RTLIB_PATH)/riscv64/libunwind.a
 
 # Address sanitizer clang config
 ADDRESS_SANITIZER_LINKER := /system/bin/linker_asan64
 ADDRESS_SANITIZER_LINKER_FILE := /system/bin/bootstrap/linker_asan64
+
+PREBUILT_LIBCXX_ARCH_DIR := riscv64
diff --git a/core/clang/TARGET_x86.mk b/core/clang/TARGET_x86.mk
index 5491a05..1a08c79 100644
--- a/core/clang/TARGET_x86.mk
+++ b/core/clang/TARGET_x86.mk
@@ -4,7 +4,10 @@
 
 $(clang_2nd_arch_prefix)TARGET_LIBPROFILE_RT := $(LLVM_RTLIB_PATH)/libclang_rt.profile-i686-android.a
 $(clang_2nd_arch_prefix)TARGET_LIBCRT_BUILTINS := $(LLVM_RTLIB_PATH)/libclang_rt.builtins-i686-android.a
+$(clang_2nd_arch_prefix)TARGET_LIBUNWIND := $(LLVM_RTLIB_PATH)/i386/libunwind.a
 
 # Address sanitizer clang config
 $(clang_2nd_arch_prefix)ADDRESS_SANITIZER_LINKER := /system/bin/linker_asan
 $(clang_2nd_arch_prefix)ADDRESS_SANITIZER_LINKER_FILE := /system/bin/bootstrap/linker_asan
+
+$(clang_2nd_arch_prefix)PREBUILT_LIBCXX_ARCH_DIR := i386
diff --git a/core/clang/TARGET_x86_64.mk b/core/clang/TARGET_x86_64.mk
index 167db72..f39b41e 100644
--- a/core/clang/TARGET_x86_64.mk
+++ b/core/clang/TARGET_x86_64.mk
@@ -4,7 +4,10 @@
 
 TARGET_LIBPROFILE_RT := $(LLVM_RTLIB_PATH)/libclang_rt.profile-x86_64-android.a
 TARGET_LIBCRT_BUILTINS := $(LLVM_RTLIB_PATH)/libclang_rt.builtins-x86_64-android.a
+TARGET_LIBUNWIND := $(LLVM_RTLIB_PATH)/x86_64/libunwind.a
 
 # Address sanitizer clang config
 ADDRESS_SANITIZER_LINKER := /system/bin/linker_asan64
 ADDRESS_SANITIZER_LINKER_FILE := /system/bin/bootstrap/linker_asan64
+
+PREBUILT_LIBCXX_ARCH_DIR := x86_64
diff --git a/core/config.mk b/core/config.mk
index ae65944..bd905dc 100644
--- a/core/config.mk
+++ b/core/config.mk
@@ -1246,6 +1246,16 @@
 # in the source tree.
 dont_bother_goals := out product-graph
 
+ifeq ($(TARGET_SYSTEM_PROP),)
+TARGET_SYSTEM_PROP := $(wildcard $(TARGET_DEVICE_DIR)/system.prop)
+endif
+
+ifeq ($(TARGET_SYSTEM_EXT_PROP),)
+TARGET_SYSTEM_EXT_PROP := $(wildcard $(TARGET_DEVICE_DIR)/system_ext.prop)
+endif
+
+.KATI_READONLY += TARGET_SYSTEM_PROP TARGET_SYSTEM_EXT_PROP
+
 include $(BUILD_SYSTEM)/sysprop_config.mk
 
 # Make ANDROID Soong config variables visible to Android.mk files, for
diff --git a/core/install_jni_libs_internal.mk b/core/install_jni_libs_internal.mk
index 5491247..4959edd 100644
--- a/core/install_jni_libs_internal.mk
+++ b/core/install_jni_libs_internal.mk
@@ -38,8 +38,9 @@
       $(error LOCAL_SDK_VERSION must be defined with LOCAL_NDK_STL_VARIANT, \
           LOCAL_PACKAGE_NAME=$(LOCAL_PACKAGE_NAME))
     endif
+    my_libcxx_arch := $($(LOCAL_2ND_ARCH_VAR_PREFIX)PREBUILT_LIBCXX_ARCH_DIR)
     my_jni_shared_libraries += \
-        $(HISTORICAL_NDK_VERSIONS_ROOT)/$(LOCAL_NDK_VERSION)/sources/cxx-stl/llvm-libc++/libs/$(TARGET_$(my_2nd_arch_prefix)CPU_ABI)/libc++_shared.so
+        $(LLVM_PREBUILTS_BASE)/$(BUILD_OS)-x86/$(LLVM_PREBUILTS_VERSION)/android_libc++/ndk/$(my_libcxx_arch)/lib/libc++_shared.so
   endif
 
   # Set the abi directory used by the local JNI shared libraries.
diff --git a/core/product.mk b/core/product.mk
index ad80ee4..8d86d92 100644
--- a/core/product.mk
+++ b/core/product.mk
@@ -26,6 +26,7 @@
 _product_single_value_vars += PRODUCT_MODEL
 _product_single_value_vars += PRODUCT_NAME_FOR_ATTESTATION
 _product_single_value_vars += PRODUCT_MODEL_FOR_ATTESTATION
+_product_single_value_vars += PRODUCT_BASE_OS
 
 # Defines the ELF segment alignment for binaries (executables and shared libraries).
 # The ELF segment alignment has to be a PAGE_SIZE multiple. For example, if
diff --git a/core/product_config.mk b/core/product_config.mk
index cc2fea9..738d4cf 100644
--- a/core/product_config.mk
+++ b/core/product_config.mk
@@ -311,6 +311,14 @@
 
 TARGET_DEVICE := $(PRODUCT_DEVICE)
 
+# Allow overriding PLATFORM_BASE_OS when PRODUCT_BASE_OS is defined
+ifdef PRODUCT_BASE_OS
+  PLATFORM_BASE_OS := $(PRODUCT_BASE_OS)
+else
+  PLATFORM_BASE_OS := $(PLATFORM_BASE_OS_ENV_INPUT)
+endif
+.KATI_READONLY := PLATFORM_BASE_OS
+
 # TODO: also keep track of things like "port", "land" in product files.
 
 # Figure out which resoure configuration options to use for this
diff --git a/core/ravenwood_test_config_template.xml b/core/ravenwood_test_config_template.xml
index 088a55a..2f21bae 100644
--- a/core/ravenwood_test_config_template.xml
+++ b/core/ravenwood_test_config_template.xml
@@ -21,7 +21,6 @@
     <option name="java-folder" value="prebuilts/jdk/jdk21/linux-x86/" />
     <option name="use-ravenwood-resources" value="true" />
     <option name="exclude-paths" value="java" />
-    <option name="socket-timeout" value="10000" />
     <option name="null-device" value="true" />
 
     {EXTRA_CONFIGS}
diff --git a/core/soong_config.mk b/core/soong_config.mk
index 72ee2e4..5fca203 100644
--- a/core/soong_config.mk
+++ b/core/soong_config.mk
@@ -340,12 +340,20 @@
 
 $(call add_json_list, OemProperties, $(PRODUCT_OEM_PROPERTIES))
 
+$(call add_json_list, SystemPropFiles, $(TARGET_SYSTEM_PROP))
+$(call add_json_list, SystemExtPropFiles, $(TARGET_SYSTEM_EXT_PROP))
+
 # Do not set ArtTargetIncludeDebugBuild into any value if PRODUCT_ART_TARGET_INCLUDE_DEBUG_BUILD is not set,
 # to have the same behavior from runtime_libart.mk.
 ifneq ($(PRODUCT_ART_TARGET_INCLUDE_DEBUG_BUILD),)
 $(call add_json_bool, ArtTargetIncludeDebugBuild, $(PRODUCT_ART_TARGET_INCLUDE_DEBUG_BUILD))
 endif
 
+_config_enable_uffd_gc := \
+  $(firstword $(OVERRIDE_ENABLE_UFFD_GC) $(PRODUCT_ENABLE_UFFD_GC) default)
+$(call add_json_str, EnableUffdGc, $(_config_enable_uffd_gc))
+_config_enable_uffd_gc :=
+
 $(call json_end)
 
 $(file >$(SOONG_VARIABLES).tmp,$(json_contents))
diff --git a/core/soong_extra_config.mk b/core/soong_extra_config.mk
index e4432d2..76da0d7 100644
--- a/core/soong_extra_config.mk
+++ b/core/soong_extra_config.mk
@@ -48,11 +48,6 @@
 
 $(call add_json_bool, SdkBuild, $(filter sdk sdk_addon,$(MAKECMDGOALS)))
 
-_config_enable_uffd_gc := \
-  $(firstword $(OVERRIDE_ENABLE_UFFD_GC) $(PRODUCT_ENABLE_UFFD_GC) default)
-$(call add_json_str, EnableUffdGc, $(_config_enable_uffd_gc))
-_config_enable_uffd_gc :=
-
 $(call add_json_str, SystemServerCompilerFilter, $(PRODUCT_SYSTEM_SERVER_COMPILER_FILTER))
 
 $(call add_json_bool, Product16KDeveloperOption, $(filter true,$(PRODUCT_16K_DEVELOPER_OPTION)))
@@ -93,6 +88,8 @@
 
 $(call add_json_list, BuildVersionTags, $(BUILD_VERSION_TAGS))
 
+$(call add_json_bool, ProductNotDebuggableInUserdebug, $(PRODUCT_NOT_DEBUGGABLE_IN_USERDEBUG))
+
 $(call json_end)
 
 $(shell mkdir -p $(dir $(SOONG_EXTRA_VARIABLES)))
diff --git a/core/sysprop.mk b/core/sysprop.mk
index 47d8a41..6d65e19 100644
--- a/core/sysprop.mk
+++ b/core/sysprop.mk
@@ -33,34 +33,26 @@
     echo "# from generate-common-build-props" >> $(2);\
     echo "# These properties identify this partition image." >> $(2);\
     echo "####################################" >> $(2);\
-    $(if $(filter system,$(1)),\
-        echo "ro.product.$(1).brand=$(PRODUCT_SYSTEM_BRAND)" >> $(2);\
-        echo "ro.product.$(1).device=$(PRODUCT_SYSTEM_DEVICE)" >> $(2);\
-        echo "ro.product.$(1).manufacturer=$(PRODUCT_SYSTEM_MANUFACTURER)" >> $(2);\
-        echo "ro.product.$(1).model=$(PRODUCT_SYSTEM_MODEL)" >> $(2);\
-        echo "ro.product.$(1).name=$(PRODUCT_SYSTEM_NAME)" >> $(2);\
-      ,\
-        echo "ro.product.$(1).brand=$(PRODUCT_BRAND)" >> $(2);\
-        echo "ro.product.$(1).device=$(TARGET_DEVICE)" >> $(2);\
-        echo "ro.product.$(1).manufacturer=$(PRODUCT_MANUFACTURER)" >> $(2);\
-        echo "ro.product.$(1).model=$(PRODUCT_MODEL)" >> $(2);\
-        echo "ro.product.$(1).name=$(TARGET_PRODUCT)" >> $(2);\
-        if [ -n "$(strip $(PRODUCT_MODEL_FOR_ATTESTATION))" ]; then \
-            echo "ro.product.model_for_attestation=$(PRODUCT_MODEL_FOR_ATTESTATION)" >> $(2);\
-        fi; \
-        if [ -n "$(strip $(PRODUCT_BRAND_FOR_ATTESTATION))" ]; then \
-            echo "ro.product.brand_for_attestation=$(PRODUCT_BRAND_FOR_ATTESTATION)" >> $(2);\
-        fi; \
-        if [ -n "$(strip $(PRODUCT_NAME_FOR_ATTESTATION))" ]; then \
-            echo "ro.product.name_for_attestation=$(PRODUCT_NAME_FOR_ATTESTATION)" >> $(2);\
-        fi; \
-        if [ -n "$(strip $(PRODUCT_DEVICE_FOR_ATTESTATION))" ]; then \
-            echo "ro.product.device_for_attestation=$(PRODUCT_DEVICE_FOR_ATTESTATION)" >> $(2);\
-        fi; \
-        if [ -n "$(strip $(PRODUCT_MANUFACTURER_FOR_ATTESTATION))" ]; then \
-            echo "ro.product.manufacturer_for_attestation=$(PRODUCT_MANUFACTURER_FOR_ATTESTATION)" >> $(2);\
-        fi; \
-    )\
+    echo "ro.product.$(1).brand=$(PRODUCT_BRAND)" >> $(2);\
+    echo "ro.product.$(1).device=$(TARGET_DEVICE)" >> $(2);\
+    echo "ro.product.$(1).manufacturer=$(PRODUCT_MANUFACTURER)" >> $(2);\
+    echo "ro.product.$(1).model=$(PRODUCT_MODEL)" >> $(2);\
+    echo "ro.product.$(1).name=$(TARGET_PRODUCT)" >> $(2);\
+    if [ -n "$(strip $(PRODUCT_MODEL_FOR_ATTESTATION))" ]; then \
+        echo "ro.product.model_for_attestation=$(PRODUCT_MODEL_FOR_ATTESTATION)" >> $(2);\
+    fi; \
+    if [ -n "$(strip $(PRODUCT_BRAND_FOR_ATTESTATION))" ]; then \
+        echo "ro.product.brand_for_attestation=$(PRODUCT_BRAND_FOR_ATTESTATION)" >> $(2);\
+    fi; \
+    if [ -n "$(strip $(PRODUCT_NAME_FOR_ATTESTATION))" ]; then \
+        echo "ro.product.name_for_attestation=$(PRODUCT_NAME_FOR_ATTESTATION)" >> $(2);\
+    fi; \
+    if [ -n "$(strip $(PRODUCT_DEVICE_FOR_ATTESTATION))" ]; then \
+        echo "ro.product.device_for_attestation=$(PRODUCT_DEVICE_FOR_ATTESTATION)" >> $(2);\
+    fi; \
+    if [ -n "$(strip $(PRODUCT_MANUFACTURER_FOR_ATTESTATION))" ]; then \
+        echo "ro.product.manufacturer_for_attestation=$(PRODUCT_MANUFACTURER_FOR_ATTESTATION)" >> $(2);\
+    fi; \
     $(if $(filter true,$(ZYGOTE_FORCE_64)),\
         $(if $(filter vendor,$(1)),\
             echo "ro.$(1).product.cpu.abilist=$(TARGET_CPU_ABI_LIST_64_BIT)" >> $(2);\
@@ -226,50 +218,11 @@
 # -----------------------------------------------------------------
 # system/build.prop
 #
-# Note: parts of this file that can't be generated by the build-properties
-# macro are manually created as separate files and then fed into the macro
-
-buildinfo_prop := $(call intermediates-dir-for,ETC,buildinfo.prop)/buildinfo.prop
-
-ifdef TARGET_SYSTEM_PROP
-system_prop_file := $(TARGET_SYSTEM_PROP)
-else
-system_prop_file := $(wildcard $(TARGET_DEVICE_DIR)/system.prop)
-endif
-
-_prop_files_ := \
-  $(buildinfo_prop) \
-  $(system_prop_file)
-
-# Order matters here. When there are duplicates, the last one wins.
-# TODO(b/117892318): don't allow duplicates so that the ordering doesn't matter
-_prop_vars_ := \
-    ADDITIONAL_SYSTEM_PROPERTIES \
-    PRODUCT_SYSTEM_PROPERTIES
-
-# TODO(b/117892318): deprecate this
-_prop_vars_ += \
-    PRODUCT_SYSTEM_DEFAULT_PROPERTIES
-
-ifndef property_overrides_split_enabled
-_prop_vars_ += \
-    ADDITIONAL_VENDOR_PROPERTIES \
-    PRODUCT_VENDOR_PROPERTIES
-endif
+# system/build.prop is built by Soong. See system-build.prop module in
+# build/soong/Android.bp.
 
 INSTALLED_BUILD_PROP_TARGET := $(TARGET_OUT)/build.prop
 
-$(eval $(call build-properties,\
-    system,\
-    $(INSTALLED_BUILD_PROP_TARGET),\
-    $(_prop_files_),\
-    $(_prop_vars_),\
-    $(PRODUCT_SYSTEM_PROPERTY_BLACKLIST),\
-    $(empty),\
-    $(empty)))
-
-$(eval $(call declare-1p-target,$(INSTALLED_BUILD_PROP_TARGET)))
-
 # -----------------------------------------------------------------
 # vendor/build.prop
 #
@@ -442,25 +395,10 @@
 # -----------------------------------------------------------------
 # system_ext/etc/build.prop
 #
-_prop_files_ := $(if $(TARGET_SYSTEM_EXT_PROP),\
-    $(TARGET_SYSTEM_EXT_PROP),\
-    $(wildcard $(TARGET_DEVICE_DIR)/system_ext.prop))
-
-# Order matters here. When there are duplicates, the last one wins.
-# TODO(b/117892318): don't allow duplicates so that the ordering doesn't matter
-_prop_vars_ := PRODUCT_SYSTEM_EXT_PROPERTIES
+# system_ext/build.prop is built by Soong. See system-build.prop module in
+# build/soong/Android.bp.
 
 INSTALLED_SYSTEM_EXT_BUILD_PROP_TARGET := $(TARGET_OUT_SYSTEM_EXT)/etc/build.prop
-$(eval $(call build-properties,\
-    system_ext,\
-    $(INSTALLED_SYSTEM_EXT_BUILD_PROP_TARGET),\
-    $(_prop_files_),\
-    $(_prop_vars_),\
-    $(empty),\
-    $(empty),\
-    $(empty)))
-
-$(eval $(call declare-1p-target,$(INSTALLED_SYSTEM_EXT_BUILD_PROP_TARGET)))
 
 # ----------------------------------------------------------------
 # ramdisk/boot/etc/build.prop
diff --git a/core/sysprop_config.mk b/core/sysprop_config.mk
index f9b9d1c..543b86b 100644
--- a/core/sysprop_config.mk
+++ b/core/sysprop_config.mk
@@ -15,28 +15,7 @@
 )
 _additional_prop_var_names :=
 
-#
-# -----------------------------------------------------------------
-# Add the product-defined properties to the build properties.
-ifneq ($(BOARD_PROPERTY_OVERRIDES_SPLIT_ENABLED), true)
-  ADDITIONAL_SYSTEM_PROPERTIES += $(PRODUCT_PROPERTY_OVERRIDES)
-else
-  ifndef BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE
-    ADDITIONAL_SYSTEM_PROPERTIES += $(PRODUCT_PROPERTY_OVERRIDES)
-  endif
-endif
-
-ADDITIONAL_SYSTEM_PROPERTIES += ro.treble.enabled=${PRODUCT_FULL_TREBLE}
-
-# Set ro.llndk.api_level to show the maximum vendor API level that the LLNDK in
-# the system partition supports.
-ifdef RELEASE_BOARD_API_LEVEL
-ADDITIONAL_SYSTEM_PROPERTIES += ro.llndk.api_level=$(RELEASE_BOARD_API_LEVEL)
-endif
-
-# Sets ro.actionable_compatible_property.enabled to know on runtime whether the
-# allowed list of actionable compatible properties is enabled or not.
-ADDITIONAL_SYSTEM_PROPERTIES += ro.actionable_compatible_property.enabled=true
+$(KATI_obsolete_var ADDITIONAL_SYSTEM_PROPERTIES,Use build/soong/scripts/gen_build_prop.py instead)
 
 # Add the system server compiler filter if they are specified for the product.
 ifneq (,$(PRODUCT_SYSTEM_SERVER_COMPILER_FILTER))
@@ -56,23 +35,6 @@
 ADDITIONAL_PRODUCT_PROPERTIES += ro.product.page_size=4096
 endif
 
-# Enable core platform API violation warnings on userdebug and eng builds.
-ifneq ($(TARGET_BUILD_VARIANT),user)
-ADDITIONAL_SYSTEM_PROPERTIES += persist.debug.dalvik.vm.core_platform_api_policy=just-warn
-endif
-
-# Define ro.sanitize.<name> properties for all global sanitizers.
-ADDITIONAL_SYSTEM_PROPERTIES += $(foreach s,$(SANITIZE_TARGET),ro.sanitize.$(s)=true)
-
-# Sets the default value of ro.postinstall.fstab.prefix to /system.
-# Device board config should override the value to /product when needed by:
-#
-#     PRODUCT_PRODUCT_PROPERTIES += ro.postinstall.fstab.prefix=/product
-#
-# It then uses ${ro.postinstall.fstab.prefix}/etc/fstab.postinstall to
-# mount system_other partition.
-ADDITIONAL_SYSTEM_PROPERTIES += ro.postinstall.fstab.prefix=/system
-
 # Add cpu properties for bionic and ART.
 ADDITIONAL_VENDOR_PROPERTIES += ro.bionic.arch=$(TARGET_ARCH)
 ADDITIONAL_VENDOR_PROPERTIES += ro.bionic.cpu_variant=$(TARGET_CPU_VARIANT_RUNTIME)
@@ -200,87 +162,6 @@
 endif
 
 user_variant := $(filter user userdebug,$(TARGET_BUILD_VARIANT))
-enable_target_debugging := true
-enable_dalvik_lock_contention_logging := true
-ifneq (,$(user_variant))
-  # Target is secure in user builds.
-  ADDITIONAL_SYSTEM_PROPERTIES += ro.secure=1
-  ADDITIONAL_SYSTEM_PROPERTIES += security.perf_harden=1
-
-  ifeq ($(user_variant),user)
-    ADDITIONAL_SYSTEM_PROPERTIES += ro.adb.secure=1
-  endif
-
-  ifneq ($(user_variant),userdebug)
-    # Disable debugging in plain user builds.
-    enable_target_debugging :=
-    enable_dalvik_lock_contention_logging :=
-  else
-    # Disable debugging in userdebug builds if PRODUCT_NOT_DEBUGGABLE_IN_USERDEBUG
-    # is set.
-    ifneq (,$(strip $(PRODUCT_NOT_DEBUGGABLE_IN_USERDEBUG)))
-      enable_target_debugging :=
-    endif
-  endif
-
-  # Disallow mock locations by default for user builds
-  ADDITIONAL_SYSTEM_PROPERTIES += ro.allow.mock.location=0
-
-else # !user_variant
-  # Turn on checkjni for non-user builds.
-  ADDITIONAL_SYSTEM_PROPERTIES += ro.kernel.android.checkjni=1
-  # Set device insecure for non-user builds.
-  ADDITIONAL_SYSTEM_PROPERTIES += ro.secure=0
-  # Allow mock locations by default for non user builds
-  ADDITIONAL_SYSTEM_PROPERTIES += ro.allow.mock.location=1
-endif # !user_variant
-
-ifeq (true,$(strip $(enable_dalvik_lock_contention_logging)))
-  # Enable Dalvik lock contention logging.
-  ADDITIONAL_SYSTEM_PROPERTIES += dalvik.vm.lockprof.threshold=500
-endif # !enable_dalvik_lock_contention_logging
-
-ifeq (true,$(strip $(enable_target_debugging)))
-  # Target is more debuggable and adbd is on by default
-  ADDITIONAL_SYSTEM_PROPERTIES += ro.debuggable=1
-else # !enable_target_debugging
-  # Target is less debuggable and adbd is off by default
-  ADDITIONAL_SYSTEM_PROPERTIES += ro.debuggable=0
-endif # !enable_target_debugging
-
-enable_target_debugging:=
-enable_dalvik_lock_contention_logging:=
-
-ifneq ($(filter sdk sdk_addon,$(MAKECMDGOALS)),)
-_is_sdk_build := true
-endif
-
-ifeq ($(TARGET_BUILD_VARIANT),eng)
-ifneq ($(filter ro.setupwizard.mode=ENABLED, $(call collapse-pairs, $(ADDITIONAL_SYSTEM_PROPERTIES))),)
-  # Don't require the setup wizard on eng builds
-  ADDITIONAL_SYSTEM_PROPERTIES := $(filter-out ro.setupwizard.mode=%,\
-          $(call collapse-pairs, $(ADDITIONAL_SYSTEM_PROPERTIES))) \
-          ro.setupwizard.mode=OPTIONAL
-endif
-ifndef _is_sdk_build
-  # To speedup startup of non-preopted builds, don't verify or compile the boot image.
-  ADDITIONAL_SYSTEM_PROPERTIES += dalvik.vm.image-dex2oat-filter=extract
-endif
-# b/323566535
-ADDITIONAL_SYSTEM_PROPERTIES += init.svc_debug.no_fatal.zygote=true
-endif
-
-ifdef _is_sdk_build
-ADDITIONAL_SYSTEM_PROPERTIES += xmpp.auto-presence=true
-ADDITIONAL_SYSTEM_PROPERTIES += ro.config.nocheckin=yes
-endif
-
-_is_sdk_build :=
-
-ADDITIONAL_SYSTEM_PROPERTIES += net.bt.name=Android
-
-# This property is set by flashing debug boot image, so default to false.
-ADDITIONAL_SYSTEM_PROPERTIES += ro.force.debuggable=0
 
 config_enable_uffd_gc := \
   $(firstword $(OVERRIDE_ENABLE_UFFD_GC) $(PRODUCT_ENABLE_UFFD_GC) default)
@@ -291,11 +172,9 @@
 # If the value is "default", it will be mangled by post_process_props.py.
 ADDITIONAL_PRODUCT_PROPERTIES += ro.dalvik.vm.enable_uffd_gc=$(config_enable_uffd_gc)
 
-ADDITIONAL_SYSTEM_PROPERTIES := $(strip $(ADDITIONAL_SYSTEM_PROPERTIES))
 ADDITIONAL_PRODUCT_PROPERTIES := $(strip $(ADDITIONAL_PRODUCT_PROPERTIES))
 ADDITIONAL_VENDOR_PROPERTIES := $(strip $(ADDITIONAL_VENDOR_PROPERTIES))
 
 .KATI_READONLY += \
-    ADDITIONAL_SYSTEM_PROPERTIES \
     ADDITIONAL_PRODUCT_PROPERTIES \
     ADDITIONAL_VENDOR_PROPERTIES
diff --git a/core/tasks/meta-lic.mk b/core/tasks/meta-lic.mk
index 85357eb..24adfc8 100644
--- a/core/tasks/meta-lic.mk
+++ b/core/tasks/meta-lic.mk
@@ -83,6 +83,40 @@
 $(eval $(call declare-1p-copy-files,device/google/coral,audio_policy_configuration.xml))
 $(eval $(call declare-1p-copy-files,device/google/coral,display_19260504575090817.xml))
 
+# Moved here from device/google/cuttlefish/Android.mk
+$(eval $(call declare-copy-files-license-metadata,device/google/cuttlefish,.idc,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,))
+$(eval $(call declare-copy-files-license-metadata,device/google/cuttlefish,default-permissions.xml,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,))
+$(eval $(call declare-copy-files-license-metadata,device/google/cuttlefish,libnfc-nci.conf,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,))
+$(eval $(call declare-copy-files-license-metadata,device/google/cuttlefish,fstab.postinstall,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,))
+$(eval $(call declare-copy-files-license-metadata,device/google/cuttlefish,ueventd.rc,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,))
+$(eval $(call declare-copy-files-license-metadata,device/google/cuttlefish,wpa_supplicant.conf,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,))
+$(eval $(call declare-copy-files-license-metadata,device/google/cuttlefish,hals.conf,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,))
+$(eval $(call declare-copy-files-license-metadata,device/google/cuttlefish,device_state_configuration.xml,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,))
+$(eval $(call declare-copy-files-license-metadata,device/google/cuttlefish,p2p_supplicant.conf,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,))
+$(eval $(call declare-copy-files-license-metadata,device/google/cuttlefish,wpa_supplicant.conf,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,))
+$(eval $(call declare-copy-files-license-metadata,device/google/cuttlefish,wpa_supplicant_overlay.conf,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,))
+$(eval $(call declare-copy-files-license-metadata,device/google/cuttlefish,wpa_supplicant.rc,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,))
+$(eval $(call declare-copy-files-license-metadata,device/google/cuttlefish,init.cutf_cvm.rc,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,))
+$(eval $(call declare-copy-files-license-metadata,device/google/cuttlefish,fstab.cf.f2fs.hctr2,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,))
+$(eval $(call declare-copy-files-license-metadata,device/google/cuttlefish,fstab.cf.f2fs.cts,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,))
+$(eval $(call declare-copy-files-license-metadata,device/google/cuttlefish,fstab.cf.ext4.hctr2,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,))
+$(eval $(call declare-copy-files-license-metadata,device/google/cuttlefish,fstab.cf.ext4.cts,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,))
+$(eval $(call declare-copy-files-license-metadata,device/google/cuttlefish,init.rc,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,))
+$(eval $(call declare-copy-files-license-metadata,device/google/cuttlefish,audio_policy.conf,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,))
+
+$(eval $(call declare-copy-files-license-metadata,device/google/cuttlefish/shared/config,pci.ids,SPDX-license-identifier-BSD-3-Clause,notice,device/google/cuttlefish/shared/config/LICENSE_BSD,))
+
+$(eval $(call declare-1p-copy-files,device/google/cuttlefish,privapp-permissions-cuttlefish.xml))
+$(eval $(call declare-1p-copy-files,device/google/cuttlefish,media_profiles_V1_0.xml))
+$(eval $(call declare-1p-copy-files,device/google/cuttlefish,media_codecs_performance.xml))
+$(eval $(call declare-1p-copy-files,device/google/cuttlefish,cuttlefish_excluded_hardware.xml))
+$(eval $(call declare-1p-copy-files,device/google/cuttlefish,media_codecs.xml))
+$(eval $(call declare-1p-copy-files,device/google/cuttlefish,media_codecs_google_video.xml))
+$(eval $(call declare-1p-copy-files,device/google/cuttlefish,car_audio_configuration.xml))
+$(eval $(call declare-1p-copy-files,device/google/cuttlefish,audio_policy_configuration.xml))
+$(eval $(call declare-1p-copy-files,device/google/cuttlefish,preinstalled-packages-product-car-cuttlefish.xml))
+$(eval $(call declare-1p-copy-files,hardware/google/camera/devices,.json))
+
 # Moved here from device/google/gs101/Android.mk
 $(eval $(call declare-copy-files-license-metadata,device/google/gs101,default-permissions.xml,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,))
 $(eval $(call declare-copy-files-license-metadata,device/google/gs101,libnfc-nci.conf,SPDX-license-identifier-Apache-2.0,notice,build/soong/licenses/LICENSE,))
diff --git a/core/version_util.mk b/core/version_util.mk
index eb568be..0e34634 100644
--- a/core/version_util.mk
+++ b/core/version_util.mk
@@ -183,14 +183,17 @@
 endif
 .KATI_READONLY := PLATFORM_SECURITY_PATCH_TIMESTAMP
 
-ifndef PLATFORM_BASE_OS
-  # Used to indicate the base os applied to the device.
-  # Can be an arbitrary string, but must be a single word.
-  #
-  # If there is no $PLATFORM_BASE_OS set, keep it empty.
-  PLATFORM_BASE_OS :=
-endif
-.KATI_READONLY := PLATFORM_BASE_OS
+# PLATFORM_BASE_OS is used to indicate the base os applied
+# to the device. Can be an arbitrary string, but must be a
+# single word.
+#
+# If there is no $PLATFORM_BASE_OS set, keep it empty.
+#
+# PLATFORM_BASE_OS can either be set via an enviornment
+# variable, or set via the PRODUCT_BASE_OS product variable.
+PLATFORM_BASE_OS_ENV_INPUT := $(PLATFORM_BASE_OS)
+.KATI_READONLY := PLATFORM_BASE_OS_ENV_INPUT
+PLATFORM_BASE_OS :=
 
 ifndef BUILD_ID
   # Used to signify special builds.  E.g., branches and/or releases,
diff --git a/target/product/base_system.mk b/target/product/base_system.mk
index 2b726c1..5b54051 100644
--- a/target/product/base_system.mk
+++ b/target/product/base_system.mk
@@ -280,6 +280,7 @@
     storaged \
     surfaceflinger \
     svc \
+    system-build.prop \
     task_profiles.json \
     tc \
     telecom \
diff --git a/target/product/base_system_ext.mk b/target/product/base_system_ext.mk
index 92ca227..febe537 100644
--- a/target/product/base_system_ext.mk
+++ b/target/product/base_system_ext.mk
@@ -24,6 +24,7 @@
     SatelliteClient \
     selinux_policy_system_ext \
     system_ext_manifest.xml \
+    system_ext-build.prop \
 
 # Base modules when shipping api level is less than or equal to 34
 PRODUCT_PACKAGES_SHIPPING_API_LEVEL_34 += \
diff --git a/tools/aconfig/aconfig/src/codegen/java.rs b/tools/aconfig/aconfig/src/codegen/java.rs
index 7238590..727f810 100644
--- a/tools/aconfig/aconfig/src/codegen/java.rs
+++ b/tools/aconfig/aconfig/src/codegen/java.rs
@@ -518,8 +518,8 @@
         let expected_featureflagsmpl_content_1 = r#"
         /** @hide */
         public final class FeatureFlagsImpl implements FeatureFlags {
-            private static boolean aconfig_test_is_cached = false;
-            private static boolean other_namespace_is_cached = false;
+            private static volatile boolean aconfig_test_is_cached = false;
+            private static volatile boolean other_namespace_is_cached = false;
             private static boolean disabledRw = false;
             private static boolean disabledRwExported = false;
             private static boolean disabledRwInOtherNamespace = false;
@@ -886,7 +886,7 @@
         import android.provider.DeviceConfig.Properties;
         /** @hide */
         public final class FeatureFlagsImpl implements FeatureFlags {
-            private static boolean aconfig_test_is_cached = false;
+            private static volatile boolean aconfig_test_is_cached = false;
             private static boolean disabledRwExported = false;
             private static boolean enabledFixedRoExported = false;
             private static boolean enabledRoExported = false;
diff --git a/tools/aconfig/aconfig/templates/FeatureFlagsImpl.java.template b/tools/aconfig/aconfig/templates/FeatureFlagsImpl.java.template
index d93d302..97d1254 100644
--- a/tools/aconfig/aconfig/templates/FeatureFlagsImpl.java.template
+++ b/tools/aconfig/aconfig/templates/FeatureFlagsImpl.java.template
@@ -22,7 +22,7 @@
 public final class FeatureFlagsImpl implements FeatureFlags \{
 {{ -if runtime_lookup_required }}
 {{ -for namespace_with_flags in namespace_flags }}
-    private static boolean {namespace_with_flags.namespace}_is_cached = false;
+    private static volatile boolean {namespace_with_flags.namespace}_is_cached = false;
 {{ -endfor- }}
 
 {{ for flag in flag_elements }}
diff --git a/tools/aconfig/aconfig_storage_read_api/srcs/android/aconfig/storage/StorageInternalReader.java b/tools/aconfig/aconfig_storage_read_api/srcs/android/aconfig/storage/StorageInternalReader.java
index bbb6813..f73f35e 100644
--- a/tools/aconfig/aconfig_storage_read_api/srcs/android/aconfig/storage/StorageInternalReader.java
+++ b/tools/aconfig/aconfig_storage_read_api/srcs/android/aconfig/storage/StorageInternalReader.java
@@ -18,9 +18,11 @@
 
 import android.compat.annotation.UnsupportedAppUsage;
 
-import java.io.FileInputStream;
+import java.io.Closeable;
 import java.nio.MappedByteBuffer;
 import java.nio.channels.FileChannel;
+import java.nio.file.Paths;
+import java.nio.file.StandardOpenOption;
 
 /** @hide */
 public class StorageInternalReader {
@@ -68,13 +70,25 @@
 
     // Map a storage file given file path
     private static MappedByteBuffer mapStorageFile(String file) {
+        FileChannel channel = null;
         try {
-            FileInputStream stream = new FileInputStream(file);
-            FileChannel channel = stream.getChannel();
+            channel = FileChannel.open(Paths.get(file), StandardOpenOption.READ);
             return channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());
         } catch (Exception e) {
             throw new AconfigStorageException(
                     String.format("Fail to mmap storage file %s", file), e);
+        } finally {
+            quietlyDispose(channel);
+        }
+    }
+
+    private static void quietlyDispose(Closeable closable) {
+        try {
+            if (closable != null) {
+                closable.close();
+            }
+        } catch (Exception e) {
+            // no need to care, at least as of now
         }
     }
 }
diff --git a/tools/ide_query/prober_scripts/jvm/Foo.java b/tools/ide_query/prober_scripts/jvm/Foo.java
new file mode 100644
index 0000000..a043f72
--- /dev/null
+++ b/tools/ide_query/prober_scripts/jvm/Foo.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package jvm;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+
+/** Foo class. */
+public final class Foo {
+
+  void testCompletion() {
+    ArrayList<Integer> list = new ArrayList<>();
+    System.out.println(list);
+
+    // ^
+
+    // step
+    // ; Test completion on the standard types.
+    // type("list.")
+    // completion.trigger()
+    // assert completion.items.filter(label="add.*")
+  }
+}
diff --git a/tools/ide_query/prober_scripts/jvm/suite.textpb b/tools/ide_query/prober_scripts/jvm/suite.textpb
new file mode 100644
index 0000000..460e08c
--- /dev/null
+++ b/tools/ide_query/prober_scripts/jvm/suite.textpb
@@ -0,0 +1,4 @@
+tests: {
+  name: "general"
+  scripts: "build/make/tools/ide_query/prober_scripts/jvm/Foo.java"
+}
diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py
index 4834834..f6f6944 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -2434,12 +2434,23 @@
         "Failed to obtain minSdkVersion for {}: aapt2 return code {}:\n{}\n{}".format(
             apk_name, proc.returncode, stdoutdata, stderrdata))
 
+  is_split_apk = False
   for line in stdoutdata.split("\n"):
+    # See b/353837347 , split APKs do not have sdk version defined,
+    # so we default to 21 as split APKs are only supported since SDK
+    # 21.
+    if (re.search(r"split=[\"'].*[\"']", line)):
+      is_split_apk = True
     # Due to ag/24161708, looking for lines such as minSdkVersion:'23',minSdkVersion:'M'
     # or sdkVersion:'23', sdkVersion:'M'.
     m = re.match(r'(?:minSdkVersion|sdkVersion):\'([^\']*)\'', line)
     if m:
       return m.group(1)
+  if is_split_apk:
+    logger.info("%s is a split APK, it does not have minimum SDK version"
+                " defined. Defaulting to 21 because split APK isn't supported"
+                " before that.", apk_name)
+    return 21
   raise ExternalError("No minSdkVersion returned by aapt2 for apk: {}".format(apk_name))