Merge "Generate aconfig flags for autogenerated system_ext partition" into main
diff --git a/android/config.go b/android/config.go
index 696e772..9ccd099 100644
--- a/android/config.go
+++ b/android/config.go
@@ -385,24 +385,28 @@
 }
 
 type partialCompileFlags struct {
-	// Is partial compilation enabled at all?
-	Enabled bool
-
 	// Whether to use d8 instead of r8
 	Use_d8 bool
 
+	// Whether to disable stub validation.  This is slightly more surgical
+	// than DISABLE_STUB_VALIDATION, in that it only applies to partial
+	// compile builds.
+	Disable_stub_validation bool
+
+	// Whether to disable api lint.
+	Disable_api_lint bool
+
 	// Add others as needed.
 }
 
 // These are the flags when `SOONG_PARTIAL_COMPILE` is empty or not set.
-var defaultPartialCompileFlags = partialCompileFlags{
-	Enabled: false,
-}
+var defaultPartialCompileFlags = partialCompileFlags{}
 
 // These are the flags when `SOONG_PARTIAL_COMPILE=true`.
 var enabledPartialCompileFlags = partialCompileFlags{
-	Enabled: true,
-	Use_d8:  true,
+	Use_d8:                  true,
+	Disable_stub_validation: false,
+	Disable_api_lint:        false,
 }
 
 type deviceConfig struct {
@@ -477,13 +481,29 @@
 			state = "+"
 		}
 		switch tok {
+		case "all":
+			// Turn on **all** of the flags.
+			ret = partialCompileFlags{
+				Use_d8:                  true,
+				Disable_stub_validation: true,
+				Disable_api_lint:        true,
+			}
 		case "true":
 			ret = enabledPartialCompileFlags
 		case "false":
 			// Set everything to false.
 			ret = partialCompileFlags{}
-		case "enabled":
-			ret.Enabled = makeVal(state, defaultPartialCompileFlags.Enabled)
+
+		case "api_lint", "enable_api_lint":
+			ret.Disable_api_lint = !makeVal(state, !defaultPartialCompileFlags.Disable_api_lint)
+		case "disable_api_lint":
+			ret.Disable_api_lint = makeVal(state, defaultPartialCompileFlags.Disable_api_lint)
+
+		case "stub_validation", "enable_stub_validation":
+			ret.Disable_stub_validation = !makeVal(state, !defaultPartialCompileFlags.Disable_stub_validation)
+		case "disable_stub_validation":
+			ret.Disable_stub_validation = makeVal(state, defaultPartialCompileFlags.Disable_stub_validation)
+
 		case "use_d8":
 			ret.Use_d8 = makeVal(state, defaultPartialCompileFlags.Use_d8)
 		default:
diff --git a/android/config_test.go b/android/config_test.go
index 3d86860..d1b26c1 100644
--- a/android/config_test.go
+++ b/android/config_test.go
@@ -213,13 +213,18 @@
 	})
 }
 
-func (p partialCompileFlags) updateEnabled(value bool) partialCompileFlags {
-	p.Enabled = value
+func (p partialCompileFlags) updateUseD8(value bool) partialCompileFlags {
+	p.Use_d8 = value
 	return p
 }
 
-func (p partialCompileFlags) updateUseD8(value bool) partialCompileFlags {
-	p.Use_d8 = value
+func (p partialCompileFlags) updateDisableApiLint(value bool) partialCompileFlags {
+	p.Disable_api_lint = value
+	return p
+}
+
+func (p partialCompileFlags) updateDisableStubValidation(value bool) partialCompileFlags {
+	p.Disable_stub_validation = value
 	return p
 }
 
@@ -241,10 +246,29 @@
 		{"false", true, partialCompileFlags{}},
 		{"true", true, enabledPartialCompileFlags},
 		{"true", false, partialCompileFlags{}},
+		{"all", true, partialCompileFlags{}.updateUseD8(true).updateDisableApiLint(true).updateDisableStubValidation(true)},
+
+		// This verifies both use_d8 and the processing order.
 		{"true,use_d8", true, enabledPartialCompileFlags.updateUseD8(true)},
 		{"true,-use_d8", true, enabledPartialCompileFlags.updateUseD8(false)},
 		{"use_d8,false", true, partialCompileFlags{}},
 		{"false,+use_d8", true, partialCompileFlags{}.updateUseD8(true)},
+
+		// disable_api_lint can be specified with any of 3 options.
+		{"false,-api_lint", true, partialCompileFlags{}.updateDisableApiLint(true)},
+		{"false,-enable_api_lint", true, partialCompileFlags{}.updateDisableApiLint(true)},
+		{"false,+disable_api_lint", true, partialCompileFlags{}.updateDisableApiLint(true)},
+		{"false,+api_lint", true, partialCompileFlags{}.updateDisableApiLint(false)},
+		{"false,+enable_api_lint", true, partialCompileFlags{}.updateDisableApiLint(false)},
+		{"false,-disable_api_lint", true, partialCompileFlags{}.updateDisableApiLint(false)},
+
+		// disable_stub_validation can be specified with any of 3 options.
+		{"false,-stub_validation", true, partialCompileFlags{}.updateDisableStubValidation(true)},
+		{"false,-enable_stub_validation", true, partialCompileFlags{}.updateDisableStubValidation(true)},
+		{"false,+disable_stub_validation", true, partialCompileFlags{}.updateDisableStubValidation(true)},
+		{"false,+stub_validation", true, partialCompileFlags{}.updateDisableStubValidation(false)},
+		{"false,+enable_stub_validation", true, partialCompileFlags{}.updateDisableStubValidation(false)},
+		{"false,-disable_stub_validation", true, partialCompileFlags{}.updateDisableStubValidation(false)},
 	}
 
 	for _, test := range tests {
diff --git a/android/module.go b/android/module.go
index 713751a..a56fea3 100644
--- a/android/module.go
+++ b/android/module.go
@@ -1669,9 +1669,10 @@
 
 	if len(ctx.installFiles) > 0 {
 		name := namespacePrefix + ctx.ModuleName() + "-install"
-		ctx.Phony(name, ctx.installFiles.Paths()...)
+		installFiles := ctx.installFiles.Paths()
+		ctx.Phony(name, installFiles...)
 		info.InstallTarget = PathForPhony(ctx, name)
-		deps = append(deps, info.InstallTarget)
+		deps = append(deps, installFiles...)
 	}
 
 	// A module's -checkbuild phony targets should
@@ -1681,13 +1682,13 @@
 	if (!ctx.Config().KatiEnabled() || !shouldSkipAndroidMkProcessing(ctx, m)) && !ctx.uncheckedModule && ctx.checkbuildTarget != nil {
 		name := namespacePrefix + ctx.ModuleName() + "-checkbuild"
 		ctx.Phony(name, ctx.checkbuildTarget)
-		deps = append(deps, PathForPhony(ctx, name))
+		deps = append(deps, ctx.checkbuildTarget)
 	}
 
 	if outputFiles, err := outputFilesForModule(ctx, ctx.Module(), ""); err == nil && len(outputFiles) > 0 {
 		name := namespacePrefix + ctx.ModuleName() + "-outputs"
 		ctx.Phony(name, outputFiles...)
-		deps = append(deps, PathForPhony(ctx, name))
+		deps = append(deps, outputFiles...)
 	}
 
 	if len(deps) > 0 {
@@ -1914,6 +1915,7 @@
 	Dists                                        []Dist
 	ExportedToMake                               bool
 	Team                                         string
+	PartitionTag                                 string
 }
 
 type ApiLevelOrPlatform struct {
@@ -2281,6 +2283,7 @@
 		Dists:                                        m.Dists(),
 		ExportedToMake:                               m.ExportedToMake(),
 		Team:                                         m.Team(),
+		PartitionTag:                                 m.PartitionTag(ctx.DeviceConfig()),
 	}
 	if mm, ok := m.module.(interface {
 		MinSdkVersion(ctx EarlyModuleContext) ApiLevel
diff --git a/android/rule_builder.go b/android/rule_builder.go
index db56c3f..ea6aaa4 100644
--- a/android/rule_builder.go
+++ b/android/rule_builder.go
@@ -1187,7 +1187,11 @@
 // Textf adds the specified formatted text to the command line.  The text should not contain input or output paths or
 // the rule will not have them listed in its dependencies or outputs.
 func (c *RuleBuilderCommand) Textf(format string, a ...interface{}) *RuleBuilderCommand {
-	return c.Text(fmt.Sprintf(format, a...))
+	if c.buf.Len() > 0 {
+		c.buf.WriteByte(' ')
+	}
+	fmt.Fprintf(&c.buf, format, a...)
+	return c
 }
 
 // Flag adds the specified raw text to the command line.  The text should not contain input or output paths or the
diff --git a/cc/afdo.go b/cc/afdo.go
index 1233e33..9be3918 100644
--- a/cc/afdo.go
+++ b/cc/afdo.go
@@ -108,6 +108,8 @@
 		// Salvage stale profile by fuzzy matching and use the remapped location for sample profile query.
 		flags.Local.CFlags = append([]string{"-mllvm", "--salvage-stale-profile=true"}, flags.Local.CFlags...)
 		flags.Local.CFlags = append([]string{"-mllvm", "--salvage-stale-profile-max-callsites=2000"}, flags.Local.CFlags...)
+		// Salvage stale profile by fuzzy matching renamed functions.
+		flags.Local.CFlags = append([]string{"-mllvm", "--salvage-unused-profile=true"}, flags.Local.CFlags...)
 		flags.Local.LdFlags = append([]string{profileUseFlag, "-Wl,-mllvm,-no-warn-sample-unused=true"}, flags.Local.LdFlags...)
 
 		// Update CFlagsDeps and LdFlagsDeps so the module is rebuilt
diff --git a/filesystem/android_device.go b/filesystem/android_device.go
index 5911a4e..3d306e3 100644
--- a/filesystem/android_device.go
+++ b/filesystem/android_device.go
@@ -106,12 +106,14 @@
 
 	allImagesZip android.Path
 
-	proguardDictZip     android.Path
-	proguardDictMapping android.Path
-	proguardUsageZip    android.Path
-	kernelConfig        android.Path
-	kernelVersion       android.Path
-	miscInfo            android.Path
+	proguardDictZip             android.Path
+	proguardDictMapping         android.Path
+	proguardUsageZip            android.Path
+	kernelConfig                android.Path
+	kernelVersion               android.Path
+	miscInfo                    android.Path
+	rootDirForFsConfig          string
+	rootDirForFsConfigTimestamp android.Path
 }
 
 func AndroidDeviceFactory() android.Module {
@@ -335,6 +337,10 @@
 		ctx.DistForGoalWithFilename("droidcore-unbundled", a.proguardDictZip, namePrefix+insertBeforeExtension(a.proguardDictZip.Base(), "-FILE_NAME_TAG_PLACEHOLDER"))
 		ctx.DistForGoalWithFilename("droidcore-unbundled", a.proguardDictMapping, namePrefix+insertBeforeExtension(a.proguardDictMapping.Base(), "-FILE_NAME_TAG_PLACEHOLDER"))
 		ctx.DistForGoalWithFilename("droidcore-unbundled", a.proguardUsageZip, namePrefix+insertBeforeExtension(a.proguardUsageZip.Base(), "-FILE_NAME_TAG_PLACEHOLDER"))
+
+		if a.deviceProps.Android_info != nil {
+			ctx.DistForGoal("droidcore-unbundled", android.PathForModuleSrc(ctx, *a.deviceProps.Android_info))
+		}
 	}
 }
 
@@ -472,6 +478,17 @@
 		if toCopy.destSubdir == "SYSTEM" {
 			// Create the ROOT partition in target_files.zip
 			builder.Command().Textf("rsync --links --exclude=system/* %s/ -r %s/ROOT", toCopy.fsInfo.RootDir, targetFilesDir.String())
+			// Add a duplicate rule to assemble the ROOT/ directory in separate intermediates.
+			// The output timestamp will be an input to a separate fs_config call.
+			a.rootDirForFsConfig = android.PathForModuleOut(ctx, "root_dir_for_fs_config").String()
+			rootDirBuilder := android.NewRuleBuilder(pctx, ctx)
+			rootDirForFsConfigTimestamp := android.PathForModuleOut(ctx, "root_dir_for_fs_config.timestamp")
+			rootDirBuilder.Command().Textf("rsync --links --exclude=system/* %s/ -r %s", toCopy.fsInfo.RootDir, a.rootDirForFsConfig).
+				Implicit(toCopy.fsInfo.Output).
+				Text("&& touch").
+				Output(rootDirForFsConfigTimestamp)
+			rootDirBuilder.Build("assemble_root_dir_for_fs_config", "Assemble ROOT/ for fs_config")
+			a.rootDirForFsConfigTimestamp = rootDirForFsConfigTimestamp
 		}
 	}
 	// Copy cmdline, kernel etc. files of boot images
@@ -610,11 +627,11 @@
 		}
 		if partition == "system" {
 			// Create root_filesystem_config from the assembled ROOT/ intermediates directory
-			a.generateFilesystemConfigForTargetFiles(ctx, builder, targetFilesDir.String(), targetFilesDir.String()+"/ROOT", "root_filesystem_config.txt")
+			a.generateFilesystemConfigForTargetFiles(ctx, builder, a.rootDirForFsConfigTimestamp, targetFilesDir.String(), a.rootDirForFsConfig, "root_filesystem_config.txt")
 		}
 		if partition == "vendor_ramdisk" {
 			// Create vendor_boot_filesystem_config from the assembled VENDOR_BOOT/RAMDISK intermediates directory
-			a.generateFilesystemConfigForTargetFiles(ctx, builder, targetFilesDir.String(), targetFilesDir.String()+"/VENDOR_BOOT/RAMDISK", "vendor_boot_filesystem_config.txt")
+			a.generateFilesystemConfigForTargetFiles(ctx, builder, nil, targetFilesDir.String(), targetFilesDir.String()+"/VENDOR_BOOT/RAMDISK", "vendor_boot_filesystem_config.txt")
 		}
 	}
 	// Copy ramdisk_node_list
@@ -727,11 +744,12 @@
 
 var ApexKeyPathInfoProvider = blueprint.NewProvider[ApexKeyPathInfo]()
 
-func (a *androidDevice) generateFilesystemConfigForTargetFiles(ctx android.ModuleContext, builder *android.RuleBuilder, targetFilesDir, stagingDir, filename string) {
+func (a *androidDevice) generateFilesystemConfigForTargetFiles(ctx android.ModuleContext, builder *android.RuleBuilder, stagingDirTimestamp android.Path, targetFilesDir, stagingDir, filename string) {
 	fsConfigOut := android.PathForModuleOut(ctx, filename)
 	ctx.Build(pctx, android.BuildParams{
-		Rule:   fsConfigRule,
-		Output: fsConfigOut,
+		Rule:     fsConfigRule,
+		Implicit: stagingDirTimestamp,
+		Output:   fsConfigOut,
 		Args: map[string]string{
 			"rootDir": stagingDir,
 			"prefix":  "",
diff --git a/java/droiddoc.go b/java/droiddoc.go
index 225f201..3faf294 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -195,6 +195,9 @@
 				"them instead.")
 		}
 		return false
+	} else if ctx.Config().PartialCompileFlags().Disable_stub_validation &&
+		!ctx.Config().BuildFromTextStub() {
+		return false
 	} else if String(apiToCheck.Api_file) != "" && String(apiToCheck.Removed_api_file) != "" {
 		return true
 	} else if String(apiToCheck.Api_file) != "" {
diff --git a/java/droidstubs.go b/java/droidstubs.go
index b3241cc..c215925 100644
--- a/java/droidstubs.go
+++ b/java/droidstubs.go
@@ -1243,7 +1243,7 @@
 
 	// Add options for the other optional tasks: API-lint and check-released.
 	// We generate separate timestamp files for them.
-	doApiLint := BoolDefault(d.properties.Check_api.Api_lint.Enabled, false)
+	doApiLint := BoolDefault(d.properties.Check_api.Api_lint.Enabled, false) && !ctx.Config().PartialCompileFlags().Disable_api_lint
 	doCheckReleased := apiCheckEnabled(ctx, d.properties.Check_api.Last_released, "last_released")
 
 	writeSdkValues := Bool(d.properties.Write_sdk_values)
diff --git a/java/java.go b/java/java.go
index c1e4f8c..215fbbd 100644
--- a/java/java.go
+++ b/java/java.go
@@ -2530,6 +2530,7 @@
 	apiContributions := al.properties.Api_contributions
 	addValidations := !ctx.Config().IsEnvTrue("DISABLE_STUB_VALIDATION") &&
 		!ctx.Config().IsEnvTrue("WITHOUT_CHECK_API") &&
+		!ctx.Config().PartialCompileFlags().Disable_stub_validation &&
 		proptools.BoolDefault(al.properties.Enable_validation, true)
 	for _, apiContributionName := range apiContributions {
 		ctx.AddDependency(ctx.Module(), javaApiContributionTag, apiContributionName)
diff --git a/java/rro.go b/java/rro.go
index b3d9348..42d42b8 100644
--- a/java/rro.go
+++ b/java/rro.go
@@ -427,6 +427,11 @@
 	// Install the signed apk
 	installDir := android.PathForModuleInstall(ctx, "overlay")
 	ctx.InstallFile(installDir, signed.Base(), signed)
+
+	android.SetProvider(ctx, RuntimeResourceOverlayInfoProvider, RuntimeResourceOverlayInfo{
+		OutputFile:  signed,
+		Certificate: a.certificate,
+	})
 }
 
 func (a *AutogenRuntimeResourceOverlay) SdkVersion(ctx android.EarlyModuleContext) android.SdkSpec {