Merge "Autogenerate a soong module to build odm.img" into main
diff --git a/android/config.go b/android/config.go
index 616385a..16d77db 100644
--- a/android/config.go
+++ b/android/config.go
@@ -2254,3 +2254,11 @@
 func (c *config) SystemExtManifestFiles() []string {
 	return c.productVariables.SystemExtManifestFiles
 }
+
+func (c *config) DeviceManifestFiles() []string {
+	return c.productVariables.DeviceManifestFiles
+}
+
+func (c *config) OdmManifestFiles() []string {
+	return c.productVariables.OdmManifestFiles
+}
diff --git a/android/packaging.go b/android/packaging.go
index acafcd4..b5c4503 100644
--- a/android/packaging.go
+++ b/android/packaging.go
@@ -17,6 +17,7 @@
 import (
 	"fmt"
 	"path/filepath"
+	"slices"
 	"sort"
 	"strings"
 
@@ -207,97 +208,128 @@
 	// If this is set to true by a module type inheriting PackagingBase, the deps property
 	// collects the first target only even with compile_multilib: true.
 	DepsCollectFirstTargetOnly bool
+
+	// If this is set to try by a module type inheriting PackagingBase, the module type is
+	// allowed to utilize High_priority_deps.
+	AllowHighPriorityDeps bool
 }
 
-type depsProperty struct {
+type DepsProperty struct {
+	// Deps that have higher priority in packaging when there is a packaging conflict.
+	// For example, if multiple files are being installed to same filepath, the install file
+	// of the module listed in this property will have a higher priority over those in other
+	// deps properties.
+	High_priority_deps []string `android:"arch_variant"`
+
 	// Modules to include in this package
 	Deps proptools.Configurable[[]string] `android:"arch_variant"`
 }
 
 type packagingMultilibProperties struct {
-	First    depsProperty `android:"arch_variant"`
-	Common   depsProperty `android:"arch_variant"`
-	Lib32    depsProperty `android:"arch_variant"`
-	Lib64    depsProperty `android:"arch_variant"`
-	Both     depsProperty `android:"arch_variant"`
-	Prefer32 depsProperty `android:"arch_variant"`
+	First    DepsProperty `android:"arch_variant"`
+	Common   DepsProperty `android:"arch_variant"`
+	Lib32    DepsProperty `android:"arch_variant"`
+	Lib64    DepsProperty `android:"arch_variant"`
+	Both     DepsProperty `android:"arch_variant"`
+	Prefer32 DepsProperty `android:"arch_variant"`
 }
 
 type packagingArchProperties struct {
-	Arm64  depsProperty
-	Arm    depsProperty
-	X86_64 depsProperty
-	X86    depsProperty
+	Arm64  DepsProperty
+	Arm    DepsProperty
+	X86_64 DepsProperty
+	X86    DepsProperty
 }
 
 type PackagingProperties struct {
-	Deps     proptools.Configurable[[]string] `android:"arch_variant"`
-	Multilib packagingMultilibProperties      `android:"arch_variant"`
+	DepsProperty
+
+	Multilib packagingMultilibProperties `android:"arch_variant"`
 	Arch     packagingArchProperties
 }
 
 func InitPackageModule(p PackageModule) {
 	base := p.packagingBase()
-	p.AddProperties(&base.properties)
+	p.AddProperties(&base.properties, &base.properties.DepsProperty)
 }
 
 func (p *PackagingBase) packagingBase() *PackagingBase {
 	return p
 }
 
+func (p *PackagingBase) highPriorityDeps() []string {
+	return slices.Concat(
+		p.properties.High_priority_deps,
+		p.properties.Multilib.Both.High_priority_deps,
+		p.properties.Multilib.Common.High_priority_deps,
+		p.properties.Multilib.First.High_priority_deps,
+		p.properties.Multilib.Lib32.High_priority_deps,
+		p.properties.Multilib.Lib64.High_priority_deps,
+		p.properties.Multilib.Prefer32.High_priority_deps,
+		p.properties.Arch.Arm.High_priority_deps,
+		p.properties.Arch.Arm64.High_priority_deps,
+		p.properties.Arch.X86.High_priority_deps,
+		p.properties.Arch.X86_64.High_priority_deps,
+	)
+}
+
 // From deps and multilib.*.deps, select the dependencies that are for the given arch deps is for
 // the current archicture when this module is not configured for multi target. When configured for
 // multi target, deps is selected for each of the targets and is NOT selected for the current
 // architecture which would be Common.
 func (p *PackagingBase) getDepsForArch(ctx BaseModuleContext, arch ArchType) []string {
-	get := func(prop proptools.Configurable[[]string]) []string {
-		return prop.GetOrDefault(ctx, nil)
+	if len(p.highPriorityDeps()) > 0 && !p.AllowHighPriorityDeps {
+		ctx.ModuleErrorf("Usage of high_priority_deps is not allowed for %s module type", ctx.ModuleType())
+	}
+
+	get := func(prop DepsProperty) []string {
+		return Concat(prop.Deps.GetOrDefault(ctx, nil), prop.High_priority_deps)
 	}
 
 	var ret []string
 	if arch == ctx.Target().Arch.ArchType && len(ctx.MultiTargets()) == 0 {
-		ret = append(ret, get(p.properties.Deps)...)
+		ret = append(ret, get(p.properties.DepsProperty)...)
 	} else if arch.Multilib == "lib32" {
-		ret = append(ret, get(p.properties.Multilib.Lib32.Deps)...)
+		ret = append(ret, get(p.properties.Multilib.Lib32)...)
 		// multilib.prefer32.deps are added for lib32 only when they support 32-bit arch
-		for _, dep := range get(p.properties.Multilib.Prefer32.Deps) {
+		for _, dep := range get(p.properties.Multilib.Prefer32) {
 			if checkIfOtherModuleSupportsLib32(ctx, dep) {
 				ret = append(ret, dep)
 			}
 		}
 	} else if arch.Multilib == "lib64" {
-		ret = append(ret, get(p.properties.Multilib.Lib64.Deps)...)
+		ret = append(ret, get(p.properties.Multilib.Lib64)...)
 		// multilib.prefer32.deps are added for lib64 only when they don't support 32-bit arch
-		for _, dep := range get(p.properties.Multilib.Prefer32.Deps) {
+		for _, dep := range get(p.properties.Multilib.Prefer32) {
 			if !checkIfOtherModuleSupportsLib32(ctx, dep) {
 				ret = append(ret, dep)
 			}
 		}
 	} else if arch == Common {
-		ret = append(ret, get(p.properties.Multilib.Common.Deps)...)
+		ret = append(ret, get(p.properties.Multilib.Common)...)
 	}
 
 	if p.DepsCollectFirstTargetOnly {
-		if len(get(p.properties.Multilib.First.Deps)) > 0 {
+		if len(get(p.properties.Multilib.First)) > 0 {
 			ctx.PropertyErrorf("multilib.first.deps", "not supported. use \"deps\" instead")
 		}
 		for i, t := range ctx.MultiTargets() {
 			if t.Arch.ArchType == arch {
-				ret = append(ret, get(p.properties.Multilib.Both.Deps)...)
+				ret = append(ret, get(p.properties.Multilib.Both)...)
 				if i == 0 {
-					ret = append(ret, get(p.properties.Deps)...)
+					ret = append(ret, get(p.properties.DepsProperty)...)
 				}
 			}
 		}
 	} else {
-		if len(get(p.properties.Multilib.Both.Deps)) > 0 {
+		if len(get(p.properties.Multilib.Both)) > 0 {
 			ctx.PropertyErrorf("multilib.both.deps", "not supported. use \"deps\" instead")
 		}
 		for i, t := range ctx.MultiTargets() {
 			if t.Arch.ArchType == arch {
-				ret = append(ret, get(p.properties.Deps)...)
+				ret = append(ret, get(p.properties.DepsProperty)...)
 				if i == 0 {
-					ret = append(ret, get(p.properties.Multilib.First.Deps)...)
+					ret = append(ret, get(p.properties.Multilib.First)...)
 				}
 			}
 		}
@@ -306,13 +338,13 @@
 	if ctx.Arch().ArchType == Common {
 		switch arch {
 		case Arm64:
-			ret = append(ret, get(p.properties.Arch.Arm64.Deps)...)
+			ret = append(ret, get(p.properties.Arch.Arm64)...)
 		case Arm:
-			ret = append(ret, get(p.properties.Arch.Arm.Deps)...)
+			ret = append(ret, get(p.properties.Arch.Arm)...)
 		case X86_64:
-			ret = append(ret, get(p.properties.Arch.X86_64.Deps)...)
+			ret = append(ret, get(p.properties.Arch.X86_64)...)
 		case X86:
-			ret = append(ret, get(p.properties.Arch.X86.Deps)...)
+			ret = append(ret, get(p.properties.Arch.X86)...)
 		}
 	}
 
@@ -360,6 +392,8 @@
 	IsPackagingItem() bool
 }
 
+var _ PackagingItem = (*PackagingItemAlwaysDepTag)(nil)
+
 // DepTag provides default implementation of PackagingItem interface.
 // PackagingBase-derived modules can define their own dependency tag by embedding this, which
 // can be passed to AddDeps() or AddDependencies().
@@ -371,8 +405,14 @@
 	return true
 }
 
+// highPriorityDepTag provides default implementation of HighPriorityPackagingItem interface.
+type highPriorityDepTag struct {
+	blueprint.DependencyTag
+}
+
 // See PackageModule.AddDeps
 func (p *PackagingBase) AddDeps(ctx BottomUpMutatorContext, depTag blueprint.DependencyTag) {
+	highPriorityDeps := p.highPriorityDeps()
 	for _, t := range getSupportedTargets(ctx) {
 		for _, dep := range p.getDepsForArch(ctx, t.Arch.ArchType) {
 			if p.IgnoreMissingDependencies && !ctx.OtherModuleExists(dep) {
@@ -388,14 +428,22 @@
 			if ctx.OtherModuleFarDependencyVariantExists([]blueprint.Variation{sharedVariation}, dep) {
 				targetVariation = append(targetVariation, sharedVariation)
 			}
+			if InList(dep, highPriorityDeps) {
+				depTag = highPriorityDepTag{depTag}
+			}
+
 			ctx.AddFarVariationDependencies(targetVariation, depTag, dep)
 		}
 	}
 }
 
 func (p *PackagingBase) GatherPackagingSpecsWithFilter(ctx ModuleContext, filter func(PackagingSpec) bool) map[string]PackagingSpec {
-	// all packaging specs gathered from the dep.
-	var all []PackagingSpec
+	// packaging specs gathered from the dep that are not high priorities.
+	var regularPriorities []PackagingSpec
+
+	// 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).
@@ -420,7 +468,8 @@
 	}
 
 	ctx.VisitDirectDeps(func(child Module) {
-		if pi, ok := ctx.OtherModuleDependencyTag(child).(PackagingItem); !ok || !pi.IsPackagingItem() {
+		depTag := ctx.OtherModuleDependencyTag(child)
+		if pi, ok := depTag.(PackagingItem); !ok || !pi.IsPackagingItem() {
 			return
 		}
 		for _, ps := range OtherModuleProviderOrDefault(
@@ -434,7 +483,13 @@
 					continue
 				}
 			}
-			all = append(all, ps)
+
+			if _, ok := depTag.(highPriorityDepTag); ok {
+				highPriorities = append(highPriorities, ps)
+			} else {
+				regularPriorities = append(regularPriorities, ps)
+			}
+
 			depNames = append(depNames, child.Name())
 			if ps.overrides != nil {
 				overridden = append(overridden, *ps.overrides...)
@@ -442,21 +497,26 @@
 		}
 	})
 
-	// all minus packaging specs that are overridden
-	var filtered []PackagingSpec
-	for index, ps := range all {
-		if ps.owner != "" && InList(ps.owner, overridden) {
-			continue
+	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
+			}
+			// The dependency which requested this packaging spec has been overridden.
+			if InList(depNames[index], overridden) {
+				continue
+			}
+			filtered = append(filtered, ps)
 		}
-		// The dependency which requested this packaging spec has been overridden.
-		if InList(depNames[index], overridden) {
-			continue
-		}
-		filtered = append(filtered, ps)
+		return filtered
 	}
 
+	filteredRegularPriority := filterOverridden(regularPriorities)
+
 	m := make(map[string]PackagingSpec)
-	for _, ps := range filtered {
+	for _, ps := range filteredRegularPriority {
 		dstPath := ps.relPathInPackage
 		if existingPs, ok := m[dstPath]; ok {
 			if !existingPs.Equals(&ps) {
@@ -466,6 +526,21 @@
 		}
 		m[dstPath] = ps
 	}
+
+	filteredHighPriority := filterOverridden(highPriorities)
+	highPriorityPs := make(map[string]PackagingSpec)
+	for _, ps := range filteredHighPriority {
+		dstPath := ps.relPathInPackage
+		if existingPs, ok := highPriorityPs[dstPath]; ok {
+			if !existingPs.Equals(&ps) {
+				ctx.ModuleErrorf("packaging conflict at %v:\n%v\n%v", dstPath, existingPs, ps)
+			}
+			continue
+		}
+		highPriorityPs[dstPath] = ps
+		m[dstPath] = ps
+	}
+
 	return m
 }
 
diff --git a/android/variable.go b/android/variable.go
index 4cdf5fb..a4ee886 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -541,6 +541,8 @@
 	ProductManifestFiles   []string `json:",omitempty"`
 	SystemManifestFile     []string `json:",omitempty"`
 	SystemExtManifestFiles []string `json:",omitempty"`
+	DeviceManifestFiles    []string `json:",omitempty"`
+	OdmManifestFiles       []string `json:",omitempty"`
 }
 
 type PartitionQualifiedVariablesType struct {
diff --git a/android/vintf_data.go b/android/vintf_data.go
index cd5f096..7823397 100644
--- a/android/vintf_data.go
+++ b/android/vintf_data.go
@@ -26,6 +26,8 @@
 	systemManifestType    = "system_manifest"
 	productManifestType   = "product_manifest"
 	systemExtManifestType = "system_ext_manifest"
+	vendorManifestType    = "vendor_manifest"
+	odmManifestType       = "odm_manifest"
 
 	defaultDcm               = "system/libhidl/vintfdata/device_compatibility_matrix.default.xml"
 	defaultSystemManifest    = "system/libhidl/vintfdata/manifest.xml"
@@ -111,6 +113,27 @@
 		if len(systemExtManifestFiles) > 0 {
 			inputPaths = append(inputPaths, systemExtManifestFiles...)
 		}
+	case vendorManifestType:
+		assembleVintfEnvs = append(assembleVintfEnvs, fmt.Sprintf("BOARD_SEPOLICY_VERS=\"%s\"", ctx.DeviceConfig().BoardSepolicyVers()))
+		assembleVintfEnvs = append(assembleVintfEnvs, fmt.Sprintf("PRODUCT_ENFORCE_VINTF_MANIFEST=%t", *ctx.Config().productVariables.Enforce_vintf_manifest))
+		deviceManifestFiles := PathsForSource(ctx, ctx.Config().DeviceManifestFiles())
+		// Only need to generate the manifest if DEVICE_MANIFEST_FILE is defined.
+		if len(deviceManifestFiles) == 0 {
+			m.noAction = true
+			return
+		}
+
+		inputPaths = append(inputPaths, deviceManifestFiles...)
+	case odmManifestType:
+		assembleVintfEnvs = append(assembleVintfEnvs, "VINTF_IGNORE_TARGET_FCM_VERSION=true")
+		odmManifestFiles := PathsForSource(ctx, ctx.Config().OdmManifestFiles())
+		// Only need to generate the manifest if ODM_MANIFEST_FILES is defined.
+		if len(odmManifestFiles) == 0 {
+			m.noAction = true
+			return
+		}
+
+		inputPaths = append(inputPaths, odmManifestFiles...)
 	default:
 		panic(fmt.Errorf("For %s: The attribute 'type' value only allowed device_cm, system_manifest, product_manifest, system_ext_manifest!", ctx.Module().Name()))
 	}
diff --git a/cc/ndk_library.go b/cc/ndk_library.go
index 01551ab..2411614 100644
--- a/cc/ndk_library.go
+++ b/cc/ndk_library.go
@@ -144,11 +144,9 @@
 }
 
 func ndkLibraryVersions(ctx android.BaseModuleContext, from android.ApiLevel) []string {
-	var versions []android.ApiLevel
 	versionStrs := []string{}
-	for _, version := range ctx.Config().AllSupportedApiLevels() {
+	for _, version := range ctx.Config().FinalApiLevels() {
 		if version.GreaterThanOrEqualTo(from) {
-			versions = append(versions, version)
 			versionStrs = append(versionStrs, version.String())
 		}
 	}
@@ -330,6 +328,12 @@
 	return android.ExistentPathForSource(ctx, subpath)
 }
 
+func (this *stubDecorator) builtAbiDumpLocation(ctx ModuleContext, apiLevel android.ApiLevel) android.OutputPath {
+	return getNdkAbiDumpInstallBase(ctx).Join(ctx,
+		apiLevel.String(), ctx.Arch().ArchType.String(),
+		this.libraryName(ctx), "abi.stg")
+}
+
 // Feature flag.
 func (this *stubDecorator) canDumpAbi(ctx ModuleContext) bool {
 	if runtime.GOOS == "darwin" {
@@ -345,25 +349,24 @@
 		return false
 	}
 
-	if this.apiLevel.IsCurrent() {
-		// "current" (AKA 10000) is not tracked.
-		return false
-	}
-
 	// http://b/156513478
 	return ctx.Config().ReleaseNdkAbiMonitored()
 }
 
 // Feature flag to disable diffing against prebuilts.
-func canDiffAbi(config android.Config) bool {
+func (this *stubDecorator) canDiffAbi(config android.Config) bool {
+	if this.apiLevel.IsCurrent() {
+		// Diffs are performed from this to next, and there's nothing after
+		// current.
+		return false
+	}
+
 	return config.ReleaseNdkAbiMonitored()
 }
 
 func (this *stubDecorator) dumpAbi(ctx ModuleContext, symbolList android.Path) {
 	implementationLibrary := this.findImplementationLibrary(ctx)
-	this.abiDumpPath = getNdkAbiDumpInstallBase(ctx).Join(ctx,
-		this.apiLevel.String(), ctx.Arch().ArchType.String(),
-		this.libraryName(ctx), "abi.stg")
+	this.abiDumpPath = this.builtAbiDumpLocation(ctx, this.apiLevel)
 	this.hasAbiDump = true
 	headersList := getNdkABIHeadersFile(ctx)
 	ctx.Build(pctx, android.BuildParams{
@@ -383,7 +386,7 @@
 }
 
 func findNextApiLevel(ctx ModuleContext, apiLevel android.ApiLevel) *android.ApiLevel {
-	apiLevels := append(ctx.Config().AllSupportedApiLevels(),
+	apiLevels := append(ctx.Config().FinalApiLevels(),
 		android.FutureApiLevel)
 	for _, api := range apiLevels {
 		if api.GreaterThan(apiLevel) {
@@ -436,38 +439,49 @@
 				"non-current API level %s", this.apiLevel))
 		}
 
-		// "current" ABI is not tracked.
-		if !nextApiLevel.IsCurrent() {
-			nextAbiDiffPath := android.PathForModuleOut(ctx,
-				"abidiff_next.timestamp")
-			nextAbiDump := this.findPrebuiltAbiDump(ctx, *nextApiLevel)
+		// Preview ABI levels are not recorded in prebuilts. ABI compatibility
+		// for preview APIs is still monitored via "current" so we have early
+		// warning rather than learning about an ABI break during finalization,
+		// but is only checked against the "current" API dumps in the out
+		// directory.
+		nextAbiDiffPath := android.PathForModuleOut(ctx,
+			"abidiff_next.timestamp")
+
+		var nextAbiDump android.OptionalPath
+		if nextApiLevel.IsCurrent() {
+			nextAbiDump = android.OptionalPathForPath(
+				this.builtAbiDumpLocation(ctx, *nextApiLevel),
+			)
+		} else {
+			nextAbiDump = this.findPrebuiltAbiDump(ctx, *nextApiLevel)
+		}
+
+		if !nextAbiDump.Valid() {
 			missingNextPrebuiltError := fmt.Sprintf(
 				missingPrebuiltErrorTemplate, this.libraryName(ctx),
 				nextAbiDump.InvalidReason())
-			if !nextAbiDump.Valid() {
-				ctx.Build(pctx, android.BuildParams{
-					Rule:   android.ErrorRule,
-					Output: nextAbiDiffPath,
-					Args: map[string]string{
-						"error": missingNextPrebuiltError,
-					},
-				})
-			} else {
-				ctx.Build(pctx, android.BuildParams{
-					Rule: stgdiff,
-					Description: fmt.Sprintf(
-						"Comparing ABI to the next API level %s %s",
-						prebuiltAbiDump, nextAbiDump),
-					Output: nextAbiDiffPath,
-					Inputs: android.Paths{
-						prebuiltAbiDump.Path(), nextAbiDump.Path()},
-					Args: map[string]string{
-						"args": "--format=small --ignore=interface_addition",
-					},
-				})
-			}
-			this.abiDiffPaths = append(this.abiDiffPaths, nextAbiDiffPath)
+			ctx.Build(pctx, android.BuildParams{
+				Rule:   android.ErrorRule,
+				Output: nextAbiDiffPath,
+				Args: map[string]string{
+					"error": missingNextPrebuiltError,
+				},
+			})
+		} else {
+			ctx.Build(pctx, android.BuildParams{
+				Rule: stgdiff,
+				Description: fmt.Sprintf(
+					"Comparing ABI to the next API level %s %s",
+					prebuiltAbiDump, nextAbiDump),
+				Output: nextAbiDiffPath,
+				Inputs: android.Paths{
+					prebuiltAbiDump.Path(), nextAbiDump.Path()},
+				Args: map[string]string{
+					"args": "--format=small --ignore=interface_addition",
+				},
+			})
 		}
+		this.abiDiffPaths = append(this.abiDiffPaths, nextAbiDiffPath)
 	}
 }
 
@@ -492,7 +506,7 @@
 	c.versionScriptPath = nativeAbiResult.versionScript
 	if c.canDumpAbi(ctx) {
 		c.dumpAbi(ctx, nativeAbiResult.symbolList)
-		if canDiffAbi(ctx.Config()) {
+		if c.canDiffAbi(ctx.Config()) {
 			c.diffAbi(ctx)
 		}
 	}
diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go
index d0d4825..6ed962f 100644
--- a/filesystem/filesystem.go
+++ b/filesystem/filesystem.go
@@ -147,9 +147,7 @@
 
 	Erofs ErofsProperties
 
-	// List of files (in .json format) that will be converted to a linker config file (in .pb format).
-	// The linker config file be installed in the filesystem at /etc/linker.config.pb
-	Linker_config_srcs []string `android:"path"`
+	Linkerconfig LinkerConfigProperties
 
 	// Determines if the module is auto-generated from Soong or not. If the module is
 	// auto-generated, its deps are exempted from visibility enforcement.
@@ -168,6 +166,16 @@
 	Sparse *bool
 }
 
+type LinkerConfigProperties struct {
+
+	// Build a linker.config.pb file
+	Gen_linker_config *bool
+
+	// List of files (in .json format) that will be converted to a linker config file (in .pb format).
+	// The linker config file be installed in the filesystem at /etc/linker.config.pb
+	Linker_config_srcs []string `android:"path"`
+}
+
 // android_filesystem packages a set of modules and their transitive dependencies into a filesystem
 // image. The filesystem images are expected to be mounted in the target device, which means the
 // modules in the filesystem image are built for the target device (i.e. Android, not Linux host).
@@ -184,6 +192,7 @@
 	module.AddProperties(&filesystemModule.properties)
 	android.InitPackageModule(filesystemModule)
 	filesystemModule.PackagingBase.DepsCollectFirstTargetOnly = true
+	filesystemModule.PackagingBase.AllowHighPriorityDeps = true
 	android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
 	android.InitDefaultableModule(module)
 }
@@ -690,13 +699,13 @@
 }
 
 func (f *filesystem) buildLinkerConfigFile(ctx android.ModuleContext, builder *android.RuleBuilder, rebasedDir android.OutputPath) {
-	if len(f.properties.Linker_config_srcs) == 0 {
+	if !proptools.Bool(f.properties.Linkerconfig.Gen_linker_config) {
 		return
 	}
 
 	provideModules, _ := f.getLibsForLinkerConfig(ctx)
 	output := rebasedDir.Join(ctx, "etc", "linker.config.pb")
-	linkerconfig.BuildLinkerConfig(ctx, builder, android.PathsForModuleSrc(ctx, f.properties.Linker_config_srcs), provideModules, nil, output)
+	linkerconfig.BuildLinkerConfig(ctx, builder, android.PathsForModuleSrc(ctx, f.properties.Linkerconfig.Linker_config_srcs), provideModules, nil, output)
 
 	f.appendToEntry(ctx, output)
 }
diff --git a/filesystem/filesystem_test.go b/filesystem/filesystem_test.go
index 8fe5dac..f767eae 100644
--- a/filesystem/filesystem_test.go
+++ b/filesystem/filesystem_test.go
@@ -670,7 +670,10 @@
 android_filesystem {
     name: "myfilesystem",
     deps: ["libfoo_has_no_stubs", "libfoo_has_stubs"],
-    linker_config_srcs: ["linker.config.json"],
+    linkerconfig: {
+	    gen_linker_config: true,
+	    linker_config_srcs: ["linker.config.json"],
+    },
     partition_type: "vendor",
 }
 cc_library {
diff --git a/fsgen/Android.bp b/fsgen/Android.bp
index 9fa9557..baf9291 100644
--- a/fsgen/Android.bp
+++ b/fsgen/Android.bp
@@ -18,6 +18,7 @@
         "filesystem_creator_test.go",
     ],
     pluginFor: ["soong_build"],
+    visibility: ["//visibility:public"],
 }
 
 soong_filesystem_creator {
diff --git a/fsgen/filesystem_creator.go b/fsgen/filesystem_creator.go
index 71af3f9..001cac8 100644
--- a/fsgen/filesystem_creator.go
+++ b/fsgen/filesystem_creator.go
@@ -237,8 +237,9 @@
 }
 
 type packagingPropsStruct struct {
-	Deps     []string
-	Multilib multilibDepsStruct
+	High_priority_deps []string
+	Deps               []string
+	Multilib           multilibDepsStruct
 }
 
 func fullyQualifiedModuleName(moduleName, namespace string) string {
@@ -314,12 +315,16 @@
 	})
 }
 
+var HighPriorityDeps = []string{}
+
 func generateDepStruct(deps map[string]*depCandidateProps) *packagingPropsStruct {
 	depsStruct := packagingPropsStruct{}
 	for depName, depProps := range deps {
 		bitness := getBitness(depProps.Arch)
 		fullyQualifiedDepName := fullyQualifiedModuleName(depName, depProps.Namespace)
-		if android.InList("32", bitness) && android.InList("64", bitness) {
+		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
 			switch depProps.Multilib {
 			case string(android.MultilibBoth):
@@ -495,7 +500,8 @@
 	}
 
 	if partitionType == "vendor" || partitionType == "product" {
-		fsProps.Linker_config_srcs = f.createLinkerConfigSourceFilegroups(ctx, partitionType)
+		fsProps.Linkerconfig.Gen_linker_config = proptools.BoolPtr(true)
+		fsProps.Linkerconfig.Linker_config_srcs = f.createLinkerConfigSourceFilegroups(ctx, partitionType)
 	}
 
 	var module android.Module
diff --git a/sdk/Android.bp b/sdk/Android.bp
index f436320..f42b478 100644
--- a/sdk/Android.bp
+++ b/sdk/Android.bp
@@ -18,7 +18,6 @@
         "bp.go",
         "build_release.go",
         "exports.go",
-        "genrule.go",
         "member_trait.go",
         "member_type.go",
         "sdk.go",
@@ -31,7 +30,6 @@
         "cc_sdk_test.go",
         "compat_config_sdk_test.go",
         "exports_test.go",
-        "genrule_test.go",
         "java_sdk_test.go",
         "license_sdk_test.go",
         "member_trait_test.go",
diff --git a/sdk/genrule.go b/sdk/genrule.go
deleted file mode 100644
index 347ab05..0000000
--- a/sdk/genrule.go
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2023 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 sdk
-
-import (
-	"android/soong/android"
-	"android/soong/genrule"
-)
-
-func init() {
-	registerGenRuleBuildComponents(android.InitRegistrationContext)
-}
-
-func registerGenRuleBuildComponents(ctx android.RegistrationContext) {
-	ctx.RegisterModuleType("sdk_genrule", SdkGenruleFactory)
-}
-
-// sdk_genrule_host is a genrule that can depend on sdk and sdk_snapshot module types
-//
-// What this means is that it's a genrule with only the "common_os" variant.
-// sdk modules have 3 variants: host, android, and common_os. The common_os one depends
-// on the host/device ones and packages their result into a final snapshot zip.
-// Genrules probably want access to this snapshot zip when they depend on an sdk module,
-// which means they want to depend on the common_os variant and not the host/android
-// variants.
-func SdkGenruleFactory() android.Module {
-	module := genrule.NewGenRule()
-
-	android.InitCommonOSAndroidMultiTargetsArchModule(module, android.NeitherHostNorDeviceSupported, android.MultilibCommon)
-	android.InitDefaultableModule(module)
-
-	return module
-}
diff --git a/sdk/genrule_test.go b/sdk/genrule_test.go
deleted file mode 100644
index bf67795..0000000
--- a/sdk/genrule_test.go
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2018 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 sdk
-
-import (
-	"testing"
-
-	"android/soong/android"
-	"android/soong/genrule"
-	"android/soong/java"
-)
-
-func TestSdkGenrule(t *testing.T) {
-	// Test that a genrule can depend on an sdk if using common_os_srcs
-	bp := `
-				sdk {
-					name: "my_sdk",
-				}
-				genrule {
-					name: "my_regular_genrule",
-					common_os_srcs: [":my_sdk"],
-					out: ["out"],
-					cmd: "cp $(in) $(out)",
-				}
-			`
-	android.GroupFixturePreparers(
-		// if java components aren't registered, the sdk module doesn't create a snapshot for some reason.
-		java.PrepareForTestWithJavaBuildComponents,
-		genrule.PrepareForTestWithGenRuleBuildComponents,
-		PrepareForTestWithSdkBuildComponents,
-		android.FixtureRegisterWithContext(registerGenRuleBuildComponents),
-	).RunTestWithBp(t, bp)
-}