Merge "Allow variable-prefixed include statements in mk2rbc"
diff --git a/android/license_metadata.go b/android/license_metadata.go
index 3bc53d6..6a5b0da 100644
--- a/android/license_metadata.go
+++ b/android/license_metadata.go
@@ -34,7 +34,7 @@
 	}, "args")
 )
 
-func buildLicenseMetadata(ctx ModuleContext) {
+func buildLicenseMetadata(ctx ModuleContext, licenseMetadataFile WritablePath) {
 	base := ctx.Module().base()
 
 	if !base.Enabled() {
@@ -45,9 +45,18 @@
 		return
 	}
 
+	var outputFiles Paths
+	if outputFileProducer, ok := ctx.Module().(OutputFileProducer); ok {
+		outputFiles, _ = outputFileProducer.OutputFiles("")
+		outputFiles = PathsIfNonNil(outputFiles...)
+	}
+
+	isContainer := isContainerFromFileExtensions(base.installFiles, outputFiles)
+
 	var allDepMetadataFiles Paths
 	var allDepMetadataArgs []string
 	var allDepOutputFiles Paths
+	var allDepMetadataDepSets []*PathsDepSet
 
 	ctx.VisitDirectDepsBlueprint(func(bpdep blueprint.Module) {
 		dep, _ := bpdep.(Module)
@@ -61,6 +70,9 @@
 		if ctx.OtherModuleHasProvider(dep, LicenseMetadataProvider) {
 			info := ctx.OtherModuleProvider(dep, LicenseMetadataProvider).(*LicenseMetadataInfo)
 			allDepMetadataFiles = append(allDepMetadataFiles, info.LicenseMetadataPath)
+			if isContainer || IsInstallDepNeeded(ctx.OtherModuleDependencyTag(dep)) {
+				allDepMetadataDepSets = append(allDepMetadataDepSets, info.LicenseMetadataDepSet)
+			}
 
 			depAnnotations := licenseAnnotationsFromTag(ctx.OtherModuleDependencyTag(dep))
 
@@ -105,9 +117,16 @@
 	args = append(args,
 		JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(base.commonProperties.Effective_license_text.Strings()), "-n "))
 
-	args = append(args,
-		JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(allDepMetadataArgs), "-d "))
-	orderOnlyDeps = append(orderOnlyDeps, allDepMetadataFiles...)
+	if isContainer {
+		transitiveDeps := newPathsDepSet(nil, allDepMetadataDepSets).ToList()
+		args = append(args,
+			JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(transitiveDeps.Strings()), "-d "))
+		orderOnlyDeps = append(orderOnlyDeps, transitiveDeps...)
+	} else {
+		args = append(args,
+			JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(allDepMetadataArgs), "-d "))
+		orderOnlyDeps = append(orderOnlyDeps, allDepMetadataFiles...)
+	}
 
 	args = append(args,
 		JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(allDepOutputFiles.Strings()), "-s "))
@@ -117,12 +136,6 @@
 		JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(base.licenseInstallMap), "-m "))
 
 	// Built files
-	var outputFiles Paths
-	if outputFileProducer, ok := ctx.Module().(OutputFileProducer); ok {
-		outputFiles, _ = outputFileProducer.OutputFiles("")
-		outputFiles = PathsIfNonNil(outputFiles...)
-	}
-
 	if len(outputFiles) > 0 {
 		args = append(args,
 			JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(outputFiles.Strings()), "-t "))
@@ -134,13 +147,10 @@
 	args = append(args,
 		JoinWithPrefix(proptools.NinjaAndShellEscapeListIncludingSpaces(base.installFiles.Strings()), "-i "))
 
-	isContainer := isContainerFromFileExtensions(base.installFiles, outputFiles)
 	if isContainer {
 		args = append(args, "--is_container")
 	}
 
-	licenseMetadataFile := PathForModuleOut(ctx, "meta_lic")
-
 	ctx.Build(pctx, BuildParams{
 		Rule:        licenseMetadataRule,
 		Output:      licenseMetadataFile,
@@ -152,7 +162,8 @@
 	})
 
 	ctx.SetProvider(LicenseMetadataProvider, &LicenseMetadataInfo{
-		LicenseMetadataPath: licenseMetadataFile,
+		LicenseMetadataPath:   licenseMetadataFile,
+		LicenseMetadataDepSet: newPathsDepSet(Paths{licenseMetadataFile}, allDepMetadataDepSets),
 	})
 }
 
@@ -179,7 +190,8 @@
 
 // LicenseMetadataInfo stores the license metadata path for a module.
 type LicenseMetadataInfo struct {
-	LicenseMetadataPath Path
+	LicenseMetadataPath   Path
+	LicenseMetadataDepSet *PathsDepSet
 }
 
 // licenseAnnotationsFromTag returns the LicenseAnnotations for a tag (if any) converted into
@@ -212,6 +224,9 @@
 	// LicenseAnnotationSharedDependency should be returned by LicenseAnnotations implementations
 	// of dependency tags when the usage of the dependency is dynamic, for example a shared library
 	// linkage for native modules or as a classpath library for java modules.
+	//
+	// Dependency tags that need to always return LicenseAnnotationSharedDependency
+	// can embed LicenseAnnotationSharedDependencyTag to implement LicenseAnnotations.
 	LicenseAnnotationSharedDependency LicenseAnnotation = "dynamic"
 
 	// LicenseAnnotationToolchain should be returned by LicenseAnnotations implementations of
@@ -222,6 +237,14 @@
 	LicenseAnnotationToolchain LicenseAnnotation = "toolchain"
 )
 
+// LicenseAnnotationSharedDependencyTag can be embedded in a dependency tag to implement
+// LicenseAnnotations that always returns LicenseAnnotationSharedDependency.
+type LicenseAnnotationSharedDependencyTag struct{}
+
+func (LicenseAnnotationSharedDependencyTag) LicenseAnnotations() []LicenseAnnotation {
+	return []LicenseAnnotation{LicenseAnnotationSharedDependency}
+}
+
 // LicenseAnnotationToolchainDependencyTag can be embedded in a dependency tag to implement
 // LicenseAnnotations that always returns LicenseAnnotationToolchain.
 type LicenseAnnotationToolchainDependencyTag struct{}
diff --git a/android/module.go b/android/module.go
index 666732f..00aed95 100644
--- a/android/module.go
+++ b/android/module.go
@@ -1321,6 +1321,9 @@
 	// set of dependency module:location mappings used to populate the license metadata for
 	// apex containers.
 	licenseInstallMap []string
+
+	// The path to the generated license metadata file for the module.
+	licenseMetadataFile WritablePath
 }
 
 // A struct containing all relevant information about a Bazel target converted via bp2build.
@@ -2076,6 +2079,8 @@
 		variables:         make(map[string]string),
 	}
 
+	m.licenseMetadataFile = PathForModuleOut(ctx, "meta_lic")
+
 	dependencyInstallFiles, dependencyPackagingSpecs := m.computeInstallDeps(ctx)
 	// set m.installFilesDepSet to only the transitive dependencies to be used as the dependencies
 	// of installed files of this module.  It will be replaced by a depset including the installed
@@ -2207,7 +2212,7 @@
 	m.installFilesDepSet = newInstallPathsDepSet(m.installFiles, dependencyInstallFiles)
 	m.packagingSpecsDepSet = newPackagingSpecsDepSet(m.packagingSpecs, dependencyPackagingSpecs)
 
-	buildLicenseMetadata(ctx)
+	buildLicenseMetadata(ctx, m.licenseMetadataFile)
 
 	m.buildParams = ctx.buildParams
 	m.ruleParams = ctx.ruleParams
diff --git a/android/notices.go b/android/notices.go
index d8cfaf2..194a734 100644
--- a/android/notices.go
+++ b/android/notices.go
@@ -16,6 +16,7 @@
 
 import (
 	"path/filepath"
+	"strings"
 
 	"github.com/google/blueprint"
 )
@@ -101,55 +102,15 @@
 	}
 }
 
-// BuildNotices merges the supplied NOTICE files into a single file that lists notices
-// for every key in noticeMap (which would normally be installed files).
-func BuildNotices(ctx ModuleContext, noticeMap map[string]Paths) NoticeOutputs {
-	// TODO(jungjw): We should just produce a well-formatted NOTICE.html file in a single pass.
-	//
-	// generate-notice-files.py, which processes the merged NOTICE file, has somewhat strict rules
-	// about input NOTICE file paths.
-	// 1. Their relative paths to the src root become their NOTICE index titles. We want to use
-	// on-device paths as titles, and so output the merged NOTICE file the corresponding location.
-	// 2. They must end with .txt extension. Otherwise, they're ignored.
-
-	mergeTool := PathForSource(ctx, "build/soong/scripts/mergenotice.py")
-	generateNoticeTool := PathForSource(ctx, "build/soong/scripts/generate-notice-files.py")
-
-	outputDir := PathForModuleOut(ctx, "notices")
-	builder := NewRuleBuilder(pctx, ctx).
-		Sbox(outputDir, PathForModuleOut(ctx, "notices.sbox.textproto"))
-	for _, installPath := range SortedStringKeys(noticeMap) {
-		noticePath := outputDir.Join(ctx, installPath+".txt")
-		// It would be nice if sbox created directories for temporaries, but until then
-		// this is simple enough.
-		builder.Command().
-			Text("(cd").OutputDir().Text("&&").
-			Text("mkdir -p").Text(filepath.Dir(installPath)).Text(")")
-		builder.Temporary(noticePath)
-		builder.Command().
-			Tool(mergeTool).
-			Flag("--output").Output(noticePath).
-			Inputs(noticeMap[installPath])
-	}
-
-	// Transform the merged NOTICE file into a gzipped HTML file.
-	txtOutput := outputDir.Join(ctx, "NOTICE.txt")
-	htmlOutput := outputDir.Join(ctx, "NOTICE.html")
-	htmlGzOutput := outputDir.Join(ctx, "NOTICE.html.gz")
-	title := "\"Notices for " + ctx.ModuleName() + "\""
-	builder.Command().Tool(generateNoticeTool).
-		FlagWithOutput("--text-output ", txtOutput).
-		FlagWithOutput("--html-output ", htmlOutput).
-		FlagWithArg("-t ", title).
-		Flag("-s").OutputDir()
-	builder.Command().BuiltTool("minigzip").
-		FlagWithInput("-c ", htmlOutput).
-		FlagWithOutput("> ", htmlGzOutput)
-	builder.Build("build_notices", "generate notice output")
-
-	return NoticeOutputs{
-		TxtOutput:    OptionalPathForPath(txtOutput),
-		HtmlOutput:   OptionalPathForPath(htmlOutput),
-		HtmlGzOutput: OptionalPathForPath(htmlGzOutput),
-	}
+// BuildNoticeTextOutputFromLicenseMetadata writes out a notice text file based on the module's
+// generated license metadata file.
+func BuildNoticeTextOutputFromLicenseMetadata(ctx ModuleContext, outputFile WritablePath) {
+	depsFile := outputFile.ReplaceExtension(ctx, strings.TrimPrefix(outputFile.Ext()+".d", "."))
+	rule := NewRuleBuilder(pctx, ctx)
+	rule.Command().
+		BuiltTool("textnotice").
+		FlagWithOutput("-o ", outputFile).
+		FlagWithDepFile("-d ", depsFile).
+		Input(ctx.Module().base().licenseMetadataFile)
+	rule.Build("container_notice", "container notice file")
 }
diff --git a/android/paths.go b/android/paths.go
index 70e427b..4c69de7 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -2149,3 +2149,23 @@
 	}
 	return false
 }
+
+// PathsDepSet is a thin type-safe wrapper around the generic depSet.  It always uses
+// topological order.
+type PathsDepSet struct {
+	depSet
+}
+
+// newPathsDepSet returns an immutable PathsDepSet with the given direct and
+// transitive contents.
+func newPathsDepSet(direct Paths, transitive []*PathsDepSet) *PathsDepSet {
+	return &PathsDepSet{*newDepSet(TOPOLOGICAL, direct, transitive)}
+}
+
+// ToList returns the PathsDepSet flattened to a list in topological order.
+func (d *PathsDepSet) ToList() Paths {
+	if d == nil {
+		return nil
+	}
+	return d.depSet.ToList().(Paths)
+}
diff --git a/android_sdk/sdk_repo_host.go b/android_sdk/sdk_repo_host.go
index d64eb7a..f050a2e 100644
--- a/android_sdk/sdk_repo_host.go
+++ b/android_sdk/sdk_repo_host.go
@@ -122,17 +122,10 @@
 
 	s.CopySpecsToDir(ctx, builder, packageSpecs, dir)
 
-	// Collect licenses to write into NOTICE.txt
-	noticeMap := map[string]android.Paths{}
-	for path, pkgSpec := range packageSpecs {
-		licenseFiles := pkgSpec.EffectiveLicenseFiles()
-		if len(licenseFiles) > 0 {
-			noticeMap[path] = pkgSpec.EffectiveLicenseFiles()
-		}
-	}
-	notices := android.BuildNotices(ctx, noticeMap)
+	noticeFile := android.PathForModuleOut(ctx, "NOTICES.txt")
+	android.BuildNoticeTextOutputFromLicenseMetadata(ctx, noticeFile)
 	builder.Command().Text("cp").
-		Input(notices.TxtOutput.Path()).
+		Input(noticeFile).
 		Text(filepath.Join(dir.String(), "NOTICE.txt"))
 
 	// Handle `merge_zips` by extracting their contents into our tmpdir
diff --git a/androidmk/androidmk/android.go b/androidmk/androidmk/android.go
index ae52688..6fac79d 100644
--- a/androidmk/androidmk/android.go
+++ b/androidmk/androidmk/android.go
@@ -191,6 +191,7 @@
 			// will be removed later by byfix
 			// TODO: does this property matter in the license module?
 			"LOCAL_LICENSE_CONDITIONS": "android_license_conditions",
+			"LOCAL_GENERATED_SOURCES":  "generated_sources",
 		})
 
 	addStandardProperties(bpparser.BoolType,
diff --git a/androidmk/androidmk/androidmk_test.go b/androidmk/androidmk/androidmk_test.go
index abdbf53..81b5c30 100644
--- a/androidmk/androidmk/androidmk_test.go
+++ b/androidmk/androidmk/androidmk_test.go
@@ -1620,6 +1620,31 @@
 }
 `,
 	},
+	{
+		desc: "LOCAL_GENERATED_SOURCES",
+		in: `
+include $(CLEAR_VARS)
+LOCAL_MODULE := foo
+LOCAL_SRC_FILES := src1, src2, src3
+LOCAL_GENERATED_SOURCES := gen_src1, gen_src2, gen_src3
+include $(BUILD_PACKAGE)
+		`,
+		expected: `
+android_app {
+	name: "foo",
+	srcs: [
+		"src1,",
+		"src2,",
+		"src3",
+	],
+	generated_sources: [
+		"gen_src1,",
+		"gen_src2,",
+		"gen_src3",
+	],
+}
+`,
+	},
 }
 
 func TestEndToEnd(t *testing.T) {
diff --git a/apex/builder.go b/apex/builder.go
index a66e1e0..1a1f22b 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -397,6 +397,22 @@
 	return output.OutputPath
 }
 
+func markManifestTestOnly(ctx android.ModuleContext, androidManifestFile android.Path) android.Path {
+	return java.ManifestFixer(java.ManifestFixerParams{
+		Ctx:                   ctx,
+		Manifest:              androidManifestFile,
+		SdkContext:            nil,
+		ClassLoaderContexts:   nil,
+		IsLibrary:             false,
+		UseEmbeddedNativeLibs: false,
+		UsesNonSdkApis:        false,
+		UseEmbeddedDex:        false,
+		HasNoCode:             false,
+		TestOnly:              true,
+		LoggingParent:         "",
+	})
+}
+
 // buildUnflattendApex creates build rules to build an APEX using apexer.
 func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext) {
 	apexType := a.properties.ApexType
@@ -595,6 +611,11 @@
 
 		if a.properties.AndroidManifest != nil {
 			androidManifestFile := android.PathForModuleSrc(ctx, proptools.String(a.properties.AndroidManifest))
+
+			if a.testApex {
+				androidManifestFile = markManifestTestOnly(ctx, androidManifestFile)
+			}
+
 			implicitInputs = append(implicitInputs, androidManifestFile)
 			optFlags = append(optFlags, "--android_manifest "+androidManifestFile.String())
 		}
diff --git a/cc/binary.go b/cc/binary.go
index ee3de3f..bf77d3d 100644
--- a/cc/binary.go
+++ b/cc/binary.go
@@ -76,7 +76,6 @@
 // cc_binary_host produces a binary that is runnable on a host.
 func BinaryHostFactory() android.Module {
 	module, _ := newBinary(android.HostSupported, true)
-	module.bazelable = true
 	return module.Init()
 }
 
diff --git a/dexpreopt/config.go b/dexpreopt/config.go
index 1f99a96..153b025 100644
--- a/dexpreopt/config.go
+++ b/dexpreopt/config.go
@@ -408,6 +408,7 @@
 
 type dex2oatDependencyTag struct {
 	blueprint.BaseDependencyTag
+	android.LicenseAnnotationToolchainDependencyTag
 }
 
 func (d dex2oatDependencyTag) ExcludeFromVisibilityEnforcement() {
diff --git a/java/aar.go b/java/aar.go
index aabbec6..4687424 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -276,9 +276,19 @@
 	manifestFile := proptools.StringDefault(a.aaptProperties.Manifest, "AndroidManifest.xml")
 	manifestSrcPath := android.PathForModuleSrc(ctx, manifestFile)
 
-	manifestPath := manifestFixer(ctx, manifestSrcPath, sdkContext, classLoaderContexts,
-		a.isLibrary, a.useEmbeddedNativeLibs, a.usesNonSdkApis, a.useEmbeddedDex, a.hasNoCode,
-		a.LoggingParent)
+	manifestPath := ManifestFixer(ManifestFixerParams{
+		Ctx:                   ctx,
+		Manifest:              manifestSrcPath,
+		SdkContext:            sdkContext,
+		ClassLoaderContexts:   classLoaderContexts,
+		IsLibrary:             a.isLibrary,
+		UseEmbeddedNativeLibs: a.useEmbeddedNativeLibs,
+		UsesNonSdkApis:        a.usesNonSdkApis,
+		UseEmbeddedDex:        a.useEmbeddedDex,
+		HasNoCode:             a.hasNoCode,
+		TestOnly:              false,
+		LoggingParent:         a.LoggingParent,
+	})
 
 	// Add additional manifest files to transitive manifests.
 	additionalManifests := android.PathsForModuleSrc(ctx, a.aaptProperties.Additional_manifests)
diff --git a/java/android_manifest.go b/java/android_manifest.go
index f29d8ad..a5d5b97 100644
--- a/java/android_manifest.go
+++ b/java/android_manifest.go
@@ -28,13 +28,10 @@
 var manifestFixerRule = pctx.AndroidStaticRule("manifestFixer",
 	blueprint.RuleParams{
 		Command: `${config.ManifestFixerCmd} ` +
-			`--minSdkVersion ${minSdkVersion} ` +
-			`--targetSdkVersion ${targetSdkVersion} ` +
-			`--raise-min-sdk-version ` +
 			`$args $in $out`,
 		CommandDeps: []string{"${config.ManifestFixerCmd}"},
 	},
-	"minSdkVersion", "targetSdkVersion", "args")
+	"args")
 
 var manifestMergerRule = pctx.AndroidStaticRule("manifestMerger",
 	blueprint.RuleParams{
@@ -58,84 +55,110 @@
 	return targetSdkVersion
 }
 
-// Uses manifest_fixer.py to inject minSdkVersion, etc. into an AndroidManifest.xml
-func manifestFixer(ctx android.ModuleContext, manifest android.Path, sdkContext android.SdkContext,
-	classLoaderContexts dexpreopt.ClassLoaderContextMap, isLibrary, useEmbeddedNativeLibs, usesNonSdkApis,
-	useEmbeddedDex, hasNoCode bool, loggingParent string) android.Path {
+type ManifestFixerParams struct {
+	Ctx                   android.ModuleContext
+	Manifest              android.Path
+	SdkContext            android.SdkContext
+	ClassLoaderContexts   dexpreopt.ClassLoaderContextMap
+	IsLibrary             bool
+	UseEmbeddedNativeLibs bool
+	UsesNonSdkApis        bool
+	UseEmbeddedDex        bool
+	HasNoCode             bool
+	TestOnly              bool
+	LoggingParent         string
+}
 
+// Uses manifest_fixer.py to inject minSdkVersion, etc. into an AndroidManifest.xml
+func ManifestFixer(params ManifestFixerParams) android.Path {
 	var args []string
-	if isLibrary {
+
+	if params.IsLibrary {
 		args = append(args, "--library")
-	} else {
-		minSdkVersion, err := sdkContext.MinSdkVersion(ctx).EffectiveVersion(ctx)
+	} else if params.SdkContext != nil {
+		minSdkVersion, err := params.SdkContext.MinSdkVersion(params.Ctx).EffectiveVersion(params.Ctx)
 		if err != nil {
-			ctx.ModuleErrorf("invalid minSdkVersion: %s", err)
+			params.Ctx.ModuleErrorf("invalid minSdkVersion: %s", err)
 		}
 		if minSdkVersion.FinalOrFutureInt() >= 23 {
-			args = append(args, fmt.Sprintf("--extract-native-libs=%v", !useEmbeddedNativeLibs))
-		} else if useEmbeddedNativeLibs {
-			ctx.ModuleErrorf("module attempted to store uncompressed native libraries, but minSdkVersion=%d doesn't support it",
+			args = append(args, fmt.Sprintf("--extract-native-libs=%v", !params.UseEmbeddedNativeLibs))
+		} else if params.UseEmbeddedNativeLibs {
+			params.Ctx.ModuleErrorf("module attempted to store uncompressed native libraries, but minSdkVersion=%d doesn't support it",
 				minSdkVersion)
 		}
 	}
 
-	if usesNonSdkApis {
+	if params.UsesNonSdkApis {
 		args = append(args, "--uses-non-sdk-api")
 	}
 
-	if useEmbeddedDex {
+	if params.UseEmbeddedDex {
 		args = append(args, "--use-embedded-dex")
 	}
 
-	// manifest_fixer should add only the implicit SDK libraries inferred by Soong, not those added
-	// explicitly via `uses_libs`/`optional_uses_libs`.
-	requiredUsesLibs, optionalUsesLibs := classLoaderContexts.ImplicitUsesLibs()
-	for _, usesLib := range requiredUsesLibs {
-		args = append(args, "--uses-library", usesLib)
-	}
-	for _, usesLib := range optionalUsesLibs {
-		args = append(args, "--optional-uses-library", usesLib)
+	if params.ClassLoaderContexts != nil {
+		// manifest_fixer should add only the implicit SDK libraries inferred by Soong, not those added
+		// explicitly via `uses_libs`/`optional_uses_libs`.
+		requiredUsesLibs, optionalUsesLibs := params.ClassLoaderContexts.ImplicitUsesLibs()
+
+		for _, usesLib := range requiredUsesLibs {
+			args = append(args, "--uses-library", usesLib)
+		}
+		for _, usesLib := range optionalUsesLibs {
+			args = append(args, "--optional-uses-library", usesLib)
+		}
 	}
 
-	if hasNoCode {
+	if params.HasNoCode {
 		args = append(args, "--has-no-code")
 	}
 
-	if loggingParent != "" {
-		args = append(args, "--logging-parent", loggingParent)
+	if params.TestOnly {
+		args = append(args, "--test-only")
+	}
+
+	if params.LoggingParent != "" {
+		args = append(args, "--logging-parent", params.LoggingParent)
 	}
 	var deps android.Paths
-	targetSdkVersion := targetSdkVersionForManifestFixer(ctx, sdkContext)
+	var argsMapper = make(map[string]string)
 
-	if UseApiFingerprint(ctx) && ctx.ModuleName() != "framework-res" {
-		targetSdkVersion = ctx.Config().PlatformSdkCodename() + fmt.Sprintf(".$$(cat %s)", ApiFingerprintPath(ctx).String())
-		deps = append(deps, ApiFingerprintPath(ctx))
+	if params.SdkContext != nil {
+		targetSdkVersion := targetSdkVersionForManifestFixer(params.Ctx, params.SdkContext)
+		args = append(args, "--targetSdkVersion ", targetSdkVersion)
+
+		if UseApiFingerprint(params.Ctx) && params.Ctx.ModuleName() != "framework-res" {
+			targetSdkVersion = params.Ctx.Config().PlatformSdkCodename() + fmt.Sprintf(".$$(cat %s)", ApiFingerprintPath(params.Ctx).String())
+			deps = append(deps, ApiFingerprintPath(params.Ctx))
+		}
+
+		minSdkVersion, err := params.SdkContext.MinSdkVersion(params.Ctx).EffectiveVersionString(params.Ctx)
+		if err != nil {
+			params.Ctx.ModuleErrorf("invalid minSdkVersion: %s", err)
+		}
+
+		if UseApiFingerprint(params.Ctx) && params.Ctx.ModuleName() != "framework-res" {
+			minSdkVersion = params.Ctx.Config().PlatformSdkCodename() + fmt.Sprintf(".$$(cat %s)", ApiFingerprintPath(params.Ctx).String())
+			deps = append(deps, ApiFingerprintPath(params.Ctx))
+		}
+
+		if err != nil {
+			params.Ctx.ModuleErrorf("invalid minSdkVersion: %s", err)
+		}
+		args = append(args, "--minSdkVersion ", minSdkVersion)
+		args = append(args, "--raise-min-sdk-version")
 	}
 
-	minSdkVersion, err := sdkContext.MinSdkVersion(ctx).EffectiveVersionString(ctx)
-	if err != nil {
-		ctx.ModuleErrorf("invalid minSdkVersion: %s", err)
-	}
-	if UseApiFingerprint(ctx) && ctx.ModuleName() != "framework-res" {
-		minSdkVersion = ctx.Config().PlatformSdkCodename() + fmt.Sprintf(".$$(cat %s)", ApiFingerprintPath(ctx).String())
-		deps = append(deps, ApiFingerprintPath(ctx))
-	}
+	fixedManifest := android.PathForModuleOut(params.Ctx, "manifest_fixer", "AndroidManifest.xml")
+	argsMapper["args"] = strings.Join(args, " ")
 
-	fixedManifest := android.PathForModuleOut(ctx, "manifest_fixer", "AndroidManifest.xml")
-	if err != nil {
-		ctx.ModuleErrorf("invalid minSdkVersion: %s", err)
-	}
-	ctx.Build(pctx, android.BuildParams{
+	params.Ctx.Build(pctx, android.BuildParams{
 		Rule:        manifestFixerRule,
 		Description: "fix manifest",
-		Input:       manifest,
+		Input:       params.Manifest,
 		Implicits:   deps,
 		Output:      fixedManifest,
-		Args: map[string]string{
-			"minSdkVersion":    minSdkVersion,
-			"targetSdkVersion": targetSdkVersion,
-			"args":             strings.Join(args, " "),
-		},
+		Args:        argsMapper,
 	})
 
 	return fixedManifest.WithoutRel()
diff --git a/java/app_test.go b/java/app_test.go
index 2322ef4..16bbec1 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -2512,7 +2512,7 @@
 		`--uses-library qux ` +
 		`--uses-library quuz ` +
 		`--uses-library runtime-library`
-	android.AssertStringEquals(t, "manifest_fixer args", expectManifestFixerArgs, actualManifestFixerArgs)
+	android.AssertStringDoesContain(t, "manifest_fixer args", actualManifestFixerArgs, expectManifestFixerArgs)
 
 	// Test that all libraries are verified (library order matters).
 	verifyCmd := app.Rule("verify_uses_libraries").RuleParams.Command
@@ -3055,7 +3055,7 @@
 		result := fixture.RunTestWithBp(t, bp)
 		foo := result.ModuleForTests("foo", "android_common")
 
-		manifestFixerArgs := foo.Output("manifest_fixer/AndroidManifest.xml").Args
-		android.AssertStringEquals(t, testCase.name, testCase.targetSdkVersionExpected, manifestFixerArgs["targetSdkVersion"])
+		manifestFixerArgs := foo.Output("manifest_fixer/AndroidManifest.xml").Args["args"]
+		android.AssertStringDoesContain(t, testCase.name, manifestFixerArgs, "--targetSdkVersion  "+testCase.targetSdkVersionExpected)
 	}
 }
diff --git a/java/hiddenapi.go b/java/hiddenapi.go
index 7c8be1e..3af5f1c 100644
--- a/java/hiddenapi.go
+++ b/java/hiddenapi.go
@@ -297,6 +297,7 @@
 
 type hiddenApiAnnotationsDependencyTag struct {
 	blueprint.BaseDependencyTag
+	android.LicenseAnnotationSharedDependencyTag
 }
 
 // Tag used to mark dependencies on java_library instances that contains Java source files whose
diff --git a/java/java.go b/java/java.go
index ca4b3cf..fef9912 100644
--- a/java/java.go
+++ b/java/java.go
@@ -274,6 +274,9 @@
 
 	// True if the dependency is relinked at runtime.
 	runtimeLinked bool
+
+	// True if the dependency is a toolchain, for example an annotation processor.
+	toolchain bool
 }
 
 // installDependencyTag is a dependency tag that is annotated to cause the installed files of the
@@ -287,6 +290,8 @@
 func (d dependencyTag) LicenseAnnotations() []android.LicenseAnnotation {
 	if d.runtimeLinked {
 		return []android.LicenseAnnotation{android.LicenseAnnotationSharedDependency}
+	} else if d.toolchain {
+		return []android.LicenseAnnotation{android.LicenseAnnotationToolchain}
 	}
 	return nil
 }
@@ -329,19 +334,19 @@
 	staticLibTag            = dependencyTag{name: "staticlib"}
 	libTag                  = dependencyTag{name: "javalib", runtimeLinked: true}
 	java9LibTag             = dependencyTag{name: "java9lib", runtimeLinked: true}
-	pluginTag               = dependencyTag{name: "plugin"}
-	errorpronePluginTag     = dependencyTag{name: "errorprone-plugin"}
-	exportedPluginTag       = dependencyTag{name: "exported-plugin"}
+	pluginTag               = dependencyTag{name: "plugin", toolchain: true}
+	errorpronePluginTag     = dependencyTag{name: "errorprone-plugin", toolchain: true}
+	exportedPluginTag       = dependencyTag{name: "exported-plugin", toolchain: true}
 	bootClasspathTag        = dependencyTag{name: "bootclasspath", runtimeLinked: true}
 	systemModulesTag        = dependencyTag{name: "system modules", runtimeLinked: true}
 	frameworkResTag         = dependencyTag{name: "framework-res"}
 	kotlinStdlibTag         = dependencyTag{name: "kotlin-stdlib", runtimeLinked: true}
 	kotlinAnnotationsTag    = dependencyTag{name: "kotlin-annotations", runtimeLinked: true}
-	kotlinPluginTag         = dependencyTag{name: "kotlin-plugin"}
+	kotlinPluginTag         = dependencyTag{name: "kotlin-plugin", toolchain: true}
 	proguardRaiseTag        = dependencyTag{name: "proguard-raise"}
 	certificateTag          = dependencyTag{name: "certificate"}
 	instrumentationForTag   = dependencyTag{name: "instrumentation_for"}
-	extraLintCheckTag       = dependencyTag{name: "extra-lint-check"}
+	extraLintCheckTag       = dependencyTag{name: "extra-lint-check", toolchain: true}
 	jniLibTag               = dependencyTag{name: "jnilib", runtimeLinked: true}
 	syspropPublicStubDepTag = dependencyTag{name: "sysprop public stub"}
 	jniInstallTag           = installDependencyTag{name: "jni install"}
diff --git a/mk2rbc/expr.go b/mk2rbc/expr.go
index 3f355ac..07f7ca1 100644
--- a/mk2rbc/expr.go
+++ b/mk2rbc/expr.go
@@ -378,32 +378,6 @@
 	}
 }
 
-// variableDefinedExpr corresponds to Make's ifdef VAR
-type variableDefinedExpr struct {
-	v variable
-}
-
-func (v *variableDefinedExpr) emit(gctx *generationContext) {
-	if v.v != nil {
-		v.v.emitDefined(gctx)
-		return
-	}
-	gctx.writef("%s(%q)", cfnWarning, "TODO(VAR)")
-}
-
-func (_ *variableDefinedExpr) typ() starlarkType {
-	return starlarkTypeBool
-}
-
-func (v *variableDefinedExpr) emitListVarCopy(gctx *generationContext) {
-	v.emit(gctx)
-}
-
-func (v *variableDefinedExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
-	// TODO: VariableDefinedExpr isn't really an expression?
-	return v
-}
-
 type listExpr struct {
 	items []starlarkExpr
 }
diff --git a/mk2rbc/mk2rbc.go b/mk2rbc/mk2rbc.go
index ebb463b..90dc46b 100644
--- a/mk2rbc/mk2rbc.go
+++ b/mk2rbc/mk2rbc.go
@@ -1005,19 +1005,14 @@
 	ctx.popReceiver()
 }
 
-func (ctx *parseContext) newIfDefinedNode(check *mkparser.Directive) (starlarkExpr, bool) {
-	if !check.Args.Const() {
-		return ctx.newBadExpr(check, "ifdef variable ref too complex: %s", check.Args.Dump()), false
-	}
-	v := ctx.addVariable(check.Args.Strings[0])
-	return &variableDefinedExpr{v}, true
-}
-
 func (ctx *parseContext) parseCondition(check *mkparser.Directive) starlarkNode {
 	switch check.Name {
 	case "ifdef", "ifndef", "elifdef", "elifndef":
-		v, ok := ctx.newIfDefinedNode(check)
-		if ok && strings.HasSuffix(check.Name, "ndef") {
+		if !check.Args.Const() {
+			return &exprNode{expr: ctx.newBadExpr(check, "ifdef variable ref too complex: %s", check.Args.Dump())}
+		}
+		v := NewVariableRefExpr(ctx.addVariable(check.Args.Strings[0]), false)
+		if strings.HasSuffix(check.Name, "ndef") {
 			v = &notExpr{v}
 		}
 		return &ifNode{
diff --git a/mk2rbc/mk2rbc_test.go b/mk2rbc/mk2rbc_test.go
index 20f198a..376ee5e 100644
--- a/mk2rbc/mk2rbc_test.go
+++ b/mk2rbc/mk2rbc_test.go
@@ -131,7 +131,7 @@
 def init(g, handle):
   cfg = rblf.cfg(handle)
   rblf.inherit(handle, "part", _part_init)
-  if g.get("PRODUCT_NAME") != None:
+  if cfg.get("PRODUCT_NAME", ""):
     if not _part1_init:
       rblf.mkerror("product.mk", "Cannot find %s" % (":part1.star"))
     rblf.inherit(handle, "part1", _part1_init)
@@ -174,7 +174,7 @@
 def init(g, handle):
   cfg = rblf.cfg(handle)
   _part_init(g, handle)
-  if g.get("PRODUCT_NAME") != None:
+  if cfg.get("PRODUCT_NAME", ""):
     if not _part1_init:
       rblf.mkerror("product.mk", "Cannot find %s" % (":part1.star"))
     _part1_init(g, handle)
@@ -231,7 +231,7 @@
 
 def init(g, handle):
   cfg = rblf.cfg(handle)
-  if g.get("PRODUCT_NAME") != None:
+  if cfg.get("PRODUCT_NAME", ""):
     cfg["PRODUCT_NAME"] = "gizmo"
   else:
     pass
@@ -275,7 +275,7 @@
 
 def init(g, handle):
   cfg = rblf.cfg(handle)
-  if g.get("PRODUCT_NAME") != None:
+  if cfg.get("PRODUCT_NAME", ""):
     # Comment
     pass
   else:
@@ -296,7 +296,7 @@
 
 def init(g, handle):
   cfg = rblf.cfg(handle)
-  if not g.get("PRODUCT_NAME") != None:
+  if not cfg.get("PRODUCT_NAME", ""):
     cfg["PRODUCT_NAME"] = "gizmo1"
   else:
     cfg["PRODUCT_NAME"] = "gizmo2"
@@ -315,9 +315,9 @@
 
 def init(g, handle):
   cfg = rblf.cfg(handle)
-  if g.get("PRODUCT_NAME") != None:
+  if cfg.get("PRODUCT_NAME", ""):
     cfg["PRODUCT_NAME"] = "gizmo"
-  elif not g.get("PRODUCT_PACKAGES") != None:
+  elif not cfg.get("PRODUCT_PACKAGES", []):
     # Comment
     pass
 `,
@@ -509,11 +509,11 @@
 
 def init(g, handle):
   cfg = rblf.cfg(handle)
-  if g.get("PRODUCT_NAME") != None:
+  if cfg.get("PRODUCT_NAME", ""):
     cfg["PRODUCT_PACKAGES"] = ["pack-if0"]
-    if g.get("PRODUCT_MODEL") != None:
+    if cfg.get("PRODUCT_MODEL", ""):
       cfg["PRODUCT_PACKAGES"] = ["pack-if-if"]
-    elif g.get("PRODUCT_NAME") != None:
+    elif cfg.get("PRODUCT_NAME", ""):
       cfg["PRODUCT_PACKAGES"] = ["pack-if-elif"]
     else:
       cfg["PRODUCT_PACKAGES"] = ["pack-if-else"]
diff --git a/scripts/manifest_fixer.py b/scripts/manifest_fixer.py
index d80a617..2d3103b 100755
--- a/scripts/manifest_fixer.py
+++ b/scripts/manifest_fixer.py
@@ -65,6 +65,9 @@
   parser.add_argument('--has-no-code', dest='has_no_code', action='store_true',
                       help=('adds hasCode="false" attribute to application. Ignored if application elem '
                             'already has a hasCode attribute.'))
+  parser.add_argument('--test-only', dest='test_only', action='store_true',
+                      help=('adds testOnly="true" attribute to application. Assign true value if application elem '
+                            'already has a testOnly attribute.'))
   parser.add_argument('input', help='input AndroidManifest.xml file')
   parser.add_argument('output', help='output AndroidManifest.xml file')
   return parser.parse_args()
@@ -318,6 +321,26 @@
   attr.value = 'false'
   application.setAttributeNode(attr)
 
+def set_test_only_flag_to_true(doc):
+  manifest = parse_manifest(doc)
+  elems = get_children_with_tag(manifest, 'application')
+  application = elems[0] if len(elems) == 1 else None
+  if len(elems) > 1:
+    raise RuntimeError('found multiple <application> tags')
+  elif not elems:
+    application = doc.createElement('application')
+    indent = get_indent(manifest.firstChild, 1)
+    first = manifest.firstChild
+    manifest.insertBefore(doc.createTextNode(indent), first)
+    manifest.insertBefore(application, first)
+
+  attr = application.getAttributeNodeNS(android_ns, 'testOnly')
+  if attr is not None:
+    # Do nothing If the application already has a testOnly attribute.
+    return
+  attr = doc.createAttributeNS(android_ns, 'android:testOnly')
+  attr.value = 'true'
+  application.setAttributeNode(attr)
 
 def main():
   """Program entry point."""
@@ -349,6 +372,9 @@
     if args.has_no_code:
       set_has_code_to_false(doc)
 
+    if args.test_only:
+      set_test_only_flag_to_true(doc)
+
     if args.extract_native_libs is not None:
       add_extract_native_libs(doc, args.extract_native_libs)
 
diff --git a/scripts/manifest_fixer_test.py b/scripts/manifest_fixer_test.py
index f6fcaaf..199b279 100755
--- a/scripts/manifest_fixer_test.py
+++ b/scripts/manifest_fixer_test.py
@@ -521,12 +521,55 @@
     self.assert_xml_equal(output, manifest_input)
 
   def test_has_application_has_code_true(self):
-    """ Do nothing if there's already an application elemeent even if its
+    """ Do nothing if there's already an application element even if its
      hasCode attribute is true. """
     manifest_input = self.manifest_tmpl % '    <application android:hasCode="true"/>\n'
     output = self.run_test(manifest_input)
     self.assert_xml_equal(output, manifest_input)
 
 
+class AddTestOnlyApplicationTest(unittest.TestCase):
+  """Unit tests for set_test_only_flag_to_true function."""
+
+  def assert_xml_equal(self, output, expected):
+    self.assertEqual(ET.canonicalize(output), ET.canonicalize(expected))
+
+  def run_test(self, input_manifest):
+    doc = minidom.parseString(input_manifest)
+    manifest_fixer.set_test_only_flag_to_true(doc)
+    output = io.StringIO()
+    manifest_fixer.write_xml(output, doc)
+    return output.getvalue()
+
+  manifest_tmpl = (
+      '<?xml version="1.0" encoding="utf-8"?>\n'
+      '<manifest xmlns:android="http://schemas.android.com/apk/res/android">\n'
+      '%s'
+      '</manifest>\n')
+
+  def test_no_application(self):
+    manifest_input = self.manifest_tmpl % ''
+    expected = self.manifest_tmpl % '    <application android:testOnly="true"/>\n'
+    output = self.run_test(manifest_input)
+    self.assert_xml_equal(output, expected)
+
+  def test_has_application_no_test_only(self):
+    manifest_input = self.manifest_tmpl % '    <application/>\n'
+    expected = self.manifest_tmpl % '    <application android:testOnly="true"/>\n'
+    output = self.run_test(manifest_input)
+    self.assert_xml_equal(output, expected)
+
+  def test_has_application_test_only_true(self):
+    """ If there's already an application element."""
+    manifest_input = self.manifest_tmpl % '    <application android:testOnly="true"/>\n'
+    output = self.run_test(manifest_input)
+    self.assert_xml_equal(output, manifest_input)
+
+  def test_has_application_test_only_false(self):
+    """ If there's already an application element with the testOnly attribute as false."""
+    manifest_input = self.manifest_tmpl % '    <application android:testOnly="false"/>\n'
+    output = self.run_test(manifest_input)
+    self.assert_xml_equal(output, manifest_input)
+
 if __name__ == '__main__':
   unittest.main(verbosity=2)