Merge "Include shared lib in vendor snapshot if isVndkExt"
diff --git a/android/override_module.go b/android/override_module.go
index 6b246db..3994084 100644
--- a/android/override_module.go
+++ b/android/override_module.go
@@ -28,6 +28,7 @@
 // module based on it.
 
 import (
+	"sort"
 	"sync"
 
 	"github.com/google/blueprint"
@@ -161,6 +162,11 @@
 
 // Should NOT be used in the same mutator as addOverride.
 func (b *OverridableModuleBase) getOverrides() []OverrideModule {
+	b.overridesLock.Lock()
+	sort.Slice(b.overrides, func(i, j int) bool {
+		return b.overrides[i].Name() < b.overrides[j].Name()
+	})
+	b.overridesLock.Unlock()
 	return b.overrides
 }
 
diff --git a/apex/builder.go b/apex/builder.go
index ede11d0..5fb9a5f 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -255,10 +255,15 @@
 
 	output := android.PathForModuleOut(ctx, "file_contexts")
 	rule := android.NewRuleBuilder()
+	// remove old file
 	rule.Command().Text("rm").FlagWithOutput("-f ", output)
+	// copy file_contexts
 	rule.Command().Text("cat").Input(fileContexts).Text(">>").Output(output)
+	// new line
 	rule.Command().Text("echo").Text(">>").Output(output)
+	// force-label /apex_manifest.pb and / as system_file so that apexd can read them
 	rule.Command().Text("echo").Flag("/apex_manifest\\\\.pb u:object_r:system_file:s0").Text(">>").Output(output)
+	rule.Command().Text("echo").Flag("/ u:object_r:system_file:s0").Text(">>").Output(output)
 	rule.Build(pctx, ctx, "file_contexts."+a.Name(), "Generate file_contexts")
 
 	a.fileContexts = output.OutputPath
diff --git a/cc/cc.go b/cc/cc.go
index 81df094..0a23967 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -873,7 +873,7 @@
 }
 
 func (c *Module) IsNdk() bool {
-	return inList(c.Name(), ndkMigratedLibs)
+	return inList(c.Name(), ndkKnownLibs)
 }
 
 func (c *Module) isLlndk(config android.Config) bool {
@@ -1759,8 +1759,6 @@
 	variantNdkLibs := []string{}
 	variantLateNdkLibs := []string{}
 	if ctx.Os() == android.Android {
-		version := ctx.sdkVersion()
-
 		// rewriteLibs takes a list of names of shared libraries and scans it for three types
 		// of names:
 		//
@@ -1802,12 +1800,8 @@
 			for _, entry := range list {
 				// strip #version suffix out
 				name, _ := StubsLibNameAndVersion(entry)
-				if ctx.useSdk() && inList(name, ndkPrebuiltSharedLibraries) {
-					if !inList(name, ndkMigratedLibs) {
-						nonvariantLibs = append(nonvariantLibs, name+".ndk."+version)
-					} else {
-						variantLibs = append(variantLibs, name+ndkLibrarySuffix)
-					}
+				if ctx.useSdk() && inList(name, ndkKnownLibs) {
+					variantLibs = append(variantLibs, name+ndkLibrarySuffix)
 				} else if ctx.useVndk() {
 					nonvariantLibs = append(nonvariantLibs, rewriteVendorLibs(entry))
 				} else if (ctx.Platform() || ctx.ProductSpecific()) && inList(name, *vendorPublicLibraries) {
diff --git a/cc/makevars.go b/cc/makevars.go
index 0f9f4c1..968eeb5 100644
--- a/cc/makevars.go
+++ b/cc/makevars.go
@@ -97,7 +97,6 @@
 	ctx.Strict("CLANG_EXTERNAL_CFLAGS", "${config.ClangExternalCflags}")
 	ctx.Strict("GLOBAL_CLANG_CFLAGS_NO_OVERRIDE", "${config.NoOverrideClangGlobalCflags}")
 	ctx.Strict("GLOBAL_CLANG_CPPFLAGS_NO_OVERRIDE", "")
-	ctx.Strict("NDK_PREBUILT_SHARED_LIBRARIES", strings.Join(ndkPrebuiltSharedLibs, " "))
 
 	ctx.Strict("BOARD_VNDK_VERSION", ctx.DeviceConfig().VndkVersion())
 
@@ -174,8 +173,8 @@
 	ctx.StrictRaw("SRC_HEADERS", strings.Join(includes, " "))
 	ctx.StrictRaw("SRC_SYSTEM_HEADERS", strings.Join(systemIncludes, " "))
 
-	sort.Strings(ndkMigratedLibs)
-	ctx.Strict("NDK_MIGRATED_LIBS", strings.Join(ndkMigratedLibs, " "))
+	sort.Strings(ndkKnownLibs)
+	ctx.Strict("NDK_KNOWN_LIBS", strings.Join(ndkKnownLibs, " "))
 
 	hostTargets := ctx.Config().Targets[android.BuildOs]
 	makeVarsToolchain(ctx, "", hostTargets[0])
diff --git a/cc/ndk_library.go b/cc/ndk_library.go
index 5ef9a78..6299b00 100644
--- a/cc/ndk_library.go
+++ b/cc/ndk_library.go
@@ -47,37 +47,10 @@
 
 	ndkLibrarySuffix = ".ndk"
 
-	ndkPrebuiltSharedLibs = []string{
-		"aaudio",
-		"amidi",
-		"android",
-		"binder_ndk",
-		"c",
-		"camera2ndk",
-		"dl",
-		"EGL",
-		"GLESv1_CM",
-		"GLESv2",
-		"GLESv3",
-		"jnigraphics",
-		"log",
-		"mediandk",
-		"nativewindow",
-		"m",
-		"neuralnetworks",
-		"OpenMAXAL",
-		"OpenSLES",
-		"stdc++",
-		"sync",
-		"vulkan",
-		"z",
-	}
-	ndkPrebuiltSharedLibraries = addPrefix(append([]string(nil), ndkPrebuiltSharedLibs...), "lib")
-
-	// These libraries have migrated over to the new ndk_library, which is added
-	// as a variation dependency via depsMutator.
-	ndkMigratedLibs     = []string{}
-	ndkMigratedLibsLock sync.Mutex // protects ndkMigratedLibs writes during parallel BeginMutator
+	// Added as a variation dependency via depsMutator.
+	ndkKnownLibs = []string{}
+	// protects ndkKnownLibs writes during parallel BeginMutator.
+	ndkKnownLibsLock sync.Mutex
 )
 
 // Creates a stub shared library based on the provided version file.
@@ -257,14 +230,14 @@
 		ctx.PropertyErrorf("name", "Do not append %q manually, just use the base name", ndkLibrarySuffix)
 	}
 
-	ndkMigratedLibsLock.Lock()
-	defer ndkMigratedLibsLock.Unlock()
-	for _, lib := range ndkMigratedLibs {
+	ndkKnownLibsLock.Lock()
+	defer ndkKnownLibsLock.Unlock()
+	for _, lib := range ndkKnownLibs {
 		if lib == name {
 			return
 		}
 	}
-	ndkMigratedLibs = append(ndkMigratedLibs, name)
+	ndkKnownLibs = append(ndkKnownLibs, name)
 }
 
 func addStubLibraryCompilerFlags(flags Flags) Flags {
diff --git a/cc/testing.go b/cc/testing.go
index b5cf45c..b0c3c162 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -32,6 +32,7 @@
 	ctx.RegisterModuleType("cc_object", ObjectFactory)
 	ctx.RegisterModuleType("ndk_prebuilt_shared_stl", NdkPrebuiltSharedStlFactory)
 	ctx.RegisterModuleType("ndk_prebuilt_object", NdkPrebuiltObjectFactory)
+	ctx.RegisterModuleType("ndk_library", NdkLibraryFactory)
 }
 
 func GatherRequiredDepsForTest(oses ...android.OsType) string {
@@ -393,25 +394,22 @@
 			system_shared_libs: [],
 		}
 
-		cc_library {
-			name: "libc.ndk.current",
-			sdk_version: "current",
-			stl: "none",
-			system_shared_libs: [],
+		ndk_library {
+			name: "libc",
+			first_version: "minimum",
+			symbol_file: "libc.map.txt",
 		}
 
-		cc_library {
-			name: "libm.ndk.current",
-			sdk_version: "current",
-			stl: "none",
-			system_shared_libs: [],
+		ndk_library {
+			name: "libm",
+			first_version: "minimum",
+			symbol_file: "libm.map.txt",
 		}
 
-		cc_library {
-			name: "libdl.ndk.current",
-			sdk_version: "current",
-			stl: "none",
-			system_shared_libs: [],
+		ndk_library {
+			name: "libdl",
+			first_version: "minimum",
+			symbol_file: "libdl.map.txt",
 		}
 
 		ndk_prebuilt_object {
@@ -503,7 +501,6 @@
 	ctx.RegisterModuleType("cc_fuzz", FuzzFactory)
 	ctx.RegisterModuleType("cc_test", TestFactory)
 	ctx.RegisterModuleType("llndk_headers", llndkHeadersFactory)
-	ctx.RegisterModuleType("ndk_library", NdkLibraryFactory)
 	ctx.RegisterModuleType("vendor_public_library", vendorPublicLibraryFactory)
 	ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
 	ctx.RegisterModuleType("vndk_prebuilt_shared", VndkPrebuiltSharedFactory)
diff --git a/cmd/extract_apks/main.go b/cmd/extract_apks/main.go
index e9a850e..db54ffb 100644
--- a/cmd/extract_apks/main.go
+++ b/cmd/extract_apks/main.go
@@ -24,6 +24,7 @@
 	"math"
 	"os"
 	"regexp"
+	"sort"
 	"strings"
 
 	"github.com/golang/protobuf/proto"
@@ -355,7 +356,7 @@
 
 // Writes out selected entries, renaming them as needed
 func (apkSet *ApkSet) writeApks(selected SelectionResult, config TargetConfig,
-	writer Zip2ZipWriter) error {
+	writer Zip2ZipWriter, partition string) ([]string, error) {
 	// Renaming rules:
 	//  splits/MODULE-master.apk to STEM.apk
 	// else
@@ -389,10 +390,11 @@
 	}
 
 	entryOrigin := make(map[string]string) // output entry to input entry
+	var apkcerts []string
 	for _, apk := range selected.entries {
 		apkFile, ok := apkSet.entries[apk]
 		if !ok {
-			return fmt.Errorf("TOC refers to an entry %s which does not exist", apk)
+			return nil, fmt.Errorf("TOC refers to an entry %s which does not exist", apk)
 		}
 		inName := apkFile.Name
 		outName, ok := renamer(inName)
@@ -405,10 +407,15 @@
 		}
 		entryOrigin[outName] = inName
 		if err := writer.CopyFrom(apkFile, outName); err != nil {
-			return err
+			return nil, err
+		}
+		if partition != "" {
+			apkcerts = append(apkcerts, fmt.Sprintf(
+				`name="%s" certificate="PRESIGNED" private_key="" partition="%s"`, outName, partition))
 		}
 	}
-	return nil
+	sort.Strings(apkcerts)
+	return apkcerts, nil
 }
 
 func (apkSet *ApkSet) extractAndCopySingle(selected SelectionResult, outFile *os.File) error {
@@ -433,6 +440,9 @@
 	}
 	extractSingle = flag.Bool("extract-single", false,
 		"extract a single target and output it uncompressed. only available for standalone apks and apexes.")
+	apkcertsOutput = flag.String("apkcerts", "",
+		"optional apkcerts.txt output file containing signing info of all outputted apks")
+	partition = flag.String("partition", "", "partition string. required when -apkcerts is used.")
 )
 
 // Parse abi values
@@ -485,7 +495,8 @@
 func processArgs() {
 	flag.Usage = func() {
 		fmt.Fprintln(os.Stderr, `usage: extract_apks -o <output-file> -sdk-version value -abis value `+
-			`-screen-densities value {-stem value | -extract-single} [-allow-prereleased] <APK set>`)
+			`-screen-densities value {-stem value | -extract-single} [-allow-prereleased] `+
+			`[-apkcerts <apkcerts output file> -partition <partition>] <APK set>`)
 		flag.PrintDefaults()
 		os.Exit(2)
 	}
@@ -498,7 +509,8 @@
 		"allow prereleased")
 	flag.StringVar(&targetConfig.stem, "stem", "", "output entries base name in the output zip file")
 	flag.Parse()
-	if (*outputFile == "") || len(flag.Args()) != 1 || *version == 0 || (targetConfig.stem == "" && !*extractSingle) {
+	if (*outputFile == "") || len(flag.Args()) != 1 || *version == 0 ||
+		(targetConfig.stem == "" && !*extractSingle) || (*apkcertsOutput != "" && *partition == "") {
 		flag.Usage()
 	}
 	targetConfig.sdkVersion = int32(*version)
@@ -536,7 +548,20 @@
 				log.Fatal(err)
 			}
 		}()
-		err = apkSet.writeApks(sel, targetConfig, writer)
+		apkcerts, err := apkSet.writeApks(sel, targetConfig, writer, *partition)
+		if err == nil && *apkcertsOutput != "" {
+			apkcertsFile, err := os.Create(*apkcertsOutput)
+			if err != nil {
+				log.Fatal(err)
+			}
+			defer apkcertsFile.Close()
+			for _, a := range apkcerts {
+				_, err = apkcertsFile.WriteString(a + "\n")
+				if err != nil {
+					log.Fatal(err)
+				}
+			}
+		}
 	}
 	if err != nil {
 		log.Fatal(err)
diff --git a/cmd/extract_apks/main_test.go b/cmd/extract_apks/main_test.go
index bdd4bec..c3e6a2d 100644
--- a/cmd/extract_apks/main_test.go
+++ b/cmd/extract_apks/main_test.go
@@ -16,10 +16,11 @@
 
 import (
 	"fmt"
-	"github.com/golang/protobuf/proto"
 	"reflect"
 	"testing"
 
+	"github.com/golang/protobuf/proto"
+
 	bp "android/soong/cmd/extract_apks/bundle_proto"
 	"android/soong/third_party/zip"
 )
@@ -430,48 +431,63 @@
 	return nil
 }
 
-type testCaseWriteZip struct {
+type testCaseWriteApks struct {
 	name       string
 	moduleName string
 	stem       string
+	partition  string
 	// what we write from what
-	expected map[string]string
+	expectedZipEntries map[string]string
+	expectedApkcerts   []string
 }
 
-func TestWriteZip(t *testing.T) {
-	testCases := []testCaseWriteZip{
+func TestWriteApks(t *testing.T) {
+	testCases := []testCaseWriteApks{
 		{
 			name:       "splits",
 			moduleName: "mybase",
 			stem:       "Foo",
-			expected: map[string]string{
+			partition:  "system",
+			expectedZipEntries: map[string]string{
 				"Foo.apk":       "splits/mybase-master.apk",
 				"Foo-xhdpi.apk": "splits/mybase-xhdpi.apk",
 			},
+			expectedApkcerts: []string{
+				`name="Foo-xhdpi.apk" certificate="PRESIGNED" private_key="" partition="system"`,
+				`name="Foo.apk" certificate="PRESIGNED" private_key="" partition="system"`,
+			},
 		},
 		{
 			name:       "universal",
 			moduleName: "base",
 			stem:       "Bar",
-			expected: map[string]string{
+			partition:  "product",
+			expectedZipEntries: map[string]string{
 				"Bar.apk": "universal.apk",
 			},
+			expectedApkcerts: []string{
+				`name="Bar.apk" certificate="PRESIGNED" private_key="" partition="product"`,
+			},
 		},
 	}
 	for _, testCase := range testCases {
 		apkSet := ApkSet{entries: make(map[string]*zip.File)}
 		sel := SelectionResult{moduleName: testCase.moduleName}
-		for _, in := range testCase.expected {
+		for _, in := range testCase.expectedZipEntries {
 			apkSet.entries[in] = &zip.File{FileHeader: zip.FileHeader{Name: in}}
 			sel.entries = append(sel.entries, in)
 		}
 		writer := testZip2ZipWriter{make(map[string]string)}
 		config := TargetConfig{stem: testCase.stem}
-		if err := apkSet.writeApks(sel, config, writer); err != nil {
+		apkcerts, err := apkSet.writeApks(sel, config, writer, testCase.partition)
+		if err != nil {
 			t.Error(err)
 		}
-		if !reflect.DeepEqual(testCase.expected, writer.entries) {
-			t.Errorf("expected %v, got %v", testCase.expected, writer.entries)
+		if !reflect.DeepEqual(testCase.expectedZipEntries, writer.entries) {
+			t.Errorf("expected zip entries %v, got %v", testCase.expectedZipEntries, writer.entries)
+		}
+		if !reflect.DeepEqual(testCase.expectedApkcerts, apkcerts) {
+			t.Errorf("expected apkcerts %v, got %v", testCase.expectedApkcerts, apkcerts)
 		}
 	}
 }
diff --git a/java/androidmk.go b/java/androidmk.go
index e73b030..618e15d 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -719,6 +719,7 @@
 				func(entries *android.AndroidMkEntries) {
 					entries.SetBoolIfTrue("LOCAL_PRIVILEGED_MODULE", apkSet.Privileged())
 					entries.SetString("LOCAL_APK_SET_MASTER_FILE", apkSet.masterFile)
+					entries.SetPath("LOCAL_APKCERTS_FILE", apkSet.apkcertsFile)
 					entries.AddStrings("LOCAL_OVERRIDES_PACKAGES", apkSet.properties.Overrides...)
 				},
 			},
diff --git a/java/app.go b/java/app.go
index 37a6453..44164e8 100755
--- a/java/app.go
+++ b/java/app.go
@@ -79,6 +79,7 @@
 	properties   AndroidAppSetProperties
 	packedOutput android.WritablePath
 	masterFile   string
+	apkcertsFile android.ModuleOutPath
 }
 
 func (as *AndroidAppSet) Name() string {
@@ -130,6 +131,7 @@
 
 func (as *AndroidAppSet) GenerateAndroidBuildActions(ctx android.ModuleContext) {
 	as.packedOutput = android.PathForModuleOut(ctx, ctx.ModuleName()+".zip")
+	as.apkcertsFile = android.PathForModuleOut(ctx, "apkcerts.txt")
 	// We are assuming here that the master file in the APK
 	// set has `.apk` suffix. If it doesn't the build will fail.
 	// APK sets containing APEX files are handled elsewhere.
@@ -142,16 +144,19 @@
 	// TODO(asmundak): do we support device features
 	ctx.Build(pctx,
 		android.BuildParams{
-			Rule:        extractMatchingApks,
-			Description: "Extract APKs from APK set",
-			Output:      as.packedOutput,
-			Inputs:      android.Paths{as.prebuilt.SingleSourcePath(ctx)},
+			Rule:           extractMatchingApks,
+			Description:    "Extract APKs from APK set",
+			Output:         as.packedOutput,
+			ImplicitOutput: as.apkcertsFile,
+			Inputs:         android.Paths{as.prebuilt.SingleSourcePath(ctx)},
 			Args: map[string]string{
 				"abis":              strings.Join(SupportedAbis(ctx), ","),
 				"allow-prereleased": strconv.FormatBool(proptools.Bool(as.properties.Prerelease)),
 				"screen-densities":  screenDensities,
 				"sdk-version":       ctx.Config().PlatformSdkVersion(),
 				"stem":              as.BaseModuleName(),
+				"apkcerts":          as.apkcertsFile.String(),
+				"partition":         as.PartitionTag(ctx.DeviceConfig()),
 			},
 		})
 }
diff --git a/java/app_test.go b/java/app_test.go
index 120dc00..beb29a7 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -147,7 +147,7 @@
 			name: "foo",
 			set: "prebuilts/apks/app.apks",
 			prerelease: true,
-        }`)
+		}`)
 	module := ctx.ModuleForTests("foo", "android_common")
 	const packedSplitApks = "foo.zip"
 	params := module.Output(packedSplitApks)
@@ -157,6 +157,9 @@
 	if s := params.Args["allow-prereleased"]; s != "true" {
 		t.Errorf("wrong allow-prereleased value: '%s', expected 'true'", s)
 	}
+	if s := params.Args["partition"]; s != "system" {
+		t.Errorf("wrong partition value: '%s', expected 'system'", s)
+	}
 	mkEntries := android.AndroidMkEntriesForTest(t, config, "", module.Module())[0]
 	actualMaster := mkEntries.EntryMap["LOCAL_APK_SET_MASTER_FILE"]
 	expectedMaster := []string{"foo.apk"}
diff --git a/java/builder.go b/java/builder.go
index a27e5c3..7318fcb 100644
--- a/java/builder.go
+++ b/java/builder.go
@@ -120,10 +120,11 @@
 				`${config.ExtractApksCmd} -o "${out}" -allow-prereleased=${allow-prereleased} ` +
 				`-sdk-version=${sdk-version} -abis=${abis} ` +
 				`--screen-densities=${screen-densities} --stem=${stem} ` +
+				`-apkcerts=${apkcerts} -partition=${partition} ` +
 				`${in}`,
 			CommandDeps: []string{"${config.ExtractApksCmd}"},
 		},
-		"abis", "allow-prereleased", "screen-densities", "sdk-version", "stem")
+		"abis", "allow-prereleased", "screen-densities", "sdk-version", "stem", "apkcerts", "partition")
 
 	turbine, turbineRE = remoteexec.StaticRules(pctx, "turbine",
 		blueprint.RuleParams{
diff --git a/java/sdk.go b/java/sdk.go
index e3472ce..c4861e3 100644
--- a/java/sdk.go
+++ b/java/sdk.go
@@ -94,9 +94,9 @@
 	case sdkCorePlatform:
 		return "core_platform"
 	case sdkModule:
-		return "module"
+		return "module-lib"
 	case sdkSystemServer:
-		return "system_server"
+		return "system-server"
 	default:
 		return "invalid"
 	}
diff --git a/rust/binary.go b/rust/binary.go
index 56d6f0b..a1cd410 100644
--- a/rust/binary.go
+++ b/rust/binary.go
@@ -131,3 +131,11 @@
 func (binary *binaryDecorator) coverageOutputZipPath() android.OptionalPath {
 	return binary.coverageOutputZipFile
 }
+
+func (binary *binaryDecorator) autoDep() autoDep {
+	if binary.preferDynamic() {
+		return dylibAutoDep
+	} else {
+		return rlibAutoDep
+	}
+}
diff --git a/rust/builder.go b/rust/builder.go
index b0ab297..16d7306 100644
--- a/rust/builder.go
+++ b/rust/builder.go
@@ -70,37 +70,37 @@
 }
 
 func TransformSrcToBinary(ctx ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags,
-	outputFile android.WritablePath, includeDirs []string) buildOutput {
+	outputFile android.WritablePath, linkDirs []string) buildOutput {
 	flags.RustFlags = append(flags.RustFlags, "-C lto")
 
-	return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, "bin", includeDirs)
+	return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, "bin", linkDirs)
 }
 
 func TransformSrctoRlib(ctx ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags,
-	outputFile android.WritablePath, includeDirs []string) buildOutput {
-	return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, "rlib", includeDirs)
+	outputFile android.WritablePath, linkDirs []string) buildOutput {
+	return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, "rlib", linkDirs)
 }
 
 func TransformSrctoDylib(ctx ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags,
-	outputFile android.WritablePath, includeDirs []string) buildOutput {
-	return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, "dylib", includeDirs)
+	outputFile android.WritablePath, linkDirs []string) buildOutput {
+	return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, "dylib", linkDirs)
 }
 
 func TransformSrctoStatic(ctx ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags,
-	outputFile android.WritablePath, includeDirs []string) buildOutput {
+	outputFile android.WritablePath, linkDirs []string) buildOutput {
 	flags.RustFlags = append(flags.RustFlags, "-C lto")
-	return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, "staticlib", includeDirs)
+	return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, "staticlib", linkDirs)
 }
 
 func TransformSrctoShared(ctx ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags,
-	outputFile android.WritablePath, includeDirs []string) buildOutput {
+	outputFile android.WritablePath, linkDirs []string) buildOutput {
 	flags.RustFlags = append(flags.RustFlags, "-C lto")
-	return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, "cdylib", includeDirs)
+	return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, "cdylib", linkDirs)
 }
 
 func TransformSrctoProcMacro(ctx ModuleContext, mainSrc android.Path, deps PathDeps,
-	flags Flags, outputFile android.WritablePath, includeDirs []string) buildOutput {
-	return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, "proc-macro", includeDirs)
+	flags Flags, outputFile android.WritablePath, linkDirs []string) buildOutput {
+	return transformSrctoCrate(ctx, mainSrc, deps, flags, outputFile, "proc-macro", linkDirs)
 }
 
 func rustLibsToPaths(libs RustLibraries) android.Paths {
@@ -112,7 +112,7 @@
 }
 
 func transformSrctoCrate(ctx ModuleContext, main android.Path, deps PathDeps, flags Flags,
-	outputFile android.WritablePath, crate_type string, includeDirs []string) buildOutput {
+	outputFile android.WritablePath, crate_type string, linkDirs []string) buildOutput {
 
 	var inputs android.Paths
 	var implicits android.Paths
@@ -137,16 +137,10 @@
 		rustcFlags = append(rustcFlags, "--target="+targetTriple)
 		linkFlags = append(linkFlags, "-target "+targetTriple)
 	}
-	// TODO(b/159718669): Once we have defined static libraries in the host
-	// prebuilts Blueprint file, sysroot should be unconditionally sourced
-	// from /dev/null. Explicitly set sysroot to avoid clippy-driver to
-	// internally call rustc.
-	if ctx.Host() && ctx.TargetPrimary() {
-		rustcFlags = append(rustcFlags, "--sysroot=${config.RustPath}")
-	} else {
-		// If we're not targeting the host primary arch, do not use a sysroot.
-		rustcFlags = append(rustcFlags, "--sysroot=/dev/null")
-	}
+
+	// Suppress an implicit sysroot
+	rustcFlags = append(rustcFlags, "--sysroot=/dev/null")
+
 	// Collect linker flags
 	linkFlags = append(linkFlags, flags.GlobalLinkFlags...)
 	linkFlags = append(linkFlags, flags.LinkFlags...)
@@ -162,7 +156,7 @@
 		libFlags = append(libFlags, "--extern "+proc_macro.CrateName+"="+proc_macro.Path.String())
 	}
 
-	for _, path := range includeDirs {
+	for _, path := range linkDirs {
 		libFlags = append(libFlags, "-L "+path)
 	}
 
diff --git a/rust/clippy_test.go b/rust/clippy_test.go
index af5cd17..3144173 100644
--- a/rust/clippy_test.go
+++ b/rust/clippy_test.go
@@ -32,14 +32,14 @@
 			clippy: false,
 		}`)
 
-	ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Output("libfoo.so")
-	fooClippy := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").MaybeRule("clippy")
+	ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_dylib").Output("libfoo.dylib.so")
+	fooClippy := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_dylib").MaybeRule("clippy")
 	if fooClippy.Rule.String() != "android/soong/rust.clippy" {
 		t.Errorf("Clippy output (default) for libfoo was not generated: %+v", fooClippy)
 	}
 
-	ctx.ModuleForTests("libfoobar", "android_arm64_armv8-a_shared").Output("libfoobar.so")
-	foobarClippy := ctx.ModuleForTests("libfoobar", "android_arm64_armv8-a_shared").MaybeRule("clippy")
+	ctx.ModuleForTests("libfoobar", "android_arm64_armv8-a_dylib").Output("libfoobar.dylib.so")
+	foobarClippy := ctx.ModuleForTests("libfoobar", "android_arm64_armv8-a_dylib").MaybeRule("clippy")
 	if foobarClippy.Rule != nil {
 		t.Errorf("Clippy output for libfoobar is not empty")
 	}
diff --git a/rust/compiler.go b/rust/compiler.go
index 51d7180..92a3b07 100644
--- a/rust/compiler.go
+++ b/rust/compiler.go
@@ -67,6 +67,9 @@
 	// list of rust dylib crate dependencies
 	Dylibs []string `android:"arch_variant"`
 
+	// list of rust automatic crate dependencies
+	Rustlibs []string `android:"arch_variant"`
+
 	// list of rust proc_macro crate dependencies
 	Proc_macros []string `android:"arch_variant"`
 
@@ -100,8 +103,6 @@
 
 type baseCompiler struct {
 	Properties   BaseCompilerProperties
-	depFlags     []string
-	linkDirs     []string
 	coverageFile android.Path //rustc generates a single gcno file
 
 	// Install related
@@ -178,6 +179,7 @@
 func (compiler *baseCompiler) compilerDeps(ctx DepsContext, deps Deps) Deps {
 	deps.Rlibs = append(deps.Rlibs, compiler.Properties.Rlibs...)
 	deps.Dylibs = append(deps.Dylibs, compiler.Properties.Dylibs...)
+	deps.Rustlibs = append(deps.Rustlibs, compiler.Properties.Rustlibs...)
 	deps.ProcMacros = append(deps.ProcMacros, compiler.Properties.Proc_macros...)
 	deps.StaticLibs = append(deps.StaticLibs, compiler.Properties.Static_libs...)
 	deps.SharedLibs = append(deps.SharedLibs, compiler.Properties.Shared_libs...)
@@ -189,17 +191,7 @@
 				stdlib = stdlib + "_" + ctx.toolchain().RustTriple()
 			}
 
-			// This check is technically insufficient - on the host, where
-			// static linking is the default, if one of our static
-			// dependencies uses a dynamic library, we need to dynamically
-			// link the stdlib as well.
-			if (len(deps.Dylibs) > 0) || ctx.Device() {
-				// Dynamically linked stdlib
-				deps.Dylibs = append(deps.Dylibs, stdlib)
-			} else if ctx.Host() && !ctx.TargetPrimary() {
-				// Otherwise use the static in-tree stdlib for host secondary arch
-				deps.Rlibs = append(deps.Rlibs, stdlib+".static")
-			}
+			deps.Rustlibs = append(deps.Rustlibs, stdlib)
 		}
 	}
 	return deps
diff --git a/rust/config/allowed_list.go b/rust/config/allowed_list.go
index a339050..0204cd2 100644
--- a/rust/config/allowed_list.go
+++ b/rust/config/allowed_list.go
@@ -15,13 +15,15 @@
 		"rust_library",
 		"rust_library_dylib",
 		"rust_library_rlib",
-		"rust_library_shared",
-		"rust_library_static",
+		"rust_ffi",
+		"rust_ffi_shared",
+		"rust_ffi_static",
 		"rust_library_host",
 		"rust_library_host_dylib",
 		"rust_library_host_rlib",
-		"rust_library_host_shared",
-		"rust_library_host_static",
+		"rust_ffi_host",
+		"rust_ffi_host_shared",
+		"rust_ffi_host_static",
 		"rust_proc_macro",
 		"rust_test",
 		"rust_test_host",
diff --git a/rust/coverage_test.go b/rust/coverage_test.go
index 27acad3..357c2e8 100644
--- a/rust/coverage_test.go
+++ b/rust/coverage_test.go
@@ -105,6 +105,12 @@
 			rlibs: ["librlib"],
 			crate_name: "foo",
 		}
+                rust_ffi_static {
+                        name: "libbaz",
+                        srcs: ["foo.rs"],
+                        rlibs: ["librlib"],
+                        crate_name: "baz",
+                }
 		rust_library_rlib {
 			name: "librlib",
 			srcs: ["foo.rs"],
@@ -113,17 +119,17 @@
 		rust_binary {
 			name: "fizz",
 			rlibs: ["librlib"],
-			static_libs: ["libfoo"],
+			static_libs: ["libbaz"],
 			srcs: ["foo.rs"],
 		}
 		cc_binary {
 			name: "buzz",
-			static_libs: ["libfoo"],
+			static_libs: ["libbaz"],
 			srcs: ["foo.c"],
 		}
 		cc_library {
 			name: "libbar",
-			static_libs: ["libfoo"],
+			static_libs: ["libbaz"],
 			compile_multilib: "64",
 			srcs: ["foo.c"],
 		}`)
@@ -149,7 +155,7 @@
 
 	// Make sure the expected inputs are provided to the zip rule.
 	if !android.SuffixInList(fizzZipInputs, "android_arm64_armv8-a_rlib_cov/librlib.gcno") ||
-		!android.SuffixInList(fizzZipInputs, "android_arm64_armv8-a_static_cov/libfoo.gcno") ||
+		!android.SuffixInList(fizzZipInputs, "android_arm64_armv8-a_static_cov/libbaz.gcno") ||
 		!android.SuffixInList(fizzZipInputs, "android_arm64_armv8-a_cov/fizz.gcno") {
 		t.Fatalf("missing expected coverage files for rust 'fizz' binary: %#v", fizzZipInputs)
 	}
@@ -158,11 +164,11 @@
 		t.Fatalf("missing expected coverage files for rust 'fizz' binary: %#v", libfooZipInputs)
 	}
 	if !android.SuffixInList(buzzZipInputs, "android_arm64_armv8-a_cov/obj/foo.gcno") ||
-		!android.SuffixInList(buzzZipInputs, "android_arm64_armv8-a_static_cov/libfoo.gcno") {
+		!android.SuffixInList(buzzZipInputs, "android_arm64_armv8-a_static_cov/libbaz.gcno") {
 		t.Fatalf("missing expected coverage files for cc 'buzz' binary: %#v", buzzZipInputs)
 	}
 	if !android.SuffixInList(libbarZipInputs, "android_arm64_armv8-a_static_cov/obj/foo.gcno") ||
-		!android.SuffixInList(libbarZipInputs, "android_arm64_armv8-a_static_cov/libfoo.gcno") {
+		!android.SuffixInList(libbarZipInputs, "android_arm64_armv8-a_static_cov/libbaz.gcno") {
 		t.Fatalf("missing expected coverage files for cc 'libbar' library: %#v", libbarZipInputs)
 	}
 }
diff --git a/rust/library.go b/rust/library.go
index f070c34..8b8e797 100644
--- a/rust/library.go
+++ b/rust/library.go
@@ -19,7 +19,6 @@
 	"strings"
 
 	"android/soong/android"
-	"android/soong/rust/config"
 )
 
 func init() {
@@ -29,14 +28,17 @@
 	android.RegisterModuleType("rust_library_host", RustLibraryHostFactory)
 	android.RegisterModuleType("rust_library_host_dylib", RustLibraryDylibHostFactory)
 	android.RegisterModuleType("rust_library_host_rlib", RustLibraryRlibHostFactory)
-	android.RegisterModuleType("rust_library_shared", RustLibrarySharedFactory)
-	android.RegisterModuleType("rust_library_static", RustLibraryStaticFactory)
-	android.RegisterModuleType("rust_library_host_shared", RustLibrarySharedHostFactory)
-	android.RegisterModuleType("rust_library_host_static", RustLibraryStaticHostFactory)
+	android.RegisterModuleType("rust_ffi", RustFFIFactory)
+	android.RegisterModuleType("rust_ffi_shared", RustFFISharedFactory)
+	android.RegisterModuleType("rust_ffi_static", RustFFIStaticFactory)
+	android.RegisterModuleType("rust_ffi_host", RustFFIHostFactory)
+	android.RegisterModuleType("rust_ffi_host_shared", RustFFISharedHostFactory)
+	android.RegisterModuleType("rust_ffi_host_static", RustFFIStaticHostFactory)
 }
 
 type VariantLibraryProperties struct {
-	Enabled *bool `android:"arch_variant"`
+	Enabled *bool    `android:"arch_variant"`
+	Srcs    []string `android:"path,arch_variant"`
 }
 
 type LibraryCompilerProperties struct {
@@ -71,6 +73,7 @@
 
 type libraryDecorator struct {
 	*baseCompiler
+	*flagExporter
 
 	Properties        LibraryCompilerProperties
 	MutatedProperties LibraryMutatedProperties
@@ -96,6 +99,8 @@
 	setStatic()
 
 	// Build a specific library variant
+	BuildOnlyFFI()
+	BuildOnlyRust()
 	BuildOnlyRlib()
 	BuildOnlyDylib()
 	BuildOnlyStatic()
@@ -106,22 +111,6 @@
 	return true
 }
 
-func (library *libraryDecorator) exportedDirs() []string {
-	return library.linkDirs
-}
-
-func (library *libraryDecorator) exportedDepFlags() []string {
-	return library.depFlags
-}
-
-func (library *libraryDecorator) reexportDirs(dirs ...string) {
-	library.linkDirs = android.FirstUniqueStrings(append(library.linkDirs, dirs...))
-}
-
-func (library *libraryDecorator) reexportDepFlags(flags ...string) {
-	library.depFlags = android.FirstUniqueStrings(append(library.depFlags, flags...))
-}
-
 func (library *libraryDecorator) rlib() bool {
 	return library.MutatedProperties.VariantIsRlib
 }
@@ -182,12 +171,31 @@
 	library.MutatedProperties.VariantIsDylib = false
 }
 
+func (library *libraryDecorator) autoDep() autoDep {
+	if library.rlib() || library.static() {
+		return rlibAutoDep
+	} else if library.dylib() || library.shared() {
+		return dylibAutoDep
+	} else {
+		return rlibAutoDep
+	}
+}
+
 var _ compiler = (*libraryDecorator)(nil)
 var _ libraryInterface = (*libraryDecorator)(nil)
+var _ exportedFlagsProducer = (*libraryDecorator)(nil)
 
-// rust_library produces all variants.
+// rust_library produces all rust variants.
 func RustLibraryFactory() android.Module {
-	module, _ := NewRustLibrary(android.HostAndDeviceSupported)
+	module, library := NewRustLibrary(android.HostAndDeviceSupported)
+	library.BuildOnlyRust()
+	return module.Init()
+}
+
+// rust_ffi produces all ffi variants.
+func RustFFIFactory() android.Module {
+	module, library := NewRustLibrary(android.HostAndDeviceSupported)
+	library.BuildOnlyFFI()
 	return module.Init()
 }
 
@@ -205,23 +213,31 @@
 	return module.Init()
 }
 
-// rust_library_shared produces a shared library.
-func RustLibrarySharedFactory() android.Module {
+// rust_ffi_shared produces a shared library.
+func RustFFISharedFactory() android.Module {
 	module, library := NewRustLibrary(android.HostAndDeviceSupported)
 	library.BuildOnlyShared()
 	return module.Init()
 }
 
-// rust_library_static produces a static library.
-func RustLibraryStaticFactory() android.Module {
+// rust_ffi_static produces a static library.
+func RustFFIStaticFactory() android.Module {
 	module, library := NewRustLibrary(android.HostAndDeviceSupported)
 	library.BuildOnlyStatic()
 	return module.Init()
 }
 
-// rust_library_host produces all variants.
+// rust_library_host produces all rust variants.
 func RustLibraryHostFactory() android.Module {
-	module, _ := NewRustLibrary(android.HostSupported)
+	module, library := NewRustLibrary(android.HostSupported)
+	library.BuildOnlyRust()
+	return module.Init()
+}
+
+// rust_ffi_host produces all FFI variants.
+func RustFFIHostFactory() android.Module {
+	module, library := NewRustLibrary(android.HostSupported)
+	library.BuildOnlyFFI()
 	return module.Init()
 }
 
@@ -239,44 +255,60 @@
 	return module.Init()
 }
 
-// rust_library_static_host produces a static library.
-func RustLibraryStaticHostFactory() android.Module {
+// rust_ffi_static_host produces a static library.
+func RustFFIStaticHostFactory() android.Module {
 	module, library := NewRustLibrary(android.HostSupported)
 	library.BuildOnlyStatic()
 	return module.Init()
 }
 
-// rust_library_shared_host produces an shared library.
-func RustLibrarySharedHostFactory() android.Module {
+// rust_ffi_shared_host produces an shared library.
+func RustFFISharedHostFactory() android.Module {
 	module, library := NewRustLibrary(android.HostSupported)
 	library.BuildOnlyShared()
 	return module.Init()
 }
 
+func (library *libraryDecorator) BuildOnlyFFI() {
+	library.MutatedProperties.BuildDylib = false
+	library.MutatedProperties.BuildRlib = false
+	library.MutatedProperties.BuildShared = true
+	library.MutatedProperties.BuildStatic = true
+}
+
+func (library *libraryDecorator) BuildOnlyRust() {
+	library.MutatedProperties.BuildDylib = true
+	library.MutatedProperties.BuildRlib = true
+	library.MutatedProperties.BuildShared = false
+	library.MutatedProperties.BuildStatic = false
+}
+
 func (library *libraryDecorator) BuildOnlyDylib() {
+	library.MutatedProperties.BuildDylib = true
 	library.MutatedProperties.BuildRlib = false
 	library.MutatedProperties.BuildShared = false
 	library.MutatedProperties.BuildStatic = false
-
 }
 
 func (library *libraryDecorator) BuildOnlyRlib() {
 	library.MutatedProperties.BuildDylib = false
+	library.MutatedProperties.BuildRlib = true
 	library.MutatedProperties.BuildShared = false
 	library.MutatedProperties.BuildStatic = false
 }
 
 func (library *libraryDecorator) BuildOnlyStatic() {
-	library.MutatedProperties.BuildShared = false
 	library.MutatedProperties.BuildRlib = false
 	library.MutatedProperties.BuildDylib = false
-
+	library.MutatedProperties.BuildShared = false
+	library.MutatedProperties.BuildStatic = true
 }
 
 func (library *libraryDecorator) BuildOnlyShared() {
-	library.MutatedProperties.BuildStatic = false
 	library.MutatedProperties.BuildRlib = false
 	library.MutatedProperties.BuildDylib = false
+	library.MutatedProperties.BuildStatic = false
+	library.MutatedProperties.BuildShared = true
 }
 
 func NewRustLibrary(hod android.HostOrDeviceSupported) (*Module, *libraryDecorator) {
@@ -284,12 +316,13 @@
 
 	library := &libraryDecorator{
 		MutatedProperties: LibraryMutatedProperties{
-			BuildDylib:  true,
-			BuildRlib:   true,
-			BuildShared: true,
-			BuildStatic: true,
+			BuildDylib:  false,
+			BuildRlib:   false,
+			BuildShared: false,
+			BuildStatic: false,
 		},
 		baseCompiler: NewBaseCompiler("lib", "lib64", InstallInSystem),
+		flagExporter: NewFlagExporter(),
 	}
 
 	module.compiler = library
@@ -304,15 +337,6 @@
 }
 
 func (library *libraryDecorator) compilerDeps(ctx DepsContext, deps Deps) Deps {
-
-	// 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")
-		}
-	}
-
 	deps = library.baseCompiler.compilerDeps(ctx, deps)
 
 	if ctx.toolchain().Bionic() && (library.dylib() || library.shared()) {
@@ -391,8 +415,8 @@
 	library.coverageOutputZipFile = TransformCoverageFilesToZip(ctx, coverageFiles, library.getStem(ctx))
 
 	if library.rlib() || library.dylib() {
-		library.reexportDirs(deps.linkDirs...)
-		library.reexportDepFlags(deps.depFlags...)
+		library.exportLinkDirs(deps.linkDirs...)
+		library.exportDepFlags(deps.depFlags...)
 	}
 	library.unstrippedOutputFile = outputFile
 
diff --git a/rust/library_test.go b/rust/library_test.go
index 9d2f6c0..8a91cf1 100644
--- a/rust/library_test.go
+++ b/rust/library_test.go
@@ -29,13 +29,18 @@
 			name: "libfoo",
 			srcs: ["foo.rs"],
 			crate_name: "foo",
-		}`)
+		}
+                rust_ffi_host {
+                        name: "libfoo.ffi",
+                        srcs: ["foo.rs"],
+                        crate_name: "foo"
+                }`)
 
 	// Test all variants are being built.
 	libfooRlib := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_rlib").Output("libfoo.rlib")
 	libfooDylib := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_dylib").Output("libfoo.dylib.so")
-	libfooStatic := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_static").Output("libfoo.a")
-	libfooShared := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_shared").Output("libfoo.so")
+	libfooStatic := ctx.ModuleForTests("libfoo.ffi", "linux_glibc_x86_64_static").Output("libfoo.ffi.a")
+	libfooShared := ctx.ModuleForTests("libfoo.ffi", "linux_glibc_x86_64_shared").Output("libfoo.ffi.so")
 
 	rlibCrateType := "rlib"
 	dylibCrateType := "dylib"
@@ -119,7 +124,7 @@
 
 func TestSharedLibrary(t *testing.T) {
 	ctx := testRust(t, `
-		rust_library {
+		rust_ffi_shared {
 			name: "libfoo",
 			srcs: ["foo.rs"],
 			crate_name: "foo",
@@ -138,3 +143,50 @@
 			libfoo.Module().(*Module).Properties.AndroidMkDylibs)
 	}
 }
+
+// Test that variants pull in the right type of rustlib autodep
+func TestAutoDeps(t *testing.T) {
+
+	ctx := testRust(t, `
+                rust_library_host {
+                        name: "libbar",
+                        srcs: ["bar.rs"],
+                        crate_name: "bar",
+                }
+		rust_library_host {
+			name: "libfoo",
+			srcs: ["foo.rs"],
+			crate_name: "foo",
+                        rustlibs: ["libbar"],
+		}
+                rust_ffi_host {
+                        name: "libfoo.ffi",
+                        srcs: ["foo.rs"],
+                        crate_name: "foo",
+                        rustlibs: ["libbar"],
+                }`)
+
+	libfooRlib := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_rlib")
+	libfooDylib := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_dylib")
+	libfooStatic := ctx.ModuleForTests("libfoo.ffi", "linux_glibc_x86_64_static")
+	libfooShared := ctx.ModuleForTests("libfoo.ffi", "linux_glibc_x86_64_shared")
+
+	for _, static := range []android.TestingModule{libfooRlib, libfooStatic} {
+		if !android.InList("libbar", static.Module().(*Module).Properties.AndroidMkRlibs) {
+			t.Errorf("libbar not present as static dependency in static lib")
+		}
+		if android.InList("libbar", static.Module().(*Module).Properties.AndroidMkDylibs) {
+			t.Errorf("libbar present as dynamic dependency in static lib")
+		}
+	}
+
+	for _, dyn := range []android.TestingModule{libfooDylib, libfooShared} {
+		if !android.InList("libbar", dyn.Module().(*Module).Properties.AndroidMkDylibs) {
+			t.Errorf("libbar not present as dynamic dependency in dynamic lib")
+		}
+		if android.InList("libbar", dyn.Module().(*Module).Properties.AndroidMkRlibs) {
+			t.Errorf("libbar present as static dependency in dynamic lib")
+		}
+
+	}
+}
diff --git a/rust/prebuilt.go b/rust/prebuilt.go
index 1d97650..67d649d 100644
--- a/rust/prebuilt.go
+++ b/rust/prebuilt.go
@@ -19,12 +19,16 @@
 )
 
 func init() {
+	android.RegisterModuleType("rust_prebuilt_library", PrebuiltLibraryFactory)
 	android.RegisterModuleType("rust_prebuilt_dylib", PrebuiltDylibFactory)
+	android.RegisterModuleType("rust_prebuilt_rlib", PrebuiltRlibFactory)
 }
 
 type PrebuiltProperties struct {
 	// path to the prebuilt file
 	Srcs []string `android:"path,arch_variant"`
+	// directories containing associated rlib dependencies
+	Link_dirs []string `android:"path,arch_variant"`
 }
 
 type prebuiltLibraryDecorator struct {
@@ -33,32 +37,65 @@
 }
 
 var _ compiler = (*prebuiltLibraryDecorator)(nil)
+var _ exportedFlagsProducer = (*prebuiltLibraryDecorator)(nil)
+
+func PrebuiltLibraryFactory() android.Module {
+	module, _ := NewPrebuiltLibrary(android.HostAndDeviceSupported)
+	return module.Init()
+}
 
 func PrebuiltDylibFactory() android.Module {
 	module, _ := NewPrebuiltDylib(android.HostAndDeviceSupported)
 	return module.Init()
 }
 
-func NewPrebuiltDylib(hod android.HostOrDeviceSupported) (*Module, *prebuiltLibraryDecorator) {
+func PrebuiltRlibFactory() android.Module {
+	module, _ := NewPrebuiltRlib(android.HostAndDeviceSupported)
+	return module.Init()
+}
+
+func NewPrebuiltLibrary(hod android.HostOrDeviceSupported) (*Module, *prebuiltLibraryDecorator) {
 	module, library := NewRustLibrary(hod)
-	library.BuildOnlyDylib()
+	library.BuildOnlyRust()
 	library.setNoStdlibs()
-	library.setDylib()
 	prebuilt := &prebuiltLibraryDecorator{
 		libraryDecorator: library,
 	}
 	module.compiler = prebuilt
-	module.AddProperties(&library.Properties)
+	return module, prebuilt
+}
+
+func NewPrebuiltDylib(hod android.HostOrDeviceSupported) (*Module, *prebuiltLibraryDecorator) {
+	module, library := NewRustLibrary(hod)
+	library.BuildOnlyDylib()
+	library.setNoStdlibs()
+	prebuilt := &prebuiltLibraryDecorator{
+		libraryDecorator: library,
+	}
+	module.compiler = prebuilt
+	return module, prebuilt
+}
+
+func NewPrebuiltRlib(hod android.HostOrDeviceSupported) (*Module, *prebuiltLibraryDecorator) {
+	module, library := NewRustLibrary(hod)
+	library.BuildOnlyRlib()
+	library.setNoStdlibs()
+	prebuilt := &prebuiltLibraryDecorator{
+		libraryDecorator: library,
+	}
+	module.compiler = prebuilt
 	return module, prebuilt
 }
 
 func (prebuilt *prebuiltLibraryDecorator) compilerProps() []interface{} {
-	return append(prebuilt.baseCompiler.compilerProps(),
+	return append(prebuilt.libraryDecorator.compilerProps(),
 		&prebuilt.Properties)
 }
 
 func (prebuilt *prebuiltLibraryDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) android.Path {
-	srcPath := srcPathFromModuleSrcs(ctx, prebuilt.Properties.Srcs)
+	prebuilt.exportLinkDirs(android.PathsForModuleSrc(ctx, prebuilt.Properties.Link_dirs).Strings()...)
+
+	srcPath := srcPathFromModuleSrcs(ctx, prebuilt.prebuiltSrcs())
 
 	prebuilt.unstrippedOutputFile = srcPath
 
@@ -73,3 +110,15 @@
 func (prebuilt *prebuiltLibraryDecorator) nativeCoverage() bool {
 	return false
 }
+
+func (prebuilt *prebuiltLibraryDecorator) prebuiltSrcs() []string {
+	srcs := prebuilt.Properties.Srcs
+	if prebuilt.rlib() {
+		srcs = append(srcs, prebuilt.libraryDecorator.Properties.Rlib.Srcs...)
+	}
+	if prebuilt.dylib() {
+		srcs = append(srcs, prebuilt.libraryDecorator.Properties.Dylib.Srcs...)
+	}
+
+	return srcs
+}
diff --git a/rust/proc_macro.go b/rust/proc_macro.go
index 42c8537..2719161 100644
--- a/rust/proc_macro.go
+++ b/rust/proc_macro.go
@@ -27,6 +27,7 @@
 
 type procMacroDecorator struct {
 	*baseCompiler
+	*flagExporter
 
 	Properties ProcMacroCompilerProperties
 }
@@ -35,6 +36,7 @@
 }
 
 var _ compiler = (*procMacroDecorator)(nil)
+var _ exportedFlagsProducer = (*procMacroDecorator)(nil)
 
 func ProcMacroFactory() android.Module {
 	module, _ := NewProcMacro(android.HostSupportedNoCross)
@@ -46,6 +48,7 @@
 
 	procMacro := &procMacroDecorator{
 		baseCompiler: NewBaseCompiler("lib", "lib64", InstallInSystem),
+		flagExporter: NewFlagExporter(),
 	}
 
 	module.compiler = procMacro
@@ -76,3 +79,7 @@
 
 	return stem + String(procMacro.baseCompiler.Properties.Suffix)
 }
+
+func (procMacro *procMacroDecorator) autoDep() autoDep {
+	return rlibAutoDep
+}
diff --git a/rust/rust.go b/rust/rust.go
index 6c60348..72301a7 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -217,6 +217,7 @@
 type Deps struct {
 	Dylibs     []string
 	Rlibs      []string
+	Rustlibs   []string
 	ProcMacros []string
 	SharedLibs []string
 	StaticLibs []string
@@ -261,6 +262,43 @@
 	nativeCoverage() bool
 }
 
+type exportedFlagsProducer interface {
+	exportedLinkDirs() []string
+	exportedDepFlags() []string
+	exportLinkDirs(...string)
+	exportDepFlags(...string)
+}
+
+type flagExporter struct {
+	depFlags []string
+	linkDirs []string
+}
+
+func (flagExporter *flagExporter) exportedLinkDirs() []string {
+	return flagExporter.linkDirs
+}
+
+func (flagExporter *flagExporter) exportedDepFlags() []string {
+	return flagExporter.depFlags
+}
+
+func (flagExporter *flagExporter) exportLinkDirs(dirs ...string) {
+	flagExporter.linkDirs = android.FirstUniqueStrings(append(flagExporter.linkDirs, dirs...))
+}
+
+func (flagExporter *flagExporter) exportDepFlags(flags ...string) {
+	flagExporter.depFlags = android.FirstUniqueStrings(append(flagExporter.depFlags, flags...))
+}
+
+var _ exportedFlagsProducer = (*flagExporter)(nil)
+
+func NewFlagExporter() *flagExporter {
+	return &flagExporter{
+		depFlags: []string{},
+		linkDirs: []string{},
+	}
+}
+
 func (mod *Module) isCoverageVariant() bool {
 	return mod.coverage.Properties.IsCoverageVariant
 }
@@ -415,7 +453,7 @@
 func (mod *Module) StubsVersions() []string {
 	// For now, Rust has no stubs versions.
 	if mod.compiler != nil {
-		if _, ok := mod.compiler.(*libraryDecorator); ok {
+		if _, ok := mod.compiler.(libraryInterface); ok {
 			return []string{}
 		}
 	}
@@ -439,6 +477,9 @@
 
 func (mod *Module) CoverageFiles() android.Paths {
 	if mod.compiler != nil {
+		if !mod.compiler.nativeCoverage() {
+			return android.Paths{}
+		}
 		if library, ok := mod.compiler.(*libraryDecorator); ok {
 			if library.coverageFile != nil {
 				return android.Paths{library.coverageFile}
@@ -617,6 +658,7 @@
 
 	deps.Rlibs = android.LastUniqueStrings(deps.Rlibs)
 	deps.Dylibs = android.LastUniqueStrings(deps.Dylibs)
+	deps.Rustlibs = android.LastUniqueStrings(deps.Rustlibs)
 	deps.ProcMacros = android.LastUniqueStrings(deps.ProcMacros)
 	deps.SharedLibs = android.LastUniqueStrings(deps.SharedLibs)
 	deps.StaticLibs = android.LastUniqueStrings(deps.StaticLibs)
@@ -639,6 +681,20 @@
 	testPerSrcDepTag = dependencyTag{name: "rust_unit_tests"}
 )
 
+type autoDep struct {
+	variation string
+	depTag    dependencyTag
+}
+
+var (
+	rlibAutoDep  = autoDep{variation: "rlib", depTag: rlibDepTag}
+	dylibAutoDep = autoDep{variation: "dylib", depTag: dylibDepTag}
+)
+
+type autoDeppable interface {
+	autoDep() autoDep
+}
+
 func (mod *Module) begin(ctx BaseModuleContext) {
 	if mod.coverage != nil {
 		mod.coverage.begin(ctx)
@@ -689,19 +745,15 @@
 			}
 
 			//Append the dependencies exportedDirs
-			if lib, ok := rustDep.compiler.(*libraryDecorator); ok {
-				depPaths.linkDirs = append(depPaths.linkDirs, lib.exportedDirs()...)
+			if lib, ok := rustDep.compiler.(exportedFlagsProducer); ok {
+				depPaths.linkDirs = append(depPaths.linkDirs, lib.exportedLinkDirs()...)
 				depPaths.depFlags = append(depPaths.depFlags, lib.exportedDepFlags()...)
 			}
 
-			// Append this dependencies output to this mod's linkDirs so they can be exported to dependencies
-			// This can be probably be refactored by defining a common exporter interface similar to cc's
 			if depTag == dylibDepTag || depTag == rlibDepTag || depTag == procMacroDepTag {
 				linkDir := linkPathFromFilePath(linkFile.Path())
-				if lib, ok := mod.compiler.(*libraryDecorator); ok {
-					lib.linkDirs = append(lib.linkDirs, linkDir)
-				} else if procMacro, ok := mod.compiler.(*procMacroDecorator); ok {
-					procMacro.linkDirs = append(procMacro.linkDirs, linkDir)
+				if lib, ok := mod.compiler.(exportedFlagsProducer); ok {
+					lib.exportLinkDirs(linkDir)
 				}
 			}
 
@@ -752,14 +804,10 @@
 			}
 
 			// Make sure these dependencies are propagated
-			if lib, ok := mod.compiler.(*libraryDecorator); ok && exportDep {
-				lib.linkDirs = append(lib.linkDirs, linkPath)
-				lib.depFlags = append(lib.depFlags, depFlag)
-			} else if procMacro, ok := mod.compiler.(*procMacroDecorator); ok && exportDep {
-				procMacro.linkDirs = append(procMacro.linkDirs, linkPath)
-				procMacro.depFlags = append(procMacro.depFlags, depFlag)
+			if lib, ok := mod.compiler.(exportedFlagsProducer); ok && exportDep {
+				lib.exportLinkDirs(linkPath)
+				lib.exportDepFlags(depFlag)
 			}
-
 		}
 	})
 
@@ -844,6 +892,15 @@
 			{Mutator: "link", Variation: ""}}...),
 		dylibDepTag, deps.Dylibs...)
 
+	if deps.Rustlibs != nil {
+		autoDep := mod.compiler.(autoDeppable).autoDep()
+		actx.AddVariationDependencies(
+			append(commonDepVariations, []blueprint.Variation{
+				{Mutator: "rust_libraries", Variation: autoDep.variation},
+				{Mutator: "link", Variation: ""}}...),
+			autoDep.depTag, deps.Rustlibs...)
+	}
+
 	actx.AddVariationDependencies(append(commonDepVariations,
 		blueprint.Variation{Mutator: "link", Variation: "shared"}),
 		cc.SharedDepTag, deps.SharedLibs...)
diff --git a/rust/rust_test.go b/rust/rust_test.go
index 280c22a..08bc8ca 100644
--- a/rust/rust_test.go
+++ b/rust/rust_test.go
@@ -164,12 +164,12 @@
 // Test to make sure dependencies are being picked up correctly.
 func TestDepsTracking(t *testing.T) {
 	ctx := testRust(t, `
-		rust_library_host_static {
+		rust_ffi_host_static {
 			name: "libstatic",
 			srcs: ["foo.rs"],
 			crate_name: "static",
 		}
-		rust_library_host_shared {
+		rust_ffi_host_shared {
 			name: "libshared",
 			srcs: ["foo.rs"],
 			crate_name: "shared",
diff --git a/rust/test.go b/rust/test.go
index 416c557..e27a70c 100644
--- a/rust/test.go
+++ b/rust/test.go
@@ -105,6 +105,10 @@
 	return flags
 }
 
+func (test *testDecorator) autoDep() autoDep {
+	return rlibAutoDep
+}
+
 func init() {
 	// Rust tests are binary files built with --test.
 	android.RegisterModuleType("rust_test", RustTestFactory)
diff --git a/rust/testing.go b/rust/testing.go
index 4e186d3..3d583e1 100644
--- a/rust/testing.go
+++ b/rust/testing.go
@@ -21,14 +21,26 @@
 
 func GatherRequiredDepsForTest() string {
 	bp := `
-		rust_prebuilt_dylib {
+		rust_prebuilt_library {
 				name: "libstd_x86_64-unknown-linux-gnu",
-				srcs: [""],
+                                crate_name: "std",
+                                rlib: {
+                                    srcs: ["libstd.rlib"],
+                                },
+                                dylib: {
+                                    srcs: ["libstd.so"],
+                                },
 				host_supported: true,
 		}
-		rust_prebuilt_dylib {
+		rust_prebuilt_library {
 				name: "libtest_x86_64-unknown-linux-gnu",
-				srcs: [""],
+                                crate_name: "test",
+                                rlib: {
+                                    srcs: ["libtest.rlib"],
+                                },
+                                dylib: {
+                                    srcs: ["libtest.so"],
+                                },
 				host_supported: true,
 		}
 
@@ -41,34 +53,21 @@
 			nocrt: true,
 			system_shared_libs: [],
 		}
-		rust_library_dylib {
+		rust_library {
 			name: "libstd",
 			crate_name: "std",
 			srcs: ["foo.rs"],
 			no_stdlibs: true,
 			host_supported: true,
+                        native_coverage: false,
 		}
-		rust_library_rlib {
-			name: "libstd.static",
-			crate_name: "std",
-			srcs: ["foo.rs"],
-			no_stdlibs: true,
-			host_supported: true,
-		}
-		rust_library_dylib {
+		rust_library {
 			name: "libtest",
 			crate_name: "test",
 			srcs: ["foo.rs"],
 			no_stdlibs: true,
 			host_supported: true,
-
-		}
-		rust_library_rlib {
-			name: "libtest.static",
-			crate_name: "test",
-			srcs: ["foo.rs"],
-			no_stdlibs: true,
-			host_supported: true,
+                        native_coverage: false,
 		}
 
 ` + cc.GatherRequiredDepsForTest(android.NoOsType)
@@ -83,17 +82,21 @@
 	ctx.RegisterModuleType("rust_test", RustTestFactory)
 	ctx.RegisterModuleType("rust_test_host", RustTestHostFactory)
 	ctx.RegisterModuleType("rust_library", RustLibraryFactory)
-	ctx.RegisterModuleType("rust_library_host", RustLibraryHostFactory)
-	ctx.RegisterModuleType("rust_library_host_rlib", RustLibraryRlibHostFactory)
-	ctx.RegisterModuleType("rust_library_host_dylib", RustLibraryDylibHostFactory)
-	ctx.RegisterModuleType("rust_library_rlib", RustLibraryRlibFactory)
 	ctx.RegisterModuleType("rust_library_dylib", RustLibraryDylibFactory)
-	ctx.RegisterModuleType("rust_library_shared", RustLibrarySharedFactory)
-	ctx.RegisterModuleType("rust_library_static", RustLibraryStaticFactory)
-	ctx.RegisterModuleType("rust_library_host_shared", RustLibrarySharedHostFactory)
-	ctx.RegisterModuleType("rust_library_host_static", RustLibraryStaticHostFactory)
+	ctx.RegisterModuleType("rust_library_rlib", RustLibraryRlibFactory)
+	ctx.RegisterModuleType("rust_library_host", RustLibraryHostFactory)
+	ctx.RegisterModuleType("rust_library_host_dylib", RustLibraryDylibHostFactory)
+	ctx.RegisterModuleType("rust_library_host_rlib", RustLibraryRlibHostFactory)
+	ctx.RegisterModuleType("rust_ffi", RustFFIFactory)
+	ctx.RegisterModuleType("rust_ffi_shared", RustFFISharedFactory)
+	ctx.RegisterModuleType("rust_ffi_static", RustFFIStaticFactory)
+	ctx.RegisterModuleType("rust_ffi_host", RustFFIHostFactory)
+	ctx.RegisterModuleType("rust_ffi_host_shared", RustFFISharedHostFactory)
+	ctx.RegisterModuleType("rust_ffi_host_static", RustFFIStaticHostFactory)
 	ctx.RegisterModuleType("rust_proc_macro", ProcMacroFactory)
+	ctx.RegisterModuleType("rust_prebuilt_library", PrebuiltLibraryFactory)
 	ctx.RegisterModuleType("rust_prebuilt_dylib", PrebuiltDylibFactory)
+	ctx.RegisterModuleType("rust_prebuilt_rlib", PrebuiltRlibFactory)
 	ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
 		// rust mutators
 		ctx.BottomUp("rust_libraries", LibraryMutator).Parallel()