Merge changes from topics "soong-apilevel", "soong-config-apilevel"

* changes:
  Convert more versions in config to ApiLevel.
  Replace FutureApiLevel with an ApiLevel.
  Replace ApiStrToNum uses with ApiLevel.
diff --git a/android/arch.go b/android/arch.go
index 4141138..eb3c709 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -78,13 +78,22 @@
     },
     target: {
         android: {
-            // Device variants
+            // Device variants (implies Bionic)
         },
         host: {
             // Host variants
         },
+        bionic: {
+            // Bionic (device and host) variants
+        },
+        linux_bionic: {
+            // Bionic host variants
+        },
+        linux: {
+            // Bionic (device and host) and Linux glibc variants
+        },
         linux_glibc: {
-            // Linux host variants
+            // Linux host variants (using non-Bionic libc)
         },
         darwin: {
             // Darwin host variants
@@ -95,6 +104,9 @@
         not_windows: {
             // Non-windows host variants
         },
+        android_arm: {
+            // Any <os>_<arch> combination restricts to that os and arch
+        },
     },
 }
 */
diff --git a/android/module.go b/android/module.go
index 5bc7a17..d3341d2 100644
--- a/android/module.go
+++ b/android/module.go
@@ -176,6 +176,31 @@
 	// It is intended for use inside the visit functions of Visit* and WalkDeps.
 	OtherModuleType(m blueprint.Module) string
 
+	// OtherModuleProvider returns the value for a provider for the given module.  If the value is
+	// not set it returns the zero value of the type of the provider, so the return value can always
+	// be type asserted to the type of the provider.  The value returned may be a deep copy of the
+	// value originally passed to SetProvider.
+	OtherModuleProvider(m blueprint.Module, provider blueprint.ProviderKey) interface{}
+
+	// OtherModuleHasProvider returns true if the provider for the given module has been set.
+	OtherModuleHasProvider(m blueprint.Module, provider blueprint.ProviderKey) bool
+
+	// Provider returns the value for a provider for the current module.  If the value is
+	// not set it returns the zero value of the type of the provider, so the return value can always
+	// be type asserted to the type of the provider.  It panics if called before the appropriate
+	// mutator or GenerateBuildActions pass for the provider.  The value returned may be a deep
+	// copy of the value originally passed to SetProvider.
+	Provider(provider blueprint.ProviderKey) interface{}
+
+	// HasProvider returns true if the provider for the current module has been set.
+	HasProvider(provider blueprint.ProviderKey) bool
+
+	// SetProvider sets the value for a provider for the current module.  It panics if not called
+	// during the appropriate mutator or GenerateBuildActions pass for the provider, if the value
+	// is not of the appropriate type, or if the value has already been set.  The value should not
+	// be modified after being passed to SetProvider.
+	SetProvider(provider blueprint.ProviderKey, value interface{})
+
 	GetDirectDepsWithTag(tag blueprint.DependencyTag) []Module
 
 	// GetDirectDepWithTag returns the Module the direct dependency with the specified name, or nil if
@@ -245,6 +270,24 @@
 	// and returns a top-down dependency path from a start module to current child module.
 	GetWalkPath() []Module
 
+	// PrimaryModule returns the first variant of the current module.  Variants of a module are always visited in
+	// order by mutators and GenerateBuildActions, so the data created by the current mutator can be read from the
+	// Module returned by PrimaryModule without data races.  This can be used to perform singleton actions that are
+	// only done once for all variants of a module.
+	PrimaryModule() Module
+
+	// FinalModule returns the last variant of the current module.  Variants of a module are always visited in
+	// order by mutators and GenerateBuildActions, so the data created by the current mutator can be read from all
+	// variants using VisitAllModuleVariants if the current module == FinalModule().  This can be used to perform
+	// singleton actions that are only done once for all variants of a module.
+	FinalModule() Module
+
+	// VisitAllModuleVariants calls visit for each variant of the current module.  Variants of a module are always
+	// visited in order by mutators and GenerateBuildActions, so the data created by the current mutator can be read
+	// from all variants if the current module == FinalModule().  Otherwise, care must be taken to not access any
+	// data modified by the current mutator.
+	VisitAllModuleVariants(visit func(Module))
+
 	// GetTagPath is supposed to be called in visit function passed in WalkDeps()
 	// and returns a top-down dependency tags path from a start module to current child module.
 	// It has one less entry than GetWalkPath() as it contains the dependency tags that
@@ -324,24 +367,6 @@
 	// additional dependencies.
 	Phony(phony string, deps ...Path)
 
-	// PrimaryModule returns the first variant of the current module.  Variants of a module are always visited in
-	// order by mutators and GenerateBuildActions, so the data created by the current mutator can be read from the
-	// Module returned by PrimaryModule without data races.  This can be used to perform singleton actions that are
-	// only done once for all variants of a module.
-	PrimaryModule() Module
-
-	// FinalModule returns the last variant of the current module.  Variants of a module are always visited in
-	// order by mutators and GenerateBuildActions, so the data created by the current mutator can be read from all
-	// variants using VisitAllModuleVariants if the current module == FinalModule().  This can be used to perform
-	// singleton actions that are only done once for all variants of a module.
-	FinalModule() Module
-
-	// VisitAllModuleVariants calls visit for each variant of the current module.  Variants of a module are always
-	// visited in order by mutators and GenerateBuildActions, so the data created by the current mutator can be read
-	// from all variants if the current module == FinalModule().  Otherwise, care must be taken to not access any
-	// data modified by the current mutator.
-	VisitAllModuleVariants(visit func(Module))
-
 	// GetMissingDependencies returns the list of dependencies that were passed to AddDependencies or related methods,
 	// but do not exist.
 	GetMissingDependencies() []string
@@ -541,7 +566,7 @@
 	// control whether this module compiles for 32-bit, 64-bit, or both.  Possible values
 	// are "32" (compile for 32-bit only), "64" (compile for 64-bit only), "both" (compile for both
 	// architectures), or "first" (compile for 64-bit on a 64-bit platform, and 32-bit on a 32-bit
-	// platform
+	// platform).
 	Compile_multilib *string `android:"arch_variant"`
 
 	Target struct {
@@ -1681,6 +1706,21 @@
 func (b *baseModuleContext) OtherModuleType(m blueprint.Module) string {
 	return b.bp.OtherModuleType(m)
 }
+func (b *baseModuleContext) OtherModuleProvider(m blueprint.Module, provider blueprint.ProviderKey) interface{} {
+	return b.bp.OtherModuleProvider(m, provider)
+}
+func (b *baseModuleContext) OtherModuleHasProvider(m blueprint.Module, provider blueprint.ProviderKey) bool {
+	return b.bp.OtherModuleHasProvider(m, provider)
+}
+func (b *baseModuleContext) Provider(provider blueprint.ProviderKey) interface{} {
+	return b.bp.Provider(provider)
+}
+func (b *baseModuleContext) HasProvider(provider blueprint.ProviderKey) bool {
+	return b.bp.HasProvider(provider)
+}
+func (b *baseModuleContext) SetProvider(provider blueprint.ProviderKey, value interface{}) {
+	b.bp.SetProvider(provider, value)
+}
 
 func (b *baseModuleContext) GetDirectDepWithTag(name string, tag blueprint.DependencyTag) blueprint.Module {
 	return b.bp.GetDirectDepWithTag(name, tag)
@@ -2001,6 +2041,20 @@
 	return b.tagPath
 }
 
+func (b *baseModuleContext) VisitAllModuleVariants(visit func(Module)) {
+	b.bp.VisitAllModuleVariants(func(module blueprint.Module) {
+		visit(module.(Module))
+	})
+}
+
+func (b *baseModuleContext) PrimaryModule() Module {
+	return b.bp.PrimaryModule().(Module)
+}
+
+func (b *baseModuleContext) FinalModule() Module {
+	return b.bp.FinalModule().(Module)
+}
+
 // A regexp for removing boilerplate from BaseDependencyTag from the string representation of
 // a dependency tag.
 var tagCleaner = regexp.MustCompile(`\QBaseDependencyTag:{}\E(, )?`)
@@ -2036,20 +2090,6 @@
 	return sb.String()
 }
 
-func (m *moduleContext) VisitAllModuleVariants(visit func(Module)) {
-	m.bp.VisitAllModuleVariants(func(module blueprint.Module) {
-		visit(module.(Module))
-	})
-}
-
-func (m *moduleContext) PrimaryModule() Module {
-	return m.bp.PrimaryModule().(Module)
-}
-
-func (m *moduleContext) FinalModule() Module {
-	return m.bp.FinalModule().(Module)
-}
-
 func (m *moduleContext) ModuleSubDir() string {
 	return m.bp.ModuleSubDir()
 }
diff --git a/android/mutator.go b/android/mutator.go
index 738b2ba..7a10477 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -210,10 +210,14 @@
 type BottomUpMutatorContext interface {
 	BaseMutatorContext
 
-	// AddDependency adds a dependency to the given module.
-	// Does not affect the ordering of the current mutator pass, but will be ordered
-	// correctly for all future mutator passes.
-	AddDependency(module blueprint.Module, tag blueprint.DependencyTag, name ...string)
+	// AddDependency adds a dependency to the given module.  It returns a slice of modules for each
+	// dependency (some entries may be nil).
+	//
+	// If the mutator is parallel (see MutatorHandle.Parallel), this method will pause until the
+	// new dependencies have had the current mutator called on them.  If the mutator is not
+	// parallel this method does not affect the ordering of the current mutator pass, but will
+	// be ordered correctly for all future mutator passes.
+	AddDependency(module blueprint.Module, tag blueprint.DependencyTag, name ...string) []blueprint.Module
 
 	// AddReverseDependency adds a dependency from the destination to the given module.
 	// Does not affect the ordering of the current mutator pass, but will be ordered
@@ -253,19 +257,30 @@
 	SetDefaultDependencyVariation(*string)
 
 	// AddVariationDependencies adds deps as dependencies of the current module, but uses the variations
-	// argument to select which variant of the dependency to use.  A variant of the dependency must
-	// exist that matches the all of the non-local variations of the current module, plus the variations
-	// argument.
-	AddVariationDependencies([]blueprint.Variation, blueprint.DependencyTag, ...string)
+	// argument to select which variant of the dependency to use.  It returns a slice of modules for
+	// each dependency (some entries may be nil).  A variant of the dependency must exist that matches
+	// the all of the non-local variations of the current module, plus the variations argument.
+	//
+	// If the mutator is parallel (see MutatorHandle.Parallel), this method will pause until the
+	// new dependencies have had the current mutator called on them.  If the mutator is not
+	// parallel this method does not affect the ordering of the current mutator pass, but will
+	// be ordered correctly for all future mutator passes.
+	AddVariationDependencies([]blueprint.Variation, blueprint.DependencyTag, ...string) []blueprint.Module
 
 	// AddFarVariationDependencies adds deps as dependencies of the current module, but uses the
-	// variations argument to select which variant of the dependency to use.  A variant of the
-	// dependency must exist that matches the variations argument, but may also have other variations.
+	// variations argument to select which variant of the dependency to use.  It returns a slice of
+	// modules for each dependency (some entries may be nil).  A variant of the dependency must
+	// exist that matches the variations argument, but may also have other variations.
 	// For any unspecified variation the first variant will be used.
 	//
 	// Unlike AddVariationDependencies, the variations of the current module are ignored - the
 	// dependency only needs to match the supplied variations.
-	AddFarVariationDependencies([]blueprint.Variation, blueprint.DependencyTag, ...string)
+	//
+	// If the mutator is parallel (see MutatorHandle.Parallel), this method will pause until the
+	// new dependencies have had the current mutator called on them.  If the mutator is not
+	// parallel this method does not affect the ordering of the current mutator pass, but will
+	// be ordered correctly for all future mutator passes.
+	AddFarVariationDependencies([]blueprint.Variation, blueprint.DependencyTag, ...string) []blueprint.Module
 
 	// AddInterVariantDependency adds a dependency between two variants of the same module.  Variants are always
 	// ordered in the same orderas they were listed in CreateVariations, and AddInterVariantDependency does not change
@@ -300,6 +315,14 @@
 	// be used to add dependencies on the toVariationName variant using the fromVariationName
 	// variant.
 	CreateAliasVariation(fromVariationName, toVariationName string)
+
+	// SetVariationProvider sets the value for a provider for the given newly created variant of
+	// the current module, i.e. one of the Modules returned by CreateVariations..  It panics if
+	// not called during the appropriate mutator or GenerateBuildActions pass for the provider,
+	// if the value is not of the appropriate type, or if the module is not a newly created
+	// variant of the current module.  The value should not be modified after being passed to
+	// SetVariationProvider.
+	SetVariationProvider(module blueprint.Module, provider blueprint.ProviderKey, value interface{})
 }
 
 type bottomUpMutatorContext struct {
@@ -452,8 +475,8 @@
 	b.Module().base().commonProperties.DebugName = name
 }
 
-func (b *bottomUpMutatorContext) AddDependency(module blueprint.Module, tag blueprint.DependencyTag, name ...string) {
-	b.bp.AddDependency(module, tag, name...)
+func (b *bottomUpMutatorContext) AddDependency(module blueprint.Module, tag blueprint.DependencyTag, name ...string) []blueprint.Module {
+	return b.bp.AddDependency(module, tag, name...)
 }
 
 func (b *bottomUpMutatorContext) AddReverseDependency(module blueprint.Module, tag blueprint.DependencyTag, name string) {
@@ -505,15 +528,15 @@
 }
 
 func (b *bottomUpMutatorContext) AddVariationDependencies(variations []blueprint.Variation, tag blueprint.DependencyTag,
-	names ...string) {
+	names ...string) []blueprint.Module {
 
-	b.bp.AddVariationDependencies(variations, tag, names...)
+	return b.bp.AddVariationDependencies(variations, tag, names...)
 }
 
 func (b *bottomUpMutatorContext) AddFarVariationDependencies(variations []blueprint.Variation,
-	tag blueprint.DependencyTag, names ...string) {
+	tag blueprint.DependencyTag, names ...string) []blueprint.Module {
 
-	b.bp.AddFarVariationDependencies(variations, tag, names...)
+	return b.bp.AddFarVariationDependencies(variations, tag, names...)
 }
 
 func (b *bottomUpMutatorContext) AddInterVariantDependency(tag blueprint.DependencyTag, from, to blueprint.Module) {
@@ -535,3 +558,7 @@
 func (b *bottomUpMutatorContext) CreateAliasVariation(fromVariationName, toVariationName string) {
 	b.bp.CreateAliasVariation(fromVariationName, toVariationName)
 }
+
+func (b *bottomUpMutatorContext) SetVariationProvider(module blueprint.Module, provider blueprint.ProviderKey, value interface{}) {
+	b.bp.SetVariationProvider(module, provider, value)
+}
diff --git a/android/prebuilt_build_tool.go b/android/prebuilt_build_tool.go
index 1dcf199..e2555e4 100644
--- a/android/prebuilt_build_tool.go
+++ b/android/prebuilt_build_tool.go
@@ -14,6 +14,8 @@
 
 package android
 
+import "path/filepath"
+
 func init() {
 	RegisterModuleType("prebuilt_build_tool", prebuiltBuildToolFactory)
 }
@@ -58,13 +60,18 @@
 	installedPath := PathForModuleOut(ctx, t.ModuleBase.Name())
 	deps := PathsForModuleSrc(ctx, t.properties.Deps)
 
+	var fromPath = sourcePath.String()
+	if !filepath.IsAbs(fromPath) {
+		fromPath = "$$PWD/" + fromPath
+	}
+
 	ctx.Build(pctx, BuildParams{
 		Rule:      Symlink,
 		Output:    installedPath,
 		Input:     sourcePath,
 		Implicits: deps,
 		Args: map[string]string{
-			"fromPath": "$$PWD/" + sourcePath.String(),
+			"fromPath": fromPath,
 		},
 	})
 
diff --git a/android/singleton.go b/android/singleton.go
index 2c51c6c..9832378 100644
--- a/android/singleton.go
+++ b/android/singleton.go
@@ -29,6 +29,16 @@
 	ModuleType(module blueprint.Module) string
 	BlueprintFile(module blueprint.Module) string
 
+	// ModuleProvider returns the value, if any, for the provider for a module.  If the value for the
+	// provider was not set it returns the zero value of the type of the provider, which means the
+	// return value can always be type-asserted to the type of the provider.  The return value should
+	// always be considered read-only.  It panics if called before the appropriate mutator or
+	// GenerateBuildActions pass for the provider on the module.
+	ModuleProvider(module blueprint.Module, provider blueprint.ProviderKey) interface{}
+
+	// ModuleHasProvider returns true if the provider for the given module has been set.
+	ModuleHasProvider(module blueprint.Module, provider blueprint.ProviderKey) bool
+
 	ModuleErrorf(module blueprint.Module, format string, args ...interface{})
 	Errorf(format string, args ...interface{})
 	Failed() bool
diff --git a/cc/binary_sdk_member.go b/cc/binary_sdk_member.go
index a1abc72..55e400e 100644
--- a/cc/binary_sdk_member.go
+++ b/cc/binary_sdk_member.go
@@ -44,7 +44,7 @@
 		for _, target := range targets {
 			name, version := StubsLibNameAndVersion(lib)
 			if version == "" {
-				version = LatestStubsVersionFor(mctx.Config(), name)
+				version = "latest"
 			}
 			variations := target.Variations()
 			if mctx.Device() {
diff --git a/cc/cc.go b/cc/cc.go
index aad1ac9..9877cc6 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -47,7 +47,8 @@
 		ctx.BottomUp("link", LinkageMutator).Parallel()
 		ctx.BottomUp("ndk_api", NdkApiMutator).Parallel()
 		ctx.BottomUp("test_per_src", TestPerSrcMutator).Parallel()
-		ctx.BottomUp("version", VersionMutator).Parallel()
+		ctx.BottomUp("version_selector", versionSelectorMutator).Parallel()
+		ctx.BottomUp("version", versionMutator).Parallel()
 		ctx.BottomUp("begin", BeginMutator).Parallel()
 		ctx.BottomUp("sysprop_cc", SyspropMutator).Parallel()
 		ctx.BottomUp("vendor_snapshot", VendorSnapshotMutator).Parallel()
@@ -784,7 +785,28 @@
 	panic(fmt.Errorf("BuildStubs called on non-library module: %q", c.BaseModuleName()))
 }
 
-func (c *Module) SetStubsVersions(version string) {
+func (c *Module) SetAllStubsVersions(versions []string) {
+	if library, ok := c.linker.(*libraryDecorator); ok {
+		library.MutatedProperties.AllStubsVersions = versions
+		return
+	}
+	if llndk, ok := c.linker.(*llndkStubDecorator); ok {
+		llndk.libraryDecorator.MutatedProperties.AllStubsVersions = versions
+		return
+	}
+}
+
+func (c *Module) AllStubsVersions() []string {
+	if library, ok := c.linker.(*libraryDecorator); ok {
+		return library.MutatedProperties.AllStubsVersions
+	}
+	if llndk, ok := c.linker.(*llndkStubDecorator); ok {
+		return llndk.libraryDecorator.MutatedProperties.AllStubsVersions
+	}
+	return nil
+}
+
+func (c *Module) SetStubsVersion(version string) {
 	if c.linker != nil {
 		if library, ok := c.linker.(*libraryDecorator); ok {
 			library.MutatedProperties.StubsVersion = version
@@ -795,7 +817,7 @@
 			return
 		}
 	}
-	panic(fmt.Errorf("SetStubsVersions called on non-library module: %q", c.BaseModuleName()))
+	panic(fmt.Errorf("SetStubsVersion called on non-library module: %q", c.BaseModuleName()))
 }
 
 func (c *Module) StubsVersion() string {
@@ -1996,18 +2018,20 @@
 			variations = append(variations, blueprint.Variation{Mutator: "version", Variation: version})
 			depTag.explicitlyVersioned = true
 		}
-		actx.AddVariationDependencies(variations, depTag, name)
+		deps := actx.AddVariationDependencies(variations, depTag, name)
 
 		// If the version is not specified, add dependency to all stubs libraries.
 		// The stubs library will be used when the depending module is built for APEX and
 		// the dependent module is not in the same APEX.
 		if version == "" && VersionVariantAvailable(c) {
-			for _, ver := range stubsVersionsFor(actx.Config())[name] {
-				// Note that depTag.ExplicitlyVersioned is false in this case.
-				actx.AddVariationDependencies([]blueprint.Variation{
-					{Mutator: "link", Variation: "shared"},
-					{Mutator: "version", Variation: ver},
-				}, depTag, name)
+			if dep, ok := deps[0].(*Module); ok {
+				for _, ver := range dep.AllStubsVersions() {
+					// Note that depTag.ExplicitlyVersioned is false in this case.
+					ctx.AddVariationDependencies([]blueprint.Variation{
+						{Mutator: "link", Variation: "shared"},
+						{Mutator: "version", Variation: ver},
+					}, depTag, name)
+				}
 			}
 		}
 	}
@@ -2459,7 +2483,7 @@
 				if m, ok := ccDep.(*Module); ok && m.IsStubs() { // LLNDK
 					// by default, use current version of LLNDK
 					versionToUse := ""
-					versions := stubsVersionsFor(ctx.Config())[depName]
+					versions := m.AllStubsVersions()
 					if c.ApexVariationName() != "" && len(versions) > 0 {
 						// if this is for use_vendor apex && dep has stubsVersions
 						// apply the same rule of apex sdk enforcement to choose right version
diff --git a/cc/cc_test.go b/cc/cc_test.go
index a4c0677..132d091 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -3025,6 +3025,7 @@
 }
 
 func checkEquals(t *testing.T, message string, expected, actual interface{}) {
+	t.Helper()
 	if !reflect.DeepEqual(actual, expected) {
 		t.Errorf(message+
 			"\nactual:   %v"+
diff --git a/cc/library.go b/cc/library.go
index 8d0c578..8048f00 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -150,6 +150,8 @@
 	BuildStubs bool `blueprint:"mutated"`
 	// Version of the stubs lib
 	StubsVersion string `blueprint:"mutated"`
+	// List of all stubs versions associated with an implementation lib
+	AllStubsVersions []string `blueprint:"mutated"`
 }
 
 type FlagExporterProperties struct {
@@ -1515,26 +1517,6 @@
 	}
 }
 
-var stubVersionsKey = android.NewOnceKey("stubVersions")
-
-// maps a module name to the list of stubs versions available for the module
-func stubsVersionsFor(config android.Config) map[string][]string {
-	return config.Once(stubVersionsKey, func() interface{} {
-		return make(map[string][]string)
-	}).(map[string][]string)
-}
-
-var stubsVersionsLock sync.Mutex
-
-func LatestStubsVersionFor(config android.Config, name string) string {
-	versions, ok := stubsVersionsFor(config)[name]
-	if ok && len(versions) > 0 {
-		// the versions are alreay sorted in ascending order
-		return versions[len(versions)-1]
-	}
-	return ""
-}
-
 func normalizeVersions(ctx android.BaseModuleContext, versions []string) {
 	var previous android.ApiLevel
 	for i, v := range versions {
@@ -1552,17 +1534,22 @@
 }
 
 func createVersionVariations(mctx android.BottomUpMutatorContext, versions []string) {
-	// "" is for the non-stubs variant
-	versions = append([]string{""}, versions...)
+	// "" is for the non-stubs (implementation) variant.
+	variants := append([]string{""}, versions...)
 
-	modules := mctx.CreateLocalVariations(versions...)
+	modules := mctx.CreateLocalVariations(variants...)
 	for i, m := range modules {
-		if versions[i] != "" {
+		if variants[i] != "" {
 			m.(LinkableInterface).SetBuildStubs()
-			m.(LinkableInterface).SetStubsVersions(versions[i])
+			m.(LinkableInterface).SetStubsVersion(variants[i])
 		}
 	}
 	mctx.AliasVariation("")
+	latestVersion := ""
+	if len(versions) > 0 {
+		latestVersion = versions[len(versions)-1]
+	}
+	mctx.CreateAliasVariation("latest", latestVersion)
 }
 
 func VersionVariantAvailable(module interface {
@@ -1573,44 +1560,41 @@
 	return !module.Host() && !module.InRamdisk() && !module.InRecovery()
 }
 
-// VersionMutator splits a module into the mandatory non-stubs variant
-// (which is unnamed) and zero or more stubs variants.
-func VersionMutator(mctx android.BottomUpMutatorContext) {
+// versionSelector normalizes the versions in the Stubs.Versions property into MutatedProperties.AllStubsVersions,
+// and propagates the value from implementation libraries to llndk libraries with the same name.
+func versionSelectorMutator(mctx android.BottomUpMutatorContext) {
 	if library, ok := mctx.Module().(LinkableInterface); ok && VersionVariantAvailable(library) {
 		if library.CcLibrary() && library.BuildSharedVariant() && len(library.StubsVersions()) > 0 &&
 			!library.IsSdkVariant() {
+
 			versions := library.StubsVersions()
 			normalizeVersions(mctx, versions)
 			if mctx.Failed() {
 				return
 			}
-
-			stubsVersionsLock.Lock()
-			defer stubsVersionsLock.Unlock()
-			// save the list of versions for later use
-			stubsVersionsFor(mctx.Config())[mctx.ModuleName()] = versions
-
-			createVersionVariations(mctx, versions)
+			// Set the versions on the pre-mutated module so they can be read by any llndk modules that
+			// depend on the implementation library and haven't been mutated yet.
+			library.SetAllStubsVersions(versions)
 			return
 		}
 
 		if c, ok := library.(*Module); ok && c.IsStubs() {
-			stubsVersionsLock.Lock()
-			defer stubsVersionsLock.Unlock()
-			// For LLNDK llndk_library, we borrow stubs.versions from its implementation library.
-			// Since llndk_library has dependency to its implementation library,
-			// we can safely access stubsVersionsFor() with its baseModuleName.
-			versions := stubsVersionsFor(mctx.Config())[c.BaseModuleName()]
-			// save the list of versions for later use
-			stubsVersionsFor(mctx.Config())[mctx.ModuleName()] = versions
-
-			createVersionVariations(mctx, versions)
-			return
+			// Get the versions from the implementation module.
+			impls := mctx.GetDirectDepsWithTag(llndkImplDep)
+			if len(impls) > 1 {
+				panic(fmt.Errorf("Expected single implmenetation library, got %d", len(impls)))
+			} else if len(impls) == 1 {
+				c.SetAllStubsVersions(impls[0].(*Module).AllStubsVersions())
+			}
 		}
+	}
+}
 
-		mctx.CreateLocalVariations("")
-		mctx.AliasVariation("")
-		return
+// versionMutator splits a module into the mandatory non-stubs variant
+// (which is unnamed) and zero or more stubs variants.
+func versionMutator(mctx android.BottomUpMutatorContext) {
+	if library, ok := mctx.Module().(LinkableInterface); ok && VersionVariantAvailable(library) {
+		createVersionVariations(mctx, library.AllStubsVersions())
 	}
 }
 
diff --git a/cc/library_sdk_member.go b/cc/library_sdk_member.go
index ecfdc99..2f15544 100644
--- a/cc/library_sdk_member.go
+++ b/cc/library_sdk_member.go
@@ -80,7 +80,7 @@
 		for _, target := range targets {
 			name, version := StubsLibNameAndVersion(lib)
 			if version == "" {
-				version = LatestStubsVersionFor(mctx.Config(), name)
+				version = "latest"
 			}
 			variations := target.Variations()
 			if mctx.Device() {
diff --git a/cc/linkable.go b/cc/linkable.go
index 4c84163..6d8a4b7 100644
--- a/cc/linkable.go
+++ b/cc/linkable.go
@@ -26,8 +26,10 @@
 	StubsVersions() []string
 	BuildStubs() bool
 	SetBuildStubs()
-	SetStubsVersions(string)
+	SetStubsVersion(string)
 	StubsVersion() string
+	SetAllStubsVersions([]string)
+	AllStubsVersions() []string
 	HasStubsVariants() bool
 	SelectedStl() string
 	ApiLevel() string
diff --git a/cc/lto.go b/cc/lto.go
index e034337..d1903b8 100644
--- a/cc/lto.go
+++ b/cc/lto.go
@@ -117,12 +117,11 @@
 			flags.Local.LdFlags = append(flags.Local.LdFlags, cachePolicyFormat+policy)
 		}
 
-		// If the module does not have a profile, be conservative and do not inline
-		// or unroll loops during LTO, in order to prevent significant size bloat.
+		// If the module does not have a profile, be conservative and limit cross TU inline
+		// limit to 5 LLVM IR instructions, to balance binary size increase and performance.
 		if !ctx.isPgoCompile() {
 			flags.Local.LdFlags = append(flags.Local.LdFlags,
-				"-Wl,-plugin-opt,-inline-threshold=0",
-				"-Wl,-plugin-opt,-unroll-threshold=0")
+				"-Wl,-plugin-opt,-import-instr-limit=5")
 		}
 	}
 	return flags
diff --git a/cc/pgo.go b/cc/pgo.go
index 6bf0ad0..439d2f7 100644
--- a/cc/pgo.go
+++ b/cc/pgo.go
@@ -70,6 +70,7 @@
 	PgoPresent          bool `blueprint:"mutated"`
 	ShouldProfileModule bool `blueprint:"mutated"`
 	PgoCompile          bool `blueprint:"mutated"`
+	PgoInstrLink        bool `blueprint:"mutated"`
 }
 
 type pgo struct {
@@ -89,13 +90,12 @@
 }
 
 func (props *PgoProperties) addInstrumentationProfileGatherFlags(ctx ModuleContext, flags Flags) Flags {
-	flags.Local.CFlags = append(flags.Local.CFlags, props.Pgo.Cflags...)
-
-	flags.Local.CFlags = append(flags.Local.CFlags, profileInstrumentFlag)
-	// The profile runtime is added below in deps().  Add the below
-	// flag, which is the only other link-time action performed by
-	// the Clang driver during link.
-	flags.Local.LdFlags = append(flags.Local.LdFlags, "-u__llvm_profile_runtime")
+	// Add to C flags iff PGO is explicitly enabled for this module.
+	if props.ShouldProfileModule {
+		flags.Local.CFlags = append(flags.Local.CFlags, props.Pgo.Cflags...)
+		flags.Local.CFlags = append(flags.Local.CFlags, profileInstrumentFlag)
+	}
+	flags.Local.LdFlags = append(flags.Local.LdFlags, profileInstrumentFlag)
 	return flags
 }
 func (props *PgoProperties) addSamplingProfileGatherFlags(ctx ModuleContext, flags Flags) Flags {
@@ -250,10 +250,12 @@
 
 	if pgoBenchmarksMap["all"] == true || pgoBenchmarksMap["ALL"] == true {
 		pgo.Properties.ShouldProfileModule = true
+		pgo.Properties.PgoInstrLink = pgo.Properties.isInstrumentation()
 	} else {
 		for _, b := range pgo.Properties.Pgo.Benchmarks {
 			if pgoBenchmarksMap[b] == true {
 				pgo.Properties.ShouldProfileModule = true
+				pgo.Properties.PgoInstrLink = pgo.Properties.isInstrumentation()
 				break
 			}
 		}
@@ -286,10 +288,42 @@
 		return flags
 	}
 
-	props := pgo.Properties
+	// Deduce PgoInstrLink property i.e. whether this module needs to be
+	// linked with profile-generation flags.  Here, we're setting it if any
+	// dependency needs PGO instrumentation.  It is initially set in
+	// begin() if PGO is directly enabled for this module.
+	if ctx.static() && !ctx.staticBinary() {
+		// For static libraries, check if any whole_static_libs are
+		// linked with profile generation
+		ctx.VisitDirectDeps(func(m android.Module) {
+			if depTag, ok := ctx.OtherModuleDependencyTag(m).(libraryDependencyTag); ok {
+				if depTag.static() && depTag.wholeStatic {
+					if cc, ok := m.(*Module); ok {
+						if cc.pgo.Properties.PgoInstrLink {
+							pgo.Properties.PgoInstrLink = true
+						}
+					}
+				}
+			}
+		})
+	} else {
+		// For executables and shared libraries, check all static dependencies.
+		ctx.VisitDirectDeps(func(m android.Module) {
+			if depTag, ok := ctx.OtherModuleDependencyTag(m).(libraryDependencyTag); ok {
+				if depTag.static() {
+					if cc, ok := m.(*Module); ok {
+						if cc.pgo.Properties.PgoInstrLink {
+							pgo.Properties.PgoInstrLink = true
+						}
+					}
+				}
+			}
+		})
+	}
 
+	props := pgo.Properties
 	// Add flags to profile this module based on its profile_kind
-	if props.ShouldProfileModule && props.isInstrumentation() {
+	if (props.ShouldProfileModule && props.isInstrumentation()) || props.PgoInstrLink {
 		// Instrumentation PGO use and gather flags cannot coexist.
 		return props.addInstrumentationProfileGatherFlags(ctx, flags)
 	} else if props.ShouldProfileModule && props.isSampling() {
diff --git a/cc/prebuilt.go b/cc/prebuilt.go
index 1ee096e..9d1b016 100644
--- a/cc/prebuilt.go
+++ b/cc/prebuilt.go
@@ -16,6 +16,7 @@
 
 import (
 	"android/soong/android"
+	"path/filepath"
 )
 
 func init() {
@@ -360,13 +361,18 @@
 			sharedLibPaths = append(sharedLibPaths, deps.SharedLibs...)
 			sharedLibPaths = append(sharedLibPaths, deps.LateSharedLibs...)
 
+			var fromPath = in.String()
+			if !filepath.IsAbs(fromPath) {
+				fromPath = "$$PWD/" + fromPath
+			}
+
 			ctx.Build(pctx, android.BuildParams{
 				Rule:      android.Symlink,
 				Output:    outputFile,
 				Input:     in,
 				Implicits: sharedLibPaths,
 				Args: map[string]string{
-					"fromPath": "$$PWD/" + in.String(),
+					"fromPath": fromPath,
 				},
 			})
 
diff --git a/rust/rust.go b/rust/rust.go
index e561477..d22acea 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -460,12 +460,20 @@
 	panic("SetBuildStubs not yet implemented for rust modules")
 }
 
-func (mod *Module) SetStubsVersions(string) {
-	panic("SetStubsVersions not yet implemented for rust modules")
+func (mod *Module) SetStubsVersion(string) {
+	panic("SetStubsVersion not yet implemented for rust modules")
 }
 
 func (mod *Module) StubsVersion() string {
-	panic("SetStubsVersions not yet implemented for rust modules")
+	panic("StubsVersion not yet implemented for rust modules")
+}
+
+func (mod *Module) SetAllStubsVersions([]string) {
+	panic("SetAllStubsVersions not yet implemented for rust modules")
+}
+
+func (mod *Module) AllStubsVersions() []string {
+	return nil
 }
 
 func (mod *Module) BuildStaticVariant() bool {