Merge "Remove module_build_from_source soong config variable" into main
diff --git a/ci/build_test_suites.py b/ci/build_test_suites.py
index 75dd9f2..deb1f1d 100644
--- a/ci/build_test_suites.py
+++ b/ci/build_test_suites.py
@@ -81,6 +81,7 @@
 
     build_targets = set()
     packaging_functions = set()
+    self.file_download_options = self._aggregate_file_download_options()
     for target in self.args.extra_targets:
       if self._unused_target_exclusion_enabled(
           target
@@ -107,49 +108,24 @@
 
   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
+    regex = r'\b(%s)\b' % re.escape(target)
+    return any(re.search(regex, opt) for opt in self.file_download_options)
 
-  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]:
+  def _aggregate_file_download_options(self) -> set[str]:
     """Lists out all test config options to specify targets to download.
 
     These come in the form of regexes.
     """
-    all_regexes = set()
+    all_options = 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
+          all_options.update(opt.get('values', []))
+    return all_options
 
   def _get_test_infos(self):
     return self.build_context.get('testContext', dict()).get('testInfos', [])
diff --git a/ci/build_test_suites_test.py b/ci/build_test_suites_test.py
index 25c072e..463bdd0 100644
--- a/ci/build_test_suites_test.py
+++ b/ci/build_test_suites_test.py
@@ -380,6 +380,25 @@
 
     self.assertSetEqual(build_plan.build_targets, set())
 
+  def test_target_regex_matching_not_too_broad(self):
+    build_target = 'test_target'
+    test_context = self.get_test_context(build_target)
+    test_context['testInfos'][0]['extraOptions'] = [{
+        'key': 'additional-files-filter',
+        'values': [f'.*a{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, set())
+
   def create_build_planner(
       self,
       build_targets: set[str],
diff --git a/core/Makefile b/core/Makefile
index 96588e3..1e7e3f2 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -6883,6 +6883,33 @@
 	$(hide) echo "$(BOARD_KERNEL_PAGESIZE)" > $(zip_root)/INIT_BOOT/pagesize
 endif # BOARD_KERNEL_PAGESIZE
 endif # BUILDING_INIT_BOOT_IMAGE
+ifdef BOARD_EROFS_COMPRESS_HINTS
+	$(hide) cp $(BOARD_EROFS_COMPRESS_HINTS) $(zip_root)/META/erofs_default_compress_hints.txt
+endif
+ifdef BOARD_SYSTEMIMAGE_EROFS_COMPRESS_HINTS
+	$(hide) cp $(BOARD_SYSTEMIMAGE_EROFS_COMPRESS_HINTS) $(zip_root)/META/system_erofs_compress_hints.txt
+endif
+ifdef BOARD_SYSTEM_EXTIMAGE_EROFS_COMPRESS_HINTS
+	$(hide) cp $(BOARD_SYSTEM_EXTIMAGE_EROFS_COMPRESS_HINTS) $(zip_root)/META/system_ext_erofs_compress_hints.txt
+endif
+ifdef BOARD_PRODUCTIMAGE_EROFS_COMPRESS_HINTS
+	$(hide) cp $(BOARD_PRODUCTIMAGE_EROFS_COMPRESS_HINTS) $(zip_root)/META/product_erofs_compress_hints.txt
+endif
+ifdef BOARD_VENDORIMAGE_EROFS_COMPRESS_HINTS
+	$(hide) cp $(BOARD_VENDORIMAGE_EROFS_COMPRESS_HINTS) $(zip_root)/META/vendor_erofs_compress_hints.txt
+endif
+ifdef BOARD_ODMIMAGE_EROFS_COMPRESS_HINTS
+	$(hide) cp $(BOARD_ODMIMAGE_EROFS_COMPRESS_HINTS) $(zip_root)/META/odm_erofs_compress_hints.txt
+endif
+ifdef BOARD_VENDOR_DLKMIMAGE_EROFS_COMPRESS_HINTS
+	$(hide) cp $(BOARD_VENDOR_DLKMIMAGE_EROFS_COMPRESS_HINTS) $(zip_root)/META/vendor_dlkm_erofs_compress_hints.txt
+endif
+ifdef BOARD_ODM_DLKMIMAGE_EROFS_COMPRESS_HINTS
+	$(hide) cp $(BOARD_ODM_DLKMIMAGE_EROFS_COMPRESS_HINTS) $(zip_root)/META/odm_dlkm_erofs_compress_hints.txt
+endif
+ifdef BOARD_SYSTEM_DLKMIMAGE_EROFS_COMPRESS_HINTS
+	$(hide) cp $(BOARD_SYSTEM_DLKMIMAGE_EROFS_COMPRESS_HINTS) $(zip_root)/META/system_dlkm_erofs_compress_hints.txt
+endif
 ifneq ($(INSTALLED_VENDOR_BOOTIMAGE_TARGET),)
 	$(call fs_config,$(zip_root)/VENDOR_BOOT/RAMDISK,) > $(zip_root)/META/vendor_boot_filesystem_config.txt
 endif
diff --git a/tools/aconfig/aconfig/src/codegen/java.rs b/tools/aconfig/aconfig/src/codegen/java.rs
index a74ef85..dbc4ab5 100644
--- a/tools/aconfig/aconfig/src/codegen/java.rs
+++ b/tools/aconfig/aconfig/src/codegen/java.rs
@@ -698,6 +698,8 @@
         StorageInternalReader reader;
         boolean readFromNewStorage;
 
+        boolean useNewStorageValueAndDiscardOld = false;
+
         private final static String TAG = "AconfigJavaCodegen";
         private final static String SUCCESS_LOG = "success: %s value matches";
         private final static String MISMATCH_LOG = "error: %s value mismatch, new storage value is %s, old storage value is %s";
@@ -713,6 +715,9 @@
                     reader = null;
                 }
             }
+
+            useNewStorageValueAndDiscardOld =
+                DeviceConfig.getBoolean("core_experiments_team_internal", "com.android.providers.settings.use_new_storage_value", false);
         }
 
         private void load_overrides_aconfig_test() {
@@ -746,7 +751,7 @@
                         Log.i(TAG, String.format(MISMATCH_LOG, "disabledRw", val, disabledRw));
                     }
 
-                    if (DeviceConfig.getBoolean("core_experiments_team_internal", "com.android.providers.settings.use_new_storage_value", false)) {
+                    if (useNewStorageValueAndDiscardOld) {
                         disabledRw = val;
                     }
 
@@ -757,7 +762,7 @@
                         Log.i(TAG, String.format(MISMATCH_LOG, "disabledRwExported", val, disabledRwExported));
                     }
 
-                    if (DeviceConfig.getBoolean("core_experiments_team_internal", "com.android.providers.settings.use_new_storage_value", false)) {
+                    if (useNewStorageValueAndDiscardOld) {
                         disabledRwExported = val;
                     }
 
@@ -768,7 +773,7 @@
                         Log.i(TAG, String.format(MISMATCH_LOG, "enabledRw", val, enabledRw));
                     }
 
-                    if (DeviceConfig.getBoolean("core_experiments_team_internal", "com.android.providers.settings.use_new_storage_value", false)) {
+                    if (useNewStorageValueAndDiscardOld) {
                         enabledRw = val;
                     }
 
@@ -805,7 +810,7 @@
                         Log.i(TAG, String.format(MISMATCH_LOG, "disabledRwInOtherNamespace", val, disabledRwInOtherNamespace));
                     }
 
-                    if (DeviceConfig.getBoolean("core_experiments_team_internal", "com.android.providers.settings.use_new_storage_value", false)) {
+                    if (useNewStorageValueAndDiscardOld) {
                         disabledRwInOtherNamespace = val;
                     }
 
diff --git a/tools/aconfig/aconfig/templates/FeatureFlagsImpl.java.template b/tools/aconfig/aconfig/templates/FeatureFlagsImpl.java.template
index 96e7623..9970b1f 100644
--- a/tools/aconfig/aconfig/templates/FeatureFlagsImpl.java.template
+++ b/tools/aconfig/aconfig/templates/FeatureFlagsImpl.java.template
@@ -35,6 +35,8 @@
     StorageInternalReader reader;
     boolean readFromNewStorage;
 
+    boolean useNewStorageValueAndDiscardOld = false;
+
     private final static String TAG = "AconfigJavaCodegen";
     private final static String SUCCESS_LOG = "success: %s value matches";
     private final static String MISMATCH_LOG = "error: %s value mismatch, new storage value is %s, old storage value is %s";
@@ -50,6 +52,9 @@
                 reader = null;
             }
         }
+
+        useNewStorageValueAndDiscardOld =
+            DeviceConfig.getBoolean("core_experiments_team_internal", "com.android.providers.settings.use_new_storage_value", false);
     }
 
 {{ -endif }}
@@ -91,7 +96,7 @@
                     Log.i(TAG, String.format(MISMATCH_LOG, "{flag.method_name}", val, {flag.method_name}));
                 }
 
-                if (DeviceConfig.getBoolean("core_experiments_team_internal", "com.android.providers.settings.use_new_storage_value", false)) \{
+                if (useNewStorageValueAndDiscardOld) \{
                     {flag.method_name} = val;
                 }
 
diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py
index f6f6944..6cec380 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -907,9 +907,10 @@
     d["root_fs_config"] = os.path.join(
         input_file, "META", "root_filesystem_config.txt")
 
+    partitions = ["system", "vendor", "system_ext", "product", "odm",
+                  "vendor_dlkm", "odm_dlkm", "system_dlkm"]
     # Redirect {partition}_base_fs_file for each of the named partitions.
-    for part_name in ["system", "vendor", "system_ext", "product", "odm",
-                      "vendor_dlkm", "odm_dlkm", "system_dlkm"]:
+    for part_name in partitions:
       key_name = part_name + "_base_fs_file"
       if key_name not in d:
         continue
@@ -922,6 +923,25 @@
             "Failed to find %s base fs file: %s", part_name, base_fs_file)
         del d[key_name]
 
+    # Redirecting helper for optional properties like erofs_compress_hints
+    def redirect_file(prop, filename):
+      if prop not in d:
+        return
+      config_file = os.path.join(input_file, "META/" + filename)
+      if os.path.exists(config_file):
+        d[prop] = config_file
+      else:
+        logger.warning(
+            "Failed to find %s fro %s", filename, prop)
+        del d[key_name]
+
+    # Redirect erofs_[default_]compress_hints files
+    redirect_file("erofs_default_compress_hints",
+                  "erofs_default_compress_hints.txt")
+    for part in partitions:
+      redirect_file(part + "_erofs_compress_hints",
+                    part + "_erofs_compress_hints.txt")
+
   def makeint(key):
     if key in d:
       d[key] = int(d[key], 0)