Merge changes Ie51f097e,Ibf26da14

* changes:
  Use apex and jar to select boot image dex jar
  Ensure that only one dex jar is chosen for each boot image library
diff --git a/androidmk/parser/make_strings.go b/androidmk/parser/make_strings.go
index 4b782a2..3c4815e 100644
--- a/androidmk/parser/make_strings.go
+++ b/androidmk/parser/make_strings.go
@@ -15,8 +15,10 @@
 package parser
 
 import (
+	"fmt"
 	"strings"
 	"unicode"
+	"unicode/utf8"
 )
 
 // A MakeString is a string that may contain variable substitutions in it.
@@ -130,8 +132,85 @@
 	})
 }
 
+// Words splits MakeString into multiple makeStrings separated by whitespace.
+// Thus, " a $(X)b  c " will be split into ["a", "$(X)b", "c"].
+// Splitting a MakeString consisting solely of whitespace yields empty array.
 func (ms *MakeString) Words() []*MakeString {
-	return ms.splitNFunc(-1, splitWords)
+	var ch rune    // current character
+	const EOF = -1 // no more characters
+	const EOS = -2 // at the end of a string chunk
+
+	// Next character's chunk and position
+	iString := 0
+	iChar := 0
+
+	var words []*MakeString
+	word := SimpleMakeString("", ms.Pos())
+
+	nextChar := func() {
+		if iString >= len(ms.Strings) {
+			ch = EOF
+		} else if iChar >= len(ms.Strings[iString]) {
+			iString++
+			iChar = 0
+			ch = EOS
+		} else {
+			var w int
+			ch, w = utf8.DecodeRuneInString(ms.Strings[iString][iChar:])
+			iChar += w
+		}
+	}
+
+	appendVariableAndAdvance := func() {
+		if iString-1 < len(ms.Variables) {
+			word.appendVariable(ms.Variables[iString-1])
+		}
+		nextChar()
+	}
+
+	appendCharAndAdvance := func(c rune) {
+		if c != EOF {
+			word.appendString(string(c))
+		}
+		nextChar()
+	}
+
+	nextChar()
+	for ch != EOF {
+		// Skip whitespace
+		for ch == ' ' || ch == '\t' {
+			nextChar()
+		}
+		if ch == EOS {
+			// "... $(X)... " case. The current word should be empty.
+			if !word.Empty() {
+				panic(fmt.Errorf("%q: EOS while current word %q is not empty, iString=%d",
+					ms.Dump(), word.Dump(), iString))
+			}
+			appendVariableAndAdvance()
+		}
+		// Copy word
+		for ch != EOF {
+			if ch == ' ' || ch == '\t' {
+				words = append(words, word)
+				word = SimpleMakeString("", ms.Pos())
+				break
+			}
+			if ch == EOS {
+				// "...a$(X)..." case. Append variable to the current word
+				appendVariableAndAdvance()
+			} else {
+				if ch == '\\' {
+					appendCharAndAdvance('\\')
+				}
+				appendCharAndAdvance(ch)
+			}
+		}
+	}
+	if !word.Empty() {
+		words = append(words, word)
+	}
+	return words
 }
 
 func (ms *MakeString) splitNFunc(n int, splitFunc func(s string, n int) []string) []*MakeString {
@@ -166,9 +245,7 @@
 		}
 	}
 
-	if !curMs.Empty() {
-		ret = append(ret, curMs)
-	}
+	ret = append(ret, curMs)
 	return ret
 }
 
@@ -219,44 +296,6 @@
 	return ret
 }
 
-func splitWords(s string, n int) []string {
-	ret := []string{}
-	preserve := ""
-	for n == -1 || n > 1 {
-		index := strings.IndexAny(s, " \t")
-		if index == 0 && len(preserve) == 0 {
-			s = s[1:]
-		} else if index >= 0 {
-			escapeCount := 0
-			for i := index - 1; i >= 0; i-- {
-				if s[i] != '\\' {
-					break
-				}
-				escapeCount += 1
-			}
-
-			if escapeCount%2 == 1 {
-				preserve += s[0 : index+1]
-				s = s[index+1:]
-				continue
-			}
-
-			ret = append(ret, preserve+s[0:index])
-			s = s[index+1:]
-			preserve = ""
-			if n > 0 {
-				n--
-			}
-		} else {
-			break
-		}
-	}
-	if preserve != "" || s != "" || len(ret) == 0 {
-		ret = append(ret, preserve+s)
-	}
-	return ret
-}
-
 func unescape(s string) string {
 	ret := ""
 	for {
diff --git a/androidmk/parser/make_strings_test.go b/androidmk/parser/make_strings_test.go
index 6995e89..fbb289b 100644
--- a/androidmk/parser/make_strings_test.go
+++ b/androidmk/parser/make_strings_test.go
@@ -26,64 +26,53 @@
 	n        int
 }{
 	{
-		in: &MakeString{
-			Strings: []string{
-				"a b c",
-				"d e f",
-				" h i j",
-			},
-			Variables: []Variable{
-				Variable{Name: SimpleMakeString("var1", NoPos)},
-				Variable{Name: SimpleMakeString("var2", NoPos)},
-			},
-		},
+		// "a b c$(var1)d e f$(var2) h i j"
+		in:  genMakeString("a b c", "var1", "d e f", "var2", " h i j"),
 		sep: " ",
 		n:   -1,
 		expected: []*MakeString{
-			SimpleMakeString("a", NoPos),
-			SimpleMakeString("b", NoPos),
-			&MakeString{
-				Strings: []string{"c", "d"},
-				Variables: []Variable{
-					Variable{Name: SimpleMakeString("var1", NoPos)},
-				},
-			},
-			SimpleMakeString("e", NoPos),
-			&MakeString{
-				Strings: []string{"f", ""},
-				Variables: []Variable{
-					Variable{Name: SimpleMakeString("var2", NoPos)},
-				},
-			},
-			SimpleMakeString("h", NoPos),
-			SimpleMakeString("i", NoPos),
-			SimpleMakeString("j", NoPos),
+			genMakeString("a"),
+			genMakeString("b"),
+			genMakeString("c", "var1", "d"),
+			genMakeString("e"),
+			genMakeString("f", "var2", ""),
+			genMakeString("h"),
+			genMakeString("i"),
+			genMakeString("j"),
 		},
 	},
 	{
-		in: &MakeString{
-			Strings: []string{
-				"a b c",
-				"d e f",
-				" h i j",
-			},
-			Variables: []Variable{
-				Variable{Name: SimpleMakeString("var1", NoPos)},
-				Variable{Name: SimpleMakeString("var2", NoPos)},
-			},
-		},
+		// "a b c$(var1)d e f$(var2) h i j"
+		in:  genMakeString("a b c", "var1", "d e f", "var2", " h i j"),
 		sep: " ",
 		n:   3,
 		expected: []*MakeString{
-			SimpleMakeString("a", NoPos),
-			SimpleMakeString("b", NoPos),
-			&MakeString{
-				Strings: []string{"c", "d e f", " h i j"},
-				Variables: []Variable{
-					Variable{Name: SimpleMakeString("var1", NoPos)},
-					Variable{Name: SimpleMakeString("var2", NoPos)},
-				},
-			},
+			genMakeString("a"),
+			genMakeString("b"),
+			genMakeString("c", "var1", "d e f", "var2", " h i j"),
+		},
+	},
+	{
+		// "$(var1) $(var2)"
+		in:  genMakeString("", "var1", " ", "var2", ""),
+		sep: " ",
+		n:   -1,
+		expected: []*MakeString{
+			genMakeString("", "var1", ""),
+			genMakeString("", "var2", ""),
+		},
+	},
+	{
+		// "a,,b,c,"
+		in:  genMakeString("a,,b,c,"),
+		sep: ",",
+		n:   -1,
+		expected: []*MakeString{
+			genMakeString("a"),
+			genMakeString(""),
+			genMakeString("b"),
+			genMakeString("c"),
+			genMakeString(""),
 		},
 	},
 }
@@ -104,15 +93,15 @@
 	expected string
 }{
 	{
-		in:       SimpleMakeString("a b", NoPos),
+		in:       genMakeString("a b"),
 		expected: "a b",
 	},
 	{
-		in:       SimpleMakeString("a\\ \\\tb\\\\", NoPos),
+		in:       genMakeString("a\\ \\\tb\\\\"),
 		expected: "a \tb\\",
 	},
 	{
-		in:       SimpleMakeString("a\\b\\", NoPos),
+		in:       genMakeString("a\\b\\"),
 		expected: "a\\b\\",
 	},
 }
@@ -131,31 +120,88 @@
 	expected []*MakeString
 }{
 	{
-		in:       SimpleMakeString("", NoPos),
+		in:       genMakeString(""),
 		expected: []*MakeString{},
 	},
 	{
-		in: SimpleMakeString(" a b\\ c d", NoPos),
+		in: genMakeString(` a b\ c d`),
 		expected: []*MakeString{
-			SimpleMakeString("a", NoPos),
-			SimpleMakeString("b\\ c", NoPos),
-			SimpleMakeString("d", NoPos),
+			genMakeString("a"),
+			genMakeString(`b\ c`),
+			genMakeString("d"),
 		},
 	},
 	{
-		in: SimpleMakeString("  a\tb\\\t\\ c d  ", NoPos),
+		in: SimpleMakeString("  a\tb"+`\`+"\t"+`\ c d  `, NoPos),
 		expected: []*MakeString{
-			SimpleMakeString("a", NoPos),
-			SimpleMakeString("b\\\t\\ c", NoPos),
-			SimpleMakeString("d", NoPos),
+			genMakeString("a"),
+			genMakeString("b" + `\` + "\t" + `\ c`),
+			genMakeString("d"),
 		},
 	},
 	{
-		in: SimpleMakeString(`a\\ b\\\ c d`, NoPos),
+		in: genMakeString(`a\\ b\\\ c d`),
 		expected: []*MakeString{
-			SimpleMakeString(`a\\`, NoPos),
-			SimpleMakeString(`b\\\ c`, NoPos),
-			SimpleMakeString("d", NoPos),
+			genMakeString(`a\\`),
+			genMakeString(`b\\\ c`),
+			genMakeString("d"),
+		},
+	},
+	{
+		in: genMakeString(`\\ a`),
+		expected: []*MakeString{
+			genMakeString(`\\`),
+			genMakeString("a"),
+		},
+	},
+	{
+		// "  "
+		in: &MakeString{
+			Strings:   []string{" \t \t"},
+			Variables: nil,
+		},
+		expected: []*MakeString{},
+	},
+	{
+		// " a $(X)b c "
+		in: genMakeString(" a ", "X", "b c "),
+		expected: []*MakeString{
+			genMakeString("a"),
+			genMakeString("", "X", "b"),
+			genMakeString("c"),
+		},
+	},
+	{
+		// " a b$(X)c d"
+		in: genMakeString(" a b", "X", "c d"),
+		expected: []*MakeString{
+			genMakeString("a"),
+			genMakeString("b", "X", "c"),
+			genMakeString("d"),
+		},
+	},
+	{
+		// "$(X) $(Y)"
+		in: genMakeString("", "X", " ", "Y", ""),
+		expected: []*MakeString{
+			genMakeString("", "X", ""),
+			genMakeString("", "Y", ""),
+		},
+	},
+	{
+		// " a$(X) b"
+		in: genMakeString(" a", "X", " b"),
+		expected: []*MakeString{
+			genMakeString("a", "X", ""),
+			genMakeString("b"),
+		},
+	},
+	{
+		// "a$(X) b$(Y) "
+		in: genMakeString("a", "X", " b", "Y", " "),
+		expected: []*MakeString{
+			genMakeString("a", "X", ""),
+			genMakeString("b", "Y", ""),
 		},
 	},
 }
@@ -180,3 +226,20 @@
 
 	return strings.Join(ret, "|||")
 }
+
+// generates MakeString from alternating string chunks and variable names,
+// e.g., genMakeString("a", "X", "b") returns MakeString for "a$(X)b"
+func genMakeString(items ...string) *MakeString {
+	n := len(items) / 2
+	if len(items) != (2*n + 1) {
+		panic("genMakeString expects odd number of arguments")
+	}
+
+	ms := &MakeString{Strings: make([]string, n+1), Variables: make([]Variable, n)}
+	ms.Strings[0] = items[0]
+	for i := 1; i <= n; i++ {
+		ms.Variables[i-1] = Variable{Name: SimpleMakeString(items[2*i-1], NoPos)}
+		ms.Strings[i] = items[2*i]
+	}
+	return ms
+}
diff --git a/apex/allowed_deps.txt b/apex/allowed_deps.txt
index 5b8563d..b416d31 100644
--- a/apex/allowed_deps.txt
+++ b/apex/allowed_deps.txt
@@ -333,6 +333,7 @@
 libminijail_gen_syscall_obj(minSdkVersion:29)
 libminijail_generated(minSdkVersion:29)
 libmkvextractor(minSdkVersion:29)
+libmodules-utils-build(minSdkVersion:29)
 libmp3extractor(minSdkVersion:29)
 libmp4extractor(minSdkVersion:29)
 libmpeg2dec(minSdkVersion:29)
diff --git a/cmd/soong_build/writedocs.go b/cmd/soong_build/writedocs.go
index 5fb6e6b..253979e 100644
--- a/cmd/soong_build/writedocs.go
+++ b/cmd/soong_build/writedocs.go
@@ -44,9 +44,10 @@
 	"name":             0,
 	"src":              1,
 	"srcs":             2,
-	"defaults":         3,
-	"host_supported":   4,
-	"device_supported": 5,
+	"exclude_srcs":     3,
+	"defaults":         4,
+	"host_supported":   5,
+	"device_supported": 6,
 }
 
 // For each module type, extract its documentation and convert it to the template data.
diff --git a/rust/project_json.go b/rust/project_json.go
index c4d60ad..32ce6f4 100644
--- a/rust/project_json.go
+++ b/rust/project_json.go
@@ -45,10 +45,11 @@
 }
 
 type rustProjectCrate struct {
-	RootModule string           `json:"root_module"`
-	Edition    string           `json:"edition,omitempty"`
-	Deps       []rustProjectDep `json:"deps"`
-	Cfgs       []string         `json:"cfgs"`
+	DisplayName string           `json:"display_name"`
+	RootModule  string           `json:"root_module"`
+	Edition     string           `json:"edition,omitempty"`
+	Deps        []rustProjectDep `json:"deps"`
+	Cfgs        []string         `json:"cfgs"`
 }
 
 type rustProjectJson struct {
@@ -58,13 +59,13 @@
 
 // crateInfo is used during the processing to keep track of the known crates.
 type crateInfo struct {
-	ID   int
-	Deps map[string]int
+	Idx  int            // Index of the crate in rustProjectJson.Crates slice.
+	Deps map[string]int // The keys are the module names and not the crate names.
 }
 
 type projectGeneratorSingleton struct {
 	project     rustProjectJson
-	knownCrates map[string]crateInfo
+	knownCrates map[string]crateInfo // Keys are module names.
 }
 
 func rustProjectGeneratorSingleton() android.Singleton {
@@ -75,66 +76,129 @@
 	android.RegisterSingletonType("rust_project_generator", rustProjectGeneratorSingleton)
 }
 
-// crateSource finds the main source file (.rs) for a crate.
-func crateSource(ctx android.SingletonContext, rModule *Module, comp *baseCompiler) (string, bool) {
-	srcs := comp.Properties.Srcs
-	if len(srcs) != 0 {
-		return path.Join(ctx.ModuleDir(rModule), srcs[0]), true
-	}
+// sourceProviderVariantSource returns the path to the source file if this
+// module variant should be used as a priority.
+//
+// SourceProvider modules may have multiple variants considered as source
+// (e.g., x86_64 and armv8). For a module available on device, use the source
+// generated for the target. For a host-only module, use the source generated
+// for the host.
+func sourceProviderVariantSource(ctx android.SingletonContext, rModule *Module) (string, bool) {
 	rustLib, ok := rModule.compiler.(*libraryDecorator)
 	if !ok {
 		return "", false
 	}
-	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().AndroidFirstDeviceTarget.String() {
-			return "", false
+	if rustLib.source() {
+		switch rModule.hod {
+		case android.HostSupported, android.HostSupportedNoCross:
+			if rModule.Target().String() == ctx.Config().BuildOSTarget.String() {
+				src := rustLib.sourceProvider.Srcs()[0]
+				return src.String(), true
+			}
+		default:
+			if rModule.Target().String() == ctx.Config().AndroidFirstDeviceTarget.String() {
+				src := rustLib.sourceProvider.Srcs()[0]
+				return src.String(), true
+			}
 		}
 	}
-	src := rustLib.sourceProvider.Srcs()[0]
-	return src.String(), true
+	return "", false
 }
 
-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 := singleton.appendLibraryAndDeps(ctx, child)
-		if !ok {
+// sourceProviderSource finds the main source file of a source-provider crate.
+func sourceProviderSource(ctx android.SingletonContext, rModule *Module) (string, bool) {
+	rustLib, ok := rModule.compiler.(*libraryDecorator)
+	if !ok {
+		return "", false
+	}
+	if rustLib.source() {
+		// This is a source-variant, check if we are the right variant
+		// depending on the module configuration.
+		if src, ok := sourceProviderVariantSource(ctx, rModule); ok {
+			return src, true
+		}
+	}
+	foundSource := false
+	sourceSrc := ""
+	// Find the variant with the source and return its.
+	ctx.VisitAllModuleVariants(rModule, func(variant android.Module) {
+		if foundSource {
 			return
 		}
+		// All variants of a source provider library are libraries.
+		rVariant, _ := variant.(*Module)
+		variantLib, _ := rVariant.compiler.(*libraryDecorator)
+		if variantLib.source() {
+			sourceSrc, ok = sourceProviderVariantSource(ctx, rVariant)
+			if ok {
+				foundSource = true
+			}
+		}
+	})
+	if !foundSource {
+		fmt.Errorf("No valid source for source provider found: %v\n", rModule)
+	}
+	return sourceSrc, foundSource
+}
+
+// crateSource finds the main source file (.rs) for a crate.
+func crateSource(ctx android.SingletonContext, rModule *Module, comp *baseCompiler) (string, bool) {
+	// Basic libraries, executables and tests.
+	srcs := comp.Properties.Srcs
+	if len(srcs) != 0 {
+		return path.Join(ctx.ModuleDir(rModule), srcs[0]), true
+	}
+	// SourceProvider libraries.
+	if rModule.sourceProvider != nil {
+		return sourceProviderSource(ctx, rModule)
+	}
+	return "", false
+}
+
+// mergeDependencies visits all the dependencies for module and updates crate and deps
+// with any new dependency.
+func (singleton *projectGeneratorSingleton) mergeDependencies(ctx android.SingletonContext,
+	module *Module, crate *rustProjectCrate, deps map[string]int) {
+
+	ctx.VisitDirectDeps(module, func(child android.Module) {
 		// Skip intra-module dependencies (i.e., generated-source library depending on the source variant).
 		if module.Name() == child.Name() {
 			return
 		}
-		if _, ok = deps[ctx.ModuleName(child)]; ok {
+		// Skip unsupported modules.
+		rChild, compChild, ok := isModuleSupported(ctx, child)
+		if !ok {
 			return
 		}
-		crate.Deps = append(crate.Deps, rustProjectDep{Crate: childId, Name: childCrateName})
-		deps[ctx.ModuleName(child)] = childId
+		// For unknown dependency, add it first.
+		var childId int
+		cInfo, known := singleton.knownCrates[rChild.Name()]
+		if !known {
+			childId, ok = singleton.addCrate(ctx, rChild, compChild)
+			if !ok {
+				return
+			}
+		} else {
+			childId = cInfo.Idx
+		}
+		// Is this dependency known already?
+		if _, ok = deps[child.Name()]; ok {
+			return
+		}
+		crate.Deps = append(crate.Deps, rustProjectDep{Crate: childId, Name: rChild.CrateName()})
+		deps[child.Name()] = childId
 	})
 }
 
-// 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) {
+// isModuleSupported returns the RustModule and baseCompiler if the module
+// should be considered for inclusion in rust-project.json.
+func isModuleSupported(ctx android.SingletonContext, module android.Module) (*Module, *baseCompiler, bool) {
 	rModule, ok := module.(*Module)
 	if !ok {
-		return 0, "", false
+		return nil, nil, false
 	}
 	if rModule.compiler == nil {
-		return 0, "", false
+		return nil, nil, false
 	}
 	var comp *baseCompiler
 	switch c := rModule.compiler.(type) {
@@ -145,35 +209,57 @@
 	case *testDecorator:
 		comp = c.binaryDecorator.baseCompiler
 	default:
-		return 0, "", false
+		return nil, nil, false
 	}
-	moduleName := ctx.ModuleName(module)
-	crateName := rModule.CrateName()
-	if cInfo, ok := singleton.knownCrates[moduleName]; ok {
-		// We have seen this crate already; merge any new dependencies.
-		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)}
+	return rModule, comp, true
+}
+
+// addCrate adds a crate to singleton.project.Crates ensuring that required
+// dependencies are also added. It returns the index of the new crate in
+// singleton.project.Crates
+func (singleton *projectGeneratorSingleton) addCrate(ctx android.SingletonContext, rModule *Module, comp *baseCompiler) (int, bool) {
 	rootModule, ok := crateSource(ctx, rModule, comp)
 	if !ok {
-		return 0, "", false
+		fmt.Errorf("Unable to find source for valid module: %v", rModule)
+		return 0, false
 	}
-	crate.RootModule = rootModule
-	crate.Edition = comp.edition()
+
+	crate := rustProjectCrate{
+		DisplayName: rModule.Name(),
+		RootModule:  rootModule,
+		Edition:     comp.edition(),
+		Deps:        make([]rustProjectDep, 0),
+		Cfgs:        make([]string, 0),
+	}
 
 	deps := make(map[string]int)
-	singleton.mergeDependencies(ctx, module, &crate, deps)
+	singleton.mergeDependencies(ctx, rModule, &crate, deps)
 
-	id := len(singleton.project.Crates)
-	singleton.knownCrates[moduleName] = crateInfo{ID: id, Deps: deps}
+	idx := len(singleton.project.Crates)
+	singleton.knownCrates[rModule.Name()] = crateInfo{Idx: idx, 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.
 	singleton.project.Roots = append(singleton.project.Roots, path.Dir(crate.RootModule))
-	return id, crateName, true
+	return idx, true
+}
+
+// appendCrateAndDependencies 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.
+func (singleton *projectGeneratorSingleton) appendCrateAndDependencies(ctx android.SingletonContext, module android.Module) {
+	rModule, comp, ok := isModuleSupported(ctx, module)
+	if !ok {
+		return
+	}
+	// If we have seen this crate already; merge any new dependencies.
+	if cInfo, ok := singleton.knownCrates[module.Name()]; ok {
+		crate := singleton.project.Crates[cInfo.Idx]
+		singleton.mergeDependencies(ctx, rModule, &crate, cInfo.Deps)
+		singleton.project.Crates[cInfo.Idx] = crate
+		return
+	}
+	singleton.addCrate(ctx, rModule, comp)
 }
 
 func (singleton *projectGeneratorSingleton) GenerateBuildActions(ctx android.SingletonContext) {
@@ -183,7 +269,7 @@
 
 	singleton.knownCrates = make(map[string]crateInfo)
 	ctx.VisitAllModules(func(module android.Module) {
-		singleton.appendLibraryAndDeps(ctx, module)
+		singleton.appendCrateAndDependencies(ctx, module)
 	})
 
 	path := android.PathForOutput(ctx, rustProjectJsonFileName)
diff --git a/rust/project_json_test.go b/rust/project_json_test.go
index aff1697..ba66215 100644
--- a/rust/project_json_test.go
+++ b/rust/project_json_test.go
@@ -119,9 +119,9 @@
 func TestProjectJsonBinary(t *testing.T) {
 	bp := `
 	rust_binary {
-		name: "liba",
-		srcs: ["a/src/lib.rs"],
-		crate_name: "a"
+		name: "libz",
+		srcs: ["z/src/lib.rs"],
+		crate_name: "z"
 	}
 	`
 	jsonContent := testProjectJson(t, bp)
@@ -132,7 +132,7 @@
 		if !ok {
 			t.Fatalf("Unexpected type for root_module: %v", crate["root_module"])
 		}
-		if rootModule == "a/src/lib.rs" {
+		if rootModule == "z/src/lib.rs" {
 			return
 		}
 	}
@@ -142,10 +142,10 @@
 func TestProjectJsonBindGen(t *testing.T) {
 	bp := `
 	rust_library {
-		name: "liba",
-		srcs: ["src/lib.rs"],
+		name: "libd",
+		srcs: ["d/src/lib.rs"],
 		rlibs: ["libbindings1"],
-		crate_name: "a"
+		crate_name: "d"
 	}
 	rust_bindgen {
 		name: "libbindings1",
@@ -155,10 +155,10 @@
 		wrapper_src: "src/any.h",
 	}
 	rust_library_host {
-		name: "libb",
-		srcs: ["src/lib.rs"],
+		name: "libe",
+		srcs: ["e/src/lib.rs"],
 		rustlibs: ["libbindings2"],
-		crate_name: "b"
+		crate_name: "e"
 	}
 	rust_bindgen_host {
 		name: "libbindings2",
@@ -190,6 +190,19 @@
 				}
 			}
 		}
+		// Check that liba depends on libbindings1
+		if strings.Contains(rootModule, "d/src/lib.rs") {
+			found := false
+			for _, depName := range validateDependencies(t, crate) {
+				if depName == "bindings1" {
+					found = true
+					break
+				}
+			}
+			if !found {
+				t.Errorf("liba does not depend on libbindings1: %v", crate)
+			}
+		}
 	}
 }