Merge "Add license_kinds for CDDL"
diff --git a/android/module.go b/android/module.go
index a20dc56..dcc2b84 100644
--- a/android/module.go
+++ b/android/module.go
@@ -1885,19 +1885,11 @@
 }
 
 func (e *earlyModuleContext) Glob(globPattern string, excludes []string) Paths {
-	ret, err := e.GlobWithDeps(globPattern, excludes)
-	if err != nil {
-		e.ModuleErrorf("glob: %s", err.Error())
-	}
-	return pathsForModuleSrcFromFullPath(e, ret, true)
+	return Glob(e, globPattern, excludes)
 }
 
 func (e *earlyModuleContext) GlobFiles(globPattern string, excludes []string) Paths {
-	ret, err := e.GlobWithDeps(globPattern, excludes)
-	if err != nil {
-		e.ModuleErrorf("glob: %s", err.Error())
-	}
-	return pathsForModuleSrcFromFullPath(e, ret, false)
+	return GlobFiles(e, globPattern, excludes)
 }
 
 func (b *earlyModuleContext) IsSymlink(path Path) bool {
diff --git a/android/paths.go b/android/paths.go
index 592b9e1..b5a1401 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -51,6 +51,53 @@
 func (NullPathContext) AddNinjaFileDeps(...string) {}
 func (ctx NullPathContext) Config() Config         { return ctx.config }
 
+// EarlyModulePathContext is a subset of EarlyModuleContext methods required by the
+// Path methods. These path methods can be called before any mutators have run.
+type EarlyModulePathContext interface {
+	PathContext
+	PathGlobContext
+
+	ModuleDir() string
+	ModuleErrorf(fmt string, args ...interface{})
+}
+
+var _ EarlyModulePathContext = ModuleContext(nil)
+
+// Glob globs files and directories matching globPattern relative to ModuleDir(),
+// paths in the excludes parameter will be omitted.
+func Glob(ctx EarlyModulePathContext, globPattern string, excludes []string) Paths {
+	ret, err := ctx.GlobWithDeps(globPattern, excludes)
+	if err != nil {
+		ctx.ModuleErrorf("glob: %s", err.Error())
+	}
+	return pathsForModuleSrcFromFullPath(ctx, ret, true)
+}
+
+// GlobFiles globs *only* files (not directories) matching globPattern relative to ModuleDir().
+// Paths in the excludes parameter will be omitted.
+func GlobFiles(ctx EarlyModulePathContext, globPattern string, excludes []string) Paths {
+	ret, err := ctx.GlobWithDeps(globPattern, excludes)
+	if err != nil {
+		ctx.ModuleErrorf("glob: %s", err.Error())
+	}
+	return pathsForModuleSrcFromFullPath(ctx, ret, false)
+}
+
+// ModuleWithDepsPathContext is a subset of *ModuleContext methods required by
+// the Path methods that rely on module dependencies having been resolved.
+type ModuleWithDepsPathContext interface {
+	EarlyModulePathContext
+	GetDirectDepWithTag(name string, tag blueprint.DependencyTag) blueprint.Module
+}
+
+// ModuleMissingDepsPathContext is a subset of *ModuleContext methods required by
+// the Path methods that rely on module dependencies having been resolved and ability to report
+// missing dependency errors.
+type ModuleMissingDepsPathContext interface {
+	ModuleWithDepsPathContext
+	AddMissingDependencies(missingDeps []string)
+}
+
 type ModuleInstallPathContext interface {
 	BaseModuleContext
 
@@ -143,18 +190,18 @@
 }
 
 type genPathProvider interface {
-	genPathWithExt(ctx ModuleContext, subdir, ext string) ModuleGenPath
+	genPathWithExt(ctx ModuleOutPathContext, subdir, ext string) ModuleGenPath
 }
 type objPathProvider interface {
-	objPathWithExt(ctx ModuleContext, subdir, ext string) ModuleObjPath
+	objPathWithExt(ctx ModuleOutPathContext, subdir, ext string) ModuleObjPath
 }
 type resPathProvider interface {
-	resPathWithName(ctx ModuleContext, name string) ModuleResPath
+	resPathWithName(ctx ModuleOutPathContext, name string) ModuleResPath
 }
 
 // GenPathWithExt derives a new file path in ctx's generated sources directory
 // from the current path, but with the new extension.
-func GenPathWithExt(ctx ModuleContext, subdir string, p Path, ext string) ModuleGenPath {
+func GenPathWithExt(ctx ModuleOutPathContext, subdir string, p Path, ext string) ModuleGenPath {
 	if path, ok := p.(genPathProvider); ok {
 		return path.genPathWithExt(ctx, subdir, ext)
 	}
@@ -164,7 +211,7 @@
 
 // ObjPathWithExt derives a new file path in ctx's object directory from the
 // current path, but with the new extension.
-func ObjPathWithExt(ctx ModuleContext, subdir string, p Path, ext string) ModuleObjPath {
+func ObjPathWithExt(ctx ModuleOutPathContext, subdir string, p Path, ext string) ModuleObjPath {
 	if path, ok := p.(objPathProvider); ok {
 		return path.objPathWithExt(ctx, subdir, ext)
 	}
@@ -175,7 +222,7 @@
 // ResPathWithName derives a new path in ctx's output resource directory, using
 // the current path to create the directory name, and the `name` argument for
 // the filename.
-func ResPathWithName(ctx ModuleContext, p Path, name string) ModuleResPath {
+func ResPathWithName(ctx ModuleOutPathContext, p Path, name string) ModuleResPath {
 	if path, ok := p.(resPathProvider); ok {
 		return path.resPathWithName(ctx, name)
 	}
@@ -261,7 +308,7 @@
 // `android:"path"` so that dependencies on SourceFileProducer modules will have already been handled by the
 // path_properties mutator.  If ctx.Config().AllowMissingDependencies() is true then any missing SourceFileProducer or
 // OutputFileProducer dependencies will cause the module to be marked as having missing dependencies.
-func PathsForModuleSrc(ctx ModuleContext, paths []string) Paths {
+func PathsForModuleSrc(ctx ModuleMissingDepsPathContext, paths []string) Paths {
 	return PathsForModuleSrcExcludes(ctx, paths, nil)
 }
 
@@ -272,7 +319,7 @@
 // will have already been handled by the path_properties mutator.  If ctx.Config().AllowMissingDependencies() is
 // true then any missing SourceFileProducer or OutputFileProducer dependencies will cause the module to be marked as
 // having missing dependencies.
-func PathsForModuleSrcExcludes(ctx ModuleContext, paths, excludes []string) Paths {
+func PathsForModuleSrcExcludes(ctx ModuleMissingDepsPathContext, paths, excludes []string) Paths {
 	ret, missingDeps := PathsAndMissingDepsForModuleSrcExcludes(ctx, paths, excludes)
 	if ctx.Config().AllowMissingDependencies() {
 		ctx.AddMissingDependencies(missingDeps)
@@ -311,6 +358,29 @@
 	return ret
 }
 
+// Expands Paths to a SourceFileProducer or OutputFileProducer module dependency referenced via ":name" or ":name{.tag}" syntax.
+// If the dependency is not found, a missingErrorDependency is returned.
+// If the module dependency is not a SourceFileProducer or OutputFileProducer, appropriate errors will be returned.
+func getPathsFromModuleDep(ctx ModuleWithDepsPathContext, path, moduleName, tag string) (Paths, error) {
+	module := ctx.GetDirectDepWithTag(moduleName, sourceOrOutputDepTag(tag))
+	if module == nil {
+		return nil, missingDependencyError{[]string{moduleName}}
+	}
+	if outProducer, ok := module.(OutputFileProducer); ok {
+		outputFiles, err := outProducer.OutputFiles(tag)
+		if err != nil {
+			return nil, fmt.Errorf("path dependency %q: %s", path, err)
+		}
+		return outputFiles, nil
+	} else if tag != "" {
+		return nil, fmt.Errorf("path dependency %q is not an output file producing module", path)
+	} else if srcProducer, ok := module.(SourceFileProducer); ok {
+		return srcProducer.Srcs(), nil
+	} else {
+		return nil, fmt.Errorf("path dependency %q is not a source file producing module", path)
+	}
+}
+
 // PathsAndMissingDepsForModuleSrcExcludes returns Paths rooted from the module's local source directory, excluding
 // paths listed in the excludes arguments, and a list of missing dependencies.  It expands globs, references to
 // SourceFileProducer modules using the ":name" syntax, and references to OutputFileProducer modules using the
@@ -319,7 +389,7 @@
 // path_properties mutator.  If ctx.Config().AllowMissingDependencies() is true then any missing SourceFileProducer or
 // OutputFileProducer dependencies will be returned, and they will NOT cause the module to be marked as having missing
 // dependencies.
-func PathsAndMissingDepsForModuleSrcExcludes(ctx ModuleContext, paths, excludes []string) (Paths, []string) {
+func PathsAndMissingDepsForModuleSrcExcludes(ctx ModuleWithDepsPathContext, paths, excludes []string) (Paths, []string) {
 	prefix := pathForModuleSrc(ctx).String()
 
 	var expandedExcludes []string
@@ -331,23 +401,13 @@
 
 	for _, e := range excludes {
 		if m, t := SrcIsModuleWithTag(e); m != "" {
-			module := ctx.GetDirectDepWithTag(m, sourceOrOutputDepTag(t))
-			if module == nil {
-				missingExcludeDeps = append(missingExcludeDeps, m)
-				continue
-			}
-			if outProducer, ok := module.(OutputFileProducer); ok {
-				outputFiles, err := outProducer.OutputFiles(t)
-				if err != nil {
-					ctx.ModuleErrorf("path dependency %q: %s", e, err)
-				}
-				expandedExcludes = append(expandedExcludes, outputFiles.Strings()...)
-			} else if t != "" {
-				ctx.ModuleErrorf("path dependency %q is not an output file producing module", e)
-			} else if srcProducer, ok := module.(SourceFileProducer); ok {
-				expandedExcludes = append(expandedExcludes, srcProducer.Srcs().Strings()...)
+			modulePaths, err := getPathsFromModuleDep(ctx, e, m, t)
+			if m, ok := err.(missingDependencyError); ok {
+				missingExcludeDeps = append(missingExcludeDeps, m.missingDeps...)
+			} else if err != nil {
+				reportPathError(ctx, err)
 			} else {
-				ctx.ModuleErrorf("path dependency %q is not a source file producing module", e)
+				expandedExcludes = append(expandedExcludes, modulePaths.Strings()...)
 			}
 		} else {
 			expandedExcludes = append(expandedExcludes, filepath.Join(prefix, e))
@@ -382,7 +442,10 @@
 	return "missing dependencies: " + strings.Join(e.missingDeps, ", ")
 }
 
-func expandOneSrcPath(ctx ModuleContext, s string, expandedExcludes []string) (Paths, error) {
+// Expands one path string to Paths rooted from the module's local source
+// directory, excluding those listed in the expandedExcludes.
+// Expands globs, references to SourceFileProducer or OutputFileProducer modules using the ":name" and ":name{.tag}" syntax.
+func expandOneSrcPath(ctx ModuleWithDepsPathContext, sPath string, expandedExcludes []string) (Paths, error) {
 	excludePaths := func(paths Paths) Paths {
 		if len(expandedExcludes) == 0 {
 			return paths
@@ -395,29 +458,18 @@
 		}
 		return remainder
 	}
-	if m, t := SrcIsModuleWithTag(s); m != "" {
-		module := ctx.GetDirectDepWithTag(m, sourceOrOutputDepTag(t))
-		if module == nil {
-			return nil, missingDependencyError{[]string{m}}
-		}
-		if outProducer, ok := module.(OutputFileProducer); ok {
-			outputFiles, err := outProducer.OutputFiles(t)
-			if err != nil {
-				return nil, fmt.Errorf("path dependency %q: %s", s, err)
-			}
-			return excludePaths(outputFiles), nil
-		} else if t != "" {
-			return nil, fmt.Errorf("path dependency %q is not an output file producing module", s)
-		} else if srcProducer, ok := module.(SourceFileProducer); ok {
-			return excludePaths(srcProducer.Srcs()), nil
+	if m, t := SrcIsModuleWithTag(sPath); m != "" {
+		modulePaths, err := getPathsFromModuleDep(ctx, sPath, m, t)
+		if err != nil {
+			return nil, err
 		} else {
-			return nil, fmt.Errorf("path dependency %q is not a source file producing module", s)
+			return excludePaths(modulePaths), nil
 		}
-	} else if pathtools.IsGlob(s) {
-		paths := ctx.GlobFiles(pathForModuleSrc(ctx, s).String(), expandedExcludes)
+	} else if pathtools.IsGlob(sPath) {
+		paths := GlobFiles(ctx, pathForModuleSrc(ctx, sPath).String(), expandedExcludes)
 		return PathsWithModuleSrcSubDir(ctx, paths, ""), nil
 	} else {
-		p := pathForModuleSrc(ctx, s)
+		p := pathForModuleSrc(ctx, sPath)
 		if exists, _, err := ctx.Config().fs.Exists(p.String()); err != nil {
 			ReportPathErrorf(ctx, "%s: %s", p, err.Error())
 		} else if !exists && !ctx.Config().testAllowNonExistentPaths {
@@ -436,7 +488,7 @@
 // each string. If incDirs is false, strip paths with a trailing '/' from the list.
 // It intended for use in globs that only list files that exist, so it allows '$' in
 // filenames.
-func pathsForModuleSrcFromFullPath(ctx EarlyModuleContext, paths []string, incDirs bool) Paths {
+func pathsForModuleSrcFromFullPath(ctx EarlyModulePathContext, paths []string, incDirs bool) Paths {
 	prefix := filepath.Join(ctx.Config().srcDir, ctx.ModuleDir()) + "/"
 	if prefix == "./" {
 		prefix = ""
@@ -465,16 +517,16 @@
 	return ret
 }
 
-// PathsWithOptionalDefaultForModuleSrc returns Paths rooted from the module's
-// local source directory. If input is nil, use the default if it exists.  If input is empty, returns nil.
-func PathsWithOptionalDefaultForModuleSrc(ctx ModuleContext, input []string, def string) Paths {
+// PathsWithOptionalDefaultForModuleSrc returns Paths rooted from the module's local source
+// directory. If input is nil, use the default if it exists.  If input is empty, returns nil.
+func PathsWithOptionalDefaultForModuleSrc(ctx ModuleMissingDepsPathContext, input []string, def string) Paths {
 	if input != nil {
 		return PathsForModuleSrc(ctx, input)
 	}
 	// Use Glob so that if the default doesn't exist, a dependency is added so that when it
 	// is created, we're run again.
 	path := filepath.Join(ctx.Config().srcDir, ctx.ModuleDir(), def)
-	return ctx.Glob(path, nil)
+	return Glob(ctx, path, nil)
 }
 
 // Strings returns the Paths in string form
@@ -846,7 +898,7 @@
 		ReportPathErrorf(ctx, "path may not contain a glob: %s", path.String())
 	}
 
-	if modCtx, ok := ctx.(ModuleContext); ok && ctx.Config().AllowMissingDependencies() {
+	if modCtx, ok := ctx.(ModuleMissingDepsPathContext); ok && ctx.Config().AllowMissingDependencies() {
 		exists, err := existsWithDependencies(ctx, path)
 		if err != nil {
 			reportPathError(ctx, err)
@@ -913,7 +965,7 @@
 
 // OverlayPath returns the overlay for `path' if it exists. This assumes that the
 // SourcePath is the path to a resource overlay directory.
-func (p SourcePath) OverlayPath(ctx ModuleContext, path Path) OptionalPath {
+func (p SourcePath) OverlayPath(ctx ModuleMissingDepsPathContext, path Path) OptionalPath {
 	var relDir string
 	if srcPath, ok := path.(SourcePath); ok {
 		relDir = srcPath.path
@@ -1054,7 +1106,7 @@
 
 // PathForModuleSrc returns a Path representing the paths... under the
 // module's local source directory.
-func PathForModuleSrc(ctx ModuleContext, pathComponents ...string) Path {
+func PathForModuleSrc(ctx ModuleMissingDepsPathContext, pathComponents ...string) Path {
 	p, err := validatePath(pathComponents...)
 	if err != nil {
 		reportPathError(ctx, err)
@@ -1080,7 +1132,7 @@
 	return paths[0]
 }
 
-func pathForModuleSrc(ctx ModuleContext, paths ...string) SourcePath {
+func pathForModuleSrc(ctx EarlyModulePathContext, paths ...string) SourcePath {
 	p, err := validatePath(paths...)
 	if err != nil {
 		reportPathError(ctx, err)
@@ -1099,7 +1151,7 @@
 // PathsWithModuleSrcSubDir takes a list of Paths and returns a new list of Paths where Rel() on each path
 // will return the path relative to subDir in the module's source directory.  If any input paths are not located
 // inside subDir then a path error will be reported.
-func PathsWithModuleSrcSubDir(ctx ModuleContext, paths Paths, subDir string) Paths {
+func PathsWithModuleSrcSubDir(ctx EarlyModulePathContext, paths Paths, subDir string) Paths {
 	paths = append(Paths(nil), paths...)
 	subDirFullPath := pathForModuleSrc(ctx, subDir)
 	for i, path := range paths {
@@ -1111,7 +1163,7 @@
 
 // PathWithModuleSrcSubDir takes a Path and returns a Path where Rel() will return the path relative to subDir in the
 // module's source directory.  If the input path is not located inside subDir then a path error will be reported.
-func PathWithModuleSrcSubDir(ctx ModuleContext, path Path, subDir string) Path {
+func PathWithModuleSrcSubDir(ctx EarlyModulePathContext, path Path, subDir string) Path {
 	subDirFullPath := pathForModuleSrc(ctx, subDir)
 	rel := Rel(ctx, subDirFullPath.String(), path.String())
 	return subDirFullPath.Join(ctx, rel)
@@ -1119,22 +1171,22 @@
 
 // OptionalPathForModuleSrc returns an OptionalPath. The OptionalPath contains a
 // valid path if p is non-nil.
-func OptionalPathForModuleSrc(ctx ModuleContext, p *string) OptionalPath {
+func OptionalPathForModuleSrc(ctx ModuleMissingDepsPathContext, p *string) OptionalPath {
 	if p == nil {
 		return OptionalPath{}
 	}
 	return OptionalPathForPath(PathForModuleSrc(ctx, *p))
 }
 
-func (p SourcePath) genPathWithExt(ctx ModuleContext, subdir, ext string) ModuleGenPath {
+func (p SourcePath) genPathWithExt(ctx ModuleOutPathContext, subdir, ext string) ModuleGenPath {
 	return PathForModuleGen(ctx, subdir, pathtools.ReplaceExtension(p.path, ext))
 }
 
-func (p SourcePath) objPathWithExt(ctx ModuleContext, subdir, ext string) ModuleObjPath {
+func (p SourcePath) objPathWithExt(ctx ModuleOutPathContext, subdir, ext string) ModuleObjPath {
 	return PathForModuleObj(ctx, subdir, pathtools.ReplaceExtension(p.path, ext))
 }
 
-func (p SourcePath) resPathWithName(ctx ModuleContext, name string) ModuleResPath {
+func (p SourcePath) resPathWithName(ctx ModuleOutPathContext, name string) ModuleResPath {
 	// TODO: Use full directory if the new ctx is not the current ctx?
 	return PathForModuleRes(ctx, p.path, name)
 }
@@ -1146,11 +1198,20 @@
 
 var _ Path = ModuleOutPath{}
 
-func (p ModuleOutPath) objPathWithExt(ctx ModuleContext, subdir, ext string) ModuleObjPath {
+func (p ModuleOutPath) objPathWithExt(ctx ModuleOutPathContext, subdir, ext string) ModuleObjPath {
 	return PathForModuleObj(ctx, subdir, pathtools.ReplaceExtension(p.path, ext))
 }
 
-func pathForModule(ctx ModuleContext) OutputPath {
+// ModuleOutPathContext Subset of ModuleContext functions necessary for output path methods.
+type ModuleOutPathContext interface {
+	PathContext
+
+	ModuleName() string
+	ModuleDir() string
+	ModuleSubDir() string
+}
+
+func pathForModuleOut(ctx ModuleOutPathContext) OutputPath {
 	return PathForOutput(ctx, ".intermediates", ctx.ModuleDir(), ctx.ModuleName(), ctx.ModuleSubDir())
 }
 
@@ -1161,13 +1222,13 @@
 var _ Path = BazelOutPath{}
 var _ objPathProvider = BazelOutPath{}
 
-func (p BazelOutPath) objPathWithExt(ctx ModuleContext, subdir, ext string) ModuleObjPath {
+func (p BazelOutPath) objPathWithExt(ctx ModuleOutPathContext, subdir, ext string) ModuleObjPath {
 	return PathForModuleObj(ctx, subdir, pathtools.ReplaceExtension(p.path, ext))
 }
 
 // PathForVndkRefAbiDump returns an OptionalPath representing the path of the
 // reference abi dump for the given module. This is not guaranteed to be valid.
-func PathForVndkRefAbiDump(ctx ModuleContext, version, fileName string,
+func PathForVndkRefAbiDump(ctx ModuleInstallPathContext, version, fileName string,
 	isNdk, isLlndkOrVndk, isGzip bool) OptionalPath {
 
 	arches := ctx.DeviceConfig().Arches()
@@ -1223,13 +1284,13 @@
 
 // PathForModuleOut returns a Path representing the paths... under the module's
 // output directory.
-func PathForModuleOut(ctx ModuleContext, paths ...string) ModuleOutPath {
+func PathForModuleOut(ctx ModuleOutPathContext, paths ...string) ModuleOutPath {
 	p, err := validatePath(paths...)
 	if err != nil {
 		reportPathError(ctx, err)
 	}
 	return ModuleOutPath{
-		OutputPath: pathForModule(ctx).withRel(p),
+		OutputPath: pathForModuleOut(ctx).withRel(p),
 	}
 }
 
@@ -1245,24 +1306,24 @@
 
 // PathForModuleGen returns a Path representing the paths... under the module's
 // `gen' directory.
-func PathForModuleGen(ctx ModuleContext, paths ...string) ModuleGenPath {
+func PathForModuleGen(ctx ModuleOutPathContext, paths ...string) ModuleGenPath {
 	p, err := validatePath(paths...)
 	if err != nil {
 		reportPathError(ctx, err)
 	}
 	return ModuleGenPath{
 		ModuleOutPath: ModuleOutPath{
-			OutputPath: pathForModule(ctx).withRel("gen").withRel(p),
+			OutputPath: pathForModuleOut(ctx).withRel("gen").withRel(p),
 		},
 	}
 }
 
-func (p ModuleGenPath) genPathWithExt(ctx ModuleContext, subdir, ext string) ModuleGenPath {
+func (p ModuleGenPath) genPathWithExt(ctx ModuleOutPathContext, subdir, ext string) ModuleGenPath {
 	// TODO: make a different path for local vs remote generated files?
 	return PathForModuleGen(ctx, subdir, pathtools.ReplaceExtension(p.path, ext))
 }
 
-func (p ModuleGenPath) objPathWithExt(ctx ModuleContext, subdir, ext string) ModuleObjPath {
+func (p ModuleGenPath) objPathWithExt(ctx ModuleOutPathContext, subdir, ext string) ModuleObjPath {
 	return PathForModuleObj(ctx, subdir, pathtools.ReplaceExtension(p.path, ext))
 }
 
@@ -1276,7 +1337,7 @@
 
 // PathForModuleObj returns a Path representing the paths... under the module's
 // 'obj' directory.
-func PathForModuleObj(ctx ModuleContext, pathComponents ...string) ModuleObjPath {
+func PathForModuleObj(ctx ModuleOutPathContext, pathComponents ...string) ModuleObjPath {
 	p, err := validatePath(pathComponents...)
 	if err != nil {
 		reportPathError(ctx, err)
@@ -1294,7 +1355,7 @@
 
 // PathForModuleRes returns a Path representing the paths... under the module's
 // 'res' directory.
-func PathForModuleRes(ctx ModuleContext, pathComponents ...string) ModuleResPath {
+func PathForModuleRes(ctx ModuleOutPathContext, pathComponents ...string) ModuleResPath {
 	p, err := validatePath(pathComponents...)
 	if err != nil {
 		reportPathError(ctx, err)
diff --git a/apex/apex_test.go b/apex/apex_test.go
index b1e8480..efe3e04 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -4213,9 +4213,11 @@
 	}
 }
 
+// These tests verify that the prebuilt_apex/deapexer to java_import wiring allows for the
+// propagation of paths to dex implementation jars from the former to the latter.
 func TestPrebuiltExportDexImplementationJars(t *testing.T) {
 	transform := func(config *dexpreopt.GlobalConfig) {
-		config.BootJars = android.CreateTestConfiguredJarList([]string{"myapex:libfoo"})
+		// Empty transformation.
 	}
 
 	checkDexJarBuildPath := func(ctx *android.TestContext, name string) {
@@ -4298,7 +4300,6 @@
 		bp := `
 		prebuilt_apex {
 			name: "myapex",
-			prefer: true,
 			arch: {
 				arm64: {
 					src: "myapex-arm64.apex",
@@ -4312,6 +4313,7 @@
 
 		java_import {
 			name: "libfoo",
+			prefer: true,
 			jars: ["libfoo.jar"],
 		}
 
@@ -5925,7 +5927,6 @@
 
 	bp += cc.GatherRequiredDepsForTest(android.Android)
 	bp += java.GatherRequiredDepsForTest()
-	bp += dexpreopt.BpToolModulesForTest()
 
 	fs := map[string][]byte{
 		"a.java":                             nil,
@@ -5957,7 +5958,6 @@
 
 	ctx.Register()
 
-	dexpreopt.RegisterToolModulesForTest(ctx)
 	pathCtx := android.PathContextForTesting(config)
 	dexpreoptConfig := dexpreopt.GlobalConfigForTests(pathCtx)
 	transformDexpreoptConfig(dexpreoptConfig)
diff --git a/bp2build/build_conversion.go b/bp2build/build_conversion.go
index 8284ae3..a7c3adb 100644
--- a/bp2build/build_conversion.go
+++ b/bp2build/build_conversion.go
@@ -67,6 +67,17 @@
 	QueryView
 )
 
+func (mode CodegenMode) String() string {
+	switch mode {
+	case Bp2Build:
+		return "Bp2Build"
+	case QueryView:
+		return "QueryView"
+	default:
+		return fmt.Sprintf("%d", mode)
+	}
+}
+
 func (ctx CodegenContext) AddNinjaFileDeps(...string) {}
 func (ctx CodegenContext) Config() android.Config     { return ctx.config }
 func (ctx CodegenContext) Context() android.Context   { return ctx.context }
diff --git a/cc/cc.go b/cc/cc.go
index 8755efe..afa6bf9 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -390,6 +390,17 @@
 	// Nothing happens if BOARD_VNDK_VERSION isn't set in the BoardConfig.mk
 	Vendor_available *bool
 
+	// This is the same as the "vendor_available" except that the install path
+	// of the vendor variant is /odm or /vendor/odm.
+	// By replacing "vendor_available: true" with "odm_available: true", the
+	// module will install its vendor variant to the /odm partition or /vendor/odm.
+	// As the modules with "odm_available: true" still create the vendor variants,
+	// they can link to the other vendor modules as the vendor_available modules do.
+	// Also, the vendor modules can link to odm_available modules.
+	//
+	// It may not be used for VNDK modules.
+	Odm_available *bool
+
 	// whether this module should be allowed to be directly depended by other
 	// modules with `product_specific: true` or `product_available: true`.
 	// If set to true, an additional product variant will be built separately
diff --git a/cc/genrule.go b/cc/genrule.go
index 1ce2169..ca4fda7 100644
--- a/cc/genrule.go
+++ b/cc/genrule.go
@@ -25,6 +25,7 @@
 
 type GenruleExtraProperties struct {
 	Vendor_available         *bool
+	Odm_available            *bool
 	Product_available        *bool
 	Ramdisk_available        *bool
 	Vendor_ramdisk_available *bool
@@ -63,7 +64,7 @@
 		return false
 	}
 
-	return Bool(g.Vendor_available) || Bool(g.Product_available) || !(ctx.SocSpecific() || ctx.DeviceSpecific())
+	return !(ctx.SocSpecific() || ctx.DeviceSpecific())
 }
 
 func (g *GenruleExtraProperties) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
@@ -92,7 +93,7 @@
 	}
 
 	var variants []string
-	if Bool(g.Vendor_available) || ctx.SocSpecific() || ctx.DeviceSpecific() {
+	if Bool(g.Vendor_available) || Bool(g.Odm_available) || ctx.SocSpecific() || ctx.DeviceSpecific() {
 		vndkVersion := ctx.DeviceConfig().VndkVersion()
 		// If vndkVersion is current, we can always use PlatformVndkVersion.
 		// If not, we assume modules under proprietary paths are compatible for
diff --git a/cc/image.go b/cc/image.go
index f89194f..231da7e 100644
--- a/cc/image.go
+++ b/cc/image.go
@@ -56,8 +56,14 @@
 
 func (ctx *moduleContext) SocSpecific() bool {
 	// Additionally check if this module is inVendor() that means it is a "vendor" variant of a
-	// module. As well as SoC specific modules, vendor variants must be installed to /vendor.
-	return ctx.ModuleContext.SocSpecific() || ctx.mod.InVendor()
+	// module. As well as SoC specific modules, vendor variants must be installed to /vendor
+	// unless they have "odm_available: true".
+	return ctx.ModuleContext.SocSpecific() || (ctx.mod.InVendor() && !ctx.mod.VendorVariantToOdm())
+}
+
+func (ctx *moduleContext) DeviceSpecific() bool {
+	// Some vendor variants want to be installed to /odm by setting "odm_available: true".
+	return ctx.ModuleContext.DeviceSpecific() || (ctx.mod.InVendor() && ctx.mod.VendorVariantToOdm())
 }
 
 func (ctx *moduleContextImpl) inProduct() bool {
@@ -82,7 +88,13 @@
 
 // Returns true when this module is configured to have core and vendor variants.
 func (c *Module) HasVendorVariant() bool {
-	return Bool(c.VendorProperties.Vendor_available)
+	return Bool(c.VendorProperties.Vendor_available) || Bool(c.VendorProperties.Odm_available)
+}
+
+// Returns true when this module creates a vendor variant and wants to install the vendor variant
+// to the odm partition.
+func (c *Module) VendorVariantToOdm() bool {
+	return Bool(c.VendorProperties.Odm_available)
 }
 
 // Returns true when this module is configured to have core and product variants.
@@ -183,7 +195,18 @@
 	if Bool(m.VendorProperties.Vendor_available) {
 		if vendorSpecific {
 			mctx.PropertyErrorf("vendor_available",
-				"doesn't make sense at the same time as `vendor: true`, `proprietary: true`, or `device_specific:true`")
+				"doesn't make sense at the same time as `vendor: true`, `proprietary: true`, or `device_specific: true`")
+		}
+		if Bool(m.VendorProperties.Odm_available) {
+			mctx.PropertyErrorf("vendor_available",
+				"doesn't make sense at the same time as `odm_available: true`")
+		}
+	}
+
+	if Bool(m.VendorProperties.Odm_available) {
+		if vendorSpecific {
+			mctx.PropertyErrorf("odm_available",
+				"doesn't make sense at the same time as `vendor: true`, `proprietary: true`, or `device_specific: true`")
 		}
 	}
 
diff --git a/cc/library_sdk_member.go b/cc/library_sdk_member.go
index 3f2cf49..1402991 100644
--- a/cc/library_sdk_member.go
+++ b/cc/library_sdk_member.go
@@ -130,6 +130,10 @@
 		pbm.AddProperty("vendor_available", true)
 	}
 
+	if proptools.Bool(ccModule.VendorProperties.Odm_available) {
+		pbm.AddProperty("odm_available", true)
+	}
+
 	if proptools.Bool(ccModule.VendorProperties.Product_available) {
 		pbm.AddProperty("product_available", true)
 	}
diff --git a/dexpreopt/testing.go b/dexpreopt/testing.go
index b572eb3..bccbfc1 100644
--- a/dexpreopt/testing.go
+++ b/dexpreopt/testing.go
@@ -34,7 +34,7 @@
 	return module
 }
 
-func RegisterToolModulesForTest(ctx *android.TestContext) {
+func RegisterToolModulesForTest(ctx android.RegistrationContext) {
 	ctx.RegisterModuleType("dummy_tool_binary", dummyToolBinaryFactory)
 }
 
diff --git a/java/java_test.go b/java/java_test.go
index 7b89848..e7776c3 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -59,8 +59,6 @@
 }
 
 func testConfig(env map[string]string, bp string, fs map[string][]byte) android.Config {
-	bp += dexpreopt.BpToolModulesForTest()
-
 	return TestConfig(buildDir, env, bp, fs)
 }
 
@@ -84,8 +82,6 @@
 	// Register module types and mutators from cc needed for JNI testing
 	cc.RegisterRequiredBuildComponentsForTest(ctx)
 
-	dexpreopt.RegisterToolModulesForTest(ctx)
-
 	ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
 		ctx.TopDown("propagate_rro_enforcement", propagateRROEnforcementMutator).Parallel()
 	})
diff --git a/java/testing.go b/java/testing.go
index 445b8b2..0b1f2d1 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -116,6 +116,9 @@
 	RegisterSdkLibraryBuildComponents(ctx)
 	RegisterStubsBuildComponents(ctx)
 	RegisterSystemModulesBuildComponents(ctx)
+
+	// Make sure that any tool related module types needed by dexpreopt have been registered.
+	dexpreopt.RegisterToolModulesForTest(ctx)
 }
 
 // Gather the module definitions needed by tests that depend upon code from this package.
@@ -207,6 +210,9 @@
 		`, extra)
 	}
 
+	// Make sure that any tools needed for dexpreopting are defined.
+	bp += dexpreopt.BpToolModulesForTest()
+
 	// Make sure that the dex_bootjars singleton module is instantiated for the tests.
 	bp += `
 		dex_bootjars {
diff --git a/rust/androidmk.go b/rust/androidmk.go
index e9da6fa..0307727 100644
--- a/rust/androidmk.go
+++ b/rust/androidmk.go
@@ -82,9 +82,6 @@
 	}
 
 	ret.Class = "EXECUTABLES"
-	ret.ExtraEntries = append(ret.ExtraEntries, func(entries *android.AndroidMkEntries) {
-		entries.SetOptionalPath("LOCAL_PREBUILT_COVERAGE_ARCHIVE", binary.coverageOutputZipFile)
-	})
 }
 
 func (test *testDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkEntries) {
@@ -117,10 +114,6 @@
 	if library.distFile.Valid() {
 		ret.DistFiles = android.MakeDefaultDistFiles(library.distFile.Path())
 	}
-
-	ret.ExtraEntries = append(ret.ExtraEntries, func(entries *android.AndroidMkEntries) {
-		entries.SetOptionalPath("LOCAL_PREBUILT_COVERAGE_ARCHIVE", library.coverageOutputZipFile)
-	})
 }
 
 func (procMacro *procMacroDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkEntries) {
diff --git a/rust/binary.go b/rust/binary.go
index ca07d07..2963a37 100644
--- a/rust/binary.go
+++ b/rust/binary.go
@@ -121,7 +121,7 @@
 	flags.RustFlags = append(flags.RustFlags, deps.depFlags...)
 	flags.LinkFlags = append(flags.LinkFlags, deps.linkObjects...)
 
-	outputs := TransformSrcToBinary(ctx, srcPath, deps, flags, outputFile, deps.linkDirs)
+	TransformSrcToBinary(ctx, srcPath, deps, flags, outputFile, deps.linkDirs)
 
 	if binary.stripper.NeedsStrip(ctx) {
 		strippedOutputFile := android.PathForModuleOut(ctx, "stripped", fileName)
@@ -129,24 +129,9 @@
 		binary.strippedOutputFile = android.OptionalPathForPath(strippedOutputFile)
 	}
 
-	binary.coverageFile = outputs.coverageFile
-
-	var coverageFiles android.Paths
-	if outputs.coverageFile != nil {
-		coverageFiles = append(coverageFiles, binary.coverageFile)
-	}
-	if len(deps.coverageFiles) > 0 {
-		coverageFiles = append(coverageFiles, deps.coverageFiles...)
-	}
-	binary.coverageOutputZipFile = TransformCoverageFilesToZip(ctx, coverageFiles, binary.getStem(ctx))
-
 	return outputFile
 }
 
-func (binary *binaryDecorator) coverageOutputZipPath() android.OptionalPath {
-	return binary.coverageOutputZipFile
-}
-
 func (binary *binaryDecorator) autoDep(ctx BaseModuleContext) autoDep {
 	// Binaries default to dylib dependencies for device, rlib for host.
 	if binary.preferRlib() {
diff --git a/rust/binary_test.go b/rust/binary_test.go
index b44a5bc..86f50d3 100644
--- a/rust/binary_test.go
+++ b/rust/binary_test.go
@@ -130,6 +130,9 @@
 	if !strings.Contains(flags, "-C relocation-model=static") {
 		t.Errorf("static binary missing '-C relocation-model=static' in rustcFlags, found: %#v", flags)
 	}
+	if !strings.Contains(flags, "-C panic=abort") {
+		t.Errorf("static binary missing '-C panic=abort' in rustcFlags, found: %#v", flags)
+	}
 	if !strings.Contains(linkFlags, "-static") {
 		t.Errorf("static binary missing '-static' in linkFlags, found: %#v", flags)
 	}
diff --git a/rust/builder.go b/rust/builder.go
index 77d339a..56fe031 100644
--- a/rust/builder.go
+++ b/rust/builder.go
@@ -19,10 +19,8 @@
 	"strings"
 
 	"github.com/google/blueprint"
-	"github.com/google/blueprint/pathtools"
 
 	"android/soong/android"
-	"android/soong/cc"
 	"android/soong/rust/config"
 )
 
@@ -76,8 +74,7 @@
 )
 
 type buildOutput struct {
-	outputFile   android.Path
-	coverageFile android.Path
+	outputFile android.Path
 }
 
 func init() {
@@ -195,27 +192,6 @@
 		implicits = append(implicits, deps.CrtBegin.Path(), deps.CrtEnd.Path())
 	}
 
-	if flags.Coverage {
-		var gcnoFile android.WritablePath
-		// Provide consistency with cc gcda output, see cc/builder.go init()
-		profileEmitArg := strings.TrimPrefix(cc.PwdPrefix(), "PWD=") + "/"
-
-		if outputFile.Ext() != "" {
-			// rustc seems to split the output filename at the first '.' when determining the gcno filename
-			// so we need to do the same here.
-			gcnoFile = android.PathForModuleOut(ctx, strings.Split(outputFile.Base(), ".")[0]+".gcno")
-			rustcFlags = append(rustcFlags, "-Z profile-emit="+profileEmitArg+android.PathForModuleOut(
-				ctx, pathtools.ReplaceExtension(outputFile.Base(), "gcda")).String())
-		} else {
-			gcnoFile = android.PathForModuleOut(ctx, outputFile.Base()+".gcno")
-			rustcFlags = append(rustcFlags, "-Z profile-emit="+profileEmitArg+android.PathForModuleOut(
-				ctx, outputFile.Base()+".gcda").String())
-		}
-
-		implicitOutputs = append(implicitOutputs, gcnoFile)
-		output.coverageFile = gcnoFile
-	}
-
 	if len(deps.SrcDeps) > 0 {
 		genSubDir := "out/"
 		moduleGenDir := android.PathForModuleOut(ctx, genSubDir)
@@ -292,21 +268,3 @@
 
 	return output
 }
-
-func TransformCoverageFilesToZip(ctx ModuleContext,
-	covFiles android.Paths, baseName string) android.OptionalPath {
-	if len(covFiles) > 0 {
-
-		outputFile := android.PathForModuleOut(ctx, baseName+".zip")
-
-		ctx.Build(pctx, android.BuildParams{
-			Rule:        zip,
-			Description: "zip " + outputFile.Base(),
-			Inputs:      covFiles,
-			Output:      outputFile,
-		})
-
-		return android.OptionalPathForPath(outputFile)
-	}
-	return android.OptionalPath{}
-}
diff --git a/rust/compiler.go b/rust/compiler.go
index 2d9575c..c921824 100644
--- a/rust/compiler.go
+++ b/rust/compiler.go
@@ -136,8 +136,7 @@
 }
 
 type baseCompiler struct {
-	Properties   BaseCompilerProperties
-	coverageFile android.Path //rustc generates a single gcno file
+	Properties BaseCompilerProperties
 
 	// Install related
 	dir      string
@@ -148,8 +147,7 @@
 	location installLocation
 	sanitize *sanitize
 
-	coverageOutputZipFile android.OptionalPath
-	distFile              android.OptionalPath
+	distFile android.OptionalPath
 	// Stripped output file. If Valid(), this file will be installed instead of outputFile.
 	strippedOutputFile android.OptionalPath
 }
diff --git a/rust/config/global.go b/rust/config/global.go
index 08ec877..fb62278 100644
--- a/rust/config/global.go
+++ b/rust/config/global.go
@@ -49,7 +49,9 @@
 		"-C relocation-model=pic",
 	}
 
-	deviceGlobalRustFlags = []string{}
+	deviceGlobalRustFlags = []string{
+		"-C panic=abort",
+	}
 
 	deviceGlobalLinkFlags = []string{
 		// Prepend the lld flags from cc_config so we stay in sync with cc
diff --git a/rust/coverage.go b/rust/coverage.go
index 26375f5..dac526a 100644
--- a/rust/coverage.go
+++ b/rust/coverage.go
@@ -20,7 +20,9 @@
 	"android/soong/cc"
 )
 
-var CovLibraryName = "libprofile-extras"
+var CovLibraryName = "libprofile-clang-extras"
+
+const profileInstrFlag = "-fprofile-instr-generate=/data/misc/trace/clang-%p-%m.profraw"
 
 type coverage struct {
 	Properties cc.CoverageProperties
@@ -53,9 +55,9 @@
 		flags.Coverage = true
 		coverage := ctx.GetDirectDepWithTag(CovLibraryName, cc.CoverageDepTag).(cc.LinkableInterface)
 		flags.RustFlags = append(flags.RustFlags,
-			"-Z profile", "-g", "-C opt-level=0", "-C link-dead-code")
+			"-Z instrument-coverage", "-g", "-C link-dead-code")
 		flags.LinkFlags = append(flags.LinkFlags,
-			"--coverage", "-g", coverage.OutputFile().Path().String(), "-Wl,--wrap,getenv")
+			profileInstrFlag, "-g", coverage.OutputFile().Path().String(), "-Wl,--wrap,open")
 		deps.StaticLibs = append(deps.StaticLibs, coverage.OutputFile().Path())
 	}
 
diff --git a/rust/coverage_test.go b/rust/coverage_test.go
index e7f873e..4b6c9d4 100644
--- a/rust/coverage_test.go
+++ b/rust/coverage_test.go
@@ -56,7 +56,7 @@
 	fizzCov := ctx.ModuleForTests("fizz_cov", "android_arm64_armv8-a_cov").Rule("rustc")
 	buzzNoCov := ctx.ModuleForTests("buzzNoCov", "android_arm64_armv8-a").Rule("rustc")
 
-	rustcCoverageFlags := []string{"-Z profile", " -g ", "-C opt-level=0", "-C link-dead-code"}
+	rustcCoverageFlags := []string{"-Z instrument-coverage", " -g ", "-C link-dead-code"}
 	for _, flag := range rustcCoverageFlags {
 		missingErrorStr := "missing rustc flag '%s' for '%s' module with coverage enabled; rustcFlags: %#v"
 		containsErrorStr := "contains rustc flag '%s' for '%s' module with coverage disabled; rustcFlags: %#v"
@@ -75,7 +75,7 @@
 		}
 	}
 
-	linkCoverageFlags := []string{"--coverage", " -g "}
+	linkCoverageFlags := []string{"-fprofile-instr-generate=/data/misc/trace/clang-%p-%m.profraw", " -g "}
 	for _, flag := range linkCoverageFlags {
 		missingErrorStr := "missing rust linker flag '%s' for '%s' module with coverage enabled; rustcFlags: %#v"
 		containsErrorStr := "contains rust linker flag '%s' for '%s' module with coverage disabled; rustcFlags: %#v"
@@ -96,83 +96,6 @@
 
 }
 
-// Test coverage files are included correctly
-func TestCoverageZip(t *testing.T) {
-	ctx := testRustCov(t, `
-		rust_library {
-			name: "libfoo",
-			srcs: ["foo.rs"],
-			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"],
-			crate_name: "rlib",
-		}
-		rust_binary {
-			name: "fizz",
-			rlibs: ["librlib"],
-			static_libs: ["libbaz"],
-			srcs: ["foo.rs"],
-		}
-		cc_binary {
-			name: "buzz",
-			static_libs: ["libbaz"],
-			srcs: ["foo.c"],
-		}
-		cc_library {
-			name: "libbar",
-			static_libs: ["libbaz"],
-			compile_multilib: "64",
-			srcs: ["foo.c"],
-		}`)
-
-	fizzZipInputs := ctx.ModuleForTests("fizz", "android_arm64_armv8-a_cov").Rule("zip").Inputs.Strings()
-	libfooZipInputs := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_dylib_cov").Rule("zip").Inputs.Strings()
-	buzzZipInputs := ctx.ModuleForTests("buzz", "android_arm64_armv8-a_cov").Rule("zip").Inputs.Strings()
-	libbarZipInputs := ctx.ModuleForTests("libbar", "android_arm64_armv8-a_shared_cov").Rule("zip").Inputs.Strings()
-
-	// Make sure the expected number of input files are included.
-	if len(fizzZipInputs) != 3 {
-		t.Fatalf("expected only 3 coverage inputs for rust 'fizz' binary, got %#v: %#v", len(fizzZipInputs), fizzZipInputs)
-	}
-	if len(libfooZipInputs) != 2 {
-		t.Fatalf("expected only 2 coverage inputs for rust 'libfoo' library, got %#v: %#v", len(libfooZipInputs), libfooZipInputs)
-	}
-	if len(buzzZipInputs) != 2 {
-		t.Fatalf("expected only 2 coverage inputs for cc 'buzz' binary, got %#v: %#v", len(buzzZipInputs), buzzZipInputs)
-	}
-	if len(libbarZipInputs) != 2 {
-		t.Fatalf("expected only 2 coverage inputs for cc 'libbar' library, got %#v: %#v", len(libbarZipInputs), libbarZipInputs)
-	}
-
-	// Make sure the expected inputs are provided to the zip rule.
-	if !android.SuffixInList(fizzZipInputs, "android_arm64_armv8-a_rlib_dylib-std_cov/librlib.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)
-	}
-	if !android.SuffixInList(libfooZipInputs, "android_arm64_armv8-a_rlib_dylib-std_cov/librlib.gcno") ||
-		!android.SuffixInList(libfooZipInputs, "android_arm64_armv8-a_dylib_cov/libfoo.gcno") {
-		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/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/libbaz.gcno") {
-		t.Fatalf("missing expected coverage files for cc 'libbar' library: %#v", libbarZipInputs)
-	}
-}
-
 func TestCoverageDeps(t *testing.T) {
 	ctx := testRustCov(t, `
 		rust_binary {
@@ -181,7 +104,7 @@
 		}`)
 
 	fizz := ctx.ModuleForTests("fizz", "android_arm64_armv8-a_cov").Rule("rustc")
-	if !strings.Contains(fizz.Args["linkFlags"], "libprofile-extras.a") {
-		t.Fatalf("missing expected coverage 'libprofile-extras' dependency in linkFlags: %#v", fizz.Args["linkFlags"])
+	if !strings.Contains(fizz.Args["linkFlags"], "libprofile-clang-extras.a") {
+		t.Fatalf("missing expected coverage 'libprofile-clang-extras' dependency in linkFlags: %#v", fizz.Args["linkFlags"])
 	}
 }
diff --git a/rust/image.go b/rust/image.go
index 5e55e22..5ff10ae 100644
--- a/rust/image.go
+++ b/rust/image.go
@@ -68,11 +68,7 @@
 
 // Returns true when this module is configured to have core and vendor variants.
 func (mod *Module) HasVendorVariant() bool {
-	return mod.IsVndk() || Bool(mod.VendorProperties.Vendor_available)
-}
-
-func (c *Module) VendorAvailable() bool {
-	return Bool(c.VendorProperties.Vendor_available)
+	return Bool(mod.VendorProperties.Vendor_available) || Bool(mod.VendorProperties.Odm_available)
 }
 
 func (c *Module) InProduct() bool {
@@ -114,10 +110,15 @@
 	coreVariantNeeded := true
 	var vendorVariants []string
 
-	if Bool(mod.VendorProperties.Vendor_available) {
+	if mod.HasVendorVariant() {
+		prop := "vendor_available"
+		if Bool(mod.VendorProperties.Odm_available) {
+			prop = "odm_available"
+		}
+
 		if vendorSpecific {
-			mctx.PropertyErrorf("vendor_available",
-				"doesn't make sense at the same time as `vendor: true`, `proprietary: true`, or `device_specific:true`")
+			mctx.PropertyErrorf(prop,
+				"doesn't make sense at the same time as `vendor: true`, `proprietary: true`, or `device_specific: true`")
 		}
 
 		if lib, ok := mod.compiler.(libraryInterface); ok {
@@ -128,9 +129,8 @@
 			// We can't check shared() here because image mutator is called before the library mutator, so we need to
 			// check buildShared()
 			if lib.buildShared() {
-				mctx.PropertyErrorf("vendor_available",
-					"vendor_available can only be set for rust_ffi_static modules.")
-			} else if Bool(mod.VendorProperties.Vendor_available) == true {
+				mctx.PropertyErrorf(prop, "can only be set for rust_ffi_static modules.")
+			} else {
 				vendorVariants = append(vendorVariants, platformVndkVersion)
 			}
 		}
diff --git a/rust/image_test.go b/rust/image_test.go
index 025b0fd..fd71962 100644
--- a/rust/image_test.go
+++ b/rust/image_test.go
@@ -46,7 +46,7 @@
 
 // Test that shared libraries cannot be made vendor available until proper support is added.
 func TestForbiddenVendorLinkage(t *testing.T) {
-	testRustError(t, "vendor_available can only be set for rust_ffi_static modules", `
+	testRustError(t, "can only be set for rust_ffi_static modules", `
 		rust_ffi_shared {
 			name: "libfoo_vendor",
 			crate_name: "foo",
diff --git a/rust/library.go b/rust/library.go
index 4ac52b4..6433285 100644
--- a/rust/library.go
+++ b/rust/library.go
@@ -452,26 +452,22 @@
 		fileName = library.getStem(ctx) + ctx.toolchain().RlibSuffix()
 		outputFile = android.PathForModuleOut(ctx, fileName)
 
-		outputs := TransformSrctoRlib(ctx, srcPath, deps, flags, outputFile, deps.linkDirs)
-		library.coverageFile = outputs.coverageFile
+		TransformSrctoRlib(ctx, srcPath, deps, flags, outputFile, deps.linkDirs)
 	} else if library.dylib() {
 		fileName = library.getStem(ctx) + ctx.toolchain().DylibSuffix()
 		outputFile = android.PathForModuleOut(ctx, fileName)
 
-		outputs := TransformSrctoDylib(ctx, srcPath, deps, flags, outputFile, deps.linkDirs)
-		library.coverageFile = outputs.coverageFile
+		TransformSrctoDylib(ctx, srcPath, deps, flags, outputFile, deps.linkDirs)
 	} else if library.static() {
 		fileName = library.getStem(ctx) + ctx.toolchain().StaticLibSuffix()
 		outputFile = android.PathForModuleOut(ctx, fileName)
 
-		outputs := TransformSrctoStatic(ctx, srcPath, deps, flags, outputFile, deps.linkDirs)
-		library.coverageFile = outputs.coverageFile
+		TransformSrctoStatic(ctx, srcPath, deps, flags, outputFile, deps.linkDirs)
 	} else if library.shared() {
 		fileName = library.sharedLibFilename(ctx)
 		outputFile = android.PathForModuleOut(ctx, fileName)
 
-		outputs := TransformSrctoShared(ctx, srcPath, deps, flags, outputFile, deps.linkDirs)
-		library.coverageFile = outputs.coverageFile
+		TransformSrctoShared(ctx, srcPath, deps, flags, outputFile, deps.linkDirs)
 	}
 
 	if !library.rlib() && library.stripper.NeedsStrip(ctx) {
@@ -480,15 +476,6 @@
 		library.strippedOutputFile = android.OptionalPathForPath(strippedOutputFile)
 	}
 
-	var coverageFiles android.Paths
-	if library.coverageFile != nil {
-		coverageFiles = append(coverageFiles, library.coverageFile)
-	}
-	if len(deps.coverageFiles) > 0 {
-		coverageFiles = append(coverageFiles, deps.coverageFiles...)
-	}
-	library.coverageOutputZipFile = TransformCoverageFilesToZip(ctx, coverageFiles, library.getStem(ctx))
-
 	if library.rlib() || library.dylib() {
 		library.flagExporter.exportLinkDirs(deps.linkDirs...)
 		library.flagExporter.exportDepFlags(deps.depFlags...)
diff --git a/rust/rust.go b/rust/rust.go
index cda01d8..2ef9daf 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -291,8 +291,6 @@
 	depGeneratedHeaders   android.Paths
 	depSystemIncludePaths android.Paths
 
-	coverageFiles android.Paths
-
 	CrtBegin android.OptionalPath
 	CrtEnd   android.OptionalPath
 
@@ -515,15 +513,7 @@
 
 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}
-			}
-			return android.Paths{}
-		}
+		return android.Paths{}
 	}
 	panic(fmt.Errorf("CoverageFiles called on non-library module: %q", mod.BaseModuleName()))
 }
@@ -840,7 +830,6 @@
 					ctx.ModuleErrorf("mod %q not an rlib library", depName+rustDep.Properties.SubName)
 					return
 				}
-				depPaths.coverageFiles = append(depPaths.coverageFiles, rustDep.CoverageFiles()...)
 				directRlibDeps = append(directRlibDeps, rustDep)
 				mod.Properties.AndroidMkRlibs = append(mod.Properties.AndroidMkRlibs, depName+rustDep.Properties.SubName)
 			case procMacroDepTag:
@@ -916,7 +905,6 @@
 				depPaths.depSystemIncludePaths = append(depPaths.depSystemIncludePaths, exportedInfo.SystemIncludeDirs...)
 				depPaths.depClangFlags = append(depPaths.depClangFlags, exportedInfo.Flags...)
 				depPaths.depGeneratedHeaders = append(depPaths.depGeneratedHeaders, exportedInfo.GeneratedHeaders...)
-				depPaths.coverageFiles = append(depPaths.coverageFiles, ccDep.CoverageFiles()...)
 				directStaticLibDeps = append(directStaticLibDeps, ccDep)
 				mod.Properties.AndroidMkStaticLibs = append(mod.Properties.AndroidMkStaticLibs, depName)
 			case cc.IsSharedDepTag(depTag):
diff --git a/rust/rust_test.go b/rust/rust_test.go
index 48c8d74..fc7f47e 100644
--- a/rust/rust_test.go
+++ b/rust/rust_test.go
@@ -134,7 +134,7 @@
 	if tctx.config == nil {
 		t.Fatalf("tctx.config not been generated yet. Please call generateConfig first.")
 	}
-	tctx.config.TestProductVariables.GcovCoverage = proptools.BoolPtr(true)
+	tctx.config.TestProductVariables.ClangCoverage = proptools.BoolPtr(true)
 	tctx.config.TestProductVariables.Native_coverage = proptools.BoolPtr(true)
 	tctx.config.TestProductVariables.NativeCoveragePaths = []string{"*"}
 }
diff --git a/rust/test.go b/rust/test.go
index 408e03a..35e04ff 100644
--- a/rust/test.go
+++ b/rust/test.go
@@ -120,6 +120,9 @@
 	if test.testHarness() {
 		flags.RustFlags = append(flags.RustFlags, "--test")
 	}
+	if ctx.Device() {
+		flags.RustFlags = append(flags.RustFlags, "-Z panic_abort_tests")
+	}
 	return flags
 }