Merge "Fix build breakages when WITHOUT_CHECK_API=true"
diff --git a/android/rule_builder.go b/android/rule_builder.go
index 6226548..afb5f4e 100644
--- a/android/rule_builder.go
+++ b/android/rule_builder.go
@@ -172,7 +172,7 @@
 
 	inputs := make(map[string]Path)
 	for _, c := range r.commands {
-		for _, input := range c.inputs {
+		for _, input := range append(c.inputs, c.implicits...) {
 			inputStr := input.String()
 			if _, isOutput := outputs[inputStr]; !isOutput {
 				if _, isDepFile := depFiles[inputStr]; !isDepFile {
@@ -480,6 +480,7 @@
 type RuleBuilderCommand struct {
 	buf           strings.Builder
 	inputs        Paths
+	implicits     Paths
 	orderOnlys    Paths
 	outputs       WritablePaths
 	depFiles      WritablePaths
@@ -503,6 +504,16 @@
 	return path.String()
 }
 
+func (c *RuleBuilderCommand) addImplicit(path Path) string {
+	if c.sbox {
+		if rel, isRel, _ := maybeRelErr(c.sboxOutDir.String(), path.String()); isRel {
+			return "__SBOX_OUT_DIR__/" + rel
+		}
+	}
+	c.implicits = append(c.implicits, path)
+	return path.String()
+}
+
 func (c *RuleBuilderCommand) addOrderOnly(path Path) {
 	c.orderOnlys = append(c.orderOnlys, path)
 }
@@ -623,7 +634,7 @@
 // Implicit adds the specified input path to the dependencies returned by RuleBuilder.Inputs without modifying the
 // command line.
 func (c *RuleBuilderCommand) Implicit(path Path) *RuleBuilderCommand {
-	c.addInput(path)
+	c.addImplicit(path)
 	return c
 }
 
@@ -631,11 +642,16 @@
 // command line.
 func (c *RuleBuilderCommand) Implicits(paths Paths) *RuleBuilderCommand {
 	for _, path := range paths {
-		c.addInput(path)
+		c.addImplicit(path)
 	}
 	return c
 }
 
+// GetImplicits returns the command's implicit inputs.
+func (c *RuleBuilderCommand) GetImplicits() Paths {
+	return c.implicits
+}
+
 // OrderOnly adds the specified input path to the dependencies returned by RuleBuilder.OrderOnlys
 // without modifying the command line.
 func (c *RuleBuilderCommand) OrderOnly(path Path) *RuleBuilderCommand {
diff --git a/cc/test.go b/cc/test.go
index 2439c94..09da976 100644
--- a/cc/test.go
+++ b/cc/test.go
@@ -40,6 +40,8 @@
 type TestOptions struct {
 	// The UID that you want to run the test as on a device.
 	Run_test_as *string
+	// A list of free-formed strings without spaces that categorize the test.
+	Test_suite_tag []string
 }
 
 type TestBinaryProperties struct {
@@ -357,6 +359,9 @@
 	if test.Properties.Test_options.Run_test_as != nil {
 		configs = append(configs, tradefed.Option{Name: "run-test-as", Value: String(test.Properties.Test_options.Run_test_as)})
 	}
+	for _, tag := range test.Properties.Test_options.Test_suite_tag {
+		configs = append(configs, tradefed.Option{Name: "test-suite-tag", Value: tag})
+	}
 	if test.Properties.Test_min_api_level != nil && test.Properties.Test_min_sdk_version != nil {
 		ctx.PropertyErrorf("test_min_api_level", "'test_min_api_level' and 'test_min_sdk_version' should not be set at the same time.")
 	} else if test.Properties.Test_min_api_level != nil {
diff --git a/java/androidmk_test.go b/java/androidmk_test.go
index 7daa624..d471fb7 100644
--- a/java/androidmk_test.go
+++ b/java/androidmk_test.go
@@ -169,3 +169,36 @@
 		t.Errorf("did not expect explicit DistFile, got %v", without_tag_entries[0].DistFile)
 	}
 }
+
+func TestJavaSdkLibrary_RequireXmlPermissionFile(t *testing.T) {
+	ctx, config := testJava(t, `
+		java_sdk_library {
+			name: "foo-shared_library",
+			srcs: ["a.java"],
+		}
+		java_sdk_library {
+			name: "foo-no_shared_library",
+			srcs: ["a.java"],
+			shared_library: false,
+		}
+		`)
+
+	// Verify the existence of internal modules
+	ctx.ModuleForTests("foo-shared_library.xml", "android_common")
+
+	testCases := []struct {
+		moduleName string
+		expected   []string
+	}{
+		{"foo-shared_library", []string{"foo-shared_library.xml"}},
+		{"foo-no_shared_library", nil},
+	}
+	for _, tc := range testCases {
+		mod := ctx.ModuleForTests(tc.moduleName, "android_common").Module()
+		entries := android.AndroidMkEntriesForTest(t, config, "", mod)[0]
+		actual := entries.EntryMap["LOCAL_REQUIRED_MODULES"]
+		if !reflect.DeepEqual(tc.expected, actual) {
+			t.Errorf("Unexpected required modules - expected: %q, actual: %q", tc.expected, actual)
+		}
+	}
+}
diff --git a/java/droiddoc.go b/java/droiddoc.go
index a24d44b..a0b7edf 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -121,6 +121,10 @@
 
 	// names of the output files used in args that will be generated
 	Out []string
+
+	// If set, metalava is sandboxed to only read files explicitly specified on the command
+	// line. Defaults to false.
+	Sandbox *bool
 }
 
 type ApiToCheck struct {
@@ -1321,6 +1325,7 @@
 			cmd.Flag("--exclude-documentation-from-stubs")
 		}
 	}
+	cmd.FlagWithArg("--hide ", "ShowingMemberInHiddenClass") // b/159121253 -- remove it once all the violations are fixed.
 }
 
 func (d *Droidstubs) annotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand) {
@@ -1434,41 +1439,25 @@
 }
 
 func metalavaCmd(ctx android.ModuleContext, rule *android.RuleBuilder, javaVersion javaVersion, srcs android.Paths,
-	srcJarList android.Path, bootclasspath, classpath classpath, sourcepaths android.Paths, implicits android.Paths) *android.RuleBuilderCommand {
+	srcJarList android.Path, bootclasspath, classpath classpath, sourcepaths android.Paths, implicitsRsp android.WritablePath, sandbox bool) *android.RuleBuilderCommand {
 	// Metalava uses lots of memory, restrict the number of metalava jobs that can run in parallel.
 	rule.HighMem()
 	cmd := rule.Command()
-
-	var implicitsRsp android.WritablePath
-	if len(implicits) > 0 {
-		implicitsRsp = android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"implicits.rsp")
-		impRule := android.NewRuleBuilder()
-		impCmd := impRule.Command()
-		// A dummy action that copies the ninja generated rsp file to a new location. This allows us to
-		// add a large number of inputs to a file without exceeding bash command length limits (which
-		// would happen if we use the WriteFile rule). The cp is needed because RuleBuilder sets the
-		// rsp file to be ${output}.rsp.
-		impCmd.Text("cp").FlagWithRspFileInputList("", implicits).Output(implicitsRsp)
-		impRule.Build(pctx, ctx, "implicitsGen", "implicits generation")
-		cmd.Implicits(implicits)
-		cmd.Implicit(implicitsRsp)
-	}
 	if ctx.Config().IsEnvTrue("RBE_METALAVA") {
 		rule.Remoteable(android.RemoteRuleSupports{RBE: true})
-		execStrategy := remoteexec.LocalExecStrategy
-		if v := ctx.Config().Getenv("RBE_METALAVA_EXEC_STRATEGY"); v != "" {
-			execStrategy = v
-		}
-		pool := "metalava"
-		if v := ctx.Config().Getenv("RBE_METALAVA_POOL"); v != "" {
-			pool = v
+		pool := ctx.Config().GetenvWithDefault("RBE_METALAVA_POOL", "metalava")
+		execStrategy := ctx.Config().GetenvWithDefault("RBE_METALAVA_EXEC_STRATEGY", remoteexec.LocalExecStrategy)
+		labels := map[string]string{"type": "compile", "lang": "java", "compiler": "metalava"}
+		if !sandbox {
+			execStrategy = remoteexec.LocalExecStrategy
+			labels["shallow"] = "true"
 		}
 		inputs := []string{android.PathForOutput(ctx, "host", ctx.Config().PrebuiltOS(), "framework", "metalava.jar").String()}
 		if v := ctx.Config().Getenv("RBE_METALAVA_INPUTS"); v != "" {
 			inputs = append(inputs, strings.Split(v, ",")...)
 		}
 		cmd.Text((&remoteexec.REParams{
-			Labels:          map[string]string{"type": "compile", "lang": "java", "compiler": "metalava", "shallow": "true"},
+			Labels:          labels,
 			ExecStrategy:    execStrategy,
 			Inputs:          inputs,
 			RSPFile:         implicitsRsp.String(),
@@ -1482,8 +1471,17 @@
 		FlagWithArg("-encoding ", "UTF-8").
 		FlagWithArg("-source ", javaVersion.String()).
 		FlagWithRspFileInputList("@", srcs).
-		FlagWithInput("@", srcJarList).
-		FlagWithOutput("--strict-input-files:warn ", android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"violations.txt"))
+		FlagWithInput("@", srcJarList)
+
+	if javaHome := ctx.Config().Getenv("ANDROID_JAVA_HOME"); javaHome != "" {
+		cmd.Implicit(android.PathForSource(ctx, javaHome))
+	}
+
+	if sandbox {
+		cmd.FlagWithOutput("--strict-input-files ", android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"violations.txt"))
+	} else {
+		cmd.FlagWithOutput("--strict-input-files:warn ", android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"violations.txt"))
+	}
 
 	if implicitsRsp != nil {
 		cmd.FlagWithArg("--strict-input-files-exempt ", "@"+implicitsRsp.String())
@@ -1533,8 +1531,12 @@
 
 	srcJarList := zipSyncCmd(ctx, rule, srcJarDir, d.Javadoc.srcJars)
 
+	implicitsRsp := android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"implicits.rsp")
+
 	cmd := metalavaCmd(ctx, rule, javaVersion, d.Javadoc.srcFiles, srcJarList,
-		deps.bootClasspath, deps.classpath, d.Javadoc.sourcepaths, d.Javadoc.implicits)
+		deps.bootClasspath, deps.classpath, d.Javadoc.sourcepaths, implicitsRsp,
+		Bool(d.Javadoc.properties.Sandbox))
+	cmd.Implicits(d.Javadoc.implicits)
 
 	d.stubsFlags(ctx, cmd, stubsDir)
 
@@ -1653,6 +1655,16 @@
 		cmd.FlagWithArg("--error-message:compatibility:released ", msg)
 	}
 
+	impRule := android.NewRuleBuilder()
+	impCmd := impRule.Command()
+	// A dummy action that copies the ninja generated rsp file to a new location. This allows us to
+	// add a large number of inputs to a file without exceeding bash command length limits (which
+	// would happen if we use the WriteFile rule). The cp is needed because RuleBuilder sets the
+	// rsp file to be ${output}.rsp.
+	impCmd.Text("cp").FlagWithRspFileInputList("", cmd.GetImplicits()).Output(implicitsRsp)
+	impRule.Build(pctx, ctx, "implicitsGen", "implicits generation")
+	cmd.Implicit(implicitsRsp)
+
 	if generateStubs {
 		rule.Command().
 			BuiltTool(ctx, "soong_zip").
diff --git a/java/java.go b/java/java.go
index 97a6747..7a42557 100644
--- a/java/java.go
+++ b/java/java.go
@@ -253,6 +253,9 @@
 
 	// List of files to include in the META-INF/services folder of the resulting jar.
 	Services []string `android:"path,arch_variant"`
+
+	// If true, package the kotlin stdlib into the jar.  Defaults to true.
+	Static_kotlin_stdlib *bool `android:"arch_variant"`
 }
 
 type CompilerDeviceProperties struct {
@@ -576,6 +579,7 @@
 	certificateTag        = dependencyTag{name: "certificate"}
 	instrumentationForTag = dependencyTag{name: "instrumentation_for"}
 	usesLibTag            = dependencyTag{name: "uses-library"}
+	extraLintCheckTag     = dependencyTag{name: "extra-lint-check"}
 )
 
 func IsLibDepTag(depTag blueprint.DependencyTag) bool {
@@ -687,6 +691,8 @@
 
 func (j *Module) deps(ctx android.BottomUpMutatorContext) {
 	if ctx.Device() {
+		j.linter.deps(ctx)
+
 		sdkDep := decodeSdkDep(ctx, sdkContext(j))
 		if sdkDep.useDefaultLibs {
 			ctx.AddVariationDependencies(nil, bootClasspathTag, config.DefaultBootclasspathLibraries...)
@@ -1350,8 +1356,10 @@
 		if len(flags.processorPath) > 0 {
 			// Use kapt for annotation processing
 			kaptSrcJar := android.PathForModuleOut(ctx, "kapt", "kapt-sources.jar")
-			kotlinKapt(ctx, kaptSrcJar, kotlinSrcFiles, srcJars, flags)
+			kaptResJar := android.PathForModuleOut(ctx, "kapt", "kapt-res.jar")
+			kotlinKapt(ctx, kaptSrcJar, kaptResJar, kotlinSrcFiles, srcJars, flags)
 			srcJars = append(srcJars, kaptSrcJar)
+			kotlinJars = append(kotlinJars, kaptResJar)
 			// Disable annotation processing in javac, it's already been handled by kapt
 			flags.processorPath = nil
 			flags.processors = nil
@@ -1366,9 +1374,11 @@
 		// Make javac rule depend on the kotlinc rule
 		flags.classpath = append(flags.classpath, kotlinJar)
 
-		// Jar kotlin classes into the final jar after javac
 		kotlinJars = append(kotlinJars, kotlinJar)
-		kotlinJars = append(kotlinJars, deps.kotlinStdlib...)
+		// Jar kotlin classes into the final jar after javac
+		if BoolDefault(j.properties.Static_kotlin_stdlib, true) {
+			kotlinJars = append(kotlinJars, deps.kotlinStdlib...)
+		}
 	}
 
 	jars := append(android.Paths(nil), kotlinJars...)
diff --git a/java/kotlin.go b/java/kotlin.go
index 9b160a0..673970b 100644
--- a/java/kotlin.go
+++ b/java/kotlin.go
@@ -90,7 +90,8 @@
 
 var kapt = pctx.AndroidRemoteStaticRule("kapt", android.RemoteRuleSupports{Goma: true},
 	blueprint.RuleParams{
-		Command: `rm -rf "$srcJarDir" "$kotlinBuildFile" "$kaptDir" && mkdir -p "$srcJarDir" "$kaptDir" && ` +
+		Command: `rm -rf "$srcJarDir" "$kotlinBuildFile" "$kaptDir" && ` +
+			`mkdir -p "$srcJarDir" "$kaptDir/sources" "$kaptDir/classes" && ` +
 			`${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" $srcJars && ` +
 			`${config.GenKotlinBuildFileCmd} $classpath "$name" "" $out.rsp $srcJarDir/list > $kotlinBuildFile &&` +
 			`${config.KotlincCmd} ${config.KotlincSuppressJDK9Warnings} ${config.JavacHeapFlags} $kotlincFlags ` +
@@ -105,6 +106,7 @@
 			`$kaptProcessor ` +
 			`-Xbuild-file=$kotlinBuildFile && ` +
 			`${config.SoongZipCmd} -jar -o $out -C $kaptDir/sources -D $kaptDir/sources && ` +
+			`${config.SoongZipCmd} -jar -o $classesJarOut -C $kaptDir/classes -D $kaptDir/classes && ` +
 			`rm -rf "$srcJarDir"`,
 		CommandDeps: []string{
 			"${config.KotlincCmd}",
@@ -118,13 +120,14 @@
 		RspfileContent: `$in`,
 	},
 	"kotlincFlags", "encodedJavacFlags", "kaptProcessorPath", "kaptProcessor",
-	"classpath", "srcJars", "srcJarDir", "kaptDir", "kotlinJvmTarget", "kotlinBuildFile", "name")
+	"classpath", "srcJars", "srcJarDir", "kaptDir", "kotlinJvmTarget", "kotlinBuildFile", "name",
+	"classesJarOut")
 
 // 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
 // added as an additional input to kotlinc and javac rules, and the javac rule should have annotation processing
 // disabled.
-func kotlinKapt(ctx android.ModuleContext, outputFile android.WritablePath,
+func kotlinKapt(ctx android.ModuleContext, srcJarOutputFile, resJarOutputFile android.WritablePath,
 	srcFiles, srcJars android.Paths,
 	flags javaBuilderFlags) {
 
@@ -152,11 +155,12 @@
 	kotlinName = strings.ReplaceAll(kotlinName, "/", "__")
 
 	ctx.Build(pctx, android.BuildParams{
-		Rule:        kapt,
-		Description: "kapt",
-		Output:      outputFile,
-		Inputs:      srcFiles,
-		Implicits:   deps,
+		Rule:           kapt,
+		Description:    "kapt",
+		Output:         srcJarOutputFile,
+		ImplicitOutput: resJarOutputFile,
+		Inputs:         srcFiles,
+		Implicits:      deps,
 		Args: map[string]string{
 			"classpath":         flags.kotlincClasspath.FormJavaClassPath("-classpath"),
 			"kotlincFlags":      flags.kotlincFlags,
@@ -168,6 +172,7 @@
 			"kaptDir":           android.PathForModuleOut(ctx, "kapt/gen").String(),
 			"encodedJavacFlags": encodedJavacFlags,
 			"name":              kotlinName,
+			"classesJarOut":     resJarOutputFile.String(),
 		},
 	})
 }
diff --git a/java/lint.go b/java/lint.go
index 441e110..fac9a19 100644
--- a/java/lint.go
+++ b/java/lint.go
@@ -42,6 +42,9 @@
 
 		// Checks that should be skipped.
 		Disabled_checks []string
+
+		// Modules that provide extra lint checks
+		Extra_check_modules []string
 	}
 }
 
@@ -76,6 +79,14 @@
 	return BoolDefault(l.properties.Lint.Enabled, true)
 }
 
+func (l *linter) deps(ctx android.BottomUpMutatorContext) {
+	if !l.enabled() {
+		return
+	}
+
+	ctx.AddFarVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), extraLintCheckTag, l.properties.Lint.Extra_check_modules...)
+}
+
 func (l *linter) writeLintProjectXML(ctx android.ModuleContext,
 	rule *android.RuleBuilder) (projectXMLPath, configXMLPath, cacheDir android.WritablePath, deps android.Paths) {
 
@@ -179,6 +190,16 @@
 		return
 	}
 
+	extraLintCheckModules := ctx.GetDirectDepsWithTag(extraLintCheckTag)
+	for _, extraLintCheckModule := range extraLintCheckModules {
+		if dep, ok := extraLintCheckModule.(Dependency); ok {
+			l.extraLintCheckJars = append(l.extraLintCheckJars, dep.ImplementationAndResourcesJars()...)
+		} else {
+			ctx.PropertyErrorf("lint.extra_check_modules",
+				"%s is not a java module", ctx.OtherModuleName(extraLintCheckModule))
+		}
+	}
+
 	rule := android.NewRuleBuilder()
 
 	if l.manifest == nil {
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 26bd670..676557e 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -1042,8 +1042,10 @@
 		return nil
 	}
 	entriesList := module.Library.AndroidMkEntries()
-	entries := &entriesList[0]
-	entries.Required = append(entries.Required, module.xmlPermissionsModuleName())
+	if module.sharedLibrary() {
+		entries := &entriesList[0]
+		entries.Required = append(entries.Required, module.xmlPermissionsModuleName())
+	}
 	return entriesList
 }
 
@@ -1088,9 +1090,12 @@
 	props := struct {
 		Name       *string
 		Visibility []string
+		Instrument bool
 	}{
 		Name:       proptools.StringPtr(module.implLibraryModuleName()),
 		Visibility: module.sdkLibraryProperties.Impl_library_visibility,
+		// Set the instrument property to ensure it is instrumented when instrumentation is required.
+		Instrument: true,
 	}
 
 	properties := []interface{}{
diff --git a/rust/library.go b/rust/library.go
index 704c77b..3c948ea 100644
--- a/rust/library.go
+++ b/rust/library.go
@@ -305,8 +305,8 @@
 
 func (library *libraryDecorator) compilerDeps(ctx DepsContext, deps Deps) Deps {
 
-	// TODO(b/144861059) Remove if C libraries support dylib linkage in the future.
-	if !ctx.Host() && (library.static() || library.shared()) {
+	// TODO(b/155498724) Remove if C static libraries no longer require libstd as an rlib dependency.
+	if !ctx.Host() && library.static() {
 		library.setNoStdlibs()
 		for _, stdlib := range config.Stdlibs {
 			deps.Rlibs = append(deps.Rlibs, stdlib+".static")
diff --git a/rust/library_test.go b/rust/library_test.go
index 37dd541..9d2f6c0 100644
--- a/rust/library_test.go
+++ b/rust/library_test.go
@@ -17,6 +17,8 @@
 import (
 	"strings"
 	"testing"
+
+	"android/soong/android"
 )
 
 // Test that variants are being generated correctly, and that crate-types are correct.
@@ -115,16 +117,24 @@
 
 }
 
-func TestSharedLibraryFlags(t *testing.T) {
+func TestSharedLibrary(t *testing.T) {
 	ctx := testRust(t, `
-		rust_library_host {
+		rust_library {
 			name: "libfoo",
 			srcs: ["foo.rs"],
 			crate_name: "foo",
 		}`)
 
-	libfooShared := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_shared").Output("libfoo.so")
-	if !strings.Contains(libfooShared.Args["linkFlags"], "-Wl,-soname=libfoo.so") {
-		t.Errorf("missing expected -Wl,-soname linker flag for libfoo shared lib, linkFlags: %#v", libfooShared.Args["linkFlags"])
+	libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared")
+
+	libfooOutput := libfoo.Output("libfoo.so")
+	if !strings.Contains(libfooOutput.Args["linkFlags"], "-Wl,-soname=libfoo.so") {
+		t.Errorf("missing expected -Wl,-soname linker flag for libfoo shared lib, linkFlags: %#v",
+			libfooOutput.Args["linkFlags"])
+	}
+
+	if !android.InList("libstd", libfoo.Module().(*Module).Properties.AndroidMkDylibs) {
+		t.Errorf("Non-static libstd dylib expected to be a dependency of Rust shared libraries. Dylib deps are: %#v",
+			libfoo.Module().(*Module).Properties.AndroidMkDylibs)
 	}
 }
diff --git a/scripts/build-mainline-modules.sh b/scripts/build-mainline-modules.sh
index df763c8..9b68a82 100755
--- a/scripts/build-mainline-modules.sh
+++ b/scripts/build-mainline-modules.sh
@@ -21,6 +21,8 @@
   conscrypt-module-host-exports
   runtime-module-sdk
   runtime-module-host-exports
+  i18n-module-test-exports
+  i18n-module-sdk
 )
 
 # We want to create apex modules for all supported architectures.