Merge "Remove PRODUCT_SHIPPING_VENDOR_API_LEVEL variable" into main
diff --git a/android/compliance_metadata.go b/android/compliance_metadata.go
index 16a3853..83f0721 100644
--- a/android/compliance_metadata.go
+++ b/android/compliance_metadata.go
@@ -129,30 +129,34 @@
 // dependencies, built/installed files, etc. It is a wrapper on a map[string]string with some utility
 // methods to get/set properties' values.
 type ComplianceMetadataInfo struct {
-	properties          map[string]string
-	filesContained      []string
-	prebuiltFilesCopied []string
+	properties             map[string]string
+	filesContained         []string
+	prebuiltFilesCopied    []string
+	platformGeneratedFiles []string
 }
 
 type complianceMetadataInfoGob struct {
-	Properties          map[string]string
-	FilesContained      []string
-	PrebuiltFilesCopied []string
+	Properties             map[string]string
+	FilesContained         []string
+	PrebuiltFilesCopied    []string
+	PlatformGeneratedFiles []string
 }
 
 func NewComplianceMetadataInfo() *ComplianceMetadataInfo {
 	return &ComplianceMetadataInfo{
-		properties:          map[string]string{},
-		filesContained:      make([]string, 0),
-		prebuiltFilesCopied: make([]string, 0),
+		properties:             map[string]string{},
+		filesContained:         make([]string, 0),
+		prebuiltFilesCopied:    make([]string, 0),
+		platformGeneratedFiles: make([]string, 0),
 	}
 }
 
 func (m *ComplianceMetadataInfo) ToGob() *complianceMetadataInfoGob {
 	return &complianceMetadataInfoGob{
-		Properties:          m.properties,
-		FilesContained:      m.filesContained,
-		PrebuiltFilesCopied: m.prebuiltFilesCopied,
+		Properties:             m.properties,
+		FilesContained:         m.filesContained,
+		PrebuiltFilesCopied:    m.prebuiltFilesCopied,
+		PlatformGeneratedFiles: m.platformGeneratedFiles,
 	}
 }
 
@@ -160,6 +164,7 @@
 	m.properties = data.Properties
 	m.filesContained = data.FilesContained
 	m.prebuiltFilesCopied = data.PrebuiltFilesCopied
+	m.platformGeneratedFiles = data.PlatformGeneratedFiles
 }
 
 func (c *ComplianceMetadataInfo) GobEncode() ([]byte, error) {
@@ -197,6 +202,14 @@
 	return c.prebuiltFilesCopied
 }
 
+func (c *ComplianceMetadataInfo) SetPlatformGeneratedFiles(files []string) {
+	c.platformGeneratedFiles = files
+}
+
+func (c *ComplianceMetadataInfo) GetPlatformGeneratedFiles() []string {
+	return c.platformGeneratedFiles
+}
+
 func (c *ComplianceMetadataInfo) getStringValue(propertyName string) string {
 	if !slices.Contains(COMPLIANCE_METADATA_PROPS, propertyName) {
 		panic(fmt.Errorf("Unknown metadata property: %s.", propertyName))
@@ -368,6 +381,8 @@
 							if _, ok := prebuiltFilesSrcDest[file]; ok {
 								srcDestPair := prebuiltFilesSrcDest[file]
 								csvContent = append(csvContent, file+",,,,"+srcDestPair+",,,,,")
+							} else if slices.Contains(metadataInfo.platformGeneratedFiles, file) {
+								csvContent = append(csvContent, file+",,,,,,Y,,,build/soong/licenses/LICENSE")
 							} else {
 								csvContent = append(csvContent, file+",,Y,,,,,,,")
 							}
diff --git a/android/defs.go b/android/defs.go
index 57fcc9b..c4591b0 100644
--- a/android/defs.go
+++ b/android/defs.go
@@ -126,6 +126,12 @@
 			Description: "concatenate files to $out",
 		})
 
+	CatAndSort = pctx.AndroidStaticRule("CatAndSort",
+		blueprint.RuleParams{
+			Command:     "rm -f $out && cat $in > $out && sort -o $out $out",
+			Description: "concatenate sorted file contents to $out",
+		})
+
 	// Used only when USE_GOMA=true is set, to restrict non-goma jobs to the local parallelism value
 	localPool = blueprint.NewBuiltinPool("local_pool")
 
diff --git a/android/module.go b/android/module.go
index b2e91c3..55f170c 100644
--- a/android/module.go
+++ b/android/module.go
@@ -45,14 +45,6 @@
 	// 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.
 	//
@@ -2403,12 +2395,8 @@
 			})
 		}
 	}
-
-	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 b292b5c..e2af4a0 100644
--- a/android/module_proxy.go
+++ b/android/module_proxy.go
@@ -27,10 +27,6 @@
 	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/neverallow.go b/android/neverallow.go
index 98b443e..5307590 100644
--- a/android/neverallow.go
+++ b/android/neverallow.go
@@ -253,6 +253,7 @@
 			NotModuleType("prebuilt_first_stage_ramdisk").
 			NotModuleType("prebuilt_res").
 			NotModuleType("prebuilt_any").
+			NotModuleType("prebuilt_lib").
 			Because("install_in_root is only for init_first_stage or librecovery_ui_ext."),
 	}
 }
diff --git a/android/util.go b/android/util.go
index 4520f40..197bbca 100644
--- a/android/util.go
+++ b/android/util.go
@@ -209,8 +209,8 @@
 // that are in l1 but not l2, and l2 but not l1.
 func ListSetDifference[T comparable](l1, l2 []T) (bool, []T, []T) {
 	listsDiffer := false
-	l1 = firstUnique(l1)
-	l2 = firstUnique(l2)
+	l1 = FirstUnique(l1)
+	l2 = FirstUnique(l2)
 	diff1 := []T{}
 	diff2 := []T{}
 	m1 := setFromList(l1)
@@ -379,21 +379,21 @@
 // FirstUniqueStrings returns all unique elements of a slice of strings, keeping the first copy of
 // each.  It does not modify the input slice.
 func FirstUniqueStrings(list []string) []string {
-	return firstUnique(list)
+	return FirstUnique(list)
 }
 
-// firstUnique returns all unique elements of a slice, keeping the first copy of each.  It
+// FirstUnique returns all unique elements of a slice, keeping the first copy of each.  It
 // does not modify the input slice.
-func firstUnique[T comparable](slice []T) []T {
+func FirstUnique[T comparable](slice []T) []T {
 	// Do not modify the input in-place, operate on a copy instead.
 	slice = CopyOf(slice)
-	return firstUniqueInPlace(slice)
+	return FirstUniqueInPlace(slice)
 }
 
-// firstUniqueInPlace returns all unique elements of a slice, keeping the first copy of
+// FirstUniqueInPlace returns all unique elements of a slice, keeping the first copy of
 // each.  It modifies the slice contents in place, and returns a subslice of the original
 // slice.
-func firstUniqueInPlace[T comparable](slice []T) []T {
+func FirstUniqueInPlace[T comparable](slice []T) []T {
 	// 128 was chosen based on BenchmarkFirstUniqueStrings results.
 	if len(slice) > 128 {
 		return firstUniqueMap(slice)
@@ -401,7 +401,7 @@
 	return firstUniqueList(slice)
 }
 
-// firstUniqueList is an implementation of firstUnique using an O(N^2) list comparison to look for
+// firstUniqueList is an implementation of FirstUnique using an O(N^2) list comparison to look for
 // duplicates.
 func firstUniqueList[T any](in []T) []T {
 	writeIndex := 0
@@ -422,7 +422,7 @@
 	return in[0:writeIndex]
 }
 
-// firstUniqueMap is an implementation of firstUnique using an O(N) hash set lookup to look for
+// firstUniqueMap is an implementation of FirstUnique using an O(N) hash set lookup to look for
 // duplicates.
 func firstUniqueMap[T comparable](in []T) []T {
 	writeIndex := 0
diff --git a/cc/cc.go b/cc/cc.go
index a5e154f..dc9b831 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -2556,27 +2556,6 @@
 	}
 }
 
-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/etc/prebuilt_etc.go b/etc/prebuilt_etc.go
index 7820047..fc5bc30 100644
--- a/etc/prebuilt_etc.go
+++ b/etc/prebuilt_etc.go
@@ -92,6 +92,7 @@
 	ctx.RegisterModuleType("prebuilt_system", PrebuiltSystemFactory)
 	ctx.RegisterModuleType("prebuilt_first_stage_ramdisk", PrebuiltFirstStageRamdiskFactory)
 	ctx.RegisterModuleType("prebuilt_any", PrebuiltAnyFactory)
+	ctx.RegisterModuleType("prebuilt_lib", PrebuiltLibFactory)
 
 	ctx.RegisterModuleType("prebuilt_defaults", defaultsFactory)
 
@@ -862,6 +863,20 @@
 	return module
 }
 
+// prebuilt_lib installs a prebuilt file to <partition>/lib directory for system
+// image.
+// If soc_specific property is set to true, the prebuilt file is installed to the
+// vendor <partition>/lib directory for vendor image.
+func PrebuiltLibFactory() android.Module {
+	module := &PrebuiltEtc{}
+	module.socInstallDirBase = "lib"
+	InitPrebuiltEtcModule(module, "lib")
+	// This module is device-only
+	android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
+	android.InitDefaultableModule(module)
+	return module
+}
+
 // prebuilt_gpu is for a prebuilt artifact in <partition>/gpu directory.
 func PrebuiltGPUFactory() android.Module {
 	module := &PrebuiltEtc{}
diff --git a/filesystem/aconfig_files.go b/filesystem/aconfig_files.go
index 20a1953..66d8833 100644
--- a/filesystem/aconfig_files.go
+++ b/filesystem/aconfig_files.go
@@ -45,6 +45,7 @@
 	specs map[string]android.PackagingSpec,
 	dir android.OutputPath,
 	fullInstallPaths *[]FullInstallPathInfo,
+	platformGeneratedFiles *[]string,
 ) {
 	if !proptools.Bool(f.properties.Gen_aconfig_flags_pb) {
 		return
@@ -88,11 +89,13 @@
 		installAconfigFlagsPath := installEtcDir.Join(ctx, "aconfig_flags.pb")
 		builder.Command().Text("mkdir -p ").Text(installEtcDir.String())
 		builder.Command().Text("cp").Input(aconfigFlagsPb).Text(installAconfigFlagsPath.String())
+		installPath := fullInstallPath.Join(ctx, "etc/aconfig_flags.pb")
 		*fullInstallPaths = append(*fullInstallPaths, FullInstallPathInfo{
-			FullInstallPath: fullInstallPath.Join(ctx, "etc/aconfig_flags.pb"),
+			FullInstallPath: installPath,
 			SourcePath:      aconfigFlagsPb,
 		})
 		f.appendToEntry(ctx, installAconfigFlagsPath)
+		*platformGeneratedFiles = append(*platformGeneratedFiles, installPath.String())
 
 		// To enable fingerprint, we need to have v2 storage files. The default version is 1.
 		storageFilesVersion := 1
@@ -118,11 +121,13 @@
 			})
 			builder.Command().
 				Text("cp").Input(outPath).Text(installPath.String())
+			fip := fullInstallPath.Join(ctx, "etc/aconfig", fileName)
 			*fullInstallPaths = append(*fullInstallPaths, FullInstallPathInfo{
 				SourcePath:      outPath,
-				FullInstallPath: fullInstallPath.Join(ctx, "etc/aconfig", fileName),
+				FullInstallPath: fip,
 			})
 			f.appendToEntry(ctx, installPath)
+			*platformGeneratedFiles = append(*platformGeneratedFiles, fip.String())
 		}
 
 		if ctx.Config().ReleaseCreateAconfigStorageFile() {
diff --git a/filesystem/android_device.go b/filesystem/android_device.go
index bc00279..9b0159d 100644
--- a/filesystem/android_device.go
+++ b/filesystem/android_device.go
@@ -304,11 +304,13 @@
 	// Collect metadata from deps
 	filesContained := make([]string, 0)
 	prebuiltFilesCopied := make([]string, 0)
+	platformGeneratedFiles := make([]string, 0)
 	for _, tag := range tags {
 		ctx.VisitDirectDepsProxyWithTag(tag, func(m android.ModuleProxy) {
 			if complianceMetadataInfo, ok := android.OtherModuleProvider(ctx, m, android.ComplianceMetadataProvider); ok {
 				filesContained = append(filesContained, complianceMetadataInfo.GetFilesContained()...)
 				prebuiltFilesCopied = append(prebuiltFilesCopied, complianceMetadataInfo.GetPrebuiltFilesCopied()...)
+				platformGeneratedFiles = append(platformGeneratedFiles, complianceMetadataInfo.GetPlatformGeneratedFiles()...)
 			}
 		})
 	}
@@ -321,6 +323,10 @@
 	prebuiltFilesCopied = append(prebuiltFilesCopied, complianceMetadataInfo.GetPrebuiltFilesCopied()...)
 	sort.Strings(prebuiltFilesCopied)
 	complianceMetadataInfo.SetPrebuiltFilesCopied(prebuiltFilesCopied)
+
+	platformGeneratedFiles = append(platformGeneratedFiles, complianceMetadataInfo.GetPlatformGeneratedFiles()...)
+	sort.Strings(platformGeneratedFiles)
+	complianceMetadataInfo.SetPlatformGeneratedFiles(platformGeneratedFiles)
 }
 
 type installedOwnerInfo struct {
@@ -361,9 +367,7 @@
 	})
 
 	// Remove duplicates
-	ret = android.FirstUniqueFunc(ret, func(a, b android.Module) bool {
-		return a.String() == b.String()
-	})
+	ret = android.FirstUniqueInPlace(ret)
 
 	// Sort the modules by their names and variants
 	slices.SortFunc(ret, func(a, b android.Module) int {
@@ -1182,7 +1186,7 @@
 	android.WriteFileRuleVerbatim(ctx, apkCertsInfoWithoutAppSets, strings.Join(apkCerts, "\n")+"\n")
 	apkCertsInfo := android.PathForModuleOut(ctx, "apkcerts.txt")
 	ctx.Build(pctx, android.BuildParams{
-		Rule:        android.Cat,
+		Rule:        android.CatAndSort,
 		Description: "combine apkcerts.txt",
 		Output:      apkCertsInfo,
 		Inputs:      append(apkCertsFiles, apkCertsInfoWithoutAppSets),
diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go
index df60a8c..d2131dc 100644
--- a/filesystem/filesystem.go
+++ b/filesystem/filesystem.go
@@ -104,7 +104,7 @@
 }
 
 type filesystemBuilder interface {
-	BuildLinkerConfigFile(ctx android.ModuleContext, builder *android.RuleBuilder, rebasedDir android.OutputPath, fullInstallPaths *[]FullInstallPathInfo)
+	BuildLinkerConfigFile(ctx android.ModuleContext, builder *android.RuleBuilder, rebasedDir android.OutputPath, fullInstallPaths *[]FullInstallPathInfo, platformGeneratedFiles *[]string)
 	// Function that filters PackagingSpec in PackagingBase.GatherPackagingSpecs()
 	FilterPackagingSpec(spec android.PackagingSpec) bool
 	// Function that modifies PackagingSpec in PackagingBase.GatherPackagingSpecs() to customize.
@@ -638,12 +638,13 @@
 		})
 	}
 
+	platformGeneratedFiles := []string{}
 	f.entries = f.copyPackagingSpecs(ctx, builder, specs, rootDir, rebasedDir)
-	f.buildNonDepsFiles(ctx, builder, rootDir, rebasedDir, &fullInstallPaths)
+	f.buildNonDepsFiles(ctx, builder, rootDir, rebasedDir, &fullInstallPaths, &platformGeneratedFiles)
 	f.buildFsverityMetadataFiles(ctx, builder, specs, rootDir, rebasedDir, &fullInstallPaths)
-	f.buildEventLogtagsFile(ctx, builder, rebasedDir, &fullInstallPaths)
-	f.buildAconfigFlagsFiles(ctx, builder, specs, rebasedDir, &fullInstallPaths)
-	f.filesystemBuilder.BuildLinkerConfigFile(ctx, builder, rebasedDir, &fullInstallPaths)
+	f.buildEventLogtagsFile(ctx, builder, rebasedDir, &fullInstallPaths, &platformGeneratedFiles)
+	f.buildAconfigFlagsFiles(ctx, builder, specs, rebasedDir, &fullInstallPaths, &platformGeneratedFiles)
+	f.filesystemBuilder.BuildLinkerConfigFile(ctx, builder, rebasedDir, &fullInstallPaths, &platformGeneratedFiles)
 	// Assemeble the staging dir and output a timestamp
 	builder.Command().Text("touch").Output(f.fileystemStagingDirTimestamp(ctx))
 	builder.Build("assemble_filesystem_staging_dir", fmt.Sprintf("Assemble filesystem staging dir %s", f.BaseModuleName()))
@@ -703,6 +704,29 @@
 		erofsCompressHints = android.PathForModuleSrc(ctx, *f.properties.Erofs.Compress_hints)
 	}
 
+	installedFilesStructList := []InstalledFilesStruct{buildInstalledFiles(ctx, partitionNameForInstalledFiles, rebasedDir, f.output)}
+	if f.partitionName() == "system" {
+		rootDirForInstalledFiles := android.PathForModuleOut(ctx, "root_for_installed_files", "root")
+		copyToRootTimestamp := android.PathForModuleOut(ctx, "root_copy_timestamp")
+
+		builder := android.NewRuleBuilder(pctx, ctx)
+		builder.Command().Text("touch").Text(copyToRootTimestamp.String())
+		builder.Command().Text("rm -rf").Text(rootDirForInstalledFiles.String())
+		builder.Command().Text("mkdir -p").Text(rootDirForInstalledFiles.String())
+		builder.Command().
+			Text("rsync").
+			Flag("-a").
+			Flag("--checksum").
+			Flag("--exclude='system/'").
+			Text(rootDir.String() + "/").
+			Text(rootDirForInstalledFiles.String()).
+			Implicit(f.output).
+			ImplicitOutput(copyToRootTimestamp)
+		builder.Build("system_root_dir", "Construct system partition root dir")
+
+		installedFilesStructList = append(installedFilesStructList, buildInstalledFiles(ctx, "root", rootDirForInstalledFiles, copyToRootTimestamp))
+	}
+
 	fsInfo := FilesystemInfo{
 		Output:                 f.OutputPath(),
 		SignedOutputPath:       f.SignedOutputPath(),
@@ -719,7 +743,7 @@
 		FullInstallPaths:       fullInstallPaths,
 		InstalledFilesDepSet: depset.New(
 			depset.POSTORDER,
-			[]InstalledFilesStruct{buildInstalledFiles(ctx, partitionNameForInstalledFiles, rootDir, f.output)},
+			installedFilesStructList,
 			includeFilesInstalledFiles(ctx),
 		),
 		ErofsCompressHints: erofsCompressHints,
@@ -767,6 +791,7 @@
 		filesContained = append(filesContained, file.FullInstallPath.String())
 	}
 	complianceMetadataInfo.SetFilesContained(filesContained)
+	complianceMetadataInfo.SetPlatformGeneratedFiles(platformGeneratedFiles)
 }
 
 func (f *filesystem) fileystemStagingDirTimestamp(ctx android.ModuleContext) android.WritablePath {
@@ -905,6 +930,7 @@
 	rootDir android.OutputPath,
 	rebasedDir android.OutputPath,
 	fullInstallPaths *[]FullInstallPathInfo,
+	platformGeneratedFiles *[]string,
 ) {
 	rebasedPrefix, err := filepath.Rel(rootDir.String(), rebasedDir.String())
 	if err != nil || strings.HasPrefix(rebasedPrefix, "../") {
@@ -958,16 +984,19 @@
 			if !strings.HasPrefix(name, rebasedPrefix) {
 				installPath = android.PathForModuleInPartitionInstall(ctx, "root", name)
 			}
+			*platformGeneratedFiles = append(*platformGeneratedFiles, installPath.String())
 			*fullInstallPaths = append(*fullInstallPaths, FullInstallPathInfo{
 				FullInstallPath: installPath,
 				SymlinkTarget:   target,
 			})
 		} else {
 			if strings.HasPrefix(name, rebasedPrefix) {
+				installPath := android.PathForModuleInPartitionInstall(ctx, f.PartitionType(), strings.TrimPrefix(name, rebasedPrefix))
 				*fullInstallPaths = append(*fullInstallPaths, FullInstallPathInfo{
-					FullInstallPath: android.PathForModuleInPartitionInstall(ctx, f.PartitionType(), strings.TrimPrefix(name, rebasedPrefix)),
+					FullInstallPath: installPath,
 					SymlinkTarget:   target,
 				})
+				*platformGeneratedFiles = append(*platformGeneratedFiles, installPath.String())
 			}
 		}
 	}
@@ -1402,6 +1431,7 @@
 	builder *android.RuleBuilder,
 	rebasedDir android.OutputPath,
 	fullInstallPaths *[]FullInstallPathInfo,
+	platformGeneratedFiles *[]string,
 ) {
 	if !proptools.Bool(f.properties.Build_logtags) {
 		return
@@ -1412,12 +1442,14 @@
 	builder.Command().Text("mkdir").Flag("-p").Text(etcPath.String())
 	builder.Command().Text("cp").Input(android.MergedLogtagsPath(ctx)).Text(eventLogtagsPath.String())
 
+	installPath := android.PathForModuleInPartitionInstall(ctx, f.PartitionType(), "etc", "event-log-tags")
 	*fullInstallPaths = append(*fullInstallPaths, FullInstallPathInfo{
-		FullInstallPath: android.PathForModuleInPartitionInstall(ctx, f.PartitionType(), "etc", "event-log-tags"),
+		FullInstallPath: installPath,
 		SourcePath:      android.MergedLogtagsPath(ctx),
 	})
 
 	f.appendToEntry(ctx, eventLogtagsPath)
+	*platformGeneratedFiles = append(*platformGeneratedFiles, installPath.String())
 }
 
 func (f *filesystem) BuildLinkerConfigFile(
@@ -1425,6 +1457,7 @@
 	builder *android.RuleBuilder,
 	rebasedDir android.OutputPath,
 	fullInstallPaths *[]FullInstallPathInfo,
+	platformGeneratedFiles *[]string,
 ) {
 	if !proptools.Bool(f.properties.Linker_config.Gen_linker_config) {
 		return
@@ -1436,10 +1469,12 @@
 	output := rebasedDir.Join(ctx, "etc", "linker.config.pb")
 	builder.Command().Text("cp").Input(intermediateOutput).Output(output)
 
+	installPath := android.PathForModuleInPartitionInstall(ctx, f.PartitionType(), "etc", "linker.config.pb")
 	*fullInstallPaths = append(*fullInstallPaths, FullInstallPathInfo{
-		FullInstallPath: android.PathForModuleInPartitionInstall(ctx, f.PartitionType(), "etc", "linker.config.pb"),
+		FullInstallPath: installPath,
 		SourcePath:      intermediateOutput,
 	})
+	*platformGeneratedFiles = append(*platformGeneratedFiles, installPath.String())
 
 	f.appendToEntry(ctx, output)
 }
diff --git a/filesystem/system_image.go b/filesystem/system_image.go
index cc9093f..166b052 100644
--- a/filesystem/system_image.go
+++ b/filesystem/system_image.go
@@ -49,6 +49,7 @@
 	builder *android.RuleBuilder,
 	rebasedDir android.OutputPath,
 	fullInstallPaths *[]FullInstallPathInfo,
+	platformGeneratedFiles *[]string,
 ) {
 	if !proptools.Bool(s.filesystem.properties.Linker_config.Gen_linker_config) {
 		return
@@ -61,10 +62,12 @@
 		linkerconfig.BuildLinkerConfig(ctx, android.PathsForModuleSrc(ctx, s.filesystem.properties.Linker_config.Linker_config_srcs), provideModules, requireModules, intermediateOutput)
 		builder.Command().Text("cp").Input(intermediateOutput).Output(output)
 
+		installPath := android.PathForModuleInPartitionInstall(ctx, s.PartitionType(), "etc", "linker.config.pb")
 		*fullInstallPaths = append(*fullInstallPaths, FullInstallPathInfo{
-			FullInstallPath: android.PathForModuleInPartitionInstall(ctx, s.PartitionType(), "etc", "linker.config.pb"),
+			FullInstallPath: installPath,
 			SourcePath:      intermediateOutput,
 		})
+		*platformGeneratedFiles = append(*platformGeneratedFiles, installPath.String())
 	} else {
 		// TODO: This branch is the logic that make uses for the linker config file, which is
 		// different than linkerconfig.BuildLinkerConfig used above. Keeping both branches for now
@@ -98,10 +101,12 @@
 		// TODO: Make also supports adding an extra append command with PRODUCT_EXTRA_STUB_LIBRARIES,
 		// but that variable appears to have no usages.
 
+		installPath := android.PathForModuleInPartitionInstall(ctx, s.PartitionType(), "etc", "linker.config.pb")
 		*fullInstallPaths = append(*fullInstallPaths, FullInstallPathInfo{
-			FullInstallPath: android.PathForModuleInPartitionInstall(ctx, s.PartitionType(), "etc", "linker.config.pb"),
+			FullInstallPath: installPath,
 			SourcePath:      output,
 		})
+		*platformGeneratedFiles = append(*platformGeneratedFiles, installPath.String())
 	}
 
 	s.appendToEntry(ctx, output)
diff --git a/filesystem/system_other.go b/filesystem/system_other.go
index 32a6cc7..67e5f2f 100644
--- a/filesystem/system_other.go
+++ b/filesystem/system_other.go
@@ -23,6 +23,7 @@
 	"time"
 
 	"github.com/google/blueprint"
+	"github.com/google/blueprint/depset"
 	"github.com/google/blueprint/proptools"
 )
 
@@ -93,7 +94,7 @@
 	}
 
 	output := android.PathForModuleOut(ctx, "system_other.img")
-	stagingDir := android.PathForModuleOut(ctx, "staging_dir")
+	stagingDir := android.PathForModuleOut(ctx, "system_other")
 	stagingDirTimestamp := android.PathForModuleOut(ctx, "staging_dir.timestamp")
 
 	builder := android.NewRuleBuilder(pctx, ctx)
@@ -183,6 +184,11 @@
 		RootDir:             stagingDir,
 		FilesystemConfig:    m.generateFilesystemConfig(ctx, stagingDir, stagingDirTimestamp),
 		PropFileForMiscInfo: m.buildPropFileForMiscInfo(ctx),
+		InstalledFilesDepSet: depset.New(
+			depset.POSTORDER,
+			[]InstalledFilesStruct{buildInstalledFiles(ctx, "system-other", stagingDir, output)},
+			nil,
+		),
 	}
 
 	android.SetProvider(ctx, FilesystemProvider, fsInfo)
diff --git a/fsgen/filesystem_creator_test.go b/fsgen/filesystem_creator_test.go
index 2c4d3c8..06a8599 100644
--- a/fsgen/filesystem_creator_test.go
+++ b/fsgen/filesystem_creator_test.go
@@ -252,7 +252,7 @@
 			`),
 		}),
 		android.FixtureModifyConfig(func(config android.Config) {
-			config.TestProductVariables.PartitionVarsForSoongMigrationOnlyDoNotUse.ProductPackages = []string{"libfoo", "libbar"}
+			config.TestProductVariables.PartitionVarsForSoongMigrationOnlyDoNotUse.ProductPackages = []string{"libfoo", "libbar", "prebuiltA", "prebuiltB"}
 		}),
 	).RunTestWithBp(t, `
 java_library {
@@ -266,10 +266,19 @@
 	name: "libbaz",
 	overrides: ["libfoo"], // overrides libfoo
 }
+java_import {
+	name: "prebuiltA",
+}
+java_import {
+	name: "prebuiltB",
+	overrides: ["prebuiltA"], // overrides prebuiltA
+}
 	`)
 	resolvedSystemDeps := result.TestContext.Config().Get(fsGenStateOnceKey).(*FsGenState).fsDeps["system"]
 	_, libFooInDeps := (*resolvedSystemDeps)["libfoo"]
 	android.AssertBoolEquals(t, "libfoo should not appear in deps because it has been overridden by libbaz. The latter is a required dep of libbar, which is listed in PRODUCT_PACKAGES", false, libFooInDeps)
+	_, prebuiltAInDeps := (*resolvedSystemDeps)["prebuiltA"]
+	android.AssertBoolEquals(t, "prebuiltA should not appear in deps because it has been overridden by prebuiltB. The latter is listed in PRODUCT_PACKAGES", false, prebuiltAInDeps)
 }
 
 func TestPrebuiltEtcModuleGen(t *testing.T) {
diff --git a/fsgen/fsgen_mutators.go b/fsgen/fsgen_mutators.go
index 4f3d2a7..bef3712 100644
--- a/fsgen/fsgen_mutators.go
+++ b/fsgen/fsgen_mutators.go
@@ -248,7 +248,7 @@
 	// store the map of module to (required,overrides) even if the module is not in PRODUCT_PACKAGES.
 	// the module might be installed transitively.
 	if m.Enabled(mctx) && m.ExportedToMake() {
-		fsGenState.moduleToInstallationProps[m.Name()] = installationProperties{
+		fsGenState.moduleToInstallationProps[mctx.ModuleName()] = installationProperties{
 			Required:  m.RequiredModuleNames(mctx),
 			Overrides: m.Overrides(),
 		}
diff --git a/java/dex.go b/java/dex.go
index dd64675..e3058e9 100644
--- a/java/dex.go
+++ b/java/dex.go
@@ -42,6 +42,10 @@
 		// True if the module containing this has it set by default.
 		EnabledByDefault bool `blueprint:"mutated"`
 
+		// If true, then `d8` will be used on eng builds instead of `r8`, even though
+		// optimize.enabled is true.
+		D8_on_eng *bool
+
 		// Whether to allow that library classes inherit from program classes.
 		// Defaults to false.
 		Ignore_library_extends_program *bool
@@ -162,7 +166,12 @@
 }
 
 func (d *dexer) effectiveOptimizeEnabled(ctx android.EarlyModuleContext) bool {
-	return BoolDefault(d.dexProperties.Optimize.Enabled, d.dexProperties.Optimize.EnabledByDefault && !ctx.Config().Eng())
+	// For eng builds, if Optimize.D8_on_eng is true, then disable optimization.
+	if ctx.Config().Eng() && proptools.Bool(d.dexProperties.Optimize.D8_on_eng) {
+		return false
+	}
+	// Otherwise, use the legacy logic of a default value which can be explicitly overridden by the module.
+	return BoolDefault(d.dexProperties.Optimize.Enabled, d.dexProperties.Optimize.EnabledByDefault)
 }
 
 func (d *DexProperties) resourceShrinkingEnabled(ctx android.ModuleContext) bool {
diff --git a/rust/fuzz_test.go b/rust/fuzz_test.go
index f462795..bdcfbbb 100644
--- a/rust/fuzz_test.go
+++ b/rust/fuzz_test.go
@@ -134,24 +134,17 @@
 			}
 	`)
 
-	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()
+	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)
 
-	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_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())
 	}
-
-	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_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_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)
+	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())
 	}
 }