Merge "Add support for using sdk_version: "module_<ver>""
diff --git a/android/androidmk.go b/android/androidmk.go
index e90e5f0..ddd51ff 100644
--- a/android/androidmk.go
+++ b/android/androidmk.go
@@ -639,3 +639,21 @@
 		// Make does not understand LinuxBionic
 		module.Os() == LinuxBionic
 }
+
+func AndroidMkDataPaths(data []DataPath) []string {
+	var testFiles []string
+	for _, d := range data {
+		rel := d.SrcPath.Rel()
+		path := d.SrcPath.String()
+		if !strings.HasSuffix(path, rel) {
+			panic(fmt.Errorf("path %q does not end with %q", path, rel))
+		}
+		path = strings.TrimSuffix(path, rel)
+		testFileString := path + ":" + rel
+		if len(d.RelativeInstallPath) > 0 {
+			testFileString += ":" + d.RelativeInstallPath
+		}
+		testFiles = append(testFiles, testFileString)
+	}
+	return testFiles
+}
diff --git a/apex/androidmk.go b/apex/androidmk.go
index c4fe3a3..f76181d 100644
--- a/apex/androidmk.go
+++ b/apex/androidmk.go
@@ -135,7 +135,7 @@
 				}
 			}
 			if len(newDataPaths) > 0 {
-				fmt.Fprintln(w, "LOCAL_TEST_DATA :=", strings.Join(cc.AndroidMkDataPaths(newDataPaths), " "))
+				fmt.Fprintln(w, "LOCAL_TEST_DATA :=", strings.Join(android.AndroidMkDataPaths(newDataPaths), " "))
 			}
 
 			if fi.module != nil && len(fi.module.NoticeFiles()) > 0 {
diff --git a/cc/androidmk.go b/cc/androidmk.go
index f0e6152..4f149af 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -156,24 +156,6 @@
 	return []android.AndroidMkEntries{entries}
 }
 
-func AndroidMkDataPaths(data []android.DataPath) []string {
-	var testFiles []string
-	for _, d := range data {
-		rel := d.SrcPath.Rel()
-		path := d.SrcPath.String()
-		if !strings.HasSuffix(path, rel) {
-			panic(fmt.Errorf("path %q does not end with %q", path, rel))
-		}
-		path = strings.TrimSuffix(path, rel)
-		testFileString := path + ":" + rel
-		if len(d.RelativeInstallPath) > 0 {
-			testFileString += ":" + d.RelativeInstallPath
-		}
-		testFiles = append(testFiles, testFileString)
-	}
-	return testFiles
-}
-
 func androidMkWriteExtraTestConfigs(extraTestConfigs android.Paths, entries *android.AndroidMkEntries) {
 	if len(extraTestConfigs) > 0 {
 		entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
@@ -183,7 +165,7 @@
 }
 
 func androidMkWriteTestData(data []android.DataPath, ctx AndroidMkContext, entries *android.AndroidMkEntries) {
-	testFiles := AndroidMkDataPaths(data)
+	testFiles := android.AndroidMkDataPaths(data)
 	if len(testFiles) > 0 {
 		entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
 			entries.AddStrings("LOCAL_TEST_DATA", testFiles...)
diff --git a/cc/lto.go b/cc/lto.go
index acdc767..abd8dfb 100644
--- a/cc/lto.go
+++ b/cc/lto.go
@@ -45,8 +45,6 @@
 		Thin  *bool `android:"arch_variant"`
 	} `android:"arch_variant"`
 
-	GlobalThin *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"`
@@ -71,7 +69,13 @@
 	if ctx.Config().IsEnvTrue("DISABLE_LTO") {
 		lto.Properties.Lto.Never = boolPtr(true)
 	} else if ctx.Config().IsEnvTrue("GLOBAL_THINLTO") {
-		lto.Properties.GlobalThin = boolPtr(true)
+		staticLib := ctx.static() && !ctx.staticBinary()
+		hostBin := ctx.Host()
+		if !staticLib && !hostBin {
+			if !lto.Never() && !lto.FullLTO() {
+				lto.Properties.Lto.Thin = boolPtr(true)
+			}
+		}
 	}
 }
 
@@ -145,12 +149,6 @@
 }
 
 func (lto *lto) ThinLTO() bool {
-	if Bool(lto.Properties.GlobalThin) {
-		if !lto.Never() && !lto.FullLTO() {
-			return true
-		}
-	}
-
 	return Bool(lto.Properties.Lto.Thin)
 }
 
diff --git a/python/androidmk.go b/python/androidmk.go
index 247b80d..8ad5889 100644
--- a/python/androidmk.go
+++ b/python/androidmk.go
@@ -15,11 +15,12 @@
 package python
 
 import (
-	"android/soong/android"
 	"fmt"
 	"io"
 	"path/filepath"
 	"strings"
+
+	"android/soong/android"
 )
 
 type subAndroidMkProvider interface {
@@ -74,6 +75,11 @@
 		if !BoolDefault(p.binaryProperties.Auto_gen_config, true) {
 			fmt.Fprintln(w, "LOCAL_DISABLE_AUTO_GENERATE_TEST_CONFIG := true")
 		}
+
+		if len(p.data) > 0 {
+			fmt.Fprintln(w, "LOCAL_TEST_DATA :=",
+				strings.Join(android.AndroidMkDataPaths(p.data), " "))
+		}
 	})
 	base.subAndroidMk(ret, p.binaryDecorator.pythonInstaller)
 }
diff --git a/python/test.go b/python/test.go
index a669c73..434e71a 100644
--- a/python/test.go
+++ b/python/test.go
@@ -34,6 +34,10 @@
 	// the name of the test configuration template (for example "AndroidTestTemplate.xml") that
 	// should be installed with the module.
 	Test_config_template *string `android:"path,arch_variant"`
+
+	// list of files or filegroup modules that provide data that should be installed alongside
+	// the test
+	Data []string `android:"path,arch_variant"`
 }
 
 type testDecorator struct {
@@ -42,6 +46,8 @@
 	testProperties TestProperties
 
 	testConfig android.Path
+
+	data []android.DataPath
 }
 
 func (test *testDecorator) bootstrapperProps() []interface{} {
@@ -59,6 +65,12 @@
 	test.binaryDecorator.pythonInstaller.relative = ctx.ModuleName()
 
 	test.binaryDecorator.pythonInstaller.install(ctx, file)
+
+	dataSrcPaths := android.PathsForModuleSrc(ctx, test.testProperties.Data)
+
+	for _, dataSrcPath := range dataSrcPaths {
+		test.data = append(test.data, android.DataPath{SrcPath: dataSrcPath})
+	}
 }
 
 func NewTest(hod android.HostOrDeviceSupported) *Module {
diff --git a/rust/config/allowed_list.go b/rust/config/allowed_list.go
index 62d469e..483dddb 100644
--- a/rust/config/allowed_list.go
+++ b/rust/config/allowed_list.go
@@ -1,6 +1,10 @@
 package config
 
 var (
+	// When adding a new path below, add a rustfmt.toml file at the root of
+	// the repository and enable the rustfmt repo hook. See aosp/1347562
+	// for an example.
+	// TODO(b/160223496): enable rustfmt globally.
 	RustAllowedPaths = []string{
 		"external/minijail",
 		"external/rust",
diff --git a/rust/project_json.go b/rust/project_json.go
index 8310479..8d161b2 100644
--- a/rust/project_json.go
+++ b/rust/project_json.go
@@ -30,16 +30,6 @@
 //
 //   $ SOONG_GEN_RUST_PROJECT=1 m nothing
 
-func init() {
-	android.RegisterSingletonType("rust_project_generator", rustProjectGeneratorSingleton)
-}
-
-func rustProjectGeneratorSingleton() android.Singleton {
-	return &projectGeneratorSingleton{}
-}
-
-type projectGeneratorSingleton struct{}
-
 const (
 	// Environment variables used to control the behavior of this singleton.
 	envVariableCollectRustDeps = "SOONG_GEN_RUST_PROJECT"
@@ -49,6 +39,7 @@
 // The format of rust-project.json is not yet finalized. A current description is available at:
 // https://github.com/rust-analyzer/rust-analyzer/blob/master/docs/user/manual.adoc#non-cargo-based-projects
 type rustProjectDep struct {
+	// The Crate attribute is the index of the dependency in the Crates array in rustProjectJson.
 	Crate int    `json:"crate"`
 	Name  string `json:"name"`
 }
@@ -71,12 +62,50 @@
 	Deps map[string]int
 }
 
-func mergeDependencies(ctx android.SingletonContext, project *rustProjectJson,
-	knownCrates map[string]crateInfo, module android.Module,
-	crate *rustProjectCrate, deps map[string]int) {
+type projectGeneratorSingleton struct {
+	project     rustProjectJson
+	knownCrates map[string]crateInfo
+}
+
+func rustProjectGeneratorSingleton() android.Singleton {
+	return &projectGeneratorSingleton{}
+}
+
+func init() {
+	android.RegisterSingletonType("rust_project_generator", rustProjectGeneratorSingleton)
+}
+
+// librarySource finds the main source file (.rs) for a crate.
+func librarySource(ctx android.SingletonContext, rModule *Module, rustLib *libraryDecorator) (string, bool) {
+	srcs := rustLib.baseCompiler.Properties.Srcs
+	if len(srcs) != 0 {
+		return path.Join(ctx.ModuleDir(rModule), srcs[0]), true
+	}
+	if !rustLib.source() {
+		return "", false
+	}
+	// It is a SourceProvider module. If this module is host only, uses the variation for the host.
+	// Otherwise, use the variation for the primary target.
+	switch rModule.hod {
+	case android.HostSupported:
+	case android.HostSupportedNoCross:
+		if rModule.Target().String() != ctx.Config().BuildOSTarget.String() {
+			return "", false
+		}
+	default:
+		if rModule.Target().String() != ctx.Config().Targets[android.Android][0].String() {
+			return "", false
+		}
+	}
+	src := rustLib.sourceProvider.Srcs()[0]
+	return src.String(), true
+}
+
+func (singleton *projectGeneratorSingleton) mergeDependencies(ctx android.SingletonContext,
+	module android.Module, crate *rustProjectCrate, deps map[string]int) {
 
 	ctx.VisitDirectDeps(module, func(child android.Module) {
-		childId, childCrateName, ok := appendLibraryAndDeps(ctx, project, knownCrates, child)
+		childId, childCrateName, ok := singleton.appendLibraryAndDeps(ctx, child)
 		if !ok {
 			return
 		}
@@ -88,12 +117,10 @@
 	})
 }
 
-// appendLibraryAndDeps creates a rustProjectCrate for the module argument and
-// appends it to the rustProjectJson struct.  It visits the dependencies of the
-// module depth-first. If the current module is already in knownCrates, its
-// dependencies are merged. Returns a tuple (id, crate_name, ok).
-func appendLibraryAndDeps(ctx android.SingletonContext, project *rustProjectJson,
-	knownCrates map[string]crateInfo, module android.Module) (int, string, bool) {
+// appendLibraryAndDeps creates a rustProjectCrate for the module argument and appends it to singleton.project.
+// It visits the dependencies of the module depth-first so the dependency ID can be added to the current module. If the
+// current module is already in singleton.knownCrates, its dependencies are merged. Returns a tuple (id, crate_name, ok).
+func (singleton *projectGeneratorSingleton) appendLibraryAndDeps(ctx android.SingletonContext, module android.Module) (int, string, bool) {
 	rModule, ok := module.(*Module)
 	if !ok {
 		return 0, "", false
@@ -107,46 +134,45 @@
 	}
 	moduleName := ctx.ModuleName(module)
 	crateName := rModule.CrateName()
-	if cInfo, ok := knownCrates[moduleName]; ok {
+	if cInfo, ok := singleton.knownCrates[moduleName]; ok {
 		// We have seen this crate already; merge any new dependencies.
-		crate := project.Crates[cInfo.ID]
-		mergeDependencies(ctx, project, knownCrates, module, &crate, cInfo.Deps)
-		project.Crates[cInfo.ID] = crate
+		crate := singleton.project.Crates[cInfo.ID]
+		singleton.mergeDependencies(ctx, module, &crate, cInfo.Deps)
+		singleton.project.Crates[cInfo.ID] = crate
 		return cInfo.ID, crateName, true
 	}
 	crate := rustProjectCrate{Deps: make([]rustProjectDep, 0), Cfgs: make([]string, 0)}
-	srcs := rustLib.baseCompiler.Properties.Srcs
-	if len(srcs) == 0 {
+	rootModule, ok := librarySource(ctx, rModule, rustLib)
+	if !ok {
 		return 0, "", false
 	}
-	crate.RootModule = path.Join(ctx.ModuleDir(rModule), srcs[0])
+	crate.RootModule = rootModule
 	crate.Edition = rustLib.baseCompiler.edition()
 
 	deps := make(map[string]int)
-	mergeDependencies(ctx, project, knownCrates, module, &crate, deps)
+	singleton.mergeDependencies(ctx, module, &crate, deps)
 
-	id := len(project.Crates)
-	knownCrates[moduleName] = crateInfo{ID: id, Deps: deps}
-	project.Crates = append(project.Crates, crate)
+	id := len(singleton.project.Crates)
+	singleton.knownCrates[moduleName] = crateInfo{ID: id, Deps: deps}
+	singleton.project.Crates = append(singleton.project.Crates, crate)
 	// rust-analyzer requires that all crates belong to at least one root:
 	// https://github.com/rust-analyzer/rust-analyzer/issues/4735.
-	project.Roots = append(project.Roots, path.Dir(crate.RootModule))
+	singleton.project.Roots = append(singleton.project.Roots, path.Dir(crate.RootModule))
 	return id, crateName, true
 }
 
-func (r *projectGeneratorSingleton) GenerateBuildActions(ctx android.SingletonContext) {
+func (singleton *projectGeneratorSingleton) GenerateBuildActions(ctx android.SingletonContext) {
 	if !ctx.Config().IsEnvTrue(envVariableCollectRustDeps) {
 		return
 	}
 
-	project := rustProjectJson{}
-	knownCrates := make(map[string]crateInfo)
+	singleton.knownCrates = make(map[string]crateInfo)
 	ctx.VisitAllModules(func(module android.Module) {
-		appendLibraryAndDeps(ctx, &project, knownCrates, module)
+		singleton.appendLibraryAndDeps(ctx, module)
 	})
 
 	path := android.PathForOutput(ctx, rustProjectJsonFileName)
-	err := createJsonFile(project, path)
+	err := createJsonFile(singleton.project, path)
 	if err != nil {
 		ctx.Errorf(err.Error())
 	}
diff --git a/rust/project_json_test.go b/rust/project_json_test.go
index 8521940..11964f3 100644
--- a/rust/project_json_test.go
+++ b/rust/project_json_test.go
@@ -18,6 +18,7 @@
 	"encoding/json"
 	"io/ioutil"
 	"path/filepath"
+	"strings"
 	"testing"
 
 	"android/soong/android"
@@ -100,22 +101,51 @@
 	rust_library {
 		name: "liba",
 		srcs: ["src/lib.rs"],
-		rlibs: ["libbindings"],
+		rlibs: ["libbindings1"],
 		crate_name: "a"
 	}
 	rust_bindgen {
-		name: "libbindings",
-		crate_name: "bindings",
-		source_stem: "bindings",
+		name: "libbindings1",
+		crate_name: "bindings1",
+		source_stem: "bindings1",
 		host_supported: true,
 		wrapper_src: "src/any.h",
 	}
+	rust_library_host {
+		name: "libb",
+		srcs: ["src/lib.rs"],
+		rustlibs: ["libbindings2"],
+		crate_name: "b"
+	}
+	rust_bindgen_host {
+		name: "libbindings2",
+		crate_name: "bindings2",
+		source_stem: "bindings2",
+		wrapper_src: "src/any.h",
+	}
 	` + GatherRequiredDepsForTest()
 	fs := map[string][]byte{
 		"src/lib.rs": nil,
 	}
 	jsonContent := testProjectJson(t, bp, fs)
-	validateJsonCrates(t, jsonContent)
+	crates := validateJsonCrates(t, jsonContent)
+	for _, c := range crates {
+		crate, ok := c.(map[string]interface{})
+		if !ok {
+			t.Fatalf("Unexpected type for crate: %v", c)
+		}
+		rootModule, ok := crate["root_module"].(string)
+		if !ok {
+			t.Fatalf("Unexpected type for root_module: %v", crate["root_module"])
+		}
+		if strings.Contains(rootModule, "libbindings1") && !strings.Contains(rootModule, "android_arm64") {
+			t.Errorf("The source path for libbindings1 does not contain android_arm64, got %v", rootModule)
+		}
+		if strings.Contains(rootModule, "libbindings2") && !strings.Contains(rootModule, android.BuildOs.String()) {
+			t.Errorf("The source path for libbindings2 does not contain the BuildOs, got %v; want %v",
+				rootModule, android.BuildOs.String())
+		}
+	}
 }
 
 func TestProjectJsonMultiVersion(t *testing.T) {
diff --git a/rust/testing.go b/rust/testing.go
index ee303ed..42b0da1 100644
--- a/rust/testing.go
+++ b/rust/testing.go
@@ -117,6 +117,7 @@
 	ctx.RegisterModuleType("rust_binary", RustBinaryFactory)
 	ctx.RegisterModuleType("rust_binary_host", RustBinaryHostFactory)
 	ctx.RegisterModuleType("rust_bindgen", RustBindgenFactory)
+	ctx.RegisterModuleType("rust_bindgen_host", RustBindgenHostFactory)
 	ctx.RegisterModuleType("rust_test", RustTestFactory)
 	ctx.RegisterModuleType("rust_test_host", RustTestHostFactory)
 	ctx.RegisterModuleType("rust_library", RustLibraryFactory)