Introduce product variables to select Java code coverage paths in Soong.

Introduce product variables `JavaCoveragePaths` and
`JavaCoverageExcludePaths` (resp. populated from environment variables
`JAVA_COVERAGE_PATHS` and `JAVA_COVERAGE_EXCLUDE_PATHS`). Use them to
control which Java modules are candidate for instrumentation based on
their source path. By default (when `JavaCoveragePaths` is empty),
have all Java module be candidate for instrumentation, to preserve the
existing behavior.

Test: export EMMA_INSTRUMENT=true \
        && export EMMA_INSTRUMENT_FRAMEWORK=true \
        && export JAVA_COVERAGE_PATHS=art \
        && m
Bug: 158212027
Bug: 156284897
Change-Id: Ibe9c1f41ed6110867411952689c5a7ad6536f277
diff --git a/android/config.go b/android/config.go
index e1d597a..a53f44a 100644
--- a/android/config.go
+++ b/android/config.go
@@ -1029,6 +1029,27 @@
 	return Bool(c.config.productVariables.SamplingPGO)
 }
 
+// JavaCoverageEnabledForPath returns whether Java code coverage is enabled for
+// path. Coverage is enabled by default when the product variable
+// JavaCoveragePaths is empty. If JavaCoveragePaths is not empty, coverage is
+// enabled for any path which is part of this variable (and not part of the
+// JavaCoverageExcludePaths product variable). Value "*" in JavaCoveragePaths
+// represents any path.
+func (c *deviceConfig) JavaCoverageEnabledForPath(path string) bool {
+	coverage := false
+	if c.config.productVariables.JavaCoveragePaths == nil ||
+		InList("*", c.config.productVariables.JavaCoveragePaths) ||
+		HasAnyPrefix(path, c.config.productVariables.JavaCoveragePaths) {
+		coverage = true
+	}
+	if coverage && c.config.productVariables.JavaCoverageExcludePaths != nil {
+		if HasAnyPrefix(path, c.config.productVariables.JavaCoverageExcludePaths) {
+			coverage = false
+		}
+	}
+	return coverage
+}
+
 func (c *config) NativeLineCoverage() bool {
 	return Bool(c.productVariables.NativeLineCoverage)
 }
diff --git a/android/variable.go b/android/variable.go
index 4440cee..863fe5a 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -266,6 +266,9 @@
 
 	SamplingPGO *bool `json:",omitempty"`
 
+	JavaCoveragePaths        []string `json:",omitempty"`
+	JavaCoverageExcludePaths []string `json:",omitempty"`
+
 	NativeLineCoverage         *bool    `json:",omitempty"`
 	Native_coverage            *bool    `json:",omitempty"`
 	ClangCoverage              *bool    `json:",omitempty"`
diff --git a/java/java.go b/java/java.go
index 1cdfbf1..8b5aeaa 100644
--- a/java/java.go
+++ b/java/java.go
@@ -601,7 +601,9 @@
 }
 
 func (j *Module) shouldInstrument(ctx android.BaseModuleContext) bool {
-	return j.properties.Instrument && ctx.Config().IsEnvTrue("EMMA_INSTRUMENT")
+	return j.properties.Instrument &&
+		ctx.Config().IsEnvTrue("EMMA_INSTRUMENT") &&
+		ctx.DeviceConfig().JavaCoverageEnabledForPath(ctx.ModuleDir())
 }
 
 func (j *Module) shouldInstrumentStatic(ctx android.BaseModuleContext) bool {