Merge tag 'android-11.0.0_r48' of https://android.googlesource.com/platform//build/soong into r

Android 11.0.0 Release 48 (RD2A.211001.002)

Change-Id: Iae772858f9d035ce13e3f433350984594a25a5b4
diff --git a/android/Android.bp b/android/Android.bp
index bd72b7b..0ebcce7 100644
--- a/android/Android.bp
+++ b/android/Android.bp
@@ -14,6 +14,7 @@
         "apex.go",
         "api_levels.go",
         "arch.go",
+        "bootjar.go",
         "config.go",
         "csuite_config.go",
         "defaults.go",
diff --git a/android/apex.go b/android/apex.go
index 30152db..f0ff7ad 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -29,11 +29,22 @@
 )
 
 type ApexInfo struct {
-	// Name of the apex variant that this module is mutated into
-	ApexName string
+	// Name of the apex variation that this module is mutated into
+	ApexVariationName string
 
 	MinSdkVersion int
 	Updatable     bool
+	RequiredSdks  SdkRefs
+
+	InApexes []string
+}
+
+func (i ApexInfo) mergedName() string {
+	name := "apex" + strconv.Itoa(i.MinSdkVersion)
+	for _, sdk := range i.RequiredSdks {
+		name += "_" + sdk.Name + "_" + sdk.Version
+	}
+	return name
 }
 
 // Extracted from ApexModule to make it easier to define custom subsets of the
@@ -65,23 +76,26 @@
 
 	apexModuleBase() *ApexModuleBase
 
-	// Marks that this module should be built for the specified APEXes.
+	// Marks that this module should be built for the specified APEX.
 	// Call this before apex.apexMutator is run.
-	BuildForApexes(apexes []ApexInfo)
+	BuildForApex(apex ApexInfo)
 
-	// Returns the APEXes that this module will be built for
-	ApexVariations() []ApexInfo
-
-	// Returns the name of APEX that this module will be built for. Empty string
-	// is returned when 'IsForPlatform() == true'. Note that a module can be
-	// included in multiple APEXes, in which case, the module is mutated into
-	// multiple modules each of which for an APEX. This method returns the
-	// name of the APEX that a variant module is for.
+	// Returns the name of APEX variation that this module will be built for.
+	// Empty string is returned when 'IsForPlatform() == true'. Note that a
+	// module can beincluded in multiple APEXes, in which case, the module
+	// is mutated into one or more variants, each of which is for one or
+	// more APEXes.  This method returns the name of the APEX variation of
+	// the module.
 	// Call this after apex.apexMutator is run.
-	ApexName() string
+	ApexVariationName() string
+
+	// Returns the name of the APEX modules that this variant of this module
+	// is present in.
+	// Call this after apex.apexMutator is run.
+	InApexes() []string
 
 	// Tests whether this module will be built for the platform or not.
-	// This is a shortcut for ApexName() == ""
+	// This is a shortcut for ApexVariationName() == ""
 	IsForPlatform() bool
 
 	// Tests if this module could have APEX variants. APEX variants are
@@ -96,7 +110,7 @@
 	IsInstallableToApex() bool
 
 	// Mutate this module into one or more variants each of which is built
-	// for an APEX marked via BuildForApexes().
+	// for an APEX marked via BuildForApex().
 	CreateApexVariations(mctx BottomUpMutatorContext) []Module
 
 	// Tests if this module is available for the specified APEX or ":platform"
@@ -124,6 +138,15 @@
 	// the private part of the listed APEXes even when it is not included in the
 	// APEXes.
 	TestFor() []string
+
+	// Returns true if this module needs a unique variation per apex, for example if
+	// use_apex_name_macro is set.
+	UniqueApexVariations() bool
+
+	// UpdateUniqueApexVariationsForDeps sets UniqueApexVariationsForDeps if any dependencies
+	// that are in the same APEX have unique APEX variations so that the module can link against
+	// the right variant.
+	UpdateUniqueApexVariationsForDeps(mctx BottomUpMutatorContext)
 }
 
 type ApexProperties struct {
@@ -139,6 +162,8 @@
 	Info ApexInfo `blueprint:"mutated"`
 
 	NotAvailableForPlatform bool `blueprint:"mutated"`
+
+	UniqueApexVariationsForDeps bool `blueprint:"mutated"`
 }
 
 // Marker interface that identifies dependencies that are excluded from APEX
@@ -174,30 +199,68 @@
 	return nil
 }
 
-func (m *ApexModuleBase) BuildForApexes(apexes []ApexInfo) {
-	m.apexVariationsLock.Lock()
-	defer m.apexVariationsLock.Unlock()
-nextApex:
-	for _, apex := range apexes {
-		for _, v := range m.apexVariations {
-			if v.ApexName == apex.ApexName {
-				continue nextApex
+func (m *ApexModuleBase) UniqueApexVariations() bool {
+	return false
+}
+
+func (m *ApexModuleBase) UpdateUniqueApexVariationsForDeps(mctx BottomUpMutatorContext) {
+	// anyInSameApex returns true if the two ApexInfo lists contain any values in an InApexes list
+	// in common.  It is used instead of DepIsInSameApex because it needs to determine if the dep
+	// is in the same APEX due to being directly included, not only if it is included _because_ it
+	// is a dependency.
+	anyInSameApex := func(a, b []ApexInfo) bool {
+		collectApexes := func(infos []ApexInfo) []string {
+			var ret []string
+			for _, info := range infos {
+				ret = append(ret, info.InApexes...)
+			}
+			return ret
+		}
+
+		aApexes := collectApexes(a)
+		bApexes := collectApexes(b)
+		sort.Strings(bApexes)
+		for _, aApex := range aApexes {
+			index := sort.SearchStrings(bApexes, aApex)
+			if index < len(bApexes) && bApexes[index] == aApex {
+				return true
 			}
 		}
-		m.apexVariations = append(m.apexVariations, apex)
+		return false
 	}
+
+	mctx.VisitDirectDeps(func(dep Module) {
+		if depApexModule, ok := dep.(ApexModule); ok {
+			if anyInSameApex(depApexModule.apexModuleBase().apexVariations, m.apexVariations) &&
+				(depApexModule.UniqueApexVariations() ||
+					depApexModule.apexModuleBase().ApexProperties.UniqueApexVariationsForDeps) {
+				m.ApexProperties.UniqueApexVariationsForDeps = true
+			}
+		}
+	})
 }
 
-func (m *ApexModuleBase) ApexVariations() []ApexInfo {
-	return m.apexVariations
+func (m *ApexModuleBase) BuildForApex(apex ApexInfo) {
+	m.apexVariationsLock.Lock()
+	defer m.apexVariationsLock.Unlock()
+	for _, v := range m.apexVariations {
+		if v.ApexVariationName == apex.ApexVariationName {
+			return
+		}
+	}
+	m.apexVariations = append(m.apexVariations, apex)
 }
 
-func (m *ApexModuleBase) ApexName() string {
-	return m.ApexProperties.Info.ApexName
+func (m *ApexModuleBase) ApexVariationName() string {
+	return m.ApexProperties.Info.ApexVariationName
+}
+
+func (m *ApexModuleBase) InApexes() []string {
+	return m.ApexProperties.Info.InApexes
 }
 
 func (m *ApexModuleBase) IsForPlatform() bool {
-	return m.ApexProperties.Info.ApexName == ""
+	return m.ApexProperties.Info.ApexVariationName == ""
 }
 
 func (m *ApexModuleBase) CanHaveApexVariants() bool {
@@ -272,17 +335,48 @@
 
 func (a byApexName) Len() int           { return len(a) }
 func (a byApexName) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
-func (a byApexName) Less(i, j int) bool { return a[i].ApexName < a[j].ApexName }
+func (a byApexName) Less(i, j int) bool { return a[i].ApexVariationName < a[j].ApexVariationName }
+
+// mergeApexVariations deduplicates APEX variations that would build identically into a common
+// variation.  It returns the reduced list of variations and a list of aliases from the original
+// variation names to the new variation names.
+func mergeApexVariations(apexVariations []ApexInfo) (merged []ApexInfo, aliases [][2]string) {
+	sort.Sort(byApexName(apexVariations))
+	seen := make(map[string]int)
+	for _, apexInfo := range apexVariations {
+		apexName := apexInfo.ApexVariationName
+		mergedName := apexInfo.mergedName()
+		if index, exists := seen[mergedName]; exists {
+			merged[index].InApexes = append(merged[index].InApexes, apexName)
+			merged[index].Updatable = merged[index].Updatable || apexInfo.Updatable
+		} else {
+			seen[mergedName] = len(merged)
+			apexInfo.ApexVariationName = apexInfo.mergedName()
+			apexInfo.InApexes = CopyOf(apexInfo.InApexes)
+			merged = append(merged, apexInfo)
+		}
+		aliases = append(aliases, [2]string{apexName, mergedName})
+	}
+	return merged, aliases
+}
 
 func (m *ApexModuleBase) CreateApexVariations(mctx BottomUpMutatorContext) []Module {
 	if len(m.apexVariations) > 0 {
 		m.checkApexAvailableProperty(mctx)
 
-		sort.Sort(byApexName(m.apexVariations))
+		var apexVariations []ApexInfo
+		var aliases [][2]string
+		if !mctx.Module().(ApexModule).UniqueApexVariations() && !m.ApexProperties.UniqueApexVariationsForDeps {
+			apexVariations, aliases = mergeApexVariations(m.apexVariations)
+		} else {
+			apexVariations = m.apexVariations
+		}
+
+		sort.Sort(byApexName(apexVariations))
 		variations := []string{}
 		variations = append(variations, "") // Original variation for platform
-		for _, apex := range m.apexVariations {
-			variations = append(variations, apex.ApexName)
+		for _, apex := range apexVariations {
+			variations = append(variations, apex.ApexVariationName)
 		}
 
 		defaultVariation := ""
@@ -295,9 +389,14 @@
 				mod.SkipInstall()
 			}
 			if !platformVariation {
-				mod.(ApexModule).apexModuleBase().ApexProperties.Info = m.apexVariations[i-1]
+				mod.(ApexModule).apexModuleBase().ApexProperties.Info = apexVariations[i-1]
 			}
 		}
+
+		for _, alias := range aliases {
+			mctx.CreateAliasVariation(alias[0], alias[1])
+		}
+
 		return modules
 	}
 	return nil
@@ -323,16 +422,17 @@
 // depended on by the specified APEXes. Directly depending means that a module
 // is explicitly listed in the build definition of the APEX via properties like
 // native_shared_libs, java_libs, etc.
-func UpdateApexDependency(apexes []ApexInfo, moduleName string, directDep bool) {
+func UpdateApexDependency(apex ApexInfo, moduleName string, directDep bool) {
 	apexNamesMapMutex.Lock()
 	defer apexNamesMapMutex.Unlock()
-	for _, apex := range apexes {
-		apexesForModule, ok := apexNamesMap()[moduleName]
-		if !ok {
-			apexesForModule = make(map[string]bool)
-			apexNamesMap()[moduleName] = apexesForModule
-		}
-		apexesForModule[apex.ApexName] = apexesForModule[apex.ApexName] || directDep
+	apexesForModule, ok := apexNamesMap()[moduleName]
+	if !ok {
+		apexesForModule = make(map[string]bool)
+		apexNamesMap()[moduleName] = apexesForModule
+	}
+	apexesForModule[apex.ApexVariationName] = apexesForModule[apex.ApexVariationName] || directDep
+	for _, apexName := range apex.InApexes {
+		apexesForModule[apexName] = apexesForModule[apex.ApexVariationName] || directDep
 	}
 }
 
@@ -349,12 +449,26 @@
 func DirectlyInApex(apexName string, moduleName string) bool {
 	apexNamesMapMutex.Lock()
 	defer apexNamesMapMutex.Unlock()
-	if apexNames, ok := apexNamesMap()[moduleName]; ok {
-		return apexNames[apexName]
+	if apexNamesForModule, ok := apexNamesMap()[moduleName]; ok {
+		return apexNamesForModule[apexName]
 	}
 	return false
 }
 
+// Tests whether a module named moduleName is directly depended on by all APEXes
+// in a list of apexNames.
+func DirectlyInAllApexes(apexNames []string, moduleName string) bool {
+	apexNamesMapMutex.Lock()
+	defer apexNamesMapMutex.Unlock()
+	for _, apexName := range apexNames {
+		apexNamesForModule := apexNamesMap()[moduleName]
+		if !apexNamesForModule[apexName] {
+			return false
+		}
+	}
+	return true
+}
+
 type hostContext interface {
 	Host() bool
 }
diff --git a/android/apex_test.go b/android/apex_test.go
new file mode 100644
index 0000000..db02833
--- /dev/null
+++ b/android/apex_test.go
@@ -0,0 +1,111 @@
+// Copyright 2020 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package android
+
+import (
+	"reflect"
+	"testing"
+)
+
+func Test_mergeApexVariations(t *testing.T) {
+	tests := []struct {
+		name        string
+		in          []ApexInfo
+		wantMerged  []ApexInfo
+		wantAliases [][2]string
+	}{
+		{
+			name: "single",
+			in: []ApexInfo{
+				{"foo", 10000, false, nil, []string{"foo"}},
+			},
+			wantMerged: []ApexInfo{
+				{"apex10000", 10000, false, nil, []string{"foo"}},
+			},
+			wantAliases: [][2]string{
+				{"foo", "apex10000"},
+			},
+		},
+		{
+			name: "merge",
+			in: []ApexInfo{
+				{"foo", 10000, false, SdkRefs{{"baz", "1"}}, []string{"foo"}},
+				{"bar", 10000, false, SdkRefs{{"baz", "1"}}, []string{"bar"}},
+			},
+			wantMerged: []ApexInfo{
+				{"apex10000_baz_1", 10000, false, SdkRefs{{"baz", "1"}}, []string{"bar", "foo"}},
+			},
+			wantAliases: [][2]string{
+				{"bar", "apex10000_baz_1"},
+				{"foo", "apex10000_baz_1"},
+			},
+		},
+		{
+			name: "don't merge version",
+			in: []ApexInfo{
+				{"foo", 10000, false, nil, []string{"foo"}},
+				{"bar", 30, false, nil, []string{"bar"}},
+			},
+			wantMerged: []ApexInfo{
+				{"apex30", 30, false, nil, []string{"bar"}},
+				{"apex10000", 10000, false, nil, []string{"foo"}},
+			},
+			wantAliases: [][2]string{
+				{"bar", "apex30"},
+				{"foo", "apex10000"},
+			},
+		},
+		{
+			name: "merge updatable",
+			in: []ApexInfo{
+				{"foo", 10000, false, nil, []string{"foo"}},
+				{"bar", 10000, true, nil, []string{"bar"}},
+			},
+			wantMerged: []ApexInfo{
+				{"apex10000", 10000, true, nil, []string{"bar", "foo"}},
+			},
+			wantAliases: [][2]string{
+				{"bar", "apex10000"},
+				{"foo", "apex10000"},
+			},
+		},
+		{
+			name: "don't merge sdks",
+			in: []ApexInfo{
+				{"foo", 10000, false, SdkRefs{{"baz", "1"}}, []string{"foo"}},
+				{"bar", 10000, false, SdkRefs{{"baz", "2"}}, []string{"bar"}},
+			},
+			wantMerged: []ApexInfo{
+				{"apex10000_baz_2", 10000, false, SdkRefs{{"baz", "2"}}, []string{"bar"}},
+				{"apex10000_baz_1", 10000, false, SdkRefs{{"baz", "1"}}, []string{"foo"}},
+			},
+			wantAliases: [][2]string{
+				{"bar", "apex10000_baz_2"},
+				{"foo", "apex10000_baz_1"},
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			gotMerged, gotAliases := mergeApexVariations(tt.in)
+			if !reflect.DeepEqual(gotMerged, tt.wantMerged) {
+				t.Errorf("mergeApexVariations() gotMerged = %v, want %v", gotMerged, tt.wantMerged)
+			}
+			if !reflect.DeepEqual(gotAliases, tt.wantAliases) {
+				t.Errorf("mergeApexVariations() gotAliases = %v, want %v", gotAliases, tt.wantAliases)
+			}
+		})
+	}
+}
diff --git a/android/bootjar.go b/android/bootjar.go
new file mode 100644
index 0000000..ea04dc8
--- /dev/null
+++ b/android/bootjar.go
@@ -0,0 +1,117 @@
+// Copyright (C) 2019 The LineageOS Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package android
+
+import (
+	"strings"
+)
+
+// Keys are bootjar name, value is whether or not
+// we've marked a module as being a provider for it.
+var jarMap map[string]bool
+
+func init() {
+	PreArchMutators(RegisterBootJarMutators)
+}
+
+// Note: registration function is structured this way so that it can be included
+// from soong module tests.
+func RegisterBootJarMutators(ctx RegisterMutatorsContext) {
+	// Note: can't use Parallel() since we touch global jarMap
+	ctx.TopDown("bootjar_exportednamespace", bootJarMutatorExportedNamespace)
+	ctx.TopDown("bootjar_anynamespace", bootJarMutatorAnyNamespace)
+}
+
+func mutatorInit(mctx TopDownMutatorContext) {
+	// Did we init already ?
+	if jarMap != nil {
+		return
+	}
+
+	jarMap = make(map[string]bool)
+	for _, moduleName := range mctx.Config().BootJars() {
+		jarMap[moduleName] = false
+	}
+}
+
+// Mark modules in soong exported namespace as providing a boot jar.
+func bootJarMutatorExportedNamespace(mctx TopDownMutatorContext) {
+	bootJarMutator(mctx, true)
+}
+
+// Mark modules in any namespace (incl root) as providing a boot jar.
+func bootJarMutatorAnyNamespace(mctx TopDownMutatorContext) {
+	bootJarMutator(mctx, false)
+}
+
+func bootJarMutator(mctx TopDownMutatorContext, requireExportedNamespace bool) {
+	mutatorInit(mctx)
+
+	module, ok := mctx.Module().(Module)
+	if !ok {
+		// Not a proper module
+		return
+	}
+
+	// Does this module produce a dex jar ?
+	if _, ok := module.(interface{ DexJar() Path }); !ok {
+		// No
+		return
+	}
+
+	// If jarMap is empty we must be running in a test so
+	// set boot jar provide to true for all modules.
+	if len(jarMap) == 0 {
+		module.base().commonProperties.BootJarProvider = true
+		return
+	}
+
+	name := mctx.ModuleName()
+	dir := mctx.ModuleDir()
+
+	// Special treatment for hiddenapi modules - create extra
+	// jarMap entries if needed.
+	baseName := strings.TrimSuffix(name, "-hiddenapi")
+	if name != baseName {
+		_, baseIsBootJar := jarMap[baseName]
+		_, alreadyExists := jarMap[name]
+		if baseIsBootJar && !alreadyExists {
+			// This is a hidden api module whose base name exists in the boot jar list
+			// and we've not visited it before.  Create a map entry for it.
+			jarMap[name] = false
+		}
+	}
+
+	// Does this module match the name of a boot jar ?
+	if found, exists := jarMap[name]; !exists || found {
+		// No
+		return
+	}
+
+	if requireExportedNamespace {
+		for _, n := range mctx.Config().ExportedNamespaces() {
+			if strings.HasPrefix(dir, n) {
+				jarMap[name] = true
+				module.base().commonProperties.BootJarProvider = true
+				break
+			}
+		}
+	} else {
+		jarMap[name] = true
+		module.base().commonProperties.BootJarProvider = true
+	}
+
+	return
+}
diff --git a/android/config.go b/android/config.go
index 3417729..d345efc 100644
--- a/android/config.go
+++ b/android/config.go
@@ -1044,6 +1044,10 @@
 	return c.config.productVariables.DeviceKernelHeaders
 }
 
+func (c *deviceConfig) TargetSpecificHeaderPath() string {
+	return String(c.config.productVariables.TargetSpecificHeaderPath)
+}
+
 func (c *deviceConfig) SamplingPGO() bool {
 	return Bool(c.config.productVariables.SamplingPGO)
 }
diff --git a/android/module.go b/android/module.go
index a498839..78c827c 100644
--- a/android/module.go
+++ b/android/module.go
@@ -215,6 +215,16 @@
 	// For more information, see Module.GenerateBuildActions within Blueprint's module_ctx.go
 	GenerateAndroidBuildActions(ModuleContext)
 
+	// Add dependencies to the components of a module, i.e. modules that are created
+	// by the module and which are considered to be part of the creating module.
+	//
+	// This is called before prebuilts are renamed so as to allow a dependency to be
+	// added directly to a prebuilt child module instead of depending on a source module
+	// and relying on prebuilt processing to switch to the prebuilt module if preferred.
+	//
+	// A dependency on a prebuilt must include the "prebuilt_" prefix.
+	ComponentDepsMutator(ctx BottomUpMutatorContext)
+
 	DepsMutator(BottomUpMutatorContext)
 
 	base() *ModuleBase
@@ -523,6 +533,9 @@
 
 	// set by ImageMutator
 	ImageVariation string `blueprint:"mutated"`
+
+	// Whether this module provides a boot jar
+	BootJarProvider bool `blueprint:"mutated"`
 }
 
 type hostAndDeviceProperties struct {
@@ -737,6 +750,8 @@
 	prefer32 func(ctx BaseModuleContext, base *ModuleBase, class OsClass) bool
 }
 
+func (m *ModuleBase) ComponentDepsMutator(BottomUpMutatorContext) {}
+
 func (m *ModuleBase) DepsMutator(BottomUpMutatorContext) {}
 
 func (m *ModuleBase) AddProperties(props ...interface{}) {
@@ -786,6 +801,10 @@
 	return sb.String()
 }
 
+func (a *ModuleBase) BootJarProvider() bool {
+	return a.commonProperties.BootJarProvider
+}
+
 // BaseModuleName returns the name of the module as specified in the blueprints file.
 func (m *ModuleBase) BaseModuleName() string {
 	return String(m.nameProperties.Name)
@@ -1226,7 +1245,7 @@
 		suffix = append(suffix, ctx.Arch().ArchType.String())
 	}
 	if apex, ok := m.module.(ApexModule); ok && !apex.IsForPlatform() {
-		suffix = append(suffix, apex.ApexName())
+		suffix = append(suffix, apex.ApexVariationName())
 	}
 
 	ctx.Variable(pctx, "moduleDesc", desc)
diff --git a/android/mutator.go b/android/mutator.go
index 77d5f43..40e61de 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -115,6 +115,18 @@
 	// a DefaultableHook.
 	RegisterDefaultsPreArchMutators,
 
+	// Add dependencies on any components so that any component references can be
+	// resolved within the deps mutator.
+	//
+	// Must be run after defaults so it can be used to create dependencies on the
+	// component modules that are creating in a DefaultableHook.
+	//
+	// Must be run before RegisterPrebuiltsPreArchMutators, i.e. before prebuilts are
+	// renamed. That is so that if a module creates components using a prebuilt module
+	// type that any dependencies (which must use prebuilt_ prefixes) are resolved to
+	// the prebuilt module and not the source module.
+	RegisterComponentsMutator,
+
 	// Create an association between prebuilt modules and their corresponding source
 	// modules (if any).
 	//
@@ -202,7 +214,9 @@
 	AddFarVariationDependencies([]blueprint.Variation, blueprint.DependencyTag, ...string)
 	AddInterVariantDependency(tag blueprint.DependencyTag, from, to blueprint.Module)
 	ReplaceDependencies(string)
+	ReplaceDependenciesIf(string, blueprint.ReplaceDependencyPredicate)
 	AliasVariation(variationName string)
+	CreateAliasVariation(fromVariationName, toVariationName string)
 }
 
 type bottomUpMutatorContext struct {
@@ -252,8 +266,21 @@
 	return mutator
 }
 
+func RegisterComponentsMutator(ctx RegisterMutatorsContext) {
+	ctx.BottomUp("component-deps", componentDepsMutator).Parallel()
+}
+
+// A special mutator that runs just prior to the deps mutator to allow the dependencies
+// on component modules to be added so that they can depend directly on a prebuilt
+// module.
+func componentDepsMutator(ctx BottomUpMutatorContext) {
+	if m := ctx.Module(); m.Enabled() {
+		m.ComponentDepsMutator(ctx)
+	}
+}
+
 func depsMutator(ctx BottomUpMutatorContext) {
-	if m, ok := ctx.Module().(Module); ok && m.Enabled() {
+	if m := ctx.Module(); m.Enabled() {
 		m.DepsMutator(ctx)
 	}
 }
@@ -403,6 +430,14 @@
 	b.bp.ReplaceDependencies(name)
 }
 
+func (b *bottomUpMutatorContext) ReplaceDependenciesIf(name string, predicate blueprint.ReplaceDependencyPredicate) {
+	b.bp.ReplaceDependenciesIf(name, predicate)
+}
+
 func (b *bottomUpMutatorContext) AliasVariation(variationName string) {
 	b.bp.AliasVariation(variationName)
 }
+
+func (b *bottomUpMutatorContext) CreateAliasVariation(fromVariationName, toVariationName string) {
+	b.bp.CreateAliasVariation(fromVariationName, toVariationName)
+}
diff --git a/android/override_module.go b/android/override_module.go
index 90ddf50..6b246db 100644
--- a/android/override_module.go
+++ b/android/override_module.go
@@ -223,6 +223,11 @@
 // next phase.
 func overrideModuleDepsMutator(ctx BottomUpMutatorContext) {
 	if module, ok := ctx.Module().(OverrideModule); ok {
+		base := String(module.getOverrideModuleProperties().Base)
+		if !ctx.OtherModuleExists(base) {
+			ctx.PropertyErrorf("base", "%q is not a valid module name", base)
+			return
+		}
 		// See if there's a prebuilt module that overrides this override module with prefer flag,
 		// in which case we call SkipInstall on the corresponding variant later.
 		ctx.VisitDirectDepsWithTag(PrebuiltDepTag, func(dep Module) {
diff --git a/android/paths.go b/android/paths.go
index ddbeed3..44d26df 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -724,6 +724,31 @@
 	return ret, nil
 }
 
+// pathForSourceRelaxed creates a SourcePath from pathComponents, but does not check that it exists.
+// It differs from pathForSource in that the path is allowed to exist outside of the PathContext.
+func pathForSourceRelaxed(ctx PathContext, pathComponents ...string) (SourcePath, error) {
+	p := filepath.Join(pathComponents...)
+	ret := SourcePath{basePath{p, ctx.Config(), ""}}
+
+	abs, err := filepath.Abs(ret.String())
+	if err != nil {
+		return ret, err
+	}
+	buildroot, err := filepath.Abs(ctx.Config().buildDir)
+	if err != nil {
+		return ret, err
+	}
+	if strings.HasPrefix(abs, buildroot) {
+		return ret, fmt.Errorf("source path %s is in output", abs)
+	}
+
+	if pathtools.IsGlob(ret.String()) {
+		return ret, fmt.Errorf("path may not contain a glob: %s", ret.String())
+	}
+
+	return ret, nil
+}
+
 // existsWithDependencies returns true if the path exists, and adds appropriate dependencies to rerun if the
 // path does not exist.
 func existsWithDependencies(ctx PathContext, path SourcePath) (exists bool, err error) {
@@ -777,6 +802,31 @@
 	return path
 }
 
+// PathForSourceRelaxed joins the provided path components.  Unlike PathForSource,
+// the result is allowed to exist outside of the source dir.
+// On error, it will return a usable, but invalid SourcePath, and report a ModuleError.
+func PathForSourceRelaxed(ctx PathContext, pathComponents ...string) SourcePath {
+	path, err := pathForSourceRelaxed(ctx, pathComponents...)
+	if err != nil {
+		reportPathError(ctx, err)
+	}
+
+	if modCtx, ok := ctx.(ModuleContext); ok && ctx.Config().AllowMissingDependencies() {
+		exists, err := existsWithDependencies(ctx, path)
+		if err != nil {
+			reportPathError(ctx, err)
+		}
+		if !exists {
+			modCtx.AddMissingDependencies([]string{path.String()})
+		}
+	} else if exists, _, err := ctx.Config().fs.Exists(path.String()); err != nil {
+		reportPathErrorf(ctx, "%s: %s", path, err.Error())
+	} else if !exists {
+		reportPathErrorf(ctx, "source path %s does not exist", path)
+	}
+	return path
+}
+
 // ExistentPathForSource returns an OptionalPath with the SourcePath if the
 // path exists, or an empty OptionalPath if it doesn't exist. Dependencies are added
 // so that the ninja file will be regenerated if the state of the path changes.
diff --git a/android/prebuilt.go b/android/prebuilt.go
index ee4a13a..dfab13b 100644
--- a/android/prebuilt.go
+++ b/android/prebuilt.go
@@ -30,6 +30,16 @@
 	ctx.PostDepsMutators(RegisterPrebuiltsPostDepsMutators)
 }
 
+// Marks a dependency tag as possibly preventing a reference to a source from being
+// replaced with the prebuilt.
+type ReplaceSourceWithPrebuilt interface {
+	blueprint.DependencyTag
+
+	// Return true if the dependency defined by this tag should be replaced with the
+	// prebuilt.
+	ReplaceSourceWithPrebuilt() bool
+}
+
 type prebuiltDependencyTag struct {
 	blueprint.BaseDependencyTag
 }
@@ -244,7 +254,13 @@
 		name := m.base().BaseModuleName()
 		if p.properties.UsePrebuilt {
 			if p.properties.SourceExists {
-				ctx.ReplaceDependencies(name)
+				ctx.ReplaceDependenciesIf(name, func(from blueprint.Module, tag blueprint.DependencyTag, to blueprint.Module) bool {
+					if t, ok := tag.(ReplaceSourceWithPrebuilt); ok {
+						return t.ReplaceSourceWithPrebuilt()
+					}
+
+					return true
+				})
 			}
 		} else {
 			m.SkipInstall()
diff --git a/android/testing.go b/android/testing.go
index 90989ef..42acb6f 100644
--- a/android/testing.go
+++ b/android/testing.go
@@ -382,7 +382,7 @@
 	if !found {
 		t.Errorf("missing the expected error %q (checked %d error(s))", pattern, len(errs))
 		for i, err := range errs {
-			t.Errorf("errs[%d] = %s", i, err)
+			t.Errorf("errs[%d] = %q", i, err)
 		}
 	}
 }
diff --git a/android/variable.go b/android/variable.go
index 983c235..0a80e2a 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -49,6 +49,13 @@
 			Exclude_static_libs []string `android:"arch_variant"`
 		} `android:"arch_variant"`
 
+		Malloc_not_svelte_libc32 struct {
+			Cflags              []string `android:"arch_variant"`
+			Shared_libs         []string `android:"arch_variant"`
+			Whole_static_libs   []string `android:"arch_variant"`
+			Exclude_static_libs []string `android:"arch_variant"`
+		} `android:"arch_variant"`
+
 		Safestack struct {
 			Cflags []string `android:"arch_variant"`
 		} `android:"arch_variant"`
@@ -131,6 +138,7 @@
 			Srcs         []string `android:"arch_variant"`
 			Exclude_srcs []string `android:"arch_variant"`
 		} `android:"arch_variant"`
+
 	} `android:"arch_variant"`
 }
 
@@ -207,6 +215,7 @@
 	Unbundled_build                  *bool `json:",omitempty"`
 	Unbundled_build_sdks_from_source *bool `json:",omitempty"`
 	Malloc_not_svelte                *bool `json:",omitempty"`
+	Malloc_not_svelte_libc32         *bool `json:",omitempty"`
 	Safestack                        *bool `json:",omitempty"`
 	HostStaticBinaries               *bool `json:",omitempty"`
 	Binder32bit                      *bool `json:",omitempty"`
@@ -283,6 +292,8 @@
 
 	DeviceKernelHeaders []string `json:",omitempty"`
 
+	TargetSpecificHeaderPath *string `json:",omitempty"`
+
 	ExtraVndkVersions []string `json:",omitempty"`
 
 	NamespacesToExport []string `json:",omitempty"`
@@ -336,6 +347,7 @@
 	InstallExtraFlattenedApexes *bool `json:",omitempty"`
 
 	BoardUsesRecoveryAsBoot *bool `json:",omitempty"`
+
 }
 
 func boolPtr(v bool) *bool {
@@ -378,8 +390,9 @@
 		AAPTCharacteristics: stringPtr("nosdcard"),
 		AAPTPrebuiltDPI:     []string{"xhdpi", "xxhdpi"},
 
-		Malloc_not_svelte: boolPtr(true),
-		Safestack:         boolPtr(false),
+		Malloc_not_svelte:        boolPtr(true),
+		Malloc_not_svelte_libc32: boolPtr(true),
+		Safestack:                boolPtr(false),
 	}
 
 	if runtime.GOOS == "linux" {
@@ -411,8 +424,8 @@
 		property := "product_variables." + proptools.PropertyNameForField(name)
 
 		// Check that the variable was set for the product
-		val := reflect.ValueOf(mctx.Config().productVariables).FieldByName(name)
-		if !val.IsValid() || val.Kind() != reflect.Ptr || val.IsNil() {
+ 		val := reflect.ValueOf(mctx.Config().productVariables).FieldByName(name)
+ 		if !val.IsValid() || val.Kind() != reflect.Ptr || val.IsNil() {
 			continue
 		}
 
@@ -584,6 +597,7 @@
 func createVariablePropertiesType(moduleTypeProps []interface{}, productVariables interface{}) reflect.Type {
 	typ, _ := proptools.FilterPropertyStruct(reflect.TypeOf(productVariables),
 		func(field reflect.StructField, prefix string) (bool, reflect.StructField) {
+
 			// Filter function, returns true if the field should be in the resulting struct
 			if prefix == "" {
 				// Keep the top level Product_variables field
diff --git a/androidmk/androidmk/android.go b/androidmk/androidmk/android.go
index 8860984..68c332f 100644
--- a/androidmk/androidmk/android.go
+++ b/androidmk/androidmk/android.go
@@ -57,6 +57,7 @@
 	"LOCAL_SANITIZE_DIAG":         sanitize("diag."),
 	"LOCAL_STRIP_MODULE":          strip(),
 	"LOCAL_CFLAGS":                cflags,
+	"LOCAL_EXPORT_CFLAGS":         exportCflags,
 	"LOCAL_UNINSTALLABLE_MODULE":  invert("installable"),
 	"LOCAL_PROGUARD_ENABLED":      proguardEnabled,
 	"LOCAL_MODULE_PATH":           prebuiltModulePath,
@@ -706,6 +707,13 @@
 	return includeVariableNow(bpVariable{"cflags", bpparser.ListType}, ctx)
 }
 
+func exportCflags(ctx variableAssignmentContext) error {
+	// The Soong replacement for EXPORT_CFLAGS doesn't need the same extra escaped quotes that were present in Make
+	ctx.mkvalue = ctx.mkvalue.Clone()
+	ctx.mkvalue.ReplaceLiteral(`\"`, `"`)
+	return includeVariableNow(bpVariable{"export_cflags", bpparser.ListType}, ctx)
+}
+
 func proguardEnabled(ctx variableAssignmentContext) error {
 	val, err := makeVariableToBlueprint(ctx.file, ctx.mkvalue, bpparser.ListType)
 	if err != nil {
diff --git a/apex/apex.go b/apex/apex.go
index 7da8e1c..f86a086 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -780,7 +780,8 @@
 }
 
 func RegisterPostDepsMutators(ctx android.RegisterMutatorsContext) {
-	ctx.TopDown("apex_deps", apexDepsMutator)
+	ctx.TopDown("apex_deps", apexDepsMutator).Parallel()
+	ctx.BottomUp("apex_unique", apexUniqueVariationsMutator).Parallel()
 	ctx.BottomUp("apex", apexMutator).Parallel()
 	ctx.BottomUp("apex_flattened", apexFlattenedMutator).Parallel()
 	ctx.BottomUp("apex_uses", apexUsesMutator).Parallel()
@@ -793,36 +794,46 @@
 	if !mctx.Module().Enabled() {
 		return
 	}
-	var apexBundles []android.ApexInfo
-	var directDep bool
-	if a, ok := mctx.Module().(*apexBundle); ok && !a.vndkApex {
-		apexBundles = []android.ApexInfo{{
-			ApexName:      mctx.ModuleName(),
-			MinSdkVersion: a.minSdkVersion(mctx),
-			Updatable:     a.Updatable(),
-		}}
-		directDep = true
-	} else if am, ok := mctx.Module().(android.ApexModule); ok {
-		apexBundles = am.ApexVariations()
-		directDep = false
-	}
-
-	if len(apexBundles) == 0 {
+	a, ok := mctx.Module().(*apexBundle)
+	if !ok || a.vndkApex {
 		return
 	}
-
-	cur := mctx.Module().(android.DepIsInSameApex)
-
-	mctx.VisitDirectDeps(func(child android.Module) {
-		depName := mctx.OtherModuleName(child)
-		if am, ok := child.(android.ApexModule); ok && am.CanHaveApexVariants() &&
-			(cur.DepIsInSameApex(mctx, child) || inAnySdk(child)) {
-			android.UpdateApexDependency(apexBundles, depName, directDep)
-			am.BuildForApexes(apexBundles)
+	apexInfo := android.ApexInfo{
+		ApexVariationName: mctx.ModuleName(),
+		MinSdkVersion:     a.minSdkVersion(mctx),
+		RequiredSdks:      a.RequiredSdks(),
+		Updatable:         a.Updatable(),
+		InApexes:          []string{mctx.ModuleName()},
+	}
+	mctx.WalkDeps(func(child, parent android.Module) bool {
+		am, ok := child.(android.ApexModule)
+		if !ok || !am.CanHaveApexVariants() {
+			return false
 		}
+		if !parent.(android.DepIsInSameApex).DepIsInSameApex(mctx, child) {
+			return false
+		}
+
+		depName := mctx.OtherModuleName(child)
+		// If the parent is apexBundle, this child is directly depended.
+		_, directDep := parent.(*apexBundle)
+		android.UpdateApexDependency(apexInfo, depName, directDep)
+		am.BuildForApex(apexInfo)
+		return true
 	})
 }
 
+func apexUniqueVariationsMutator(mctx android.BottomUpMutatorContext) {
+	if !mctx.Module().Enabled() {
+		return
+	}
+	if am, ok := mctx.Module().(android.ApexModule); ok {
+		// Check if any dependencies use unique apex variations.  If so, use unique apex variations
+		// for this module.
+		am.UpdateUniqueApexVariationsForDeps(mctx)
+	}
+}
+
 // mark if a module cannot be available to platform. A module cannot be available
 // to platform if 1) it is explicitly marked as not available (i.e. "//apex_available:platform"
 // is absent) or 2) it depends on another module that isn't (or can't be) available to platform
@@ -1845,7 +1856,7 @@
 		}
 
 		// Check for the indirect dependencies if it is considered as part of the APEX
-		if am.ApexName() != "" {
+		if android.InList(ctx.ModuleName(), am.InApexes()) {
 			return do(ctx, parent, am, false /* externalDep */)
 		}
 
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 8803a5f..ebe8cfb 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -199,6 +199,7 @@
 
 	// from android package
 	android.RegisterPackageBuildComponents(ctx)
+	ctx.PreArchMutators(android.RegisterBootJarMutators)
 	ctx.PreArchMutators(android.RegisterVisibilityRuleChecker)
 
 	ctx.RegisterModuleType("apex", BundleFactory)
@@ -211,6 +212,7 @@
 	ctx.RegisterModuleType("apex_set", apexSetFactory)
 
 	ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
+	ctx.PreArchMutators(android.RegisterComponentsMutator)
 	ctx.PostDepsMutators(android.RegisterOverridePostDepsMutators)
 
 	cc.RegisterRequiredBuildComponentsForTest(ctx)
@@ -479,13 +481,13 @@
 	ensureContains(t, apexRule.Output.String(), "myapex.apex.unsigned")
 
 	// Ensure that apex variant is created for the direct dep
-	ensureListContains(t, ctx.ModuleVariantsForTests("mylib"), "android_arm64_armv8-a_shared_myapex")
-	ensureListContains(t, ctx.ModuleVariantsForTests("myjar"), "android_common_myapex")
-	ensureListContains(t, ctx.ModuleVariantsForTests("myjar_dex"), "android_common_myapex")
+	ensureListContains(t, ctx.ModuleVariantsForTests("mylib"), "android_arm64_armv8-a_shared_apex10000")
+	ensureListContains(t, ctx.ModuleVariantsForTests("myjar"), "android_common_apex10000")
+	ensureListContains(t, ctx.ModuleVariantsForTests("myjar_dex"), "android_common_apex10000")
 
 	// Ensure that apex variant is created for the indirect dep
-	ensureListContains(t, ctx.ModuleVariantsForTests("mylib2"), "android_arm64_armv8-a_shared_myapex")
-	ensureListContains(t, ctx.ModuleVariantsForTests("myotherjar"), "android_common_myapex")
+	ensureListContains(t, ctx.ModuleVariantsForTests("mylib2"), "android_arm64_armv8-a_shared_apex10000")
+	ensureListContains(t, ctx.ModuleVariantsForTests("myotherjar"), "android_common_apex10000")
 
 	// Ensure that both direct and indirect deps are copied into apex
 	ensureContains(t, copyCmds, "image.apex/lib64/mylib.so")
@@ -666,10 +668,10 @@
 	ensureContains(t, zipApexRule.Output.String(), "myapex.zipapex.unsigned")
 
 	// Ensure that APEX variant is created for the direct dep
-	ensureListContains(t, ctx.ModuleVariantsForTests("mylib"), "android_arm64_armv8-a_shared_myapex")
+	ensureListContains(t, ctx.ModuleVariantsForTests("mylib"), "android_arm64_armv8-a_shared_apex10000")
 
 	// Ensure that APEX variant is created for the indirect dep
-	ensureListContains(t, ctx.ModuleVariantsForTests("mylib2"), "android_arm64_armv8-a_shared_myapex")
+	ensureListContains(t, ctx.ModuleVariantsForTests("mylib2"), "android_arm64_armv8-a_shared_apex10000")
 
 	// Ensure that both direct and indirect deps are copied into apex
 	ensureContains(t, copyCmds, "image.zipapex/lib64/mylib.so")
@@ -743,7 +745,7 @@
 	// Ensure that direct stubs dep is included
 	ensureContains(t, copyCmds, "image.apex/lib64/mylib3.so")
 
-	mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_myapex").Rule("ld").Args["libFlags"]
+	mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_apex10000").Rule("ld").Args["libFlags"]
 
 	// Ensure that mylib is linking with the latest version of stubs for mylib2
 	ensureContains(t, mylibLdFlags, "mylib2/android_arm64_armv8-a_shared_3/mylib2.so")
@@ -751,9 +753,9 @@
 	ensureNotContains(t, mylibLdFlags, "mylib2/android_arm64_armv8-a_shared/mylib2.so")
 
 	// Ensure that mylib is linking with the non-stub (impl) of mylib3 (because mylib3 is in the same apex)
-	ensureContains(t, mylibLdFlags, "mylib3/android_arm64_armv8-a_shared_myapex/mylib3.so")
+	ensureContains(t, mylibLdFlags, "mylib3/android_arm64_armv8-a_shared_apex10000/mylib3.so")
 	// .. and not linking to the stubs variant of mylib3
-	ensureNotContains(t, mylibLdFlags, "mylib3/android_arm64_armv8-a_shared_12_myapex/mylib3.so")
+	ensureNotContains(t, mylibLdFlags, "mylib3/android_arm64_armv8-a_shared_12/mylib3.so")
 
 	// Ensure that stubs libs are built without -include flags
 	mylib2Cflags := ctx.ModuleForTests("mylib2", "android_arm64_armv8-a_static").Rule("cc").Args["cFlags"]
@@ -833,7 +835,7 @@
 	// Ensure that dependency of stubs is not included
 	ensureNotContains(t, copyCmds, "image.apex/lib64/libbar.so")
 
-	mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_myapex2").Rule("ld").Args["libFlags"]
+	mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_apex10000").Rule("ld").Args["libFlags"]
 
 	// Ensure that mylib is linking with version 10 of libfoo
 	ensureContains(t, mylibLdFlags, "libfoo/android_arm64_armv8-a_shared_10/libfoo.so")
@@ -929,18 +931,21 @@
 	testcases := []struct {
 		name          string
 		minSdkVersion string
+		apexVariant   string
 		shouldLink    string
 		shouldNotLink []string
 	}{
 		{
 			name:          "should link to the latest",
 			minSdkVersion: "current",
+			apexVariant:   "apex10000",
 			shouldLink:    "30",
 			shouldNotLink: []string{"29"},
 		},
 		{
 			name:          "should link to llndk#29",
 			minSdkVersion: "29",
+			apexVariant:   "apex29",
 			shouldLink:    "29",
 			shouldNotLink: []string{"30"},
 		},
@@ -998,13 +1003,13 @@
 			ensureListEmpty(t, names(apexManifestRule.Args["provideNativeLibs"]))
 			ensureListContains(t, names(apexManifestRule.Args["requireNativeLibs"]), "libbar.so")
 
-			mylibLdFlags := ctx.ModuleForTests("mylib", "android_vendor.VER_arm64_armv8-a_shared_myapex").Rule("ld").Args["libFlags"]
+			mylibLdFlags := ctx.ModuleForTests("mylib", "android_vendor.VER_arm64_armv8-a_shared_"+tc.apexVariant).Rule("ld").Args["libFlags"]
 			ensureContains(t, mylibLdFlags, "libbar.llndk/android_vendor.VER_arm64_armv8-a_shared_"+tc.shouldLink+"/libbar.so")
 			for _, ver := range tc.shouldNotLink {
 				ensureNotContains(t, mylibLdFlags, "libbar.llndk/android_vendor.VER_arm64_armv8-a_shared_"+ver+"/libbar.so")
 			}
 
-			mylibCFlags := ctx.ModuleForTests("mylib", "android_vendor.VER_arm64_armv8-a_static_myapex").Rule("cc").Args["cFlags"]
+			mylibCFlags := ctx.ModuleForTests("mylib", "android_vendor.VER_arm64_armv8-a_static_"+tc.apexVariant).Rule("cc").Args["cFlags"]
 			ensureContains(t, mylibCFlags, "__LIBBAR_API__="+tc.shouldLink)
 		})
 	}
@@ -1059,9 +1064,9 @@
 	// Ensure that libc is not included (since it has stubs and not listed in native_shared_libs)
 	ensureNotContains(t, copyCmds, "image.apex/lib64/bionic/libc.so")
 
-	mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_myapex").Rule("ld").Args["libFlags"]
-	mylibCFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_static_myapex").Rule("cc").Args["cFlags"]
-	mylibSharedCFlags := ctx.ModuleForTests("mylib_shared", "android_arm64_armv8-a_shared_myapex").Rule("cc").Args["cFlags"]
+	mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_apex10000").Rule("ld").Args["libFlags"]
+	mylibCFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_static_apex10000").Rule("cc").Args["cFlags"]
+	mylibSharedCFlags := ctx.ModuleForTests("mylib_shared", "android_arm64_armv8-a_shared_apex10000").Rule("cc").Args["cFlags"]
 
 	// For dependency to libc
 	// Ensure that mylib is linking with the latest version of stubs
@@ -1074,7 +1079,7 @@
 
 	// For dependency to libm
 	// Ensure that mylib is linking with the non-stub (impl) variant
-	ensureContains(t, mylibLdFlags, "libm/android_arm64_armv8-a_shared_myapex/libm.so")
+	ensureContains(t, mylibLdFlags, "libm/android_arm64_armv8-a_shared_apex10000/libm.so")
 	// ... and not linking to the stub variant
 	ensureNotContains(t, mylibLdFlags, "libm/android_arm64_armv8-a_shared_29/libm.so")
 	// ... and is not compiling with the stub
@@ -1088,7 +1093,7 @@
 	ensureNotContains(t, mylibLdFlags, "libdl/android_arm64_armv8-a_shared_28/libdl.so")
 	ensureNotContains(t, mylibLdFlags, "libdl/android_arm64_armv8-a_shared_29/libdl.so")
 	// ... and not linking to the non-stub (impl) variant
-	ensureNotContains(t, mylibLdFlags, "libdl/android_arm64_armv8-a_shared_myapex/libdl.so")
+	ensureNotContains(t, mylibLdFlags, "libdl/android_arm64_armv8-a_shared_apex10000/libdl.so")
 	// ... Cflags from stub is correctly exported to mylib
 	ensureContains(t, mylibCFlags, "__LIBDL_API__=27")
 	ensureContains(t, mylibSharedCFlags, "__LIBDL_API__=27")
@@ -1174,13 +1179,13 @@
 	// platform liba is linked to non-stub version
 	expectLink("liba", "shared", "libz", "shared")
 	// liba in myapex is linked to #1
-	expectLink("liba", "shared_myapex", "libz", "shared_1")
-	expectNoLink("liba", "shared_myapex", "libz", "shared_3")
-	expectNoLink("liba", "shared_myapex", "libz", "shared")
+	expectLink("liba", "shared_apex2", "libz", "shared_1")
+	expectNoLink("liba", "shared_apex2", "libz", "shared_3")
+	expectNoLink("liba", "shared_apex2", "libz", "shared")
 	// liba in otherapex is linked to #3
-	expectLink("liba", "shared_otherapex", "libz", "shared_3")
-	expectNoLink("liba", "shared_otherapex", "libz", "shared_1")
-	expectNoLink("liba", "shared_otherapex", "libz", "shared")
+	expectLink("liba", "shared_apex3", "libz", "shared_3")
+	expectNoLink("liba", "shared_apex3", "libz", "shared_1")
+	expectNoLink("liba", "shared_apex3", "libz", "shared")
 }
 
 func TestApexMinSdkVersion_SupportsCodeNames(t *testing.T) {
@@ -1232,9 +1237,9 @@
 	// to distinguish them from finalized and future_api(10000)
 	// In this test, "R" is assumed not finalized yet( listed in Platform_version_active_codenames) and translated into 9000
 	// (refer android/api_levels.go)
-	expectLink("libx", "shared_myapex", "libz", "shared_9000")
-	expectNoLink("libx", "shared_myapex", "libz", "shared_29")
-	expectNoLink("libx", "shared_myapex", "libz", "shared")
+	expectLink("libx", "shared_apex9000", "libz", "shared_9000")
+	expectNoLink("libx", "shared_apex9000", "libz", "shared_29")
+	expectNoLink("libx", "shared_apex9000", "libz", "shared")
 }
 
 func TestApexMinSdkVersionDefaultsToLatest(t *testing.T) {
@@ -1277,9 +1282,9 @@
 		ldArgs := ctx.ModuleForTests(from, "android_arm64_armv8-a_"+from_variant).Rule("ld").Args["libFlags"]
 		ensureNotContains(t, ldArgs, "android_arm64_armv8-a_"+to_variant+"/"+to+".so")
 	}
-	expectLink("libx", "shared_myapex", "libz", "shared_2")
-	expectNoLink("libx", "shared_myapex", "libz", "shared_1")
-	expectNoLink("libx", "shared_myapex", "libz", "shared")
+	expectLink("libx", "shared_apex10000", "libz", "shared_2")
+	expectNoLink("libx", "shared_apex10000", "libz", "shared_1")
+	expectNoLink("libx", "shared_apex10000", "libz", "shared")
 }
 
 func TestPlatformUsesLatestStubsFromApexes(t *testing.T) {
@@ -1362,7 +1367,7 @@
 		libFlags := ld.Args["libFlags"]
 		ensureContains(t, libFlags, "android_arm64_armv8-a_"+to_variant+"/"+to+".so")
 	}
-	expectLink("libx", "shared_hwasan_myapex", "libbar", "shared_30")
+	expectLink("libx", "shared_hwasan_apex29", "libbar", "shared_30")
 }
 
 func TestQTargetApexUsesStaticUnwinder(t *testing.T) {
@@ -1387,7 +1392,7 @@
 	`)
 
 	// ensure apex variant of c++ is linked with static unwinder
-	cm := ctx.ModuleForTests("libc++", "android_arm64_armv8-a_shared_myapex").Module().(*cc.Module)
+	cm := ctx.ModuleForTests("libc++", "android_arm64_armv8-a_shared_apex29").Module().(*cc.Module)
 	ensureListContains(t, cm.Properties.AndroidMkStaticLibs, "libgcc_stripped")
 	// note that platform variant is not.
 	cm = ctx.ModuleForTests("libc++", "android_arm64_armv8-a_shared").Module().(*cc.Module)
@@ -1666,12 +1671,12 @@
 	inputsString := strings.Join(inputsList, " ")
 
 	// ensure that the apex includes vendor variants of the direct and indirect deps
-	ensureContains(t, inputsString, "android_vendor.VER_arm64_armv8-a_shared_myapex/mylib.so")
-	ensureContains(t, inputsString, "android_vendor.VER_arm64_armv8-a_shared_myapex/mylib2.so")
+	ensureContains(t, inputsString, "android_vendor.VER_arm64_armv8-a_shared_apex10000/mylib.so")
+	ensureContains(t, inputsString, "android_vendor.VER_arm64_armv8-a_shared_apex10000/mylib2.so")
 
 	// ensure that the apex does not include core variants
-	ensureNotContains(t, inputsString, "android_arm64_armv8-a_shared_myapex/mylib.so")
-	ensureNotContains(t, inputsString, "android_arm64_armv8-a_shared_myapex/mylib2.so")
+	ensureNotContains(t, inputsString, "android_arm64_armv8-a_shared_apex10000/mylib.so")
+	ensureNotContains(t, inputsString, "android_arm64_armv8-a_shared_apex10000/mylib2.so")
 }
 
 func TestUseVendorRestriction(t *testing.T) {
@@ -1999,7 +2004,20 @@
 				"myapex",
 				"otherapex",
 			],
+			static_libs: ["mylib3"],
+			recovery_available: true,
+		}
+		cc_library {
+			name: "mylib3",
+			srcs: ["mylib.cpp"],
+			system_shared_libs: [],
+			stl: "none",
+			apex_available: [
+				"myapex",
+				"otherapex",
+			],
 			use_apex_name_macro: true,
+			recovery_available: true,
 		}
 	`)
 
@@ -2009,19 +2027,43 @@
 	ensureNotContains(t, mylibCFlags, "-D__ANDROID_SDK_VERSION__")
 
 	// APEX variant has __ANDROID_APEX__ and __ANDROID_APEX_SDK__ defined
-	mylibCFlags = ctx.ModuleForTests("mylib", "android_arm64_armv8-a_static_myapex").Rule("cc").Args["cFlags"]
+	mylibCFlags = ctx.ModuleForTests("mylib", "android_arm64_armv8-a_static_apex10000").Rule("cc").Args["cFlags"]
 	ensureContains(t, mylibCFlags, "-D__ANDROID_APEX__")
 	ensureContains(t, mylibCFlags, "-D__ANDROID_SDK_VERSION__=10000")
 	ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX_MYAPEX__")
 
 	// APEX variant has __ANDROID_APEX__ and __ANDROID_APEX_SDK__ defined
-	mylibCFlags = ctx.ModuleForTests("mylib", "android_arm64_armv8-a_static_otherapex").Rule("cc").Args["cFlags"]
+	mylibCFlags = ctx.ModuleForTests("mylib", "android_arm64_armv8-a_static_apex29").Rule("cc").Args["cFlags"]
 	ensureContains(t, mylibCFlags, "-D__ANDROID_APEX__")
 	ensureContains(t, mylibCFlags, "-D__ANDROID_SDK_VERSION__=29")
 	ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX_OTHERAPEX__")
 
-	// When cc_library sets use_apex_name_macro: true
-	// apex variants define additional macro to distinguish which apex variant it is built for
+	// When a cc_library sets use_apex_name_macro: true each apex gets a unique variant and
+	// each variant defines additional macros to distinguish which apex variant it is built for
+
+	// non-APEX variant does not have __ANDROID_APEX__ defined
+	mylibCFlags = ctx.ModuleForTests("mylib3", "android_arm64_armv8-a_static").Rule("cc").Args["cFlags"]
+	ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX__")
+
+	// APEX variant has __ANDROID_APEX__ defined
+	mylibCFlags = ctx.ModuleForTests("mylib3", "android_arm64_armv8-a_static_myapex").Rule("cc").Args["cFlags"]
+	ensureContains(t, mylibCFlags, "-D__ANDROID_APEX__")
+	ensureContains(t, mylibCFlags, "-D__ANDROID_APEX_MYAPEX__")
+	ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX_OTHERAPEX__")
+
+	// APEX variant has __ANDROID_APEX__ defined
+	mylibCFlags = ctx.ModuleForTests("mylib3", "android_arm64_armv8-a_static_otherapex").Rule("cc").Args["cFlags"]
+	ensureContains(t, mylibCFlags, "-D__ANDROID_APEX__")
+	ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX_MYAPEX__")
+	ensureContains(t, mylibCFlags, "-D__ANDROID_APEX_OTHERAPEX__")
+
+	// recovery variant does not set __ANDROID_SDK_VERSION__
+	mylibCFlags = ctx.ModuleForTests("mylib3", "android_recovery_arm64_armv8-a_static").Rule("cc").Args["cFlags"]
+	ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX__")
+	ensureNotContains(t, mylibCFlags, "-D__ANDROID_SDK_VERSION__")
+
+	// When a dependency of a cc_library sets use_apex_name_macro: true each apex gets a unique
+	// variant.
 
 	// non-APEX variant does not have __ANDROID_APEX__ defined
 	mylibCFlags = ctx.ModuleForTests("mylib2", "android_arm64_armv8-a_static").Rule("cc").Args["cFlags"]
@@ -2030,17 +2072,17 @@
 	// APEX variant has __ANDROID_APEX__ defined
 	mylibCFlags = ctx.ModuleForTests("mylib2", "android_arm64_armv8-a_static_myapex").Rule("cc").Args["cFlags"]
 	ensureContains(t, mylibCFlags, "-D__ANDROID_APEX__")
-	ensureContains(t, mylibCFlags, "-D__ANDROID_APEX_MYAPEX__")
+	ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX_MYAPEX__")
 	ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX_OTHERAPEX__")
 
 	// APEX variant has __ANDROID_APEX__ defined
 	mylibCFlags = ctx.ModuleForTests("mylib2", "android_arm64_armv8-a_static_otherapex").Rule("cc").Args["cFlags"]
 	ensureContains(t, mylibCFlags, "-D__ANDROID_APEX__")
 	ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX_MYAPEX__")
-	ensureContains(t, mylibCFlags, "-D__ANDROID_APEX_OTHERAPEX__")
+	ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX_OTHERAPEX__")
 
 	// recovery variant does not set __ANDROID_SDK_VERSION__
-	mylibCFlags = ctx.ModuleForTests("mylib", "android_recovery_arm64_armv8-a_static").Rule("cc").Args["cFlags"]
+	mylibCFlags = ctx.ModuleForTests("mylib2", "android_recovery_arm64_armv8-a_static").Rule("cc").Args["cFlags"]
 	ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX__")
 	ensureNotContains(t, mylibCFlags, "-D__ANDROID_SDK_VERSION__")
 }
@@ -2793,7 +2835,7 @@
 	ensureContains(t, apexRule.Output.String(), "myapex.apex.unsigned")
 
 	// Ensure that apex variant is created for the direct dep
-	ensureListContains(t, ctx.ModuleVariantsForTests("mylib_common"), "android_arm64_armv8-a_shared_myapex")
+	ensureListContains(t, ctx.ModuleVariantsForTests("mylib_common"), "android_arm64_armv8-a_shared_apex10000")
 
 	// Ensure that both direct and indirect deps are copied into apex
 	ensureContains(t, copyCmds, "image.apex/lib64/mylib_common.so")
@@ -2849,7 +2891,7 @@
 	ensureContains(t, apexRule.Output.String(), "myapex.apex.unsigned")
 
 	// Ensure that apex variant is created for the direct dep
-	ensureListContains(t, ctx.ModuleVariantsForTests("mylib_common_test"), "android_arm64_armv8-a_shared_myapex")
+	ensureListContains(t, ctx.ModuleVariantsForTests("mylib_common_test"), "android_arm64_armv8-a_shared_apex10000")
 
 	// Ensure that both direct and indirect deps are copied into apex
 	ensureContains(t, copyCmds, "image.apex/lib64/mylib_common_test.so")
@@ -2933,9 +2975,9 @@
 	ensureContains(t, apexRule.Output.String(), "myapex.apex.unsigned")
 
 	// Ensure that apex variant is created for the direct dep
-	ensureListContains(t, ctx.ModuleVariantsForTests("mylib"), "android_arm64_armv8-a_shared_myapex")
-	ensureListContains(t, ctx.ModuleVariantsForTests("mylib_common"), "android_arm64_armv8-a_shared_myapex")
-	ensureListNotContains(t, ctx.ModuleVariantsForTests("mylib2"), "android_arm64_armv8-a_shared_myapex")
+	ensureListContains(t, ctx.ModuleVariantsForTests("mylib"), "android_arm64_armv8-a_shared_apex10000")
+	ensureListContains(t, ctx.ModuleVariantsForTests("mylib_common"), "android_arm64_armv8-a_shared_apex10000")
+	ensureListNotContains(t, ctx.ModuleVariantsForTests("mylib2"), "android_arm64_armv8-a_shared_apex10000")
 
 	// Ensure that both direct and indirect deps are copied into apex
 	ensureContains(t, copyCmds, "image.apex/lib64/mylib.so")
@@ -3366,8 +3408,8 @@
 	apexRule2 := module2.Rule("apexRule")
 	copyCmds2 := apexRule2.Args["copy_commands"]
 
-	ensureListContains(t, ctx.ModuleVariantsForTests("mylib"), "android_arm64_armv8-a_shared_myapex")
-	ensureListContains(t, ctx.ModuleVariantsForTests("libcommon"), "android_arm64_armv8-a_shared_commonapex")
+	ensureListContains(t, ctx.ModuleVariantsForTests("mylib"), "android_arm64_armv8-a_shared_apex10000")
+	ensureListContains(t, ctx.ModuleVariantsForTests("libcommon"), "android_arm64_armv8-a_shared_apex10000")
 	ensureContains(t, copyCmds1, "image.apex/lib64/mylib.so")
 	ensureContains(t, copyCmds2, "image.apex/lib64/libcommon.so")
 	ensureNotContains(t, copyCmds1, "image.apex/lib64/libcommon.so")
@@ -3547,14 +3589,14 @@
 	ensureContains(t, copyCmds, "image.apex/app/AppFoo/AppFoo.apk")
 	ensureContains(t, copyCmds, "image.apex/priv-app/AppFooPriv/AppFooPriv.apk")
 
-	appZipRule := ctx.ModuleForTests("AppFoo", "android_common_myapex").Description("zip jni libs")
+	appZipRule := ctx.ModuleForTests("AppFoo", "android_common_apex10000").Description("zip jni libs")
 	// JNI libraries are uncompressed
 	if args := appZipRule.Args["jarArgs"]; !strings.Contains(args, "-L 0") {
 		t.Errorf("jni libs are not uncompressed for AppFoo")
 	}
 	// JNI libraries including transitive deps are
 	for _, jni := range []string{"libjni", "libfoo"} {
-		jniOutput := ctx.ModuleForTests(jni, "android_arm64_armv8-a_sdk_shared_myapex").Module().(*cc.Module).OutputFile()
+		jniOutput := ctx.ModuleForTests(jni, "android_arm64_armv8-a_sdk_shared_apex10000").Module().(*cc.Module).OutputFile()
 		// ... embedded inside APK (jnilibs.zip)
 		ensureListContains(t, appZipRule.Implicits.Strings(), jniOutput.String())
 		// ... and not directly inside the APEX
@@ -4064,7 +4106,7 @@
 	// the dependency names directly here but for some reason the names are blank in
 	// this test.
 	for _, lib := range []string{"libc++", "mylib"} {
-		apexImplicits := ctx.ModuleForTests(lib, "android_arm64_armv8-a_shared_myapex").Rule("ld").Implicits
+		apexImplicits := ctx.ModuleForTests(lib, "android_arm64_armv8-a_shared_apex29").Rule("ld").Implicits
 		nonApexImplicits := ctx.ModuleForTests(lib, "android_arm64_armv8-a_shared").Rule("ld").Implicits
 		if len(apexImplicits) != len(nonApexImplicits)+1 {
 			t.Errorf("%q missing unwinder dep", lib)
@@ -4663,6 +4705,7 @@
 	ctx.RegisterModuleType("apex", BundleFactory)
 	ctx.RegisterModuleType("apex_key", ApexKeyFactory)
 	ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
+	ctx.PreArchMutators(android.RegisterBootJarMutators)
 	ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
 	cc.RegisterRequiredBuildComponentsForTest(ctx)
 	java.RegisterJavaBuildComponents(ctx)
@@ -4794,28 +4837,28 @@
 	testNoUpdatableJarsInBootImage(t, "", bp, transform)
 
 	// updatable jar from ART apex in the framework boot image => error
-	error = "module 'some-art-lib' from updatable apex 'com.android.art.something' is not allowed in the framework boot image"
+	error = `module "some-art-lib" from updatable apexes \["com.android.art.something"\] is not allowed in the framework boot image`
 	transform = func(config *dexpreopt.GlobalConfig) {
 		config.BootJars = []string{"some-art-lib"}
 	}
 	testNoUpdatableJarsInBootImage(t, error, bp, transform)
 
 	// updatable jar from some other apex in the ART boot image => error
-	error = "module 'some-updatable-apex-lib' from updatable apex 'some-updatable-apex' is not allowed in the ART boot image"
+	error = `module "some-updatable-apex-lib" from updatable apexes \["some-updatable-apex"\] is not allowed in the ART boot image`
 	transform = func(config *dexpreopt.GlobalConfig) {
 		config.ArtApexJars = []string{"some-updatable-apex-lib"}
 	}
 	testNoUpdatableJarsInBootImage(t, error, bp, transform)
 
 	// non-updatable jar from some other apex in the ART boot image => error
-	error = "module 'some-non-updatable-apex-lib' is not allowed in the ART boot image"
+	error = `module "some-non-updatable-apex-lib" is not allowed in the ART boot image`
 	transform = func(config *dexpreopt.GlobalConfig) {
 		config.ArtApexJars = []string{"some-non-updatable-apex-lib"}
 	}
 	testNoUpdatableJarsInBootImage(t, error, bp, transform)
 
 	// updatable jar from some other apex in the framework boot image => error
-	error = "module 'some-updatable-apex-lib' from updatable apex 'some-updatable-apex' is not allowed in the framework boot image"
+	error = `module "some-updatable-apex-lib" from updatable apexes \["some-updatable-apex"\] is not allowed in the framework boot image`
 	transform = func(config *dexpreopt.GlobalConfig) {
 		config.BootJars = []string{"some-updatable-apex-lib"}
 	}
@@ -4842,7 +4885,7 @@
 	testNoUpdatableJarsInBootImage(t, error, bp, transform)
 
 	// platform jar in the ART boot image => error
-	error = "module 'some-platform-lib' is not allowed in the ART boot image"
+	error = `module "some-platform-lib" is not allowed in the ART boot image`
 	transform = func(config *dexpreopt.GlobalConfig) {
 		config.ArtApexJars = []string{"some-platform-lib"}
 	}
@@ -4873,6 +4916,7 @@
 	ctx := android.NewTestArchContext()
 	ctx.RegisterModuleType("apex", BundleFactory)
 	ctx.RegisterModuleType("apex_key", ApexKeyFactory)
+	ctx.PreArchMutators(android.RegisterBootJarMutators)
 	ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
 	cc.RegisterRequiredBuildComponentsForTest(ctx)
 	java.RegisterJavaBuildComponents(ctx)
diff --git a/cc/binary.go b/cc/binary.go
index 251b7f0..6c2fb12 100644
--- a/cc/binary.go
+++ b/cc/binary.go
@@ -467,7 +467,7 @@
 	// The original path becomes a symlink to the corresponding file in the
 	// runtime APEX.
 	translatedArch := ctx.Target().NativeBridge == android.NativeBridgeEnabled
-	if InstallToBootstrap(ctx.baseModuleName(), ctx.Config()) && !translatedArch && ctx.apexName() == "" && !ctx.inRamdisk() && !ctx.inRecovery() {
+	if InstallToBootstrap(ctx.baseModuleName(), ctx.Config()) && !translatedArch && ctx.apexVariationName() == "" && !ctx.inRamdisk() && !ctx.inRecovery() {
 		if ctx.Device() && isBionic(ctx.baseModuleName()) {
 			binary.installSymlinkToRuntimeApex(ctx, file)
 		}
diff --git a/cc/cc.go b/cc/cc.go
index 0f874f1..31b381a 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -335,7 +335,7 @@
 	isNDKStubLibrary() bool
 	useClangLld(actx ModuleContext) bool
 	isForPlatform() bool
-	apexName() string
+	apexVariationName() string
 	apexSdkVersion() int
 	hasStubsVariants() bool
 	isStubs() bool
@@ -1249,8 +1249,8 @@
 	return ctx.mod.IsForPlatform()
 }
 
-func (ctx *moduleContextImpl) apexName() string {
-	return ctx.mod.ApexName()
+func (ctx *moduleContextImpl) apexVariationName() string {
+	return ctx.mod.ApexVariationName()
 }
 
 func (ctx *moduleContextImpl) apexSdkVersion() int {
@@ -2323,7 +2323,7 @@
 			if ccDep.CcLibrary() && !depIsStatic {
 				depIsStubs := ccDep.BuildStubs()
 				depHasStubs := VersionVariantAvailable(c) && ccDep.HasStubsVariants()
-				depInSameApex := android.DirectlyInApex(c.ApexName(), depName)
+				depInSameApexes := android.DirectlyInAllApexes(c.InApexes(), depName)
 				depInPlatform := !android.DirectlyInAnyApex(ctx, depName)
 
 				var useThisDep bool
@@ -2353,9 +2353,9 @@
 						}
 					}
 				} else {
-					// If building for APEX, use stubs only when it is not from
-					// the same APEX
-					useThisDep = (depInSameApex != depIsStubs)
+					// If building for APEX, use stubs when the parent is in any APEX that
+					// the child is not in.
+					useThisDep = (depInSameApexes != depIsStubs)
 				}
 
 				// when to use (unspecified) stubs, check min_sdk_version and choose the right one
@@ -2379,7 +2379,7 @@
 					// by default, use current version of LLNDK
 					versionToUse := ""
 					versions := stubsVersionsFor(ctx.Config())[depName]
-					if c.ApexName() != "" && len(versions) > 0 {
+					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
 						var err error
@@ -2806,6 +2806,16 @@
 	}
 }
 
+func (c *Module) UniqueApexVariations() bool {
+	if u, ok := c.compiler.(interface {
+		uniqueApexVariations() bool
+	}); ok {
+		return u.uniqueApexVariations()
+	} else {
+		return false
+	}
+}
+
 // Return true if the module is ever installable.
 func (c *Module) EverInstallable() bool {
 	return c.installer != nil &&
diff --git a/cc/compiler.go b/cc/compiler.go
index f6c3587..d9567e8 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -323,10 +323,10 @@
 		flags.Global.CommonFlags = append(flags.Global.CommonFlags, "-D__ANDROID_RECOVERY__")
 	}
 
-	if ctx.apexName() != "" {
+	if ctx.apexVariationName() != "" {
 		flags.Global.CommonFlags = append(flags.Global.CommonFlags, "-D__ANDROID_APEX__")
 		if Bool(compiler.Properties.Use_apex_name_macro) {
-			flags.Global.CommonFlags = append(flags.Global.CommonFlags, "-D__ANDROID_APEX_"+makeDefineString(ctx.apexName())+"__")
+			flags.Global.CommonFlags = append(flags.Global.CommonFlags, "-D__ANDROID_APEX_"+makeDefineString(ctx.apexVariationName())+"__")
 		}
 		if ctx.Device() {
 			flags.Global.CommonFlags = append(flags.Global.CommonFlags, "-D__ANDROID_SDK_VERSION__="+strconv.Itoa(ctx.apexSdkVersion()))
@@ -548,6 +548,10 @@
 	return false
 }
 
+func (compiler *baseCompiler) uniqueApexVariations() bool {
+	return Bool(compiler.Properties.Use_apex_name_macro)
+}
+
 // makeDefineString transforms a name of an APEX module into a value to be used as value for C define
 // For example, com.android.foo => COM_ANDROID_FOO
 func makeDefineString(name string) string {
diff --git a/cc/config/x86_darwin_host.go b/cc/config/x86_darwin_host.go
index 8eb79e3..81c907d 100644
--- a/cc/config/x86_darwin_host.go
+++ b/cc/config/x86_darwin_host.go
@@ -66,6 +66,7 @@
 		"10.13",
 		"10.14",
 		"10.15",
+		"11.0",
 	}
 
 	darwinAvailableLibraries = append(
diff --git a/cc/library.go b/cc/library.go
index 3deb173..4191ce9 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -162,6 +162,9 @@
 	// using -isystem for this module and any module that links against this module.
 	Export_system_include_dirs []string `android:"arch_variant"`
 
+	// list of plain cc flags to be used for any module that links against this module.
+	Export_cflags []string  `android:"arch_variant"`
+
 	Target struct {
 		Vendor struct {
 			// list of exported include directories, like
@@ -256,6 +259,10 @@
 	f.systemDirs = append(f.systemDirs, android.PathsForModuleSrc(ctx, f.Properties.Export_system_include_dirs)...)
 }
 
+func (f *flagExporter) exportExtraFlags(ctx ModuleContext) {
+	f.flags = append(f.flags, f.Properties.Export_cflags...)
+}
+
 func (f *flagExporter) exportIncludesAsSystem(ctx ModuleContext) {
 	// all dirs are force exported as system
 	f.systemDirs = append(f.systemDirs, f.exportedIncludes(ctx)...)
@@ -539,6 +546,16 @@
 }
 
 func (library *libraryDecorator) compilerFlags(ctx ModuleContext, flags Flags, deps PathDeps) Flags {
+	additionalIncludeDirs := ctx.DeviceConfig().TargetSpecificHeaderPath()
+	if len(additionalIncludeDirs) > 0 {
+		// devices can have multiple paths in TARGET_SPECIFIC_HEADER_PATH
+		// add -I in front of all of them
+		if (strings.Contains(additionalIncludeDirs, " ")) {
+			additionalIncludeDirs = strings.ReplaceAll(additionalIncludeDirs, " ", " -I")
+		}
+		flags.Local.CommonFlags = append(flags.Local.CommonFlags, "-I" + additionalIncludeDirs)
+	}
+
 	exportIncludeDirs := library.flagExporter.exportedIncludes(ctx)
 	if len(exportIncludeDirs) > 0 {
 		f := includeDirsToFlags(exportIncludeDirs)
@@ -1114,6 +1131,7 @@
 	}
 
 	library.exportIncludes(ctx)
+	library.exportExtraFlags(ctx)
 	library.reexportDirs(deps.ReexportedDirs...)
 	library.reexportSystemDirs(deps.ReexportedSystemDirs...)
 	library.reexportFlags(deps.ReexportedFlags...)
diff --git a/cmd/sbox/sbox.go b/cmd/sbox/sbox.go
index 65a34fd..10ad5d8 100644
--- a/cmd/sbox/sbox.go
+++ b/cmd/sbox/sbox.go
@@ -35,6 +35,7 @@
 	rawCommand    string
 	outputRoot    string
 	keepOutDir    bool
+	copyAllOutput bool
 	depfileOut    string
 	inputHash     string
 )
@@ -48,6 +49,8 @@
 		"root of directory to copy outputs into")
 	flag.BoolVar(&keepOutDir, "keep-out-dir", false,
 		"whether to keep the sandbox directory when done")
+	flag.BoolVar(&copyAllOutput, "copy-all-output", false,
+		"whether to copy all output files")
 
 	flag.StringVar(&depfileOut, "depfile-out", "",
 		"file path of the depfile to generate. This value will replace '__SBOX_DEPFILE__' in the command and will be treated as an output but won't be added to __SBOX_OUT_FILES__")
@@ -120,7 +123,7 @@
 
 	// the contents of the __SBOX_OUT_FILES__ variable
 	outputsVarEntries := flag.Args()
-	if len(outputsVarEntries) == 0 {
+	if !copyAllOutput && len(outputsVarEntries) == 0 {
 		usageViolation("at least one output file must be given")
 	}
 
@@ -226,7 +229,7 @@
 			missingOutputErrors = append(missingOutputErrors, fmt.Sprintf("%s: not a file", filePath))
 		}
 	}
-	if len(missingOutputErrors) > 0 {
+	if !copyAllOutput && len(missingOutputErrors) > 0 {
 		// find all created files for making a more informative error message
 		createdFiles := findAllFilesUnder(tempDir)
 
@@ -258,8 +261,14 @@
 		keepOutDir = true
 		return errors.New(errorMessage)
 	}
+	var filePathList []string
+	if copyAllOutput {
+		filePathList = findAllFilesUnder(tempDir)
+	} else {
+		filePathList = allOutputs
+	}
 	// the created files match the declared files; now move them
-	for _, filePath := range allOutputs {
+	for _, filePath := range filePathList {
 		tempPath := filepath.Join(tempDir, filePath)
 		destPath := filePath
 		if len(outputRoot) != 0 {
diff --git a/java/androidmk.go b/java/androidmk.go
index ae257d7..bddb181 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -541,14 +541,12 @@
 					fmt.Fprintln(w, ddoc.Name()+"-check-last-released-api:",
 						ddoc.checkLastReleasedApiTimestamp.String())
 
-					if ddoc.Name() == "api-stubs-docs" || ddoc.Name() == "system-api-stubs-docs" {
-						fmt.Fprintln(w, ".PHONY: checkapi")
-						fmt.Fprintln(w, "checkapi:",
-							ddoc.checkLastReleasedApiTimestamp.String())
+					fmt.Fprintln(w, ".PHONY: checkapi")
+					fmt.Fprintln(w, "checkapi:",
+						ddoc.checkLastReleasedApiTimestamp.String())
 
-						fmt.Fprintln(w, ".PHONY: droidcore")
-						fmt.Fprintln(w, "droidcore: checkapi")
-					}
+					fmt.Fprintln(w, ".PHONY: droidcore")
+					fmt.Fprintln(w, "droidcore: checkapi")
 				}
 			},
 		},
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index 2f0cbdb..d40d72e 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -266,7 +266,7 @@
 	apex, isApexModule := module.(android.ApexModule)
 	fromUpdatableApex := isApexModule && apex.Updatable()
 	if image.name == artBootImageName {
-		if isApexModule && strings.HasPrefix(apex.ApexName(), "com.android.art.") {
+		if isApexModule && len(apex.InApexes()) > 0 && allHavePrefix(apex.InApexes(), "com.android.art.") {
 			// ok: found the jar in the ART apex
 		} else if isApexModule && apex.IsForPlatform() && Bool(module.(*Library).deviceProperties.Hostdex) {
 			// exception (skip and continue): special "hostdex" platform variant
@@ -276,17 +276,17 @@
 			return -1, nil
 		} else if fromUpdatableApex {
 			// error: this jar is part of an updatable apex other than ART
-			ctx.Errorf("module '%s' from updatable apex '%s' is not allowed in the ART boot image", name, apex.ApexName())
+			ctx.Errorf("module %q from updatable apexes %q is not allowed in the ART boot image", name, apex.InApexes())
 		} else {
 			// error: this jar is part of the platform or a non-updatable apex
-			ctx.Errorf("module '%s' is not allowed in the ART boot image", name)
+			ctx.Errorf("module %q is not allowed in the ART boot image", name)
 		}
 	} else if image.name == frameworkBootImageName {
 		if !fromUpdatableApex {
 			// ok: this jar is part of the platform or a non-updatable apex
 		} else {
 			// error: this jar is part of an updatable apex
-			ctx.Errorf("module '%s' from updatable apex '%s' is not allowed in the framework boot image", name, apex.ApexName())
+			ctx.Errorf("module %q from updatable apexes %q is not allowed in the framework boot image", name, apex.InApexes())
 		}
 	} else {
 		panic("unknown boot image: " + image.name)
@@ -295,12 +295,25 @@
 	return index, jar.DexJar()
 }
 
+func allHavePrefix(list []string, prefix string) bool {
+	for _, s := range list {
+		if !strings.HasPrefix(s, prefix) {
+			return false
+		}
+	}
+	return true
+}
+
 // buildBootImage takes a bootImageConfig, creates rules to build it, and returns the image.
 func buildBootImage(ctx android.SingletonContext, image *bootImageConfig) *bootImageConfig {
 	// Collect dex jar paths for the boot image modules.
 	// This logic is tested in the apex package to avoid import cycle apex <-> java.
 	bootDexJars := make(android.Paths, len(image.modules))
 	ctx.VisitAllModules(func(module android.Module) {
+		if m, ok := module.(interface{ BootJarProvider() bool }); !ok ||
+			!m.BootJarProvider() {
+			return
+		}
 		if i, j := getBootImageJar(ctx, image, module); i != -1 {
 			bootDexJars[i] = j
 		}
diff --git a/java/dexpreopt_bootjars_test.go b/java/dexpreopt_bootjars_test.go
index e7b3c3b..b685e9b 100644
--- a/java/dexpreopt_bootjars_test.go
+++ b/java/dexpreopt_bootjars_test.go
@@ -53,6 +53,8 @@
 
 	ctx := testContext()
 
+	ctx.PreArchMutators(android.RegisterBootJarMutators)
+
 	RegisterDexpreoptBootJarsComponents(ctx)
 
 	run(t, ctx, config)
diff --git a/java/hiddenapi.go b/java/hiddenapi.go
index b5a0217..36ac061 100644
--- a/java/hiddenapi.go
+++ b/java/hiddenapi.go
@@ -77,7 +77,14 @@
 		// to the hidden API for the bootclassloader. If information is gathered for modules
 		// not on the list then that will cause failures in the CtsHiddenApiBlacklist...
 		// tests.
-		if inList(bootJarName, ctx.Config().BootJars()) {
+		isBootJarProvider := false
+		ctx.VisitAllModuleVariants(func(module android.Module) {
+			if m, ok := module.(interface{ BootJarProvider() bool }); ok &&
+				m.BootJarProvider() {
+				isBootJarProvider = true
+			}
+		})
+		if isBootJarProvider && inList(bootJarName, ctx.Config().BootJars()) {
 			// Derive the greylist from classes jar.
 			flagsCSV := android.PathForModuleOut(ctx, "hiddenapi", "flags.csv")
 			metadataCSV := android.PathForModuleOut(ctx, "hiddenapi", "metadata.csv")
diff --git a/java/java.go b/java/java.go
index 69826ee..838e2e7 100644
--- a/java/java.go
+++ b/java/java.go
@@ -1664,7 +1664,7 @@
 		j.linter.compileSdkVersion = lintSDKVersionString(j.sdkVersion())
 		j.linter.javaLanguageLevel = flags.javaVersion.String()
 		j.linter.kotlinLanguageLevel = "1.3"
-		if j.ApexName() != "" && ctx.Config().UnbundledBuild() {
+		if j.ApexVariationName() != "" && ctx.Config().UnbundledBuild() {
 			j.linter.buildModuleReportZip = true
 		}
 		j.linter.lint(ctx)
diff --git a/java/java_test.go b/java/java_test.go
index 8797119..419ab69 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -25,6 +25,7 @@
 	"strings"
 	"testing"
 
+	"github.com/google/blueprint"
 	"github.com/google/blueprint/proptools"
 
 	"android/soong/android"
@@ -85,6 +86,7 @@
 	RegisterStubsBuildComponents(ctx)
 	RegisterSdkLibraryBuildComponents(ctx)
 	ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
+	ctx.PreArchMutators(android.RegisterComponentsMutator)
 
 	RegisterPrebuiltApisBuildComponents(ctx)
 
@@ -171,6 +173,20 @@
 	}
 }
 
+func checkModuleDependencies(t *testing.T, ctx *android.TestContext, name, variant string, expected []string) {
+	t.Helper()
+	module := ctx.ModuleForTests(name, variant).Module()
+	deps := []string{}
+	ctx.VisitDirectDeps(module, func(m blueprint.Module) {
+		deps = append(deps, m.Name())
+	})
+	sort.Strings(deps)
+
+	if actual := deps; !reflect.DeepEqual(expected, actual) {
+		t.Errorf("expected %#q, found %#q", expected, actual)
+	}
+}
+
 func TestJavaLinkType(t *testing.T) {
 	testJava(t, `
 		java_library {
@@ -596,6 +612,89 @@
 			t.Errorf("foo classpath %v does not contain %q", javac.Args["classpath"], sdklibStubsJar.String())
 		}
 	}
+
+	checkModuleDependencies(t, ctx, "sdklib", "android_common", []string{
+		`prebuilt_sdklib.stubs`,
+		`prebuilt_sdklib.stubs.source.test`,
+		`prebuilt_sdklib.stubs.system`,
+		`prebuilt_sdklib.stubs.test`,
+	})
+}
+
+func TestJavaSdkLibraryImport_WithSource(t *testing.T) {
+	ctx, _ := testJava(t, `
+		java_sdk_library {
+			name: "sdklib",
+			srcs: ["a.java"],
+			sdk_version: "none",
+			system_modules: "none",
+			public: {
+				enabled: true,
+			},
+		}
+
+		java_sdk_library_import {
+			name: "sdklib",
+			public: {
+				jars: ["a.jar"],
+			},
+		}
+		`)
+
+	checkModuleDependencies(t, ctx, "sdklib", "android_common", []string{
+		`dex2oatd`,
+		`prebuilt_sdklib`,
+		`sdklib.impl`,
+		`sdklib.stubs`,
+		`sdklib.stubs.source`,
+		`sdklib.xml`,
+	})
+
+	checkModuleDependencies(t, ctx, "prebuilt_sdklib", "android_common", []string{
+		`prebuilt_sdklib.stubs`,
+		`sdklib.impl`,
+		// This should be prebuilt_sdklib.stubs but is set to sdklib.stubs because the
+		// dependency is added after prebuilts may have been renamed and so has to use
+		// the renamed name.
+		`sdklib.xml`,
+	})
+}
+
+func TestJavaSdkLibraryImport_Preferred(t *testing.T) {
+	ctx, _ := testJava(t, `
+		java_sdk_library {
+			name: "sdklib",
+			srcs: ["a.java"],
+			sdk_version: "none",
+			system_modules: "none",
+			public: {
+				enabled: true,
+			},
+		}
+
+		java_sdk_library_import {
+			name: "sdklib",
+			prefer: true,
+			public: {
+				jars: ["a.jar"],
+			},
+		}
+		`)
+
+	checkModuleDependencies(t, ctx, "sdklib", "android_common", []string{
+		`dex2oatd`,
+		`prebuilt_sdklib`,
+		`sdklib.impl`,
+		`sdklib.stubs`,
+		`sdklib.stubs.source`,
+		`sdklib.xml`,
+	})
+
+	checkModuleDependencies(t, ctx, "prebuilt_sdklib", "android_common", []string{
+		`prebuilt_sdklib.stubs`,
+		`sdklib.impl`,
+		`sdklib.xml`,
+	})
 }
 
 func TestDefaults(t *testing.T) {
@@ -1401,6 +1500,28 @@
 		`)
 }
 
+func TestJavaSdkLibrary_Deps(t *testing.T) {
+	ctx, _ := testJava(t, `
+		java_sdk_library {
+			name: "sdklib",
+			srcs: ["a.java"],
+			sdk_version: "none",
+			system_modules: "none",
+			public: {
+				enabled: true,
+			},
+		}
+		`)
+
+	checkModuleDependencies(t, ctx, "sdklib", "android_common", []string{
+		`dex2oatd`,
+		`sdklib.impl`,
+		`sdklib.stubs`,
+		`sdklib.stubs.source`,
+		`sdklib.xml`,
+	})
+}
+
 func TestJavaSdkLibraryImport_AccessOutputFiles(t *testing.T) {
 	testJava(t, `
 		java_sdk_library_import {
diff --git a/java/sdk_library.go b/java/sdk_library.go
index f2a509a..aa717f9 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -70,6 +70,12 @@
 	}
 }
 
+var _ android.ReplaceSourceWithPrebuilt = (*scopeDependencyTag)(nil)
+
+func (tag scopeDependencyTag) ReplaceSourceWithPrebuilt() bool {
+	return false
+}
+
 // Provides information about an api scope, e.g. public, system, test.
 type apiScope struct {
 	// The name of the api scope, e.g. public, system, test
@@ -976,7 +982,8 @@
 
 var implLibraryTag = sdkLibraryComponentTag{name: "impl-library"}
 
-func (module *SdkLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
+// Add the dependencies on the child modules in the component deps mutator.
+func (module *SdkLibrary) ComponentDepsMutator(ctx android.BottomUpMutatorContext) {
 	for _, apiScope := range module.getGeneratedApiScopes(ctx) {
 		// Add dependencies to the stubs library
 		ctx.AddVariationDependencies(nil, apiScope.stubsTag, module.stubsLibraryModuleName(apiScope))
@@ -1001,7 +1008,12 @@
 			// Add dependency to the rule for generating the xml permissions file
 			ctx.AddDependency(module, xmlPermissionsFileTag, module.xmlPermissionsModuleName())
 		}
+	}
+}
 
+// Add other dependencies as normal.
+func (module *SdkLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
+	if module.requiresRuntimeImplementationLibrary() {
 		// Only add the deps for the library if it is actually going to be built.
 		module.Library.deps(ctx)
 	}
@@ -1393,22 +1405,22 @@
 	return android.Paths{jarPath.Path()}
 }
 
-// Get the apex name for module, "" if it is for platform.
-func getApexNameForModule(module android.Module) string {
+// Get the apex names for module, nil if it is for platform.
+func getApexNamesForModule(module android.Module) []string {
 	if apex, ok := module.(android.ApexModule); ok {
-		return apex.ApexName()
+		return apex.InApexes()
 	}
 
-	return ""
+	return nil
 }
 
-// Check to see if the other module is within the same named APEX as this module.
+// Check to see if the other module is within the same set of named APEXes as this module.
 //
 // If either this or the other module are on the platform then this will return
 // false.
-func withinSameApexAs(module android.ApexModule, other android.Module) bool {
-	name := module.ApexName()
-	return name != "" && getApexNameForModule(other) == name
+func withinSameApexesAs(module android.ApexModule, other android.Module) bool {
+	names := module.InApexes()
+	return len(names) > 0 && reflect.DeepEqual(names, getApexNamesForModule(other))
 }
 
 func (module *SdkLibrary) sdkJars(ctx android.BaseModuleContext, sdkVersion sdkSpec, headerJars bool) android.Paths {
@@ -1427,7 +1439,7 @@
 		// Only allow access to the implementation library in the following condition:
 		// * No sdk_version specified on the referencing module.
 		// * The referencing module is in the same apex as this.
-		if sdkVersion.kind == sdkPrivate || withinSameApexAs(module, ctx.Module()) {
+		if sdkVersion.kind == sdkPrivate || withinSameApexesAs(module, ctx.Module()) {
 			if headerJars {
 				return module.HeaderJars()
 			} else {
@@ -1882,20 +1894,26 @@
 	props.Prefer = proptools.BoolPtr(module.prebuilt.Prefer())
 }
 
-func (module *SdkLibraryImport) DepsMutator(ctx android.BottomUpMutatorContext) {
+// Add the dependencies on the child module in the component deps mutator so that it
+// creates references to the prebuilt and not the source modules.
+func (module *SdkLibraryImport) ComponentDepsMutator(ctx android.BottomUpMutatorContext) {
 	for apiScope, scopeProperties := range module.scopeProperties {
 		if len(scopeProperties.Jars) == 0 {
 			continue
 		}
 
 		// Add dependencies to the prebuilt stubs library
-		ctx.AddVariationDependencies(nil, apiScope.stubsTag, module.stubsLibraryModuleName(apiScope))
+		ctx.AddVariationDependencies(nil, apiScope.stubsTag, "prebuilt_"+module.stubsLibraryModuleName(apiScope))
 
 		if len(scopeProperties.Stub_srcs) > 0 {
 			// Add dependencies to the prebuilt stubs source library
-			ctx.AddVariationDependencies(nil, apiScope.stubsSourceTag, module.stubsSourceModuleName(apiScope))
+			ctx.AddVariationDependencies(nil, apiScope.stubsSourceTag, "prebuilt_"+module.stubsSourceModuleName(apiScope))
 		}
 	}
+}
+
+// Add other dependencies as normal.
+func (module *SdkLibraryImport) DepsMutator(ctx android.BottomUpMutatorContext) {
 
 	implName := module.implLibraryModuleName()
 	if ctx.OtherModuleExists(implName) {
@@ -1969,7 +1987,7 @@
 	// For consistency with SdkLibrary make the implementation jar available to libraries that
 	// are within the same APEX.
 	implLibraryModule := module.implLibraryModule
-	if implLibraryModule != nil && withinSameApexAs(module, ctx.Module()) {
+	if implLibraryModule != nil && withinSameApexesAs(module, ctx.Module()) {
 		if headerJars {
 			return implLibraryModule.HeaderJars()
 		} else {
@@ -2076,6 +2094,12 @@
 	return module
 }
 
+func (module *sdkLibraryXml) UniqueApexVariations() bool {
+	// sdkLibraryXml needs a unique variation per APEX because the generated XML file contains the path to the
+	// mounted APEX, which contains the name of the APEX.
+	return true
+}
+
 // from android.PrebuiltEtcModule
 func (module *sdkLibraryXml) SubDir() string {
 	return "permissions"
@@ -2098,8 +2122,8 @@
 // File path to the runtime implementation library
 func (module *sdkLibraryXml) implPath() string {
 	implName := proptools.String(module.properties.Lib_name)
-	if apexName := module.ApexName(); apexName != "" {
-		// TODO(b/146468504): ApexName() is only a soong module name, not apex name.
+	if apexName := module.ApexVariationName(); apexName != "" {
+		// TODO(b/146468504): ApexVariationName() is only a soong module name, not apex name.
 		// In most cases, this works fine. But when apex_name is set or override_apex is used
 		// this can be wrong.
 		return fmt.Sprintf("/apex/%s/javalib/%s.jar", apexName, implName)
diff --git a/sdk/cc_sdk_test.go b/sdk/cc_sdk_test.go
index dded153..b8ce96c 100644
--- a/sdk/cc_sdk_test.go
+++ b/sdk/cc_sdk_test.go
@@ -154,11 +154,11 @@
 		}
 	`)
 
-	sdkMemberV1 := result.ModuleForTests("sdkmember_mysdk_1", "android_arm64_armv8-a_shared_myapex").Rule("toc").Output
-	sdkMemberV2 := result.ModuleForTests("sdkmember_mysdk_2", "android_arm64_armv8-a_shared_myapex2").Rule("toc").Output
+	sdkMemberV1 := result.ModuleForTests("sdkmember_mysdk_1", "android_arm64_armv8-a_shared_apex10000_mysdk_1").Rule("toc").Output
+	sdkMemberV2 := result.ModuleForTests("sdkmember_mysdk_2", "android_arm64_armv8-a_shared_apex10000_mysdk_2").Rule("toc").Output
 
-	cpplibForMyApex := result.ModuleForTests("mycpplib", "android_arm64_armv8-a_shared_myapex")
-	cpplibForMyApex2 := result.ModuleForTests("mycpplib", "android_arm64_armv8-a_shared_myapex2")
+	cpplibForMyApex := result.ModuleForTests("mycpplib", "android_arm64_armv8-a_shared_apex10000_mysdk_1")
+	cpplibForMyApex2 := result.ModuleForTests("mycpplib", "android_arm64_armv8-a_shared_apex10000_mysdk_2")
 
 	// Depending on the uses_sdks value, different libs are linked
 	ensureListContains(t, pathsToStrings(cpplibForMyApex.Rule("ld").Implicits), sdkMemberV1.String())
diff --git a/sdk/java_sdk_test.go b/sdk/java_sdk_test.go
index db395c5..9d86e0c 100644
--- a/sdk/java_sdk_test.go
+++ b/sdk/java_sdk_test.go
@@ -152,11 +152,11 @@
 		}
 	`)
 
-	sdkMemberV1 := result.ctx.ModuleForTests("sdkmember_mysdk_1", "android_common_myapex").Rule("combineJar").Output
-	sdkMemberV2 := result.ctx.ModuleForTests("sdkmember_mysdk_2", "android_common_myapex2").Rule("combineJar").Output
+	sdkMemberV1 := result.ctx.ModuleForTests("sdkmember_mysdk_1", "android_common").Rule("combineJar").Output
+	sdkMemberV2 := result.ctx.ModuleForTests("sdkmember_mysdk_2", "android_common").Rule("combineJar").Output
 
-	javalibForMyApex := result.ctx.ModuleForTests("myjavalib", "android_common_myapex")
-	javalibForMyApex2 := result.ctx.ModuleForTests("myjavalib", "android_common_myapex2")
+	javalibForMyApex := result.ctx.ModuleForTests("myjavalib", "android_common_apex10000_mysdk_1")
+	javalibForMyApex2 := result.ctx.ModuleForTests("myjavalib", "android_common_apex10000_mysdk_2")
 
 	// Depending on the uses_sdks value, different libs are linked
 	ensureListContains(t, pathsToStrings(javalibForMyApex.Rule("javac").Implicits), sdkMemberV1.String())
diff --git a/sdk/sdk.go b/sdk/sdk.go
index cb5a605..60727a6 100644
--- a/sdk/sdk.go
+++ b/sdk/sdk.go
@@ -401,13 +401,17 @@
 // Step 4: transitively ripple down the SDK requirements from the root modules like APEX to its
 // descendants
 func sdkDepsMutator(mctx android.TopDownMutatorContext) {
-	if m, ok := mctx.Module().(android.SdkAware); ok {
+	if parent, ok := mctx.Module().(interface {
+		android.DepIsInSameApex
+		android.RequiredSdks
+	}); ok {
 		// Module types for Mainline modules (e.g. APEX) are expected to implement RequiredSdks()
 		// by reading its own properties like `uses_sdks`.
-		requiredSdks := m.RequiredSdks()
+		requiredSdks := parent.RequiredSdks()
 		if len(requiredSdks) > 0 {
 			mctx.VisitDirectDeps(func(m android.Module) {
-				if dep, ok := m.(android.SdkAware); ok {
+				// Only propagate required sdks from the apex onto its contents.
+				if dep, ok := m.(android.SdkAware); ok && parent.DepIsInSameApex(mctx, dep) {
 					dep.BuildWithSdks(requiredSdks)
 				}
 			})
@@ -418,15 +422,28 @@
 // Step 5: if libfoo.mysdk.11 is in the context where version 11 of mysdk is requested, the
 // versioned module is used instead of the un-versioned (in-development) module libfoo
 func sdkDepsReplaceMutator(mctx android.BottomUpMutatorContext) {
-	if m, ok := mctx.Module().(android.SdkAware); ok && m.IsInAnySdk() {
-		if sdk := m.ContainingSdk(); !sdk.Unversioned() {
-			if m.RequiredSdks().Contains(sdk) {
-				// Note that this replacement is done only for the modules that have the same
-				// variations as the current module. Since current module is already mutated for
-				// apex references in other APEXes are not affected by this replacement.
-				memberName := m.MemberName()
-				mctx.ReplaceDependencies(memberName)
-			}
+	if versionedSdkMember, ok := mctx.Module().(android.SdkAware); ok && versionedSdkMember.IsInAnySdk() {
+		if sdk := versionedSdkMember.ContainingSdk(); !sdk.Unversioned() {
+			// Only replace dependencies to <sdkmember> with <sdkmember@required-version>
+			// if the depending module requires it. e.g.
+			//      foo -> sdkmember
+			// will be transformed to:
+			//      foo -> sdkmember@1
+			// if and only if foo is a member of an APEX that requires version 1 of the
+			// sdk containing sdkmember.
+			memberName := versionedSdkMember.MemberName()
+
+			// Replace dependencies on sdkmember with a dependency on the current module which
+			// is a versioned prebuilt of the sdkmember if required.
+			mctx.ReplaceDependenciesIf(memberName, func(from blueprint.Module, tag blueprint.DependencyTag, to blueprint.Module) bool {
+				// from - foo
+				// to - sdkmember
+				replace := false
+				if parent, ok := from.(android.RequiredSdks); ok {
+					replace = parent.RequiredSdks().Contains(sdk)
+				}
+				return replace
+			})
 		}
 	}
 }
diff --git a/sdk/testing.go b/sdk/testing.go
index 4361754..40abdcd 100644
--- a/sdk/testing.go
+++ b/sdk/testing.go
@@ -84,6 +84,7 @@
 	android.RegisterPackageBuildComponents(ctx)
 	ctx.PreArchMutators(android.RegisterVisibilityRuleChecker)
 	ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
+	ctx.PreArchMutators(android.RegisterComponentsMutator)
 	ctx.PreArchMutators(android.RegisterVisibilityRuleGatherer)
 	ctx.PostDepsMutators(android.RegisterVisibilityRuleEnforcer)
 
diff --git a/ui/build/build.go b/ui/build/build.go
index 349a7de..7293bbc 100644
--- a/ui/build/build.go
+++ b/ui/build/build.go
@@ -218,6 +218,10 @@
 		dataClean(ctx, config, what)
 		ctx.Println("Deleted data files.")
 		return
+	} else if inList("deviceclean", config.Arguments()) {
+		deviceClean(ctx, config, what)
+		ctx.Println(config.ProductOut(), "removed.")
+		return
 	}
 
 	if what&BuildSoong != 0 {
diff --git a/ui/build/cleanbuild.go b/ui/build/cleanbuild.go
index 0bcdccb..c477e92 100644
--- a/ui/build/cleanbuild.go
+++ b/ui/build/cleanbuild.go
@@ -103,6 +103,7 @@
 		hostOut("vts-core"),
 		productOut("*.img"),
 		productOut("*.zip"),
+		productOut("*.zip.md5sum"),
 		productOut("android-info.txt"),
 		productOut("apex"),
 		productOut("kernel"),
@@ -131,7 +132,8 @@
 		productOut("installer"),
 		productOut("odm"),
 		productOut("sysloader"),
-		productOut("testcases"))
+		productOut("testcases"),
+		productOut("install"))
 }
 
 // Since products and build variants (unfortunately) shared the same
@@ -273,3 +275,8 @@
 	}
 	cleanEmptyDirs(ctx, filepath.Dir(dir))
 }
+
+// Remove everything relevant for a clean ota package
+func deviceClean(ctx Context, config Config, what int) {
+	removeGlobs(ctx, config.ProductOut())
+}
diff --git a/ui/build/dumpvars.go b/ui/build/dumpvars.go
index bd073e5..3197ec4 100644
--- a/ui/build/dumpvars.go
+++ b/ui/build/dumpvars.go
@@ -137,31 +137,14 @@
 
 // Variables to print out in the top banner
 var BannerVars = []string{
-	"PLATFORM_VERSION_CODENAME",
-	"PLATFORM_VERSION",
+	"BLISS_VERSION",
+	"BLISS_BUILD_VARIANT",
 	"TARGET_PRODUCT",
 	"TARGET_BUILD_VARIANT",
-	"TARGET_BUILD_TYPE",
-	"TARGET_BUILD_APPS",
 	"TARGET_ARCH",
 	"TARGET_ARCH_VARIANT",
 	"TARGET_CPU_VARIANT",
-	"TARGET_2ND_ARCH",
-	"TARGET_2ND_ARCH_VARIANT",
-	"TARGET_2ND_CPU_VARIANT",
-	"HOST_ARCH",
-	"HOST_2ND_ARCH",
-	"HOST_OS",
-	"HOST_OS_EXTRA",
-	"HOST_CROSS_OS",
-	"HOST_CROSS_ARCH",
-	"HOST_CROSS_2ND_ARCH",
-	"HOST_BUILD_TYPE",
 	"BUILD_ID",
-	"OUT_DIR",
-	"AUX_OS_VARIANT_LIST",
-	"TARGET_BUILD_PDK",
-	"PDK_FUSION_PLATFORM_ZIP",
 	"PRODUCT_SOONG_NAMESPACES",
 }
 
diff --git a/ui/build/path.go b/ui/build/path.go
index f515775..a47639c 100644
--- a/ui/build/path.go
+++ b/ui/build/path.go
@@ -15,13 +15,13 @@
 package build
 
 import (
-	"fmt"
+//	"fmt"
 	"io/ioutil"
 	"os"
 	"os/exec"
 	"path/filepath"
 	"runtime"
-	"strings"
+//	"strings"
 
 	"github.com/google/blueprint/microfactory"
 
@@ -126,6 +126,7 @@
 		ctx.Fatalln("Failed to write original path:", err)
 	}
 
+/*
 	entries, err := paths.LogListener(ctx.Context, interposer+"_log")
 	if err != nil {
 		ctx.Fatalln("Failed to listen for path logs:", err)
@@ -164,6 +165,7 @@
 			}
 		}
 	}()
+*/
 
 	ensureEmptyDirectoriesExist(ctx, myPath)
 
diff --git a/ui/build/paths/config.go b/ui/build/paths/config.go
index 5717401..fda88b6 100644
--- a/ui/build/paths/config.go
+++ b/ui/build/paths/config.go
@@ -75,6 +75,7 @@
 
 var Configuration = map[string]PathConfig{
 	"bash":    Allowed,
+	"date":    Allowed,
 	"dd":      Allowed,
 	"diff":    Allowed,
 	"dlv":     Allowed,