Merge "Revert "Make d8-on-eng a per-module opt-out"" into main
diff --git a/android/Android.bp b/android/Android.bp
index 71e6747..97d634f 100644
--- a/android/Android.bp
+++ b/android/Android.bp
@@ -12,6 +12,7 @@
         "blueprint-gobtools",
         "blueprint-metrics",
         "blueprint-pool",
+        "blueprint-syncmap",
         "sbox_proto",
         "soong",
         "soong-android_team_proto",
diff --git a/android/androidmk.go b/android/androidmk.go
index 7845593..e328359 100644
--- a/android/androidmk.go
+++ b/android/androidmk.go
@@ -435,13 +435,18 @@
 				suffix = *dist.Suffix
 			}
 
-			productString := ""
-			if dist.Append_artifact_with_product != nil && *dist.Append_artifact_with_product {
-				productString = fmt.Sprintf("_%s", ctx.Config().DeviceProduct())
+			prependProductString := ""
+			if proptools.Bool(dist.Prepend_artifact_with_product) {
+				prependProductString = fmt.Sprintf("%s-", ctx.Config().DeviceProduct())
 			}
 
-			if suffix != "" || productString != "" {
-				dest = strings.TrimSuffix(dest, ext) + suffix + productString + ext
+			appendProductString := ""
+			if proptools.Bool(dist.Append_artifact_with_product) {
+				appendProductString = fmt.Sprintf("_%s", ctx.Config().DeviceProduct())
+			}
+
+			if suffix != "" || appendProductString != "" || prependProductString != "" {
+				dest = prependProductString + strings.TrimSuffix(dest, ext) + suffix + appendProductString + ext
 			}
 
 			if dist.Dir != nil {
@@ -510,6 +515,9 @@
 	a.EntryMap = make(map[string][]string)
 	base := mod.base()
 	name := base.BaseModuleName()
+	if bmn, ok := mod.(baseModuleName); ok {
+		name = bmn.BaseModuleName()
+	}
 	if a.OverrideName != "" {
 		name = a.OverrideName
 	}
diff --git a/android/module.go b/android/module.go
index ecd0f23..1538861 100644
--- a/android/module.go
+++ b/android/module.go
@@ -45,6 +45,14 @@
 	// For more information, see Module.GenerateBuildActions within Blueprint's module_ctx.go
 	GenerateAndroidBuildActions(ModuleContext)
 
+	// CleanupAfterBuildActions is called after ModuleBase.GenerateBuildActions is finished.
+	// If all interactions with this module are handled via providers instead of direct access
+	// to the module then it can free memory attached to the module.
+	// This is a temporary measure to reduce memory usage, eventually blueprint's reference
+	// to the Module should be dropped after GenerateAndroidBuildActions once all accesses
+	// can be done through providers.
+	CleanupAfterBuildActions()
+
 	// Add dependencies to the components of a module, i.e. modules that are created
 	// by the module and which are considered to be part of the creating module.
 	//
@@ -200,6 +208,12 @@
 	// no change to the artifact file name.
 	Append_artifact_with_product *bool `android:"arch_variant"`
 
+	// If true, then the artifact file will be prepended with <product name>-. For
+	// example, if the product is coral and the module is an android_app module
+	// of name foo, then the artifact would be coral-foo.apk. If false, there is
+	// no change to the artifact file name.
+	Prepend_artifact_with_product *bool `android:"arch_variant"`
+
 	// A string tag to select the OutputFiles associated with the tag.
 	//
 	// If no tag is specified then it will select the default dist paths provided
@@ -2387,8 +2401,12 @@
 			})
 		}
 	}
+
+	m.module.CleanupAfterBuildActions()
 }
 
+func (m *ModuleBase) CleanupAfterBuildActions() {}
+
 func SetJarJarPrefixHandler(handler func(ModuleContext)) {
 	if jarJarPrefixHandler != nil {
 		panic("jarJarPrefixHandler already set")
diff --git a/android/module_proxy.go b/android/module_proxy.go
index 561c477..81d90e9 100644
--- a/android/module_proxy.go
+++ b/android/module_proxy.go
@@ -27,6 +27,10 @@
 	panic("method is not implemented on ModuleProxy")
 }
 
+func (m ModuleProxy) CleanupAfterBuildActions() {
+	panic("method is not implemented on ModuleProxy")
+}
+
 func (m ModuleProxy) ComponentDepsMutator(ctx BottomUpMutatorContext) {
 	panic("method is not implemented on ModuleProxy")
 }
diff --git a/android/otatools_package_cert_zip.go b/android/otatools_package_cert_zip.go
index 03265ca..3a654cf 100644
--- a/android/otatools_package_cert_zip.go
+++ b/android/otatools_package_cert_zip.go
@@ -39,7 +39,7 @@
 
 var (
 	otatoolsPackageCertRule = pctx.AndroidStaticRule("otatools_package_cert_files", blueprint.RuleParams{
-		Command:     "echo $out: > ${out}.d && cat $in >> ${out}.d && ${SoongZipCmd} -o $out -l $in",
+		Command:     "echo '$out : ' $$(cat $in) > ${out}.d && ${SoongZipCmd} -o $out -l $in",
 		CommandDeps: []string{"${SoongZipCmd}"},
 		Depfile:     "${out}.d",
 		Description: "Zip otatools-package cert files",
diff --git a/android/packaging.go b/android/packaging.go
index bb1fe4e..bf18409 100644
--- a/android/packaging.go
+++ b/android/packaging.go
@@ -506,13 +506,11 @@
 	// all packaging specs gathered from the high priority deps.
 	var highPriorities []PackagingSpec
 
-	// Name of the dependency which requested the packaging spec.
-	// If this dep is overridden, the packaging spec will not be installed via this dependency chain.
-	// (the packaging spec might still be installed if there are some other deps which depend on it).
-	var depNames []string
-
 	// list of module names overridden
-	var overridden []string
+	overridden := make(map[string]bool)
+
+	// all installed modules which are not overridden.
+	modulesToInstall := make(map[string]bool)
 
 	var arches []ArchType
 	for _, target := range getSupportedTargets(ctx) {
@@ -529,6 +527,7 @@
 		return false
 	}
 
+	// find all overridden modules and packaging specs
 	ctx.VisitDirectDepsProxy(func(child ModuleProxy) {
 		depTag := ctx.OtherModuleDependencyTag(child)
 		if pi, ok := depTag.(PackagingItem); !ok || !pi.IsPackagingItem() {
@@ -556,20 +555,32 @@
 				regularPriorities = append(regularPriorities, ps)
 			}
 
-			depNames = append(depNames, child.Name())
-			overridden = append(overridden, ps.overrides.ToSlice()...)
+			for o := range ps.overrides.Iter() {
+				overridden[o] = true
+			}
 		}
 	})
 
-	filterOverridden := func(input []PackagingSpec) []PackagingSpec {
-		// input minus packaging specs that are overridden
-		var filtered []PackagingSpec
-		for index, ps := range input {
-			if ps.owner != "" && InList(ps.owner, overridden) {
-				continue
+	// gather modules to install, skipping overridden modules
+	ctx.WalkDeps(func(child, parent Module) bool {
+		owner := ctx.OtherModuleName(child)
+		if o, ok := child.(OverridableModule); ok {
+			if overriddenBy := o.GetOverriddenBy(); overriddenBy != "" {
+				owner = overriddenBy
 			}
-			// The dependency which requested this packaging spec has been overridden.
-			if InList(depNames[index], overridden) {
+		}
+		if overridden[owner] {
+			return false
+		}
+		modulesToInstall[owner] = true
+		return true
+	})
+
+	filterOverridden := func(input []PackagingSpec) []PackagingSpec {
+		// input minus packaging specs that are not installed
+		var filtered []PackagingSpec
+		for _, ps := range input {
+			if !modulesToInstall[ps.owner] {
 				continue
 			}
 			filtered = append(filtered, ps)
diff --git a/android/raw_files.go b/android/raw_files.go
index fd37196..ebba4d1 100644
--- a/android/raw_files.go
+++ b/android/raw_files.go
@@ -26,6 +26,7 @@
 	"testing"
 
 	"github.com/google/blueprint"
+	"github.com/google/blueprint/syncmap"
 
 	"github.com/google/blueprint/proptools"
 )
@@ -213,10 +214,10 @@
 
 var rawFileSetKey OnceKey = NewOnceKey("raw file set")
 
-func getRawFileSet(config Config) *SyncMap[string, rawFileInfo] {
+func getRawFileSet(config Config) *syncmap.SyncMap[string, rawFileInfo] {
 	return config.Once(rawFileSetKey, func() any {
-		return &SyncMap[string, rawFileInfo]{}
-	}).(*SyncMap[string, rawFileInfo])
+		return &syncmap.SyncMap[string, rawFileInfo]{}
+	}).(*syncmap.SyncMap[string, rawFileInfo])
 }
 
 // ContentFromFileRuleForTests returns the content that was passed to a WriteFileRule for use
diff --git a/android/test_suites.go b/android/test_suites.go
index 9eaf785..dbcd48c 100644
--- a/android/test_suites.go
+++ b/android/test_suites.go
@@ -42,6 +42,12 @@
 
 var TestSuiteInfoProvider = blueprint.NewProvider[TestSuiteInfo]()
 
+type SupportFilesInfo struct {
+	SupportFiles InstallPaths
+}
+
+var SupportFilesInfoProvider = blueprint.NewProvider[SupportFilesInfo]()
+
 func (t *testSuiteFiles) GenerateBuildActions(ctx SingletonContext) {
 	files := make(map[string]map[string]InstallPaths)
 
diff --git a/android/util.go b/android/util.go
index 7b305b5..4520f40 100644
--- a/android/util.go
+++ b/android/util.go
@@ -23,7 +23,6 @@
 	"runtime"
 	"sort"
 	"strings"
-	"sync"
 
 	"github.com/google/blueprint/proptools"
 )
@@ -646,35 +645,6 @@
 	}
 }
 
-// SyncMap is a wrapper around sync.Map that provides type safety via generics.
-type SyncMap[K comparable, V any] struct {
-	sync.Map
-}
-
-// Load returns the value stored in the map for a key, or the zero value if no
-// value is present.
-// The ok result indicates whether value was found in the map.
-func (m *SyncMap[K, V]) Load(key K) (value V, ok bool) {
-	v, ok := m.Map.Load(key)
-	if !ok {
-		return *new(V), false
-	}
-	return v.(V), true
-}
-
-// Store sets the value for a key.
-func (m *SyncMap[K, V]) Store(key K, value V) {
-	m.Map.Store(key, value)
-}
-
-// LoadOrStore returns the existing value for the key if present.
-// Otherwise, it stores and returns the given value.
-// The loaded result is true if the value was loaded, false if stored.
-func (m *SyncMap[K, V]) LoadOrStore(key K, value V) (actual V, loaded bool) {
-	v, loaded := m.Map.LoadOrStore(key, value)
-	return v.(V), loaded
-}
-
 // AppendIfNotZero append the given value to the slice if it is not the zero value
 // for its type.
 func AppendIfNotZero[T comparable](slice []T, value T) []T {
diff --git a/android/variable.go b/android/variable.go
index 8c9a0b1..5980efd 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -715,6 +715,10 @@
 
 	ReleaseToolsExtensionDir string `json:",omitempty"`
 
+	BoardPartialOtaUpdatePartitionsList []string `json:",omitempty"`
+	BoardFlashBlockSize                 string   `json:",omitempty"`
+	BootloaderInUpdatePackage           bool     `json:",omitempty"`
+
 	BoardFastbootInfoFile string `json:",omitempty"`
 }
 
diff --git a/apex/androidmk.go b/apex/androidmk.go
index 3a81ee4..0a5644a 100644
--- a/apex/androidmk.go
+++ b/apex/androidmk.go
@@ -75,7 +75,7 @@
 // populated by Soong for unconverted APEXes, or Bazel in mixed mode. Use
 // apexFile#isBazelPrebuilt to differentiate.
 func (a *apexBundle) androidMkForFiles(w io.Writer, apexBundleName, moduleDir string,
-	apexAndroidMkData android.AndroidMkData) []string {
+	apexAndroidMkData android.AndroidMkData) (archSpecificModuleNames []string, moduleNames []string) {
 
 	// apexBundleName comes from the 'name' property or soong module.
 	// apexName comes from 'name' property of apex_manifest.
@@ -84,11 +84,12 @@
 	// However, symbol files for apex files are installed under /apex/<apexBundleName> to avoid
 	// conflicts between two apexes with the same apexName.
 
-	moduleNames := []string{}
-
 	for _, fi := range a.filesInfo {
 		linkToSystemLib := a.linkToSystemLib && fi.transitiveDep && fi.availableToPlatform()
 		moduleName := a.fullModuleName(apexBundleName, linkToSystemLib, &fi)
+		if !android.InList(moduleName, moduleNames) {
+			moduleNames = append(moduleNames, moduleName)
+		}
 
 		// This name will be added to LOCAL_REQUIRED_MODULES of the APEX. We need to be
 		// arch-specific otherwise we will end up installing both ABIs even when only
@@ -100,8 +101,8 @@
 		case "lib64":
 			aName = aName + ":64"
 		}
-		if !android.InList(aName, moduleNames) {
-			moduleNames = append(moduleNames, aName)
+		if !android.InList(aName, archSpecificModuleNames) {
+			archSpecificModuleNames = append(archSpecificModuleNames, aName)
 		}
 
 		if linkToSystemLib {
@@ -216,7 +217,7 @@
 			fmt.Fprintf(w, "%s: %s\n", fi.androidMkModuleName, moduleName)
 		}
 	}
-	return moduleNames
+	return
 }
 
 func (a *apexBundle) writeRequiredModules(w io.Writer, moduleNames []string) {
@@ -235,9 +236,10 @@
 	return android.AndroidMkData{
 		// While we do not provide a value for `Extra`, AconfigUpdateAndroidMkData may add some, which we must honor.
 		Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
+			archSpecificModuleNames := []string{}
 			moduleNames := []string{}
 			if a.installable() {
-				moduleNames = a.androidMkForFiles(w, name, moduleDir, data)
+				archSpecificModuleNames, moduleNames = a.androidMkForFiles(w, name, moduleDir, data)
 			}
 
 			fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)  # apex.apexBundle")
@@ -274,7 +276,7 @@
 			}
 
 			android.AndroidMkEmitAssignList(w, "LOCAL_OVERRIDES_MODULES", a.overridableProperties.Overrides)
-			a.writeRequiredModules(w, moduleNames)
+			a.writeRequiredModules(w, archSpecificModuleNames)
 			// AconfigUpdateAndroidMkData may have added elements to Extra.  Process them here.
 			for _, extra := range data.Extra {
 				extra(w, a.outputFile)
@@ -296,6 +298,9 @@
 				fmt.Fprintln(w, dist)
 			}
 
+			fmt.Fprintf(w, "ALL_MODULES.$(my_register_name).SYMBOLIC_OUTPUT_PATH := $(foreach m,%s,$(ALL_MODULES.$(m).SYMBOLIC_OUTPUT_PATH))\n", strings.Join(moduleNames, " "))
+			fmt.Fprintf(w, "ALL_MODULES.$(my_register_name).ELF_SYMBOL_MAPPING_PATH := $(foreach m,%s,$(ALL_MODULES.$(m).ELF_SYMBOL_MAPPING_PATH))\n", strings.Join(moduleNames, " "))
+
 			distCoverageFiles(w, "ndk_apis_usedby_apex", a.nativeApisUsedByModuleFile.String())
 			distCoverageFiles(w, "ndk_apis_backedby_apex", a.nativeApisBackedByModuleFile.String())
 			distCoverageFiles(w, "java_apis_used_by_apex", a.javaApisUsedByModuleFile.String())
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 36a6974..327e018 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -11468,6 +11468,16 @@
 		// 1. The contents of the selected apex_contributions are visible to make
 		// 2. The rest of the apexes in the mainline module family (source or other prebuilt) is hidden from make
 		checkHideFromMake(t, ctx, tc.expectedVisibleModuleName, tc.expectedHiddenModuleNames)
+
+		// Check that source_apex_name is written as LOCAL_MODULE for make packaging
+		if tc.expectedVisibleModuleName == "prebuilt_com.google.android.foo.v2" {
+			apex := ctx.ModuleForTests(t, "prebuilt_com.google.android.foo.v2", "android_common_prebuilt_com.android.foo").Module()
+			entries := android.AndroidMkEntriesForTest(t, ctx, apex)[0]
+
+			expected := "com.google.android.foo"
+			actual := entries.EntryMap["LOCAL_MODULE"][0]
+			android.AssertStringEquals(t, "LOCAL_MODULE", expected, actual)
+		}
 	}
 }
 
diff --git a/apex/prebuilt.go b/apex/prebuilt.go
index 89b0091..fdd9a75 100644
--- a/apex/prebuilt.go
+++ b/apex/prebuilt.go
@@ -15,7 +15,9 @@
 package apex
 
 import (
+	"fmt"
 	"slices"
+	"sort"
 	"strconv"
 	"strings"
 
@@ -80,6 +82,10 @@
 	// systemServerDexJars stores the list of dexjars for system server jars in the prebuilt for use when
 	// dexpreopting system server jars that are later in the system server classpath.
 	systemServerDexJars android.Paths
+
+	// Certificate information of any apk packaged inside the prebuilt apex.
+	// This will be nil if the prebuilt apex does not contain any apk.
+	apkCertsFile android.WritablePath
 }
 
 type sanitizedPrebuilt interface {
@@ -273,6 +279,10 @@
 					entries.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", !p.installable())
 					entries.AddStrings("LOCAL_OVERRIDES_MODULES", p.prebuiltCommonProperties.Overrides...)
 					entries.SetString("LOCAL_APEX_KEY_PATH", p.apexKeysPath.String())
+					if p.apkCertsFile != nil {
+						entries.SetString("LOCAL_APKCERTS_FILE", p.apkCertsFile.String())
+					}
+
 				},
 			},
 		},
@@ -286,6 +296,14 @@
 		len(p.prebuiltCommonProperties.Exported_systemserverclasspath_fragments) > 0
 }
 
+type appInPrebuiltApexDepTag struct {
+	blueprint.BaseDependencyTag
+}
+
+func (appInPrebuiltApexDepTag) ExcludeFromVisibilityEnforcement() {}
+
+var appInPrebuiltApexTag = appInPrebuiltApexDepTag{}
+
 // prebuiltApexContentsDeps adds dependencies onto the prebuilt apex module's contents.
 func (p *prebuiltCommon) prebuiltApexContentsDeps(ctx android.BottomUpMutatorContext) {
 	module := ctx.Module()
@@ -432,6 +450,12 @@
 	ApexFileProperties
 
 	PrebuiltCommonProperties
+
+	// List of apps that are bundled inside this prebuilt apex.
+	// This will be used to create the certificate info of those apps for apkcerts.txt
+	// This dependency will only be used for apkcerts.txt processing.
+	// Notably, building the prebuilt apex will not build the source app.
+	Apps []string
 }
 
 func (a *Prebuilt) hasSanitizedSource(sanitizer string) bool {
@@ -545,6 +569,9 @@
 
 func (p *Prebuilt) ComponentDepsMutator(ctx android.BottomUpMutatorContext) {
 	p.prebuiltApexContentsDeps(ctx)
+	for _, app := range p.properties.Apps {
+		ctx.AddDependency(p, appInPrebuiltApexTag, app)
+	}
 }
 
 var _ ApexTransitionMutator = (*Prebuilt)(nil)
@@ -677,11 +704,59 @@
 		p.provenanceMetaDataFile = provenance.GenerateArtifactProvenanceMetaData(ctx, p.inputApex, p.installedFile)
 	}
 
+	p.addApkCertsInfo(ctx)
+
 	ctx.SetOutputFiles(android.Paths{p.outputApex}, "")
 
 	android.SetProvider(ctx, filesystem.ApexKeyPathInfoProvider, filesystem.ApexKeyPathInfo{p.apexKeysPath})
 }
 
+// `addApkCertsInfo` sets a provider that will be used to create apkcerts.txt
+func (p *Prebuilt) addApkCertsInfo(ctx android.ModuleContext) {
+	formatLine := func(cert java.Certificate, name, partition string) string {
+		pem := cert.AndroidMkString()
+		var key string
+		if cert.Key == nil {
+			key = ""
+		} else {
+			key = cert.Key.String()
+		}
+		return fmt.Sprintf(`name="%s" certificate="%s" private_key="%s" partition="%s"`, name, pem, key, partition)
+	}
+
+	// Determine if this prebuilt_apex contains any .apks
+	var appInfos java.AppInfos
+	ctx.VisitDirectDepsProxyWithTag(appInPrebuiltApexTag, func(app android.ModuleProxy) {
+		if appInfo, ok := android.OtherModuleProvider(ctx, app, java.AppInfoProvider); ok {
+			appInfos = append(appInfos, *appInfo)
+		} else {
+			ctx.ModuleErrorf("App %s does not set AppInfoProvider\n", app.Name())
+		}
+	})
+	sort.Slice(appInfos, func(i, j int) bool {
+		return appInfos[i].InstallApkName < appInfos[j].InstallApkName
+	})
+
+	if len(appInfos) == 0 {
+		return
+	}
+
+	// Set a provider for use by `android_device`.
+	// `android_device` will create an apkcerts.txt with the list of installed apps for that device.
+	android.SetProvider(ctx, java.AppInfosProvider, appInfos)
+
+	// Set a Make variable for legacy apkcerts.txt creation
+	// p.apkCertsFile will become `LOCAL_APKCERTS_FILE`
+	var lines []string
+	for _, appInfo := range appInfos {
+		lines = append(lines, formatLine(appInfo.Certificate, appInfo.InstallApkName+".apk", p.PartitionTag(ctx.DeviceConfig())))
+	}
+	if len(lines) > 0 {
+		p.apkCertsFile = android.PathForModuleOut(ctx, "apkcerts.txt")
+		android.WriteFileRule(ctx, p.apkCertsFile, strings.Join(lines, "\n"))
+	}
+}
+
 func (p *Prebuilt) ProvenanceMetaDataFile() android.Path {
 	return p.provenanceMetaDataFile
 }
diff --git a/cc/cc.go b/cc/cc.go
index 85d2ebf..c616165 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -2438,6 +2438,27 @@
 	}
 }
 
+func (c *Module) CleanupAfterBuildActions() {
+	// Clear as much of Module as possible to reduce memory usage.
+	c.generators = nil
+	c.compiler = nil
+	c.installer = nil
+	c.features = nil
+	c.coverage = nil
+	c.fuzzer = nil
+	c.sabi = nil
+	c.lto = nil
+	c.afdo = nil
+	c.orderfile = nil
+
+	// TODO: these can be cleared after nativeBinaryInfoProperties and nativeLibInfoProperties are switched to
+	//  using providers.
+	// c.linker = nil
+	// c.stl = nil
+	// c.sanitize = nil
+	// c.library = nil
+}
+
 func CreateCommonLinkableInfo(ctx android.ModuleContext, mod VersionedLinkableInterface) *LinkableInfo {
 	info := &LinkableInfo{
 		StaticExecutable:     mod.StaticExecutable(),
diff --git a/cc/library_sdk_member.go b/cc/library_sdk_member.go
index d1440ea..4629030 100644
--- a/cc/library_sdk_member.go
+++ b/cc/library_sdk_member.go
@@ -573,9 +573,8 @@
 
 func getRequiredMemberOutputFile(ctx android.SdkMemberContext, ccModule *Module) android.Path {
 	var path android.Path
-	outputFile := ccModule.OutputFile()
-	if outputFile.Valid() {
-		path = outputFile.Path()
+	if info, ok := android.OtherModuleProvider(ctx.SdkModuleContext(), ccModule, LinkableInfoProvider); ok && info.OutputFile.Valid() {
+		path = info.OutputFile.Path()
 	} else {
 		ctx.SdkModuleContext().ModuleErrorf("member variant %s does not have a valid output file", ccModule)
 	}
diff --git a/ci_tests/ci_test_package_zip.go b/ci_tests/ci_test_package_zip.go
index d7aaa66..4cadffd 100644
--- a/ci_tests/ci_test_package_zip.go
+++ b/ci_tests/ci_test_package_zip.go
@@ -68,7 +68,7 @@
 	pctx = android.NewPackageContext("android/soong/ci_tests")
 	// test_package module type should only be used for the following modules.
 	// TODO: remove "_soong" from the module names inside when eliminating the corresponding make modules
-	moduleNamesAllowed = []string{"continuous_native_tests_soong", "continuous_instrumentation_tests_soong", "platform_tests"}
+	moduleNamesAllowed = []string{"continuous_instrumentation_tests_soong", "continuous_instrumentation_metric_tests_soong", "continuous_native_tests_soong", "continuous_native_metric_tests_soong", "platform_tests"}
 )
 
 func (p *testPackageZip) DepsMutator(ctx android.BottomUpMutatorContext) {
@@ -150,12 +150,6 @@
 	p.output = createOutput(ctx, pctx)
 
 	ctx.SetOutputFiles(android.Paths{p.output}, "")
-
-	// dist the test output
-	if ctx.ModuleName() == "platform_tests" {
-		distedName := ctx.Config().Getenv("TARGET_PRODUCT") + "-tests-FILE_NAME_TAG_PLACEHOLDER.zip"
-		ctx.DistForGoalWithFilename("platform_tests", p.output, distedName)
-	}
 }
 
 func createOutput(ctx android.ModuleContext, pctx android.PackageContext) android.ModuleOutPath {
diff --git a/cmd/soong_ui/main.go b/cmd/soong_ui/main.go
index 4f6de82..584cc04 100644
--- a/cmd/soong_ui/main.go
+++ b/cmd/soong_ui/main.go
@@ -333,7 +333,7 @@
 
 	varName := flags.Arg(0)
 	if varName == "report_config" {
-		varData, err := build.DumpMakeVars(ctx, config, nil, build.BannerVars)
+		varData, err := build.DumpMakeVars(ctx, config, nil, append(build.BannerVars, "PRODUCT_SOONG_ONLY"))
 		if err != nil {
 			ctx.Fatal(err)
 		}
@@ -400,7 +400,7 @@
 
 	if i := indexList("report_config", allVars); i != -1 {
 		allVars = append(allVars[:i], allVars[i+1:]...)
-		allVars = append(allVars, build.BannerVars...)
+		allVars = append(allVars, append(build.BannerVars, "PRODUCT_SOONG_ONLY")...)
 	}
 
 	if len(allVars) == 0 {
diff --git a/filesystem/android_device.go b/filesystem/android_device.go
index feb000d..9a085a6 100644
--- a/filesystem/android_device.go
+++ b/filesystem/android_device.go
@@ -90,6 +90,10 @@
 	Releasetools_extension *string `android:"path"`
 	FastbootInfo           *string `android:"path"`
 
+	Partial_ota_update_partitions []string
+	Flash_block_size              *string
+	Bootloader_in_update_package  *bool
+
 	// The kernel version in the build. Will be verified against the actual kernel.
 	// If not provided, will attempt to extract it from the loose kernel or the kernel inside
 	// the boot image. The version is later used to decide whether or not to enable uffd_gc
@@ -116,6 +120,7 @@
 	rootDirForFsConfig          string
 	rootDirForFsConfigTimestamp android.Path
 	apkCertsInfo                android.Path
+	targetFilesZip              android.Path
 }
 
 func AndroidDeviceFactory() android.Module {
@@ -391,6 +396,16 @@
 		if a.deviceProps.Android_info != nil {
 			ctx.DistForGoal("droidcore-unbundled", android.PathForModuleSrc(ctx, *a.deviceProps.Android_info))
 		}
+		if a.miscInfo != nil {
+			ctx.DistForGoal("droidcore-unbundled", a.miscInfo)
+			if a.partitionProps.Super_partition_name != nil {
+				ctx.DistForGoalWithFilename("dist_files", a.miscInfo, "super_misc_info.txt")
+			}
+		}
+		if a.targetFilesZip != nil {
+			ctx.DistForGoalWithFilename("target-files-package", a.targetFilesZip, namePrefix+insertBeforeExtension(a.targetFilesZip.Base(), "-FILE_NAME_TAG_PLACEHOLDER"))
+		}
+
 	}
 }
 
@@ -579,6 +594,7 @@
 	a.copyImagesToTargetZip(ctx, builder, targetFilesDir)
 	a.copyMetadataToTargetZip(ctx, builder, targetFilesDir, allInstalledModules)
 
+	a.targetFilesZip = targetFilesZip
 	builder.Command().
 		BuiltTool("soong_zip").
 		Text("-d").
@@ -840,14 +856,25 @@
 			Textf("echo avb_enable=true >> %s", miscInfo).
 			Textf("&& echo avb_building_vbmeta_image=true >> %s", miscInfo).
 			Textf("&& echo avb_avbtool=avbtool >> %s", miscInfo)
+
+		var allChainedVbmetaPartitionTypes []string
 		for _, vbmetaPartitionName := range a.partitionProps.Vbmeta_partitions {
 			img := ctx.GetDirectDepProxyWithTag(vbmetaPartitionName, filesystemDepTag)
 			if provider, ok := android.OtherModuleProvider(ctx, img, vbmetaPartitionProvider); ok {
 				builder.Command().Text("cat").Input(provider.PropFileForMiscInfo).Textf(" >> %s", miscInfo)
+				if provider.FilesystemPartitionType != "" { // the top-level vbmeta.img
+					allChainedVbmetaPartitionTypes = append(allChainedVbmetaPartitionTypes, provider.FilesystemPartitionType)
+				}
 			} else {
 				ctx.ModuleErrorf("vbmeta dep %s does not set vbmetaPartitionProvider\n", vbmetaPartitionName)
 			}
 		}
+		// Determine the custom vbmeta partitions by removing system and vendor
+		customVbmetaPartitionTypes := android.RemoveListFromList(allChainedVbmetaPartitionTypes, []string{"system", "vendor"})
+		builder.Command().Textf("echo avb_custom_vbmeta_images_partition_list=%s >> %s",
+			strings.Join(android.SortedUniqueStrings(customVbmetaPartitionTypes), " "),
+			miscInfo,
+		)
 
 	}
 	if a.partitionProps.Boot_partition_name != nil {
@@ -883,6 +910,14 @@
 		builder.Command().Text("cat").Input(bootImgInfo.PropFileForMiscInfo).Textf(" >> %s", miscInfo)
 	}
 
+	builder.Command().Textf("echo blocksize=%s >> %s", proptools.String(a.deviceProps.Flash_block_size), miscInfo)
+	if proptools.Bool(a.deviceProps.Bootloader_in_update_package) {
+		builder.Command().Textf("echo bootloader_in_update_package=true >> %s", miscInfo)
+	}
+	if len(a.deviceProps.Partial_ota_update_partitions) > 0 {
+		builder.Command().Textf("echo partial_ota_update_partitions_list=%s >> %s", strings.Join(a.deviceProps.Partial_ota_update_partitions, " "), miscInfo)
+	}
+
 	// Sort and dedup
 	builder.Command().Textf("sort -u %s -o %s", miscInfo, miscInfo)
 
diff --git a/filesystem/bootimg.go b/filesystem/bootimg.go
index 5ab0c68..485eae4 100644
--- a/filesystem/bootimg.go
+++ b/filesystem/bootimg.go
@@ -539,6 +539,14 @@
 
 	bootImgType := proptools.String(b.properties.Boot_image_type)
 	addStr("avb_"+bootImgType+"_add_hash_footer_args", b.getAvbHashFooterArgs(ctx))
+	if ramdisk := proptools.String(b.properties.Ramdisk_module); ramdisk != "" {
+		ramdiskModule := ctx.GetDirectDepWithTag(ramdisk, bootimgRamdiskDep)
+		fsInfo, _ := android.OtherModuleProvider(ctx, ramdiskModule, FilesystemProvider)
+		if fsInfo.HasOrIsRecovery {
+			// Create a dup entry for recovery
+			addStr("avb_recovery_add_hash_footer_args", strings.ReplaceAll(b.getAvbHashFooterArgs(ctx), bootImgType, "recovery"))
+		}
+	}
 	if b.properties.Avb_private_key != nil {
 		addStr("avb_"+bootImgType+"_algorithm", proptools.StringDefault(b.properties.Avb_algorithm, "SHA256_RSA4096"))
 		addStr("avb_"+bootImgType+"_key_path", android.PathForModuleSrc(ctx, proptools.String(b.properties.Avb_private_key)).String())
diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go
index e86ebf4..fd1c784 100644
--- a/filesystem/filesystem.go
+++ b/filesystem/filesystem.go
@@ -463,6 +463,9 @@
 	AvbAlgorithm     string
 	AvbHashAlgorithm string
 	AvbKey           android.Path
+	PartitionName    string
+	// HasOrIsRecovery returns true for recovery and for ramdisks with a recovery partition.
+	HasOrIsRecovery bool
 }
 
 // FullInstallPathInfo contains information about the "full install" paths of all the files
@@ -720,6 +723,8 @@
 		HasFsverity:         f.properties.Fsverity.Inputs.GetOrDefault(ctx, nil) != nil,
 		PropFileForMiscInfo: propFileForMiscInfo,
 		PartitionSize:       f.properties.Partition_size,
+		PartitionName:       f.partitionName(),
+		HasOrIsRecovery:     f.hasOrIsRecovery(ctx),
 	}
 	if proptools.Bool(f.properties.Use_avb) {
 		fsInfo.UseAvb = true
@@ -1177,10 +1182,6 @@
 
 	if proptools.Bool(f.properties.Use_avb) {
 		addStr("avb_"+f.partitionName()+"_hashtree_enable", "true")
-		if f.properties.Avb_private_key != nil {
-			key := android.PathForModuleSrc(ctx, *f.properties.Avb_private_key)
-			addStr("avb_"+f.partitionName()+"_key_path", key.String())
-		}
 		addStr("avb_"+f.partitionName()+"_add_hashtree_footer_args", strings.TrimSpace(f.getAvbAddHashtreeFooterArgs(ctx)))
 	}
 
@@ -1307,6 +1308,19 @@
 	return
 }
 
+func (f *filesystem) hasOrIsRecovery(ctx android.ModuleContext) bool {
+	if f.partitionName() == "recovery" {
+		return true
+	}
+	ret := false
+	ctx.VisitDirectDepsWithTag(interPartitionInstallDependencyTag, func(m android.Module) {
+		if fsProvider, ok := android.OtherModuleProvider(ctx, m, FilesystemProvider); ok && fsProvider.PartitionName == "recovery" {
+			ret = true
+		}
+	})
+	return ret
+}
+
 func (f *filesystem) buildCpioImage(
 	ctx android.ModuleContext,
 	builder *android.RuleBuilder,
diff --git a/filesystem/filesystem_test.go b/filesystem/filesystem_test.go
index bf7f5b6..e57e45c 100644
--- a/filesystem/filesystem_test.go
+++ b/filesystem/filesystem_test.go
@@ -736,15 +736,14 @@
 			stl: "none",
 			system_shared_libs: [],
 		}
-		android_filesystem {
-			name: "myfilesystem",
-			deps: ["myapp"],
+		phony {
+			name: "myapp_phony",
+			required: ["myapp"],
 		}
-		android_filesystem {
-			name: "myfilesystem_overridden",
-			deps: ["myapp", "myoverrideapp"],
+		phony {
+			name: "myoverrideapp_phony",
+			required: ["myoverrideapp"],
 		}
-
 		android_app {
 			name: "myapp",
 			platform_apis: true,
@@ -755,15 +754,29 @@
 			base: "myapp",
 			required: ["libbar"],
 		}
+		android_filesystem {
+			name: "myfilesystem",
+			deps: ["myapp"],
+		}
+		android_filesystem {
+			name: "myfilesystem_overridden",
+			deps: ["myapp", "myoverrideapp"],
+		}
+		android_filesystem {
+			name: "myfilesystem_overridden_indirect",
+			deps: ["myapp_phony", "myoverrideapp_phony"],
+		}
 	`)
 
 	partition := result.ModuleForTests(t, "myfilesystem", "android_common")
 	fileList := android.ContentFromFileRuleForTests(t, result.TestContext, partition.Output("fileList"))
 	android.AssertStringEquals(t, "filesystem without override app", "app/myapp/myapp.apk\nlib64/libfoo.so\n", fileList)
 
-	overriddenPartition := result.ModuleForTests(t, "myfilesystem_overridden", "android_common")
-	overriddenFileList := android.ContentFromFileRuleForTests(t, result.TestContext, overriddenPartition.Output("fileList"))
-	android.AssertStringEquals(t, "filesystem with override app", "app/myoverrideapp/myoverrideapp.apk\nlib64/libbar.so\n", overriddenFileList)
+	for _, overridden := range []string{"myfilesystem_overridden", "myfilesystem_overridden_indirect"} {
+		overriddenPartition := result.ModuleForTests(t, overridden, "android_common")
+		overriddenFileList := android.ContentFromFileRuleForTests(t, result.TestContext, overriddenPartition.Output("fileList"))
+		android.AssertStringEquals(t, "filesystem with "+overridden, "app/myoverrideapp/myoverrideapp.apk\nlib64/libbar.so\n", overriddenFileList)
+	}
 }
 
 func TestRamdiskPartitionSetsDevNodes(t *testing.T) {
diff --git a/filesystem/vbmeta.go b/filesystem/vbmeta.go
index d59a2ae..e7a39be 100644
--- a/filesystem/vbmeta.go
+++ b/filesystem/vbmeta.go
@@ -55,6 +55,10 @@
 	// Name of the partition stored in vbmeta desc. Defaults to the name of this module.
 	Partition_name *string
 
+	// Type of the `android_filesystem` for which the vbmeta.img is created.
+	// Examples are system, vendor, product.
+	Filesystem_partition_type *string
+
 	// Set the name of the output. Defaults to <module_name>.img.
 	Stem *string
 
@@ -118,6 +122,9 @@
 	// Name of the partition
 	Name string
 
+	// Partition type of the correspdonding android_filesystem.
+	FilesystemPartitionType string
+
 	// Rollback index location, non-negative int
 	RollbackIndexLocation int
 
@@ -305,11 +312,12 @@
 	})
 
 	android.SetProvider(ctx, vbmetaPartitionProvider, vbmetaPartitionInfo{
-		Name:                  v.partitionName(),
-		RollbackIndexLocation: ril,
-		PublicKey:             extractedPublicKey,
-		Output:                output,
-		PropFileForMiscInfo:   v.buildPropFileForMiscInfo(ctx),
+		Name:                    v.partitionName(),
+		FilesystemPartitionType: proptools.String(v.properties.Filesystem_partition_type),
+		RollbackIndexLocation:   ril,
+		PublicKey:               extractedPublicKey,
+		Output:                  output,
+		PropFileForMiscInfo:     v.buildPropFileForMiscInfo(ctx),
 	})
 
 	ctx.SetOutputFiles([]android.Path{output}, "")
diff --git a/fsgen/filesystem_creator.go b/fsgen/filesystem_creator.go
index b73fb21..14aa062 100644
--- a/fsgen/filesystem_creator.go
+++ b/fsgen/filesystem_creator.go
@@ -419,13 +419,16 @@
 	partitionProps.Vbmeta_partitions = vbmetaPartitions
 
 	deviceProps := &filesystem.DeviceProperties{
-		Main_device:               proptools.BoolPtr(true),
-		Ab_ota_updater:            proptools.BoolPtr(ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.AbOtaUpdater),
-		Ab_ota_partitions:         ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.AbOtaPartitions,
-		Ab_ota_postinstall_config: ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.AbOtaPostInstallConfig,
-		Ramdisk_node_list:         proptools.StringPtr(":ramdisk_node_list"),
-		Android_info:              proptools.StringPtr(":" + generatedModuleName(ctx.Config(), "android_info.prop{.txt}")),
-		Kernel_version:            ctx.Config().ProductVariables().BoardKernelVersion,
+		Main_device:                   proptools.BoolPtr(true),
+		Ab_ota_updater:                proptools.BoolPtr(ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.AbOtaUpdater),
+		Ab_ota_partitions:             ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.AbOtaPartitions,
+		Ab_ota_postinstall_config:     ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.AbOtaPostInstallConfig,
+		Ramdisk_node_list:             proptools.StringPtr(":ramdisk_node_list"),
+		Android_info:                  proptools.StringPtr(":" + generatedModuleName(ctx.Config(), "android_info.prop{.txt}")),
+		Kernel_version:                ctx.Config().ProductVariables().BoardKernelVersion,
+		Partial_ota_update_partitions: ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.BoardPartialOtaUpdatePartitionsList,
+		Flash_block_size:              proptools.StringPtr(ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.BoardFlashBlockSize),
+		Bootloader_in_update_package:  proptools.BoolPtr(ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.BootloaderInUpdatePackage),
 	}
 
 	if bootloader, ok := f.createBootloaderFilegroup(ctx); ok {
diff --git a/fsgen/vbmeta_partitions.go b/fsgen/vbmeta_partitions.go
index 11f4bd0..594c404 100644
--- a/fsgen/vbmeta_partitions.go
+++ b/fsgen/vbmeta_partitions.go
@@ -76,6 +76,7 @@
 	var chainedPartitionTypes []string
 	for _, chainedName := range android.SortedKeys(partitionVars.ChainedVbmetaPartitions) {
 		props := partitionVars.ChainedVbmetaPartitions[chainedName]
+		filesystemPartitionType := chainedName
 		chainedName = "vbmeta_" + chainedName
 		if len(props.Partitions) == 0 {
 			continue
@@ -123,13 +124,14 @@
 			filesystem.VbmetaFactory,
 			".", // Create in the root directory for now so its easy to get the key
 			&filesystem.VbmetaProperties{
-				Partition_name:          proptools.StringPtr(chainedName),
-				Stem:                    proptools.StringPtr(chainedName + ".img"),
-				Private_key:             proptools.StringPtr(props.Key),
-				Algorithm:               &props.Algorithm,
-				Rollback_index:          rollbackIndex,
-				Rollback_index_location: &ril,
-				Partitions:              proptools.NewSimpleConfigurable(partitionModules),
+				Partition_name:            proptools.StringPtr(chainedName),
+				Filesystem_partition_type: proptools.StringPtr(filesystemPartitionType),
+				Stem:                      proptools.StringPtr(chainedName + ".img"),
+				Private_key:               proptools.StringPtr(props.Key),
+				Algorithm:                 &props.Algorithm,
+				Rollback_index:            rollbackIndex,
+				Rollback_index_location:   &ril,
+				Partitions:                proptools.NewSimpleConfigurable(partitionModules),
 			}, &struct {
 				Name *string
 			}{
diff --git a/java/app_import.go b/java/app_import.go
index c0e8171..9fb13ba 100644
--- a/java/app_import.go
+++ b/java/app_import.go
@@ -338,7 +338,7 @@
 	for _, target := range ctx.MultiTargets() {
 		supported_abis := target.Arch.Abi
 		for _, arch := range supported_abis {
-			wantedJniLibSlice = append(wantedJniLibSlice, " -X lib/"+arch+"/*.so")
+			wantedJniLibSlice = append(wantedJniLibSlice, " -X 'lib/"+arch+"/*.so'")
 		}
 	}
 	wantedJniLibString := strings.Join(wantedJniLibSlice, " ")
diff --git a/rust/fuzz_test.go b/rust/fuzz_test.go
index bdcfbbb..f462795 100644
--- a/rust/fuzz_test.go
+++ b/rust/fuzz_test.go
@@ -134,17 +134,24 @@
 			}
 	`)
 
-	fuzz_shared_libtest := ctx.ModuleForTests(t, "fuzz_shared_libtest", "android_arm64_armv8-a_fuzzer").Module().(cc.LinkableInterface)
-	fuzz_static_libtest := ctx.ModuleForTests(t, "fuzz_static_libtest", "android_arm64_armv8-a_fuzzer").Module().(cc.LinkableInterface)
-	fuzz_staticffi_libtest := ctx.ModuleForTests(t, "fuzz_staticffi_libtest", "android_arm64_armv8-a_fuzzer").Module().(cc.LinkableInterface)
+	fuzz_shared_libtest := ctx.ModuleForTests(t, "fuzz_shared_libtest", "android_arm64_armv8-a_fuzzer").Module()
+	fuzz_static_libtest := ctx.ModuleForTests(t, "fuzz_static_libtest", "android_arm64_armv8-a_fuzzer").Module()
+	fuzz_staticffi_libtest := ctx.ModuleForTests(t, "fuzz_staticffi_libtest", "android_arm64_armv8-a_fuzzer").Module()
 
-	if !strings.Contains(fuzz_shared_libtest.FuzzSharedLibraries().String(), ":libcc_transitive_dep.so") {
-		t.Errorf("cc_fuzz does not contain the expected bundled transitive shared libs from rust_ffi_shared ('libcc_transitive_dep'): %#v", fuzz_shared_libtest.FuzzSharedLibraries().String())
+	fuzzSharedLibraries := func(module android.Module) string {
+		if info, ok := android.OtherModuleProvider(ctx, module, cc.LinkableInfoProvider); ok {
+			return info.FuzzSharedLibraries.String()
+		}
+		return ""
 	}
-	if !strings.Contains(fuzz_static_libtest.FuzzSharedLibraries().String(), ":libcc_transitive_dep.so") {
-		t.Errorf("cc_fuzz does not contain the expected bundled transitive shared libs from rust_ffi_static ('libcc_transitive_dep'): %#v", fuzz_static_libtest.FuzzSharedLibraries().String())
+
+	if libs := fuzzSharedLibraries(fuzz_shared_libtest); !strings.Contains(libs, ":libcc_transitive_dep.so") {
+		t.Errorf("cc_fuzz does not contain the expected bundled transitive shared libs from rust_ffi_shared ('libcc_transitive_dep'): %#v", libs)
 	}
-	if !strings.Contains(fuzz_staticffi_libtest.FuzzSharedLibraries().String(), ":libcc_transitive_dep.so") {
-		t.Errorf("cc_fuzz does not contain the expected bundled transitive shared libs from rust_ffi_static ('libcc_transitive_dep'): %#v", fuzz_staticffi_libtest.FuzzSharedLibraries().String())
+	if libs := fuzzSharedLibraries(fuzz_static_libtest); !strings.Contains(libs, ":libcc_transitive_dep.so") {
+		t.Errorf("cc_fuzz does not contain the expected bundled transitive shared libs from rust_ffi_static ('libcc_transitive_dep'): %#v", libs)
+	}
+	if libs := fuzzSharedLibraries(fuzz_staticffi_libtest); !strings.Contains(libs, ":libcc_transitive_dep.so") {
+		t.Errorf("cc_fuzz does not contain the expected bundled transitive shared libs from rust_ffi_static ('libcc_transitive_dep'): %#v", libs)
 	}
 }
diff --git a/scripts/Android.bp b/scripts/Android.bp
index c0e13d5..b6cac32 100644
--- a/scripts/Android.bp
+++ b/scripts/Android.bp
@@ -254,11 +254,6 @@
     ],
 }
 
-sh_binary_host {
-    name: "list_image",
-    src: "list_image.sh",
-}
-
 filegroup {
     name: "rustfmt.toml",
     srcs: ["rustfmt.toml"],
diff --git a/scripts/list_image.sh b/scripts/list_image.sh
deleted file mode 100755
index 0542fa6..0000000
--- a/scripts/list_image.sh
+++ /dev/null
@@ -1,51 +0,0 @@
-#! /bin/bash
-
-# Recursively list Android image directory.
-set -eu
-set -o pipefail
-
-function die() { format=$1; shift; printf "$format\n" "$@"; exit 1; }
-
-# Figure out the filer utility.
-declare filer=
-[[ -z "${ANDROID_HOST_OUT:-}" ]] || filer=${ANDROID_HOST_OUT}/bin/debugfs_static
-if [[ "${1:-}" =~ --debugfs_path=(.*) ]]; then
-  filer=${BASH_REMATCH[1]}
-  shift
-fi
-if [[ -z "${filer:-}" ]]; then
-  maybefiler="$(dirname $0)/debugfs_static"
-  [[ ! -x "$maybefiler" ]] || filer="$maybefiler"
-fi
-
-(( $# >0 )) || die "%s [--debugfs_path=<path>] IMAGE" "$0"
-
-[[ -n "${filer:-}" ]] || die "cannot locate 'debugfs' executable: \
---debugfs_path= is missing, ANDROID_HOST_OUT is not set, \
-and 'debugfs_static' is not colocated with this script"
-declare -r image="$1"
-
-function dolevel() {
-  printf "%s/\n" "$1"
-  # Each line of the file output consists of 6 fields separated with '/'.
-  # The second one contains the file's attributes, and the fifth its name.
-  $filer -R "ls -l -p $1" "$image" 2>/dev/null |\
-    sed -nr 's|^/.*/(.*)/.*/.*/(.+)/.*/$|\2 \1|p' | LANG=C sort | \
-  while read name attr; do
-    [[ "$name" != '.' && "$name" != '..' ]] || continue
-    path="$1/$name"
-    # If the second char of the attributes is '4', it is a directory.
-    if [[ $attr =~ ^.4 ]]; then
-      dolevel "$path"
-    else
-      printf "%s\n" "$path"
-    fi
-  done
-}
-
-# The filer always prints its version on stderr, so we are going
-# to redirect it to the bit bucket. On the other hand, the filer's
-# return code on error is still 0. Let's run it once to without
-# redirecting stderr to see that there is at least one entry.
-$filer -R "ls -l -p" "$image" | grep -q -m1 -P '^/.*/.*/.*/.*/.+/.*/$'
-dolevel .
diff --git a/tradefed_modules/test_module_config.go b/tradefed_modules/test_module_config.go
index 2b34128..e833df2 100644
--- a/tradefed_modules/test_module_config.go
+++ b/tradefed_modules/test_module_config.go
@@ -1,14 +1,15 @@
 package tradefed_modules
 
 import (
-	"android/soong/android"
-	"android/soong/tradefed"
 	"encoding/json"
 	"fmt"
 	"io"
 	"slices"
 	"strings"
 
+	"android/soong/android"
+	"android/soong/tradefed"
+
 	"github.com/google/blueprint"
 	"github.com/google/blueprint/proptools"
 )
@@ -178,6 +179,10 @@
 	moduleInfoJSON.TestConfig = []string{m.testConfig.String()}
 	moduleInfoJSON.AutoTestConfig = []string{"true"}
 	moduleInfoJSON.TestModuleConfigBase = proptools.String(m.Base)
+
+	android.SetProvider(ctx, android.SupportFilesInfoProvider, android.SupportFilesInfo{
+		SupportFiles: m.supportFiles,
+	})
 }
 
 // Ensure at least one test_suite is listed.  Ideally it should be general-tests
@@ -327,6 +332,9 @@
 func (m *testModuleConfigHostModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
 	m.validateBase(ctx, &testModuleConfigHostTag, "java_test_host", true)
 	m.generateManifestAndConfig(ctx)
+	android.SetProvider(ctx, android.SupportFilesInfoProvider, android.SupportFilesInfo{
+		SupportFiles: m.supportFiles,
+	})
 }
 
 // Ensure the base listed is the right type by checking that we get the expected provider data.
diff --git a/ui/build/androidmk_denylist.go b/ui/build/androidmk_denylist.go
index 622aadb..4134cf5 100644
--- a/ui/build/androidmk_denylist.go
+++ b/ui/build/androidmk_denylist.go
@@ -77,8 +77,17 @@
 }
 
 func blockAndroidMks(ctx Context, androidMks []string) {
-	allowlist := getAllLines(ctx, "vendor/google/build/androidmk/allowlist.txt")
-	androidmk_allowlist = append(androidmk_allowlist, allowlist...)
+	allowlist_files := []string{
+		"vendor/google/build/androidmk/allowlist.txt",
+		"device/google/clockwork/build/androidmk/allowlist.txt",
+		"device/google/sdv/androidmk/allowlist.txt",
+	}
+	for _, allowlist_file := range allowlist_files {
+		allowlist := getAllLines(ctx, allowlist_file)
+		androidmk_allowlist = append(androidmk_allowlist, allowlist...)
+	}
+	slices.Sort(androidmk_allowlist)
+	androidmk_allowlist = slices.Compact(androidmk_allowlist)
 
 	denylist := getAllLines(ctx, "vendor/google/build/androidmk/denylist.txt")
 	androidmk_denylist = append(androidmk_denylist, denylist...)
diff --git a/ui/build/dumpvars.go b/ui/build/dumpvars.go
index 16a3db8..710be84 100644
--- a/ui/build/dumpvars.go
+++ b/ui/build/dumpvars.go
@@ -181,7 +181,12 @@
 			fmt.Fprintf(b, "%s=%s\n", name, make_vars[name])
 		}
 	}
-	fmt.Fprintf(b, "SOONG_ONLY=%t\n", config.soongOnlyRequested)
+	if config.skipKatiControlledByFlags {
+		fmt.Fprintf(b, "SOONG_ONLY=%t\n", config.soongOnlyRequested)
+	} else { // default for this product
+		fmt.Fprintf(b, "SOONG_ONLY=%t\n", make_vars["PRODUCT_SOONG_ONLY"] == "true")
+	}
+
 	fmt.Fprint(b, "============================================")
 
 	return b.String()