Merge "Define PATH_TO_CLANG_TIDY_SHELL for build/make rules."
diff --git a/android/module.go b/android/module.go
index a058199..77765f1 100644
--- a/android/module.go
+++ b/android/module.go
@@ -1067,6 +1067,16 @@
 	return a.kind == productServicesSpecificModule
 }
 
+// Makes this module a platform module, i.e. not specific to soc, device,
+// product, or product_services.
+func (a *ModuleBase) MakeAsPlatform() {
+	a.commonProperties.Vendor = boolPtr(false)
+	a.commonProperties.Proprietary = boolPtr(false)
+	a.commonProperties.Soc_specific = boolPtr(false)
+	a.commonProperties.Product_specific = boolPtr(false)
+	a.commonProperties.Product_services_specific = boolPtr(false)
+}
+
 func (a *androidModuleContext) InstallInData() bool {
 	return a.module.InstallInData()
 }
diff --git a/cc/cc.go b/cc/cc.go
index 7f65640..07dd23c 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -1741,6 +1741,7 @@
 		} else if v == recoveryMode {
 			m := mod[i].(*Module)
 			m.Properties.InRecovery = true
+			m.MakeAsPlatform()
 			squashRecoverySrcs(m)
 		}
 	}
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 3d162e7..3d5dfb1 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -158,11 +158,13 @@
 		cc_object {
 			name: "crtbegin_so",
 			recovery_available: true,
+			vendor_available: true,
 		}
 
 		cc_object {
 			name: "crtend_so",
 			recovery_available: true,
+			vendor_available: true,
 		}
 
 		cc_library {
@@ -236,8 +238,9 @@
 }
 
 const (
-	coreVariant   = "android_arm64_armv8-a_core_shared"
-	vendorVariant = "android_arm64_armv8-a_vendor_shared"
+	coreVariant     = "android_arm64_armv8-a_core_shared"
+	vendorVariant   = "android_arm64_armv8-a_vendor_shared"
+	recoveryVariant = "android_arm64_armv8-a_recovery_shared"
 )
 
 func TestVendorSrc(t *testing.T) {
@@ -1674,6 +1677,11 @@
 			recovery: true,
 			compile_multilib:"32",
 		}
+		cc_library_shared {
+			name: "libHalInRecovery",
+			recovery_available: true,
+			vendor: true,
+		}
 	`)
 
 	variants := ctx.ModuleVariantsForTests("librecovery")
@@ -1686,4 +1694,10 @@
 	if android.InList(arm64, variants) {
 		t.Errorf("multilib was set to 32 for librecovery32, but its variants has %s.", arm64)
 	}
+
+	recoveryModule := ctx.ModuleForTests("libHalInRecovery", recoveryVariant).Module().(*Module)
+	if !recoveryModule.Platform() {
+		t.Errorf("recovery variant of libHalInRecovery must not specific to device, soc, or product")
+	}
+
 }
diff --git a/cmd/multiproduct_kati/main.go b/cmd/multiproduct_kati/main.go
index a6bc8d5..813c060 100644
--- a/cmd/multiproduct_kati/main.go
+++ b/cmd/multiproduct_kati/main.go
@@ -307,7 +307,7 @@
 			}}
 			productCtx.Status.AddOutput(terminal.NewStatusOutput(productCtx.Writer, ""))
 
-			productConfig := build.NewConfig(productCtx)
+			productConfig := build.NewConfig(productCtx, flag.Args()...)
 			productConfig.Environment().Set("OUT_DIR", productOutDir)
 			build.FindSources(productCtx, productConfig, finder)
 			productConfig.Lunch(productCtx, product, *buildVariant)
diff --git a/java/config/config.go b/java/config/config.go
index fa8cb0f..6129349 100644
--- a/java/config/config.go
+++ b/java/config/config.go
@@ -27,7 +27,7 @@
 var (
 	pctx = android.NewPackageContext("android/soong/java/config")
 
-	DefaultBootclasspathLibraries = []string{"core-oj", "core-libart"}
+	DefaultBootclasspathLibraries = []string{"core-oj", "core-libart", "core-simple"}
 	DefaultSystemModules          = "core-system-modules"
 	DefaultLibraries              = []string{"ext", "framework", "okhttp"}
 	DefaultLambdaStubsLibrary     = "core-lambda-stubs"
@@ -43,6 +43,7 @@
 		"android.car7",
 		"core-oj",
 		"core-libart",
+		"core-simple",
 	}
 
 	ManifestMergerClasspath = []string{
diff --git a/java/dex.go b/java/dex.go
index 77a3644..054a176 100644
--- a/java/dex.go
+++ b/java/dex.go
@@ -39,10 +39,12 @@
 var r8 = pctx.AndroidStaticRule("r8",
 	blueprint.RuleParams{
 		Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` +
+			`rm -f "$outDict" && ` +
 			`${config.R8Cmd} -injars $in --output $outDir ` +
 			`--force-proguard-compatibility ` +
 			`-printmapping $outDict ` +
 			`$dxFlags $r8Flags && ` +
+			`touch "$outDict" && ` +
 			`${config.SoongZipCmd} -o $outDir/classes.dex.jar -C $outDir -D $outDir && ` +
 			`${config.MergeZipsCmd} -D -stripFile "**/*.class" $out $outDir/classes.dex.jar $in`,
 		CommandDeps: []string{
diff --git a/java/java.go b/java/java.go
index e20b8b3..7f82c77 100644
--- a/java/java.go
+++ b/java/java.go
@@ -1013,8 +1013,6 @@
 	srcJars = append(srcJars, deps.srcJars...)
 	srcJars = append(srcJars, extraSrcJars...)
 
-	var jars android.Paths
-
 	jarName := ctx.ModuleName() + ".jar"
 
 	javaSrcFiles := srcFiles.FilterByExt(".java")
@@ -1029,6 +1027,8 @@
 
 	var stripFiles []string
 
+	var kotlinJars android.Paths
+
 	if srcFiles.HasExt(".kt") {
 		// If there are kotlin files, compile them first but pass all the kotlin and java files
 		// kotlinc will use the java files to resolve types referenced by the kotlin files, but
@@ -1059,7 +1059,7 @@
 		flags.classpath = append(flags.classpath, kotlinJar)
 
 		// Jar kotlin classes into the final jar after javac
-		jars = append(jars, kotlinJar)
+		kotlinJars = append(kotlinJars, kotlinJar)
 
 		if Bool(j.properties.Renamed_kotlin_stdlib) {
 			// Remove any kotlin-reflect related files
@@ -1070,10 +1070,12 @@
 		} else {
 			// Only add kotlin-stdlib if not using (on-device) renamed stdlib
 			// (it's expected to be on device bootclasspath)
-			jars = append(jars, deps.kotlinStdlib...)
+			kotlinJars = append(kotlinJars, deps.kotlinStdlib...)
 		}
 	}
 
+	jars := append(android.Paths(nil), kotlinJars...)
+
 	// Store the list of .java files that was passed to javac
 	j.compiledJavaSrcs = uniqueSrcFiles
 	j.compiledSrcJars = srcJars
@@ -1089,7 +1091,7 @@
 					j.properties.Javac_shard_size)
 			}
 		}
-		j.headerJarFile = j.compileJavaHeader(ctx, uniqueSrcFiles, srcJars, deps, flags, jarName)
+		j.headerJarFile = j.compileJavaHeader(ctx, uniqueSrcFiles, srcJars, deps, flags, jarName, kotlinJars)
 		if ctx.Failed() {
 			return
 		}
@@ -1296,7 +1298,7 @@
 }
 
 func (j *Module) compileJavaHeader(ctx android.ModuleContext, srcFiles, srcJars android.Paths,
-	deps deps, flags javaBuilderFlags, jarName string) android.Path {
+	deps deps, flags javaBuilderFlags, jarName string, extraJars android.Paths) android.Path {
 
 	var jars android.Paths
 	if len(srcFiles) > 0 || len(srcJars) > 0 {
@@ -1309,6 +1311,8 @@
 		jars = append(jars, turbineJar)
 	}
 
+	jars = append(jars, extraJars...)
+
 	// Combine any static header libraries into classes-header.jar. If there is only
 	// one input jar this step will be skipped.
 	var headerJar android.Path
diff --git a/java/java_test.go b/java/java_test.go
index 72341ee..c9f3dbf 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -101,6 +101,7 @@
 		"core-oj",
 		"core-libart",
 		"core-lambda-stubs",
+		"core-simple",
 		"framework",
 		"ext",
 		"okhttp",
@@ -353,14 +354,14 @@
 }{
 	{
 		name:          "default",
-		bootclasspath: []string{"core-oj", "core-libart"},
+		bootclasspath: []string{"core-oj", "core-libart", "core-simple"},
 		system:        "core-system-modules",
 		classpath:     []string{"ext", "framework", "okhttp"},
 	},
 	{
 		name:          "blank sdk version",
 		properties:    `sdk_version: "",`,
-		bootclasspath: []string{"core-oj", "core-libart"},
+		bootclasspath: []string{"core-oj", "core-libart", "core-simple"},
 		system:        "core-system-modules",
 		classpath:     []string{"ext", "framework", "okhttp"},
 	},
diff --git a/ui/build/config.go b/ui/build/config.go
index c171a67..2605f5b 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -50,8 +50,10 @@
 	targetDevice    string
 	targetDeviceDir string
 
-	pdkBuild       bool
-	brokenDupRules bool
+	pdkBuild bool
+
+	brokenDupRules     bool
+	brokenPhonyTargets bool
 
 	pathReplaced bool
 }
@@ -577,6 +579,14 @@
 	return c.brokenDupRules
 }
 
+func (c *configImpl) SetBuildBrokenPhonyTargets(val bool) {
+	c.brokenPhonyTargets = val
+}
+
+func (c *configImpl) BuildBrokenPhonyTargets() bool {
+	return c.brokenPhonyTargets
+}
+
 func (c *configImpl) SetTargetDeviceDir(dir string) {
 	c.targetDeviceDir = dir
 }
diff --git a/ui/build/dumpvars.go b/ui/build/dumpvars.go
index 8f9d8f2..fadf6c6 100644
--- a/ui/build/dumpvars.go
+++ b/ui/build/dumpvars.go
@@ -165,10 +165,12 @@
 		// Whether --werror_overriding_commands will work
 		"BUILD_BROKEN_DUP_RULES",
 
+		// Used to turn on --werror_ options in Kati
+		"BUILD_BROKEN_PHONY_TARGETS",
+
 		// Not used, but useful to be in the soong.log
 		"BUILD_BROKEN_ANDROIDMK_EXPORTS",
 		"BUILD_BROKEN_DUP_COPY_HEADERS",
-		"BUILD_BROKEN_PHONY_TARGETS",
 	}, exportEnvVars...), BannerVars...)
 
 	make_vars, err := dumpMakeVars(ctx, config, config.Arguments(), allVars, true)
@@ -196,4 +198,5 @@
 
 	config.SetPdkBuild(make_vars["TARGET_BUILD_PDK"] == "true")
 	config.SetBuildBrokenDupRules(make_vars["BUILD_BROKEN_DUP_RULES"] == "true")
+	config.SetBuildBrokenPhonyTargets(make_vars["BUILD_BROKEN_PHONY_TARGETS"] != "false")
 }
diff --git a/ui/build/kati.go b/ui/build/kati.go
index de8dbf4..b54872c 100644
--- a/ui/build/kati.go
+++ b/ui/build/kati.go
@@ -93,6 +93,10 @@
 		args = append(args, "--werror_overriding_commands")
 	}
 
+	if !config.BuildBrokenPhonyTargets() {
+		args = append(args, "--werror_real_to_phony", "--werror_phony_looks_real")
+	}
+
 	if !config.Environment().IsFalse("KATI_EMULATE_FIND") {
 		args = append(args, "--use_find_emulator")
 	}
diff --git a/ui/build/paths/config.go b/ui/build/paths/config.go
index aeefcf2..51fa8fe 100644
--- a/ui/build/paths/config.go
+++ b/ui/build/paths/config.go
@@ -77,6 +77,7 @@
 	"env":       Allowed,
 	"expr":      Allowed,
 	"find":      Allowed,
+	"fuser":     Allowed,
 	"getconf":   Allowed,
 	"getopt":    Allowed,
 	"git":       Allowed,