Merge "[Ravenwood] Generate manifest.properties for Ravenwood tests" into main
diff --git a/Android.bp b/Android.bp
index 9763622..1219c62 100644
--- a/Android.bp
+++ b/Android.bp
@@ -234,3 +234,12 @@
     relative_install_path: "etc", // odm_dlkm/etc/build.prop
     visibility: ["//visibility:private"],
 }
+
+build_prop {
+    name: "ramdisk-build.prop",
+    stem: "build.prop",
+    ramdisk: true,
+    product_config: ":product_config",
+    relative_install_path: "etc/ramdisk", // ramdisk/system/etc/ramdisk/build.prop
+    visibility: ["//visibility:private"],
+}
diff --git a/android/aconfig_providers.go b/android/aconfig_providers.go
index b902f8b..210a656 100644
--- a/android/aconfig_providers.go
+++ b/android/aconfig_providers.go
@@ -107,7 +107,7 @@
 	mergedAconfigFiles := make(map[string]Paths)
 	mergedModeInfos := make(map[string]ModeInfo)
 
-	ctx.VisitDirectDeps(func(module Module) {
+	ctx.VisitDirectDepsProxy(func(module ModuleProxy) {
 		if aconfig_dep, ok := OtherModuleProvider(ctx, module, CodegenInfoProvider); ok && len(aconfig_dep.ModeInfos) > 0 {
 			maps.Copy(mergedModeInfos, aconfig_dep.ModeInfos)
 		}
diff --git a/android/apex.go b/android/apex.go
index 3486350..d140833 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -870,28 +870,6 @@
 	return notInApex
 }
 
-// Tests whether a module named moduleName is directly included in the apexBundle where this
-// ApexContents is tagged.
-func (ac *ApexContents) DirectlyInApex(moduleName string) bool {
-	return ac.contents[moduleName] == directlyInApex
-}
-
-// Tests whether a module named moduleName is included in the apexBundle where this ApexContent is
-// tagged.
-func (ac *ApexContents) InApex(moduleName string) bool {
-	return ac.contents[moduleName] != notInApex
-}
-
-// Tests whether a module named moduleName is directly depended on by all APEXes in an ApexInfo.
-func DirectlyInAllApexes(apexInfo ApexInfo, moduleName string) bool {
-	for _, contents := range apexInfo.ApexContents {
-		if !contents.DirectlyInApex(moduleName) {
-			return false
-		}
-	}
-	return true
-}
-
 ////////////////////////////////////////////////////////////////////////////////////////////////////
 //Below are routines for extra safety checks.
 //
diff --git a/android/base_module_context.go b/android/base_module_context.go
index 719d6d5..1f89dea 100644
--- a/android/base_module_context.go
+++ b/android/base_module_context.go
@@ -211,6 +211,12 @@
 	// data modified by the current mutator.
 	VisitAllModuleVariants(visit func(Module))
 
+	// VisitAllModuleVariantProxies calls visit for each variant of the current module.  Variants of a module are always
+	// visited in order by mutators and GenerateBuildActions, so the data created by the current mutator can be read
+	// from all variants if the current module is the last one. Otherwise, care must be taken to not access any
+	// data modified by the current mutator.
+	VisitAllModuleVariantProxies(visit func(proxy ModuleProxy))
+
 	// GetTagPath is supposed to be called in visit function passed in WalkDeps()
 	// and returns a top-down dependency tags path from a start module to current child module.
 	// It has one less entry than GetWalkPath() as it contains the dependency tags that
@@ -266,7 +272,7 @@
 	return b.bp.OtherModuleDir(getWrappedModule(m))
 }
 func (b *baseModuleContext) OtherModuleErrorf(m blueprint.Module, fmt string, args ...interface{}) {
-	b.bp.OtherModuleErrorf(m, fmt, args...)
+	b.bp.OtherModuleErrorf(getWrappedModule(m), fmt, args...)
 }
 func (b *baseModuleContext) OtherModuleDependencyTag(m blueprint.Module) blueprint.DependencyTag {
 	return b.bp.OtherModuleDependencyTag(getWrappedModule(m))
@@ -382,7 +388,7 @@
 		return &aModule
 	}
 
-	if !OtherModuleProviderOrDefault(b, module, CommonPropertiesProviderKey).Enabled {
+	if !OtherModuleProviderOrDefault(b, module, CommonModuleInfoKey).Enabled {
 		if t, ok := tag.(AllowDisabledModuleDependency); !ok || !t.AllowDisabledModuleDependencyProxy(b, aModule) {
 			if b.Config().AllowMissingDependencies() {
 				b.AddMissingDependencies([]string{b.OtherModuleName(aModule)})
@@ -594,6 +600,10 @@
 	})
 }
 
+func (b *baseModuleContext) VisitAllModuleVariantProxies(visit func(ModuleProxy)) {
+	b.bp.VisitAllModuleVariantProxies(visitProxyAdaptor(visit))
+}
+
 func (b *baseModuleContext) PrimaryModule() Module {
 	return b.bp.PrimaryModule().(Module)
 }
diff --git a/android/build_prop.go b/android/build_prop.go
index 8389470..270e4de 100644
--- a/android/build_prop.go
+++ b/android/build_prop.go
@@ -115,21 +115,14 @@
 		return "vendor_dlkm"
 	} else if p.InstallInOdmDlkm() {
 		return "odm_dlkm"
+	} else if p.InstallInRamdisk() {
+		// From this hardcoding in make:
+		// https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/sysprop.mk;l=311;drc=274435657e4682e5cee3fffd11fb301ab32a828d
+		return "bootimage"
 	}
 	return "system"
 }
 
-var validPartitions = []string{
-	"system",
-	"system_ext",
-	"product",
-	"odm",
-	"vendor",
-	"system_dlkm",
-	"vendor_dlkm",
-	"odm_dlkm",
-}
-
 func (p *buildPropModule) GenerateAndroidBuildActions(ctx ModuleContext) {
 	if !p.SocSpecific() && p.properties.Android_info != nil {
 		ctx.ModuleErrorf("Android_info cannot be set if build.prop is not installed in vendor partition")
@@ -138,10 +131,6 @@
 	p.outputFilePath = PathForModuleOut(ctx, "build.prop").OutputPath
 
 	partition := p.partition(ctx.DeviceConfig())
-	if !InList(partition, validPartitions) {
-		ctx.PropertyErrorf("partition", "unsupported partition %q: only %q are supported", partition, validPartitions)
-		return
-	}
 
 	rule := NewRuleBuilder(pctx, ctx)
 
diff --git a/android/module.go b/android/module.go
index fba989f..ce995ad 100644
--- a/android/module.go
+++ b/android/module.go
@@ -1643,25 +1643,27 @@
 func (m *ModuleBase) generateModuleTarget(ctx *moduleContext) {
 	var allInstalledFiles InstallPaths
 	var allCheckbuildTargets Paths
-	ctx.VisitAllModuleVariants(func(module Module) {
-		a := module.base()
+	ctx.VisitAllModuleVariantProxies(func(module ModuleProxy) {
 		var checkbuildTarget Path
 		var uncheckedModule bool
-		if a == m {
+		var skipAndroidMkProcessing bool
+		if ctx.EqualModules(m.module, module) {
 			allInstalledFiles = append(allInstalledFiles, ctx.installFiles...)
 			checkbuildTarget = ctx.checkbuildTarget
 			uncheckedModule = ctx.uncheckedModule
+			skipAndroidMkProcessing = shouldSkipAndroidMkProcessing(ctx, m)
 		} else {
 			info := OtherModuleProviderOrDefault(ctx, module, InstallFilesProvider)
 			allInstalledFiles = append(allInstalledFiles, info.InstallFiles...)
 			checkbuildTarget = info.CheckbuildTarget
 			uncheckedModule = info.UncheckedModule
+			skipAndroidMkProcessing = OtherModuleProviderOrDefault(ctx, module, CommonModuleInfoKey).SkipAndroidMkProcessing
 		}
 		// A module's -checkbuild phony targets should
 		// not be created if the module is not exported to make.
 		// Those could depend on the build target and fail to compile
 		// for the current build target.
-		if (!ctx.Config().KatiEnabled() || !shouldSkipAndroidMkProcessing(ctx, a)) && !uncheckedModule && checkbuildTarget != nil {
+		if (!ctx.Config().KatiEnabled() || !skipAndroidMkProcessing) && !uncheckedModule && checkbuildTarget != nil {
 			allCheckbuildTargets = append(allCheckbuildTargets, checkbuildTarget)
 		}
 	})
@@ -1850,15 +1852,16 @@
 
 var FinalModuleBuildTargetsProvider = blueprint.NewProvider[FinalModuleBuildTargetsInfo]()
 
-type CommonPropertiesProviderData struct {
+type CommonModuleInfo struct {
 	Enabled bool
 	// Whether the module has been replaced by a prebuilt
 	ReplacedByPrebuilt bool
 	// The Target of artifacts that this module variant is responsible for creating.
-	CompileTarget Target
+	CompileTarget           Target
+	SkipAndroidMkProcessing bool
 }
 
-var CommonPropertiesProviderKey = blueprint.NewProvider[CommonPropertiesProviderData]()
+var CommonModuleInfoKey = blueprint.NewProvider[CommonModuleInfo]()
 
 type PrebuiltModuleProviderData struct {
 	// Empty for now
@@ -1940,9 +1943,7 @@
 
 	if m.Enabled(ctx) {
 		// ensure all direct android.Module deps are enabled
-		ctx.VisitDirectDeps(func(m Module) {
-			ctx.validateAndroidModule(m, ctx.OtherModuleDependencyTag(m), ctx.baseModuleContext.strictVisitDeps)
-		})
+		ctx.VisitDirectDepsProxy(func(m ModuleProxy) {})
 
 		if m.Device() {
 			// Handle any init.rc and vintf fragment files requested by the module.  All files installed by this
@@ -2122,16 +2123,17 @@
 	}
 	buildComplianceMetadataProvider(ctx, m)
 
-	commonData := CommonPropertiesProviderData{
-		ReplacedByPrebuilt: m.commonProperties.ReplacedByPrebuilt,
-		CompileTarget:      m.commonProperties.CompileTarget,
+	commonData := CommonModuleInfo{
+		ReplacedByPrebuilt:      m.commonProperties.ReplacedByPrebuilt,
+		CompileTarget:           m.commonProperties.CompileTarget,
+		SkipAndroidMkProcessing: shouldSkipAndroidMkProcessing(ctx, m),
 	}
 	if m.commonProperties.ForcedDisabled {
 		commonData.Enabled = false
 	} else {
 		commonData.Enabled = m.commonProperties.Enabled.GetOrDefault(m.ConfigurableEvaluator(ctx), !m.Os().DefaultDisabled)
 	}
-	SetProvider(ctx, CommonPropertiesProviderKey, commonData)
+	SetProvider(ctx, CommonModuleInfoKey, commonData)
 	if p, ok := m.module.(PrebuiltInterface); ok && p.Prebuilt() != nil {
 		SetProvider(ctx, PrebuiltModuleProviderKey, PrebuiltModuleProviderData{})
 	}
@@ -2140,7 +2142,7 @@
 			HostToolPath: h.HostToolPath()})
 	}
 
-	if p, ok := m.module.(AndroidMkProviderInfoProducer); ok && !shouldSkipAndroidMkProcessing(ctx, m) {
+	if p, ok := m.module.(AndroidMkProviderInfoProducer); ok && !commonData.SkipAndroidMkProcessing {
 		SetProvider(ctx, AndroidMkInfoProvider, p.PrepareAndroidMKProviderInfo(ctx.Config()))
 	}
 }
diff --git a/android/packaging.go b/android/packaging.go
index 635922c..e71d983 100644
--- a/android/packaging.go
+++ b/android/packaging.go
@@ -480,7 +480,7 @@
 		return false
 	}
 
-	ctx.VisitDirectDeps(func(child Module) {
+	ctx.VisitDirectDepsProxy(func(child ModuleProxy) {
 		depTag := ctx.OtherModuleDependencyTag(child)
 		if pi, ok := depTag.(PackagingItem); !ok || !pi.IsPackagingItem() {
 			return
diff --git a/android/paths.go b/android/paths.go
index 8f066cc..7ab1f22 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -675,7 +675,7 @@
 	if module == nil {
 		return nil, missingDependencyError{[]string{moduleName}}
 	}
-	if !OtherModuleProviderOrDefault(ctx, *module, CommonPropertiesProviderKey).Enabled {
+	if !OtherModuleProviderOrDefault(ctx, *module, CommonModuleInfoKey).Enabled {
 		return nil, missingDependencyError{[]string{moduleName}}
 	}
 
diff --git a/android/prebuilt.go b/android/prebuilt.go
index 51e72af..0ac67b3 100644
--- a/android/prebuilt.go
+++ b/android/prebuilt.go
@@ -381,7 +381,7 @@
 // the right module. This function is only safe to call after all TransitionMutators
 // have run, e.g. in GenerateAndroidBuildActions.
 func PrebuiltGetPreferred(ctx BaseModuleContext, module Module) Module {
-	if !OtherModuleProviderOrDefault(ctx, module, CommonPropertiesProviderKey).ReplacedByPrebuilt {
+	if !OtherModuleProviderOrDefault(ctx, module, CommonModuleInfoKey).ReplacedByPrebuilt {
 		return module
 	}
 	if _, ok := OtherModuleProvider(ctx, module, PrebuiltModuleProviderKey); ok {
diff --git a/apex/apex.go b/apex/apex.go
index 04b5a07..e0195d3 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -2071,8 +2071,7 @@
 			af := apexFileForNativeLibrary(ctx, ch, vctx.handleSpecialLibs)
 			af.transitiveDep = true
 
-			abInfo, _ := android.ModuleProvider(ctx, android.ApexBundleInfoProvider)
-			if !abInfo.Contents.DirectlyInApex(depName) && (ch.IsStubs() || ch.HasStubsVariants()) {
+			if ch.IsStubs() || ch.HasStubsVariants() {
 				// If the dependency is a stubs lib, don't include it in this APEX,
 				// but make sure that the lib is installed on the device.
 				// In case no APEX is having the lib, the lib is installed to the system
@@ -2576,7 +2575,10 @@
 		return
 	}
 
-	abInfo, _ := android.ModuleProvider(ctx, android.ApexBundleInfoProvider)
+	librariesDirectlyInApex := make(map[string]bool)
+	ctx.VisitDirectDepsProxyWithTag(sharedLibTag, func(dep android.ModuleProxy) {
+		librariesDirectlyInApex[ctx.OtherModuleName(dep)] = true
+	})
 
 	a.WalkPayloadDeps(ctx, func(ctx android.BaseModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool {
 		if ccm, ok := to.(*cc.Module); ok {
@@ -2602,7 +2604,7 @@
 				return false
 			}
 
-			isStubLibraryFromOtherApex := ccm.HasStubsVariants() && !abInfo.Contents.DirectlyInApex(toName)
+			isStubLibraryFromOtherApex := ccm.HasStubsVariants() && !librariesDirectlyInApex[toName]
 			if isStubLibraryFromOtherApex && !externalDep {
 				ctx.ModuleErrorf("%q required by %q is a native library providing stub. "+
 					"It shouldn't be included in this APEX via static linking. Dependency path: %s", to.String(), fromName, ctx.GetPathString(false))
@@ -2635,7 +2637,7 @@
 
 // checkClasspathFragments enforces that all classpath fragments in deps generate classpaths.proto config.
 func (a *apexBundle) checkClasspathFragments(ctx android.ModuleContext) {
-	ctx.VisitDirectDeps(func(module android.Module) {
+	ctx.VisitDirectDepsProxy(func(module android.ModuleProxy) {
 		if tag := ctx.OtherModuleDependencyTag(module); tag == bcpfTag || tag == sscpfTag {
 			info, _ := android.OtherModuleProvider(ctx, module, java.ClasspathFragmentProtoContentInfoProvider)
 			if !info.ClasspathFragmentProtoGenerated {
@@ -2742,12 +2744,12 @@
 
 // checkStaticExecutable ensures that executables in an APEX are not static.
 func (a *apexBundle) checkStaticExecutables(ctx android.ModuleContext) {
-	ctx.VisitDirectDeps(func(module android.Module) {
+	ctx.VisitDirectDepsProxy(func(module android.ModuleProxy) {
 		if ctx.OtherModuleDependencyTag(module) != executableTag {
 			return
 		}
 
-		if l, ok := module.(cc.LinkableInterface); ok && l.StaticExecutable() {
+		if android.OtherModuleProviderOrDefault(ctx, module, cc.LinkableInfoKey).StaticExecutable {
 			apex := a.ApexVariationName()
 			exec := ctx.OtherModuleName(module)
 			if isStaticExecutableAllowed(apex, exec) {
diff --git a/cc/cc.go b/cc/cc.go
index 2b011d6..76d01a5 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -53,6 +53,13 @@
 
 var CcObjectInfoProvider = blueprint.NewProvider[CcObjectInfo]()
 
+type LinkableInfo struct {
+	// StaticExecutable returns true if this is a binary module with "static_executable: true".
+	StaticExecutable bool
+}
+
+var LinkableInfoKey = blueprint.NewProvider[LinkableInfo]()
+
 func init() {
 	RegisterCCBuildComponents(android.InitRegistrationContext)
 
@@ -2119,6 +2126,10 @@
 		android.SetProvider(ctx, CcObjectInfoProvider, ccObjectInfo)
 	}
 
+	android.SetProvider(ctx, LinkableInfoKey, LinkableInfo{
+		StaticExecutable: c.StaticExecutable(),
+	})
+
 	c.setOutputFiles(ctx)
 
 	if c.makeVarsInfo != nil {
diff --git a/cc/tidy.go b/cc/tidy.go
index 5cbf8f0..6481b95 100644
--- a/cc/tidy.go
+++ b/cc/tidy.go
@@ -220,7 +220,7 @@
 
 	// (1) Collect all obj/tidy files into OS-specific groups.
 	ctx.VisitAllModuleVariantProxies(module, func(variant android.ModuleProxy) {
-		osName := android.OtherModuleProviderOrDefault(ctx, variant, android.CommonPropertiesProviderKey).CompileTarget.Os.Name
+		osName := android.OtherModuleProviderOrDefault(ctx, variant, android.CommonModuleInfoKey).CompileTarget.Os.Name
 		info := android.OtherModuleProviderOrDefault(ctx, variant, CcObjectInfoProvider)
 		addToOSGroup(osName, info.objFiles, allObjFileGroups, subsetObjFileGroups)
 		addToOSGroup(osName, info.tidyFiles, allTidyFileGroups, subsetTidyFileGroups)
diff --git a/dexpreopt/config.go b/dexpreopt/config.go
index 3dd6f9a..e3804e5 100644
--- a/dexpreopt/config.go
+++ b/dexpreopt/config.go
@@ -465,7 +465,7 @@
 func (d dex2oatDependencyTag) AllowDisabledModuleDependencyProxy(
 	ctx android.OtherModuleProviderContext, target android.ModuleProxy) bool {
 	return android.OtherModuleProviderOrDefault(
-		ctx, target, android.CommonPropertiesProviderKey).ReplacedByPrebuilt
+		ctx, target, android.CommonModuleInfoKey).ReplacedByPrebuilt
 }
 
 // Dex2oatDepTag represents the dependency onto the dex2oatd module. It is added to any module that
diff --git a/etc/Android.bp b/etc/Android.bp
index 8e043b8..e92437e 100644
--- a/etc/Android.bp
+++ b/etc/Android.bp
@@ -12,6 +12,7 @@
     ],
     srcs: [
         "adb_keys.go",
+        "avbpubkey.go",
         "install_symlink.go",
         "otacerts_zip.go",
         "prebuilt_etc.go",
diff --git a/etc/avbpubkey.go b/etc/avbpubkey.go
new file mode 100644
index 0000000..3f998d4
--- /dev/null
+++ b/etc/avbpubkey.go
@@ -0,0 +1,84 @@
+// Copyright 2024 Google Inc. All rights reserved.
+//
+// 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 etc
+
+import (
+	"android/soong/android"
+
+	"github.com/google/blueprint"
+	"github.com/google/blueprint/proptools"
+)
+
+func init() {
+	android.RegisterModuleType("avbpubkey", AvbpubkeyModuleFactory)
+	pctx.HostBinToolVariable("avbtool", "avbtool")
+}
+
+type avbpubkeyProperty struct {
+	Private_key *string `android:"path"`
+}
+
+type AvbpubkeyModule struct {
+	android.ModuleBase
+
+	properties avbpubkeyProperty
+
+	outputPath  android.WritablePath
+	installPath android.InstallPath
+}
+
+func AvbpubkeyModuleFactory() android.Module {
+	module := &AvbpubkeyModule{}
+	module.AddProperties(&module.properties)
+	android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
+	return module
+}
+
+var avbPubKeyRule = pctx.AndroidStaticRule("avbpubkey",
+	blueprint.RuleParams{
+		Command: `${avbtool} extract_public_key --key ${in} --output ${out}.tmp` +
+			` && ( if cmp -s ${out}.tmp ${out} ; then rm ${out}.tmp ; else mv ${out}.tmp ${out} ; fi )`,
+		CommandDeps: []string{"${avbtool}"},
+		Description: "Extracting system_other avb key",
+	})
+
+func (m *AvbpubkeyModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+	if !m.ProductSpecific() {
+		ctx.ModuleErrorf("avbpubkey module type must set product_specific to true")
+	}
+
+	m.outputPath = android.PathForModuleOut(ctx, ctx.ModuleName(), "system_other.avbpubkey")
+
+	ctx.Build(pctx, android.BuildParams{
+		Rule:   avbPubKeyRule,
+		Input:  android.PathForModuleSrc(ctx, proptools.String(m.properties.Private_key)),
+		Output: m.outputPath,
+	})
+
+	m.installPath = android.PathForModuleInstall(ctx, "etc/security/avb")
+	ctx.InstallFile(m.installPath, "system_other.avbpubkey", m.outputPath)
+}
+
+func (m *AvbpubkeyModule) AndroidMkEntries() []android.AndroidMkEntries {
+	if m.IsSkipInstall() {
+		return []android.AndroidMkEntries{}
+	}
+
+	return []android.AndroidMkEntries{
+		{
+			Class:      "ETC",
+			OutputFile: android.OptionalPathForPath(m.outputPath),
+		}}
+}
diff --git a/fsgen/filesystem_creator.go b/fsgen/filesystem_creator.go
index 0a65c6c..d46f679 100644
--- a/fsgen/filesystem_creator.go
+++ b/fsgen/filesystem_creator.go
@@ -62,7 +62,8 @@
 	module.AddProperties(&module.properties)
 	android.AddLoadHook(module, func(ctx android.LoadHookContext) {
 		generatedPrebuiltEtcModuleNames := createPrebuiltEtcModules(ctx)
-		createFsGenState(ctx, generatedPrebuiltEtcModuleNames)
+		avbpubkeyGenerated := createAvbpubkeyModule(ctx)
+		createFsGenState(ctx, generatedPrebuiltEtcModuleNames, avbpubkeyGenerated)
 		module.createInternalModules(ctx)
 	})
 
@@ -591,8 +592,10 @@
 	}
 
 	baseProps := generateBaseProps(proptools.StringPtr(generatedModuleNameForPartition(ctx.Config(), partitionType)))
-	deps := ctx.Config().Get(fsGenStateOnceKey).(*FsGenState).fsDeps[partitionType]
-	depProps := generateDepStruct(*deps)
+	fsGenState := ctx.Config().Get(fsGenStateOnceKey).(*FsGenState)
+	deps := fsGenState.fsDeps[partitionType]
+	highPriorityDeps := fsGenState.generatedPrebuiltEtcModuleNames
+	depProps := generateDepStruct(*deps, highPriorityDeps)
 
 	result, err := proptools.RepackProperties([]interface{}{baseProps, fsProps, depProps})
 	if err != nil {
diff --git a/fsgen/fsgen_mutators.go b/fsgen/fsgen_mutators.go
index e9fd513..e0e103a 100644
--- a/fsgen/fsgen_mutators.go
+++ b/fsgen/fsgen_mutators.go
@@ -66,6 +66,8 @@
 	fsDepsMutex sync.Mutex
 	// Map of _all_ soong module names to their corresponding installation properties
 	moduleToInstallationProps map[string]installationProperties
+	// List of prebuilt_* modules that are autogenerated.
+	generatedPrebuiltEtcModuleNames []string
 }
 
 type installationProperties struct {
@@ -110,13 +112,13 @@
 	return generatedPartitions
 }
 
-func createFsGenState(ctx android.LoadHookContext, generatedPrebuiltEtcModuleNames []string) *FsGenState {
+func createFsGenState(ctx android.LoadHookContext, generatedPrebuiltEtcModuleNames []string, avbpubkeyGenerated bool) *FsGenState {
 	return ctx.Config().Once(fsGenStateOnceKey, func() interface{} {
 		partitionVars := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse
 		candidates := android.FirstUniqueStrings(android.Concat(partitionVars.ProductPackages, partitionVars.ProductPackagesDebug))
 		candidates = android.Concat(candidates, generatedPrebuiltEtcModuleNames)
 
-		return &FsGenState{
+		fsGenState := FsGenState{
 			depCandidates: candidates,
 			fsDeps: map[string]*multilibDeps{
 				// These additional deps are added according to the cuttlefish system image bp.
@@ -174,9 +176,16 @@
 				},
 				"ramdisk": {},
 			},
-			fsDepsMutex:               sync.Mutex{},
-			moduleToInstallationProps: map[string]installationProperties{},
+			fsDepsMutex:                     sync.Mutex{},
+			moduleToInstallationProps:       map[string]installationProperties{},
+			generatedPrebuiltEtcModuleNames: generatedPrebuiltEtcModuleNames,
 		}
+
+		if avbpubkeyGenerated {
+			(*fsGenState.fsDeps["product"])["system_other_avbpubkey"] = defaultDepCandidateProps(ctx.Config())
+		}
+
+		return &fsGenState
 	}).(*FsGenState)
 }
 
@@ -278,7 +287,7 @@
 	soongGeneratedPartitionMap := getAllSoongGeneratedPartitionNames(mctx.Config(), fsGenState.soongGeneratedPartitions)
 	m := mctx.Module()
 	if partition, ok := soongGeneratedPartitionMap[m.Name()]; ok {
-		depsStruct := generateDepStruct(*fsDeps[partition])
+		depsStruct := generateDepStruct(*fsDeps[partition], fsGenState.generatedPrebuiltEtcModuleNames)
 		if err := proptools.AppendMatchingProperties(m.GetProperties(), depsStruct, nil); err != nil {
 			mctx.ModuleErrorf(err.Error())
 		}
@@ -337,12 +346,12 @@
 	return false
 }
 
-func generateDepStruct(deps map[string]*depCandidateProps) *packagingPropsStruct {
+func generateDepStruct(deps map[string]*depCandidateProps, highPriorityDeps []string) *packagingPropsStruct {
 	depsStruct := packagingPropsStruct{}
 	for depName, depProps := range deps {
 		bitness := getBitness(depProps.Arch)
 		fullyQualifiedDepName := fullyQualifiedModuleName(depName, depProps.Namespace)
-		if isHighPriorityDep(depName) {
+		if android.InList(depName, highPriorityDeps) {
 			depsStruct.High_priority_deps = append(depsStruct.High_priority_deps, fullyQualifiedDepName)
 		} else if android.InList("32", bitness) && android.InList("64", bitness) {
 			// If both 32 and 64 bit variants are enabled for this module
diff --git a/fsgen/prebuilt_etc_modules_gen.go b/fsgen/prebuilt_etc_modules_gen.go
index 97d5482..efbc462 100644
--- a/fsgen/prebuilt_etc_modules_gen.go
+++ b/fsgen/prebuilt_etc_modules_gen.go
@@ -350,3 +350,28 @@
 
 	return ret
 }
+
+func createAvbpubkeyModule(ctx android.LoadHookContext) bool {
+	avbKeyPath := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse.BoardAvbKeyPath
+	if avbKeyPath == "" {
+		return false
+	}
+	ctx.CreateModuleInDirectory(
+		etc.AvbpubkeyModuleFactory,
+		".",
+		&struct {
+			Name             *string
+			Product_specific *bool
+			Private_key      *string
+			No_full_install  *bool
+			Visibility       []string
+		}{
+			Name:             proptools.StringPtr("system_other_avbpubkey"),
+			Product_specific: proptools.BoolPtr(true),
+			Private_key:      proptools.StringPtr(avbKeyPath),
+			No_full_install:  proptools.BoolPtr(true),
+			Visibility:       []string{"//visibility:public"},
+		},
+	)
+	return true
+}
diff --git a/fsgen/vbmeta_partitions.go b/fsgen/vbmeta_partitions.go
index 52f8ae5..b7fff68 100644
--- a/fsgen/vbmeta_partitions.go
+++ b/fsgen/vbmeta_partitions.go
@@ -53,7 +53,8 @@
 
 	var chainedPartitions []string
 	var partitionTypesHandledByChainedPartitions []string
-	for chainedName, props := range partitionVars.ChainedVbmetaPartitions {
+	for _, chainedName := range android.SortedKeys(partitionVars.ChainedVbmetaPartitions) {
+		props := partitionVars.ChainedVbmetaPartitions[chainedName]
 		chainedName = "vbmeta_" + chainedName
 		if len(props.Partitions) == 0 {
 			continue
diff --git a/genrule/genrule.go b/genrule/genrule.go
index 1282bfb..9d2dbc7 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -115,7 +115,7 @@
 func (t hostToolDependencyTag) AllowDisabledModuleDependencyProxy(
 	ctx android.OtherModuleProviderContext, target android.ModuleProxy) bool {
 	return android.OtherModuleProviderOrDefault(
-		ctx, target, android.CommonPropertiesProviderKey).ReplacedByPrebuilt
+		ctx, target, android.CommonModuleInfoKey).ReplacedByPrebuilt
 }
 
 var _ android.AllowDisabledModuleDependency = (*hostToolDependencyTag)(nil)
@@ -353,7 +353,7 @@
 				if h, ok := android.OtherModuleProvider(ctx, module, android.HostToolProviderKey); ok {
 					// A HostToolProvider provides the path to a tool, which will be copied
 					// into the sandbox.
-					if !android.OtherModuleProviderOrDefault(ctx, module, android.CommonPropertiesProviderKey).Enabled {
+					if !android.OtherModuleProviderOrDefault(ctx, module, android.CommonModuleInfoKey).Enabled {
 						if ctx.Config().AllowMissingDependencies() {
 							ctx.AddMissingDependencies([]string{tool})
 						} else {
diff --git a/rust/rust.go b/rust/rust.go
index ed38ad7..48f946e 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -1001,6 +1001,10 @@
 		ctx.Phony("rust", ctx.RustModule().OutputFile().Path())
 	}
 
+	android.SetProvider(ctx, cc.LinkableInfoKey, cc.LinkableInfo{
+		StaticExecutable: mod.StaticExecutable(),
+	})
+
 	mod.setOutputFiles(ctx)
 
 	buildComplianceMetadataInfo(ctx, mod, deps)
diff --git a/scripts/gen_build_prop.py b/scripts/gen_build_prop.py
index 0b7780e..5f52d6f 100644
--- a/scripts/gen_build_prop.py
+++ b/scripts/gen_build_prop.py
@@ -608,7 +608,7 @@
         build_product_prop(args)
       case "vendor":
         build_vendor_prop(args)
-      case "system_dlkm" | "vendor_dlkm" | "odm_dlkm":
+      case "system_dlkm" | "vendor_dlkm" | "odm_dlkm" | "bootimage":
         build_prop(args, gen_build_info=False, gen_common_build_props=True, variables=[])
       case _:
         sys.exit(f"not supported partition {args.partition}")
diff --git a/ui/build/androidmk_denylist.go b/ui/build/androidmk_denylist.go
index c54d55f..6f57cb1 100644
--- a/ui/build/androidmk_denylist.go
+++ b/ui/build/androidmk_denylist.go
@@ -29,6 +29,9 @@
 	"device/google_car/",
 	"device/sample/",
 	"frameworks/",
+	"hardware/libhardware/",
+	"hardware/libhardware_legacy/",
+	"hardware/ril/",
 	// Do not block other directories in kernel/, see b/319658303.
 	"kernel/configs/",
 	"kernel/prebuilts/",
@@ -37,8 +40,10 @@
 	"libnativehelper/",
 	"packages/",
 	"pdk/",
+	"platform_testing/",
 	"prebuilts/",
 	"sdk/",
+	"system/",
 	"test/",
 	"trusty/",
 	// Add back toolchain/ once defensive Android.mk files are removed