Merge "Pass library kind when linking native libraries."
diff --git a/android/apex.go b/android/apex.go
index a4b6956..9195388 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -180,20 +180,20 @@
 func (m *ApexModuleBase) CreateApexVariations(mctx BottomUpMutatorContext) []Module {
 	if len(m.apexVariations) > 0 {
 		m.checkApexAvailableProperty(mctx)
+
 		sort.Strings(m.apexVariations)
 		variations := []string{}
-		availableForPlatform := mctx.Module().(ApexModule).AvailableFor(AvailableToPlatform) || mctx.Host()
-		if availableForPlatform {
-			variations = append(variations, "") // Original variation for platform
-		}
+		variations = append(variations, "") // Original variation for platform
 		variations = append(variations, m.apexVariations...)
 
 		defaultVariation := ""
 		mctx.SetDefaultDependencyVariation(&defaultVariation)
+
 		modules := mctx.CreateVariations(variations...)
 		for i, m := range modules {
-			if availableForPlatform && i == 0 {
-				continue
+			platformVariation := i == 0
+			if platformVariation && !mctx.Host() && !m.(ApexModule).AvailableFor(AvailableToPlatform) {
+				m.SkipInstall()
 			}
 			m.(ApexModule).setApexName(variations[i])
 		}
diff --git a/android/config.go b/android/config.go
index da4f8e2..d0ac4c3 100644
--- a/android/config.go
+++ b/android/config.go
@@ -1028,8 +1028,12 @@
 	return c.config.productVariables.DeviceKernelHeaders
 }
 
+func (c *config) NativeLineCoverage() bool {
+	return Bool(c.productVariables.NativeLineCoverage)
+}
+
 func (c *deviceConfig) NativeCoverageEnabled() bool {
-	return Bool(c.config.productVariables.Native_coverage)
+	return Bool(c.config.productVariables.Native_coverage) || Bool(c.config.productVariables.NativeLineCoverage)
 }
 
 func (c *deviceConfig) ClangCoverageEnabled() bool {
diff --git a/android/defaults.go b/android/defaults.go
index 7597446..fd707a4 100644
--- a/android/defaults.go
+++ b/android/defaults.go
@@ -15,6 +15,8 @@
 package android
 
 import (
+	"reflect"
+
 	"github.com/google/blueprint"
 	"github.com/google/blueprint/proptools"
 )
@@ -30,16 +32,18 @@
 }
 
 type DefaultableModuleBase struct {
-	defaultsProperties    defaultsProperties
-	defaultableProperties []interface{}
+	defaultsProperties            defaultsProperties
+	defaultableProperties         []interface{}
+	defaultableVariableProperties interface{}
 }
 
 func (d *DefaultableModuleBase) defaults() *defaultsProperties {
 	return &d.defaultsProperties
 }
 
-func (d *DefaultableModuleBase) setProperties(props []interface{}) {
+func (d *DefaultableModuleBase) setProperties(props []interface{}, variableProperties interface{}) {
 	d.defaultableProperties = props
+	d.defaultableVariableProperties = variableProperties
 }
 
 // Interface that must be supported by any module to which defaults can be applied.
@@ -48,7 +52,7 @@
 	defaults() *defaultsProperties
 
 	// Set the property structures into which defaults will be added.
-	setProperties([]interface{})
+	setProperties(props []interface{}, variableProperties interface{})
 
 	// Apply defaults from the supplied Defaults to the property structures supplied to
 	// setProperties(...).
@@ -63,7 +67,10 @@
 var _ Defaultable = (*DefaultableModuleBase)(nil)
 
 func InitDefaultableModule(module DefaultableModule) {
-	module.setProperties(module.(Module).GetProperties())
+	if module.(Module).base().module == nil {
+		panic("InitAndroidModule must be called before InitDefaultableModule")
+	}
+	module.setProperties(module.(Module).GetProperties(), module.(Module).base().variableProperties)
 
 	module.AddProperties(module.defaults())
 }
@@ -114,6 +121,8 @@
 	// Get the structures containing the properties for which defaults can be provided.
 	properties() []interface{}
 
+	productVariableProperties() interface{}
+
 	// Return the defaults common properties.
 	common() *commonProperties
 
@@ -134,6 +143,10 @@
 	return d.defaultableProperties
 }
 
+func (d *DefaultsModuleBase) productVariableProperties() interface{} {
+	return d.defaultableVariableProperties
+}
+
 func (d *DefaultsModuleBase) common() *commonProperties {
 	return &d.commonProperties
 }
@@ -151,9 +164,10 @@
 	module.AddProperties(
 		&hostAndDeviceProperties{},
 		commonProperties,
-		&variableProperties{},
 		&ApexProperties{})
 
+	initAndroidModuleBase(module)
+	initProductVariableModule(module)
 	InitArchModule(module)
 	InitDefaultableModule(module)
 
@@ -185,16 +199,57 @@
 
 	for _, defaults := range defaultsList {
 		for _, prop := range defaultable.defaultableProperties {
-			for _, def := range defaults.properties() {
-				if proptools.TypeEqual(prop, def) {
-					err := proptools.PrependProperties(prop, def, nil)
-					if err != nil {
-						if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok {
-							ctx.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error())
-						} else {
-							panic(err)
-						}
-					}
+			if prop == defaultable.defaultableVariableProperties {
+				defaultable.applyDefaultVariableProperties(ctx, defaults, prop)
+			} else {
+				defaultable.applyDefaultProperties(ctx, defaults, prop)
+			}
+		}
+	}
+}
+
+// Product variable properties need special handling, the type of the filtered product variable
+// property struct may not be identical between the defaults module and the defaultable module.
+// Use PrependMatchingProperties to apply whichever properties match.
+func (defaultable *DefaultableModuleBase) applyDefaultVariableProperties(ctx TopDownMutatorContext,
+	defaults Defaults, defaultableProp interface{}) {
+	if defaultableProp == nil {
+		return
+	}
+
+	defaultsProp := defaults.productVariableProperties()
+	if defaultsProp == nil {
+		return
+	}
+
+	dst := []interface{}{
+		defaultableProp,
+		// Put an empty copy of the src properties into dst so that properties in src that are not in dst
+		// don't cause a "failed to find property to extend" error.
+		proptools.CloneEmptyProperties(reflect.ValueOf(defaultsProp)).Interface(),
+	}
+
+	err := proptools.PrependMatchingProperties(dst, defaultsProp, nil)
+	if err != nil {
+		if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok {
+			ctx.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error())
+		} else {
+			panic(err)
+		}
+	}
+}
+
+func (defaultable *DefaultableModuleBase) applyDefaultProperties(ctx TopDownMutatorContext,
+	defaults Defaults, defaultableProp interface{}) {
+
+	for _, def := range defaults.properties() {
+		if proptools.TypeEqual(defaultableProp, def) {
+			err := proptools.PrependProperties(defaultableProp, def, nil)
+			if err != nil {
+				if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok {
+					ctx.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error())
+				} else {
+					panic(err)
 				}
 			}
 		}
diff --git a/android/defaults_test.go b/android/defaults_test.go
index ba607ef..d096b2f 100644
--- a/android/defaults_test.go
+++ b/android/defaults_test.go
@@ -15,6 +15,7 @@
 package android
 
 import (
+	"reflect"
 	"testing"
 
 	"github.com/google/blueprint/proptools"
@@ -40,8 +41,8 @@
 func defaultsTestModuleFactory() Module {
 	module := &defaultsTestModule{}
 	module.AddProperties(&module.properties)
-	InitDefaultableModule(module)
 	InitAndroidModule(module)
+	InitDefaultableModule(module)
 	return module
 }
 
@@ -57,6 +58,49 @@
 	return defaults
 }
 
+func TestDefaults(t *testing.T) {
+	bp := `
+		defaults {
+			name: "transitive",
+			foo: ["transitive"],
+		}
+
+		defaults {
+			name: "defaults",
+			defaults: ["transitive"],
+			foo: ["defaults"],
+		}
+
+		test {
+			name: "foo",
+			defaults: ["defaults"],
+			foo: ["module"],
+		}
+	`
+
+	config := TestConfig(buildDir, nil, bp, nil)
+
+	ctx := NewTestContext()
+
+	ctx.RegisterModuleType("test", defaultsTestModuleFactory)
+	ctx.RegisterModuleType("defaults", defaultsTestDefaultsFactory)
+
+	ctx.PreArchMutators(RegisterDefaultsPreArchMutators)
+
+	ctx.Register(config)
+
+	_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
+	FailIfErrored(t, errs)
+	_, errs = ctx.PrepareBuildActions(config)
+	FailIfErrored(t, errs)
+
+	foo := ctx.ModuleForTests("foo", "").Module().(*defaultsTestModule)
+
+	if g, w := foo.properties.Foo, []string{"transitive", "defaults", "module"}; !reflect.DeepEqual(g, w) {
+		t.Errorf("expected foo %q, got %q", w, g)
+	}
+}
+
 func TestDefaultsAllowMissingDependencies(t *testing.T) {
 	bp := `
 		defaults {
diff --git a/android/module.go b/android/module.go
index 96c2e1e..0a8737b 100644
--- a/android/module.go
+++ b/android/module.go
@@ -537,16 +537,7 @@
 		&base.nameProperties,
 		&base.commonProperties)
 
-	// Allow tests to override the default product variables
-	if base.variableProperties == nil {
-		base.variableProperties = zeroProductVariables
-	}
-
-	// Filter the product variables properties to the ones that exist on this module
-	base.variableProperties = createVariableProperties(m.GetProperties(), base.variableProperties)
-	if base.variableProperties != nil {
-		m.AddProperties(base.variableProperties)
-	}
+	initProductVariableModule(m)
 
 	base.generalProperties = m.GetProperties()
 	base.customizableProperties = m.GetProperties()
diff --git a/android/prebuilt.go b/android/prebuilt.go
index c780cb2..2d16f65 100644
--- a/android/prebuilt.go
+++ b/android/prebuilt.go
@@ -62,6 +62,10 @@
 	return "prebuilt_" + name
 }
 
+func (p *Prebuilt) ForcePrefer() {
+	p.properties.Prefer = proptools.BoolPtr(true)
+}
+
 // The below source-related functions and the srcs, src fields are based on an assumption that
 // prebuilt modules have a static source property at the moment. Currently there is only one
 // exception, android_app_import, which chooses a source file depending on the product's DPI
diff --git a/android/sdk.go b/android/sdk.go
index 27756ce..d13ad7d 100644
--- a/android/sdk.go
+++ b/android/sdk.go
@@ -180,6 +180,15 @@
 	// will only be used if the equivalently named non-prebuilt module is not
 	// present.
 	AddPrebuiltModule(member SdkMember, moduleType string) BpModule
+
+	// The property tag to use when adding a property to a BpModule that contains
+	// references to other sdk members. Using this will ensure that the reference
+	// is correctly output for both versioned and unversioned prebuilts in the
+	// snapshot.
+	//
+	// e.g.
+	// bpPropertySet.AddPropertyWithTag("libs", []string{"member1", "member2"}, builder.SdkMemberReferencePropertyTag())
+	SdkMemberReferencePropertyTag() BpPropertyTag
 }
 
 type BpPropertyTag interface{}
@@ -264,6 +273,13 @@
 	// True if the member type supports the sdk/sdk_snapshot, false otherwise.
 	UsableWithSdkAndSdkSnapshot() bool
 
+	// Return true if modules of this type can have dependencies which should be
+	// treated as if they are sdk members.
+	//
+	// Any dependency that is to be treated as a member of the sdk needs to implement
+	// SdkAware and be added with an SdkMemberTypeDependencyTag tag.
+	HasTransitiveSdkMembers() bool
+
 	// Add dependencies from the SDK module to all the variants the member
 	// contributes to the SDK. The exact set of variants required is determined
 	// by the SDK and its properties. The dependencies must be added with the
@@ -291,8 +307,9 @@
 
 // Base type for SdkMemberType implementations.
 type SdkMemberTypeBase struct {
-	PropertyName string
-	SupportsSdk  bool
+	PropertyName         string
+	SupportsSdk          bool
+	TransitiveSdkMembers bool
 }
 
 func (b *SdkMemberTypeBase) SdkPropertyName() string {
@@ -303,6 +320,10 @@
 	return b.SupportsSdk
 }
 
+func (b *SdkMemberTypeBase) HasTransitiveSdkMembers() bool {
+	return b.TransitiveSdkMembers
+}
+
 // Encapsulates the information about registered SdkMemberTypes.
 type SdkMemberTypesRegistry struct {
 	// The list of types sorted by property name.
diff --git a/android/soong_config_modules.go b/android/soong_config_modules.go
index 3e55958..198108d 100644
--- a/android/soong_config_modules.go
+++ b/android/soong_config_modules.go
@@ -54,7 +54,7 @@
 // For example, an Android.bp file could have:
 //
 //     soong_config_module_type_import {
-//         from: "device/acme/Android.bp.bp",
+//         from: "device/acme/Android.bp",
 //         module_types: ["acme_cc_defaults"],
 //     }
 //
@@ -139,9 +139,9 @@
 }
 
 // soong_config_module_type defines module types with conditionals on Soong config
-// variables from another Android.bp file.  The new module type will exist for all
-// modules after the definition in an Android.bp file, and can be imported into other
-// Android.bp files using soong_config_module_type_import.
+// variables.  The new module type will exist for all modules after the definition
+// in an Android.bp file, and can be imported into other Android.bp files using
+// soong_config_module_type_import.
 //
 // For example, an Android.bp file could have:
 //
@@ -186,8 +186,6 @@
 //         srcs: ["*.cpp"],
 //     }
 //
-// And device/acme/Android.bp could have:
-//
 // If an acme BoardConfig.mk file contained:
 //
 //     SOONG_CONFIG_NAMESPACES += acme
@@ -305,6 +303,7 @@
 	}
 
 	return ctx.Config().Once(key, func() interface{} {
+		ctx.AddNinjaFileDeps(from)
 		r, err := ctx.Config().fs.Open(from)
 		if err != nil {
 			ctx.PropertyErrorf("from", "failed to open %q: %s", from, err)
diff --git a/android/soong_config_modules_test.go b/android/soong_config_modules_test.go
index 66feba8..6ad88a2 100644
--- a/android/soong_config_modules_test.go
+++ b/android/soong_config_modules_test.go
@@ -43,7 +43,7 @@
 			name: "acme_test_defaults",
 			module_type: "test_defaults",
 			config_namespace: "acme",
-			variables: ["board", "feature1", "feature2", "feature3"],
+			variables: ["board", "feature1", "feature2", "FEATURE3"],
 			properties: ["cflags", "srcs"],
 		}
 
@@ -61,7 +61,7 @@
 		}
 
 		soong_config_bool_variable {
-			name: "feature3",
+			name: "FEATURE3",
 		}
 	`
 
@@ -91,7 +91,7 @@
 				feature2: {
 					cflags: ["-DFEATURE2"],
 				},
-				feature3: {
+				FEATURE3: {
 					cflags: ["-DFEATURE3"],
 				},
 			},
diff --git a/android/util.go b/android/util.go
index 81f481d..e985fc1 100644
--- a/android/util.go
+++ b/android/util.go
@@ -121,8 +121,19 @@
 	return IndexList(s, list) != -1
 }
 
-func PrefixInList(s string, list []string) bool {
-	for _, prefix := range list {
+// Returns true if the given string s is prefixed with any string in the given prefix list.
+func PrefixInList(s string, prefixList []string) bool {
+	for _, prefix := range prefixList {
+		if strings.HasPrefix(s, prefix) {
+			return true
+		}
+	}
+	return false
+}
+
+// Returns true if any string in the given list has the given prefix.
+func PrefixedStringInList(list []string, prefix string) bool {
+	for _, s := range list {
 		if strings.HasPrefix(s, prefix) {
 			return true
 		}
diff --git a/android/variable.go b/android/variable.go
index c277acc..58e5940 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -25,7 +25,7 @@
 
 func init() {
 	PreDepsMutators(func(ctx RegisterMutatorsContext) {
-		ctx.BottomUp("variable", variableMutator).Parallel()
+		ctx.BottomUp("variable", VariableMutator).Parallel()
 	})
 }
 
@@ -127,13 +127,14 @@
 		} `android:"arch_variant"`
 
 		Native_coverage struct {
+			Src          *string  `android:"arch_variant"`
 			Srcs         []string `android:"arch_variant"`
 			Exclude_srcs []string `android:"arch_variant"`
 		} `android:"arch_variant"`
 	} `android:"arch_variant"`
 }
 
-var zeroProductVariables interface{} = variableProperties{}
+var defaultProductVariables interface{} = variableProperties{}
 
 type productVariables struct {
 	// Suffix to add to generated Makefiles
@@ -252,6 +253,7 @@
 	ClangTidy  *bool   `json:",omitempty"`
 	TidyChecks *string `json:",omitempty"`
 
+	NativeLineCoverage   *bool    `json:",omitempty"`
 	Native_coverage      *bool    `json:",omitempty"`
 	ClangCoverage        *bool    `json:",omitempty"`
 	CoveragePaths        []string `json:",omitempty"`
@@ -383,7 +385,7 @@
 	}
 }
 
-func variableMutator(mctx BottomUpMutatorContext) {
+func VariableMutator(mctx BottomUpMutatorContext) {
 	var module Module
 	var ok bool
 	if module, ok = mctx.Module().(Module); !ok {
@@ -398,11 +400,9 @@
 	}
 
 	variableValues := reflect.ValueOf(a.variableProperties).Elem().FieldByName("Product_variables")
-	zeroValues := reflect.ValueOf(zeroProductVariables).FieldByName("Product_variables")
 
 	for i := 0; i < variableValues.NumField(); i++ {
 		variableValue := variableValues.Field(i)
-		zeroValue := zeroValues.Field(i)
 		name := variableValues.Type().Field(i).Name
 		property := "product_variables." + proptools.PropertyNameForField(name)
 
@@ -420,10 +420,9 @@
 		}
 
 		// Check if any properties were set for the module
-		if reflect.DeepEqual(variableValue.Interface(), zeroValue.Interface()) {
+		if variableValue.IsZero() {
 			continue
 		}
-
 		a.setVariableProperties(mctx, property, variableValue, val.Interface())
 	}
 }
@@ -541,6 +540,20 @@
 	return ret.Interface()
 }
 
+func initProductVariableModule(m Module) {
+	base := m.base()
+
+	// Allow tests to override the default product variables
+	if base.variableProperties == nil {
+		base.variableProperties = defaultProductVariables
+	}
+	// Filter the product variables properties to the ones that exist on this module
+	base.variableProperties = createVariableProperties(m.GetProperties(), base.variableProperties)
+	if base.variableProperties != nil {
+		m.AddProperties(base.variableProperties)
+	}
+}
+
 // createVariableProperties takes the list of property structs for a module and returns a property struct that
 // contains the product variable properties that exist in the property structs, or nil if there are none.  It
 // caches the result.
diff --git a/android/variable_test.go b/android/variable_test.go
index cde2b1a..9cafedd 100644
--- a/android/variable_test.go
+++ b/android/variable_test.go
@@ -171,7 +171,7 @@
 		Foo []string
 	}{}))
 	ctx.PreDepsMutators(func(ctx RegisterMutatorsContext) {
-		ctx.BottomUp("variable", variableMutator).Parallel()
+		ctx.BottomUp("variable", VariableMutator).Parallel()
 	})
 
 	// Test that a module can use one product variable even if it doesn't have all the properties
@@ -209,6 +209,115 @@
 	FailIfErrored(t, errs)
 }
 
+var testProductVariableDefaultsProperties = struct {
+	Product_variables struct {
+		Eng struct {
+			Foo []string
+			Bar []string
+		}
+	}
+}{}
+
+type productVariablesDefaultsTestProperties struct {
+	Foo []string
+}
+
+type productVariablesDefaultsTestProperties2 struct {
+	Foo []string
+	Bar []string
+}
+
+type productVariablesDefaultsTestModule struct {
+	ModuleBase
+	DefaultableModuleBase
+	properties productVariablesDefaultsTestProperties
+}
+
+func (d *productVariablesDefaultsTestModule) GenerateAndroidBuildActions(ctx ModuleContext) {
+	ctx.Build(pctx, BuildParams{
+		Rule:   Touch,
+		Output: PathForModuleOut(ctx, "out"),
+	})
+}
+
+func productVariablesDefaultsTestModuleFactory() Module {
+	module := &productVariablesDefaultsTestModule{}
+	module.AddProperties(&module.properties)
+	module.variableProperties = testProductVariableDefaultsProperties
+	InitAndroidModule(module)
+	InitDefaultableModule(module)
+	return module
+}
+
+type productVariablesDefaultsTestDefaults struct {
+	ModuleBase
+	DefaultsModuleBase
+}
+
+func productVariablesDefaultsTestDefaultsFactory() Module {
+	defaults := &productVariablesDefaultsTestDefaults{}
+	defaults.AddProperties(&productVariablesDefaultsTestProperties{})
+	defaults.AddProperties(&productVariablesDefaultsTestProperties2{})
+	defaults.variableProperties = testProductVariableDefaultsProperties
+	InitDefaultsModule(defaults)
+	return defaults
+}
+
+// Test a defaults module that supports more product variable properties than the target module.
+func TestProductVariablesDefaults(t *testing.T) {
+	bp := `
+		defaults {
+			name: "defaults",
+			product_variables: {
+				eng: {
+					foo: ["product_variable_defaults"],
+					bar: ["product_variable_defaults"],
+				},
+			},
+			foo: ["defaults"],
+			bar: ["defaults"],
+		}
+
+		test {
+			name: "foo",
+			defaults: ["defaults"],
+			foo: ["module"],
+			product_variables: {
+				eng: {
+					foo: ["product_variable_module"],
+				},
+			},
+		}
+	`
+
+	config := TestConfig(buildDir, nil, bp, nil)
+	config.TestProductVariables.Eng = boolPtr(true)
+
+	ctx := NewTestContext()
+
+	ctx.RegisterModuleType("test", productVariablesDefaultsTestModuleFactory)
+	ctx.RegisterModuleType("defaults", productVariablesDefaultsTestDefaultsFactory)
+
+	ctx.PreArchMutators(RegisterDefaultsPreArchMutators)
+	ctx.PreDepsMutators(func(ctx RegisterMutatorsContext) {
+		ctx.BottomUp("variable", VariableMutator).Parallel()
+	})
+
+	ctx.Register(config)
+
+	_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
+	FailIfErrored(t, errs)
+	_, errs = ctx.PrepareBuildActions(config)
+	FailIfErrored(t, errs)
+
+	foo := ctx.ModuleForTests("foo", "").Module().(*productVariablesDefaultsTestModule)
+
+	want := []string{"defaults", "module", "product_variable_defaults", "product_variable_module"}
+	if g, w := foo.properties.Foo, want; !reflect.DeepEqual(g, w) {
+		t.Errorf("expected foo %q, got %q", w, g)
+	}
+}
+
 func BenchmarkSliceToTypeArray(b *testing.B) {
 	for _, n := range []int{1, 2, 4, 8, 100} {
 		var propStructs []interface{}
diff --git a/apex/androidmk.go b/apex/androidmk.go
index 8929910..714045f 100644
--- a/apex/androidmk.go
+++ b/apex/androidmk.go
@@ -42,7 +42,11 @@
 		}}
 }
 
-func (a *apexBundle) androidMkForFiles(w io.Writer, apexName, moduleDir string) []string {
+func (a *apexBundle) androidMkForFiles(w io.Writer, apexBundleName, apexName, moduleDir string) []string {
+	// apexBundleName comes from the 'name' property; apexName comes from 'apex_name' property.
+	// An apex is installed to /system/apex/<apexBundleName> and is activated at /apex/<apexName>
+	// In many cases, the two names are the same, but could be different in general.
+
 	moduleNames := []string{}
 	apexType := a.properties.ApexType
 	// To avoid creating duplicate build rules, run this function only when primaryApexType is true
@@ -52,12 +56,21 @@
 		return moduleNames
 	}
 
+	// b/140136207. When there are overriding APEXes for a VNDK APEX, the symbols file for the overridden
+	// APEX and the overriding APEX will have the same installation paths at /apex/com.android.vndk.v<ver>
+	// as their apexName will be the same. To avoid the path conflicts, skip installing the symbol files
+	// for the overriding VNDK APEXes.
+	symbolFilesNotNeeded := a.vndkApex && len(a.overridableProperties.Overrides) > 0
+	if symbolFilesNotNeeded && apexType != flattenedApex {
+		return moduleNames
+	}
+
 	var postInstallCommands []string
 	for _, fi := range a.filesInfo {
 		if a.linkToSystemLib && fi.transitiveDep && fi.AvailableToPlatform() {
 			// TODO(jiyong): pathOnDevice should come from fi.module, not being calculated here
 			linkTarget := filepath.Join("/system", fi.Path())
-			linkPath := filepath.Join(a.installDir.ToMakePath().String(), apexName, fi.Path())
+			linkPath := filepath.Join(a.installDir.ToMakePath().String(), apexBundleName, fi.Path())
 			mkdirCmd := "mkdir -p " + filepath.Dir(linkPath)
 			linkCmd := "ln -sfn " + linkTarget + " " + linkPath
 			postInstallCommands = append(postInstallCommands, mkdirCmd, linkCmd)
@@ -75,7 +88,7 @@
 		if linkToSystemLib {
 			moduleName = fi.moduleName
 		} else {
-			moduleName = fi.moduleName + "." + apexName + a.suffix
+			moduleName = fi.moduleName + "." + apexBundleName + a.suffix
 		}
 
 		if !android.InList(moduleName, moduleNames) {
@@ -99,8 +112,8 @@
 		if apexType == flattenedApex {
 			// /system/apex/<name>/{lib|framework|...}
 			fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", filepath.Join(a.installDir.ToMakePath().String(),
-				apexName, fi.installDir))
-			if a.primaryApexType {
+				apexBundleName, fi.installDir))
+			if a.primaryApexType && !symbolFilesNotNeeded {
 				fmt.Fprintln(w, "LOCAL_SOONG_SYMBOL_PATH :=", pathWhenActivated)
 			}
 			if len(fi.symlinks) > 0 {
@@ -236,7 +249,7 @@
 			apexType := a.properties.ApexType
 			if a.installable() {
 				apexName := proptools.StringDefault(a.properties.Apex_name, name)
-				moduleNames = a.androidMkForFiles(w, apexName, moduleDir)
+				moduleNames = a.androidMkForFiles(w, name, apexName, moduleDir)
 			}
 
 			if apexType == flattenedApex {
diff --git a/apex/apex.go b/apex/apex.go
index 48cdedf..329a6ba 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -45,18 +45,21 @@
 type dependencyTag struct {
 	blueprint.BaseDependencyTag
 	name string
+
+	// determines if the dependent will be part of the APEX payload
+	payload bool
 }
 
 var (
-	sharedLibTag   = dependencyTag{name: "sharedLib"}
-	executableTag  = dependencyTag{name: "executable"}
-	javaLibTag     = dependencyTag{name: "javaLib"}
-	prebuiltTag    = dependencyTag{name: "prebuilt"}
-	testTag        = dependencyTag{name: "test"}
+	sharedLibTag   = dependencyTag{name: "sharedLib", payload: true}
+	executableTag  = dependencyTag{name: "executable", payload: true}
+	javaLibTag     = dependencyTag{name: "javaLib", payload: true}
+	prebuiltTag    = dependencyTag{name: "prebuilt", payload: true}
+	testTag        = dependencyTag{name: "test", payload: true}
 	keyTag         = dependencyTag{name: "key"}
 	certificateTag = dependencyTag{name: "certificate"}
 	usesTag        = dependencyTag{name: "uses"}
-	androidAppTag  = dependencyTag{name: "androidApp"}
+	androidAppTag  = dependencyTag{name: "androidApp", payload: true}
 	apexAvailWl    = makeApexAvailableWhitelist()
 )
 
@@ -70,107 +73,328 @@
 	//
 	// Module separator
 	//
-	m["com.android.adbd"] = []string{"adbd", "libcrypto"}
+	m["com.android.adbd"] = []string{
+		"adbd",
+		"bcm_object",
+		"fmtlib",
+		"libadbconnection_server",
+		"libadbd",
+		"libadbd_auth",
+		"libadbd_core",
+		"libadbd_services",
+		"libasyncio",
+		"libbacktrace_headers",
+		"libbase",
+		"libbase_headers",
+		"libbuildversion",
+		"libc++",
+		"libcap",
+		"libcrypto",
+		"libcrypto_utils",
+		"libcutils",
+		"libcutils_headers",
+		"libdiagnose_usb",
+		"liblog",
+		"liblog_headers",
+		"libmdnssd",
+		"libminijail",
+		"libminijail_gen_constants",
+		"libminijail_gen_constants_obj",
+		"libminijail_gen_syscall",
+		"libminijail_gen_syscall_obj",
+		"libminijail_generated",
+		"libpackagelistparser",
+		"libpcre2",
+		"libprocessgroup_headers",
+		"libqemu_pipe",
+		"libselinux",
+		"libsystem_headers",
+		"libutils_headers",
+	}
+	//
+	// Module separator
+	//
+	m["com.android.appsearch"] = []string{
+		"icing-java-proto-lite",
+		"libprotobuf-java-lite",
+	}
 	//
 	// Module separator
 	//
 	m["com.android.art"] = []string{
+		"art_cmdlineparser_headers",
+		"art_disassembler_headers",
+		"art_libartbase_headers",
+		"bcm_object",
+		"bionic_libc_platform_headers",
+		"core-repackaged-icu4j",
+		"cpp-define-generator-asm-support",
+		"cpp-define-generator-definitions",
+		"crtbegin_dynamic",
+		"crtbegin_dynamic1",
+		"crtbegin_so1",
+		"crtbrand",
+		"conscrypt.module.intra.core.api.stubs",
+		"dex2oat_headers",
+		"dt_fd_forward_export",
+		"fmtlib",
+		"icu4c_extra_headers",
 		"jacocoagent",
+		"javavm_headers",
+		"jni_platform_headers",
+		"libPlatformProperties",
+		"libadbconnection_client",
 		"libadbconnection_server",
+		"libandroidicuinit",
+		"libart_runtime_headers_ndk",
 		"libartd-disassembler",
+		"libasync_safe",
 		"libbacktrace",
 		"libbase",
+		"libbase_headers",
 		"libc++",
+		"libc++_static",
+		"libc++abi",
+		"libc++demangle",
+		"libc_headers",
 		"libcrypto",
+		"libdexfile_all_headers",
+		"libdexfile_external_headers",
 		"libdexfile_support",
+		"libdmabufinfo",
 		"libexpat",
+		"libfdlibm",
+		"libgtest_prod",
+		"libicui18n_headers",
 		"libicuuc",
+		"libicuuc_headers",
+		"libicuuc_stubdata",
+		"libjdwp_headers",
+		"liblog",
+		"liblog_headers",
+		"liblz4",
 		"liblzma",
 		"libmeminfo",
+		"libnativebridge-headers",
+		"libnativehelper_header_only",
+		"libnativeloader-headers",
+		"libnpt_headers",
+		"libopenjdkjvmti_headers",
+		"libperfetto_client_experimental",
 		"libprocinfo",
+		"libprotobuf-cpp-lite",
+		"libunwind_llvm",
 		"libunwindstack",
+		"libv8",
+		"libv8base",
+		"libv8gen",
+		"libv8platform",
+		"libv8sampler",
+		"libv8src",
 		"libvixl",
 		"libvixld",
 		"libz",
 		"libziparchive",
-		"prebuilt_libclang_rt",
+		"perfetto_trace_protos",
 	}
 	//
 	// Module separator
 	//
 	m["com.android.bluetooth.updatable"] = []string{
 		"android.hardware.audio.common@5.0",
-		"android.hardware.bluetooth@1.0",
-		"android.hardware.bluetooth@1.1",
 		"android.hardware.bluetooth.a2dp@1.0",
 		"android.hardware.bluetooth.audio@2.0",
+		"android.hardware.bluetooth@1.0",
+		"android.hardware.bluetooth@1.1",
+		"android.hardware.graphics.bufferqueue@1.0",
+		"android.hardware.graphics.bufferqueue@2.0",
+		"android.hardware.graphics.common@1.0",
+		"android.hardware.graphics.common@1.1",
+		"android.hardware.graphics.common@1.2",
+		"android.hardware.media@1.0",
 		"android.hidl.safe_union@1.0",
+		"android.hidl.token@1.0",
+		"android.hidl.token@1.0-utils",
+		"avrcp-target-service",
+		"avrcp_headers",
+		"bcm_object",
+		"bluetooth-protos-lite",
+		"bluetooth.mapsapi",
+		"com.android.vcard",
+		"fmtlib",
+		"guava",
+		"internal_include_headers",
+		"lib-bt-packets",
+		"lib-bt-packets-avrcp",
+		"lib-bt-packets-base",
+		"libFraunhoferAAC",
+		"libaudio-a2dp-hw-utils",
+		"libaudio-hearing-aid-hw-utils",
+		"libbacktrace_headers",
 		"libbase",
+		"libbase_headers",
+		"libbinder_headers",
 		"libbinderthreadstate",
 		"libbluetooth",
+		"libbluetooth-types",
+		"libbluetooth-types-header",
+		"libbluetooth_gd",
+		"libbluetooth_headers",
 		"libbluetooth_jni",
+		"libbt-audio-hal-interface",
+		"libbt-bta",
+		"libbt-common",
+		"libbt-hci",
+		"libbt-platform-protos-lite",
+		"libbt-protos-lite",
+		"libbt-sbc-decoder",
+		"libbt-sbc-encoder",
+		"libbt-stack",
+		"libbt-utils",
+		"libbtcore",
+		"libbtdevice",
+		"libbte",
+		"libbtif",
 		"libc++",
 		"libchrome",
 		"libcrypto",
 		"libcutils",
+		"libcutils_headers",
 		"libevent",
 		"libfmq",
+		"libg722codec",
+		"libgtest_prod",
+		"libgui_headers",
 		"libhidlbase",
+		"libhidlbase-impl-internal",
+		"libhidltransport-impl-internal",
+		"libhwbinder-impl-internal",
+		"libjsoncpp",
+		"liblog_headers",
+		"libmedia_headers",
+		"libmodpb64",
+		"libosi",
 		"libprocessgroup",
+		"libprocessgroup_headers",
 		"libprotobuf-cpp-lite",
+		"libprotobuf-java-lite",
+		"libprotobuf-java-micro",
+		"libstagefright_foundation_headers",
+		"libstagefright_headers",
 		"libstatslog",
+		"libstatssocket",
+		"libsystem_headers",
 		"libtinyxml2",
+		"libudrv-uipc",
 		"libutils",
+		"libutils_headers",
 		"libz",
+		"media_plugin_headers",
+		"sap-api-java-static",
+		"services.net",
 	}
 	//
 	// Module separator
 	//
-	m["com.android.conscrypt"] = []string{"boringssl_self_test", "libc++", "libcrypto", "libssl"}
+	m["com.android.cellbroadcast"] = []string{"CellBroadcastApp", "CellBroadcastServiceModule"}
 	//
 	// Module separator
 	//
-	m["com.android.cronet"] = []string{"org.chromium.net.cronet", "prebuilt_libcronet.80.0.3986.0"}
+	m["com.android.conscrypt"] = []string{
+		"bcm_object",
+		"boringssl_self_test",
+		"libc++",
+		"libcrypto",
+		"libnativehelper_header_only",
+		"libssl",
+	}
+	//
+	// Module separator
+	//
+	m["com.android.extservices"] = []string{
+		"flatbuffer_headers",
+		"liblua",
+		"libtextclassifier",
+		"libtextclassifier_hash_static",
+		"libtflite_static",
+		"libutf",
+		"libz_current",
+		"tensorflow_headers",
+	}
+	//
+	// Module separator
+	//
+	m["com.android.cronet"] = []string{
+		"cronet_impl_common_java",
+		"cronet_impl_native_java",
+		"cronet_impl_platform_java",
+		"libcronet.80.0.3986.0",
+		"org.chromium.net.cronet",
+		"prebuilt_libcronet.80.0.3986.0",
+	}
+	//
+	// Module separator
+	//
+	m["com.android.neuralnetworks"] = []string{
+		"android.hardware.neuralnetworks@1.0",
+		"android.hardware.neuralnetworks@1.1",
+		"android.hardware.neuralnetworks@1.2",
+		"android.hardware.neuralnetworks@1.3",
+		"android.hidl.allocator@1.0",
+		"android.hidl.memory.token@1.0",
+		"android.hidl.memory@1.0",
+		"android.hidl.safe_union@1.0",
+		"bcm_object",
+		"fmtlib",
+		"gemmlowp_headers",
+		"libarect",
+		"libbacktrace_headers",
+		"libbase",
+		"libbase_headers",
+		"libbinderthreadstate",
+		"libbuildversion",
+		"libc++",
+		"libcrypto",
+		"libcrypto_static",
+		"libcutils",
+		"libcutils_headers",
+		"libeigen",
+		"libfmq",
+		"libhidlbase",
+		"libhidlbase-impl-internal",
+		"libhidlmemory",
+		"libhidltransport-impl-internal",
+		"libhwbinder-impl-internal",
+		"libjsoncpp",
+		"liblog_headers",
+		"libmath",
+		"libneuralnetworks_common",
+		"libneuralnetworks_headers",
+		"libprocessgroup",
+		"libprocessgroup_headers",
+		"libprocpartition",
+		"libsync",
+		"libsystem_headers",
+		"libtextclassifier_hash",
+		"libtextclassifier_hash_headers",
+		"libtextclassifier_hash_static",
+		"libtflite_kernel_utils",
+		"libutils",
+		"libutils_headers",
+		"philox_random",
+		"philox_random_headers",
+		"tensorflow_headers",
+	}
 	//
 	// Module separator
 	//
 	m["com.android.media"] = []string{
-		"android.hardware.cas@1.0",
-		"android.hardware.cas.native@1.0",
-		"android.hidl.allocator@1.0",
-		"android.hidl.memory@1.0",
-		"android.hidl.memory.token@1.0",
-		"android.hidl.token@1.0",
-		"android.hidl.token@1.0-utils",
-		"libaacextractor",
-		"libamrextractor",
-		"libbase",
-		"libbinderthreadstate",
-		"libc++",
-		"libcrypto",
-		"libcutils",
-		"libflacextractor",
-		"libhidlbase",
-		"libhidlmemory",
-		"libmidiextractor",
-		"libmkvextractor",
-		"libmp3extractor",
-		"libmp4extractor",
-		"libmpeg2extractor",
-		"liboggextractor",
-		"libprocessgroup",
-		"libutils",
-		"libwavextractor",
-		"updatable-media",
-	}
-	//
-	// Module separator
-	//
-	m["com.android.media.swcodec"] = []string{
 		"android.frameworks.bufferhub@1.0",
+		"android.hardware.cas.native@1.0",
+		"android.hardware.cas@1.0",
+		"android.hardware.configstore-utils",
 		"android.hardware.configstore@1.0",
 		"android.hardware.configstore@1.1",
-		"android.hardware.configstore-utils",
 		"android.hardware.graphics.allocator@2.0",
 		"android.hardware.graphics.allocator@3.0",
 		"android.hardware.graphics.bufferqueue@1.0",
@@ -181,23 +405,199 @@
 		"android.hardware.graphics.mapper@2.0",
 		"android.hardware.graphics.mapper@2.1",
 		"android.hardware.graphics.mapper@3.0",
+		"android.hardware.media.omx@1.0",
 		"android.hardware.media@1.0",
+		"android.hidl.allocator@1.0",
+		"android.hidl.memory.token@1.0",
+		"android.hidl.memory@1.0",
+		"android.hidl.token@1.0",
+		"android.hidl.token@1.0-utils",
+		"bcm_object",
+		"bionic_libc_platform_headers",
+		"fmtlib",
+		"gl_headers",
+		"libEGL",
+		"libEGL_blobCache",
+		"libEGL_getProcAddress",
+		"libFLAC",
+		"libFLAC-config",
+		"libFLAC-headers",
+		"libGLESv2",
+		"libaacextractor",
+		"libamrextractor",
+		"libarect",
+		"libasync_safe",
+		"libaudio_system_headers",
+		"libaudioclient",
+		"libaudioclient_headers",
+		"libaudiofoundation",
+		"libaudiofoundation_headers",
+		"libaudiomanager",
+		"libaudiopolicy",
+		"libaudioutils",
+		"libaudioutils_fixedfft",
+		"libbacktrace",
+		"libbacktrace_headers",
+		"libbase",
+		"libbase_headers",
+		"libbinder_headers",
+		"libbinderthreadstate",
+		"libbluetooth-types-header",
+		"libbufferhub",
+		"libbufferhub_headers",
+		"libbufferhubqueue",
+		"libc++",
+		"libc_headers",
+		"libc_malloc_debug_backtrace",
+		"libcamera_client",
+		"libcamera_metadata",
+		"libcrypto",
+		"libcutils",
+		"libcutils_headers",
+		"libdexfile_external_headers",
+		"libdexfile_support",
+		"libdvr_headers",
+		"libexpat",
+		"libfifo",
+		"libflacextractor",
+		"libgrallocusage",
+		"libgraphicsenv",
+		"libgui",
+		"libgui_headers",
+		"libhardware_headers",
+		"libhidlbase",
+		"libhidlbase-impl-internal",
+		"libhidlmemory",
+		"libhidltransport-impl-internal",
+		"libhwbinder-impl-internal",
+		"libinput",
+		"libjsoncpp",
+		"liblog_headers",
+		"liblzma",
+		"libmath",
+		"libmedia",
+		"libmedia_codeclist",
+		"libmedia_headers",
+		"libmedia_helper",
+		"libmedia_helper_headers",
+		"libmedia_midiiowrapper",
+		"libmedia_omx",
+		"libmediautils",
+		"libmidiextractor",
+		"libmkvextractor",
+		"libmp3extractor",
+		"libmp4extractor",
+		"libmpeg2extractor",
+		"libnativebase_headers",
+		"libnativebridge-headers",
+		"libnativebridge_lazy",
+		"libnativeloader-headers",
+		"libnativeloader_lazy",
+		"libnativewindow_headers",
+		"libnblog",
+		"liboggextractor",
+		"libpackagelistparser",
+		"libpcre2",
+		"libpdx",
+		"libpdx_default_transport",
+		"libpdx_headers",
+		"libpdx_uds",
+		"libprocessgroup",
+		"libprocessgroup_headers",
+		"libprocinfo",
+		"libselinux",
+		"libsonivox",
+		"libspeexresampler",
+		"libspeexresampler",
+		"libstagefright_esds",
+		"libstagefright_flacdec",
+		"libstagefright_flacdec",
+		"libstagefright_foundation",
+		"libstagefright_foundation_headers",
+		"libstagefright_foundation_without_imemory",
+		"libstagefright_headers",
+		"libstagefright_id3",
+		"libstagefright_metadatautils",
+		"libstagefright_mpeg2extractor",
+		"libstagefright_mpeg2support",
+		"libsync",
+		"libsystem_headers",
+		"libui",
+		"libui_headers",
+		"libunwindstack",
+		"libutils",
+		"libutils_headers",
+		"libvibrator",
+		"libvorbisidec",
+		"libwavextractor",
+		"libwebm",
+		"media_ndk_headers",
+		"media_plugin_headers",
+		"updatable-media",
+	}
+	//
+	// Module separator
+	//
+	m["com.android.media.swcodec"] = []string{
+		"android.frameworks.bufferhub@1.0",
+		"android.hardware.common-ndk_platform",
+		"android.hardware.configstore-utils",
+		"android.hardware.configstore@1.0",
+		"android.hardware.configstore@1.1",
+		"android.hardware.graphics.allocator@2.0",
+		"android.hardware.graphics.allocator@3.0",
+		"android.hardware.graphics.bufferqueue@1.0",
+		"android.hardware.graphics.bufferqueue@2.0",
+		"android.hardware.graphics.common-ndk_platform",
+		"android.hardware.graphics.common@1.0",
+		"android.hardware.graphics.common@1.1",
+		"android.hardware.graphics.common@1.2",
+		"android.hardware.graphics.mapper@2.0",
+		"android.hardware.graphics.mapper@2.1",
+		"android.hardware.graphics.mapper@3.0",
+		"android.hardware.graphics.mapper@4.0",
 		"android.hardware.media.bufferpool@2.0",
 		"android.hardware.media.c2@1.0",
 		"android.hardware.media.omx@1.0",
-		"android.hidl.memory@1.0",
+		"android.hardware.media@1.0",
+		"android.hardware.media@1.0",
 		"android.hidl.memory.token@1.0",
+		"android.hidl.memory@1.0",
 		"android.hidl.safe_union@1.0",
 		"android.hidl.token@1.0",
 		"android.hidl.token@1.0-utils",
+		"fmtlib",
+		"libEGL",
+		"libFLAC",
+		"libFLAC-config",
+		"libFLAC-headers",
+		"libFraunhoferAAC",
+		"libarect",
+		"libasync_safe",
+		"libaudio_system_headers",
+		"libaudioutils",
+		"libaudioutils",
+		"libaudioutils_fixedfft",
+		"libavcdec",
+		"libavcenc",
+		"libavservices_minijail",
 		"libavservices_minijail",
 		"libbacktrace",
+		"libbacktrace_headers",
 		"libbase",
+		"libbase_headers",
+		"libbinder_headers",
 		"libbinderthreadstate",
+		"libbluetooth-types-header",
+		"libbufferhub_headers",
 		"libc++",
+		"libc_scudo",
 		"libcap",
 		"libcodec2",
+		"libcodec2_headers",
 		"libcodec2_hidl@1.0",
+		"libcodec2_hidl@1.1",
+		"libcodec2_internal",
 		"libcodec2_soft_aacdec",
 		"libcodec2_soft_aacenc",
 		"libcodec2_soft_amrnbdec",
@@ -230,73 +630,381 @@
 		"libcodec2_soft_vp9dec",
 		"libcodec2_soft_vp9enc",
 		"libcodec2_vndk",
-		"libc_scudo",
 		"libcutils",
+		"libcutils_headers",
 		"libdexfile_support",
-		"libEGL",
+		"libdvr_headers",
 		"libfmq",
+		"libfmq",
+		"libgav1",
+		"libgralloctypes",
+		"libgrallocusage",
 		"libgraphicsenv",
+		"libgsm",
+		"libgui_bufferqueue_static",
+		"libgui_headers",
 		"libhardware",
+		"libhardware_headers",
+		"libhevcdec",
+		"libhevcenc",
 		"libhidlbase",
+		"libhidlbase-impl-internal",
 		"libhidlmemory",
+		"libhidltransport-impl-internal",
+		"libhwbinder-impl-internal",
 		"libion",
+		"libjpeg",
+		"libjsoncpp",
+		"liblog_headers",
 		"liblzma",
+		"libmath",
 		"libmedia_codecserviceregistrant",
+		"libmedia_headers",
 		"libminijail",
+		"libminijail_gen_constants",
+		"libminijail_gen_constants_obj",
+		"libminijail_gen_syscall",
+		"libminijail_gen_syscall_obj",
+		"libminijail_generated",
+		"libmpeg2dec",
+		"libnativebase_headers",
 		"libnativebridge_lazy",
 		"libnativeloader_lazy",
+		"libnativewindow_headers",
 		"libopus",
+		"libpdx_headers",
 		"libprocessgroup",
+		"libprocessgroup_headers",
 		"libscudo_wrapper",
 		"libsfplugin_ccodec_utils",
 		"libstagefright_amrnb_common",
+		"libstagefright_amrnbdec",
+		"libstagefright_amrnbenc",
+		"libstagefright_amrwbdec",
+		"libstagefright_amrwbenc",
 		"libstagefright_bufferpool@2.0.1",
 		"libstagefright_bufferqueue_helper",
 		"libstagefright_enc_common",
 		"libstagefright_flacdec",
 		"libstagefright_foundation",
+		"libstagefright_foundation_headers",
+		"libstagefright_headers",
+		"libstagefright_m4vh263dec",
+		"libstagefright_m4vh263enc",
+		"libstagefright_mp3dec",
 		"libsync",
+		"libsystem_headers",
 		"libui",
+		"libui_headers",
 		"libunwindstack",
 		"libutils",
+		"libutils_headers",
 		"libvorbisidec",
 		"libvpx",
+		"libyuv",
+		"libyuv_static",
+		"media_ndk_headers",
+		"media_plugin_headers",
 		"mediaswcodec",
-		"prebuilt_libclang_rt",
+	}
+	//
+	// Module separator
+	//
+	m["com.android.mediaprovider"] = []string{
+		"MediaProvider",
+		"MediaProviderGoogle",
+		"fmtlib_ndk",
+		"guava",
+		"libbase_ndk",
+		"libfuse",
+		"libfuse_jni",
+		"libnativehelper_header_only",
+	}
+	//
+	// Module separator
+	//
+	m["com.android.permission"] = []string{
+		"androidx.annotation_annotation",
+		"androidx.annotation_annotation-nodeps",
+		"androidx.lifecycle_lifecycle-common",
+		"androidx.lifecycle_lifecycle-common-java8",
+		"androidx.lifecycle_lifecycle-common-java8-nodeps",
+		"androidx.lifecycle_lifecycle-common-nodeps",
+		"kotlin-annotations",
+		"kotlin-stdlib",
+		"kotlin-stdlib-jdk7",
+		"kotlin-stdlib-jdk8",
+		"kotlinx-coroutines-android",
+		"kotlinx-coroutines-android-nodeps",
+		"kotlinx-coroutines-core",
+		"kotlinx-coroutines-core-nodeps",
+		"libprotobuf-java-lite",
+		"permissioncontroller-statsd",
 	}
 	//
 	// Module separator
 	//
 	m["com.android.runtime"] = []string{
+		"bionic_libc_platform_headers",
+		"fmtlib",
+		"libarm-optimized-routines-math",
+		"libasync_safe",
+		"libasync_safe_headers",
+		"libbacktrace_headers",
+		"libbase",
+		"libbase_headers",
+		"libc++",
+		"libc_aeabi",
+		"libc_bionic",
+		"libc_bionic_ndk",
+		"libc_bootstrap",
+		"libc_common",
+		"libc_common_shared",
+		"libc_common_static",
+		"libc_dns",
+		"libc_dynamic_dispatch",
+		"libc_fortify",
+		"libc_freebsd",
+		"libc_freebsd_large_stack",
+		"libc_gdtoa",
+		"libc_headers",
+		"libc_init_dynamic",
+		"libc_init_static",
+		"libc_jemalloc_wrapper",
+		"libc_netbsd",
+		"libc_nomalloc",
+		"libc_nopthread",
+		"libc_openbsd",
+		"libc_openbsd_large_stack",
+		"libc_openbsd_ndk",
+		"libc_pthread",
+		"libc_static_dispatch",
+		"libc_syscalls",
+		"libc_tzcode",
+		"libc_unwind_static",
+		"libcutils",
+		"libcutils_headers",
+		"libdebuggerd",
+		"libdebuggerd_common_headers",
+		"libdebuggerd_handler_core",
+		"libdebuggerd_handler_fallback",
+		"libdexfile_external_headers",
+		"libdexfile_support",
+		"libdexfile_support_static",
+		"libgtest_prod",
+		"libjemalloc5",
+		"liblinker_main",
+		"liblinker_malloc",
+		"liblog",
+		"liblog_headers",
+		"liblz4",
+		"liblzma",
+		"libprocessgroup_headers",
+		"libprocinfo",
+		"libpropertyinfoparser",
+		"libscudo",
+		"libstdc++",
+		"libsystem_headers",
+		"libsystemproperties",
+		"libtombstoned_client_static",
+		"libunwindstack",
+		"libutils_headers",
+		"libz",
+		"libziparchive",
+	}
+	//
+	// Module separator
+	//
+	m["com.android.resolv"] = []string{
+		"bcm_object",
+		"dnsresolver_aidl_interface-unstable-ndk_platform",
+		"fmtlib",
+		"libbacktrace_headers",
+		"libbase",
+		"libbase_headers",
+		"libc++",
+		"libcrypto",
+		"libcutils",
+		"libcutils_headers",
+		"libgtest_prod",
+		"libjsoncpp",
+		"liblog",
+		"liblog_headers",
+		"libnativehelper_header_only",
+		"libnetd_client_headers",
+		"libnetd_resolv",
+		"libnetdutils",
+		"libprocessgroup",
+		"libprocessgroup_headers",
+		"libprotobuf-cpp-lite",
+		"libssl",
+		"libstatslog_resolv",
+		"libstatspush_compat",
+		"libstatssocket",
+		"libstatssocket_headers",
+		"libsystem_headers",
+		"libsysutils",
+		"libutils",
+		"libutils_headers",
+		"netd_event_listener_interface-ndk_platform",
+		"server_configurable_flags",
+		"stats_proto",
+	}
+	//
+	// Module separator
+	//
+	m["com.android.tethering"] = []string{
 		"libbase",
 		"libc++",
-		"libdexfile_support",
-		"liblzma",
-		"libunwindstack",
-		"prebuilt_libclang_rt",
-	}
-	//
-	// Module separator
-	//
-	m["com.android.resolv"] = []string{"libcrypto", "libnetd_resolv", "libssl"}
-	//
-	// Module separator
-	//
-	m["com.android.tethering"] = []string{"libbase", "libc++", "libnativehelper_compat_libc++"}
-	//
-	// Module separator
-	//
-	m["com.android.vndk"] = []string{
-		"libbacktrace",
+		"libnativehelper_compat_libc++",
+		"android.hardware.tetheroffload.config@1.0",
+		"fmtlib",
+		"libbacktrace_headers",
+		"libbase_headers",
 		"libbinderthreadstate",
-		"libblas",
-		"libcompiler_rt",
-		"libgui",
-		"libunwind",
+		"libcgrouprc",
+		"libcgrouprc_format",
+		"libcutils",
+		"libcutils_headers",
+		"libhidlbase",
+		"libhidlbase-impl-internal",
+		"libhidltransport-impl-internal",
+		"libhwbinder-impl-internal",
+		"libjsoncpp",
+		"liblog",
+		"liblog_headers",
+		"libprocessgroup",
+		"libprocessgroup_headers",
+		"libsystem_headers",
+		"libtetherutilsjni",
+		"libutils",
+		"libutils_headers",
+		"libvndksupport",
+		"tethering-aidl-interfaces-java",
 	}
 	//
 	// Module separator
 	//
+	m["com.android.wifi"] = []string{
+		"PlatformProperties",
+		"android.hardware.wifi-V1.0-java",
+		"android.hardware.wifi-V1.1-java",
+		"android.hardware.wifi-V1.2-java",
+		"android.hardware.wifi-V1.3-java",
+		"android.hardware.wifi-V1.4-java",
+		"android.hardware.wifi.hostapd-V1.0-java",
+		"android.hardware.wifi.hostapd-V1.1-java",
+		"android.hardware.wifi.hostapd-V1.2-java",
+		"android.hardware.wifi.supplicant-V1.0-java",
+		"android.hardware.wifi.supplicant-V1.1-java",
+		"android.hardware.wifi.supplicant-V1.2-java",
+		"android.hardware.wifi.supplicant-V1.3-java",
+		"android.hidl.base-V1.0-java",
+		"android.hidl.manager-V1.0-java",
+		"android.hidl.manager-V1.1-java",
+		"android.hidl.manager-V1.2-java",
+		"androidx.annotation_annotation",
+		"androidx.annotation_annotation-nodeps",
+		"bouncycastle-unbundled",
+		"dnsresolver_aidl_interface-V2-java",
+		"error_prone_annotations",
+		"ipmemorystore-aidl-interfaces-V3-java",
+		"ipmemorystore-aidl-interfaces-java",
+		"ksoap2",
+		"libbacktrace_headers",
+		"libbase",
+		"libbase_headers",
+		"libc++",
+		"libcutils",
+		"libcutils_headers",
+		"liblog_headers",
+		"libnanohttpd",
+		"libprocessgroup",
+		"libprocessgroup_headers",
+		"libprotobuf-java-lite",
+		"libprotobuf-java-nano",
+		"libsystem_headers",
+		"libutils",
+		"libutils_headers",
+		"libwifi-jni",
+		"net-utils-services-common",
+		"netd_aidl_interface-V2-java",
+		"netd_aidl_interface-unstable-java",
+		"netd_event_listener_interface-java",
+		"netlink-client",
+		"networkstack-aidl-interfaces-unstable-java",
+		"networkstack-client",
+		"services.net",
+		"wifi-lite-protos",
+		"wifi-nano-protos",
+		"wifi-service-pre-jarjar",
+		"wifi-service-resources",
+		"prebuilt_androidx.annotation_annotation-nodeps",
+	}
+	//
+	// Module separator
+	//
+	m["com.android.sdkext"] = []string{
+		"fmtlib_ndk",
+		"libbase_ndk",
+		"libprotobuf-cpp-lite-ndk",
+	}
+	//
+	// Module separator
+	//
+	m["com.android.os.statsd"] = []string{
+		"libbacktrace_headers",
+		"libbase_headers",
+		"libc++",
+		"libcutils",
+		"libcutils_headers",
+		"liblog_headers",
+		"libprocessgroup_headers",
+		"libstatssocket",
+		"libsystem_headers",
+		"libutils_headers",
+	}
+	//
+	// Module separator
+	//
+	m["//any"] = []string{
+		"crtbegin_dynamic",
+		"crtbegin_dynamic1",
+		"crtbegin_so",
+		"crtbegin_so1",
+		"crtbegin_static",
+		"crtbrand",
+		"crtend_android",
+		"crtend_so",
+		"libatomic",
+		"libc++_static",
+		"libc++abi",
+		"libc++demangle",
+		"libc_headers",
+		"libclang_rt",
+		"libgcc_stripped",
+		"libprofile-clang-extras",
+		"libprofile-clang-extras_ndk",
+		"libprofile-extras",
+		"libprofile-extras_ndk",
+		"libunwind_llvm",
+		"ndk_crtbegin_dynamic.27",
+		"ndk_crtbegin_so.16",
+		"ndk_crtbegin_so.19",
+		"ndk_crtbegin_so.21",
+		"ndk_crtbegin_so.24",
+		"ndk_crtbegin_so.27",
+		"ndk_crtend_android.27",
+		"ndk_crtend_so.16",
+		"ndk_crtend_so.19",
+		"ndk_crtend_so.21",
+		"ndk_crtend_so.24",
+		"ndk_crtend_so.27",
+		"ndk_libandroid_support",
+		"ndk_libc++_static",
+		"ndk_libc++abi",
+		"ndk_libunwind",
+	}
 	return m
 }
 
@@ -1194,6 +1902,12 @@
 	return newApexFile(ctx, fileToCopy, depName, dirInApex, etc, prebuilt)
 }
 
+func apexFileForCompatConfig(ctx android.BaseModuleContext, config java.PlatformCompatConfigIntf, depName string) apexFile {
+	dirInApex := filepath.Join("etc", config.SubDir())
+	fileToCopy := config.CompatConfig()
+	return newApexFile(ctx, fileToCopy, depName, dirInApex, etc, config)
+}
+
 func apexFileForAndroidApp(ctx android.BaseModuleContext, aapp interface {
 	android.Module
 	Privileged() bool
@@ -1222,6 +1936,53 @@
 	return true
 }
 
+// Visit dependencies that contributes to the payload of this APEX
+func (a *apexBundle) walkPayloadDeps(ctx android.ModuleContext,
+	do func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool)) {
+	ctx.WalkDepsBlueprint(func(child, parent blueprint.Module) bool {
+		am, ok := child.(android.ApexModule)
+		if !ok || !am.CanHaveApexVariants() {
+			return false
+		}
+
+		// Check for the direct dependencies that contribute to the payload
+		if dt, ok := ctx.OtherModuleDependencyTag(child).(dependencyTag); ok {
+			if dt.payload {
+				do(ctx, parent, am, false /* externalDep */)
+				return true
+			}
+			return false
+		}
+
+		// Check for the indirect dependencies if it is considered as part of the APEX
+		if am.DepIsInSameApex(ctx, am) {
+			do(ctx, parent, am, false /* externalDep */)
+			return true
+		}
+
+		do(ctx, parent, am, true /* externalDep */)
+
+		// As soon as the dependency graph crosses the APEX boundary, don't go further.
+		return false
+	})
+}
+
+// Ensures that the dependencies are marked as available for this APEX
+func (a *apexBundle) checkApexAvailability(ctx android.ModuleContext) {
+	// Let's be practical. Availability for test, host, and the VNDK apex isn't important
+	if ctx.Host() || a.testApex || a.vndkApex {
+		return
+	}
+
+	a.walkPayloadDeps(ctx, func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) {
+		apexName := ctx.ModuleName()
+		if externalDep || to.AvailableFor(apexName) || whitelistedApexAvailable(apexName, to) {
+			return
+		}
+		ctx.ModuleErrorf("requires %q that is not available for the APEX.", to.Name())
+	})
+}
+
 func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
 	buildFlattenedAsDefault := ctx.Config().FlattenApex() && !ctx.Config().UnbundledBuild()
 	switch a.properties.ApexType {
@@ -1257,6 +2018,8 @@
 		return
 	}
 
+	a.checkApexAvailability(ctx)
+
 	handleSpecialLibs := !android.Bool(a.properties.Ignore_system_library_special_case)
 
 	// native lib dependencies
@@ -1297,11 +2060,12 @@
 			}
 			switch depTag {
 			case sharedLibTag:
-				if cc, ok := child.(*cc.Module); ok {
-					if cc.HasStubsVariants() {
-						provideNativeLibs = append(provideNativeLibs, cc.OutputFile().Path().Base())
+				if c, ok := child.(*cc.Module); ok {
+					// bootstrap bionic libs are treated as provided by system
+					if c.HasStubsVariants() && !cc.InstallToBootstrap(c.BaseModuleName(), ctx.Config()) {
+						provideNativeLibs = append(provideNativeLibs, c.OutputFile().Path().Base())
 					}
-					filesInfo = append(filesInfo, apexFileForNativeLibrary(ctx, cc, handleSpecialLibs))
+					filesInfo = append(filesInfo, apexFileForNativeLibrary(ctx, c, handleSpecialLibs))
 					return true // track transitive dependencies
 				} else {
 					ctx.PropertyErrorf("native_shared_libs", "%q is not a cc_library or cc_library_shared module", depName)
@@ -1336,12 +2100,12 @@
 					}
 					filesInfo = append(filesInfo, af)
 
-					pf, _ := sdkLib.OutputFiles(".xml")
-					if len(pf) != 1 {
+					pf := sdkLib.XmlPermissionsFile()
+					if pf == nil {
 						ctx.PropertyErrorf("java_libs", "%q failed to generate permission XML", depName)
 						return false
 					}
-					filesInfo = append(filesInfo, newApexFile(ctx, pf[0], pf[0].Base(), "etc/permissions", etc, nil))
+					filesInfo = append(filesInfo, newApexFile(ctx, pf, pf.Base(), "etc/permissions", etc, nil))
 					return true // track transitive dependencies
 				} else {
 					ctx.PropertyErrorf("java_libs", "%q of type %q is not supported", depName, ctx.OtherModuleType(child))
@@ -1361,8 +2125,10 @@
 			case prebuiltTag:
 				if prebuilt, ok := child.(android.PrebuiltEtcModule); ok {
 					filesInfo = append(filesInfo, apexFileForPrebuiltEtc(ctx, prebuilt, depName))
+				} else if prebuilt, ok := child.(java.PlatformCompatConfigIntf); ok {
+					filesInfo = append(filesInfo, apexFileForCompatConfig(ctx, prebuilt, depName))
 				} else {
-					ctx.PropertyErrorf("prebuilts", "%q is not a prebuilt_etc module", depName)
+					ctx.PropertyErrorf("prebuilts", "%q is not a prebuilt_etc and not a platform_compat_config module", depName)
 				}
 			case testTag:
 				if ccTest, ok := child.(*cc.Module); ok {
@@ -1512,23 +2278,6 @@
 		return filesInfo[i].builtFile.String() < filesInfo[j].builtFile.String()
 	})
 
-	// check apex_available requirements
-	if !ctx.Host() && !a.testApex {
-		for _, fi := range filesInfo {
-			if am, ok := fi.module.(android.ApexModule); ok {
-				// vndk {enabled:true} implies visibility to the vndk apex
-				if ccm, ok := fi.module.(*cc.Module); ok && ccm.IsVndk() && a.vndkApex {
-					continue
-				}
-
-				if !am.AvailableFor(ctx.ModuleName()) && !whitelistedApexAvailable(ctx.ModuleName(), a.vndkApex, fi.module) {
-					ctx.ModuleErrorf("requires %q that is not available for the APEX", fi.module.Name())
-					// don't stop so that we can report other violations in the same run
-				}
-			}
-		}
-	}
-
 	a.installDir = android.PathForModuleInstall(ctx, "apex")
 	a.filesInfo = filesInfo
 
@@ -1572,22 +2321,31 @@
 	a.buildApexDependencyInfo(ctx)
 }
 
-func whitelistedApexAvailable(apex string, is_vndk bool, module android.Module) bool {
+func whitelistedApexAvailable(apex string, module android.Module) bool {
 	key := apex
 	key = strings.Replace(key, "test_", "", 1)
 	key = strings.Replace(key, "com.android.art.debug", "com.android.art", 1)
 	key = strings.Replace(key, "com.android.art.release", "com.android.art", 1)
 
 	moduleName := module.Name()
-	if strings.Contains(moduleName, "prebuilt_libclang_rt") {
-		// This module has variants that depend on the product being built.
-		moduleName = "prebuilt_libclang_rt"
+	// Prebuilt modules (e.g. java_import, etc.) have "prebuilt_" prefix added by the build
+	// system. Trim the prefix for the check since they are confusing
+	moduleName = strings.TrimPrefix(moduleName, "prebuilt_")
+	if strings.HasPrefix(moduleName, "libclang_rt.") {
+		// This module has many arch variants that depend on the product being built.
+		// We don't want to list them all
+		moduleName = "libclang_rt"
 	}
 
 	if val, ok := apexAvailWl[key]; ok && android.InList(moduleName, val) {
 		return true
 	}
 
+	key = "//any"
+	if val, ok := apexAvailWl[key]; ok && android.InList(moduleName, val) {
+		return true
+	}
+
 	return false
 }
 
diff --git a/apex/apex_test.go b/apex/apex_test.go
index c7ecbc9..508bde6 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -299,6 +299,7 @@
 	ctx.RegisterModuleType("vndk_prebuilt_shared", cc.VndkPrebuiltSharedFactory)
 	ctx.RegisterModuleType("vndk_libraries_txt", cc.VndkLibrariesTxtFactory)
 	ctx.RegisterModuleType("prebuilt_etc", android.PrebuiltEtcFactory)
+	ctx.RegisterModuleType("platform_compat_config", java.PlatformCompatConfigFactory)
 	ctx.RegisterModuleType("sh_binary", android.ShBinaryFactory)
 	ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
 	java.RegisterJavaBuildComponents(ctx)
@@ -468,6 +469,11 @@
 			sdk_version: "none",
 			system_modules: "none",
 			compile_dex: true,
+			// TODO: remove //apex_available:platform
+			apex_available: [
+				"//apex_available:platform",
+				"myapex",
+			],
 		}
 
 		java_library {
@@ -759,7 +765,7 @@
 	ensureNotContains(t, mylibLdFlags, "mylib3/android_arm64_armv8-a_shared_12_myapex/mylib3.so")
 
 	// Ensure that stubs libs are built without -include flags
-	mylib2Cflags := ctx.ModuleForTests("mylib2", "android_arm64_armv8-a_static_myapex").Rule("cc").Args["cFlags"]
+	mylib2Cflags := ctx.ModuleForTests("mylib2", "android_arm64_armv8-a_static").Rule("cc").Args["cFlags"]
 	ensureNotContains(t, mylib2Cflags, "-include ")
 
 	// Ensure that genstub is invoked with --apex
@@ -885,6 +891,7 @@
 			stubs: {
 				versions: ["10", "20", "30"],
 			},
+			apex_available: [ "myapex" ],
 		}
 
 		cc_library {
@@ -1572,6 +1579,7 @@
 			export_include_dirs: ["my_include"],
 			system_shared_libs: [],
 			stl: "none",
+			apex_available: [ "myapex" ],
 		}
 
 		cc_library {
@@ -2209,11 +2217,12 @@
 }
 
 func TestApexName(t *testing.T) {
-	ctx, _ := testApex(t, `
+	ctx, config := testApex(t, `
 		apex {
 			name: "myapex",
 			key: "myapex.key",
 			apex_name: "com.android.myapex",
+			native_shared_libs: ["mylib"],
 		}
 
 		apex_key {
@@ -2221,6 +2230,17 @@
 			public_key: "testkey.avbpubkey",
 			private_key: "testkey.pem",
 		}
+
+		cc_library {
+			name: "mylib",
+			srcs: ["mylib.cpp"],
+			system_shared_libs: [],
+			stl: "none",
+			apex_available: [
+				"//apex_available:platform",
+				"myapex",
+			],
+		}
 	`)
 
 	module := ctx.ModuleForTests("myapex", "android_common_myapex_image")
@@ -2228,6 +2248,16 @@
 	ensureContains(t, apexManifestRule.Args["opt"], "-v name com.android.myapex")
 	apexRule := module.Rule("apexRule")
 	ensureContains(t, apexRule.Args["opt_flags"], "--do_not_check_keyname")
+
+	apexBundle := ctx.ModuleForTests("myapex", "android_common_myapex_image").Module().(*apexBundle)
+	data := android.AndroidMkDataForTest(t, config, "", apexBundle)
+	name := apexBundle.BaseModuleName()
+	prefix := "TARGET_"
+	var builder strings.Builder
+	data.Custom(&builder, name, prefix, "", data)
+	androidMk := builder.String()
+	ensureContains(t, androidMk, "LOCAL_MODULE := mylib.myapex\n")
+	ensureNotContains(t, androidMk, "LOCAL_MODULE := mylib.com.android.myapex\n")
 }
 
 func TestNonTestApex(t *testing.T) {
@@ -3003,6 +3033,7 @@
 			srcs: ["mylib.cpp"],
 			stl: "none",
 			system_shared_libs: [],
+			apex_available: [ "myapex" ],
 		}
 	`)
 
@@ -3258,10 +3289,15 @@
 	}`)
 
 	// check that libfoo and libbar are created only for myapex, but not for the platform
-	ensureListContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_shared_myapex")
-	ensureListNotContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_shared")
-	ensureListContains(t, ctx.ModuleVariantsForTests("libbar"), "android_arm64_armv8-a_shared_myapex")
-	ensureListNotContains(t, ctx.ModuleVariantsForTests("libbar"), "android_arm64_armv8-a_shared")
+	// TODO(jiyong) the checks for the platform variant are removed because we now create
+	// the platform variant regardless of the apex_availability. Instead, we will make sure that
+	// the platform variants are not used from other platform modules. When that is done,
+	// these checks will be replaced by expecting a specific error message that will be
+	// emitted when the platform variant is used.
+	//	ensureListContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_shared_myapex")
+	//	ensureListNotContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_shared")
+	//	ensureListContains(t, ctx.ModuleVariantsForTests("libbar"), "android_arm64_armv8-a_shared_myapex")
+	//	ensureListNotContains(t, ctx.ModuleVariantsForTests("libbar"), "android_arm64_armv8-a_shared")
 
 	ctx, _ = testApex(t, `
 	apex {
@@ -3310,11 +3346,16 @@
 	}`)
 
 	// shared variant of libfoo is only available to myapex
-	ensureListContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_shared_myapex")
-	ensureListNotContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_shared")
-	// but the static variant is available to both myapex and the platform
-	ensureListContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_static_myapex")
-	ensureListContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_static")
+	// TODO(jiyong) the checks for the platform variant are removed because we now create
+	// the platform variant regardless of the apex_availability. Instead, we will make sure that
+	// the platform variants are not used from other platform modules. When that is done,
+	// these checks will be replaced by expecting a specific error message that will be
+	// emitted when the platform variant is used.
+	//	ensureListContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_shared_myapex")
+	//	ensureListNotContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_shared")
+	//	// but the static variant is available to both myapex and the platform
+	//	ensureListContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_static_myapex")
+	//	ensureListContains(t, ctx.ModuleVariantsForTests("libfoo"), "android_arm64_armv8-a_static")
 }
 
 func TestOverrideApex(t *testing.T) {
@@ -3447,8 +3488,44 @@
 		"etc/permissions/foo.xml",
 	})
 	// Permission XML should point to the activated path of impl jar of java_sdk_library
-	xml := ctx.ModuleForTests("foo", "android_common_myapex").Output("foo.xml")
-	ensureContains(t, xml.Args["content"], `<library name="foo" file="/apex/myapex/javalib/foo.jar"`)
+	sdkLibrary := ctx.ModuleForTests("foo", "android_common_myapex").Module().(*java.SdkLibrary)
+	xml := sdkLibrary.XmlPermissionsFileContent()
+	ensureContains(t, xml, `<library name="foo" file="/apex/myapex/javalib/foo.jar"`)
+}
+
+func TestCompatConfig(t *testing.T) {
+	ctx, _ := testApex(t, `
+		apex {
+			name: "myapex",
+			key: "myapex.key",
+			prebuilts: ["myjar-platform-compat-config"],
+			java_libs: ["myjar"],
+		}
+
+		apex_key {
+			name: "myapex.key",
+			public_key: "testkey.avbpubkey",
+			private_key: "testkey.pem",
+		}
+
+		platform_compat_config {
+		    name: "myjar-platform-compat-config",
+		    src: ":myjar",
+		}
+
+		java_library {
+			name: "myjar",
+			srcs: ["foo/bar/MyClass.java"],
+			sdk_version: "none",
+			system_modules: "none",
+			compile_dex: true,
+			apex_available: [ "myapex" ],
+		}
+	`)
+	ensureExactContents(t, ctx, "myapex", "android_common_myapex_image", []string{
+		"etc/compatconfig/myjar-platform-compat-config.xml",
+		"javalib/myjar.jar",
+	})
 }
 
 func TestRejectNonInstallableJavaLibrary(t *testing.T) {
diff --git a/apex/builder.go b/apex/builder.go
index 53f39a6..e267e49 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -239,7 +239,7 @@
 	rule.Command().
 		Implicit(builtApex).
 		Text("(cd " + imageDir.String() + " ; ").
-		Text("find . -type f -printf \"%s %p\\n\") ").
+		Text("find . \\( -type f -o -type l \\) -printf \"%s %p\\n\") ").
 		Text(" | sort -nr > ").
 		Output(output)
 	rule.Build(pctx, ctx, "installed-files."+a.Name(), "Installed files")
@@ -508,13 +508,13 @@
 	// instead of `android.PathForOutput`) to return the correct path to the flattened
 	// APEX (as its contents is installed by Make, not Soong).
 	factx := flattenedApexContext{ctx}
-	apexName := proptools.StringDefault(a.properties.Apex_name, ctx.ModuleName())
-	a.outputFile = android.PathForModuleInstall(&factx, "apex", apexName)
+	apexBundleName := a.Name()
+	a.outputFile = android.PathForModuleInstall(&factx, "apex", apexBundleName)
 
 	if a.installable() && a.GetOverriddenBy() == "" {
-		installPath := android.PathForModuleInstall(ctx, "apex", apexName)
+		installPath := android.PathForModuleInstall(ctx, "apex", apexBundleName)
 		devicePath := android.InstallPathToOnDevicePath(ctx, installPath)
-		addFlattenedFileContextsInfos(ctx, apexName+":"+devicePath+":"+a.fileContexts.String())
+		addFlattenedFileContextsInfos(ctx, apexBundleName+":"+devicePath+":"+a.fileContexts.String())
 	}
 	a.buildFilesInfo(ctx)
 }
@@ -550,9 +550,9 @@
 		a.filesInfo = append(a.filesInfo, newApexFile(ctx, copiedPubkey, "apex_pubkey", ".", etc, nil))
 
 		if a.properties.ApexType == flattenedApex {
-			apexName := proptools.StringDefault(a.properties.Apex_name, a.Name())
+			apexBundleName := a.Name()
 			for _, fi := range a.filesInfo {
-				dir := filepath.Join("apex", apexName, fi.installDir)
+				dir := filepath.Join("apex", apexBundleName, fi.installDir)
 				target := ctx.InstallFile(android.PathForModuleInstall(ctx, dir), fi.builtFile.Base(), fi.builtFile)
 				for _, sym := range fi.symlinks {
 					ctx.InstallSymlink(android.PathForModuleInstall(ctx, dir), sym, target)
diff --git a/cc/cc.go b/cc/cc.go
index ce3a2ed..2e55841 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -1266,8 +1266,11 @@
 	allTransitiveDeps := make(map[android.Path][]android.Path, len(staticDeps))
 	staticDepFiles := []android.Path{}
 	for _, dep := range staticDeps {
-		allTransitiveDeps[dep.OutputFile().Path()] = dep.GetDepsInLinkOrder()
-		staticDepFiles = append(staticDepFiles, dep.OutputFile().Path())
+		// The OutputFile may not be valid for a variant not present, and the AllowMissingDependencies flag is set.
+		if dep.OutputFile().Valid() {
+			allTransitiveDeps[dep.OutputFile().Path()] = dep.GetDepsInLinkOrder()
+			staticDepFiles = append(staticDepFiles, dep.OutputFile().Path())
+		}
 	}
 	sharedDepFiles := []android.Path{}
 	for _, sharedDep := range sharedDeps {
@@ -1777,6 +1780,9 @@
 
 	for _, lib := range deps.SharedLibs {
 		depTag := SharedDepTag
+		if c.static() {
+			depTag = SharedFromStaticDepTag
+		}
 		if inList(lib, deps.ReexportSharedLibHeaders) {
 			depTag = sharedExportDepTag
 		}
@@ -2194,7 +2200,7 @@
 		depFile := android.OptionalPath{}
 
 		switch depTag {
-		case ndkStubDepTag, SharedDepTag, sharedExportDepTag:
+		case ndkStubDepTag, SharedDepTag, SharedFromStaticDepTag, sharedExportDepTag:
 			ptr = &depPaths.SharedLibs
 			depPtr = &depPaths.SharedLibsDeps
 			depFile = ccDep.Toc()
@@ -2547,9 +2553,17 @@
 
 func (c *Module) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
 	if depTag, ok := ctx.OtherModuleDependencyTag(dep).(DependencyTag); ok {
-		if cc, ok := dep.(*Module); ok && cc.IsStubs() && depTag.Shared {
-			// dynamic dep to a stubs lib crosses APEX boundary
-			return false
+		if cc, ok := dep.(*Module); ok {
+			if cc.HasStubsVariants() && depTag.Shared && depTag.Library {
+				// dynamic dep to a stubs lib crosses APEX boundary
+				return false
+			}
+			if depTag.FromStatic {
+				// shared_lib dependency from a static lib is considered as crossing
+				// the APEX boundary because the dependency doesn't actually is
+				// linked; the dependency is used only during the compilation phase.
+				return false
+			}
 		}
 	}
 	return true
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 332cc45..c105954 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -2751,3 +2751,42 @@
 		t.Errorf("libboth ar rule wanted %q, got %q", w, g)
 	}
 }
+
+func TestProductVariableDefaults(t *testing.T) {
+	bp := `
+		cc_defaults {
+			name: "libfoo_defaults",
+			srcs: ["foo.c"],
+			cppflags: ["-DFOO"],
+			product_variables: {
+				debuggable: {
+					cppflags: ["-DBAR"],
+				},
+			},
+		}
+
+		cc_library {
+			name: "libfoo",
+			defaults: ["libfoo_defaults"],
+		}
+	`
+
+	config := TestConfig(buildDir, android.Android, nil, bp, nil)
+	config.TestProductVariables.Debuggable = BoolPtr(true)
+
+	ctx := CreateTestContext()
+	ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
+		ctx.BottomUp("variable", android.VariableMutator).Parallel()
+	})
+	ctx.Register(config)
+
+	_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
+	android.FailIfErrored(t, errs)
+	_, errs = ctx.PrepareBuildActions(config)
+	android.FailIfErrored(t, errs)
+
+	libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_static").Module().(*Module)
+	if !android.InList("-DBAR", libfoo.flags.Local.CppFlags) {
+		t.Errorf("expected -DBAR in cppflags, got %q", libfoo.flags.Local.CppFlags)
+	}
+}
diff --git a/cc/config/vndk.go b/cc/config/vndk.go
index 52bd9f0..5cecbd6 100644
--- a/cc/config/vndk.go
+++ b/cc/config/vndk.go
@@ -18,48 +18,11 @@
 // For these libraries, the vendor variants must be installed even if the device
 // has VndkUseCoreVariant set.
 var VndkMustUseVendorVariantList = []string{
-	"android.hardware.automotive.evs@1.0",
-	"android.hardware.automotive.vehicle@2.0",
-	"android.hardware.broadcastradio@2.0",
-	"android.hardware.camera.device@1.0",
-	"android.hardware.camera.device@3.2",
-	"android.hardware.camera.device@3.3",
-	"android.hardware.camera.device@3.4",
-	"android.hardware.camera.provider@2.4",
-	"android.hardware.fastboot@1.0",
-	"android.hardware.media.bufferpool@1.0",
-	"android.hardware.neuralnetworks@1.0",
-	"android.hardware.neuralnetworks@1.1",
-	"android.hardware.neuralnetworks@1.2",
-	"android.hardware.neuralnetworks@1.3",
+	"android.hardware.light-ndk_platform",
 	"android.hardware.nfc@1.2",
-	"android.hardware.oemlock@1.0",
-	"android.hardware.power.stats@1.0",
 	"android.hardware.power-ndk_platform",
-	"android.hardware.power@1.0",
-	"android.hardware.power@1.1",
-	"android.hardware.radio@1.4",
-	"android.hardware.secure_element@1.0",
-	"android.hardware.sensors@1.0",
-	"android.hardware.soundtrigger@2.0",
-	"android.hardware.soundtrigger@2.0-core",
-	"android.hardware.soundtrigger@2.1",
-	"android.hardware.tetheroffload.config@1.0",
-	"android.hardware.tetheroffload.control@1.0",
 	"android.hardware.vibrator-ndk_platform",
-	"android.hardware.weaver@1.0",
-	"android.hardware.wifi.hostapd@1.0",
-	"android.hardware.wifi.offload@1.0",
-	"android.hardware.wifi.supplicant@1.0",
-	"android.hardware.wifi.supplicant@1.1",
-	"android.hardware.wifi@1.1",
-	"android.hardware.wifi@1.2",
-	"android.hardwareundtrigger@2.0",
-	"android.hardwareundtrigger@2.0-core",
-	"android.hardwareundtrigger@2.1",
-	"libaudioroute",
 	"libbinder",
-	"libcamera_metadata",
 	"libcrypto",
 	"libexpat",
 	"libgatekeeper",
@@ -68,45 +31,17 @@
 	"libkeymaster_messages",
 	"libkeymaster_portable",
 	"libmedia_omx",
-	"libprotobuf-cpp-full",
-	"libprotobuf-cpp-lite",
 	"libpuresoftkeymasterdevice",
 	"libselinux",
 	"libsoftkeymasterdevice",
 	"libsqlite",
 	"libssl",
-	"libstagefright_amrnb_common",
 	"libstagefright_bufferpool@2.0",
 	"libstagefright_bufferqueue_helper",
-	"libstagefright_enc_common",
-	"libstagefright_flacdec",
 	"libstagefright_foundation",
 	"libstagefright_omx",
 	"libstagefright_omx_utils",
-	"libstagefright_soft_aacdec",
-	"libstagefright_soft_aacenc",
-	"libstagefright_soft_amrdec",
-	"libstagefright_soft_amrnbenc",
-	"libstagefright_soft_amrwbenc",
-	"libstagefright_soft_avcdec",
-	"libstagefright_soft_avcenc",
-	"libstagefright_soft_flacdec",
-	"libstagefright_soft_flacenc",
-	"libstagefright_soft_g711dec",
-	"libstagefright_soft_gsmdec",
-	"libstagefright_soft_hevcdec",
-	"libstagefright_soft_mp3dec",
-	"libstagefright_soft_mpeg2dec",
-	"libstagefright_soft_mpeg4dec",
-	"libstagefright_soft_mpeg4enc",
-	"libstagefright_soft_opusdec",
-	"libstagefright_soft_rawdec",
-	"libstagefright_soft_vorbisdec",
-	"libstagefright_soft_vpxdec",
-	"libstagefright_soft_vpxenc",
 	"libstagefright_xmlparser",
 	"libui",
-	"libvorbisidec",
 	"libxml2",
-	"libyuv",
 }
diff --git a/cc/library_sdk_member.go b/cc/library_sdk_member.go
index fd5a4da..165901d 100644
--- a/cc/library_sdk_member.go
+++ b/cc/library_sdk_member.go
@@ -241,39 +241,43 @@
 
 func (info *nativeLibInfo) generatePrebuiltLibrary(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, member android.SdkMember) {
 
-	// a function for emitting include dirs
-	addExportedDirsForNativeLibs := func(lib nativeLibInfoProperties, properties android.BpPropertySet, systemInclude bool) {
-		includeDirs := nativeIncludeDirPathsFor(lib, systemInclude)
-		if len(includeDirs) == 0 {
-			return
-		}
-		var propertyName string
-		if !systemInclude {
-			propertyName = "export_include_dirs"
-		} else {
-			propertyName = "export_system_include_dirs"
-		}
-		properties.AddProperty(propertyName, includeDirs)
-	}
-
 	pbm := builder.AddPrebuiltModule(member, info.memberType.prebuiltModuleType)
 
-	addExportedDirsForNativeLibs(info.commonProperties, pbm, false /*systemInclude*/)
-	addExportedDirsForNativeLibs(info.commonProperties, pbm, true /*systemInclude*/)
+	addPossiblyArchSpecificProperties(info.commonProperties, pbm)
 
 	archProperties := pbm.AddPropertySet("arch")
 	for _, av := range info.archVariantProperties {
 		archTypeProperties := archProperties.AddPropertySet(av.archType)
+		// Add any arch specific properties inside the appropriate arch: {<arch>: {...}} block
 		archTypeProperties.AddProperty("srcs", []string{nativeLibraryPathFor(av)})
 
-		// export_* properties are added inside the arch: {<arch>: {...}} block
-		addExportedDirsForNativeLibs(av, archTypeProperties, false /*systemInclude*/)
-		addExportedDirsForNativeLibs(av, archTypeProperties, true /*systemInclude*/)
+		addPossiblyArchSpecificProperties(av, archTypeProperties)
 	}
 	pbm.AddProperty("stl", "none")
 	pbm.AddProperty("system_shared_libs", []string{})
 }
 
+// Add properties that may, or may not, be arch specific.
+func addPossiblyArchSpecificProperties(libInfo nativeLibInfoProperties, outputProperties android.BpPropertySet) {
+	addExportedDirsForNativeLibs(libInfo, outputProperties, false /*systemInclude*/)
+	addExportedDirsForNativeLibs(libInfo, outputProperties, true /*systemInclude*/)
+}
+
+// a function for emitting include dirs
+func addExportedDirsForNativeLibs(lib nativeLibInfoProperties, properties android.BpPropertySet, systemInclude bool) {
+	includeDirs := nativeIncludeDirPathsFor(lib, systemInclude)
+	if len(includeDirs) == 0 {
+		return
+	}
+	var propertyName string
+	if !systemInclude {
+		propertyName = "export_include_dirs"
+	} else {
+		propertyName = "export_system_include_dirs"
+	}
+	properties.AddProperty(propertyName, includeDirs)
+}
+
 const (
 	nativeIncludeDir          = "include"
 	nativeGeneratedIncludeDir = "include_gen"
diff --git a/cc/linkable.go b/cc/linkable.go
index 3c46d9d..2abb112 100644
--- a/cc/linkable.go
+++ b/cc/linkable.go
@@ -67,12 +67,17 @@
 	ReexportFlags bool
 
 	ExplicitlyVersioned bool
+
+	FromStatic bool
 }
 
 var (
 	SharedDepTag = DependencyTag{Name: "shared", Library: true, Shared: true}
 	StaticDepTag = DependencyTag{Name: "static", Library: true}
 
+	// Same as SharedDepTag, but from a static lib
+	SharedFromStaticDepTag = DependencyTag{Name: "shared from static", Library: true, Shared: true, FromStatic: true}
+
 	CrtBeginDepTag = DependencyTag{Name: "crtbegin"}
 	CrtEndDepTag   = DependencyTag{Name: "crtend"}
 )
diff --git a/dexpreopt/config.go b/dexpreopt/config.go
index 2a929c5..e353878 100644
--- a/dexpreopt/config.go
+++ b/dexpreopt/config.go
@@ -30,8 +30,7 @@
 
 	OnlyPreoptBootImageAndSystemServer bool // only preopt jars in the boot image or system server
 
-	GenerateApexImage bool // generate an extra boot image only containing jars from the runtime apex
-	UseApexImage      bool // use the apex image by default
+	UseArtImage bool // use the art image (use other boot class path dex files without image)
 
 	HasSystemOther        bool     // store odex files that match PatternsOnSystemOther on the system_other partition
 	PatternsOnSystemOther []string // patterns (using '%' to denote a prefix match) to put odex on the system_other partition
diff --git a/java/aapt2.go b/java/aapt2.go
index cfe0dea..04e4de5 100644
--- a/java/aapt2.go
+++ b/java/aapt2.go
@@ -147,10 +147,16 @@
 		RspfileContent: "$in",
 	})
 
+var mergeAssetsRule = pctx.AndroidStaticRule("mergeAssets",
+	blueprint.RuleParams{
+		Command:     `${config.MergeZipsCmd} ${out} ${in}`,
+		CommandDeps: []string{"${config.MergeZipsCmd}"},
+	})
+
 func aapt2Link(ctx android.ModuleContext,
 	packageRes, genJar, proguardOptions, rTxt, extraPackages android.WritablePath,
 	flags []string, deps android.Paths,
-	compiledRes, compiledOverlay android.Paths, splitPackages android.WritablePaths) {
+	compiledRes, compiledOverlay, assetPackages android.Paths, splitPackages android.WritablePaths) {
 
 	genDir := android.PathForModuleGen(ctx, "aapt2", "R")
 
@@ -186,12 +192,25 @@
 	}
 
 	implicitOutputs := append(splitPackages, proguardOptions, genJar, rTxt, extraPackages)
+	linkOutput := packageRes
+
+	// AAPT2 ignores assets in overlays. Merge them after linking.
+	if len(assetPackages) > 0 {
+		linkOutput = android.PathForModuleOut(ctx, "aapt2", "package-res.apk")
+		inputZips := append(android.Paths{linkOutput}, assetPackages...)
+		ctx.Build(pctx, android.BuildParams{
+			Rule:        mergeAssetsRule,
+			Inputs:      inputZips,
+			Output:      packageRes,
+			Description: "merge assets from dependencies",
+		})
+	}
 
 	ctx.Build(pctx, android.BuildParams{
 		Rule:            aapt2LinkRule,
 		Description:     "aapt2 link",
 		Implicits:       deps,
-		Output:          packageRes,
+		Output:          linkOutput,
 		ImplicitOutputs: implicitOutputs,
 		Args: map[string]string{
 			"flags":           strings.Join(flags, " "),
diff --git a/java/aar.go b/java/aar.go
index d707e36..24c5e7d 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -32,6 +32,7 @@
 	ExportedRRODirs() []rroDir
 	ExportedStaticPackages() android.Paths
 	ExportedManifests() android.Paths
+	ExportedAssets() android.OptionalPath
 }
 
 func init() {
@@ -93,6 +94,7 @@
 	extraAaptPackagesFile   android.Path
 	mergedManifestFile      android.Path
 	noticeFile              android.OptionalPath
+	assetPackage            android.OptionalPath
 	isLibrary               bool
 	useEmbeddedNativeLibs   bool
 	useEmbeddedDex          bool
@@ -124,6 +126,10 @@
 	return a.transitiveManifestPaths
 }
 
+func (a *aapt) ExportedAssets() android.OptionalPath {
+	return a.assetPackage
+}
+
 func (a *aapt) aapt2Flags(ctx android.ModuleContext, sdkContext sdkContext,
 	manifestPath android.Path) (compileFlags, linkFlags []string, linkDeps android.Paths,
 	resDirs, overlayDirs []globbedResourceDir, rroDirs []rroDir, resZips android.Paths) {
@@ -219,9 +225,15 @@
 	}
 }
 
+var extractAssetsRule = pctx.AndroidStaticRule("extractAssets",
+	blueprint.RuleParams{
+		Command:     `${config.Zip2ZipCmd} -i ${in} -o ${out} "assets/**/*"`,
+		CommandDeps: []string{"${config.Zip2ZipCmd}"},
+	})
+
 func (a *aapt) buildActions(ctx android.ModuleContext, sdkContext sdkContext, extraLinkFlags ...string) {
 
-	transitiveStaticLibs, transitiveStaticLibManifests, staticRRODirs, libDeps, libFlags, sdkLibraries :=
+	transitiveStaticLibs, transitiveStaticLibManifests, staticRRODirs, assetPackages, libDeps, libFlags, sdkLibraries :=
 		aaptLibs(ctx, sdkContext)
 
 	// App manifest file
@@ -321,7 +333,20 @@
 	}
 
 	aapt2Link(ctx, packageRes, srcJar, proguardOptionsFile, rTxt, extraPackages,
-		linkFlags, linkDeps, compiledRes, compiledOverlay, splitPackages)
+		linkFlags, linkDeps, compiledRes, compiledOverlay, assetPackages, splitPackages)
+
+	// Extract assets from the resource package output so that they can be used later in aapt2link
+	// for modules that depend on this one.
+	if android.PrefixedStringInList(linkFlags, "-A ") || len(assetPackages) > 0 {
+		assets := android.PathForModuleOut(ctx, "assets.zip")
+		ctx.Build(pctx, android.BuildParams{
+			Rule:        extractAssetsRule,
+			Input:       packageRes,
+			Output:      assets,
+			Description: "extract assets from built resource file",
+		})
+		a.assetPackage = android.OptionalPathForPath(assets)
+	}
 
 	a.aaptSrcJar = srcJar
 	a.exportPackage = packageRes
@@ -335,7 +360,7 @@
 
 // aaptLibs collects libraries from dependencies and sdk_version and converts them into paths
 func aaptLibs(ctx android.ModuleContext, sdkContext sdkContext) (transitiveStaticLibs, transitiveStaticLibManifests android.Paths,
-	staticRRODirs []rroDir, deps android.Paths, flags []string, sdkLibraries []string) {
+	staticRRODirs []rroDir, assets, deps android.Paths, flags []string, sdkLibraries []string) {
 
 	var sharedLibs android.Paths
 
@@ -373,6 +398,9 @@
 				transitiveStaticLibs = append(transitiveStaticLibs, exportPackage)
 				transitiveStaticLibManifests = append(transitiveStaticLibManifests, aarDep.ExportedManifests()...)
 				sdkLibraries = append(sdkLibraries, aarDep.ExportedSdkLibs()...)
+				if aarDep.ExportedAssets().Valid() {
+					assets = append(assets, aarDep.ExportedAssets().Path())
+				}
 
 			outer:
 				for _, d := range aarDep.ExportedRRODirs() {
@@ -402,7 +430,7 @@
 	transitiveStaticLibManifests = android.FirstUniquePaths(transitiveStaticLibManifests)
 	sdkLibraries = android.FirstUniqueStrings(sdkLibraries)
 
-	return transitiveStaticLibs, transitiveStaticLibManifests, staticRRODirs, deps, flags, sdkLibraries
+	return transitiveStaticLibs, transitiveStaticLibManifests, staticRRODirs, assets, deps, flags, sdkLibraries
 }
 
 type AndroidLibrary struct {
@@ -572,6 +600,11 @@
 	return android.Paths{a.manifest}
 }
 
+// TODO(jungjw): Decide whether we want to implement this.
+func (a *AARImport) ExportedAssets() android.OptionalPath {
+	return android.OptionalPath{}
+}
+
 func (a *AARImport) Prebuilt() *android.Prebuilt {
 	return &a.prebuilt
 }
@@ -660,7 +693,7 @@
 	linkFlags = append(linkFlags, "--manifest "+a.manifest.String())
 	linkDeps = append(linkDeps, a.manifest)
 
-	transitiveStaticLibs, staticLibManifests, staticRRODirs, libDeps, libFlags, sdkLibraries :=
+	transitiveStaticLibs, staticLibManifests, staticRRODirs, transitiveAssets, libDeps, libFlags, sdkLibraries :=
 		aaptLibs(ctx, sdkContext(a))
 
 	_ = staticLibManifests
@@ -673,7 +706,7 @@
 	overlayRes := append(android.Paths{flata}, transitiveStaticLibs...)
 
 	aapt2Link(ctx, a.exportPackage, srcJar, proguardOptionsFile, rTxt, a.extraAaptPackagesFile,
-		linkFlags, linkDeps, nil, overlayRes, nil)
+		linkFlags, linkDeps, nil, overlayRes, transitiveAssets, nil)
 }
 
 var _ Dependency = (*AARImport)(nil)
diff --git a/java/app.go b/java/app.go
index 6e0ffeb..9503ec4 100755
--- a/java/app.go
+++ b/java/app.go
@@ -583,6 +583,13 @@
 	return String(a.overridableAppProperties.Certificate)
 }
 
+func (a *AndroidApp) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
+	if IsJniDepTag(ctx.OtherModuleDependencyTag(dep)) {
+		return true
+	}
+	return a.Library.DepIsInSameApex(ctx, dep)
+}
+
 // For OutputFileProducer interface
 func (a *AndroidApp) OutputFiles(tag string) (android.Paths, error) {
 	switch tag {
diff --git a/java/app_test.go b/java/app_test.go
index c20a8e7..c86b038 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -323,6 +323,107 @@
 	}
 }
 
+func TestLibraryAssets(t *testing.T) {
+	bp := `
+			android_app {
+				name: "foo",
+				sdk_version: "current",
+				static_libs: ["lib1", "lib2", "lib3"],
+			}
+
+			android_library {
+				name: "lib1",
+				sdk_version: "current",
+				asset_dirs: ["assets_a"],
+			}
+
+			android_library {
+				name: "lib2",
+				sdk_version: "current",
+			}
+
+			android_library {
+				name: "lib3",
+				sdk_version: "current",
+				static_libs: ["lib4"],
+			}
+
+			android_library {
+				name: "lib4",
+				sdk_version: "current",
+				asset_dirs: ["assets_b"],
+			}
+		`
+
+	testCases := []struct {
+		name          string
+		assetFlag     string
+		assetPackages []string
+	}{
+		{
+			name: "foo",
+			// lib1 has its own asset. lib3 doesn't have any, but provides lib4's transitively.
+			assetPackages: []string{
+				buildDir + "/.intermediates/foo/android_common/aapt2/package-res.apk",
+				buildDir + "/.intermediates/lib1/android_common/assets.zip",
+				buildDir + "/.intermediates/lib3/android_common/assets.zip",
+			},
+		},
+		{
+			name:      "lib1",
+			assetFlag: "-A assets_a",
+		},
+		{
+			name: "lib2",
+		},
+		{
+			name: "lib3",
+			assetPackages: []string{
+				buildDir + "/.intermediates/lib3/android_common/aapt2/package-res.apk",
+				buildDir + "/.intermediates/lib4/android_common/assets.zip",
+			},
+		},
+		{
+			name:      "lib4",
+			assetFlag: "-A assets_b",
+		},
+	}
+	ctx := testApp(t, bp)
+
+	for _, test := range testCases {
+		t.Run(test.name, func(t *testing.T) {
+			m := ctx.ModuleForTests(test.name, "android_common")
+
+			// Check asset flag in aapt2 link flags
+			var aapt2link android.TestingBuildParams
+			if len(test.assetPackages) > 0 {
+				aapt2link = m.Output("aapt2/package-res.apk")
+			} else {
+				aapt2link = m.Output("package-res.apk")
+			}
+			aapt2Flags := aapt2link.Args["flags"]
+			if test.assetFlag != "" {
+				if !strings.Contains(aapt2Flags, test.assetFlag) {
+					t.Errorf("Can't find asset flag %q in aapt2 link flags %q", test.assetFlag, aapt2Flags)
+				}
+			} else {
+				if strings.Contains(aapt2Flags, " -A ") {
+					t.Errorf("aapt2 link flags %q contain unexpected asset flag", aapt2Flags)
+				}
+			}
+
+			// Check asset merge rule.
+			if len(test.assetPackages) > 0 {
+				mergeAssets := m.Output("package-res.apk")
+				if !reflect.DeepEqual(test.assetPackages, mergeAssets.Inputs.Strings()) {
+					t.Errorf("Unexpected mergeAssets inputs: %v, expected: %v",
+						mergeAssets.Inputs.Strings(), test.assetPackages)
+				}
+			}
+		})
+	}
+}
+
 func TestAndroidResources(t *testing.T) {
 	testCases := []struct {
 		name                       string
diff --git a/java/dexpreopt.go b/java/dexpreopt.go
index da68660..c81e199 100644
--- a/java/dexpreopt.go
+++ b/java/dexpreopt.go
@@ -106,8 +106,10 @@
 
 	global := dexpreoptGlobalConfig(ctx)
 	bootImage := defaultBootImageConfig(ctx)
-	if global.UseApexImage {
-		bootImage = frameworkJZBootImageConfig(ctx)
+	dexFiles := bootImage.dexPathsDeps.Paths()
+	dexLocations := bootImage.dexLocationsDeps
+	if global.UseArtImage {
+		bootImage = artBootImageConfig(ctx)
 	}
 
 	var archs []android.ArchType
@@ -178,8 +180,8 @@
 		DexPreoptImagesDeps:     imagesDeps,
 		DexPreoptImageLocations: bootImage.imageLocations,
 
-		PreoptBootClassPathDexFiles:     bootImage.dexPathsDeps.Paths(),
-		PreoptBootClassPathDexLocations: bootImage.dexLocationsDeps,
+		PreoptBootClassPathDexFiles:     dexFiles,
+		PreoptBootClassPathDexLocations: dexLocations,
 
 		PreoptExtractedApk: false,
 
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index 87f6d5e..607a437 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -197,13 +197,6 @@
 	// Include dexpreopt files for the primary boot image.
 	files := artBootImageConfig(ctx).imagesDeps
 
-	// For JIT-zygote config, also include dexpreopt files for the primary JIT-zygote image.
-	if dexpreoptGlobalConfig(ctx).UseApexImage {
-		for arch, paths := range artJZBootImageConfig(ctx).imagesDeps {
-			files[arch] = append(files[arch], paths...)
-		}
-	}
-
 	return files
 }
 
@@ -232,11 +225,6 @@
 	d.defaultBootImage = buildBootImage(ctx, defaultBootImageConfig(ctx))
 	// Create boot image for the ART apex (build artifacts are accessed via the global boot image config).
 	d.otherImages = append(d.otherImages, buildBootImage(ctx, artBootImageConfig(ctx)))
-	if global.GenerateApexImage {
-		// Create boot images for the JIT-zygote experiment.
-		d.otherImages = append(d.otherImages, buildBootImage(ctx, artJZBootImageConfig(ctx)))
-		d.otherImages = append(d.otherImages, buildBootImage(ctx, frameworkJZBootImageConfig(ctx)))
-	}
 
 	dumpOatRules(ctx, d.defaultBootImage)
 }
diff --git a/java/dexpreopt_config.go b/java/dexpreopt_config.go
index 637a32f..4c9add8 100644
--- a/java/dexpreopt_config.go
+++ b/java/dexpreopt_config.go
@@ -125,8 +125,6 @@
 	bootImageConfigKey       = android.NewOnceKey("bootImageConfig")
 	artBootImageName         = "art"
 	frameworkBootImageName   = "boot"
-	artJZBootImageName       = "jitzygote-art"
-	frameworkJZBootImageName = "jitzygote-boot"
 )
 
 // Construct the global boot image configs.
@@ -180,33 +178,9 @@
 			dexLocationsDeps: append(artLocations, frameworkLocations...),
 		}
 
-		// ART config for JIT-zygote boot image.
-		artJZCfg := bootImageConfig{
-			extension:        false,
-			name:             artJZBootImageName,
-			stem:             "apex",
-			installSubdir:    artSubdir,
-			modules:          artModules,
-			dexLocations:     artLocations,
-			dexLocationsDeps: artLocations,
-		}
-
-		// Framework config for JIT-zygote boot image extension.
-		frameworkJZCfg := bootImageConfig{
-			extension:        true,
-			name:             frameworkJZBootImageName,
-			stem:             "apex",
-			installSubdir:    frameworkSubdir,
-			modules:          frameworkModules,
-			dexLocations:     frameworkLocations,
-			dexLocationsDeps: append(artLocations, frameworkLocations...),
-		}
-
 		configs := map[string]*bootImageConfig{
 			artBootImageName:         &artCfg,
 			frameworkBootImageName:   &frameworkCfg,
-			artJZBootImageName:       &artJZCfg,
-			frameworkJZBootImageName: &frameworkJZCfg,
 		}
 
 		// common to all configs
@@ -249,11 +223,6 @@
 		frameworkCfg.primaryImages = artCfg.images
 		frameworkCfg.imageLocations = append(artCfg.imageLocations, frameworkCfg.imageLocations...)
 
-		// specific to the jitzygote-framework config
-		frameworkJZCfg.dexPathsDeps = append(artJZCfg.dexPathsDeps, frameworkJZCfg.dexPathsDeps...)
-		frameworkJZCfg.primaryImages = artJZCfg.images
-		frameworkJZCfg.imageLocations = append(artJZCfg.imageLocations, frameworkJZCfg.imageLocations...)
-
 		return configs
 	}).(map[string]*bootImageConfig)
 }
@@ -266,14 +235,6 @@
 	return *genBootImageConfigs(ctx)[frameworkBootImageName]
 }
 
-func artJZBootImageConfig(ctx android.PathContext) bootImageConfig {
-	return *genBootImageConfigs(ctx)[artJZBootImageName]
-}
-
-func frameworkJZBootImageConfig(ctx android.PathContext) bootImageConfig {
-	return *genBootImageConfigs(ctx)[frameworkJZBootImageName]
-}
-
 func defaultBootclasspath(ctx android.PathContext) []string {
 	return ctx.Config().OnceStringSlice(defaultBootclasspathKey, func() []string {
 		global := dexpreoptGlobalConfig(ctx)
diff --git a/java/droiddoc.go b/java/droiddoc.go
index 098400b..959f1c7 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -534,6 +534,9 @@
 		ctx.AddMissingDependencies(sdkDep.java9Classpath)
 	} else if sdkDep.useFiles {
 		deps.bootClasspath = append(deps.bootClasspath, sdkDep.jars...)
+		deps.aidlPreprocess = sdkDep.aidl
+	} else {
+		deps.aidlPreprocess = sdkDep.aidl
 	}
 
 	ctx.VisitDirectDeps(func(module android.Module) {
diff --git a/java/java.go b/java/java.go
index ed3dca9..dd44d06 100644
--- a/java/java.go
+++ b/java/java.go
@@ -37,14 +37,7 @@
 	RegisterJavaBuildComponents(android.InitRegistrationContext)
 
 	// Register sdk member types.
-	android.RegisterSdkMemberType(&headerLibrarySdkMemberType{
-		librarySdkMemberType{
-			android.SdkMemberTypeBase{
-				PropertyName: "java_header_libs",
-				SupportsSdk:  true,
-			},
-		},
-	})
+	android.RegisterSdkMemberType(javaHeaderLibsSdkMemberType)
 
 	android.RegisterSdkMemberType(&implLibrarySdkMemberType{
 		librarySdkMemberType{
@@ -757,9 +750,12 @@
 type linkType int
 
 const (
+	// TODO(jiyong) rename these for better readability. Make the allowed
+	// and disallowed link types explicit
 	javaCore linkType = iota
 	javaSdk
 	javaSystem
+	javaModule
 	javaPlatform
 )
 
@@ -789,6 +785,10 @@
 		return javaSdk, true
 	case ver.kind == sdkPublic:
 		return javaSdk, false
+	case name == "android_module_lib_stubs_current":
+		return javaModule, true
+	case ver.kind == sdkModule:
+		return javaModule, false
 	case ver.kind == sdkPrivate || ver.kind == sdkNone || ver.kind == sdkCorePlatform:
 		return javaPlatform, false
 	case !ver.valid():
@@ -824,11 +824,17 @@
 		}
 		break
 	case javaSystem:
-		if otherLinkType == javaPlatform {
+		if otherLinkType == javaPlatform || otherLinkType == javaModule {
 			ctx.ModuleErrorf("compiles against system API, but dependency %q is compiling against private API."+commonMessage,
 				ctx.OtherModuleName(to))
 		}
 		break
+	case javaModule:
+		if otherLinkType == javaPlatform {
+			ctx.ModuleErrorf("compiles against module API, but dependency %q is compiling against private API."+commonMessage,
+				ctx.OtherModuleName(to))
+		}
+		break
 	case javaPlatform:
 		// no restriction on link-type
 		break
@@ -1704,8 +1710,10 @@
 
 func (j *Module) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
 	depTag := ctx.OtherModuleDependencyTag(dep)
-	// dependencies other than the static linkage are all considered crossing APEX boundary
-	return depTag == staticLibTag
+	// Dependencies other than the static linkage are all considered crossing APEX boundary
+	// Also, a dependency to an sdk member is also considered as such. This is required because
+	// sdk members should be mutated into APEXes. Refer to sdk.sdkDepsReplaceMutator.
+	return depTag == staticLibTag || j.IsInAnySdk()
 }
 
 func (j *Module) Stem() string {
@@ -1834,6 +1842,15 @@
 	module.AddProperty("jars", []string{snapshotRelativeJavaLibPath})
 }
 
+var javaHeaderLibsSdkMemberType android.SdkMemberType = &headerLibrarySdkMemberType{
+	librarySdkMemberType{
+		android.SdkMemberTypeBase{
+			PropertyName: "java_header_libs",
+			SupportsSdk:  true,
+		},
+	},
+}
+
 type headerLibrarySdkMemberType struct {
 	librarySdkMemberType
 }
@@ -2393,6 +2410,14 @@
 	return nil, nil
 }
 
+func (j *Import) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
+	depTag := ctx.OtherModuleDependencyTag(dep)
+	// dependencies other than the static linkage are all considered crossing APEX boundary
+	// Also, a dependency to an sdk member is also considered as such. This is required because
+	// sdk members should be mutated into APEXes. Refer to sdk.sdkDepsReplaceMutator.
+	return depTag == staticLibTag || j.IsInAnySdk()
+}
+
 // Add compile time check for interface implementation
 var _ android.IDEInfo = (*Import)(nil)
 var _ android.IDECustomizedModuleName = (*Import)(nil)
diff --git a/java/java_test.go b/java/java_test.go
index 0e987a6..8815c09 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -1099,6 +1099,12 @@
 			libs: ["foo"],
 			sdk_version: "test_current",
 		}
+		java_library {
+			name: "baz-29",
+			srcs: ["c.java"],
+			libs: ["foo"],
+			sdk_version: "system_29",
+		}
 		`)
 
 	// check the existence of the internal modules
@@ -1138,6 +1144,13 @@
 			"foo.stubs.test.jar")
 	}
 
+	baz29Javac := ctx.ModuleForTests("baz-29", "android_common").Rule("javac")
+	// tests if baz-29 is actually linked to the system 29 stubs lib
+	if !strings.Contains(baz29Javac.Args["classpath"], "prebuilts/sdk/29/system/foo.jar") {
+		t.Errorf("baz-29 javac classpath %v does not contain %q", baz29Javac.Args["classpath"],
+			"prebuilts/sdk/29/system/foo.jar")
+	}
+
 	// test if baz has exported SDK lib names foo and bar to qux
 	qux := ctx.ModuleForTests("qux", "android_common")
 	if quxLib, ok := qux.Module().(*Library); ok {
diff --git a/java/platform_compat_config.go b/java/platform_compat_config.go
index 95c0574..cb8e684 100644
--- a/java/platform_compat_config.go
+++ b/java/platform_compat_config.go
@@ -21,7 +21,7 @@
 
 func init() {
 	android.RegisterSingletonType("platform_compat_config_singleton", platformCompatConfigSingletonFactory)
-	android.RegisterModuleType("platform_compat_config", platformCompatConfigFactory)
+	android.RegisterModuleType("platform_compat_config", PlatformCompatConfigFactory)
 	android.RegisterModuleType("global_compat_config", globalCompatConfigFactory)
 }
 
@@ -50,11 +50,24 @@
 	return p.metadataFile
 }
 
-type platformCompatConfigIntf interface {
-	compatConfigMetadata() android.OutputPath
+func (p *platformCompatConfig) CompatConfig() android.OutputPath {
+	return p.configFile
 }
 
-var _ platformCompatConfigIntf = (*platformCompatConfig)(nil)
+func (p *platformCompatConfig) SubDir() string {
+	return "compatconfig"
+}
+
+type PlatformCompatConfigIntf interface {
+	android.Module
+
+	compatConfigMetadata() android.OutputPath
+	CompatConfig() android.OutputPath
+	// Sub dir under etc dir.
+	SubDir() string
+}
+
+var _ PlatformCompatConfigIntf = (*platformCompatConfig)(nil)
 
 // compat singleton rules
 func (p *platformCompatConfigSingleton) GenerateBuildActions(ctx android.SingletonContext) {
@@ -62,7 +75,7 @@
 	var compatConfigMetadata android.Paths
 
 	ctx.VisitAllModules(func(module android.Module) {
-		if c, ok := module.(platformCompatConfigIntf); ok {
+		if c, ok := module.(PlatformCompatConfigIntf); ok {
 			metadata := c.compatConfigMetadata()
 			compatConfigMetadata = append(compatConfigMetadata, metadata)
 		}
@@ -130,7 +143,7 @@
 	return &platformCompatConfigSingleton{}
 }
 
-func platformCompatConfigFactory() android.Module {
+func PlatformCompatConfigFactory() android.Module {
 	module := &platformCompatConfig{}
 	module.AddProperties(&module.properties)
 	android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
diff --git a/java/sdk.go b/java/sdk.go
index f388358..1c047a3 100644
--- a/java/sdk.go
+++ b/java/sdk.go
@@ -71,6 +71,7 @@
 	sdkPublic
 	sdkSystem
 	sdkTest
+	sdkModule
 	sdkPrivate
 )
 
@@ -91,6 +92,8 @@
 		return "core"
 	case sdkCorePlatform:
 		return "core_platform"
+	case sdkModule:
+		return "module"
 	default:
 		return "invalid"
 	}
@@ -256,6 +259,8 @@
 			kind = sdkSystem
 		case "test":
 			kind = sdkTest
+		case "module":
+			kind = sdkModule
 		default:
 			return sdkSpec{sdkInvalid, sdkVersionNone, str}
 		}
@@ -382,6 +387,9 @@
 		return toModule("android_test_stubs_current", "framework-res", sdkFrameworkAidlPath(ctx))
 	case sdkCore:
 		return toModule("core.current.stubs", "", nil)
+	case sdkModule:
+		// TODO(146757305): provide .apk and .aidl that have more APIs for modules
+		return toModule("android_module_lib_stubs_current", "framework-res", sdkFrameworkAidlPath(ctx))
 	default:
 		panic(fmt.Errorf("invalid sdk %q", sdkVersion.raw))
 	}
diff --git a/java/sdk_library.go b/java/sdk_library.go
index cd22e6e..3c376d0 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -16,6 +16,7 @@
 
 import (
 	"android/soong/android"
+	"android/soong/genrule"
 
 	"fmt"
 	"io"
@@ -264,17 +265,22 @@
 	}
 }
 
+var xmlPermissionsFileTag = dependencyTag{name: "xml-permissions-file"}
+
 func (module *SdkLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
-	useBuiltStubs := !ctx.Config().UnbundledBuildUsePrebuiltSdks()
 	for _, apiScope := range module.getActiveApiScopes() {
 		// Add dependencies to the stubs library
-		if useBuiltStubs {
-			ctx.AddVariationDependencies(nil, apiScope.stubsTag, module.stubsName(apiScope))
-		}
+		ctx.AddVariationDependencies(nil, apiScope.stubsTag, module.stubsName(apiScope))
 
+		// And the api file
 		ctx.AddVariationDependencies(nil, apiScope.apiFileTag, module.docsName(apiScope))
 	}
 
+	if !proptools.Bool(module.sdkLibraryProperties.Api_only) {
+		// Add dependency to the rule for generating the xml permissions file
+		ctx.AddDependency(module, xmlPermissionsFileTag, module.genXmlPermissionsFileName())
+	}
+
 	module.Library.deps(ctx)
 }
 
@@ -284,8 +290,6 @@
 		module.Library.GenerateAndroidBuildActions(ctx)
 	}
 
-	module.buildPermissionsFile(ctx)
-
 	// Record the paths to the header jars of the library (stubs and impl).
 	// When this java_sdk_library is depended upon from others via "libs" property,
 	// the recorded paths will be returned depending on the link type of the caller.
@@ -310,33 +314,21 @@
 				ctx.ModuleErrorf("depends on module %q of unknown tag %q", otherName, tag)
 			}
 		}
+		if tag == xmlPermissionsFileTag {
+			if genRule, ok := to.(genrule.SourceFileGenerator); ok {
+				pf := genRule.GeneratedSourceFiles()
+				if len(pf) != 1 {
+					ctx.ModuleErrorf("%q failed to generate permission XML", otherName)
+				} else {
+					module.permissionsFile = pf[0]
+				}
+			} else {
+				ctx.ModuleErrorf("depends on module %q to generate xml permissions file but it does not provide any outputs", otherName)
+			}
+		}
 	})
 }
 
-func (module *SdkLibrary) buildPermissionsFile(ctx android.ModuleContext) {
-	xmlContent := fmt.Sprintf(permissionsTemplate, module.BaseModuleName(), module.implPath())
-	permissionsFile := android.PathForModuleOut(ctx, module.xmlFileName())
-
-	ctx.Build(pctx, android.BuildParams{
-		Rule:        android.WriteFile,
-		Output:      permissionsFile,
-		Description: "Generating " + module.BaseModuleName() + " permissions",
-		Args: map[string]string{
-			"content": xmlContent,
-		},
-	})
-
-	module.permissionsFile = permissionsFile
-}
-
-func (module *SdkLibrary) OutputFiles(tag string) (android.Paths, error) {
-	switch tag {
-	case ".xml":
-		return android.Paths{module.permissionsFile}, nil
-	}
-	return module.Library.OutputFiles(tag)
-}
-
 func (module *SdkLibrary) AndroidMkEntries() []android.AndroidMkEntries {
 	if proptools.Bool(module.sdkLibraryProperties.Api_only) {
 		return nil
@@ -423,6 +415,11 @@
 	return module.BaseModuleName() + sdkXmlFileSuffix
 }
 
+// Module name of the rule for generating the XML permissions file
+func (module *SdkLibrary) genXmlPermissionsFileName() string {
+	return "gen-" + module.BaseModuleName() + sdkXmlFileSuffix
+}
+
 // Get the sdk version for use when compiling the stubs library.
 func (module *SdkLibrary) sdkVersionForStubsLibrary(mctx android.LoadHookContext, apiScope *apiScope) string {
 	sdkDep := decodeSdkDep(mctx, sdkContext(&module.Library))
@@ -458,6 +455,7 @@
 		Installable         *bool
 		Sdk_version         *string
 		System_modules      *string
+		Patch_module        *string
 		Libs                []string
 		Soc_specific        *bool
 		Device_specific     *bool
@@ -466,9 +464,6 @@
 		Compile_dex         *bool
 		Java_version        *string
 		Product_variables   struct {
-			Unbundled_build struct {
-				Enabled *bool
-			}
 			Pdk struct {
 				Enabled *bool
 			}
@@ -485,12 +480,9 @@
 	sdkVersion := module.sdkVersionForStubsLibrary(mctx, apiScope)
 	props.Sdk_version = proptools.StringPtr(sdkVersion)
 	props.System_modules = module.Library.Module.deviceProperties.System_modules
+	props.Patch_module = module.Library.Module.properties.Patch_module
 	props.Installable = proptools.BoolPtr(false)
 	props.Libs = module.sdkLibraryProperties.Stub_only_libs
-	// Unbundled apps will use the prebult one from /prebuilts/sdk
-	if mctx.Config().UnbundledBuildUsePrebuiltSdks() {
-		props.Product_variables.Unbundled_build.Enabled = proptools.BoolPtr(false)
-	}
 	props.Product_variables.Pdk.Enabled = proptools.BoolPtr(false)
 	props.Openjdk9.Srcs = module.Library.Module.properties.Openjdk9.Srcs
 	props.Openjdk9.Javacflags = module.Library.Module.properties.Openjdk9.Javacflags
@@ -623,8 +615,34 @@
 	mctx.CreateModule(DroidstubsFactory, &props)
 }
 
+func (module *SdkLibrary) XmlPermissionsFile() android.Path {
+	return module.permissionsFile
+}
+
+func (module *SdkLibrary) XmlPermissionsFileContent() string {
+	return fmt.Sprintf(permissionsTemplate, module.BaseModuleName(), module.implPath())
+}
+
 // Creates the xml file that publicizes the runtime library
 func (module *SdkLibrary) createXmlFile(mctx android.LoadHookContext) {
+
+	xmlContent := module.XmlPermissionsFileContent()
+
+	genRuleName := module.genXmlPermissionsFileName()
+
+	// Create a genrule module to create the XML permissions file.
+	genRuleProps := struct {
+		Name *string
+		Cmd  *string
+		Out  []string
+	}{
+		Name: proptools.StringPtr(genRuleName),
+		Cmd:  proptools.StringPtr("echo -e '" + xmlContent + "' > '$(out)'"),
+		Out:  []string{module.xmlFileName()},
+	}
+
+	mctx.CreateModule(genrule.GenRuleFactory, &genRuleProps)
+
 	// creates a prebuilt_etc module to actually place the xml file under
 	// <partition>/etc/permissions
 	etcProps := struct {
@@ -637,7 +655,7 @@
 		System_ext_specific *bool
 	}{}
 	etcProps.Name = proptools.StringPtr(module.xmlFileName())
-	etcProps.Src = proptools.StringPtr(":" + module.BaseModuleName() + "{.xml}")
+	etcProps.Src = proptools.StringPtr(":" + genRuleName)
 	etcProps.Sub_dir = proptools.StringPtr("permissions")
 	if module.SocSpecific() {
 		etcProps.Soc_specific = proptools.BoolPtr(true)
@@ -651,7 +669,7 @@
 	mctx.CreateModule(android.PrebuiltEtcFactory, &etcProps)
 }
 
-func (module *SdkLibrary) PrebuiltJars(ctx android.BaseModuleContext, s sdkSpec) android.Paths {
+func PrebuiltJars(ctx android.BaseModuleContext, baseName string, s sdkSpec) android.Paths {
 	var ver sdkVersion
 	var kind sdkKind
 	if s.usePrebuilt(ctx) {
@@ -665,7 +683,7 @@
 	}
 
 	dir := filepath.Join("prebuilts", "sdk", ver.String(), kind.String())
-	jar := filepath.Join(dir, module.BaseModuleName()+".jar")
+	jar := filepath.Join(dir, baseName+".jar")
 	jarPath := android.ExistentPathForSource(ctx, jar)
 	if !jarPath.Valid() {
 		if ctx.Config().AllowMissingDependencies() {
@@ -683,9 +701,9 @@
 	sdkVersion sdkSpec,
 	headerJars bool) android.Paths {
 
-	// This module is just a wrapper for the stubs.
-	if ctx.Config().UnbundledBuildUsePrebuiltSdks() {
-		return module.PrebuiltJars(ctx, sdkVersion)
+	// If a specific numeric version has been requested then use prebuilt versions of the sdk.
+	if sdkVersion.version.isNumbered() {
+		return PrebuiltJars(ctx, module.BaseModuleName(), sdkVersion)
 	} else {
 		if !sdkVersion.specified() {
 			if headerJars {
@@ -881,7 +899,7 @@
 
 	module.AddProperties(&module.properties)
 
-	android.InitPrebuiltModule(module, &[]string{})
+	android.InitPrebuiltModule(module, &[]string{""})
 	InitJavaModule(module, android.HostAndDeviceSupported)
 
 	android.AddLoadHook(module, func(mctx android.LoadHookContext) { module.createInternalModules(mctx) })
@@ -898,6 +916,11 @@
 
 func (module *sdkLibraryImport) createInternalModules(mctx android.LoadHookContext) {
 
+	// If the build is configured to use prebuilts then force this to be preferred.
+	if mctx.Config().UnbundledBuildUsePrebuiltSdks() {
+		module.prebuilt.ForcePrefer()
+	}
+
 	for apiScope, scopeProperties := range module.scopeProperties() {
 		if len(scopeProperties.Jars) == 0 {
 			continue
@@ -913,6 +936,7 @@
 			Sdk_version         *string
 			Libs                []string
 			Jars                []string
+			Prefer              *bool
 		}{}
 
 		props.Name = proptools.StringPtr(apiScope.stubsModuleName(module.BaseModuleName()))
@@ -932,6 +956,12 @@
 			props.System_ext_specific = proptools.BoolPtr(true)
 		}
 
+		// If the build should use prebuilt sdks then set prefer to true on the stubs library.
+		// That will cause the prebuilt version of the stubs to override the source version.
+		if mctx.Config().UnbundledBuildUsePrebuiltSdks() {
+			props.Prefer = proptools.BoolPtr(true)
+		}
+
 		mctx.CreateModule(ImportFactory, &props)
 	}
 
@@ -979,6 +1009,11 @@
 	ctx android.BaseModuleContext,
 	sdkVersion sdkSpec) android.Paths {
 
+	// If a specific numeric version has been requested then use prebuilt versions of the sdk.
+	if sdkVersion.version.isNumbered() {
+		return PrebuiltJars(ctx, module.BaseModuleName(), sdkVersion)
+	}
+
 	var apiScope *apiScope
 	switch sdkVersion.kind {
 	case sdkSystem:
diff --git a/java/sdk_test.go b/java/sdk_test.go
index 9cabd77..c815fe3 100644
--- a/java/sdk_test.go
+++ b/java/sdk_test.go
@@ -211,6 +211,15 @@
 			java8classpath: []string{"prebuilts/sdk/29/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"},
 			aidl:           "-pprebuilts/sdk/29/public/framework.aidl",
 		},
+		{
+
+			name:           "module_current",
+			properties:     `sdk_version: "module_current",`,
+			bootclasspath:  []string{"android_module_lib_stubs_current", "core-lambda-stubs"},
+			system:         "core-current-stubs-system-modules",
+			java9classpath: []string{"android_module_lib_stubs_current"},
+			aidl:           "-p" + buildDir + "/framework.aidl",
+		},
 	}
 
 	for _, testcase := range classpathTestcases {
diff --git a/java/system_modules.go b/java/system_modules.go
index 92297c4..731503f 100644
--- a/java/system_modules.go
+++ b/java/system_modules.go
@@ -31,6 +31,15 @@
 	RegisterSystemModulesBuildComponents(android.InitRegistrationContext)
 
 	pctx.SourcePathVariable("moduleInfoJavaPath", "build/soong/scripts/jars-to-module-info-java.sh")
+
+	// Register sdk member types.
+	android.RegisterSdkMemberType(&systemModulesSdkMemberType{
+		android.SdkMemberTypeBase{
+			PropertyName:         "java_system_modules",
+			SupportsSdk:          true,
+			TransitiveSdkMembers: true,
+		},
+	})
 }
 
 func RegisterSystemModulesBuildComponents(ctx android.RegistrationContext) {
@@ -66,6 +75,10 @@
 		},
 	},
 		"classpath", "outDir", "workDir")
+
+	// Dependency tag that causes the added dependencies to be added as java_header_libs
+	// to the sdk/module_exports/snapshot.
+	systemModulesLibsTag = android.DependencyTagForSdkMemberType(javaHeaderLibsSdkMemberType)
 )
 
 func TransformJarsToSystemModules(ctx android.ModuleContext, jars android.Paths) (android.Path, android.Paths) {
@@ -107,6 +120,7 @@
 type SystemModules struct {
 	android.ModuleBase
 	android.DefaultableModuleBase
+	android.SdkBase
 
 	properties SystemModulesProperties
 
@@ -125,7 +139,7 @@
 func (system *SystemModules) GenerateAndroidBuildActions(ctx android.ModuleContext) {
 	var jars android.Paths
 
-	ctx.VisitDirectDepsWithTag(libTag, func(module android.Module) {
+	ctx.VisitDirectDepsWithTag(systemModulesLibsTag, func(module android.Module) {
 		dep, _ := module.(Dependency)
 		jars = append(jars, dep.HeaderJars()...)
 	})
@@ -136,7 +150,7 @@
 }
 
 func (system *SystemModules) DepsMutator(ctx android.BottomUpMutatorContext) {
-	ctx.AddVariationDependencies(nil, libTag, system.properties.Libs...)
+	ctx.AddVariationDependencies(nil, systemModulesLibsTag, system.properties.Libs...)
 }
 
 func (system *SystemModules) AndroidMk() android.AndroidMkData {
@@ -173,6 +187,7 @@
 	android.InitPrebuiltModule(module, &module.properties.Libs)
 	android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibCommon)
 	android.InitDefaultableModule(module)
+	android.InitSdkAwareModule(module)
 	return module
 }
 
@@ -188,3 +203,37 @@
 func (system *systemModulesImport) Prebuilt() *android.Prebuilt {
 	return &system.prebuilt
 }
+
+type systemModulesSdkMemberType struct {
+	android.SdkMemberTypeBase
+}
+
+func (mt *systemModulesSdkMemberType) AddDependencies(mctx android.BottomUpMutatorContext, dependencyTag blueprint.DependencyTag, names []string) {
+	mctx.AddVariationDependencies(nil, dependencyTag, names...)
+}
+
+func (mt *systemModulesSdkMemberType) IsInstance(module android.Module) bool {
+	if _, ok := module.(*SystemModules); ok {
+		// A prebuilt system module cannot be added as a member of an sdk because the source and
+		// snapshot instances would conflict.
+		_, ok := module.(*systemModulesImport)
+		return !ok
+	}
+	return false
+}
+
+func (mt *systemModulesSdkMemberType) BuildSnapshot(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, member android.SdkMember) {
+	variants := member.Variants()
+	if len(variants) != 1 {
+		sdkModuleContext.ModuleErrorf("sdk contains %d variants of member %q but only one is allowed", len(variants), member.Name())
+		for _, variant := range variants {
+			sdkModuleContext.ModuleErrorf("    %q", variant)
+		}
+	}
+	variant := variants[0]
+	systemModule := variant.(*SystemModules)
+
+	pbm := builder.AddPrebuiltModule(member, "java_system_modules_import")
+	// Add the references to the libraries that form the system module.
+	pbm.AddPropertyWithTag("libs", systemModule.properties.Libs, builder.SdkMemberReferencePropertyTag())
+}
diff --git a/java/testing.go b/java/testing.go
index e746e2d..8f979c7 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -49,6 +49,8 @@
 		"api/test-current.txt":   nil,
 		"api/test-removed.txt":   nil,
 		"framework/aidl/a.aidl":  nil,
+		"assets_a/a":             nil,
+		"assets_b/b":             nil,
 
 		"prebuilts/ndk/current/sources/cxx-stl/llvm-libc++/libs/arm64-v8a/libc++_shared.so": nil,
 
@@ -61,6 +63,7 @@
 		"prebuilts/sdk/29/public/android.jar":         nil,
 		"prebuilts/sdk/29/public/framework.aidl":      nil,
 		"prebuilts/sdk/29/system/android.jar":         nil,
+		"prebuilts/sdk/29/system/foo.jar":             nil,
 		"prebuilts/sdk/current/core/android.jar":      nil,
 		"prebuilts/sdk/current/public/android.jar":    nil,
 		"prebuilts/sdk/current/public/framework.aidl": nil,
@@ -143,6 +146,7 @@
 		"android_stubs_current",
 		"android_system_stubs_current",
 		"android_test_stubs_current",
+		"android_module_lib_stubs_current",
 		"core.current.stubs",
 		"core.platform.api.stubs",
 		"kotlin-stdlib",
diff --git a/rust/rust.go b/rust/rust.go
index 26401d1..33ef714 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -708,13 +708,15 @@
 func linkPathFromFilePath(filepath android.Path) string {
 	return strings.Split(filepath.String(), filepath.Base())[0]
 }
+
 func libNameFromFilePath(filepath android.Path) string {
-	libName := strings.Split(filepath.Base(), filepath.Ext())[0]
+	libName := strings.TrimSuffix(filepath.Base(), filepath.Ext())
 	if strings.HasPrefix(libName, "lib") {
 		libName = libName[3:]
 	}
 	return libName
 }
+
 func (mod *Module) DepsMutator(actx android.BottomUpMutatorContext) {
 	ctx := &depsContext{
 		BottomUpMutatorContext: actx,
diff --git a/rust/rust_test.go b/rust/rust_test.go
index 3be9ee7..afe530a 100644
--- a/rust/rust_test.go
+++ b/rust/rust_test.go
@@ -114,13 +114,13 @@
 
 // Test that we can extract the lib name from a lib path.
 func TestLibNameFromFilePath(t *testing.T) {
-	libBarPath := android.PathForTesting("out/soong/.intermediates/external/libbar/libbar/linux_glibc_x86_64_shared/libbar.so")
+	libBarPath := android.PathForTesting("out/soong/.intermediates/external/libbar/libbar/linux_glibc_x86_64_shared/libbar.so.so")
 	libLibPath := android.PathForTesting("out/soong/.intermediates/external/libbar/libbar/linux_glibc_x86_64_shared/liblib.dylib.so")
 
 	libBarName := libNameFromFilePath(libBarPath)
 	libLibName := libNameFromFilePath(libLibPath)
 
-	expectedResult := "bar"
+	expectedResult := "bar.so"
 	if libBarName != expectedResult {
 		t.Errorf("libNameFromFilePath returned the wrong name; expected '%#v', got '%#v'", expectedResult, libBarName)
 	}
diff --git a/sdk/java_sdk_test.go b/sdk/java_sdk_test.go
index 692c205..0737e5e 100644
--- a/sdk/java_sdk_test.go
+++ b/sdk/java_sdk_test.go
@@ -34,7 +34,7 @@
 	result := testSdkWithJava(t, `
 		sdk {
 			name: "mysdk",
-			java_header_libs: ["myjavalib"],
+			java_header_libs: ["sdkmember"],
 		}
 
 		sdk_snapshot {
@@ -47,22 +47,36 @@
 			java_header_libs: ["sdkmember_mysdk_2"],
 		}
 
-		java_import {
+		java_library {
 			name: "sdkmember",
-			prefer: false,
+			srcs: ["Test.java"],
+			system_modules: "none",
+			sdk_version: "none",
 			host_supported: true,
+			apex_available: [
+				"//apex_available:platform",
+				"//apex_available:anyapex",
+			],
 		}
 
 		java_import {
 			name: "sdkmember_mysdk_1",
 			sdk_member_name: "sdkmember",
 			host_supported: true,
+			apex_available: [
+				"//apex_available:platform",
+				"//apex_available:anyapex",
+			],
 		}
 
 		java_import {
 			name: "sdkmember_mysdk_2",
 			sdk_member_name: "sdkmember",
 			host_supported: true,
+			apex_available: [
+				"//apex_available:platform",
+				"//apex_available:anyapex",
+			],
 		}
 
 		java_library {
@@ -569,3 +583,170 @@
 		checkMergeZip(".intermediates/myexports/linux_glibc_common/tmp/java/myjavaapistubs_stubs_sources.zip"),
 	)
 }
+
+func TestSnapshotWithJavaSystemModules(t *testing.T) {
+	result := testSdkWithJava(t, `
+		sdk {
+			name: "mysdk",
+			java_header_libs: ["exported-system-module"],
+			java_system_modules: ["my-system-modules"],
+		}
+
+		java_system_modules {
+			name: "my-system-modules",
+			libs: ["system-module", "exported-system-module"],
+		}
+
+		java_library {
+			name: "system-module",
+			srcs: ["Test.java"],
+			sdk_version: "none",
+			system_modules: "none",
+		}
+
+		java_library {
+			name: "exported-system-module",
+			srcs: ["Test.java"],
+			sdk_version: "none",
+			system_modules: "none",
+		}
+	`)
+
+	result.CheckSnapshot("mysdk", "android_common", "",
+		checkAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
+
+java_import {
+    name: "mysdk_exported-system-module@current",
+    sdk_member_name: "exported-system-module",
+    jars: ["java/exported-system-module.jar"],
+}
+
+java_import {
+    name: "exported-system-module",
+    prefer: false,
+    jars: ["java/exported-system-module.jar"],
+}
+
+java_import {
+    name: "mysdk_system-module@current",
+    sdk_member_name: "system-module",
+    visibility: ["//visibility:private"],
+    jars: ["java/system-module.jar"],
+}
+
+java_import {
+    name: "mysdk_system-module",
+    prefer: false,
+    visibility: ["//visibility:private"],
+    jars: ["java/system-module.jar"],
+}
+
+java_system_modules_import {
+    name: "mysdk_my-system-modules@current",
+    sdk_member_name: "my-system-modules",
+    libs: [
+        "mysdk_system-module@current",
+        "mysdk_exported-system-module@current",
+    ],
+}
+
+java_system_modules_import {
+    name: "my-system-modules",
+    prefer: false,
+    libs: [
+        "mysdk_system-module",
+        "exported-system-module",
+    ],
+}
+
+sdk_snapshot {
+    name: "mysdk@current",
+    java_header_libs: ["mysdk_exported-system-module@current"],
+    java_system_modules: ["mysdk_my-system-modules@current"],
+}
+`),
+		checkAllCopyRules(`
+.intermediates/exported-system-module/android_common/turbine-combined/exported-system-module.jar -> java/exported-system-module.jar
+.intermediates/system-module/android_common/turbine-combined/system-module.jar -> java/system-module.jar
+`),
+	)
+}
+
+func TestHostSnapshotWithJavaSystemModules(t *testing.T) {
+	// b/145598135 - Generating host snapshots for anything other than linux is not supported.
+	SkipIfNotLinux(t)
+
+	result := testSdkWithJava(t, `
+		sdk {
+			name: "mysdk",
+			device_supported: false,
+			host_supported: true,
+			java_system_modules: ["my-system-modules"],
+		}
+
+		java_system_modules {
+			name: "my-system-modules",
+			device_supported: false,
+			host_supported: true,
+			libs: ["system-module"],
+		}
+
+		java_library {
+			name: "system-module",
+			device_supported: false,
+			host_supported: true,
+			srcs: ["Test.java"],
+			sdk_version: "none",
+			system_modules: "none",
+		}
+	`)
+
+	result.CheckSnapshot("mysdk", "linux_glibc_common", "",
+		checkAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
+
+java_import {
+    name: "mysdk_system-module@current",
+    sdk_member_name: "system-module",
+    visibility: ["//visibility:private"],
+    device_supported: false,
+    host_supported: true,
+    jars: ["java/system-module.jar"],
+}
+
+java_import {
+    name: "mysdk_system-module",
+    prefer: false,
+    visibility: ["//visibility:private"],
+    device_supported: false,
+    host_supported: true,
+    jars: ["java/system-module.jar"],
+}
+
+java_system_modules_import {
+    name: "mysdk_my-system-modules@current",
+    sdk_member_name: "my-system-modules",
+    device_supported: false,
+    host_supported: true,
+    libs: ["mysdk_system-module@current"],
+}
+
+java_system_modules_import {
+    name: "my-system-modules",
+    prefer: false,
+    device_supported: false,
+    host_supported: true,
+    libs: ["mysdk_system-module"],
+}
+
+sdk_snapshot {
+    name: "mysdk@current",
+    device_supported: false,
+    host_supported: true,
+    java_system_modules: ["mysdk_my-system-modules@current"],
+}
+`),
+		checkAllCopyRules(".intermediates/system-module/linux_glibc_common/javac/system-module.jar -> java/system-module.jar"),
+	)
+}
diff --git a/sdk/sdk.go b/sdk/sdk.go
index f22763c..dbe9ce2 100644
--- a/sdk/sdk.go
+++ b/sdk/sdk.go
@@ -50,6 +50,9 @@
 	// list properties, e.g. java_libs.
 	dynamicMemberTypeListProperties interface{}
 
+	// The set of exported members.
+	exportedMembers map[string]struct{}
+
 	properties sdkProperties
 
 	snapshotFile android.OptionalPath
@@ -217,6 +220,33 @@
 	return s
 }
 
+func (s *sdk) memberListProperties() []*sdkMemberListProperty {
+	return s.dynamicSdkMemberTypes.memberListProperties
+}
+
+func (s *sdk) getExportedMembers() map[string]struct{} {
+	if s.exportedMembers == nil {
+		// Collect all the exported members.
+		s.exportedMembers = make(map[string]struct{})
+
+		for _, memberListProperty := range s.memberListProperties() {
+			names := memberListProperty.getter(s.dynamicMemberTypeListProperties)
+
+			// Every member specified explicitly in the properties is exported by the sdk.
+			for _, name := range names {
+				s.exportedMembers[name] = struct{}{}
+			}
+		}
+	}
+
+	return s.exportedMembers
+}
+
+func (s *sdk) isInternalMember(memberName string) bool {
+	_, ok := s.getExportedMembers()[memberName]
+	return !ok
+}
+
 func (s *sdk) snapshot() bool {
 	return s.properties.Snapshot
 }
@@ -290,7 +320,7 @@
 // Step 1: create dependencies from an SDK module to its members.
 func memberMutator(mctx android.BottomUpMutatorContext) {
 	if s, ok := mctx.Module().(*sdk); ok {
-		for _, memberListProperty := range s.dynamicSdkMemberTypes.memberListProperties {
+		for _, memberListProperty := range s.memberListProperties() {
 			names := memberListProperty.getter(s.dynamicMemberTypeListProperties)
 			tag := memberListProperty.dependencyTag
 			memberListProperty.memberType.AddDependencies(mctx, tag, names)
diff --git a/sdk/testing.go b/sdk/testing.go
index c9cc30f..6102441 100644
--- a/sdk/testing.go
+++ b/sdk/testing.go
@@ -72,6 +72,7 @@
 	java.RegisterJavaBuildComponents(ctx)
 	java.RegisterAppBuildComponents(ctx)
 	java.RegisterStubsBuildComponents(ctx)
+	java.RegisterSystemModulesBuildComponents(ctx)
 
 	// from cc package
 	cc.RegisterRequiredBuildComponentsForTest(ctx)
diff --git a/sdk/update.go b/sdk/update.go
index 97bafa1..ff567be 100644
--- a/sdk/update.go
+++ b/sdk/update.go
@@ -105,23 +105,23 @@
 // Collect all the members.
 //
 // The members are first grouped by type and then grouped by name. The order of
-// the types is the order they are referenced in android.SdkMemberTypes. The
-// names are in order in which the dependencies were added.
+// the types is the order they are referenced in android.SdkMemberTypesRegistry.
+// The names are in the order in which the dependencies were added.
 func (s *sdk) collectMembers(ctx android.ModuleContext) []*sdkMember {
 	byType := make(map[android.SdkMemberType][]*sdkMember)
 	byName := make(map[string]*sdkMember)
 
-	ctx.VisitDirectDeps(func(m android.Module) {
-		tag := ctx.OtherModuleDependencyTag(m)
+	ctx.WalkDeps(func(child android.Module, parent android.Module) bool {
+		tag := ctx.OtherModuleDependencyTag(child)
 		if memberTag, ok := tag.(android.SdkMemberTypeDependencyTag); ok {
 			memberType := memberTag.SdkMemberType()
 
 			// Make sure that the resolved module is allowed in the member list property.
-			if !memberType.IsInstance(m) {
-				ctx.ModuleErrorf("module %q is not valid in property %s", ctx.OtherModuleName(m), memberType.SdkPropertyName())
+			if !memberType.IsInstance(child) {
+				ctx.ModuleErrorf("module %q is not valid in property %s", ctx.OtherModuleName(child), memberType.SdkPropertyName())
 			}
 
-			name := ctx.OtherModuleName(m)
+			name := ctx.OtherModuleName(child)
 
 			member := byName[name]
 			if member == nil {
@@ -130,12 +130,20 @@
 				byType[memberType] = append(byType[memberType], member)
 			}
 
-			member.variants = append(member.variants, m.(android.SdkAware))
+			// Only append new variants to the list. This is needed because a member can be both
+			// exported by the sdk and also be a transitive sdk member.
+			member.variants = appendUniqueVariants(member.variants, child.(android.SdkAware))
+
+			// If the member type supports transitive sdk members then recurse down into
+			// its dependencies, otherwise exit traversal.
+			return memberType.HasTransitiveSdkMembers()
 		}
+
+		return false
 	})
 
 	var members []*sdkMember
-	for _, memberListProperty := range s.dynamicSdkMemberTypes.memberListProperties {
+	for _, memberListProperty := range s.memberListProperties() {
 		membersOfType := byType[memberListProperty.memberType]
 		members = append(members, membersOfType...)
 	}
@@ -143,6 +151,15 @@
 	return members
 }
 
+func appendUniqueVariants(variants []android.SdkAware, newVariant android.SdkAware) []android.SdkAware {
+	for _, v := range variants {
+		if v == newVariant {
+			return variants
+		}
+	}
+	return append(variants, newVariant)
+}
+
 // SDK directory structure
 // <sdk_root>/
 //     Android.bp   : definition of a 'sdk' module is here. This is a hand-made one.
@@ -197,17 +214,20 @@
 	// Create a transformer that will transform an unversioned module into a versioned module.
 	unversionedToVersionedTransformer := unversionedToVersionedTransformation{builder: builder}
 
+	// Create a transformer that will transform an unversioned module by replacing any references
+	// to internal members with a unique module name and setting prefer: false.
+	unversionedTransformer := unversionedTransformation{builder: builder}
+
 	for _, unversioned := range builder.prebuiltOrder {
 		// Copy the unversioned module so it can be modified to make it versioned.
 		versioned := unversioned.deepCopy()
 
 		// Transform the unversioned module into a versioned one.
 		versioned.transform(unversionedToVersionedTransformer)
-
 		bpFile.AddModule(versioned)
 
-		// Set prefer: false - this is not strictly required as that is the default.
-		unversioned.insertAfter("name", "prefer", false)
+		// Transform the unversioned module to make it suitable for use in the snapshot.
+		unversioned.transform(unversionedTransformer)
 		bpFile.AddModule(unversioned)
 	}
 
@@ -229,7 +249,7 @@
 	}
 
 	addHostDeviceSupportedProperties(&s.ModuleBase, snapshotModule)
-	for _, memberListProperty := range s.dynamicSdkMemberTypes.memberListProperties {
+	for _, memberListProperty := range s.memberListProperties() {
 		names := memberListProperty.getter(s.dynamicMemberTypeListProperties)
 		if len(names) > 0 {
 			snapshotModule.AddProperty(memberListProperty.propertyName(), builder.versionedSdkMemberNames(names))
@@ -285,13 +305,17 @@
 	return outputZipFile
 }
 
+type propertyTag struct {
+	name string
+}
+
+var sdkMemberReferencePropertyTag = propertyTag{"sdkMemberReferencePropertyTag"}
+
 type unversionedToVersionedTransformation struct {
 	identityTransformation
 	builder *snapshotBuilder
 }
 
-var _ bpTransformer = (*unversionedToVersionedTransformation)(nil)
-
 func (t unversionedToVersionedTransformation) transformModule(module *bpModule) *bpModule {
 	// Use a versioned name for the module but remember the original name for the
 	// snapshot.
@@ -301,6 +325,38 @@
 	return module
 }
 
+func (t unversionedToVersionedTransformation) transformProperty(name string, value interface{}, tag android.BpPropertyTag) (interface{}, android.BpPropertyTag) {
+	if tag == sdkMemberReferencePropertyTag {
+		return t.builder.versionedSdkMemberNames(value.([]string)), tag
+	} else {
+		return value, tag
+	}
+}
+
+type unversionedTransformation struct {
+	identityTransformation
+	builder *snapshotBuilder
+}
+
+func (t unversionedTransformation) transformModule(module *bpModule) *bpModule {
+	// If the module is an internal member then use a unique name for it.
+	name := module.getValue("name").(string)
+	module.setProperty("name", t.builder.unversionedSdkMemberName(name))
+
+	// Set prefer: false - this is not strictly required as that is the default.
+	module.insertAfter("name", "prefer", false)
+
+	return module
+}
+
+func (t unversionedTransformation) transformProperty(name string, value interface{}, tag android.BpPropertyTag) (interface{}, android.BpPropertyTag) {
+	if tag == sdkMemberReferencePropertyTag {
+		return t.builder.unversionedSdkMemberNames(value.([]string)), tag
+	} else {
+		return value, tag
+	}
+}
+
 func generateBpContents(contents *generatedContents, bpFile *bpFile) {
 	contents.Printfln("// This is auto-generated. DO NOT EDIT.")
 	for _, bpModule := range bpFile.order {
@@ -424,11 +480,17 @@
 	m := s.bpFile.newModule(moduleType)
 	m.AddProperty("name", name)
 
-	// Extract visibility information from a member variant. All variants have the same
-	// visibility so it doesn't matter which one is used.
-	visibility := android.EffectiveVisibilityRules(s.ctx, member.Variants()[0])
-	if len(visibility) != 0 {
-		m.AddProperty("visibility", visibility)
+	if s.sdk.isInternalMember(name) {
+		// An internal member is only referenced from the sdk snapshot which is in the
+		// same package so can be marked as private.
+		m.AddProperty("visibility", []string{"//visibility:private"})
+	} else {
+		// Extract visibility information from a member variant. All variants have the same
+		// visibility so it doesn't matter which one is used.
+		visibility := android.EffectiveVisibilityRules(s.ctx, member.Variants()[0])
+		if len(visibility) != 0 {
+			m.AddProperty("visibility", visibility)
+		}
 	}
 
 	addHostDeviceSupportedProperties(&s.sdk.ModuleBase, m)
@@ -447,6 +509,10 @@
 	}
 }
 
+func (s *snapshotBuilder) SdkMemberReferencePropertyTag() android.BpPropertyTag {
+	return sdkMemberReferencePropertyTag
+}
+
 // Get a versioned name appropriate for the SDK snapshot version being taken.
 func (s *snapshotBuilder) versionedSdkMemberName(unversionedName string) string {
 	return versionedSdkMemberName(s.ctx, unversionedName, s.version)
@@ -460,6 +526,23 @@
 	return references
 }
 
+// Get an internal name unique to the sdk.
+func (s *snapshotBuilder) unversionedSdkMemberName(unversionedName string) string {
+	if s.sdk.isInternalMember(unversionedName) {
+		return s.ctx.ModuleName() + "_" + unversionedName
+	} else {
+		return unversionedName
+	}
+}
+
+func (s *snapshotBuilder) unversionedSdkMemberNames(members []string) []string {
+	var references []string = nil
+	for _, m := range members {
+		references = append(references, s.unversionedSdkMemberName(m))
+	}
+	return references
+}
+
 var _ android.SdkMember = (*sdkMember)(nil)
 
 type sdkMember struct {