Merge "Support converting LOCAL_ROTATION_MIN_SDK_VERSION" into main
diff --git a/android/androidmk.go b/android/androidmk.go
index 7d6b056..62ab596 100644
--- a/android/androidmk.go
+++ b/android/androidmk.go
@@ -779,17 +779,6 @@
 func (so *soongOnlyAndroidMkSingleton) soongOnlyBuildActions(ctx SingletonContext, mods []blueprint.Module) {
 	allDistContributions, moduleInfoJSONs := getSoongOnlyDataFromMods(ctx, mods)
 
-	for _, provider := range append(makeVarsInitProviders, *getSingletonMakevarsProviders(ctx.Config())...) {
-		mctx := &makeVarsContext{
-			SingletonContext: ctx,
-			pctx:             provider.pctx,
-		}
-		provider.call(mctx)
-		if contribution := distsToDistContributions(mctx.dists); contribution != nil {
-			allDistContributions = append(allDistContributions, *contribution)
-		}
-	}
-
 	singletonDists := getSingletonDists(ctx.Config())
 	singletonDists.lock.Lock()
 	if contribution := distsToDistContributions(singletonDists.dists); contribution != nil {
@@ -966,31 +955,6 @@
 					}
 				}
 			}
-			if x, ok := mod.(ModuleMakeVarsProvider); ok {
-				mctx := &makeVarsContext{
-					SingletonContext: ctx.(SingletonContext),
-					config:           ctx.Config(),
-					pctx:             pctx,
-				}
-				if !x.Enabled(ctx) {
-					continue
-				}
-				x.MakeVars(mctx)
-				if contribution := distsToDistContributions(mctx.dists); contribution != nil {
-					allDistContributions = append(allDistContributions, *contribution)
-				}
-			}
-			if x, ok := mod.(SingletonMakeVarsProvider); ok {
-				mctx := &makeVarsContext{
-					SingletonContext: ctx.(SingletonContext),
-					config:           ctx.Config(),
-					pctx:             pctx,
-				}
-				x.MakeVars(mctx)
-				if contribution := distsToDistContributions(mctx.dists); contribution != nil {
-					allDistContributions = append(allDistContributions, *contribution)
-				}
-			}
 		}
 	}
 	return allDistContributions, moduleInfoJSONs
diff --git a/android/api_levels.go b/android/api_levels.go
index 6d0c389..c042eeb 100644
--- a/android/api_levels.go
+++ b/android/api_levels.go
@@ -468,6 +468,7 @@
 		"Tiramisu":        33,
 		"UpsideDownCake":  34,
 		"VanillaIceCream": 35,
+		"Baklava":         36,
 	}, nil
 }
 
diff --git a/android/makevars.go b/android/makevars.go
index baa1d44..2931d0b 100644
--- a/android/makevars.go
+++ b/android/makevars.go
@@ -65,24 +65,6 @@
 	// dependencies to be added to it.  Phony can be called on the same name multiple
 	// times to add additional dependencies.
 	Phony(names string, deps ...Path)
-
-	// DistForGoal creates a rule to copy one or more Paths to the artifacts
-	// directory on the build server when the specified goal is built.
-	DistForGoal(goal string, paths ...Path)
-
-	// DistForGoalWithFilename creates a rule to copy a Path to the artifacts
-	// directory on the build server with the given filename when the specified
-	// goal is built.
-	DistForGoalWithFilename(goal string, path Path, filename string)
-
-	// DistForGoals creates a rule to copy one or more Paths to the artifacts
-	// directory on the build server when any of the specified goals are built.
-	DistForGoals(goals []string, paths ...Path)
-
-	// DistForGoalsWithFilename creates a rule to copy a Path to the artifacts
-	// directory on the build server with the given filename when any of the
-	// specified goals are built.
-	DistForGoalsWithFilename(goals []string, path Path, filename string)
 }
 
 // MakeVarsContext contains the set of functions available for MakeVarsProvider
@@ -198,11 +180,9 @@
 
 type makeVarsContext struct {
 	SingletonContext
-	config  Config
 	pctx    PackageContext
 	vars    []makeVarsVariable
 	phonies []phony
-	dists   []dist
 }
 
 var _ MakeVarsContext = &makeVarsContext{}
@@ -263,7 +243,6 @@
 
 		vars = append(vars, mctx.vars...)
 		phonies = append(phonies, mctx.phonies...)
-		dists = append(dists, mctx.dists...)
 	}
 
 	singletonDists := getSingletonDists(ctx.Config())
@@ -281,7 +260,6 @@
 
 			vars = append(vars, mctx.vars...)
 			phonies = append(phonies, mctx.phonies...)
-			dists = append(dists, mctx.dists...)
 		}
 
 		if m.ExportedToMake() {
@@ -611,13 +589,6 @@
 	c.phonies = append(c.phonies, phony{name, deps})
 }
 
-func (c *makeVarsContext) addDist(goals []string, paths []distCopy) {
-	c.dists = append(c.dists, dist{
-		goals: goals,
-		paths: paths,
-	})
-}
-
 func (c *makeVarsContext) Strict(name, ninjaStr string) {
 	c.addVariable(name, ninjaStr, true, false)
 }
@@ -641,26 +612,3 @@
 func (c *makeVarsContext) Phony(name string, deps ...Path) {
 	c.addPhony(name, Paths(deps).Strings())
 }
-
-func (c *makeVarsContext) DistForGoal(goal string, paths ...Path) {
-	c.DistForGoals([]string{goal}, paths...)
-}
-
-func (c *makeVarsContext) DistForGoalWithFilename(goal string, path Path, filename string) {
-	c.DistForGoalsWithFilename([]string{goal}, path, filename)
-}
-
-func (c *makeVarsContext) DistForGoals(goals []string, paths ...Path) {
-	var copies distCopies
-	for _, path := range paths {
-		copies = append(copies, distCopy{
-			from: path,
-			dest: path.Base(),
-		})
-	}
-	c.addDist(goals, copies)
-}
-
-func (c *makeVarsContext) DistForGoalsWithFilename(goals []string, path Path, filename string) {
-	c.addDist(goals, distCopies{{from: path, dest: filename}})
-}
diff --git a/cc/test.go b/cc/test.go
index b3b2ae8..2c5c36e 100644
--- a/cc/test.go
+++ b/cc/test.go
@@ -418,6 +418,10 @@
 			if test.testConfig != nil {
 				ctx.InstallFile(testCases, ctx.ModuleName()+".config", test.testConfig)
 			}
+			dynamicConfig := android.ExistentPathForSource(ctx, ctx.ModuleDir(), "DynamicConfig.xml")
+			if dynamicConfig.Valid() {
+				ctx.InstallFile(testCases, ctx.ModuleName()+".dynamic", dynamicConfig.Path())
+			}
 			for _, extraTestConfig := range test.extraTestConfigs {
 				ctx.InstallFile(testCases, extraTestConfig.Base(), extraTestConfig)
 			}
diff --git a/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go
index e882470..1452b41 100644
--- a/dexpreopt/dexpreopt.go
+++ b/dexpreopt/dexpreopt.go
@@ -284,7 +284,8 @@
 		clcTargetString := "PCL[" + strings.Join(clcTarget, ":") + "]"
 
 		if systemServerClasspathJars.ContainsJar(module.Name) {
-			checkSystemServerOrder(ctx, jarIndex)
+			// TODO(b/397461231): renable this check
+			//checkSystemServerOrder(ctx, jarIndex)
 		} else {
 			// Standalone jars are loaded by separate class loaders with SYSTEMSERVERCLASSPATH as the
 			// parent.
diff --git a/filesystem/android_device.go b/filesystem/android_device.go
index 8d7f92f..4f6f983 100644
--- a/filesystem/android_device.go
+++ b/filesystem/android_device.go
@@ -302,11 +302,6 @@
 		targetFilesZipCopy{a.partitionProps.Init_boot_partition_name, "INIT_BOOT/RAMDISK"},
 		targetFilesZipCopy{a.partitionProps.Vendor_boot_partition_name, "VENDOR_BOOT/RAMDISK"},
 	}
-	// TODO: Handle cases where recovery files are copied to BOOT/ or RECOVERY/
-	// https://cs.android.com/android/platform/superproject/main/+/main:build/make/core/Makefile;l=6211-6219?q=core%2FMakefile&ss=android%2Fplatform%2Fsuperproject%2Fmain
-	if ctx.DeviceConfig().BoardMoveRecoveryResourcesToVendorBoot() {
-		toCopy = append(toCopy, targetFilesZipCopy{a.partitionProps.Recovery_partition_name, "VENDOR_BOOT/RAMDISK"})
-	}
 
 	filesystemsToCopy := []targetFilesystemZipCopy{}
 	for _, zipCopy := range toCopy {
@@ -343,6 +338,12 @@
 			BuiltTool("acp").
 			Textf("-rd %s/. %s/%s", rootDirString, targetFilesDir, toCopy.destSubdir).
 			Implicit(toCopy.fsInfo.Output) // so that the staging dir is built
+		for _, extraRootDir := range toCopy.fsInfo.ExtraRootDirs {
+			builder.Command().
+				BuiltTool("acp").
+				Textf("-rd %s/. %s/%s", extraRootDir, targetFilesDir, toCopy.destSubdir).
+				Implicit(toCopy.fsInfo.Output) // so that the staging dir is built
+		}
 
 		if toCopy.destSubdir == "SYSTEM" {
 			// Create the ROOT partition in target_files.zip
diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go
index f84993d..c78061a 100644
--- a/filesystem/filesystem.go
+++ b/filesystem/filesystem.go
@@ -397,6 +397,9 @@
 	// to add a dependency on the Output file, as you cannot add dependencies on directories
 	// in ninja.
 	RootDir android.Path
+	// Extra root directories that are also built into the partition. Currently only used for
+	// including the recovery partition files into the vendor_boot image.
+	ExtraRootDirs android.Paths
 	// The rebased staging directory used to build the output filesystem. If consuming this, make
 	// sure to add a dependency on the Output file, as you cannot add dependencies on directories
 	// in ninja. In many cases this is the same as RootDir, only in the system partition is it
@@ -612,6 +615,7 @@
 	var outputHermetic android.WritablePath
 	var buildImagePropFile android.Path
 	var buildImagePropFileDeps android.Paths
+	var extraRootDirs android.Paths
 	switch f.fsType(ctx) {
 	case ext4Type, erofsType, f2fsType:
 		buildImagePropFile, buildImagePropFileDeps = f.buildPropFile(ctx)
@@ -625,9 +629,9 @@
 		f.buildImageUsingBuildImage(ctx, hermeticBuilder, buildImageParams{rootDir, propFileHermetic, buildImagePropFileDeps, outputHermetic})
 		mapFile = f.getMapFile(ctx)
 	case compressedCpioType:
-		f.output = f.buildCpioImage(ctx, builder, rootDir, true)
+		f.output, extraRootDirs = f.buildCpioImage(ctx, builder, rootDir, true)
 	case cpioType:
-		f.output = f.buildCpioImage(ctx, builder, rootDir, false)
+		f.output, extraRootDirs = f.buildCpioImage(ctx, builder, rootDir, false)
 	default:
 		return
 	}
@@ -659,6 +663,7 @@
 		OutputHermetic:         outputHermetic,
 		FileListFile:           fileListFile,
 		RootDir:                rootDir,
+		ExtraRootDirs:          extraRootDirs,
 		RebasedDir:             rebasedDir,
 		MapFile:                mapFile,
 		ModuleName:             ctx.ModuleName(),
@@ -1157,7 +1162,7 @@
 	builder *android.RuleBuilder,
 	rootDir android.OutputPath,
 	compressed bool,
-) android.Path {
+) (android.Path, android.Paths) {
 	if proptools.Bool(f.properties.Use_avb) {
 		ctx.PropertyErrorf("use_avb", "signing compresed cpio image using avbtool is not supported."+
 			"Consider adding this to bootimg module and signing the entire boot image.")
@@ -1197,7 +1202,7 @@
 	// rootDir is not deleted. Might be useful for quick inspection.
 	builder.Build("build_cpio_image", fmt.Sprintf("Creating filesystem %s", f.BaseModuleName()))
 
-	return output
+	return output, rootDirs
 }
 
 var validPartitions = []string{
diff --git a/fsgen/filesystem_creator.go b/fsgen/filesystem_creator.go
index c2721d2..e2485a1 100644
--- a/fsgen/filesystem_creator.go
+++ b/fsgen/filesystem_creator.go
@@ -377,7 +377,7 @@
 	if modName := partitions.nameForType("userdata"); modName != "" {
 		partitionProps.Userdata_partition_name = proptools.StringPtr(modName)
 	}
-	if modName := partitions.nameForType("recovery"); modName != "" {
+	if modName := partitions.nameForType("recovery"); modName != "" && !ctx.DeviceConfig().BoardMoveRecoveryResourcesToVendorBoot() {
 		partitionProps.Recovery_partition_name = proptools.StringPtr(modName)
 	}
 	if modName := partitions.nameForType("system_dlkm"); modName != "" && !android.InList("system_dlkm", superImageSubPartitions) {
diff --git a/java/app.go b/java/app.go
index 89d688d..02e65be 100644
--- a/java/app.go
+++ b/java/app.go
@@ -1627,6 +1627,10 @@
 		if a.testConfig != nil {
 			ctx.InstallFile(pathInTestCases, ctx.Module().Name()+".config", a.testConfig)
 		}
+		dynamicConfig := android.ExistentPathForSource(ctx, ctx.ModuleDir(), "DynamicConfig.xml")
+		if dynamicConfig.Valid() {
+			ctx.InstallFile(pathInTestCases, ctx.Module().Name()+".dynamic", dynamicConfig.Path())
+		}
 		testDeps := append(a.data, a.extraTestConfigs...)
 		for _, data := range android.SortedUniquePaths(testDeps) {
 			dataPath := android.DataPath{SrcPath: data}
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index 27027f0..313d8c7 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -554,7 +554,10 @@
 				typ: dexpreoptBootJar,
 			}
 
-			ctx.AddFarVariationDependencies(ctx.Target().Variations(), tag, android.RemoveOptionalPrebuiltPrefix(selected))
+			dep := android.RemoveOptionalPrebuiltPrefix(selected)
+			if ctx.OtherModuleDependencyVariantExists(ctx.Target().Variations(), dep) {
+				ctx.AddFarVariationDependencies(ctx.Target().Variations(), tag, dep)
+			}
 		}
 	}
 }
diff --git a/java/java.go b/java/java.go
index c5dee0c..af2b86e 100644
--- a/java/java.go
+++ b/java/java.go
@@ -1910,6 +1910,10 @@
 		if j.testConfig != nil {
 			ctx.InstallFile(pathInTestCases, ctx.ModuleName()+".config", j.testConfig)
 		}
+		dynamicConfig := android.ExistentPathForSource(ctx, ctx.ModuleDir(), "DynamicConfig.xml")
+		if dynamicConfig.Valid() {
+			ctx.InstallFile(pathInTestCases, ctx.ModuleName()+".dynamic", dynamicConfig.Path())
+		}
 		testDeps := append(j.data, j.extraTestConfigs...)
 		for _, data := range android.SortedUniquePaths(testDeps) {
 			dataPath := android.DataPath{SrcPath: data}
diff --git a/python/test.go b/python/test.go
index 5e70fc1..df62ab7 100644
--- a/python/test.go
+++ b/python/test.go
@@ -224,6 +224,10 @@
 			if p.testConfig != nil {
 				ctx.InstallFile(testCases, ctx.ModuleName()+".config", p.testConfig)
 			}
+			dynamicConfig := android.ExistentPathForSource(ctx, ctx.ModuleDir(), "DynamicConfig.xml")
+			if dynamicConfig.Valid() {
+				ctx.InstallFile(testCases, ctx.ModuleName()+".dynamic", dynamicConfig.Path())
+			}
 		}
 		// Install tests and data in arch specific subdir $PRODUCT_OUT/testcases/$module/$arch
 		testCases = testCases.Join(ctx, ctx.Target().Arch.ArchType.String())
diff --git a/rust/test.go b/rust/test.go
index b658ae2..5c183bc 100644
--- a/rust/test.go
+++ b/rust/test.go
@@ -208,6 +208,10 @@
 			if test.testConfig != nil {
 				ctx.InstallFile(testCases, ctx.ModuleName()+".config", test.testConfig)
 			}
+			dynamicConfig := android.ExistentPathForSource(ctx, ctx.ModuleDir(), "DynamicConfig.xml")
+			if dynamicConfig.Valid() {
+				ctx.InstallFile(testCases, ctx.ModuleName()+".dynamic", dynamicConfig.Path())
+			}
 		}
 		// Install tests and data in arch specific subdir $PRODUCT_OUT/testcases/$module/$arch
 		testCases = testCases.Join(ctx, ctx.Target().Arch.ArchType.String())