Merge "Disable all-assigned check in hiddenapi on master-art"
diff --git a/Android.bp b/Android.bp
index 2c400cf..03071d1 100644
--- a/Android.bp
+++ b/Android.bp
@@ -249,6 +249,7 @@
         "java/jdeps.go",
         "java/java_resources.go",
         "java/kotlin.go",
+        "java/plugin.go",
         "java/prebuilt_apis.go",
         "java/proto.go",
         "java/sdk.go",
@@ -262,6 +263,7 @@
         "java/java_test.go",
         "java/jdeps_test.go",
         "java/kotlin_test.go",
+        "java/plugin_test.go",
         "java/sdk_test.go",
     ],
     pluginFor: ["soong_build"],
diff --git a/java/builder.go b/java/builder.go
index 40f72e1..67e8235 100644
--- a/java/builder.go
+++ b/java/builder.go
@@ -44,7 +44,7 @@
 				`${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" $srcJars && ` +
 				`(if [ -s $srcJarDir/list ] || [ -s $out.rsp ] ; then ` +
 				`${config.SoongJavacWrapper} ${config.JavacWrapper}${config.JavacCmd} ${config.JavacHeapFlags} ${config.CommonJdkFlags} ` +
-				`$processorpath $javacFlags $bootClasspath $classpath ` +
+				`$processorpath $processor $javacFlags $bootClasspath $classpath ` +
 				`-source $javaVersion -target $javaVersion ` +
 				`-d $outDir -s $annoDir @$out.rsp @$srcJarDir/list ; fi ) && ` +
 				`${config.SoongZipCmd} -jar -o $out -C $outDir -D $outDir`,
@@ -57,7 +57,7 @@
 			Rspfile:          "$out.rsp",
 			RspfileContent:   "$in",
 		},
-		"javacFlags", "bootClasspath", "classpath", "processorpath", "srcJars", "srcJarDir",
+		"javacFlags", "bootClasspath", "classpath", "processorpath", "processor", "srcJars", "srcJarDir",
 		"outDir", "annoDir", "javaVersion")
 
 	turbine = pctx.AndroidStaticRule("turbine",
@@ -141,6 +141,7 @@
 	bootClasspath classpath
 	classpath     classpath
 	processorPath classpath
+	processor     string
 	systemModules classpath
 	aidlFlags     string
 	javaVersion   string
@@ -254,6 +255,12 @@
 	deps = append(deps, flags.classpath...)
 	deps = append(deps, flags.processorPath...)
 
+	// TODO(b/77284273): pass -processor:none if no plugins are listed
+	processor := ""
+	if flags.processor != "" {
+		processor = "-processor " + flags.processor
+	}
+
 	srcJarDir := "srcjars"
 	outDir := "classes"
 	annoDir := "anno"
@@ -274,6 +281,7 @@
 			"bootClasspath": bootClasspath,
 			"classpath":     flags.classpath.FormJavaClassPath("-classpath"),
 			"processorpath": flags.processorPath.FormJavaClassPath("-processorpath"),
+			"processor":     processor,
 			"srcJars":       strings.Join(srcJars.Strings(), " "),
 			"srcJarDir":     android.PathForModuleOut(ctx, intermediatesDir, srcJarDir).String(),
 			"outDir":        android.PathForModuleOut(ctx, intermediatesDir, outDir).String(),
diff --git a/java/java.go b/java/java.go
index 1e5c628..a76cde5 100644
--- a/java/java.go
+++ b/java/java.go
@@ -114,11 +114,11 @@
 	// If set to true, include sources used to compile the module in to the final jar
 	Include_srcs *bool
 
-	// List of modules to use as annotation processors
+	// List of modules to use as annotation processors.  Deprecated, use plugins instead.
 	Annotation_processors []string
 
-	// List of classes to pass to javac to use as annotation processors
-	Annotation_processor_classes []string
+	// List of modules to use as annotation processors
+	Plugins []string
 
 	// The number of Java source entries each Javac instance can process
 	Javac_shard_size *int64
@@ -313,6 +313,9 @@
 	// filter out Exclude_srcs, will be used by android.IDEInfo struct
 	expandIDEInfoCompiledSrcs []string
 
+	// expanded Jarjar_rules
+	expandJarjarRules android.Path
+
 	dexpreopter
 }
 
@@ -374,6 +377,7 @@
 	staticLibTag          = dependencyTag{name: "staticlib"}
 	libTag                = dependencyTag{name: "javalib"}
 	annoTag               = dependencyTag{name: "annotation processor"}
+	pluginTag             = dependencyTag{name: "plugin"}
 	bootClasspathTag      = dependencyTag{name: "bootclasspath"}
 	systemModulesTag      = dependencyTag{name: "system modules"}
 	frameworkResTag       = dependencyTag{name: "framework-res"}
@@ -471,10 +475,15 @@
 		{Mutator: "arch", Variation: ctx.Config().BuildOsCommonVariant},
 	}, annoTag, j.properties.Annotation_processors...)
 
+	ctx.AddFarVariationDependencies([]blueprint.Variation{
+		{Mutator: "arch", Variation: ctx.Config().BuildOsCommonVariant},
+	}, pluginTag, j.properties.Plugins...)
+
 	android.ExtractSourcesDeps(ctx, j.properties.Srcs)
 	android.ExtractSourcesDeps(ctx, j.properties.Exclude_srcs)
 	android.ExtractSourcesDeps(ctx, j.properties.Java_resources)
 	android.ExtractSourceDeps(ctx, j.properties.Manifest)
+	android.ExtractSourceDeps(ctx, j.properties.Jarjar_rules)
 
 	if j.hasSrcExt(".proto") {
 		protoDeps(ctx, &j.protoProperties)
@@ -484,7 +493,7 @@
 		// TODO(ccross): move this to a mutator pass that can tell if generated sources contain
 		// Kotlin files
 		ctx.AddVariationDependencies(nil, kotlinStdlibTag, "kotlin-stdlib")
-		if len(j.properties.Annotation_processors) > 0 {
+		if len(j.properties.Annotation_processors) > 0 || len(j.properties.Plugins) > 0 {
 			ctx.AddVariationDependencies(nil, kotlinAnnotationsTag, "kotlin-annotations")
 		}
 	}
@@ -559,6 +568,7 @@
 	classpath          classpath
 	bootClasspath      classpath
 	processorPath      classpath
+	processorClasses   []string
 	staticJars         android.Paths
 	staticHeaderJars   android.Paths
 	staticResourceJars android.Paths
@@ -569,6 +579,8 @@
 	aidlPreprocess     android.OptionalPath
 	kotlinStdlib       android.Paths
 	kotlinAnnotations  android.Paths
+
+	disableTurbine bool
 }
 
 func checkProducesJars(ctx android.ModuleContext, dep android.SourceFileProducer) {
@@ -708,6 +720,16 @@
 				j.exportedSdkLibs = append(j.exportedSdkLibs, dep.ExportedSdkLibs()...)
 			case annoTag:
 				deps.processorPath = append(deps.processorPath, dep.ImplementationAndResourcesJars()...)
+			case pluginTag:
+				if plugin, ok := dep.(*Plugin); ok {
+					deps.processorPath = append(deps.processorPath, dep.ImplementationAndResourcesJars()...)
+					if plugin.pluginProperties.Processor_class != nil {
+						deps.processorClasses = append(deps.processorClasses, *plugin.pluginProperties.Processor_class)
+					}
+					deps.disableTurbine = deps.disableTurbine || Bool(plugin.pluginProperties.Generates_api)
+				} else {
+					ctx.PropertyErrorf("plugins", "%q is not a java_plugin module", otherName)
+				}
 			case frameworkResTag:
 				if (ctx.ModuleName() == "framework") || (ctx.ModuleName() == "framework-annotation-proc") {
 					// framework.jar has a one-off dependency on the R.java and Manifest.java files
@@ -855,6 +877,8 @@
 	flags.classpath = append(flags.classpath, deps.classpath...)
 	flags.processorPath = append(flags.processorPath, deps.processorPath...)
 
+	flags.processor = strings.Join(deps.processorClasses, ",")
+
 	if len(flags.bootClasspath) == 0 && ctx.Host() && flags.javaVersion != "1.9" &&
 		!Bool(j.properties.No_standard_libs) &&
 		inList(flags.javaVersion, []string{"1.6", "1.7", "1.8"}) {
@@ -940,6 +964,10 @@
 	// that IDEInfo struct will use
 	j.expandIDEInfoCompiledSrcs = append(j.expandIDEInfoCompiledSrcs, srcFiles.Strings()...)
 
+	if j.properties.Jarjar_rules != nil {
+		j.expandJarjarRules = ctx.ExpandSource(*j.properties.Jarjar_rules, "jarjar_rules")
+	}
+
 	jarName := ctx.ModuleName() + ".jar"
 
 	javaSrcFiles := srcFiles.FilterByExt(".java")
@@ -989,6 +1017,7 @@
 			srcJars = append(srcJars, kaptSrcJar)
 			// Disable annotation processing in javac, it's already been handled by kapt
 			flags.processorPath = nil
+			flags.processor = ""
 		}
 
 		kotlinJar := android.PathForModuleOut(ctx, "kotlin", jarName)
@@ -1012,7 +1041,7 @@
 	j.compiledSrcJars = srcJars
 
 	enable_sharding := false
-	if ctx.Device() && !ctx.Config().IsEnvFalse("TURBINE_ENABLED") {
+	if ctx.Device() && !ctx.Config().IsEnvFalse("TURBINE_ENABLED") && !deps.disableTurbine {
 		if j.properties.Javac_shard_size != nil && *(j.properties.Javac_shard_size) > 0 {
 			enable_sharding = true
 			// Formerly, there was a check here that prevented annotation processors
@@ -1143,17 +1172,16 @@
 	}
 
 	// jarjar implementation jar if necessary
-	if j.properties.Jarjar_rules != nil {
-		jarjar_rules := android.PathForModuleSrc(ctx, *j.properties.Jarjar_rules)
+	if j.expandJarjarRules != nil {
 		// Transform classes.jar into classes-jarjar.jar
 		jarjarFile := android.PathForModuleOut(ctx, "jarjar", jarName)
-		TransformJarJar(ctx, jarjarFile, outputFile, jarjar_rules)
+		TransformJarJar(ctx, jarjarFile, outputFile, j.expandJarjarRules)
 		outputFile = jarjarFile
 
 		// jarjar resource jar if necessary
 		if j.resourceJar != nil {
 			resourceJarJarFile := android.PathForModuleOut(ctx, "res-jarjar", jarName)
-			TransformJarJar(ctx, resourceJarJarFile, j.resourceJar, jarjar_rules)
+			TransformJarJar(ctx, resourceJarJarFile, j.resourceJar, j.expandJarjarRules)
 			j.resourceJar = resourceJarJarFile
 		}
 
@@ -1216,7 +1244,13 @@
 			combinedJar := android.PathForModuleOut(ctx, "dex-withres", jarName)
 			TransformJarsToJar(ctx, combinedJar, "for dex resources", jars, android.OptionalPath{},
 				false, nil, nil)
-			dexOutputFile = combinedJar
+			if j.deviceProperties.UncompressDex {
+				combinedAlignedJar := android.PathForModuleOut(ctx, "dex-withres-aligned", jarName)
+				TransformZipAlign(ctx, combinedAlignedJar, combinedJar)
+				dexOutputFile = combinedAlignedJar
+			} else {
+				dexOutputFile = combinedJar
+			}
 		}
 
 		j.dexJarFile = dexOutputFile
@@ -1296,11 +1330,10 @@
 		false, nil, []string{"META-INF"})
 	headerJar = combinedJar
 
-	if j.properties.Jarjar_rules != nil {
-		jarjar_rules := android.PathForModuleSrc(ctx, *j.properties.Jarjar_rules)
+	if j.expandJarjarRules != nil {
 		// Transform classes.jar into classes-jarjar.jar
 		jarjarFile := android.PathForModuleOut(ctx, "turbine-jarjar", jarName)
-		TransformJarJar(ctx, jarjarFile, headerJar, jarjar_rules)
+		TransformJarJar(ctx, jarjarFile, headerJar, j.expandJarjarRules)
 		headerJar = jarjarFile
 		if ctx.Failed() {
 			return nil
@@ -1376,8 +1409,8 @@
 	dpInfo.Deps = append(dpInfo.Deps, j.CompilerDeps()...)
 	dpInfo.Srcs = append(dpInfo.Srcs, j.expandIDEInfoCompiledSrcs...)
 	dpInfo.Aidl_include_dirs = append(dpInfo.Aidl_include_dirs, j.deviceProperties.Aidl.Include_dirs...)
-	if j.properties.Jarjar_rules != nil {
-		dpInfo.Jarjar_rules = append(dpInfo.Jarjar_rules, *j.properties.Jarjar_rules)
+	if j.expandJarjarRules != nil {
+		dpInfo.Jarjar_rules = append(dpInfo.Jarjar_rules, j.expandJarjarRules.String())
 	}
 }
 
diff --git a/java/java_test.go b/java/java_test.go
index 9f805bb..a0d962e 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -83,6 +83,7 @@
 	ctx.RegisterModuleType("java_defaults", android.ModuleFactoryAdaptor(defaultsFactory))
 	ctx.RegisterModuleType("java_system_modules", android.ModuleFactoryAdaptor(SystemModulesFactory))
 	ctx.RegisterModuleType("java_genrule", android.ModuleFactoryAdaptor(genRuleFactory))
+	ctx.RegisterModuleType("java_plugin", android.ModuleFactoryAdaptor(PluginFactory))
 	ctx.RegisterModuleType("filegroup", android.ModuleFactoryAdaptor(android.FileGroupFactory))
 	ctx.RegisterModuleType("genrule", android.ModuleFactoryAdaptor(genrule.GenRuleFactory))
 	ctx.RegisterModuleType("droiddoc", android.ModuleFactoryAdaptor(DroiddocFactory))
diff --git a/java/jdeps_test.go b/java/jdeps_test.go
index ca8a3cd..874d1d7 100644
--- a/java/jdeps_test.go
+++ b/java/jdeps_test.go
@@ -76,7 +76,7 @@
 func TestCollectJavaLibraryPropertiesAddJarjarRules(t *testing.T) {
 	expected := "Jarjar_rules.txt"
 	module := LibraryFactory().(*Library)
-	module.properties.Jarjar_rules = &expected
+	module.expandJarjarRules = android.PathForTesting(expected)
 	dpInfo := &android.IdeInfo{}
 
 	module.IDEInfo(dpInfo)
diff --git a/java/kotlin.go b/java/kotlin.go
index c72f2de..9c47f98 100644
--- a/java/kotlin.go
+++ b/java/kotlin.go
@@ -87,6 +87,7 @@
 			`-P plugin:org.jetbrains.kotlin.kapt3:aptMode=stubsAndApt ` +
 			`-P plugin:org.jetbrains.kotlin.kapt3:javacArguments=$encodedJavacFlags ` +
 			`$kaptProcessorPath ` +
+			`$kaptProcessor ` +
 			`-Xbuild-file=$kotlinBuildFile && ` +
 			`${config.SoongZipCmd} -jar -o $out -C $kaptDir/sources -D $kaptDir/sources`,
 		CommandDeps: []string{
@@ -100,7 +101,8 @@
 		Rspfile:        "$out.rsp",
 		RspfileContent: `$in`,
 	},
-	"kotlincFlags", "encodedJavacFlags", "kaptProcessorPath", "classpath", "srcJars", "srcJarDir", "kaptDir", "kotlinJvmTarget", "kotlinBuildFile")
+	"kotlincFlags", "encodedJavacFlags", "kaptProcessorPath", "kaptProcessor",
+	"classpath", "srcJars", "srcJarDir", "kaptDir", "kotlinJvmTarget", "kotlinBuildFile")
 
 // kotlinKapt performs Kotlin-compatible annotation processing.  It takes .kt and .java sources and srcjars, and runs
 // annotation processors over all of them, producing a srcjar of generated code in outputFile.  The srcjar should be
@@ -117,6 +119,11 @@
 
 	kaptProcessorPath := flags.processorPath.FormTurbineClasspath("-P plugin:org.jetbrains.kotlin.kapt3:apclasspath=")
 
+	kaptProcessor := ""
+	if flags.processor != "" {
+		kaptProcessor = "-P plugin:org.jetbrains.kotlin.kapt3:processors=" + flags.processor
+	}
+
 	encodedJavacFlags := kaptEncodeFlags([][2]string{
 		{"-source", flags.javaVersion},
 		{"-target", flags.javaVersion},
@@ -135,6 +142,7 @@
 			"srcJarDir":         android.PathForModuleOut(ctx, "kapt", "srcJars").String(),
 			"kotlinBuildFile":   android.PathForModuleOut(ctx, "kapt", "build.xml").String(),
 			"kaptProcessorPath": strings.Join(kaptProcessorPath, " "),
+			"kaptProcessor":     kaptProcessor,
 			"kaptDir":           android.PathForModuleOut(ctx, "kapt/gen").String(),
 			"encodedJavacFlags": encodedJavacFlags,
 		},
diff --git a/java/kotlin_test.go b/java/kotlin_test.go
index 1069f42..9406ef9 100644
--- a/java/kotlin_test.go
+++ b/java/kotlin_test.go
@@ -15,6 +15,7 @@
 package java
 
 import (
+	"android/soong/android"
 	"strconv"
 	"strings"
 	"testing"
@@ -87,18 +88,24 @@
 		java_library {
 			name: "foo",
 			srcs: ["a.java", "b.kt"],
-			annotation_processors: ["bar"],
+			plugins: ["bar"],
 		}
 
-		java_library_host {
+		java_plugin {
 			name: "bar",
+			processor_class: "com.bar",
+			srcs: ["b.java"],
 		}
 		`)
 
+	buildOS := android.BuildOs.String()
+
 	kapt := ctx.ModuleForTests("foo", "android_common").Rule("kapt")
 	kotlinc := ctx.ModuleForTests("foo", "android_common").Rule("kotlinc")
 	javac := ctx.ModuleForTests("foo", "android_common").Rule("javac")
 
+	bar := ctx.ModuleForTests("bar", buildOS+"_common").Rule("javac").Output.String()
+
 	// Test that the kotlin and java sources are passed to kapt and kotlinc
 	if len(kapt.Inputs) != 2 || kapt.Inputs[0].String() != "a.java" || kapt.Inputs[1].String() != "b.kt" {
 		t.Errorf(`foo kapt inputs %v != ["a.java", "b.kt"]`, kapt.Inputs)
@@ -127,6 +134,25 @@
 	if javac.Args["srcJars"] != kapt.Output.String() {
 		t.Errorf("expected %q in javac srcjars %v", kapt.Output.String(), kotlinc.Args["srcJars"])
 	}
+
+	// Test that the processors are passed to kapt
+	expectedProcessorPath := "-P plugin:org.jetbrains.kotlin.kapt3:apclasspath=" + bar
+	if kapt.Args["kaptProcessorPath"] != expectedProcessorPath {
+		t.Errorf("expected kaptProcessorPath %q, got %q", expectedProcessorPath, kapt.Args["kaptProcessorPath"])
+	}
+	expectedProcessor := "-P plugin:org.jetbrains.kotlin.kapt3:processors=com.bar"
+	if kapt.Args["kaptProcessor"] != expectedProcessor {
+		t.Errorf("expected kaptProcessor %q, got %q", expectedProcessor, kapt.Args["kaptProcessor"])
+	}
+
+	// Test that the processors are not passed to javac
+	if javac.Args["processorPath"] != "" {
+		t.Errorf("expected processorPath '', got %q", javac.Args["processorPath"])
+	}
+	// TODO(b/77284273): test for -processor:none
+	if javac.Args["processor"] != "" {
+		t.Errorf("expected processor '', got %q", javac.Args["processor"])
+	}
 }
 
 func TestKaptEncodeFlags(t *testing.T) {
diff --git a/java/plugin.go b/java/plugin.go
new file mode 100644
index 0000000..a5e8292
--- /dev/null
+++ b/java/plugin.go
@@ -0,0 +1,50 @@
+// Copyright 2019 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package java
+
+import "android/soong/android"
+
+func init() {
+	android.RegisterModuleType("java_plugin", PluginFactory)
+}
+
+// A java_plugin module describes a host java library that will be used by javac as an annotation processor.
+func PluginFactory() android.Module {
+	module := &Plugin{}
+
+	module.AddProperties(
+		&module.Module.properties,
+		&module.Module.protoProperties,
+		&module.pluginProperties)
+
+	InitJavaModule(module, android.HostSupported)
+	return module
+}
+
+type Plugin struct {
+	Library
+
+	pluginProperties PluginProperties
+}
+
+type PluginProperties struct {
+	// The optional name of the class that javac will use to run the annotation processor.
+	Processor_class *string
+
+	// If true, assume the annotation processor will generate classes that are referenced from outside the module.
+	// This necessitates disabling the turbine optimization on modules that use this plugin, which will reduce
+	// parallelism and cause more recompilation for modules that depend on modules that use this plugin.
+	Generates_api *bool
+}
diff --git a/java/plugin_test.go b/java/plugin_test.go
new file mode 100644
index 0000000..7aa0164
--- /dev/null
+++ b/java/plugin_test.go
@@ -0,0 +1,124 @@
+// Copyright 2019 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package java
+
+import (
+	"android/soong/android"
+	"testing"
+)
+
+func TestNoPlugin(t *testing.T) {
+	ctx := testJava(t, `
+		java_library {
+			name: "foo",
+			srcs: ["a.java"],
+		}
+	`)
+
+	javac := ctx.ModuleForTests("foo", "android_common").Rule("javac")
+	turbine := ctx.ModuleForTests("foo", "android_common").MaybeRule("turbine")
+
+	if turbine.Rule == nil {
+		t.Errorf("expected turbine to be enabled")
+	}
+
+	if javac.Args["processsorpath"] != "" {
+		t.Errorf("want empty processorpath, got %q", javac.Args["processorpath"])
+	}
+
+	// TODO(b/77284273): test for -processor:none if no plugins are enabled
+	if javac.Args["processor"] != "" {
+		t.Errorf("want no -processor argument, got %q", javac.Args["processor"])
+	}
+}
+
+func TestPlugin(t *testing.T) {
+	ctx := testJava(t, `
+		java_library {
+			name: "foo",
+			srcs: ["a.java"],
+			plugins: ["bar"],
+		}
+
+		java_plugin {
+			name: "bar",
+			processor_class: "com.bar",
+			srcs: ["b.java"],
+		}
+	`)
+
+	buildOS := android.BuildOs.String()
+
+	javac := ctx.ModuleForTests("foo", "android_common").Rule("javac")
+	turbine := ctx.ModuleForTests("foo", "android_common").MaybeRule("turbine")
+
+	if turbine.Rule == nil {
+		t.Errorf("expected turbine to be enabled")
+	}
+
+	bar := ctx.ModuleForTests("bar", buildOS+"_common").Rule("javac").Output.String()
+
+	if !inList(bar, javac.Implicits.Strings()) {
+		t.Errorf("foo implicits %v does not contain %q", javac.Implicits.Strings(), bar)
+	}
+
+	if javac.Args["processorpath"] != "-processorpath "+bar {
+		t.Errorf("foo processorpath %q != '-processorpath %s'", javac.Args["processorpath"], bar)
+	}
+
+	if javac.Args["processor"] != "-processor com.bar" {
+		t.Errorf("foo processor %q != '-processor com.bar'", javac.Args["processor"])
+	}
+}
+
+func TestPluginGeneratesApi(t *testing.T) {
+	ctx := testJava(t, `
+		java_library {
+			name: "foo",
+			srcs: ["a.java"],
+			plugins: ["bar"],
+		}
+
+		java_plugin {
+			name: "bar",
+			processor_class: "com.bar",
+			generates_api: true,
+			srcs: ["b.java"],
+		}
+	`)
+
+	buildOS := android.BuildOs.String()
+
+	javac := ctx.ModuleForTests("foo", "android_common").Rule("javac")
+	turbine := ctx.ModuleForTests("foo", "android_common").MaybeRule("turbine")
+
+	if turbine.Rule != nil {
+		t.Errorf("expected turbine to be disabled")
+	}
+
+	bar := ctx.ModuleForTests("bar", buildOS+"_common").Rule("javac").Output.String()
+
+	if !inList(bar, javac.Implicits.Strings()) {
+		t.Errorf("foo implicits %v does not contain %q", javac.Implicits.Strings(), bar)
+	}
+
+	if javac.Args["processorpath"] != "-processorpath "+bar {
+		t.Errorf("foo processorpath %q != '-processorpath %s'", javac.Args["processorpath"], bar)
+	}
+
+	if javac.Args["processor"] != "-processor com.bar" {
+		t.Errorf("foo processor %q != '-processor com.bar'", javac.Args["processor"])
+	}
+}