Merge "Wrapper script to use Starlark-based configuration"
diff --git a/android/testing.go b/android/testing.go
index 191cb8d..b36f62c 100644
--- a/android/testing.go
+++ b/android/testing.go
@@ -713,9 +713,11 @@
 
 func (b baseTestingComponent) maybeBuildParamsFromRule(rule string) (TestingBuildParams, []string) {
 	var searchedRules []string
-	for _, p := range b.provider.BuildParamsForTests() {
-		searchedRules = append(searchedRules, p.Rule.String())
-		if strings.Contains(p.Rule.String(), rule) {
+	buildParams := b.provider.BuildParamsForTests()
+	for _, p := range buildParams {
+		ruleAsString := p.Rule.String()
+		searchedRules = append(searchedRules, ruleAsString)
+		if strings.Contains(ruleAsString, rule) {
 			return b.newTestingBuildParams(p), searchedRules
 		}
 	}
@@ -725,7 +727,7 @@
 func (b baseTestingComponent) buildParamsFromRule(rule string) TestingBuildParams {
 	p, searchRules := b.maybeBuildParamsFromRule(rule)
 	if p.Rule == nil {
-		panic(fmt.Errorf("couldn't find rule %q.\nall rules: %v", rule, searchRules))
+		panic(fmt.Errorf("couldn't find rule %q.\nall rules:\n%s", rule, strings.Join(searchRules, "\n")))
 	}
 	return p
 }
diff --git a/apex/apex.go b/apex/apex.go
index 926085b..33b83c0 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -170,9 +170,10 @@
 	// Default is false.
 	Ignore_system_library_special_case *bool
 
-	// Whenever apex_payload.img of the APEX should include dm-verity hashtree. Should be only
-	// used in tests.
-	Test_only_no_hashtree *bool
+	// Whenever apex_payload.img of the APEX should include dm-verity hashtree.
+	// Default value is false.
+	// TODO(b/190621617): change default value to true.
+	Generate_hashtree *bool
 
 	// Whenever apex_payload.img of the APEX should not be dm-verity signed. Should be only
 	// used in tests.
@@ -1317,9 +1318,9 @@
 	return !a.properties.PreventInstall && (a.properties.Installable == nil || proptools.Bool(a.properties.Installable))
 }
 
-// See the test_only_no_hashtree property
-func (a *apexBundle) testOnlyShouldSkipHashtreeGeneration() bool {
-	return proptools.Bool(a.properties.Test_only_no_hashtree)
+// See the generate_hashtree property
+func (a *apexBundle) shouldGenerateHashtree() bool {
+	return proptools.BoolDefault(a.properties.Generate_hashtree, false)
 }
 
 // See the test_only_unsigned_payload property
diff --git a/apex/builder.go b/apex/builder.go
index 021e499..24c049b 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -630,11 +630,7 @@
 			optFlags = append(optFlags, "--assets_dir "+filepath.Dir(a.mergedNotices.HtmlGzOutput.String()))
 		}
 
-		if ctx.ModuleDir() != "system/apex/apexd/apexd_testdata" && ctx.ModuleDir() != "system/apex/shim/build" && a.testOnlyShouldSkipHashtreeGeneration() {
-			ctx.PropertyErrorf("test_only_no_hashtree", "not available")
-			return
-		}
-		if (moduleMinSdkVersion.GreaterThan(android.SdkVersion_Android10) || a.testOnlyShouldSkipHashtreeGeneration()) && !compressionEnabled {
+		if (moduleMinSdkVersion.GreaterThan(android.SdkVersion_Android10) && !a.shouldGenerateHashtree()) && !compressionEnabled {
 			// Apexes which are supposed to be installed in builtin dirs(/system, etc)
 			// don't need hashtree for activation. Therefore, by removing hashtree from
 			// apex bundle (filesystem image in it, to be specific), we can save storage.
diff --git a/java/base.go b/java/base.go
index 440b004..1daa108 100644
--- a/java/base.go
+++ b/java/base.go
@@ -155,6 +155,11 @@
 
 		// List of java_plugin modules that provide extra errorprone checks.
 		Extra_check_modules []string
+
+		// Whether to run errorprone on a normal build. If this is false, errorprone
+		// will still be run if the RUN_ERROR_PRONE environment variable is true.
+		// Default false.
+		Enabled *bool
 	}
 
 	Proto struct {
@@ -701,7 +706,7 @@
 	// javaVersion flag.
 	flags.javaVersion = getJavaVersion(ctx, String(j.properties.Java_version), android.SdkContext(j))
 
-	if ctx.Config().RunErrorProne() {
+	if ctx.Config().RunErrorProne() || Bool(j.properties.Errorprone.Enabled) {
 		if config.ErrorProneClasspath == nil && ctx.Config().TestProductVariables == nil {
 			ctx.ModuleErrorf("cannot build with Error Prone, missing external/error_prone?")
 		}
@@ -972,14 +977,23 @@
 	}
 	if len(uniqueSrcFiles) > 0 || len(srcJars) > 0 {
 		var extraJarDeps android.Paths
-		if ctx.Config().RunErrorProne() {
-			// If error-prone is enabled, add an additional rule to compile the java files into
-			// a separate set of classes (so that they don't overwrite the normal ones and require
-			// a rebuild when error-prone is turned off).
-			// TODO(ccross): Once we always compile with javac9 we may be able to conditionally
-			//    enable error-prone without affecting the output class files.
+		if Bool(j.properties.Errorprone.Enabled) {
+			// If error-prone is enabled, enable errorprone flags on the regular
+			// build.
+			flags = enableErrorproneFlags(flags)
+		} else if ctx.Config().RunErrorProne() {
+			// Otherwise, if the RUN_ERROR_PRONE environment variable is set, create
+			// a new jar file just for compiling with the errorprone compiler to.
+			// This is because we don't want to cause the java files to get completely
+			// rebuilt every time the state of the RUN_ERROR_PRONE variable changes.
+			// We also don't want to run this if errorprone is enabled by default for
+			// this module, or else we could have duplicated errorprone messages.
+			errorproneFlags := enableErrorproneFlags(flags)
 			errorprone := android.PathForModuleOut(ctx, "errorprone", jarName)
-			RunErrorProne(ctx, errorprone, uniqueSrcFiles, srcJars, flags)
+
+			transformJavaToClasses(ctx, errorprone, -1, uniqueSrcFiles, srcJars, errorproneFlags, nil,
+				"errorprone", "errorprone")
+
 			extraJarDeps = append(extraJarDeps, errorprone)
 		}
 
@@ -1303,6 +1317,21 @@
 	j.outputFile = outputFile.WithoutRel()
 }
 
+// Returns a copy of the supplied flags, but with all the errorprone-related
+// fields copied to the regular build's fields.
+func enableErrorproneFlags(flags javaBuilderFlags) javaBuilderFlags {
+	flags.processorPath = append(flags.errorProneProcessorPath, flags.processorPath...)
+
+	if len(flags.errorProneExtraJavacFlags) > 0 {
+		if len(flags.javacFlags) > 0 {
+			flags.javacFlags += " " + flags.errorProneExtraJavacFlags
+		} else {
+			flags.javacFlags = flags.errorProneExtraJavacFlags
+		}
+	}
+	return flags
+}
+
 func (j *Module) compileJavaClasses(ctx android.ModuleContext, jarName string, idx int,
 	srcFiles, srcJars android.Paths, flags javaBuilderFlags, extraJarDeps android.Paths) android.WritablePath {
 
diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go
index 10d2fe2..fc8f557 100644
--- a/java/bootclasspath_fragment.go
+++ b/java/bootclasspath_fragment.go
@@ -140,7 +140,7 @@
 	// produceHiddenAPIAllFlagsFile produces the all-flags.csv and intermediate files.
 	//
 	// Updates the supplied hiddenAPIInfo with the paths to the generated files set.
-	produceHiddenAPIAllFlagsFile(ctx android.ModuleContext, contents []hiddenAPIModule, input HiddenAPIFlagInput) *HiddenAPIFlagOutput
+	produceHiddenAPIAllFlagsFile(ctx android.ModuleContext, contents []android.Module, input HiddenAPIFlagInput) *HiddenAPIFlagOutput
 }
 
 var _ commonBootclasspathFragment = (*BootclasspathFragmentModule)(nil)
@@ -465,7 +465,7 @@
 			if unencodedDex == nil {
 				// This is an error. Sometimes Soong will report the error directly, other times it will
 				// defer the error reporting to happen only when trying to use the missing file in ninja.
-				// Either way it is handled by extractBootDexJarsFromHiddenAPIModules which must have been
+				// Either way it is handled by extractBootDexJarsFromModules which must have been
 				// called before this as it generates the flags that are used to encode these files.
 				continue
 			}
@@ -561,12 +561,9 @@
 	// TODO(b/179354495): Stop hidden API processing being conditional once all bootclasspath_fragment
 	//  modules have been updated to support it.
 	if input.canPerformHiddenAPIProcessing(ctx, b.properties) {
-		// Get the content modules that contribute to the hidden API processing.
-		hiddenAPIModules := gatherHiddenAPIModuleFromContents(ctx, contents)
-
 		// Delegate the production of the hidden API all-flags.csv file to a module type specific method.
 		common := ctx.Module().(commonBootclasspathFragment)
-		output = common.produceHiddenAPIAllFlagsFile(ctx, hiddenAPIModules, input)
+		output = common.produceHiddenAPIAllFlagsFile(ctx, contents, input)
 	}
 
 	// Initialize a HiddenAPIInfo structure.
@@ -620,7 +617,7 @@
 
 // produceHiddenAPIAllFlagsFile produces the hidden API all-flags.csv file (and supporting files)
 // for the fragment.
-func (b *BootclasspathFragmentModule) produceHiddenAPIAllFlagsFile(ctx android.ModuleContext, contents []hiddenAPIModule, input HiddenAPIFlagInput) *HiddenAPIFlagOutput {
+func (b *BootclasspathFragmentModule) produceHiddenAPIAllFlagsFile(ctx android.ModuleContext, contents []android.Module, input HiddenAPIFlagInput) *HiddenAPIFlagOutput {
 	// Generate the rules to create the hidden API flags and update the supplied hiddenAPIInfo with the
 	// paths to the created files.
 	return hiddenAPIGenerateAllFlagsForBootclasspathFragment(ctx, contents, input)
@@ -841,7 +838,7 @@
 
 // produceHiddenAPIAllFlagsFile returns a path to the prebuilt all-flags.csv or nil if none is
 // specified.
-func (module *prebuiltBootclasspathFragmentModule) produceHiddenAPIAllFlagsFile(ctx android.ModuleContext, contents []hiddenAPIModule, _ HiddenAPIFlagInput) *HiddenAPIFlagOutput {
+func (module *prebuiltBootclasspathFragmentModule) produceHiddenAPIAllFlagsFile(ctx android.ModuleContext, contents []android.Module, _ HiddenAPIFlagInput) *HiddenAPIFlagOutput {
 	pathForOptionalSrc := func(src *string) android.Path {
 		if src == nil {
 			// TODO(b/179354495): Fail if this is not provided once prebuilts have been updated.
diff --git a/java/builder.go b/java/builder.go
index cde8731..ea011b8 100644
--- a/java/builder.go
+++ b/java/builder.go
@@ -279,23 +279,6 @@
 	transformJavaToClasses(ctx, outputFile, shardIdx, srcFiles, srcJars, flags, deps, "javac", desc)
 }
 
-func RunErrorProne(ctx android.ModuleContext, outputFile android.WritablePath,
-	srcFiles, srcJars android.Paths, flags javaBuilderFlags) {
-
-	flags.processorPath = append(flags.errorProneProcessorPath, flags.processorPath...)
-
-	if len(flags.errorProneExtraJavacFlags) > 0 {
-		if len(flags.javacFlags) > 0 {
-			flags.javacFlags += " " + flags.errorProneExtraJavacFlags
-		} else {
-			flags.javacFlags = flags.errorProneExtraJavacFlags
-		}
-	}
-
-	transformJavaToClasses(ctx, outputFile, -1, srcFiles, srcJars, flags, nil,
-		"errorprone", "errorprone")
-}
-
 // Emits the rule to generate Xref input file (.kzip file) for the given set of source files and source jars
 // to compile with given set of builder flags, etc.
 func emitXrefRule(ctx android.ModuleContext, xrefFile android.WritablePath, idx int,
diff --git a/java/hiddenapi_modular.go b/java/hiddenapi_modular.go
index 5600645..643c5cb 100644
--- a/java/hiddenapi_modular.go
+++ b/java/hiddenapi_modular.go
@@ -679,11 +679,11 @@
 // * metadata.csv
 // * index.csv
 // * all-flags.csv
-func hiddenAPIGenerateAllFlagsForBootclasspathFragment(ctx android.ModuleContext, contents []hiddenAPIModule, input HiddenAPIFlagInput) *HiddenAPIFlagOutput {
+func hiddenAPIGenerateAllFlagsForBootclasspathFragment(ctx android.ModuleContext, contents []android.Module, input HiddenAPIFlagInput) *HiddenAPIFlagOutput {
 	hiddenApiSubDir := "modular-hiddenapi"
 
 	// Gather the dex files for the boot libraries provided by this fragment.
-	bootDexJars := extractBootDexJarsFromHiddenAPIModules(ctx, contents)
+	bootDexJars := extractBootDexJarsFromModules(ctx, contents)
 
 	// Generate the stub-flags.csv.
 	stubFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "stub-flags.csv")
@@ -691,7 +691,7 @@
 	rule.Build("modularHiddenAPIStubFlagsFile", "modular hiddenapi stub flags")
 
 	// Extract the classes jars from the contents.
-	classesJars := extractClassJarsFromHiddenAPIModules(ctx, contents)
+	classesJars := extractClassesJarsFromModules(contents)
 
 	// Generate the set of flags from the annotations in the source code.
 	annotationFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "annotation-flags.csv")
@@ -746,26 +746,15 @@
 	return android.OptionalPathForPath(output)
 }
 
-// gatherHiddenAPIModuleFromContents gathers the hiddenAPIModule from the supplied contents.
-func gatherHiddenAPIModuleFromContents(ctx android.ModuleContext, contents []android.Module) []hiddenAPIModule {
-	hiddenAPIModules := []hiddenAPIModule{}
-	for _, module := range contents {
-		if hiddenAPI, ok := module.(hiddenAPIModule); ok {
-			hiddenAPIModules = append(hiddenAPIModules, hiddenAPI)
-		} else if _, ok := module.(*DexImport); ok {
-			// Ignore this for the purposes of hidden API processing
-		} else {
-			ctx.ModuleErrorf("module %s does not implement hiddenAPIModule", module)
-		}
-	}
-	return hiddenAPIModules
-}
-
-// extractBootDexJarsFromHiddenAPIModules extracts the boot dex jars from the supplied modules.
-func extractBootDexJarsFromHiddenAPIModules(ctx android.ModuleContext, contents []hiddenAPIModule) android.Paths {
+// extractBootDexJarsFromModules extracts the boot dex jars from the supplied modules.
+func extractBootDexJarsFromModules(ctx android.ModuleContext, contents []android.Module) android.Paths {
 	bootDexJars := android.Paths{}
 	for _, module := range contents {
-		bootDexJar := module.bootDexJar()
+		hiddenAPIModule := hiddenAPIModuleFromModule(ctx, module)
+		if hiddenAPIModule == nil {
+			continue
+		}
+		bootDexJar := hiddenAPIModule.bootDexJar()
 		if bootDexJar == nil {
 			if ctx.Config().AlwaysUsePrebuiltSdks() {
 				// TODO(b/179354495): Remove this workaround when it is unnecessary.
@@ -793,15 +782,36 @@
 	return bootDexJars
 }
 
-// extractClassJarsFromHiddenAPIModules extracts the class jars from the supplied modules.
-func extractClassJarsFromHiddenAPIModules(ctx android.ModuleContext, contents []hiddenAPIModule) android.Paths {
+func hiddenAPIModuleFromModule(ctx android.BaseModuleContext, module android.Module) hiddenAPIModule {
+	if hiddenAPIModule, ok := module.(hiddenAPIModule); ok {
+		return hiddenAPIModule
+	} else if _, ok := module.(*DexImport); ok {
+		// Ignore this for the purposes of hidden API processing
+	} else {
+		ctx.ModuleErrorf("module %s does not implement hiddenAPIModule", module)
+	}
+
+	return nil
+}
+
+// extractClassesJarsFromModules extracts the class jars from the supplied modules.
+func extractClassesJarsFromModules(contents []android.Module) android.Paths {
 	classesJars := android.Paths{}
 	for _, module := range contents {
-		classesJars = append(classesJars, module.classesJars()...)
+		classesJars = append(classesJars, retrieveClassesJarsFromModule(module)...)
 	}
 	return classesJars
 }
 
+// retrieveClassesJarsFromModule retrieves the classes jars from the supplied module.
+func retrieveClassesJarsFromModule(module android.Module) android.Paths {
+	if hiddenAPIModule, ok := module.(hiddenAPIModule); ok {
+		return hiddenAPIModule.classesJars()
+	}
+
+	return nil
+}
+
 // deferReportingMissingBootDexJar returns true if a missing boot dex jar should not be reported by
 // Soong but should instead only be reported in ninja if the file is actually built.
 func deferReportingMissingBootDexJar(ctx android.ModuleContext, module android.Module) bool {
diff --git a/java/java_test.go b/java/java_test.go
index bd373c1..78d9ab4 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -1392,3 +1392,31 @@
 	assertDeepEquals(t, "Default installable value should be true.", proptools.BoolPtr(true),
 		module.properties.Installable)
 }
+
+func TestErrorproneEnabled(t *testing.T) {
+	ctx, _ := testJava(t, `
+		java_library {
+			name: "foo",
+			srcs: ["a.java"],
+			errorprone: {
+				enabled: true,
+			},
+		}
+	`)
+
+	javac := ctx.ModuleForTests("foo", "android_common").Description("javac")
+
+	// Test that the errorprone plugins are passed to javac
+	expectedSubstring := "-Xplugin:ErrorProne"
+	if !strings.Contains(javac.Args["javacFlags"], expectedSubstring) {
+		t.Errorf("expected javacFlags to conain %q, got %q", expectedSubstring, javac.Args["javacFlags"])
+	}
+
+	// Modules with errorprone { enabled: true } will include errorprone checks
+	// in the main javac build rule. Only when RUN_ERROR_PRONE is true will
+	// the explicit errorprone build rule be created.
+	errorprone := ctx.ModuleForTests("foo", "android_common").MaybeDescription("errorprone")
+	if errorprone.RuleParams.Description != "" {
+		t.Errorf("expected errorprone build rule to not exist, but it did")
+	}
+}
diff --git a/java/kotlin_test.go b/java/kotlin_test.go
index 1c146a1..fd2f3ca 100644
--- a/java/kotlin_test.go
+++ b/java/kotlin_test.go
@@ -185,7 +185,6 @@
 		buildOS := android.BuildOs.String()
 
 		kapt := result.ModuleForTests("foo", "android_common").Rule("kapt")
-		//kotlinc := ctx.ModuleForTests("foo", "android_common").Rule("kotlinc")
 		javac := result.ModuleForTests("foo", "android_common").Description("javac")
 		errorprone := result.ModuleForTests("foo", "android_common").Description("errorprone")
 
diff --git a/java/platform_bootclasspath.go b/java/platform_bootclasspath.go
index a4beb89..fba73d0 100644
--- a/java/platform_bootclasspath.go
+++ b/java/platform_bootclasspath.go
@@ -290,16 +290,14 @@
 	// Use the flag files from this module and all the fragments.
 	input.FlagFilesByCategory = monolithicInfo.FlagsFilesByCategory
 
-	hiddenAPIModules := gatherHiddenAPIModuleFromContents(ctx, modules)
-
 	// Generate the monolithic stub-flags.csv file.
-	bootDexJars := extractBootDexJarsFromHiddenAPIModules(ctx, hiddenAPIModules)
+	bootDexJars := extractBootDexJarsFromModules(ctx, modules)
 	stubFlags := hiddenAPISingletonPaths(ctx).stubFlags
 	rule := ruleToGenerateHiddenAPIStubFlagsFile(ctx, stubFlags, bootDexJars, input)
 	rule.Build("platform-bootclasspath-monolithic-hiddenapi-stub-flags", "monolithic hidden API stub flags")
 
 	// Extract the classes jars from the contents.
-	classesJars := extractClassJarsFromHiddenAPIModules(ctx, hiddenAPIModules)
+	classesJars := extractClassesJarsFromModules(modules)
 
 	// Generate the annotation-flags.csv file from all the module annotations.
 	annotationFlags := android.PathForModuleOut(ctx, "hiddenapi-monolithic", "annotation-flags.csv")