Merge "Expose the NDK STLs to make."
diff --git a/cc/cc.go b/cc/cc.go
index 6e28522..04aa6a6 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -1036,6 +1036,27 @@
 		ctx.ModuleErrorf("links %q built against newer API version %q",
 			ctx.OtherModuleName(to), String(to.Properties.Sdk_version))
 	}
+
+	// Also check that the two STL choices are compatible.
+	fromStl := from.stl.Properties.SelectedStl
+	toStl := to.stl.Properties.SelectedStl
+	if fromStl == "" || toStl == "" {
+		// Libraries that don't use the STL are unrestricted.
+		return
+	}
+
+	if fromStl == "ndk_system" || toStl == "ndk_system" {
+		// We can be permissive with the system "STL" since it is only the C++
+		// ABI layer, but in the future we should make sure that everyone is
+		// using either libc++ or nothing.
+		return
+	}
+
+	if getNdkStlFamily(ctx, from) != getNdkStlFamily(ctx, to) {
+		ctx.ModuleErrorf("uses %q and depends on %q which uses incompatible %q",
+			from.stl.Properties.SelectedStl, ctx.OtherModuleName(to),
+			to.stl.Properties.SelectedStl)
+	}
 }
 
 // Convert dependencies to paths.  Returns a PathDeps containing paths
diff --git a/cc/compiler.go b/cc/compiler.go
index 40dbea4..4eae898 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -522,7 +522,7 @@
 	if ctx.useSdk() {
 		// The NDK sysroot timestamp file depends on all the NDK sysroot files
 		// (headers and libraries).
-		return android.Paths{getNdkSysrootTimestampFile(ctx)}
+		return android.Paths{getNdkBaseTimestampFile(ctx)}
 	}
 	return nil
 }
diff --git a/cc/config/global.go b/cc/config/global.go
index 6f4b3e2..6de1300 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -120,17 +120,14 @@
 	ClangDefaultShortVersion = "5.0.1"
 
 	WarningAllowedProjects = []string{
-		"external/skia/",
 		"device/",
 		"vendor/",
 	}
 
 	// Some Android.mk files still have warnings.
 	WarningAllowedOldProjects = []string{
-		"frameworks/av/drm/mediacas/plugins/",
 		"hardware/libhardware/modules/",
 		"hardware/qcom/",
-		"tools/adt/idea/android/ultimate/get_modification_time/jni/",
 	}
 )
 
diff --git a/cc/library.go b/cc/library.go
index b664a5e..d53bcfc 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -733,7 +733,8 @@
 		library.baseInstaller.install(ctx, file)
 	}
 
-	if Bool(library.Properties.Static_ndk_lib) && library.static() {
+	if Bool(library.Properties.Static_ndk_lib) && library.static() &&
+		!ctx.useVndk() && ctx.Device() {
 		installPath := getNdkSysrootBase(ctx).Join(
 			ctx, "usr/lib", ctx.toolchain().ClangTriple(), file.Base())
 
diff --git a/cc/lto.go b/cc/lto.go
index fdb7688..b1e7cfa 100644
--- a/cc/lto.go
+++ b/cc/lto.go
@@ -40,10 +40,15 @@
 	// Lto must violate capitialization style for acronyms so that it can be
 	// referred to in blueprint files as "lto"
 	Lto struct {
-		Full *bool `android:"arch_variant"`
-		Thin *bool `android:"arch_variant"`
+		Never *bool `android:"arch_variant"`
+		Full  *bool `android:"arch_variant"`
+		Thin  *bool `android:"arch_variant"`
 	} `android:"arch_variant"`
-	LTODep bool `blueprint:"mutated"`
+
+	// Dep properties indicate that this module needs to be built with LTO
+	// since it is an object dependency of an LTO module.
+	FullDep bool `blueprint:"mutated"`
+	ThinDep bool `blueprint:"mutated"`
 }
 
 type lto struct {
@@ -84,7 +89,7 @@
 
 // Can be called with a null receiver
 func (lto *lto) LTO() bool {
-	if lto == nil {
+	if lto == nil || lto.Disabled() {
 		return false
 	}
 
@@ -93,41 +98,91 @@
 	return full || thin
 }
 
+// Is lto.never explicitly set to true?
+func (lto *lto) Disabled() bool {
+	return lto.Properties.Lto.Never != nil && *lto.Properties.Lto.Never
+}
+
 // Propagate lto requirements down from binaries
 func ltoDepsMutator(mctx android.TopDownMutatorContext) {
-	if c, ok := mctx.Module().(*Module); ok && c.lto.LTO() {
-		full := Bool(c.lto.Properties.Lto.Full)
-		thin := Bool(c.lto.Properties.Lto.Thin)
+	if m, ok := mctx.Module().(*Module); ok && m.lto.LTO() {
+		full := Bool(m.lto.Properties.Lto.Full)
+		thin := Bool(m.lto.Properties.Lto.Thin)
 		if full && thin {
 			mctx.PropertyErrorf("LTO", "FullLTO and ThinLTO are mutually exclusive")
 		}
 
-		mctx.VisitDepsDepthFirst(func(m android.Module) {
-			tag := mctx.OtherModuleDependencyTag(m)
+		mctx.WalkDeps(func(dep android.Module, parent android.Module) bool {
+			tag := mctx.OtherModuleDependencyTag(dep)
 			switch tag {
 			case staticDepTag, staticExportDepTag, lateStaticDepTag, wholeStaticDepTag, objDepTag, reuseObjTag:
-				if cc, ok := m.(*Module); ok && cc.lto != nil {
-					cc.lto.Properties.LTODep = true
+				if dep, ok := dep.(*Module); ok && dep.lto != nil &&
+					!dep.lto.Disabled() {
+					if full && !Bool(dep.lto.Properties.Lto.Full) {
+						dep.lto.Properties.FullDep = true
+					}
+					if thin && !Bool(dep.lto.Properties.Lto.Thin) {
+						dep.lto.Properties.ThinDep = true
+					}
 				}
+
+				// Recursively walk static dependencies
+				return true
 			}
+
+			// Do not recurse down non-static dependencies
+			return false
 		})
 	}
 }
 
 // Create lto variants for modules that need them
 func ltoMutator(mctx android.BottomUpMutatorContext) {
-	if c, ok := mctx.Module().(*Module); ok && c.lto != nil {
-		if c.lto.LTO() {
-			mctx.SetDependencyVariation("lto")
-		} else if c.lto.Properties.LTODep {
-			modules := mctx.CreateVariations("", "lto")
-			modules[0].(*Module).lto.Properties.Lto.Full = boolPtr(false)
-			modules[0].(*Module).lto.Properties.Lto.Thin = boolPtr(false)
-			modules[0].(*Module).lto.Properties.LTODep = false
-			modules[1].(*Module).lto.Properties.LTODep = false
-			modules[1].(*Module).Properties.PreventInstall = true
-			modules[1].(*Module).Properties.HideFromMake = true
+	if m, ok := mctx.Module().(*Module); ok && m.lto != nil {
+		// Create variations for LTO types required as static
+		// dependencies
+		variationNames := []string{""}
+		if m.lto.Properties.FullDep && !Bool(m.lto.Properties.Lto.Full) {
+			variationNames = append(variationNames, "lto-full")
 		}
-		c.lto.Properties.LTODep = false
+		if m.lto.Properties.ThinDep && !Bool(m.lto.Properties.Lto.Thin) {
+			variationNames = append(variationNames, "lto-thin")
+		}
+
+		// Use correct dependencies if LTO property is explicitly set
+		// (mutually exclusive)
+		if Bool(m.lto.Properties.Lto.Full) {
+			mctx.SetDependencyVariation("lto-full")
+		}
+		if Bool(m.lto.Properties.Lto.Thin) {
+			mctx.SetDependencyVariation("lto-thin")
+		}
+
+		if len(variationNames) > 1 {
+			modules := mctx.CreateVariations(variationNames...)
+			for i, name := range variationNames {
+				variation := modules[i].(*Module)
+				// Default module which will be
+				// installed. Variation set above according to
+				// explicit LTO properties
+				if name == "" {
+					continue
+				}
+
+				// LTO properties for dependencies
+				if name == "lto-full" {
+					variation.lto.Properties.Lto.Full = boolPtr(true)
+					variation.lto.Properties.Lto.Thin = boolPtr(false)
+				}
+				if name == "lto-thin" {
+					variation.lto.Properties.Lto.Full = boolPtr(false)
+					variation.lto.Properties.Lto.Thin = boolPtr(true)
+				}
+				variation.Properties.PreventInstall = true
+				variation.Properties.HideFromMake = true
+				variation.lto.Properties.FullDep = false
+				variation.lto.Properties.ThinDep = false
+			}
+		}
 	}
 }
diff --git a/cc/ndk_sysroot.go b/cc/ndk_sysroot.go
index 4324458..c7ba588 100644
--- a/cc/ndk_sysroot.go
+++ b/cc/ndk_sysroot.go
@@ -74,7 +74,16 @@
 	return getNdkInstallBase(ctx).Join(ctx, "sysroot")
 }
 
-func getNdkSysrootTimestampFile(ctx android.PathContext) android.WritablePath {
+// The base timestamp file depends on the NDK headers and stub shared libraries,
+// but not the static libraries. This distinction is needed because the static
+// libraries themselves might need to depend on the base sysroot.
+func getNdkBaseTimestampFile(ctx android.PathContext) android.WritablePath {
+	return android.PathForOutput(ctx, "ndk_base.timestamp")
+}
+
+// The full timestamp file depends on the base timestamp *and* the static
+// libraries.
+func getNdkFullTimestampFile(ctx android.PathContext) android.WritablePath {
 	return android.PathForOutput(ctx, "ndk.timestamp")
 }
 
@@ -85,6 +94,7 @@
 type ndkSingleton struct{}
 
 func (n *ndkSingleton) GenerateBuildActions(ctx android.SingletonContext) {
+	var staticLibInstallPaths android.Paths
 	var installPaths android.Paths
 	var licensePaths android.Paths
 	ctx.VisitAllModules(func(module android.Module) {
@@ -109,7 +119,8 @@
 
 			if library, ok := m.linker.(*libraryDecorator); ok {
 				if library.ndkSysrootPath != nil {
-					installPaths = append(installPaths, library.ndkSysrootPath)
+					staticLibInstallPaths = append(
+						staticLibInstallPaths, library.ndkSysrootPath)
 				}
 			}
 		}
@@ -123,13 +134,21 @@
 		Inputs:      licensePaths,
 	})
 
-	depPaths := append(installPaths, combinedLicense)
+	baseDepPaths := append(installPaths, combinedLicense)
 
 	// There's a dummy "ndk" rule defined in ndk/Android.mk that depends on
 	// this. `m ndk` will build the sysroots.
 	ctx.Build(pctx, android.BuildParams{
 		Rule:      android.Touch,
-		Output:    getNdkSysrootTimestampFile(ctx),
-		Implicits: depPaths,
+		Output:    getNdkBaseTimestampFile(ctx),
+		Implicits: baseDepPaths,
+	})
+
+	fullDepPaths := append(staticLibInstallPaths, getNdkBaseTimestampFile(ctx))
+
+	ctx.Build(pctx, android.BuildParams{
+		Rule:      android.Touch,
+		Output:    getNdkFullTimestampFile(ctx),
+		Implicits: fullDepPaths,
 	})
 }
diff --git a/cc/pgo.go b/cc/pgo.go
index 9fea154..fef962e 100644
--- a/cc/pgo.go
+++ b/cc/pgo.go
@@ -42,6 +42,9 @@
 		Profile_file       *string `android:"arch_variant"`
 		Benchmarks         []string
 		Enable_profile_use *bool `android:"arch_variant"`
+		// Additional compiler flags to use when building this module
+		// for profiling (either instrumentation or sampling).
+		Cflags []string `android:"arch_variant"`
 	} `android:"arch_variant"`
 
 	PgoPresent          bool `blueprint:"mutated"`
@@ -65,6 +68,8 @@
 }
 
 func (props *PgoProperties) addProfileGatherFlags(ctx ModuleContext, flags Flags) Flags {
+	flags.CFlags = append(flags.CFlags, props.Pgo.Cflags...)
+
 	if props.isInstrumentation() {
 		flags.CFlags = append(flags.CFlags, profileInstrumentFlag)
 		// The profile runtime is added below in deps().  Add the below
diff --git a/cc/stl.go b/cc/stl.go
index 347db99..338db84 100644
--- a/cc/stl.go
+++ b/cc/stl.go
@@ -19,6 +19,25 @@
 	"fmt"
 )
 
+func getNdkStlFamily(ctx android.ModuleContext, m *Module) string {
+	stl := m.stl.Properties.SelectedStl
+	switch stl {
+	case "ndk_libc++_shared", "ndk_libc++_static":
+		return "libc++"
+	case "ndk_libstlport_shared", "ndk_libstlport_static":
+		return "stlport"
+	case "ndk_libgnustl_static":
+		return "gnustl"
+	case "ndk_system":
+		return "system"
+	case "":
+		return "none"
+	default:
+		ctx.ModuleErrorf("stl: %q is not a valid STL", stl)
+		return ""
+	}
+}
+
 type StlProperties struct {
 	// select the STL library to use.  Possible values are "libc++", "libc++_static",
 	// "stlport", "stlport_static", "ndk", "libstdc++", or "none".  Leave blank to select the
diff --git a/cc/tidy.go b/cc/tidy.go
index 6d7c957..67fd3db 100644
--- a/cc/tidy.go
+++ b/cc/tidy.go
@@ -77,6 +77,11 @@
 		flags.TidyFlags = append(flags.TidyFlags, headerFilter)
 	}
 
+	// If clang-tidy is not enabled globally, add the -quiet flag.
+	if !ctx.Config().ClangTidy() {
+		flags.TidyFlags = append(flags.TidyFlags, "-quiet")
+	}
+
 	// We might be using the static analyzer through clang tidy.
 	// https://bugs.llvm.org/show_bug.cgi?id=32914
 	flags.TidyFlags = append(flags.TidyFlags, "-extra-arg-before=-D__clang_analyzer__")
diff --git a/java/androidmk.go b/java/androidmk.go
index 40ebe5b..24fe43a 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -156,6 +156,12 @@
 				if app.dexJarFile != nil {
 					fmt.Fprintln(w, "LOCAL_SOONG_DEX_JAR :=", app.dexJarFile.String())
 				}
+				if app.implementationJarFile != nil {
+					fmt.Fprintln(w, "LOCAL_SOONG_CLASSES_JAR :=", app.implementationJarFile)
+				}
+				if app.headerJarFile != nil {
+					fmt.Fprintln(w, "LOCAL_SOONG_HEADER_JAR :=", app.headerJarFile.String())
+				}
 				if app.jacocoReportClassesFile != nil {
 					fmt.Fprintln(w, "LOCAL_SOONG_JACOCO_REPORT_CLASSES_JAR :=", app.jacocoReportClassesFile.String())
 				}
diff --git a/java/builder.go b/java/builder.go
index 48fba23..ff618d8 100644
--- a/java/builder.go
+++ b/java/builder.go
@@ -214,11 +214,15 @@
 	inputs := append(android.Paths(nil), srcFiles...)
 	inputs = append(inputs, srcJars...)
 
+	var deps android.Paths
+	deps = append(deps, flags.kotlincClasspath...)
+
 	ctx.Build(pctx, android.BuildParams{
 		Rule:        kotlinc,
 		Description: "kotlinc",
 		Output:      outputFile,
 		Inputs:      inputs,
+		Implicits:   deps,
 		Args: map[string]string{
 			"classpath":    flags.kotlincClasspath.FormJavaClassPath("-classpath"),
 			"kotlincFlags": flags.kotlincFlags,
diff --git a/java/java.go b/java/java.go
index d9075b1..9b345fd 100644
--- a/java/java.go
+++ b/java/java.go
@@ -142,6 +142,11 @@
 		Exclude_filter []string
 	}
 
+	Proto struct {
+		// List of extra options that will be passed to the proto generator.
+		Output_params []string
+	}
+
 	Instrument bool `blueprint:"mutated"`
 }
 
@@ -620,7 +625,7 @@
 	}
 	srcFiles := ctx.ExpandSources(j.properties.Srcs, j.properties.Exclude_srcs)
 	if hasSrcExt(srcFiles.Strings(), ".proto") {
-		flags = protoFlags(ctx, &j.protoProperties, flags)
+		flags = protoFlags(ctx, &j.properties, &j.protoProperties, flags)
 	}
 
 	srcFiles = j.genSources(ctx, srcFiles, flags)
diff --git a/java/java_test.go b/java/java_test.go
index 78fbd41..84fe903 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -705,43 +705,61 @@
 	ctx := testJava(t, `
 		java_library {
 			name: "foo",
-                        srcs: ["a.java", "b.kt"],
+			srcs: ["a.java", "b.kt"],
 		}
 
 		java_library {
 			name: "bar",
-                        srcs: ["b.kt"],
+			srcs: ["b.kt"],
+			libs: ["foo"],
+			static_libs: ["baz"],
+		}
+
+		java_library {
+			name: "baz",
+			srcs: ["c.java"],
 		}
 		`)
 
-	kotlinc := ctx.ModuleForTests("foo", "android_common").Rule("kotlinc")
-	javac := ctx.ModuleForTests("foo", "android_common").Rule("javac")
-	jar := ctx.ModuleForTests("foo", "android_common").Output("combined/foo.jar")
+	fooKotlinc := ctx.ModuleForTests("foo", "android_common").Rule("kotlinc")
+	fooJavac := ctx.ModuleForTests("foo", "android_common").Rule("javac")
+	fooJar := ctx.ModuleForTests("foo", "android_common").Output("combined/foo.jar")
 
-	if len(kotlinc.Inputs) != 2 || kotlinc.Inputs[0].String() != "a.java" ||
-		kotlinc.Inputs[1].String() != "b.kt" {
-		t.Errorf(`foo kotlinc inputs %v != ["a.java", "b.kt"]`, kotlinc.Inputs)
+	if len(fooKotlinc.Inputs) != 2 || fooKotlinc.Inputs[0].String() != "a.java" ||
+		fooKotlinc.Inputs[1].String() != "b.kt" {
+		t.Errorf(`foo kotlinc inputs %v != ["a.java", "b.kt"]`, fooKotlinc.Inputs)
 	}
 
-	if len(javac.Inputs) != 1 || javac.Inputs[0].String() != "a.java" {
-		t.Errorf(`foo inputs %v != ["a.java"]`, javac.Inputs)
+	if len(fooJavac.Inputs) != 1 || fooJavac.Inputs[0].String() != "a.java" {
+		t.Errorf(`foo inputs %v != ["a.java"]`, fooJavac.Inputs)
 	}
 
-	if !strings.Contains(javac.Args["classpath"], kotlinc.Output.String()) {
+	if !strings.Contains(fooJavac.Args["classpath"], fooKotlinc.Output.String()) {
 		t.Errorf("foo classpath %v does not contain %q",
-			javac.Args["classpath"], kotlinc.Output.String())
+			fooJavac.Args["classpath"], fooKotlinc.Output.String())
 	}
 
-	if !inList(kotlinc.Output.String(), jar.Inputs.Strings()) {
+	if !inList(fooKotlinc.Output.String(), fooJar.Inputs.Strings()) {
 		t.Errorf("foo jar inputs %v does not contain %q",
-			jar.Inputs.Strings(), kotlinc.Output.String())
+			fooJar.Inputs.Strings(), fooKotlinc.Output.String())
 	}
 
-	kotlinc = ctx.ModuleForTests("bar", "android_common").Rule("kotlinc")
-	jar = ctx.ModuleForTests("bar", "android_common").Output("combined/bar.jar")
+	fooHeaderJar := ctx.ModuleForTests("foo", "android_common").Output("turbine-combined/foo.jar")
+	bazHeaderJar := ctx.ModuleForTests("baz", "android_common").Output("turbine-combined/baz.jar")
+	barKotlinc := ctx.ModuleForTests("bar", "android_common").Rule("kotlinc")
 
-	if len(kotlinc.Inputs) != 1 || kotlinc.Inputs[0].String() != "b.kt" {
-		t.Errorf(`bar kotlinc inputs %v != ["b.kt"]`, kotlinc.Inputs)
+	if len(barKotlinc.Inputs) != 1 || barKotlinc.Inputs[0].String() != "b.kt" {
+		t.Errorf(`bar kotlinc inputs %v != ["b.kt"]`, barKotlinc.Inputs)
+	}
+
+	if !inList(fooHeaderJar.Output.String(), barKotlinc.Implicits.Strings()) {
+		t.Errorf(`expected %q in bar implicits %v`,
+			fooHeaderJar.Output.String(), barKotlinc.Implicits.Strings())
+	}
+
+	if !inList(bazHeaderJar.Output.String(), barKotlinc.Implicits.Strings()) {
+		t.Errorf(`expected %q in bar implicits %v`,
+			bazHeaderJar.Output.String(), barKotlinc.Implicits.Strings())
 	}
 }
 
@@ -754,7 +772,7 @@
 
 		java_library {
 			name: "bar",
-                        srcs: ["b.java"],
+			srcs: ["b.java"],
 			static_libs: ["foo"],
 		}
 
diff --git a/java/proto.go b/java/proto.go
index 428413f..226fac0 100644
--- a/java/proto.go
+++ b/java/proto.go
@@ -77,7 +77,9 @@
 	}
 }
 
-func protoFlags(ctx android.ModuleContext, p *android.ProtoProperties, flags javaBuilderFlags) javaBuilderFlags {
+func protoFlags(ctx android.ModuleContext, j *CompilerProperties, p *android.ProtoProperties,
+	flags javaBuilderFlags) javaBuilderFlags {
+
 	switch proptools.String(p.Proto.Type) {
 	case "micro":
 		flags.protoOutTypeFlag = "--javamicro_out"
@@ -93,6 +95,13 @@
 			proptools.String(p.Proto.Type))
 	}
 
+	if len(j.Proto.Output_params) > 0 {
+		if flags.protoOutParams != "" {
+			flags.protoOutParams += ","
+		}
+		flags.protoOutParams += strings.Join(j.Proto.Output_params, ",")
+	}
+
 	flags.protoFlags = android.ProtoFlags(ctx, p)
 
 	return flags