Merge "add apex_pubkey and apex_manifest.pb to the bundle module"
diff --git a/README.md b/README.md
index 37feb1d..b6fda50 100644
--- a/README.md
+++ b/README.md
@@ -74,7 +74,7 @@
 ```
 
 Variables are scoped to the remainder of the file they are declared in, as well
-as any child blueprint files.  Variables are immutable with one exception - they
+as any child Android.bp files.  Variables are immutable with one exception - they
 can be appended to with a += assignment, but only before they have been
 referenced.
 
@@ -168,37 +168,114 @@
 }
 ```
 
-### Name resolution
+### Referencing Modules
 
-Soong provides the ability for modules in different directories to specify
-the same name, as long as each module is declared within a separate namespace.
-A namespace can be declared like this:
+A module `libfoo` can be referenced by its name
 
 ```
-soong_namespace {
-    imports: ["path/to/otherNamespace1", "path/to/otherNamespace2"],
+cc_binary {
+    name: "app",
+    shared_libs: ["libfoo"],
 }
 ```
 
-Each Soong module is assigned a namespace based on its location in the tree.
-Each Soong module is considered to be in the namespace defined by the
-soong_namespace found in an Android.bp in the current directory or closest
-ancestor directory, unless no such soong_namespace module is found, in which
-case the module is considered to be in the implicit root namespace.
+Obviously, this works only if there is only one `libfoo` module in the source
+tree. Ensuring such name uniqueness for larger trees may become problematic. We
+might also want to use the same name in multiple mutually exclusive subtrees
+(for example, implementing different devices) deliberately in order to describe
+a functionally equivalent module. Enter Soong namespaces.
 
-When Soong attempts to resolve dependency D declared my module M in namespace
-N which imports namespaces I1, I2, I3..., then if D is a fully-qualified name
-of the form "//namespace:module", only the specified namespace will be searched
-for the specified module name. Otherwise, Soong will first look for a module
-named D declared in namespace N. If that module does not exist, Soong will look
-for a module named D in namespaces I1, I2, I3... Lastly, Soong will look in the
-root namespace.
+#### Namespaces
 
-Until we have fully converted from Make to Soong, it will be necessary for the
-Make product config to specify a value of PRODUCT_SOONG_NAMESPACES. Its value
-should be a space-separated list of namespaces that Soong export to Make to be
-built by the `m` command. After we have fully converted from Make to Soong, the
-details of enabling namespaces could potentially change.
+A presense of the `soong_namespace {..}` in an Android.bp file defines a
+**namespace**. For instance, having
+
+```
+soong_namespace {
+    ...
+}
+...
+```
+
+in `device/google/bonito/Android.bp` informs Soong that within the
+`device/google/bonito` package the module names are unique, that is, all the
+modules defined in the Android.bp files in the `device/google/bonito/` tree have
+unique names. However, there may be modules with the same names outside
+`device/google/bonito` tree. Indeed, there is a module `"pixelstats-vendor"`
+both in `device/google/bonito/pixelstats` and in
+`device/google/coral/pixelstats`.
+
+The name of a namespace is the path of its directory. The name of the namespace
+in the example above is thus `device/google/bonito`.
+
+An implicit **global namespace** corresponds to the source tree as a whole. It
+has empty name.
+
+A module name's **scope** is the smallest namespace containing it. Suppose a
+source tree has `device/my` and `device/my/display` namespaces. If `libfoo`
+module is defined in `device/co/display/lib/Android.bp`, its namespace is
+`device/co/display`.
+
+The name uniqueness thus means that module's name is unique within its scope. In
+other words, "//_scope_:_name_" is globally unique module reference, e.g,
+`"//device/google/bonito:pixelstats-vendor"`. _Note_ that the name of the
+namespace for a module may be different from module's package name: `libfoo`
+belongs to `device/my/display` namespace but is contained in
+`device/my/display/lib` package.
+
+#### Name Resolution
+
+The form of a module reference determines how Soong locates the module.
+
+For a **global reference** of the "//_scope_:_name_" form, Soong verifies there
+is a namespace called "_scope_", then verifies it contains a "_name_" module and
+uses it. Soong verifies there is only one "_name_" in "_scope_" at the beginning
+when it parses Android.bp files.
+
+A **local reference** has "_name_" form, and resolving it involves looking for a
+module "_name_" in one or more namespaces. By default only the global namespace
+is searched for "_name_" (in other words, only the modules not belonging to an
+explicitly defined scope are considered). The `imports` attribute of the
+`soong_namespaces` allows to specify where to look for modules . For instance,
+with `device/google/bonito/Android.bp` containing
+
+```
+soong_namespace {
+    imports: [
+        "hardware/google/interfaces",
+        "hardware/google/pixel",
+        "hardware/qcom/bootctrl",
+    ],
+}
+```
+
+a reference to `"libpixelstats"` will resolve to the module defined in
+`hardware/google/pixel/pixelstats/Android.bp` because this module is in
+`hardware/google/pixel` namespace.
+
+**TODO**: Conventionally, languages with similar concepts provide separate
+constructs for namespace definition and name resolution (`namespace` and `using`
+in C++, for instance). Should Soong do that, too?
+
+#### Referencing modules in makefiles
+
+While we are gradually converting makefiles to Android.bp files, Android build
+is described by a mixture of Android.bp and Android.mk files, and a module
+defined in an Android.mk file can reference a module defined in Android.bp file.
+For instance, a binary still defined in an Android.mk file may have a library
+defined in already converted Android.bp as a dependency.
+
+A module defined in an Android.bp file and belonging to the global namespace can
+be referenced from a makefile without additional effort. If a module belongs to
+an explicit namespace, it can be referenced from a makefile only after after the
+name of the namespace has been added to the value of PRODUCT_SOONG_NAMESPACES
+variable.
+
+Note that makefiles have no notion of namespaces and exposing namespaces with
+the same modules via PRODUCT_SOONG_NAMESPACES may cause Make failure. For
+instance, exposing both `device/google/bonito` and `device/google/coral`
+namespaces will cause Make failure because it will see two targets for the
+`pixelstats-vendor` module.
 
 ### Visibility
 
@@ -266,7 +343,7 @@
 
 ### Formatter
 
-Soong includes a canonical formatter for blueprint files, similar to
+Soong includes a canonical formatter for Android.bp files, similar to
 [gofmt](https://golang.org/cmd/gofmt/).  To recursively reformat all Android.bp files
 in the current directory:
 ```
diff --git a/android/androidmk.go b/android/androidmk.go
index 4893bf4..f3c15e4 100644
--- a/android/androidmk.go
+++ b/android/androidmk.go
@@ -61,7 +61,7 @@
 
 // Allows modules to customize their Android*.mk output.
 type AndroidMkEntriesProvider interface {
-	AndroidMkEntries() AndroidMkEntries
+	AndroidMkEntries() []AndroidMkEntries
 	BaseModuleName() string
 }
 
@@ -510,10 +510,10 @@
 		return nil
 	}
 
-	entries := provider.AndroidMkEntries()
-	entries.fillInEntries(ctx.Config(), ctx.BlueprintFile(mod), mod)
-
-	entries.write(w)
+	for _, entries := range provider.AndroidMkEntries() {
+		entries.fillInEntries(ctx.Config(), ctx.BlueprintFile(mod), mod)
+		entries.write(w)
+	}
 
 	return nil
 }
diff --git a/android/config.go b/android/config.go
index 1e5a24d..271a54a 100644
--- a/android/config.go
+++ b/android/config.go
@@ -418,6 +418,18 @@
 	return PathForOutput(ctx, "host", c.PrebuiltOS(), "bin", tool)
 }
 
+func (c *config) HostJNIToolPath(ctx PathContext, path string) Path {
+	ext := ".so"
+	if runtime.GOOS == "darwin" {
+		ext = ".dylib"
+	}
+	return PathForOutput(ctx, "host", c.PrebuiltOS(), "lib64", path+ext)
+}
+
+func (c *config) HostJavaToolPath(ctx PathContext, path string) Path {
+	return PathForOutput(ctx, "host", c.PrebuiltOS(), "framework", path)
+}
+
 // HostSystemTool looks for non-hermetic tools from the system we're running on.
 // Generally shouldn't be used, but useful to find the XCode SDK, etc.
 func (c *config) HostSystemTool(name string) string {
diff --git a/android/mutator.go b/android/mutator.go
index eba0e2f..e9ccd7f 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -78,11 +78,11 @@
 	registerLoadHookMutator,
 	RegisterNamespaceMutator,
 	// Rename package module types.
-	registerPackageRenamer,
+	RegisterPackageRenamer,
 	RegisterPrebuiltsPreArchMutators,
-	registerVisibilityRuleChecker,
+	RegisterVisibilityRuleChecker,
 	RegisterDefaultsPreArchMutators,
-	registerVisibilityRuleGatherer,
+	RegisterVisibilityRuleGatherer,
 }
 
 func registerArchMutator(ctx RegisterMutatorsContext) {
@@ -99,7 +99,7 @@
 var postDeps = []RegisterMutatorFunc{
 	registerPathDepsMutator,
 	RegisterPrebuiltsPostDepsMutators,
-	registerVisibilityRuleEnforcer,
+	RegisterVisibilityRuleEnforcer,
 	registerNeverallowMutator,
 	RegisterOverridePostDepsMutators,
 }
diff --git a/android/package.go b/android/package.go
index 880d6a9..ed604c6 100644
--- a/android/package.go
+++ b/android/package.go
@@ -98,7 +98,7 @@
 }
 
 // Registers the function that renames the packages.
-func registerPackageRenamer(ctx RegisterMutatorsContext) {
+func RegisterPackageRenamer(ctx RegisterMutatorsContext) {
 	ctx.BottomUp("packageRenamer", packageRenamer).Parallel()
 	ctx.BottomUp("packageErrorReporter", packageErrorReporter).Parallel()
 }
diff --git a/android/package_ctx.go b/android/package_ctx.go
index cf8face..d3527fa 100644
--- a/android/package_ctx.go
+++ b/android/package_ctx.go
@@ -16,7 +16,6 @@
 
 import (
 	"fmt"
-	"runtime"
 	"strings"
 
 	"github.com/google/blueprint"
@@ -177,46 +176,30 @@
 // package-scoped variable's initialization.
 func (p PackageContext) HostBinToolVariable(name, path string) blueprint.Variable {
 	return p.VariableFunc(name, func(ctx PackageVarContext) string {
-		return p.HostBinToolPath(ctx, path).String()
+		return ctx.Config().HostToolPath(ctx, path).String()
 	})
 }
 
-func (p PackageContext) HostBinToolPath(ctx PackageVarContext, path string) Path {
-	return PathForOutput(ctx, "host", ctx.Config().PrebuiltOS(), "bin", path)
-}
-
 // HostJNIToolVariable returns a Variable whose value is the path to a host tool
 // in the lib directory for host targets. It may only be called during a Go
 // package's initialization - either from the init() function or as part of a
 // package-scoped variable's initialization.
 func (p PackageContext) HostJNIToolVariable(name, path string) blueprint.Variable {
 	return p.VariableFunc(name, func(ctx PackageVarContext) string {
-		return p.HostJNIToolPath(ctx, path).String()
+		return ctx.Config().HostJNIToolPath(ctx, path).String()
 	})
 }
 
-func (p PackageContext) HostJNIToolPath(ctx PackageVarContext, path string) Path {
-	ext := ".so"
-	if runtime.GOOS == "darwin" {
-		ext = ".dylib"
-	}
-	return PathForOutput(ctx, "host", ctx.Config().PrebuiltOS(), "lib64", path+ext)
-}
-
 // HostJavaToolVariable returns a Variable whose value is the path to a host
 // tool in the frameworks directory for host targets. It may only be called
 // during a Go package's initialization - either from the init() function or as
 // part of a package-scoped variable's initialization.
 func (p PackageContext) HostJavaToolVariable(name, path string) blueprint.Variable {
 	return p.VariableFunc(name, func(ctx PackageVarContext) string {
-		return p.HostJavaToolPath(ctx, path).String()
+		return ctx.Config().HostJavaToolPath(ctx, path).String()
 	})
 }
 
-func (p PackageContext) HostJavaToolPath(ctx PackageVarContext, path string) Path {
-	return PathForOutput(ctx, "host", ctx.Config().PrebuiltOS(), "framework", path)
-}
-
 // IntermediatesPathVariable returns a Variable whose value is the intermediate
 // directory appended with the supplied path. It may only be called during a Go
 // package's initialization - either from the init() function or as part of a
diff --git a/android/package_test.go b/android/package_test.go
index ae286d6..8071c51 100644
--- a/android/package_test.go
+++ b/android/package_test.go
@@ -88,7 +88,7 @@
 
 	ctx := NewTestArchContext()
 	ctx.RegisterModuleType("package", PackageFactory)
-	ctx.PreArchMutators(registerPackageRenamer)
+	ctx.PreArchMutators(RegisterPackageRenamer)
 	ctx.Register()
 
 	ctx.MockFileSystem(fs)
diff --git a/android/prebuilt_etc.go b/android/prebuilt_etc.go
index 2701185..388d17f 100644
--- a/android/prebuilt_etc.go
+++ b/android/prebuilt_etc.go
@@ -165,12 +165,12 @@
 	})
 }
 
-func (p *PrebuiltEtc) AndroidMkEntries() AndroidMkEntries {
+func (p *PrebuiltEtc) AndroidMkEntries() []AndroidMkEntries {
 	nameSuffix := ""
 	if p.inRecovery() && !p.onlyInRecovery() {
 		nameSuffix = ".recovery"
 	}
-	return AndroidMkEntries{
+	return []AndroidMkEntries{AndroidMkEntries{
 		Class:      "ETC",
 		SubName:    nameSuffix,
 		OutputFile: OptionalPathForPath(p.outputFilePath),
@@ -187,7 +187,7 @@
 				}
 			},
 		},
-	}
+	}}
 }
 
 func InitPrebuiltEtcModule(p *PrebuiltEtc, dirBase string) {
diff --git a/android/prebuilt_etc_test.go b/android/prebuilt_etc_test.go
index 2c4123f..6bb3ccf 100644
--- a/android/prebuilt_etc_test.go
+++ b/android/prebuilt_etc_test.go
@@ -142,7 +142,7 @@
 	}
 
 	mod := ctx.ModuleForTests("foo", "android_arm64_armv8-a_core").Module().(*PrebuiltEtc)
-	entries := AndroidMkEntriesForTest(t, config, "", mod)
+	entries := AndroidMkEntriesForTest(t, config, "", mod)[0]
 	for k, expectedValue := range expected {
 		if value, ok := entries.EntryMap[k]; ok {
 			if !reflect.DeepEqual(value, expectedValue) {
diff --git a/android/sdk.go b/android/sdk.go
index b9220ca..533bd0e 100644
--- a/android/sdk.go
+++ b/android/sdk.go
@@ -178,7 +178,7 @@
 	// prefer=true. And one that is not versioned, not marked as prefer=true and
 	// will only be used if the equivalently named non-prebuilt module is not
 	// present.
-	AddPrebuiltModule(name string, moduleType string) BpModule
+	AddPrebuiltModule(member SdkMember, moduleType string) BpModule
 }
 
 // A set of properties for use in a .bp file.
diff --git a/android/sh_binary.go b/android/sh_binary.go
index 2b649c4..3293d4f 100644
--- a/android/sh_binary.go
+++ b/android/sh_binary.go
@@ -135,8 +135,8 @@
 	})
 }
 
-func (s *ShBinary) AndroidMkEntries() AndroidMkEntries {
-	return AndroidMkEntries{
+func (s *ShBinary) AndroidMkEntries() []AndroidMkEntries {
+	return []AndroidMkEntries{AndroidMkEntries{
 		Class:      "EXECUTABLES",
 		OutputFile: OptionalPathForPath(s.outputFilePath),
 		Include:    "$(BUILD_SYSTEM)/soong_cc_prebuilt.mk",
@@ -145,7 +145,7 @@
 				s.customAndroidMkEntries(entries)
 			},
 		},
-	}
+	}}
 }
 
 func (s *ShBinary) customAndroidMkEntries(entries *AndroidMkEntries) {
@@ -163,8 +163,8 @@
 	s.data = PathsForModuleSrc(ctx, s.testProperties.Data)
 }
 
-func (s *ShTest) AndroidMkEntries() AndroidMkEntries {
-	return AndroidMkEntries{
+func (s *ShTest) AndroidMkEntries() []AndroidMkEntries {
+	return []AndroidMkEntries{AndroidMkEntries{
 		Class:      "NATIVE_TESTS",
 		OutputFile: OptionalPathForPath(s.outputFilePath),
 		Include:    "$(BUILD_SYSTEM)/soong_cc_prebuilt.mk",
@@ -185,7 +185,7 @@
 				}
 			},
 		},
-	}
+	}}
 }
 
 func InitShBinaryModule(s *ShBinary) {
diff --git a/android/sh_binary_test.go b/android/sh_binary_test.go
index a138754..8488fe4 100644
--- a/android/sh_binary_test.go
+++ b/android/sh_binary_test.go
@@ -42,7 +42,7 @@
 
 	mod := ctx.ModuleForTests("foo", "android_arm64_armv8-a").Module().(*ShTest)
 
-	entries := AndroidMkEntriesForTest(t, config, "", mod)
+	entries := AndroidMkEntriesForTest(t, config, "", mod)[0]
 	expected := []string{":testdata/data1", ":testdata/sub/data2"}
 	actual := entries.EntryMap["LOCAL_TEST_DATA"]
 	if !reflect.DeepEqual(expected, actual) {
diff --git a/android/testing.go b/android/testing.go
index 4b55920..26f1e4d 100644
--- a/android/testing.go
+++ b/android/testing.go
@@ -403,15 +403,18 @@
 
 }
 
-func AndroidMkEntriesForTest(t *testing.T, config Config, bpPath string, mod blueprint.Module) AndroidMkEntries {
+func AndroidMkEntriesForTest(t *testing.T, config Config, bpPath string, mod blueprint.Module) []AndroidMkEntries {
 	var p AndroidMkEntriesProvider
 	var ok bool
 	if p, ok = mod.(AndroidMkEntriesProvider); !ok {
 		t.Errorf("module does not implement AndroidMkEntriesProvider: " + mod.Name())
 	}
-	entries := p.AndroidMkEntries()
-	entries.fillInEntries(config, bpPath, mod)
-	return entries
+
+	entriesList := p.AndroidMkEntries()
+	for i, _ := range entriesList {
+		entriesList[i].fillInEntries(config, bpPath, mod)
+	}
+	return entriesList
 }
 
 func AndroidMkDataForTest(t *testing.T, config Config, bpPath string, mod blueprint.Module) AndroidMkData {
diff --git a/android/visibility.go b/android/visibility.go
index a7e718b..c28ec93 100644
--- a/android/visibility.go
+++ b/android/visibility.go
@@ -117,12 +117,15 @@
 }
 
 func (c compositeRule) String() string {
+	return "[" + strings.Join(c.Strings(), ", ") + "]"
+}
+
+func (c compositeRule) Strings() []string {
 	s := make([]string, 0, len(c))
 	for _, r := range c {
 		s = append(s, r.String())
 	}
-
-	return "[" + strings.Join(s, ", ") + "]"
+	return s
 }
 
 // A packageRule is a visibility rule that matches modules in a specific package (i.e. directory).
@@ -189,7 +192,7 @@
 
 // The rule checker needs to be registered before defaults expansion to correctly check that
 // //visibility:xxx isn't combined with other packages in the same list in any one module.
-func registerVisibilityRuleChecker(ctx RegisterMutatorsContext) {
+func RegisterVisibilityRuleChecker(ctx RegisterMutatorsContext) {
 	ctx.BottomUp("visibilityRuleChecker", visibilityRuleChecker).Parallel()
 }
 
@@ -199,12 +202,12 @@
 // having to process multiple variants for each module. This goes after defaults expansion to gather
 // the complete visibility lists from flat lists and after the package info is gathered to ensure
 // that default_visibility is available.
-func registerVisibilityRuleGatherer(ctx RegisterMutatorsContext) {
+func RegisterVisibilityRuleGatherer(ctx RegisterMutatorsContext) {
 	ctx.BottomUp("visibilityRuleGatherer", visibilityRuleGatherer).Parallel()
 }
 
 // This must be registered after the deps have been resolved.
-func registerVisibilityRuleEnforcer(ctx RegisterMutatorsContext) {
+func RegisterVisibilityRuleEnforcer(ctx RegisterMutatorsContext) {
 	ctx.TopDown("visibilityRuleEnforcer", visibilityRuleEnforcer).Parallel()
 }
 
@@ -384,8 +387,6 @@
 
 	qualified := createQualifiedModuleName(ctx)
 
-	moduleToVisibilityRule := moduleToVisibilityRuleMap(ctx)
-
 	// Visit all the dependencies making sure that this module has access to them all.
 	ctx.VisitDirectDeps(func(dep Module) {
 		depName := ctx.OtherModuleName(dep)
@@ -397,19 +398,25 @@
 			return
 		}
 
-		value, ok := moduleToVisibilityRule.Load(depQualified)
-		var rule compositeRule
-		if ok {
-			rule = value.(compositeRule)
-		} else {
-			rule = packageDefaultVisibility(ctx, depQualified)
-		}
+		rule := effectiveVisibilityRules(ctx, depQualified)
 		if rule != nil && !rule.matches(qualified) {
 			ctx.ModuleErrorf("depends on %s which is not visible to this module", depQualified)
 		}
 	})
 }
 
+func effectiveVisibilityRules(ctx BaseModuleContext, qualified qualifiedModuleName) compositeRule {
+	moduleToVisibilityRule := moduleToVisibilityRuleMap(ctx)
+	value, ok := moduleToVisibilityRule.Load(qualified)
+	var rule compositeRule
+	if ok {
+		rule = value.(compositeRule)
+	} else {
+		rule = packageDefaultVisibility(ctx, qualified)
+	}
+	return rule
+}
+
 func createQualifiedModuleName(ctx BaseModuleContext) qualifiedModuleName {
 	moduleName := ctx.ModuleName()
 	dir := ctx.ModuleDir()
@@ -433,3 +440,19 @@
 		packageQualifiedId = packageQualifiedId.getContainingPackageId()
 	}
 }
+
+// Get the effective visibility rules, i.e. the actual rules that affect the visibility of the
+// property irrespective of where they are defined.
+//
+// Includes visibility rules specified by package default_visibility and/or on defaults.
+// Short hand forms, e.g. //:__subpackages__ are replaced with their full form, e.g.
+// //package/containing/rule:__subpackages__.
+func EffectiveVisibilityRules(ctx BaseModuleContext, module Module) []string {
+	moduleName := ctx.OtherModuleName(module)
+	dir := ctx.OtherModuleDir(module)
+	qualified := qualifiedModuleName{dir, moduleName}
+
+	rule := effectiveVisibilityRules(ctx, qualified)
+
+	return rule.Strings()
+}
diff --git a/android/visibility_test.go b/android/visibility_test.go
index fd9e98c..1984a21 100644
--- a/android/visibility_test.go
+++ b/android/visibility_test.go
@@ -874,11 +874,11 @@
 	ctx.RegisterModuleType("package", PackageFactory)
 	ctx.RegisterModuleType("mock_library", newMockLibraryModule)
 	ctx.RegisterModuleType("mock_defaults", defaultsFactory)
-	ctx.PreArchMutators(registerPackageRenamer)
-	ctx.PreArchMutators(registerVisibilityRuleChecker)
+	ctx.PreArchMutators(RegisterPackageRenamer)
+	ctx.PreArchMutators(RegisterVisibilityRuleChecker)
 	ctx.PreArchMutators(RegisterDefaultsPreArchMutators)
-	ctx.PreArchMutators(registerVisibilityRuleGatherer)
-	ctx.PostDepsMutators(registerVisibilityRuleEnforcer)
+	ctx.PreArchMutators(RegisterVisibilityRuleGatherer)
+	ctx.PostDepsMutators(RegisterVisibilityRuleEnforcer)
 	ctx.Register()
 
 	ctx.MockFileSystem(fs)
diff --git a/apex/apex.go b/apex/apex.go
index 3dde149..81c1230 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -339,6 +339,10 @@
 	// binaries would be installed by default (in PRODUCT_PACKAGES) the other binary will be removed
 	// from PRODUCT_PACKAGES.
 	Overrides []string
+
+	// Whenever apex_payload.img of the APEX should include dm-verity hashtree.
+	// Should be only used in tests#.
+	Test_only_no_hashtree *bool
 }
 
 type apexTargetBundleProperties struct {
@@ -731,6 +735,10 @@
 	return !a.properties.PreventInstall && (a.properties.Installable == nil || proptools.Bool(a.properties.Installable))
 }
 
+func (a *apexBundle) testOnlyShouldSkipHashtreeGeneration() bool {
+	return proptools.Bool(a.properties.Test_only_no_hashtree)
+}
+
 func (a *apexBundle) getImageVariation(config android.DeviceConfig) string {
 	if a.vndkApex {
 		return cc.VendorVariationPrefix + a.vndkVersion(config)
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 944852d..ee5d0f2 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -2380,7 +2380,7 @@
 	p := ctx.ModuleForTests("myapex.prebuilt", "android_common").Module().(*Prebuilt)
 
 	expected := []string{"myapex"}
-	actual := android.AndroidMkEntriesForTest(t, config, "", p).EntryMap["LOCAL_OVERRIDES_MODULES"]
+	actual := android.AndroidMkEntriesForTest(t, config, "", p)[0].EntryMap["LOCAL_OVERRIDES_MODULES"]
 	if !reflect.DeepEqual(actual, expected) {
 		t.Errorf("Incorrect LOCAL_OVERRIDES_MODULES value '%s', expected '%s'", actual, expected)
 	}
diff --git a/apex/builder.go b/apex/builder.go
index aef76fa..3455ec7 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -43,7 +43,7 @@
 			if !ctx.Config().FrameworksBaseDirExists(ctx) {
 				return filepath.Join(prebuiltDir, runtime.GOOS, "bin", tool)
 			} else {
-				return pctx.HostBinToolPath(ctx, tool).String()
+				return ctx.Config().HostToolPath(ctx, tool).String()
 			}
 		})
 	}
@@ -377,7 +377,11 @@
 			optFlags = append(optFlags, "--assets_dir "+filepath.Dir(noticeFile.String()))
 		}
 
-		if !ctx.Config().UnbundledBuild() && a.installable() {
+		if ctx.ModuleDir() != "system/apex/apexd/apexd_testdata" && a.testOnlyShouldSkipHashtreeGeneration() {
+			ctx.PropertyErrorf("test_only_no_hashtree", "not available")
+			return
+		}
+		if (!ctx.Config().UnbundledBuild() && a.installable()) || a.testOnlyShouldSkipHashtreeGeneration() {
 			// Apexes which are supposed to be installed in builtin dirs(/system, etc)
 			// don't need hashtree for activation. Therefore, by removing hashtree from
 			// apex bundle (filesystem image in it, to be specific), we can save storage.
diff --git a/apex/prebuilt.go b/apex/prebuilt.go
index db3b5ef..ba5a466 100644
--- a/apex/prebuilt.go
+++ b/apex/prebuilt.go
@@ -181,8 +181,8 @@
 	// TODO(b/143192278): Add compat symlinks for prebuilt_apex
 }
 
-func (p *Prebuilt) AndroidMkEntries() android.AndroidMkEntries {
-	return android.AndroidMkEntries{
+func (p *Prebuilt) AndroidMkEntries() []android.AndroidMkEntries {
+	return []android.AndroidMkEntries{android.AndroidMkEntries{
 		Class:      "ETC",
 		OutputFile: android.OptionalPathForPath(p.inputApex),
 		Include:    "$(BUILD_PREBUILT)",
@@ -194,5 +194,5 @@
 				entries.AddStrings("LOCAL_OVERRIDES_MODULES", p.properties.Overrides...)
 			},
 		},
-	}
+	}}
 }
diff --git a/cc/androidmk.go b/cc/androidmk.go
index ff181d8..c1225bc 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -317,6 +317,11 @@
 			filepath.Dir(fuzz.corpusIntermediateDir.String())+":corpus/"+d.Base())
 	}
 
+	for _, d := range fuzz.data {
+		fuzzFiles = append(fuzzFiles,
+			filepath.Dir(fuzz.dataIntermediateDir.String())+":data/"+d.Rel())
+	}
+
 	if fuzz.dictionary != nil {
 		fuzzFiles = append(fuzzFiles,
 			filepath.Dir(fuzz.dictionary.String())+":"+fuzz.dictionary.Base())
diff --git a/cc/cc.go b/cc/cc.go
index e80e2a2..e8df8e6 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -94,6 +94,7 @@
 
 	GeneratedSources []string
 	GeneratedHeaders []string
+	GeneratedDeps    []string
 
 	ReexportGeneratedHeaders []string
 
@@ -120,14 +121,16 @@
 	// Paths to generated source files
 	GeneratedSources android.Paths
 	GeneratedHeaders android.Paths
+	GeneratedDeps    android.Paths
 
-	Flags                []string
-	IncludeDirs          android.Paths
-	SystemIncludeDirs    android.Paths
-	ReexportedDirs       android.Paths
-	ReexportedSystemDirs android.Paths
-	ReexportedFlags      []string
-	ReexportedDeps       android.Paths
+	Flags                      []string
+	IncludeDirs                android.Paths
+	SystemIncludeDirs          android.Paths
+	ReexportedDirs             android.Paths
+	ReexportedSystemDirs       android.Paths
+	ReexportedFlags            []string
+	ReexportedGeneratedHeaders android.Paths
+	ReexportedDeps             android.Paths
 
 	// Paths to crt*.o files
 	CrtBegin, CrtEnd android.OptionalPath
@@ -283,6 +286,7 @@
 	isPgoCompile() bool
 	isNDKStubLibrary() bool
 	useClangLld(actx ModuleContext) bool
+	isForPlatform() bool
 	apexName() string
 	hasStubsVariants() bool
 	isStubs() bool
@@ -894,6 +898,13 @@
 	return nil
 }
 
+func (c *Module) ExportedGeneratedHeaders() android.Paths {
+	if flagsProducer, ok := c.linker.(exportedFlagsProducer); ok {
+		return flagsProducer.exportedGeneratedHeaders()
+	}
+	return nil
+}
+
 func isBionic(name string) bool {
 	switch name {
 	case "libc", "libm", "libdl", "libdl_android", "linker":
@@ -1046,10 +1057,6 @@
 		// Host modules do not need ABI dumps.
 		return false
 	}
-	if !ctx.mod.IsForPlatform() {
-		// APEX variants do not need ABI dumps.
-		return false
-	}
 	if ctx.isStubs() {
 		// Stubs do not need ABI dumps.
 		return false
@@ -1076,6 +1083,10 @@
 	return ctx.mod.getVndkExtendsModuleName()
 }
 
+func (ctx *moduleContextImpl) isForPlatform() bool {
+	return ctx.mod.IsForPlatform()
+}
+
 func (ctx *moduleContextImpl) apexName() string {
 	return ctx.mod.ApexName()
 }
@@ -1905,6 +1916,7 @@
 		depPaths.ReexportedSystemDirs = append(depPaths.ReexportedSystemDirs, exporter.exportedSystemDirs()...)
 		depPaths.ReexportedFlags = append(depPaths.ReexportedFlags, exporter.exportedFlags()...)
 		depPaths.ReexportedDeps = append(depPaths.ReexportedDeps, exporter.exportedDeps()...)
+		depPaths.ReexportedGeneratedHeaders = append(depPaths.ReexportedGeneratedHeaders, exporter.exportedGeneratedHeaders()...)
 	}
 
 	ctx.VisitDirectDeps(func(dep android.Module) {
@@ -1928,11 +1940,15 @@
 			case genHeaderDepTag, genHeaderExportDepTag:
 				if genRule, ok := dep.(genrule.SourceFileGenerator); ok {
 					depPaths.GeneratedHeaders = append(depPaths.GeneratedHeaders,
+						genRule.GeneratedSourceFiles()...)
+					depPaths.GeneratedDeps = append(depPaths.GeneratedDeps,
 						genRule.GeneratedDeps()...)
 					dirs := genRule.GeneratedHeaderDirs()
 					depPaths.IncludeDirs = append(depPaths.IncludeDirs, dirs...)
 					if depTag == genHeaderExportDepTag {
 						depPaths.ReexportedDirs = append(depPaths.ReexportedDirs, dirs...)
+						depPaths.ReexportedGeneratedHeaders = append(depPaths.ReexportedGeneratedHeaders,
+							genRule.GeneratedSourceFiles()...)
 						depPaths.ReexportedDeps = append(depPaths.ReexportedDeps, genRule.GeneratedDeps()...)
 						// Add these re-exported flags to help header-abi-dumper to infer the abi exported by a library.
 						c.sabi.Properties.ReexportedIncludes = append(c.sabi.Properties.ReexportedIncludes, dirs.Strings()...)
@@ -2045,7 +2061,8 @@
 			if _, ok := ccDep.(*Module); ok {
 				if i, ok := ccDep.(*Module).linker.(exportedFlagsProducer); ok {
 					depPaths.SystemIncludeDirs = append(depPaths.SystemIncludeDirs, i.exportedSystemDirs()...)
-					depPaths.GeneratedHeaders = append(depPaths.GeneratedHeaders, i.exportedDeps()...)
+					depPaths.GeneratedHeaders = append(depPaths.GeneratedHeaders, i.exportedGeneratedHeaders()...)
+					depPaths.GeneratedDeps = append(depPaths.GeneratedDeps, i.exportedDeps()...)
 					depPaths.Flags = append(depPaths.Flags, i.exportedFlags()...)
 
 					if t.ReexportFlags {
@@ -2243,10 +2260,12 @@
 	depPaths.IncludeDirs = android.FirstUniquePaths(depPaths.IncludeDirs)
 	depPaths.SystemIncludeDirs = android.FirstUniquePaths(depPaths.SystemIncludeDirs)
 	depPaths.GeneratedHeaders = android.FirstUniquePaths(depPaths.GeneratedHeaders)
+	depPaths.GeneratedDeps = android.FirstUniquePaths(depPaths.GeneratedDeps)
 	depPaths.ReexportedDirs = android.FirstUniquePaths(depPaths.ReexportedDirs)
 	depPaths.ReexportedSystemDirs = android.FirstUniquePaths(depPaths.ReexportedSystemDirs)
 	depPaths.ReexportedFlags = android.FirstUniqueStrings(depPaths.ReexportedFlags)
 	depPaths.ReexportedDeps = android.FirstUniquePaths(depPaths.ReexportedDeps)
+	depPaths.ReexportedGeneratedHeaders = android.FirstUniquePaths(depPaths.ReexportedGeneratedHeaders)
 
 	if c.sabi != nil {
 		c.sabi.Properties.ReexportedIncludes = android.FirstUniqueStrings(c.sabi.Properties.ReexportedIncludes)
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 0cbdd52..f378f71 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -421,7 +421,7 @@
 		}`, config)
 
 	module := ctx.ModuleForTests("llndk.libraries.txt", "")
-	entries := android.AndroidMkEntriesForTest(t, config, "", module.Module())
+	entries := android.AndroidMkEntriesForTest(t, config, "", module.Module())[0]
 	assertArrayString(t, entries.EntryMap["LOCAL_MODULE_STEM"], []string{"llndk.libraries.VER.txt"})
 }
 
diff --git a/cc/compiler.go b/cc/compiler.go
index 2bc6ae2..1ced451 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -560,7 +560,7 @@
 }
 
 func (compiler *baseCompiler) compile(ctx ModuleContext, flags Flags, deps PathDeps) Objects {
-	pathDeps := deps.GeneratedHeaders
+	pathDeps := deps.GeneratedDeps
 	pathDeps = append(pathDeps, ndkPathDeps(ctx)...)
 
 	buildFlags := flagsToBuilderFlags(flags)
diff --git a/cc/config/clang.go b/cc/config/clang.go
index 8618d09..eddc341 100644
--- a/cc/config/clang.go
+++ b/cc/config/clang.go
@@ -132,10 +132,6 @@
 		// Disable -Winconsistent-missing-override until we can clean up the existing
 		// codebase for it.
 		"-Wno-inconsistent-missing-override",
-
-		// Warnings from clang-10
-		// Nested and array designated initialization is nice to have.
-		"-Wno-c99-designator",
 	}, " "))
 
 	pctx.StaticVariable("ClangExtraCppflags", strings.Join([]string{
@@ -165,10 +161,6 @@
 		// new warnings are fixed.
 		"-Wno-tautological-constant-compare",
 		"-Wno-tautological-type-limit-compare",
-		// http://b/145210666
-		"-Wno-reorder-init-list",
-		// http://b/145211066
-		"-Wno-implicit-int-float-conversion",
 	}, " "))
 
 	// Extra cflags for external third-party projects to disable warnings that
@@ -184,13 +176,6 @@
 		// Bug: http://b/29823425 Disable -Wnull-dereference until the
 		// new instances detected by this warning are fixed.
 		"-Wno-null-dereference",
-
-		// http://b/145211477
-		"-Wno-pointer-compare",
-		// http://b/145211022
-		"-Wno-xor-used-as-pow",
-		// http://b/145211022
-		"-Wno-final-dtor-non-final-class",
 	}, " "))
 }
 
diff --git a/cc/config/global.go b/cc/config/global.go
index bae5555..0a09fa4 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -126,8 +126,8 @@
 
 	// prebuilts/clang default settings.
 	ClangDefaultBase         = "prebuilts/clang/host"
-	ClangDefaultVersion      = "clang-r370808"
-	ClangDefaultShortVersion = "10.0.1"
+	ClangDefaultVersion      = "clang-r365631b"
+	ClangDefaultShortVersion = "9.0.7"
 
 	// Directories with warnings from Android.bp files.
 	WarningAllowedProjects = []string{
diff --git a/cc/fuzz.go b/cc/fuzz.go
index c2b0ff4..0d3cc74 100644
--- a/cc/fuzz.go
+++ b/cc/fuzz.go
@@ -49,6 +49,9 @@
 	// Optional list of seed files to be installed to the fuzz target's output
 	// directory.
 	Corpus []string `android:"path"`
+	// Optional list of data files to be installed to the fuzz target's output
+	// directory. Directory structure relative to the module is preserved.
+	Data []string `android:"path"`
 	// Optional dictionary to be installed to the fuzz target's output directory.
 	Dictionary *string `android:"path"`
 	// Config for running the target on fuzzing infrastructure.
@@ -81,6 +84,8 @@
 	corpus                android.Paths
 	corpusIntermediateDir android.Path
 	config                android.Path
+	data                  android.Paths
+	dataIntermediateDir   android.Path
 	installedSharedDeps   []string
 }
 
@@ -210,6 +215,17 @@
 	builder.Build(pctx, ctx, "copy_corpus", "copy corpus")
 	fuzz.corpusIntermediateDir = intermediateDir
 
+	fuzz.data = android.PathsForModuleSrc(ctx, fuzz.Properties.Data)
+	builder = android.NewRuleBuilder()
+	intermediateDir = android.PathForModuleOut(ctx, "data")
+	for _, entry := range fuzz.data {
+		builder.Command().Text("cp").
+			Input(entry).
+			Output(intermediateDir.Join(ctx, entry.Rel()))
+	}
+	builder.Build(pctx, ctx, "copy_data", "copy data")
+	fuzz.dataIntermediateDir = intermediateDir
+
 	if fuzz.Properties.Dictionary != nil {
 		fuzz.dictionary = android.PathForModuleSrc(ctx, *fuzz.Properties.Dictionary)
 		if fuzz.dictionary.Ext() != ".dict" {
@@ -377,6 +393,19 @@
 			files = append(files, fileToZip{corpusZip, ""})
 		}
 
+		// Package the data into a zipfile.
+		if fuzzModule.data != nil {
+			dataZip := archDir.Join(ctx, module.Name()+"_data.zip")
+			command := builder.Command().BuiltTool(ctx, "soong_zip").
+				FlagWithOutput("-o ", dataZip)
+			for _, f := range fuzzModule.data {
+				intermediateDir := strings.TrimSuffix(f.String(), f.Rel())
+				command.FlagWithArg("-C ", intermediateDir)
+				command.FlagWithInput("-f ", f)
+			}
+			files = append(files, fileToZip{dataZip, ""})
+		}
+
 		// Find and mark all the transiently-dependent shared libraries for
 		// packaging.
 		for _, library := range sharedLibraries {
diff --git a/cc/library.go b/cc/library.go
index 60b00b1..a147956 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -238,6 +238,7 @@
 	systemDirs android.Paths
 	flags      []string
 	deps       android.Paths
+	headers    android.Paths
 }
 
 func (f *flagExporter) exportedIncludes(ctx ModuleContext) android.Paths {
@@ -281,6 +282,12 @@
 	f.deps = append(f.deps, deps...)
 }
 
+// addExportedGeneratedHeaders does nothing but collects generated header files.
+// This can be differ to exportedDeps which may contain phony files to minimize ninja.
+func (f *flagExporter) addExportedGeneratedHeaders(headers ...android.Path) {
+	f.headers = append(f.headers, headers...)
+}
+
 func (f *flagExporter) exportedDirs() android.Paths {
 	return f.dirs
 }
@@ -297,11 +304,16 @@
 	return f.deps
 }
 
+func (f *flagExporter) exportedGeneratedHeaders() android.Paths {
+	return f.headers
+}
+
 type exportedFlagsProducer interface {
 	exportedDirs() android.Paths
 	exportedSystemDirs() android.Paths
 	exportedFlags() []string
 	exportedDeps() android.Paths
+	exportedGeneratedHeaders() android.Paths
 }
 
 var _ exportedFlagsProducer = (*flagExporter)(nil)
@@ -510,6 +522,19 @@
 	if !ctx.shouldCreateSourceAbiDump() {
 		return false
 	}
+	if !ctx.isForPlatform() {
+		if !ctx.hasStubsVariants() {
+			// Skip ABI checks if this library is for APEX but isn't exported.
+			return false
+		}
+		if !Bool(library.Properties.Header_abi_checker.Enabled) {
+			// Skip ABI checks if this library is for APEX and did not explicitly enable
+			// ABI checks.
+			// TODO(b/145608479): ABI checks should be enabled by default. Remove this
+			// after evaluating the extra build time.
+			return false
+		}
+	}
 	return library.classifySourceAbiDump(ctx) != ""
 }
 
@@ -967,12 +992,16 @@
 	library.reexportSystemDirs(deps.ReexportedSystemDirs...)
 	library.reexportFlags(deps.ReexportedFlags...)
 	library.reexportDeps(deps.ReexportedDeps...)
+	library.addExportedGeneratedHeaders(deps.ReexportedGeneratedHeaders...)
 
 	if Bool(library.Properties.Aidl.Export_aidl_headers) {
 		if library.baseCompiler.hasSrcExt(".aidl") {
 			dir := android.PathForModuleGen(ctx, "aidl")
 			library.reexportDirs(dir)
-			library.reexportDeps(library.baseCompiler.pathDeps...) // TODO: restrict to aidl deps
+
+			// TODO: restrict to aidl deps
+			library.reexportDeps(library.baseCompiler.pathDeps...)
+			library.addExportedGeneratedHeaders(library.baseCompiler.pathDeps...)
 		}
 	}
 
@@ -984,7 +1013,10 @@
 			}
 			includes = append(includes, flags.proto.Dir)
 			library.reexportDirs(includes...)
-			library.reexportDeps(library.baseCompiler.pathDeps...) // TODO: restrict to proto deps
+
+			// TODO: restrict to proto deps
+			library.reexportDeps(library.baseCompiler.pathDeps...)
+			library.addExportedGeneratedHeaders(library.baseCompiler.pathDeps...)
 		}
 	}
 
@@ -1002,6 +1034,7 @@
 
 		library.reexportDirs(dir)
 		library.reexportDeps(library.baseCompiler.pathDeps...)
+		library.addExportedGeneratedHeaders(library.baseCompiler.pathDeps...)
 	}
 
 	if library.buildStubs() {
@@ -1405,9 +1438,21 @@
 	return outputFile
 }
 
-var LibrarySdkMemberType = &librarySdkMemberType{}
+var SharedLibrarySdkMemberType = &librarySdkMemberType{
+	prebuiltModuleType: "cc_prebuilt_library_shared",
+	linkTypes:          []string{"shared"},
+}
+
+var StaticLibrarySdkMemberType = &librarySdkMemberType{
+	prebuiltModuleType: "cc_prebuilt_library_static",
+	linkTypes:          []string{"static"},
+}
 
 type librarySdkMemberType struct {
+	prebuiltModuleType string
+
+	// The set of link types supported, set of "static", "shared".
+	linkTypes []string
 }
 
 func (mt *librarySdkMemberType) AddDependencies(mctx android.BottomUpMutatorContext, dependencyTag blueprint.DependencyTag, names []string) {
@@ -1418,11 +1463,13 @@
 			if version == "" {
 				version = LatestStubsVersionFor(mctx.Config(), name)
 			}
-			mctx.AddFarVariationDependencies(append(target.Variations(), []blueprint.Variation{
-				{Mutator: "image", Variation: android.CoreVariation},
-				{Mutator: "link", Variation: "shared"},
-				{Mutator: "version", Variation: version},
-			}...), dependencyTag, name)
+			for _, linkType := range mt.linkTypes {
+				mctx.AddFarVariationDependencies(append(target.Variations(), []blueprint.Variation{
+					{Mutator: "image", Variation: android.CoreVariation},
+					{Mutator: "link", Variation: linkType},
+					{Mutator: "version", Variation: version},
+				}...), dependencyTag, name)
+			}
 		}
 	}
 }
@@ -1434,11 +1481,51 @@
 
 // copy exported header files and stub *.so files
 func (mt *librarySdkMemberType) BuildSnapshot(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, member android.SdkMember) {
-	info := organizeVariants(member)
-	buildSharedNativeLibSnapshot(sdkModuleContext, info, builder)
+	info := mt.organizeVariants(member)
+	buildSharedNativeLibSnapshot(sdkModuleContext, info, builder, member)
 }
 
-func buildSharedNativeLibSnapshot(sdkModuleContext android.ModuleContext, info *nativeLibInfo, builder android.SnapshotBuilder) {
+// Organize the variants by architecture.
+func (mt *librarySdkMemberType) organizeVariants(member android.SdkMember) *nativeLibInfo {
+	info := &nativeLibInfo{
+		name:       member.Name(),
+		memberType: mt,
+	}
+
+	for _, variant := range member.Variants() {
+		ccModule := variant.(*Module)
+
+		info.archVariants = append(info.archVariants, archSpecificNativeLibInfo{
+			name:                      ccModule.BaseModuleName(),
+			archType:                  ccModule.Target().Arch.ArchType.String(),
+			exportedIncludeDirs:       ccModule.ExportedIncludeDirs(),
+			exportedSystemIncludeDirs: ccModule.ExportedSystemIncludeDirs(),
+			exportedFlags:             ccModule.ExportedFlags(),
+			exportedGeneratedHeaders:  ccModule.ExportedGeneratedHeaders(),
+			outputFile:                ccModule.OutputFile().Path(),
+		})
+	}
+
+	// Determine if include dirs and flags for each variant are different across arch-specific
+	// variants or not. And set hasArchSpecificFlags accordingly
+	// by default, include paths and flags are assumed to be the same across arches
+	info.hasArchSpecificFlags = false
+	oldSignature := ""
+	for _, av := range info.archVariants {
+		newSignature := av.signature()
+		if oldSignature == "" {
+			oldSignature = newSignature
+		}
+		if oldSignature != newSignature {
+			info.hasArchSpecificFlags = true
+			break
+		}
+	}
+
+	return info
+}
+
+func buildSharedNativeLibSnapshot(sdkModuleContext android.ModuleContext, info *nativeLibInfo, builder android.SnapshotBuilder, member android.SdkMember) {
 	// a function for emitting include dirs
 	printExportedDirCopyCommandsForNativeLibs := func(lib archSpecificNativeLibInfo) {
 		includeDirs := lib.exportedIncludeDirs
@@ -1448,7 +1535,7 @@
 		}
 		for _, dir := range includeDirs {
 			if _, gen := dir.(android.WritablePath); gen {
-				// generated headers are copied via exportedDeps. See below.
+				// generated headers are copied via exportedGeneratedHeaders. See below.
 				continue
 			}
 			targetDir := nativeIncludeDir
@@ -1465,7 +1552,7 @@
 			}
 		}
 
-		genHeaders := lib.exportedDeps
+		genHeaders := lib.exportedGeneratedHeaders
 		for _, file := range genHeaders {
 			targetDir := nativeGeneratedIncludeDir
 			if info.hasArchSpecificFlags {
@@ -1482,17 +1569,17 @@
 
 	// for each architecture
 	for _, av := range info.archVariants {
-		builder.CopyToSnapshot(av.outputFile, nativeStubFilePathFor(av))
+		builder.CopyToSnapshot(av.outputFile, nativeLibraryPathFor(av))
 
 		if info.hasArchSpecificFlags {
 			printExportedDirCopyCommandsForNativeLibs(av)
 		}
 	}
 
-	info.generatePrebuiltLibrary(sdkModuleContext, builder)
+	info.generatePrebuiltLibrary(sdkModuleContext, builder, member)
 }
 
-func (info *nativeLibInfo) generatePrebuiltLibrary(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder) {
+func (info *nativeLibInfo) generatePrebuiltLibrary(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, member android.SdkMember) {
 
 	// a function for emitting include dirs
 	addExportedDirsForNativeLibs := func(lib archSpecificNativeLibInfo, properties android.BpPropertySet, systemInclude bool) {
@@ -1509,7 +1596,7 @@
 		properties.AddProperty(propertyName, includeDirs)
 	}
 
-	pbm := builder.AddPrebuiltModule(info.name, "cc_prebuilt_library_shared")
+	pbm := builder.AddPrebuiltModule(member, info.memberType.prebuiltModuleType)
 
 	if !info.hasArchSpecificFlags {
 		addExportedDirsForNativeLibs(info.archVariants[0], pbm, false /*systemInclude*/)
@@ -1519,7 +1606,7 @@
 	archProperties := pbm.AddPropertySet("arch")
 	for _, av := range info.archVariants {
 		archTypeProperties := archProperties.AddPropertySet(av.archType)
-		archTypeProperties.AddProperty("srcs", []string{nativeStubFilePathFor(av)})
+		archTypeProperties.AddProperty("srcs", []string{nativeLibraryPathFor(av)})
 		if info.hasArchSpecificFlags {
 			// export_* properties are added inside the arch: {<arch>: {...}} block
 			addExportedDirsForNativeLibs(av, archTypeProperties, false /*systemInclude*/)
@@ -1534,13 +1621,12 @@
 	nativeIncludeDir          = "include"
 	nativeGeneratedIncludeDir = "include_gen"
 	nativeStubDir             = "lib"
-	nativeStubFileSuffix      = ".so"
 )
 
-// path to the stub file of a native shared library. Relative to <sdk_root>/<api_dir>
-func nativeStubFilePathFor(lib archSpecificNativeLibInfo) string {
+// path to the native library. Relative to <sdk_root>/<api_dir>
+func nativeLibraryPathFor(lib archSpecificNativeLibInfo) string {
 	return filepath.Join(lib.archType,
-		nativeStubDir, lib.name+nativeStubFileSuffix)
+		nativeStubDir, lib.outputFile.Base())
 }
 
 // paths to the include dirs of a native shared library. Relative to <sdk_root>/<api_dir>
@@ -1574,7 +1660,7 @@
 	exportedIncludeDirs       android.Paths
 	exportedSystemIncludeDirs android.Paths
 	exportedFlags             []string
-	exportedDeps              android.Paths
+	exportedGeneratedHeaders  android.Paths
 	outputFile                android.Path
 }
 
@@ -1589,45 +1675,9 @@
 // nativeLibInfo represents a collection of arch-specific modules having the same name
 type nativeLibInfo struct {
 	name         string
+	memberType   *librarySdkMemberType
 	archVariants []archSpecificNativeLibInfo
 	// hasArchSpecificFlags is set to true if modules for each architecture all have the same
 	// include dirs, flags, etc, in which case only those of the first arch is selected.
 	hasArchSpecificFlags bool
 }
-
-// Organize the variants by architecture.
-func organizeVariants(member android.SdkMember) *nativeLibInfo {
-	info := &nativeLibInfo{name: member.Name()}
-
-	for _, variant := range member.Variants() {
-		ccModule := variant.(*Module)
-
-		info.archVariants = append(info.archVariants, archSpecificNativeLibInfo{
-			name:                      ccModule.BaseModuleName(),
-			archType:                  ccModule.Target().Arch.ArchType.String(),
-			exportedIncludeDirs:       ccModule.ExportedIncludeDirs(),
-			exportedSystemIncludeDirs: ccModule.ExportedSystemIncludeDirs(),
-			exportedFlags:             ccModule.ExportedFlags(),
-			exportedDeps:              ccModule.ExportedDeps(),
-			outputFile:                ccModule.OutputFile().Path(),
-		})
-	}
-
-	// Determine if include dirs and flags for each variant are different across arch-specific
-	// variants or not. And set hasArchSpecificFlags accordingly
-	// by default, include paths and flags are assumed to be the same across arches
-	info.hasArchSpecificFlags = false
-	oldSignature := ""
-	for _, av := range info.archVariants {
-		newSignature := av.signature()
-		if oldSignature == "" {
-			oldSignature = newSignature
-		}
-		if oldSignature != newSignature {
-			info.hasArchSpecificFlags = true
-			break
-		}
-	}
-
-	return info
-}
diff --git a/cc/ndk_library.go b/cc/ndk_library.go
index da94d33..c47cbf0 100644
--- a/cc/ndk_library.go
+++ b/cc/ndk_library.go
@@ -261,7 +261,6 @@
 		// We're knowingly doing some otherwise unsightly things with builtin
 		// functions here. We're just generating stub libraries, so ignore it.
 		"-Wno-incompatible-library-redeclaration",
-		"-Wno-incomplete-setjmp-declaration",
 		"-Wno-builtin-requires-header",
 		"-Wno-invalid-noreturn",
 		"-Wall",
diff --git a/cc/prebuilt.go b/cc/prebuilt.go
index 4e6cdd7..f20616f 100644
--- a/cc/prebuilt.go
+++ b/cc/prebuilt.go
@@ -90,6 +90,7 @@
 		p.libraryDecorator.reexportSystemDirs(deps.ReexportedSystemDirs...)
 		p.libraryDecorator.reexportFlags(deps.ReexportedFlags...)
 		p.libraryDecorator.reexportDeps(deps.ReexportedDeps...)
+		p.libraryDecorator.addExportedGeneratedHeaders(deps.ReexportedGeneratedHeaders...)
 
 		builderFlags := flagsToBuilderFlags(flags)
 
@@ -129,16 +130,8 @@
 	p.properties.Srcs = nil
 }
 
-// cc_prebuilt_library_shared installs a precompiled shared library that are
-// listed in the srcs property in the device's directory.
-func PrebuiltSharedLibraryFactory() android.Module {
-	module, _ := NewPrebuiltSharedLibrary(android.HostAndDeviceSupported)
-	return module.Init()
-}
-
-func NewPrebuiltSharedLibrary(hod android.HostOrDeviceSupported) (*Module, *libraryDecorator) {
+func NewPrebuiltLibrary(hod android.HostOrDeviceSupported) (*Module, *libraryDecorator) {
 	module, library := NewLibrary(hod)
-	library.BuildOnlyShared()
 	module.compiler = nil
 
 	prebuilt := &prebuiltLibraryLinker{
@@ -150,9 +143,24 @@
 
 	android.InitPrebuiltModule(module, &prebuilt.properties.Srcs)
 
-	// Prebuilt libraries can be included in APEXes
-	android.InitApexModule(module)
+	// Prebuilt libraries can be used in SDKs.
 	android.InitSdkAwareModule(module)
+	return module, library
+}
+
+// cc_prebuilt_library_shared installs a precompiled shared library that are
+// listed in the srcs property in the device's directory.
+func PrebuiltSharedLibraryFactory() android.Module {
+	module, _ := NewPrebuiltSharedLibrary(android.HostAndDeviceSupported)
+	return module.Init()
+}
+
+func NewPrebuiltSharedLibrary(hod android.HostOrDeviceSupported) (*Module, *libraryDecorator) {
+	module, library := NewPrebuiltLibrary(hod)
+	library.BuildOnlyShared()
+
+	// Prebuilt shared libraries can be included in APEXes
+	android.InitApexModule(module)
 
 	return module, library
 }
@@ -165,19 +173,8 @@
 }
 
 func NewPrebuiltStaticLibrary(hod android.HostOrDeviceSupported) (*Module, *libraryDecorator) {
-	module, library := NewLibrary(hod)
+	module, library := NewPrebuiltLibrary(hod)
 	library.BuildOnlyStatic()
-	module.compiler = nil
-
-	prebuilt := &prebuiltLibraryLinker{
-		libraryDecorator: library,
-	}
-	module.linker = prebuilt
-
-	module.AddProperties(&prebuilt.properties)
-
-	android.InitPrebuiltModule(module, &prebuilt.properties.Srcs)
-	android.InitSdkAwareModule(module)
 	return module, library
 }
 
diff --git a/cc/rs.go b/cc/rs.go
index 61fd1a8..9149e17 100644
--- a/cc/rs.go
+++ b/cc/rs.go
@@ -29,7 +29,7 @@
 			// Use RenderScript prebuilts for unbundled builds but not PDK builds
 			return filepath.Join("prebuilts/sdk/tools", runtime.GOOS, "bin/llvm-rs-cc")
 		} else {
-			return pctx.HostBinToolPath(ctx, "llvm-rs-cc").String()
+			return ctx.Config().HostToolPath(ctx, "llvm-rs-cc").String()
 		}
 	})
 }
diff --git a/cc/vndk.go b/cc/vndk.go
index f25861a..f531af3 100644
--- a/cc/vndk.go
+++ b/cc/vndk.go
@@ -460,8 +460,8 @@
 	ctx.InstallFile(installPath, filename, txt.outputFile)
 }
 
-func (txt *vndkLibrariesTxt) AndroidMkEntries() android.AndroidMkEntries {
-	return android.AndroidMkEntries{
+func (txt *vndkLibrariesTxt) AndroidMkEntries() []android.AndroidMkEntries {
+	return []android.AndroidMkEntries{android.AndroidMkEntries{
 		Class:      "ETC",
 		OutputFile: android.OptionalPathForPath(txt.outputFile),
 		ExtraEntries: []android.AndroidMkExtraEntriesFunc{
@@ -469,7 +469,7 @@
 				entries.SetString("LOCAL_MODULE_STEM", txt.outputFile.Base())
 			},
 		},
-	}
+	}}
 }
 
 func (txt *vndkLibrariesTxt) OutputFile() android.OutputPath {
@@ -704,7 +704,7 @@
 		// We glob headers from include directories inside source tree. So we first gather
 		// all include directories inside our source tree. On the contrast, we manually
 		// collect generated headers from dependencies as they can't globbed.
-		generatedHeaders = append(generatedHeaders, l.exportedDeps()...)
+		generatedHeaders = append(generatedHeaders, l.exportedGeneratedHeaders()...)
 		for _, dir := range append(l.exportedDirs(), l.exportedSystemDirs()...) {
 			exportedIncludes[dir.String()] = true
 		}
diff --git a/docs/best_practices.md b/docs/best_practices.md
index 93be319..bc760b8 100644
--- a/docs/best_practices.md
+++ b/docs/best_practices.md
@@ -240,8 +240,8 @@
 In cases where the names cannot be made unique a `soong_namespace` should be
 used to partition a set of modules so that they are built only when the
 namespace is listed in `PRODUCT_SOONG_NAMESPACES`.  See the
-[Name resolution](../README.md#name-resolution) section of the Soong README.md
-for more on namespaces.
+[Referencing Modules](../README.md#referencing-modules) section of the Soong
+README.md for more on namespaces.
 
 ### Module with name based on variable
 
diff --git a/java/androidmk.go b/java/androidmk.go
index c973739..f4e3c34 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -17,101 +17,103 @@
 import (
 	"fmt"
 	"io"
-	"strings"
 
 	"android/soong/android"
 )
 
-// TODO(jungjw): We'll probably want AndroidMkEntriesProvider.AndroidMkEntries to return multiple
-// entries so that this can be more error-proof.
-func (library *Library) AndroidMkHostDex(w io.Writer, name string, entries *android.AndroidMkEntries) {
-	if Bool(library.deviceProperties.Hostdex) && !library.Host() {
-		fmt.Fprintln(w, "include $(CLEAR_VARS)")
-		fmt.Fprintln(w, "LOCAL_MODULE := "+name+"-hostdex")
-		fmt.Fprintln(w, "LOCAL_IS_HOST_MODULE := true")
-		fmt.Fprintln(w, "LOCAL_MODULE_CLASS := JAVA_LIBRARIES")
-		if library.dexJarFile != nil {
-			fmt.Fprintln(w, "LOCAL_PREBUILT_MODULE_FILE :=", library.dexJarFile.String())
-		} else {
-			fmt.Fprintln(w, "LOCAL_PREBUILT_MODULE_FILE :=", library.implementationAndResourcesJar.String())
-		}
-		if library.dexJarFile != nil {
-			fmt.Fprintln(w, "LOCAL_SOONG_DEX_JAR :=", library.dexJarFile.String())
-		}
-		fmt.Fprintln(w, "LOCAL_SOONG_HEADER_JAR :=", library.headerJarFile.String())
-		fmt.Fprintln(w, "LOCAL_SOONG_CLASSES_JAR :=", library.implementationAndResourcesJar.String())
-		if len(entries.Required) > 0 {
-			fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES :=", strings.Join(entries.Required, " "))
-		}
-		if len(entries.Host_required) > 0 {
-			fmt.Fprintln(w, "LOCAL_HOST_REQUIRED_MODULES :=", strings.Join(entries.Host_required, " "))
-		}
-		if len(entries.Target_required) > 0 {
-			fmt.Fprintln(w, "LOCAL_TARGET_REQUIRED_MODULES :=", strings.Join(entries.Target_required, " "))
-		}
-		if r := library.deviceProperties.Target.Hostdex.Required; len(r) > 0 {
-			fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES +=", strings.Join(r, " "))
-		}
-		fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", library.Stem()+"-hostdex")
-		fmt.Fprintln(w, "include $(BUILD_SYSTEM)/soong_java_prebuilt.mk")
+func (library *Library) AndroidMkEntriesHostDex() android.AndroidMkEntries {
+	hostDexNeeded := Bool(library.deviceProperties.Hostdex) && !library.Host()
+	if !library.IsForPlatform() {
+		// If the platform variant is available, don't emit hostdex modules from the APEX variants
+		hostDexNeeded = false
 	}
+
+	if hostDexNeeded {
+		var output android.Path
+		if library.dexJarFile != nil {
+			output = library.dexJarFile
+		} else {
+			output = library.implementationAndResourcesJar
+		}
+		return android.AndroidMkEntries{
+			Class:      "JAVA_LIBRARIES",
+			SubName:    "-hostdex",
+			OutputFile: android.OptionalPathForPath(output),
+			Required:   library.deviceProperties.Target.Hostdex.Required,
+			Include:    "$(BUILD_SYSTEM)/soong_java_prebuilt.mk",
+			ExtraEntries: []android.AndroidMkExtraEntriesFunc{
+				func(entries *android.AndroidMkEntries) {
+					entries.SetBool("LOCAL_IS_HOST_MODULE", true)
+					entries.SetPath("LOCAL_PREBUILT_MODULE_FILE", output)
+					if library.dexJarFile != nil {
+						entries.SetPath("LOCAL_SOONG_DEX_JAR", library.dexJarFile)
+					}
+					entries.SetPath("LOCAL_SOONG_HEADER_JAR", library.headerJarFile)
+					entries.SetPath("LOCAL_SOONG_CLASSES_JAR", library.implementationAndResourcesJar)
+					entries.SetString("LOCAL_MODULE_STEM", library.Stem()+"-hostdex")
+				},
+			},
+		}
+	}
+	return android.AndroidMkEntries{Disabled: true}
 }
 
-func (library *Library) AndroidMkEntries() android.AndroidMkEntries {
-	if !library.IsForPlatform() {
-		return android.AndroidMkEntries{
-			Disabled: true,
+func (library *Library) AndroidMkEntries() []android.AndroidMkEntries {
+	var entriesList []android.AndroidMkEntries
+
+	mainEntries := android.AndroidMkEntries{Disabled: true}
+	// For a java library built for an APEX, we don't need Make module
+	if library.IsForPlatform() {
+		mainEntries = android.AndroidMkEntries{
+			Class:      "JAVA_LIBRARIES",
+			OutputFile: android.OptionalPathForPath(library.outputFile),
+			Include:    "$(BUILD_SYSTEM)/soong_java_prebuilt.mk",
+			ExtraEntries: []android.AndroidMkExtraEntriesFunc{
+				func(entries *android.AndroidMkEntries) {
+					if len(library.logtagsSrcs) > 0 {
+						var logtags []string
+						for _, l := range library.logtagsSrcs {
+							logtags = append(logtags, l.Rel())
+						}
+						entries.AddStrings("LOCAL_LOGTAGS_FILES", logtags...)
+					}
+
+					if library.installFile == nil {
+						entries.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", true)
+					}
+					if library.dexJarFile != nil {
+						entries.SetPath("LOCAL_SOONG_DEX_JAR", library.dexJarFile)
+					}
+					if len(library.dexpreopter.builtInstalled) > 0 {
+						entries.SetString("LOCAL_SOONG_BUILT_INSTALLED", library.dexpreopter.builtInstalled)
+					}
+					entries.SetString("LOCAL_SDK_VERSION", library.sdkVersion())
+					entries.SetPath("LOCAL_SOONG_CLASSES_JAR", library.implementationAndResourcesJar)
+					entries.SetPath("LOCAL_SOONG_HEADER_JAR", library.headerJarFile)
+
+					if library.jacocoReportClassesFile != nil {
+						entries.SetPath("LOCAL_SOONG_JACOCO_REPORT_CLASSES_JAR", library.jacocoReportClassesFile)
+					}
+
+					entries.AddStrings("LOCAL_EXPORT_SDK_LIBRARIES", library.exportedSdkLibs...)
+
+					if len(library.additionalCheckedModules) != 0 {
+						entries.AddStrings("LOCAL_ADDITIONAL_CHECKED_MODULE", library.additionalCheckedModules.Strings()...)
+					}
+
+					if library.proguardDictionary != nil {
+						entries.SetPath("LOCAL_SOONG_PROGUARD_DICT", library.proguardDictionary)
+					}
+					entries.SetString("LOCAL_MODULE_STEM", library.Stem())
+				},
+			},
 		}
 	}
-	return android.AndroidMkEntries{
-		Class:      "JAVA_LIBRARIES",
-		OutputFile: android.OptionalPathForPath(library.outputFile),
-		Include:    "$(BUILD_SYSTEM)/soong_java_prebuilt.mk",
-		ExtraEntries: []android.AndroidMkExtraEntriesFunc{
-			func(entries *android.AndroidMkEntries) {
-				if len(library.logtagsSrcs) > 0 {
-					var logtags []string
-					for _, l := range library.logtagsSrcs {
-						logtags = append(logtags, l.Rel())
-					}
-					entries.AddStrings("LOCAL_LOGTAGS_FILES", logtags...)
-				}
 
-				if library.installFile == nil {
-					entries.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", true)
-				}
-				if library.dexJarFile != nil {
-					entries.SetPath("LOCAL_SOONG_DEX_JAR", library.dexJarFile)
-				}
-				if len(library.dexpreopter.builtInstalled) > 0 {
-					entries.SetString("LOCAL_SOONG_BUILT_INSTALLED", library.dexpreopter.builtInstalled)
-				}
-				entries.SetString("LOCAL_SDK_VERSION", library.sdkVersion())
-				entries.SetPath("LOCAL_SOONG_CLASSES_JAR", library.implementationAndResourcesJar)
-				entries.SetPath("LOCAL_SOONG_HEADER_JAR", library.headerJarFile)
+	hostDexEntries := library.AndroidMkEntriesHostDex()
 
-				if library.jacocoReportClassesFile != nil {
-					entries.SetPath("LOCAL_SOONG_JACOCO_REPORT_CLASSES_JAR", library.jacocoReportClassesFile)
-				}
-
-				entries.AddStrings("LOCAL_EXPORT_SDK_LIBRARIES", library.exportedSdkLibs...)
-
-				if len(library.additionalCheckedModules) != 0 {
-					entries.AddStrings("LOCAL_ADDITIONAL_CHECKED_MODULE", library.additionalCheckedModules.Strings()...)
-				}
-
-				if library.proguardDictionary != nil {
-					entries.SetPath("LOCAL_SOONG_PROGUARD_DICT", library.proguardDictionary)
-				}
-				entries.SetString("LOCAL_MODULE_STEM", library.Stem())
-			},
-		},
-		ExtraFooters: []android.AndroidMkExtraFootersFunc{
-			func(w io.Writer, name, prefix, moduleDir string, entries *android.AndroidMkEntries) {
-				library.AndroidMkHostDex(w, name, entries)
-			},
-		},
-	}
+	entriesList = append(entriesList, mainEntries, hostDexEntries)
+	return entriesList
 }
 
 // Called for modules that are a component of a test suite.
@@ -124,8 +126,9 @@
 	}
 }
 
-func (j *Test) AndroidMkEntries() android.AndroidMkEntries {
-	entries := j.Library.AndroidMkEntries()
+func (j *Test) AndroidMkEntries() []android.AndroidMkEntries {
+	entriesList := j.Library.AndroidMkEntries()
+	entries := &entriesList[0]
 	entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
 		testSuiteComponent(entries, j.testProperties.Test_suites)
 		if j.testConfig != nil {
@@ -134,25 +137,26 @@
 		androidMkWriteTestData(j.data, entries)
 	})
 
-	return entries
+	return entriesList
 }
 
-func (j *TestHelperLibrary) AndroidMkEntries() android.AndroidMkEntries {
-	entries := j.Library.AndroidMkEntries()
+func (j *TestHelperLibrary) AndroidMkEntries() []android.AndroidMkEntries {
+	entriesList := j.Library.AndroidMkEntries()
+	entries := &entriesList[0]
 	entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
 		testSuiteComponent(entries, j.testHelperLibraryProperties.Test_suites)
 	})
 
-	return entries
+	return entriesList
 }
 
-func (prebuilt *Import) AndroidMkEntries() android.AndroidMkEntries {
+func (prebuilt *Import) AndroidMkEntries() []android.AndroidMkEntries {
 	if !prebuilt.IsForPlatform() || !prebuilt.ContainingSdk().Unversioned() {
-		return android.AndroidMkEntries{
+		return []android.AndroidMkEntries{android.AndroidMkEntries{
 			Disabled: true,
-		}
+		}}
 	}
-	return android.AndroidMkEntries{
+	return []android.AndroidMkEntries{android.AndroidMkEntries{
 		Class:      "JAVA_LIBRARIES",
 		OutputFile: android.OptionalPathForPath(prebuilt.combinedClasspathFile),
 		Include:    "$(BUILD_SYSTEM)/soong_java_prebuilt.mk",
@@ -165,16 +169,16 @@
 				entries.SetString("LOCAL_MODULE_STEM", prebuilt.Stem())
 			},
 		},
-	}
+	}}
 }
 
-func (prebuilt *DexImport) AndroidMkEntries() android.AndroidMkEntries {
+func (prebuilt *DexImport) AndroidMkEntries() []android.AndroidMkEntries {
 	if !prebuilt.IsForPlatform() {
-		return android.AndroidMkEntries{
+		return []android.AndroidMkEntries{android.AndroidMkEntries{
 			Disabled: true,
-		}
+		}}
 	}
-	return android.AndroidMkEntries{
+	return []android.AndroidMkEntries{android.AndroidMkEntries{
 		Class:      "JAVA_LIBRARIES",
 		OutputFile: android.OptionalPathForPath(prebuilt.maybeStrippedDexJarFile),
 		Include:    "$(BUILD_SYSTEM)/soong_java_prebuilt.mk",
@@ -193,11 +197,11 @@
 				entries.SetString("LOCAL_MODULE_STEM", prebuilt.Stem())
 			},
 		},
-	}
+	}}
 }
 
-func (prebuilt *AARImport) AndroidMkEntries() android.AndroidMkEntries {
-	return android.AndroidMkEntries{
+func (prebuilt *AARImport) AndroidMkEntries() []android.AndroidMkEntries {
+	return []android.AndroidMkEntries{android.AndroidMkEntries{
 		Class:      "JAVA_LIBRARIES",
 		OutputFile: android.OptionalPathForPath(prebuilt.classpathFile),
 		Include:    "$(BUILD_SYSTEM)/soong_java_prebuilt.mk",
@@ -213,13 +217,13 @@
 				entries.SetString("LOCAL_SDK_VERSION", prebuilt.sdkVersion())
 			},
 		},
-	}
+	}}
 }
 
-func (binary *Binary) AndroidMkEntries() android.AndroidMkEntries {
+func (binary *Binary) AndroidMkEntries() []android.AndroidMkEntries {
 
 	if !binary.isWrapperVariant {
-		return android.AndroidMkEntries{
+		return []android.AndroidMkEntries{android.AndroidMkEntries{
 			Class:      "JAVA_LIBRARIES",
 			OutputFile: android.OptionalPathForPath(binary.outputFile),
 			Include:    "$(BUILD_SYSTEM)/soong_java_prebuilt.mk",
@@ -240,9 +244,9 @@
 					fmt.Fprintln(w, "jar_installed_module := $(LOCAL_INSTALLED_MODULE)")
 				},
 			},
-		}
+		}}
 	} else {
-		return android.AndroidMkEntries{
+		return []android.AndroidMkEntries{android.AndroidMkEntries{
 			Class:      "EXECUTABLES",
 			OutputFile: android.OptionalPathForPath(binary.wrapperFile),
 			ExtraEntries: []android.AndroidMkExtraEntriesFunc{
@@ -257,17 +261,17 @@
 					fmt.Fprintln(w, "jar_installed_module :=")
 				},
 			},
-		}
+		}}
 	}
 }
 
-func (app *AndroidApp) AndroidMkEntries() android.AndroidMkEntries {
+func (app *AndroidApp) AndroidMkEntries() []android.AndroidMkEntries {
 	if !app.IsForPlatform() {
-		return android.AndroidMkEntries{
+		return []android.AndroidMkEntries{android.AndroidMkEntries{
 			Disabled: true,
-		}
+		}}
 	}
-	return android.AndroidMkEntries{
+	return []android.AndroidMkEntries{android.AndroidMkEntries{
 		Class:      "APPS",
 		OutputFile: android.OptionalPathForPath(app.outputFile),
 		Include:    "$(BUILD_SYSTEM)/soong_app_prebuilt.mk",
@@ -359,7 +363,7 @@
 				}
 			},
 		},
-	}
+	}}
 }
 
 func (a *AndroidApp) getOverriddenPackages() []string {
@@ -373,8 +377,9 @@
 	return overridden
 }
 
-func (a *AndroidTest) AndroidMkEntries() android.AndroidMkEntries {
-	entries := a.AndroidApp.AndroidMkEntries()
+func (a *AndroidTest) AndroidMkEntries() []android.AndroidMkEntries {
+	entriesList := a.AndroidApp.AndroidMkEntries()
+	entries := &entriesList[0]
 	entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
 		testSuiteComponent(entries, a.testProperties.Test_suites)
 		if a.testConfig != nil {
@@ -383,20 +388,22 @@
 		androidMkWriteTestData(a.data, entries)
 	})
 
-	return entries
+	return entriesList
 }
 
-func (a *AndroidTestHelperApp) AndroidMkEntries() android.AndroidMkEntries {
-	entries := a.AndroidApp.AndroidMkEntries()
+func (a *AndroidTestHelperApp) AndroidMkEntries() []android.AndroidMkEntries {
+	entriesList := a.AndroidApp.AndroidMkEntries()
+	entries := &entriesList[0]
 	entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
 		testSuiteComponent(entries, a.appTestHelperAppProperties.Test_suites)
 	})
 
-	return entries
+	return entriesList
 }
 
-func (a *AndroidLibrary) AndroidMkEntries() android.AndroidMkEntries {
-	entries := a.Library.AndroidMkEntries()
+func (a *AndroidLibrary) AndroidMkEntries() []android.AndroidMkEntries {
+	entriesList := a.Library.AndroidMkEntries()
+	entries := &entriesList[0]
 
 	entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
 		if a.aarFile != nil {
@@ -417,11 +424,11 @@
 		entries.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", true)
 	})
 
-	return entries
+	return entriesList
 }
 
-func (jd *Javadoc) AndroidMkEntries() android.AndroidMkEntries {
-	return android.AndroidMkEntries{
+func (jd *Javadoc) AndroidMkEntries() []android.AndroidMkEntries {
+	return []android.AndroidMkEntries{android.AndroidMkEntries{
 		Class:      "JAVA_LIBRARIES",
 		OutputFile: android.OptionalPathForPath(jd.stubsSrcJar),
 		Include:    "$(BUILD_SYSTEM)/soong_droiddoc_prebuilt.mk",
@@ -435,11 +442,11 @@
 				}
 			},
 		},
-	}
+	}}
 }
 
-func (ddoc *Droiddoc) AndroidMkEntries() android.AndroidMkEntries {
-	return android.AndroidMkEntries{
+func (ddoc *Droiddoc) AndroidMkEntries() []android.AndroidMkEntries {
+	return []android.AndroidMkEntries{android.AndroidMkEntries{
 		Class:      "JAVA_LIBRARIES",
 		OutputFile: android.OptionalPathForPath(ddoc.stubsSrcJar),
 		Include:    "$(BUILD_SYSTEM)/soong_droiddoc_prebuilt.mk",
@@ -520,11 +527,11 @@
 				}
 			},
 		},
-	}
+	}}
 }
 
-func (dstubs *Droidstubs) AndroidMkEntries() android.AndroidMkEntries {
-	return android.AndroidMkEntries{
+func (dstubs *Droidstubs) AndroidMkEntries() []android.AndroidMkEntries {
+	return []android.AndroidMkEntries{android.AndroidMkEntries{
 		Class:      "JAVA_LIBRARIES",
 		OutputFile: android.OptionalPathForPath(dstubs.stubsSrcJar),
 		Include:    "$(BUILD_SYSTEM)/soong_droiddoc_prebuilt.mk",
@@ -636,11 +643,11 @@
 				}
 			},
 		},
-	}
+	}}
 }
 
-func (a *AndroidAppImport) AndroidMkEntries() android.AndroidMkEntries {
-	return android.AndroidMkEntries{
+func (a *AndroidAppImport) AndroidMkEntries() []android.AndroidMkEntries {
+	return []android.AndroidMkEntries{android.AndroidMkEntries{
 		Class:      "APPS",
 		OutputFile: android.OptionalPathForPath(a.outputFile),
 		Include:    "$(BUILD_SYSTEM)/soong_app_prebuilt.mk",
@@ -659,16 +666,17 @@
 				entries.AddStrings("LOCAL_INSTALLED_MODULE_STEM", a.installPath.Rel())
 			},
 		},
-	}
+	}}
 }
 
-func (a *AndroidTestImport) AndroidMkEntries() android.AndroidMkEntries {
-	entries := a.AndroidAppImport.AndroidMkEntries()
+func (a *AndroidTestImport) AndroidMkEntries() []android.AndroidMkEntries {
+	entriesList := a.AndroidAppImport.AndroidMkEntries()
+	entries := &entriesList[0]
 	entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) {
 		testSuiteComponent(entries, a.testProperties.Test_suites)
 		androidMkWriteTestData(a.data, entries)
 	})
-	return entries
+	return entriesList
 }
 
 func androidMkWriteTestData(data android.Paths, entries *android.AndroidMkEntries) {
diff --git a/java/androidmk_test.go b/java/androidmk_test.go
index 438b66a..acc6bf0 100644
--- a/java/androidmk_test.go
+++ b/java/androidmk_test.go
@@ -31,7 +31,7 @@
 	`)
 
 	mod := ctx.ModuleForTests("foo", "android_common").Module()
-	entries := android.AndroidMkEntriesForTest(t, config, "", mod)
+	entries := android.AndroidMkEntriesForTest(t, config, "", mod)[0]
 
 	expected := []string{"libfoo"}
 	actual := entries.EntryMap["LOCAL_REQUIRED_MODULES"]
@@ -50,17 +50,23 @@
 	`)
 
 	mod := ctx.ModuleForTests("foo", "android_common").Module()
-	entries := android.AndroidMkEntriesForTest(t, config, "", mod)
+	entriesList := android.AndroidMkEntriesForTest(t, config, "", mod)
+	if len(entriesList) != 2 {
+		t.Errorf("two entries are expected, but got %d", len(entriesList))
+	}
 
+	mainEntries := &entriesList[0]
 	expected := []string{"foo"}
-	actual := entries.EntryMap["LOCAL_MODULE"]
+	actual := mainEntries.EntryMap["LOCAL_MODULE"]
 	if !reflect.DeepEqual(expected, actual) {
 		t.Errorf("Unexpected module name - expected: %q, actual: %q", expected, actual)
 	}
 
-	footerLines := entries.FooterLinesForTests()
-	if !android.InList("LOCAL_MODULE := foo-hostdex", footerLines) {
-		t.Errorf("foo-hostdex is not found in the footers: %q", footerLines)
+	subEntries := &entriesList[1]
+	expected = []string{"foo-hostdex"}
+	actual = subEntries.EntryMap["LOCAL_MODULE"]
+	if !reflect.DeepEqual(expected, actual) {
+		t.Errorf("Unexpected module name - expected: %q, actual: %q", expected, actual)
 	}
 }
 
@@ -75,17 +81,23 @@
 	`)
 
 	mod := ctx.ModuleForTests("foo", "android_common").Module()
-	entries := android.AndroidMkEntriesForTest(t, config, "", mod)
+	entriesList := android.AndroidMkEntriesForTest(t, config, "", mod)
+	if len(entriesList) != 2 {
+		t.Errorf("two entries are expected, but got %d", len(entriesList))
+	}
 
+	mainEntries := &entriesList[0]
 	expected := []string{"libfoo"}
-	actual := entries.EntryMap["LOCAL_REQUIRED_MODULES"]
+	actual := mainEntries.EntryMap["LOCAL_REQUIRED_MODULES"]
 	if !reflect.DeepEqual(expected, actual) {
 		t.Errorf("Unexpected required modules - expected: %q, actual: %q", expected, actual)
 	}
 
-	footerLines := entries.FooterLinesForTests()
-	if !android.InList("LOCAL_REQUIRED_MODULES := libfoo", footerLines) {
-		t.Errorf("Wrong or missing required line for foo-hostdex in the footers: %q", footerLines)
+	subEntries := &entriesList[1]
+	expected = []string{"libfoo"}
+	actual = subEntries.EntryMap["LOCAL_REQUIRED_MODULES"]
+	if !reflect.DeepEqual(expected, actual) {
+		t.Errorf("Unexpected required modules - expected: %q, actual: %q", expected, actual)
 	}
 }
 
@@ -104,14 +116,20 @@
 	`)
 
 	mod := ctx.ModuleForTests("foo", "android_common").Module()
-	entries := android.AndroidMkEntriesForTest(t, config, "", mod)
+	entriesList := android.AndroidMkEntriesForTest(t, config, "", mod)
+	if len(entriesList) != 2 {
+		t.Errorf("two entries are expected, but got %d", len(entriesList))
+	}
 
-	if r, ok := entries.EntryMap["LOCAL_REQUIRED_MODULES"]; ok {
+	mainEntries := &entriesList[0]
+	if r, ok := mainEntries.EntryMap["LOCAL_REQUIRED_MODULES"]; ok {
 		t.Errorf("Unexpected required modules: %q", r)
 	}
 
-	footerLines := entries.FooterLinesForTests()
-	if !android.InList("LOCAL_REQUIRED_MODULES += libfoo", footerLines) {
-		t.Errorf("Wrong or missing required line for foo-hostdex in the footers: %q", footerLines)
+	subEntries := &entriesList[1]
+	expected := []string{"libfoo"}
+	actual := subEntries.EntryMap["LOCAL_REQUIRED_MODULES"]
+	if !reflect.DeepEqual(expected, actual) {
+		t.Errorf("Unexpected required modules - expected: %q, actual: %q", expected, actual)
 	}
 }
diff --git a/java/app_test.go b/java/app_test.go
index c7ed49b..1800bb7 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -1529,7 +1529,7 @@
 		a := variant.Module().(*AndroidAppImport)
 		expectedValues := []string{test.expected}
 		actualValues := android.AndroidMkEntriesForTest(
-			t, config, "", a).EntryMap["LOCAL_INSTALLED_MODULE_STEM"]
+			t, config, "", a)[0].EntryMap["LOCAL_INSTALLED_MODULE_STEM"]
 		if !reflect.DeepEqual(actualValues, expectedValues) {
 			t.Errorf("Incorrect LOCAL_INSTALLED_MODULE_STEM value '%s', expected '%s'",
 				actualValues, expectedValues)
@@ -1615,7 +1615,7 @@
 	test := ctx.ModuleForTests("foo", "android_common").Module().(*AndroidTestImport)
 
 	// Check android mks.
-	entries := android.AndroidMkEntriesForTest(t, config, "", test)
+	entries := android.AndroidMkEntriesForTest(t, config, "", test)[0]
 	expected := []string{"tests"}
 	actual := entries.EntryMap["LOCAL_MODULE_TAGS"]
 	if !reflect.DeepEqual(expected, actual) {
diff --git a/java/config/config.go b/java/config/config.go
index 333de32..fee6341 100644
--- a/java/config/config.go
+++ b/java/config/config.go
@@ -124,7 +124,7 @@
 		if ctx.Config().UnbundledBuild() {
 			return "prebuilts/build-tools/common/framework/" + turbine
 		} else {
-			return pctx.HostJavaToolPath(ctx, turbine).String()
+			return ctx.Config().HostJavaToolPath(ctx, turbine).String()
 		}
 	})
 
@@ -170,7 +170,7 @@
 		if ctx.Config().UnbundledBuild() || ctx.Config().IsPdkBuild() {
 			return filepath.Join("prebuilts/sdk/tools", runtime.GOOS, "bin", tool)
 		} else {
-			return pctx.HostBinToolPath(ctx, tool).String()
+			return ctx.Config().HostToolPath(ctx, tool).String()
 		}
 	})
 }
@@ -180,7 +180,7 @@
 		if ctx.Config().UnbundledBuild() || ctx.Config().IsPdkBuild() {
 			return filepath.Join("prebuilts/sdk/tools/lib", tool+".jar")
 		} else {
-			return pctx.HostJavaToolPath(ctx, tool+".jar").String()
+			return ctx.Config().HostJavaToolPath(ctx, tool+".jar").String()
 		}
 	})
 }
@@ -194,7 +194,7 @@
 			}
 			return filepath.Join("prebuilts/sdk/tools", runtime.GOOS, "lib64", tool+ext)
 		} else {
-			return pctx.HostJNIToolPath(ctx, tool).String()
+			return ctx.Config().HostJNIToolPath(ctx, tool).String()
 		}
 	})
 }
@@ -204,7 +204,7 @@
 		if ctx.Config().UnbundledBuild() || ctx.Config().IsPdkBuild() {
 			return filepath.Join("prebuilts/build-tools", ctx.Config().PrebuiltOS(), "bin", tool)
 		} else {
-			return pctx.HostBinToolPath(ctx, tool).String()
+			return ctx.Config().HostToolPath(ctx, tool).String()
 		}
 	})
 }
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index 88e3bc2..1d363c9 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -178,6 +178,12 @@
 	return false
 }
 
+func skipDexpreoptArtBootJars(ctx android.BuilderContext) bool {
+	// with EMMA_INSTRUMENT_FRAMEWORK=true ART boot class path libraries have dependencies on framework,
+	// therefore dexpreopt ART libraries cannot be dexpreopted in isolation => no ART boot image
+	return ctx.Config().IsEnvTrue("EMMA_INSTRUMENT_FRAMEWORK")
+}
+
 type dexpreoptBootJars struct {
 	defaultBootImage *bootImage
 	otherImages      []*bootImage
@@ -187,7 +193,7 @@
 
 // Accessor function for the apex package. Returns nil if dexpreopt is disabled.
 func DexpreoptedArtApexJars(ctx android.BuilderContext) map[android.ArchType]android.OutputPaths {
-	if skipDexpreoptBootJars(ctx) {
+	if skipDexpreoptBootJars(ctx) || skipDexpreoptArtBootJars(ctx) {
 		return nil
 	}
 	return artBootImageConfig(ctx).imagesDeps
@@ -216,8 +222,10 @@
 
 	// Always create the default boot image first, to get a unique profile rule for all images.
 	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 !skipDexpreoptArtBootJars(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, apexBootImageConfig(ctx)))
diff --git a/java/dexpreopt_bootjars_test.go b/java/dexpreopt_bootjars_test.go
index 87d5e30..29a5abe 100644
--- a/java/dexpreopt_bootjars_test.go
+++ b/java/dexpreopt_bootjars_test.go
@@ -48,7 +48,7 @@
 
 	pathCtx := android.PathContextForTesting(config, nil)
 	dexpreoptConfig := dexpreopt.GlobalConfigForTests(pathCtx)
-	dexpreoptConfig.BootJars = []string{"foo", "bar", "baz"}
+	dexpreoptConfig.ArtApexJars = []string{"foo", "bar", "baz"}
 	setDexpreoptTestGlobalConfig(config, dexpreoptConfig)
 
 	ctx := testContext(bp, nil)
@@ -59,10 +59,9 @@
 
 	dexpreoptBootJars := ctx.SingletonForTests("dex_bootjars")
 
-	bootArt := dexpreoptBootJars.Output("boot-foo.art")
+	bootArt := dexpreoptBootJars.Output("boot.art")
 
 	expectedInputs := []string{
-		"dex_artjars/apex/com.android.art/javalib/arm64/boot.art",
 		"dex_bootjars_input/foo.jar",
 		"dex_bootjars_input/bar.jar",
 		"dex_bootjars_input/baz.jar",
@@ -83,19 +82,19 @@
 	expectedOutputs := []string{
 		"dex_bootjars/system/framework/arm64/boot.invocation",
 
-		"dex_bootjars/system/framework/arm64/boot-foo.art",
+		"dex_bootjars/system/framework/arm64/boot.art",
 		"dex_bootjars/system/framework/arm64/boot-bar.art",
 		"dex_bootjars/system/framework/arm64/boot-baz.art",
 
-		"dex_bootjars/system/framework/arm64/boot-foo.oat",
+		"dex_bootjars/system/framework/arm64/boot.oat",
 		"dex_bootjars/system/framework/arm64/boot-bar.oat",
 		"dex_bootjars/system/framework/arm64/boot-baz.oat",
 
-		"dex_bootjars/system/framework/arm64/boot-foo.vdex",
+		"dex_bootjars/system/framework/arm64/boot.vdex",
 		"dex_bootjars/system/framework/arm64/boot-bar.vdex",
 		"dex_bootjars/system/framework/arm64/boot-baz.vdex",
 
-		"dex_bootjars_unstripped/system/framework/arm64/boot-foo.oat",
+		"dex_bootjars_unstripped/system/framework/arm64/boot.oat",
 		"dex_bootjars_unstripped/system/framework/arm64/boot-bar.oat",
 		"dex_bootjars_unstripped/system/framework/arm64/boot-baz.oat",
 	}
diff --git a/java/dexpreopt_config.go b/java/dexpreopt_config.go
index fd1cfd4..91e0dfb 100644
--- a/java/dexpreopt_config.go
+++ b/java/dexpreopt_config.go
@@ -135,10 +135,6 @@
 		deviceDir := android.PathForOutput(ctx, ctx.Config().DeviceName())
 
 		artModules := global.ArtApexJars
-		// In coverage builds ART boot class path jars are instrumented and have additional dependencies.
-		if ctx.Config().IsEnvTrue("EMMA_INSTRUMENT_FRAMEWORK") {
-			artModules = append(artModules, "jacocoagent")
-		}
 		frameworkModules := android.RemoveListFromList(global.BootJars,
 			concat(artModules, getJarsFromApexJarPairs(global.UpdatableBootJars)))
 
@@ -166,15 +162,15 @@
 		}
 
 		// Framework config for the boot image extension.
-		// It includes framework libraries and depends on the ART config.
+		// It includes both the Core libraries and framework.
 		frameworkCfg := bootImageConfig{
-			extension:        true,
+			extension:        false,
 			name:             frameworkBootImageName,
 			stem:             "boot",
 			installSubdir:    frameworkSubdir,
-			modules:          frameworkModules,
-			dexLocations:     frameworkLocations,
-			dexLocationsDeps: append(artLocations, frameworkLocations...),
+			modules:          concat(artModules, frameworkModules),
+			dexLocations:     concat(artLocations, frameworkLocations),
+			dexLocationsDeps: concat(artLocations, frameworkLocations),
 		}
 
 		// Apex config for the  boot image used in the JIT-zygote experiment.
@@ -230,10 +226,6 @@
 			c.zip = c.dir.Join(ctx, c.name+".zip")
 		}
 
-		// specific to the framework config
-		frameworkCfg.dexPathsDeps = append(artCfg.dexPathsDeps, frameworkCfg.dexPathsDeps...)
-		frameworkCfg.imageLocations = append(artCfg.imageLocations, frameworkCfg.imageLocations...)
-
 		return configs
 	}).(map[string]*bootImageConfig)
 }
diff --git a/java/droiddoc.go b/java/droiddoc.go
index 45a72e1..76cdaea 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -2000,6 +2000,6 @@
 	snapshotRelativeDir := filepath.Join("java", d.Name()+"_stubs_sources")
 	builder.UnzipToSnapshot(stubsSrcJar, snapshotRelativeDir)
 
-	pbm := builder.AddPrebuiltModule(sdkModuleContext.OtherModuleName(d), "prebuilt_stubs_sources")
+	pbm := builder.AddPrebuiltModule(member, "prebuilt_stubs_sources")
 	pbm.AddProperty("srcs", []string{snapshotRelativeDir})
 }
diff --git a/java/hiddenapi_singleton.go b/java/hiddenapi_singleton.go
index c0ef444..ad84cde 100644
--- a/java/hiddenapi_singleton.go
+++ b/java/hiddenapi_singleton.go
@@ -190,7 +190,7 @@
 	rule.MissingDeps(missingDeps)
 
 	rule.Command().
-		Tool(pctx.HostBinToolPath(ctx, "hiddenapi")).
+		Tool(ctx.Config().HostToolPath(ctx, "hiddenapi")).
 		Text("list").
 		FlagForEachInput("--boot-dex=", bootDexJars).
 		FlagWithInputList("--public-stub-classpath=", publicStubPaths, ":").
diff --git a/java/java.go b/java/java.go
index f933d8d..f58e5ba 100644
--- a/java/java.go
+++ b/java/java.go
@@ -1760,7 +1760,7 @@
 		}
 	}
 
-	module := builder.AddPrebuiltModule(sdkModuleContext.OtherModuleName(j), "java_import")
+	module := builder.AddPrebuiltModule(member, "java_import")
 	module.AddProperty("jars", []string{snapshotRelativeJavaLibPath})
 }
 
diff --git a/java/platform_compat_config.go b/java/platform_compat_config.go
index 23ba2b0..7801634 100644
--- a/java/platform_compat_config.go
+++ b/java/platform_compat_config.go
@@ -71,8 +71,8 @@
 
 }
 
-func (p *platformCompatConfig) AndroidMkEntries() android.AndroidMkEntries {
-	return android.AndroidMkEntries{
+func (p *platformCompatConfig) AndroidMkEntries() []android.AndroidMkEntries {
+	return []android.AndroidMkEntries{android.AndroidMkEntries{
 		Class:      "ETC",
 		OutputFile: android.OptionalPathForPath(p.configFile),
 		Include:    "$(BUILD_PREBUILT)",
@@ -82,7 +82,7 @@
 				entries.SetString("LOCAL_INSTALLED_MODULE_STEM", p.configFile.Base())
 			},
 		},
-	}
+	}}
 }
 
 func platformCompatConfigFactory() android.Module {
diff --git a/java/robolectric.go b/java/robolectric.go
index b7646eb..3195615 100644
--- a/java/robolectric.go
+++ b/java/robolectric.go
@@ -158,8 +158,9 @@
 	TransformResourcesToJar(ctx, outputFile, srcJarArgs, srcJarDeps)
 }
 
-func (r *robolectricTest) AndroidMkEntries() android.AndroidMkEntries {
-	entries := r.Library.AndroidMkEntries()
+func (r *robolectricTest) AndroidMkEntries() []android.AndroidMkEntries {
+	entriesList := r.Library.AndroidMkEntries()
+	entries := &entriesList[0]
 
 	entries.ExtraFooters = []android.AndroidMkExtraFootersFunc{
 		func(w io.Writer, name, prefix, moduleDir string, entries *android.AndroidMkEntries) {
@@ -185,7 +186,7 @@
 		},
 	}
 
-	return entries
+	return entriesList
 }
 
 func (r *robolectricTest) writeTestRunner(w io.Writer, module, name string, tests []string) {
diff --git a/java/sdk_library.go b/java/sdk_library.go
index b7efcff..e204659 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -194,13 +194,13 @@
 	})
 }
 
-func (module *SdkLibrary) AndroidMkEntries() android.AndroidMkEntries {
-	entries := module.Library.AndroidMkEntries()
+func (module *SdkLibrary) AndroidMkEntries() []android.AndroidMkEntries {
+	entriesList := module.Library.AndroidMkEntries()
+	entries := &entriesList[0]
 	entries.Required = append(entries.Required, module.xmlFileName())
 
 	entries.ExtraFooters = []android.AndroidMkExtraFootersFunc{
 		func(w io.Writer, name, prefix, moduleDir string, entries *android.AndroidMkEntries) {
-			module.Library.AndroidMkHostDex(w, name, entries)
 			if !Bool(module.sdkLibraryProperties.No_dist) {
 				// Create a phony module that installs the impl library, for the case when this lib is
 				// in PRODUCT_PACKAGES.
@@ -252,7 +252,7 @@
 			}
 		},
 	}
-	return entries
+	return entriesList
 }
 
 // Module name of the stubs library
@@ -293,6 +293,8 @@
 		partition = "odm"
 	} else if module.ProductSpecific() {
 		partition = "product"
+	} else if module.SystemExtSpecific() {
+		partition = "system_ext"
 	}
 	return "/" + partition + "/framework/" + module.implName() + ".jar"
 }
@@ -363,17 +365,18 @@
 // Creates a static java library that has API stubs
 func (module *SdkLibrary) createStubsLibrary(mctx android.LoadHookContext, apiScope apiScope) {
 	props := struct {
-		Name              *string
-		Srcs              []string
-		Sdk_version       *string
-		Libs              []string
-		Soc_specific      *bool
-		Device_specific   *bool
-		Product_specific  *bool
-		Compile_dex       *bool
-		System_modules    *string
-		Java_version      *string
-		Product_variables struct {
+		Name                *string
+		Srcs                []string
+		Sdk_version         *string
+		Libs                []string
+		Soc_specific        *bool
+		Device_specific     *bool
+		Product_specific    *bool
+		System_ext_specific *bool
+		Compile_dex         *bool
+		System_modules      *string
+		Java_version        *string
+		Product_variables   struct {
 			Unbundled_build struct {
 				Enabled *bool
 			}
@@ -417,6 +420,8 @@
 		props.Device_specific = proptools.BoolPtr(true)
 	} else if module.ProductSpecific() {
 		props.Product_specific = proptools.BoolPtr(true)
+	} else if module.SystemExtSpecific() {
+		props.System_ext_specific = proptools.BoolPtr(true)
 	}
 
 	mctx.CreateModule(LibraryFactory, &props)
@@ -561,12 +566,13 @@
 	// creates a prebuilt_etc module to actually place the xml file under
 	// <partition>/etc/permissions
 	etcProps := struct {
-		Name             *string
-		Src              *string
-		Sub_dir          *string
-		Soc_specific     *bool
-		Device_specific  *bool
-		Product_specific *bool
+		Name                *string
+		Src                 *string
+		Sub_dir             *string
+		Soc_specific        *bool
+		Device_specific     *bool
+		Product_specific    *bool
+		System_ext_specific *bool
 	}{}
 	etcProps.Name = proptools.StringPtr(module.xmlFileName())
 	etcProps.Src = proptools.StringPtr(":" + module.xmlFileName() + "-gen")
@@ -577,6 +583,8 @@
 		etcProps.Device_specific = proptools.BoolPtr(true)
 	} else if module.ProductSpecific() {
 		etcProps.Product_specific = proptools.BoolPtr(true)
+	} else if module.SystemExtSpecific() {
+		etcProps.System_ext_specific = proptools.BoolPtr(true)
 	}
 	mctx.CreateModule(android.PrebuiltEtcFactory, &etcProps)
 }
@@ -795,10 +803,11 @@
 func (module *sdkLibraryImport) createInternalModules(mctx android.LoadHookContext) {
 	// Creates a java import for the jar with ".stubs" suffix
 	props := struct {
-		Name             *string
-		Soc_specific     *bool
-		Device_specific  *bool
-		Product_specific *bool
+		Name                *string
+		Soc_specific        *bool
+		Device_specific     *bool
+		Product_specific    *bool
+		System_ext_specific *bool
 	}{}
 
 	props.Name = proptools.StringPtr(module.BaseModuleName() + sdkStubsLibrarySuffix)
@@ -809,6 +818,8 @@
 		props.Device_specific = proptools.BoolPtr(true)
 	} else if module.ProductSpecific() {
 		props.Product_specific = proptools.BoolPtr(true)
+	} else if module.SystemExtSpecific() {
+		props.System_ext_specific = proptools.BoolPtr(true)
 	}
 
 	mctx.CreateModule(ImportFactory, &props, &module.properties)
diff --git a/sdk/cc_sdk_test.go b/sdk/cc_sdk_test.go
index 315669a..bc22dbb 100644
--- a/sdk/cc_sdk_test.go
+++ b/sdk/cc_sdk_test.go
@@ -142,7 +142,46 @@
 	ensureListContains(t, pathsToStrings(cpplibForMyApex2.Rule("ld").Implicits), sdkMemberV2.String())
 }
 
-func TestSnapshotWithCcShared(t *testing.T) {
+func TestSnapshotWithCcDuplicateHeaders(t *testing.T) {
+	result := testSdkWithCc(t, `
+		sdk {
+			name: "mysdk",
+			native_shared_libs: ["mynativelib1", "mynativelib2"],
+		}
+
+		cc_library_shared {
+			name: "mynativelib1",
+			srcs: [
+				"Test.cpp",
+			],
+			export_include_dirs: ["include"],
+			system_shared_libs: [],
+			stl: "none",
+		}
+
+		cc_library_shared {
+			name: "mynativelib2",
+			srcs: [
+				"Test.cpp",
+			],
+			export_include_dirs: ["include"],
+			system_shared_libs: [],
+			stl: "none",
+		}
+	`)
+
+	result.CheckSnapshot("mysdk", "android_common", "",
+		checkAllCopyRules(`
+include/Test.h -> include/include/Test.h
+.intermediates/mynativelib1/android_arm64_armv8-a_core_shared/mynativelib1.so -> arm64/lib/mynativelib1.so
+.intermediates/mynativelib1/android_arm_armv7-a-neon_core_shared/mynativelib1.so -> arm/lib/mynativelib1.so
+.intermediates/mynativelib2/android_arm64_armv8-a_core_shared/mynativelib2.so -> arm64/lib/mynativelib2.so
+.intermediates/mynativelib2/android_arm_armv7-a-neon_core_shared/mynativelib2.so -> arm/lib/mynativelib2.so
+`),
+	)
+}
+
+func TestSnapshotWithCcSharedLibrary(t *testing.T) {
 	result := testSdkWithCc(t, `
 		sdk {
 			name: "mysdk",
@@ -164,7 +203,7 @@
 		}
 	`)
 
-	result.CheckSnapshot("mysdk", "android_common",
+	result.CheckSnapshot("mysdk", "android_common", "",
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
@@ -234,7 +273,7 @@
 	)
 }
 
-func TestHostSnapshotWithCcShared(t *testing.T) {
+func TestHostSnapshotWithCcSharedLibrary(t *testing.T) {
 	// b/145598135 - Generating host snapshots for anything other than linux is not supported.
 	SkipIfNotLinux(t)
 
@@ -263,7 +302,7 @@
 		}
 	`)
 
-	result.CheckSnapshot("mysdk", "linux_glibc_common",
+	result.CheckSnapshot("mysdk", "linux_glibc_common", "",
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
@@ -338,3 +377,200 @@
 `),
 	)
 }
+
+func TestSnapshotWithCcStaticLibrary(t *testing.T) {
+	result := testSdkWithCc(t, `
+		sdk {
+			name: "mysdk",
+			native_static_libs: ["mynativelib"],
+		}
+
+		cc_library_static {
+			name: "mynativelib",
+			srcs: [
+				"Test.cpp",
+				"aidl/foo/bar/Test.aidl",
+			],
+			export_include_dirs: ["include"],
+			aidl: {
+				export_aidl_headers: true,
+			},
+			system_shared_libs: [],
+			stl: "none",
+		}
+	`)
+
+	result.CheckSnapshot("mysdk", "android_common", "",
+		checkAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
+
+cc_prebuilt_library_static {
+    name: "mysdk_mynativelib@current",
+    sdk_member_name: "mynativelib",
+    arch: {
+        arm64: {
+            srcs: ["arm64/lib/mynativelib.a"],
+            export_include_dirs: [
+                "arm64/include/include",
+                "arm64/include_gen/mynativelib",
+            ],
+        },
+        arm: {
+            srcs: ["arm/lib/mynativelib.a"],
+            export_include_dirs: [
+                "arm/include/include",
+                "arm/include_gen/mynativelib",
+            ],
+        },
+    },
+    stl: "none",
+    system_shared_libs: [],
+}
+
+cc_prebuilt_library_static {
+    name: "mynativelib",
+    prefer: false,
+    arch: {
+        arm64: {
+            srcs: ["arm64/lib/mynativelib.a"],
+            export_include_dirs: [
+                "arm64/include/include",
+                "arm64/include_gen/mynativelib",
+            ],
+        },
+        arm: {
+            srcs: ["arm/lib/mynativelib.a"],
+            export_include_dirs: [
+                "arm/include/include",
+                "arm/include_gen/mynativelib",
+            ],
+        },
+    },
+    stl: "none",
+    system_shared_libs: [],
+}
+
+sdk_snapshot {
+    name: "mysdk@current",
+    native_static_libs: ["mysdk_mynativelib@current"],
+}
+`),
+		checkAllCopyRules(`
+.intermediates/mynativelib/android_arm64_armv8-a_core_static/mynativelib.a -> arm64/lib/mynativelib.a
+include/Test.h -> arm64/include/include/Test.h
+.intermediates/mynativelib/android_arm64_armv8-a_core_static/gen/aidl/aidl/foo/bar/Test.h -> arm64/include_gen/mynativelib/aidl/foo/bar/Test.h
+.intermediates/mynativelib/android_arm64_armv8-a_core_static/gen/aidl/aidl/foo/bar/BnTest.h -> arm64/include_gen/mynativelib/aidl/foo/bar/BnTest.h
+.intermediates/mynativelib/android_arm64_armv8-a_core_static/gen/aidl/aidl/foo/bar/BpTest.h -> arm64/include_gen/mynativelib/aidl/foo/bar/BpTest.h
+.intermediates/mynativelib/android_arm_armv7-a-neon_core_static/mynativelib.a -> arm/lib/mynativelib.a
+include/Test.h -> arm/include/include/Test.h
+.intermediates/mynativelib/android_arm_armv7-a-neon_core_static/gen/aidl/aidl/foo/bar/Test.h -> arm/include_gen/mynativelib/aidl/foo/bar/Test.h
+.intermediates/mynativelib/android_arm_armv7-a-neon_core_static/gen/aidl/aidl/foo/bar/BnTest.h -> arm/include_gen/mynativelib/aidl/foo/bar/BnTest.h
+.intermediates/mynativelib/android_arm_armv7-a-neon_core_static/gen/aidl/aidl/foo/bar/BpTest.h -> arm/include_gen/mynativelib/aidl/foo/bar/BpTest.h
+`),
+	)
+}
+
+func TestHostSnapshotWithCcStaticLibrary(t *testing.T) {
+	// b/145598135 - Generating host snapshots for anything other than linux is not supported.
+	SkipIfNotLinux(t)
+
+	result := testSdkWithCc(t, `
+		sdk {
+			name: "mysdk",
+			device_supported: false,
+			host_supported: true,
+			native_static_libs: ["mynativelib"],
+		}
+
+		cc_library_static {
+			name: "mynativelib",
+			device_supported: false,
+			host_supported: true,
+			srcs: [
+				"Test.cpp",
+				"aidl/foo/bar/Test.aidl",
+			],
+			export_include_dirs: ["include"],
+			aidl: {
+				export_aidl_headers: true,
+			},
+			system_shared_libs: [],
+			stl: "none",
+		}
+	`)
+
+	result.CheckSnapshot("mysdk", "linux_glibc_common", "",
+		checkAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
+
+cc_prebuilt_library_static {
+    name: "mysdk_mynativelib@current",
+    sdk_member_name: "mynativelib",
+    device_supported: false,
+    host_supported: true,
+    arch: {
+        x86_64: {
+            srcs: ["x86_64/lib/mynativelib.a"],
+            export_include_dirs: [
+                "x86_64/include/include",
+                "x86_64/include_gen/mynativelib",
+            ],
+        },
+        x86: {
+            srcs: ["x86/lib/mynativelib.a"],
+            export_include_dirs: [
+                "x86/include/include",
+                "x86/include_gen/mynativelib",
+            ],
+        },
+    },
+    stl: "none",
+    system_shared_libs: [],
+}
+
+cc_prebuilt_library_static {
+    name: "mynativelib",
+    prefer: false,
+    device_supported: false,
+    host_supported: true,
+    arch: {
+        x86_64: {
+            srcs: ["x86_64/lib/mynativelib.a"],
+            export_include_dirs: [
+                "x86_64/include/include",
+                "x86_64/include_gen/mynativelib",
+            ],
+        },
+        x86: {
+            srcs: ["x86/lib/mynativelib.a"],
+            export_include_dirs: [
+                "x86/include/include",
+                "x86/include_gen/mynativelib",
+            ],
+        },
+    },
+    stl: "none",
+    system_shared_libs: [],
+}
+
+sdk_snapshot {
+    name: "mysdk@current",
+    device_supported: false,
+    host_supported: true,
+    native_static_libs: ["mysdk_mynativelib@current"],
+}
+`),
+		checkAllCopyRules(`
+.intermediates/mynativelib/linux_glibc_x86_64_static/mynativelib.a -> x86_64/lib/mynativelib.a
+include/Test.h -> x86_64/include/include/Test.h
+.intermediates/mynativelib/linux_glibc_x86_64_static/gen/aidl/aidl/foo/bar/Test.h -> x86_64/include_gen/mynativelib/aidl/foo/bar/Test.h
+.intermediates/mynativelib/linux_glibc_x86_64_static/gen/aidl/aidl/foo/bar/BnTest.h -> x86_64/include_gen/mynativelib/aidl/foo/bar/BnTest.h
+.intermediates/mynativelib/linux_glibc_x86_64_static/gen/aidl/aidl/foo/bar/BpTest.h -> x86_64/include_gen/mynativelib/aidl/foo/bar/BpTest.h
+.intermediates/mynativelib/linux_glibc_x86_static/mynativelib.a -> x86/lib/mynativelib.a
+include/Test.h -> x86/include/include/Test.h
+.intermediates/mynativelib/linux_glibc_x86_static/gen/aidl/aidl/foo/bar/Test.h -> x86/include_gen/mynativelib/aidl/foo/bar/Test.h
+.intermediates/mynativelib/linux_glibc_x86_static/gen/aidl/aidl/foo/bar/BnTest.h -> x86/include_gen/mynativelib/aidl/foo/bar/BnTest.h
+.intermediates/mynativelib/linux_glibc_x86_static/gen/aidl/aidl/foo/bar/BpTest.h -> x86/include_gen/mynativelib/aidl/foo/bar/BpTest.h
+`),
+	)
+}
diff --git a/sdk/java_sdk_test.go b/sdk/java_sdk_test.go
index 5b72248..1aa9184 100644
--- a/sdk/java_sdk_test.go
+++ b/sdk/java_sdk_test.go
@@ -123,7 +123,7 @@
 		}
 	`)
 
-	result.CheckSnapshot("mysdk", "android_common",
+	result.CheckSnapshot("mysdk", "android_common", "",
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
@@ -178,7 +178,7 @@
 		}
 	`)
 
-	result.CheckSnapshot("mysdk", "linux_glibc_common",
+	result.CheckSnapshot("mysdk", "linux_glibc_common", "",
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
@@ -232,7 +232,7 @@
 		}
 	`)
 
-	result.CheckSnapshot("mysdk", "android_common",
+	result.CheckSnapshot("mysdk", "android_common", "",
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
@@ -287,7 +287,7 @@
 		}
 	`)
 
-	result.CheckSnapshot("mysdk", "linux_glibc_common",
+	result.CheckSnapshot("mysdk", "linux_glibc_common", "",
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
@@ -379,7 +379,7 @@
 		}
 	`)
 
-	result.CheckSnapshot("mysdk", "android_common",
+	result.CheckSnapshot("mysdk", "android_common", "",
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
@@ -428,7 +428,7 @@
 		}
 	`)
 
-	result.CheckSnapshot("mysdk", "linux_glibc_common",
+	result.CheckSnapshot("mysdk", "linux_glibc_common", "",
 		checkAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
 
diff --git a/sdk/sdk.go b/sdk/sdk.go
index c7e12b9..cd9aafa 100644
--- a/sdk/sdk.go
+++ b/sdk/sdk.go
@@ -61,15 +61,25 @@
 }
 
 type sdkProperties struct {
+	// For module types from the cc package
+
+	// The list of shared native libraries in this SDK
+	Native_shared_libs []string
+
+	// The list of static native libraries in this SDK
+	Native_static_libs []string
+
+	// For module types from the java package
+
 	// The list of java header libraries in this SDK
 	//
 	// This should be used for java libraries that are provided separately at runtime,
 	// e.g. through an APEX.
 	Java_header_libs []string
+
 	// The list of java implementation libraries in this SDK
 	Java_libs []string
-	// The list of native libraries in this SDK
-	Native_shared_libs []string
+
 	// The list of stub sources in this SDK
 	Stubs_sources []string
 
@@ -107,7 +117,12 @@
 	{
 		name:       "native_shared_libs",
 		getter:     func(properties *sdkProperties) []string { return properties.Native_shared_libs },
-		memberType: cc.LibrarySdkMemberType,
+		memberType: cc.SharedLibrarySdkMemberType,
+	},
+	{
+		name:       "native_static_libs",
+		getter:     func(properties *sdkProperties) []string { return properties.Native_static_libs },
+		memberType: cc.StaticLibrarySdkMemberType,
 	},
 	// Members from java package.
 	{
@@ -163,12 +178,12 @@
 	}
 }
 
-func (s *sdk) AndroidMkEntries() android.AndroidMkEntries {
+func (s *sdk) AndroidMkEntries() []android.AndroidMkEntries {
 	if !s.snapshotFile.Valid() {
-		return android.AndroidMkEntries{}
+		return []android.AndroidMkEntries{}
 	}
 
-	return android.AndroidMkEntries{
+	return []android.AndroidMkEntries{android.AndroidMkEntries{
 		Class:      "FAKE",
 		OutputFile: s.snapshotFile,
 		DistFile:   s.snapshotFile,
@@ -180,7 +195,7 @@
 				fmt.Fprintln(w, s.Name()+":", s.snapshotFile.String())
 			},
 		},
-	}
+	}}
 }
 
 // RegisterPreDepsMutators registers pre-deps mutators to support modules implementing SdkAware
diff --git a/sdk/sdk_test.go b/sdk/sdk_test.go
index f4e944a..d376e59 100644
--- a/sdk/sdk_test.go
+++ b/sdk/sdk_test.go
@@ -79,3 +79,123 @@
 		}
 	`)
 }
+
+// Ensure that prebuilt modules have the same effective visibility as the source
+// modules.
+func TestSnapshotVisibility(t *testing.T) {
+	packageBp := `
+		package {
+			default_visibility: ["//other/foo"],
+		}
+
+		sdk {
+			name: "mysdk",
+			visibility: [
+				"//other/foo",
+				// This short form will be replaced with //package:__subpackages__ in the
+				// generated sdk_snapshot.
+				":__subpackages__",
+			],
+			java_header_libs: [
+				"myjavalib",
+				"mypublicjavalib",
+				"mydefaultedjavalib",
+			],
+		}
+
+		java_library {
+			name: "myjavalib",
+			// Uses package default visibility
+			srcs: ["Test.java"],
+			system_modules: "none",
+			sdk_version: "none",
+		}
+
+		java_library {
+			name: "mypublicjavalib",
+      visibility: ["//visibility:public"],
+			srcs: ["Test.java"],
+			system_modules: "none",
+			sdk_version: "none",
+		}
+
+		java_defaults {
+			name: "myjavadefaults",
+			visibility: ["//other/bar"],
+		}
+
+		java_library {
+			name: "mydefaultedjavalib",
+			defaults: ["myjavadefaults"],
+			srcs: ["Test.java"],
+			system_modules: "none",
+			sdk_version: "none",
+		}
+	`
+
+	result := testSdkWithFs(t, ``,
+		map[string][]byte{
+			"package/Test.java":  nil,
+			"package/Android.bp": []byte(packageBp),
+		})
+
+	result.CheckSnapshot("mysdk", "android_common", "package",
+		checkAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
+
+java_import {
+    name: "mysdk_myjavalib@current",
+    sdk_member_name: "myjavalib",
+    visibility: ["//other/foo:__pkg__"],
+    jars: ["java/myjavalib.jar"],
+}
+
+java_import {
+    name: "myjavalib",
+    prefer: false,
+    visibility: ["//other/foo:__pkg__"],
+    jars: ["java/myjavalib.jar"],
+}
+
+java_import {
+    name: "mysdk_mypublicjavalib@current",
+    sdk_member_name: "mypublicjavalib",
+    visibility: ["//visibility:public"],
+    jars: ["java/mypublicjavalib.jar"],
+}
+
+java_import {
+    name: "mypublicjavalib",
+    prefer: false,
+    visibility: ["//visibility:public"],
+    jars: ["java/mypublicjavalib.jar"],
+}
+
+java_import {
+    name: "mysdk_mydefaultedjavalib@current",
+    sdk_member_name: "mydefaultedjavalib",
+    visibility: ["//other/bar:__pkg__"],
+    jars: ["java/mydefaultedjavalib.jar"],
+}
+
+java_import {
+    name: "mydefaultedjavalib",
+    prefer: false,
+    visibility: ["//other/bar:__pkg__"],
+    jars: ["java/mydefaultedjavalib.jar"],
+}
+
+sdk_snapshot {
+    name: "mysdk@current",
+    visibility: [
+        "//other/foo:__pkg__",
+        "//package:__subpackages__",
+    ],
+    java_header_libs: [
+        "mysdk_myjavalib@current",
+        "mysdk_mypublicjavalib@current",
+        "mysdk_mydefaultedjavalib@current",
+    ],
+}
+`))
+}
diff --git a/sdk/testing.go b/sdk/testing.go
index 604fa16..5082ab4 100644
--- a/sdk/testing.go
+++ b/sdk/testing.go
@@ -33,7 +33,12 @@
 	ctx := android.NewTestArchContext()
 
 	// from android package
+	ctx.PreArchMutators(android.RegisterPackageRenamer)
+	ctx.PreArchMutators(android.RegisterVisibilityRuleChecker)
 	ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
+	ctx.PreArchMutators(android.RegisterVisibilityRuleGatherer)
+	ctx.PostDepsMutators(android.RegisterVisibilityRuleEnforcer)
+
 	ctx.PreArchMutators(func(ctx android.RegisterMutatorsContext) {
 		ctx.BottomUp("prebuilts", android.PrebuiltMutator).Parallel()
 	})
@@ -41,9 +46,11 @@
 		ctx.TopDown("prebuilt_select", android.PrebuiltSelectModuleMutator).Parallel()
 		ctx.BottomUp("prebuilt_postdeps", android.PrebuiltPostDepsMutator).Parallel()
 	})
+	ctx.RegisterModuleType("package", android.PackageFactory)
 
 	// from java package
 	ctx.RegisterModuleType("android_app_certificate", java.AndroidAppCertificateFactory)
+	ctx.RegisterModuleType("java_defaults", java.DefaultsFactory)
 	ctx.RegisterModuleType("java_library", java.LibraryFactory)
 	ctx.RegisterModuleType("java_import", java.ImportFactory)
 	ctx.RegisterModuleType("droidstubs", java.DroidstubsFactory)
@@ -52,6 +59,7 @@
 	// from cc package
 	ctx.RegisterModuleType("cc_library", cc.LibraryFactory)
 	ctx.RegisterModuleType("cc_library_shared", cc.LibrarySharedFactory)
+	ctx.RegisterModuleType("cc_library_static", cc.LibraryStaticFactory)
 	ctx.RegisterModuleType("cc_object", cc.ObjectFactory)
 	ctx.RegisterModuleType("cc_prebuilt_library_shared", cc.PrebuiltSharedLibraryFactory)
 	ctx.RegisterModuleType("cc_prebuilt_library_static", cc.PrebuiltStaticLibraryFactory)
@@ -115,7 +123,7 @@
 func testSdkWithFs(t *testing.T, bp string, fs map[string][]byte) *testSdkResult {
 	t.Helper()
 	ctx, config := testSdkContext(bp, fs)
-	_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
+	_, errs := ctx.ParseBlueprintsFiles(".")
 	android.FailIfErrored(t, errs)
 	_, errs = ctx.PrepareBuildActions(config)
 	android.FailIfErrored(t, errs)
@@ -268,7 +276,7 @@
 // Takes a list of functions which check different facets of the snapshot build rules.
 // Allows each test to customize what is checked without duplicating lots of code
 // or proliferating check methods of different flavors.
-func (r *testSdkResult) CheckSnapshot(name string, variant string, checkers ...snapshotBuildInfoChecker) {
+func (r *testSdkResult) CheckSnapshot(name string, variant string, dir string, checkers ...snapshotBuildInfoChecker) {
 	r.t.Helper()
 
 	sdk := r.Module(name, variant).(*sdk)
@@ -282,8 +290,11 @@
 
 	// Make sure that the generated zip file is in the correct place.
 	actual := snapshotBuildInfo.outputZip
+	if dir != "" {
+		dir = filepath.Clean(dir) + "/"
+	}
 	r.AssertStringEquals("Snapshot zip file in wrong place",
-		fmt.Sprintf(".intermediates/%s/%s/%s-current.zip", name, variant, name), actual)
+		fmt.Sprintf(".intermediates/%s%s/%s/%s-current.zip", dir, name, variant, name), actual)
 
 	// Populate a mock filesystem with the files that would have been copied by
 	// the rules.
diff --git a/sdk/update.go b/sdk/update.go
index 7731fbb..52d21ed 100644
--- a/sdk/update.go
+++ b/sdk/update.go
@@ -30,7 +30,7 @@
 var (
 	repackageZip = pctx.AndroidStaticRule("SnapshotRepackageZip",
 		blueprint.RuleParams{
-			Command: `${config.Zip2ZipCmd} -i $in -o $out "**/*:$destdir"`,
+			Command: `${config.Zip2ZipCmd} -i $in -o $out -x META-INF/**/* "**/*:$destdir"`,
 			CommandDeps: []string{
 				"${config.Zip2ZipCmd}",
 			},
@@ -184,6 +184,7 @@
 		sdk:             s,
 		version:         "current",
 		snapshotDir:     snapshotDir.OutputPath,
+		copies:          make(map[string]string),
 		filesToZip:      []android.Path{bp.path},
 		bpFile:          bpFile,
 		prebuiltModules: make(map[string]*bpModule),
@@ -211,6 +212,13 @@
 	snapshotName := ctx.ModuleName() + string(android.SdkVersionSeparator) + builder.version
 	snapshotModule := bpFile.newModule("sdk_snapshot")
 	snapshotModule.AddProperty("name", snapshotName)
+
+	// Make sure that the snapshot has the same visibility as the sdk.
+	visibility := android.EffectiveVisibilityRules(ctx, s)
+	if len(visibility) != 0 {
+		snapshotModule.AddProperty("visibility", visibility)
+	}
+
 	addHostDeviceSupportedProperties(&s.ModuleBase, snapshotModule)
 	for _, memberListProperty := range sdkMemberListProperties {
 		names := memberListProperty.getter(&s.properties)
@@ -330,6 +338,11 @@
 	version     string
 	snapshotDir android.OutputPath
 	bpFile      *bpFile
+
+	// Map from destination to source of each copy - used to eliminate duplicates and
+	// detect conflicts.
+	copies map[string]string
+
 	filesToZip  android.Paths
 	zipsToMerge android.Paths
 
@@ -338,13 +351,22 @@
 }
 
 func (s *snapshotBuilder) CopyToSnapshot(src android.Path, dest string) {
-	path := s.snapshotDir.Join(s.ctx, dest)
-	s.ctx.Build(pctx, android.BuildParams{
-		Rule:   android.Cp,
-		Input:  src,
-		Output: path,
-	})
-	s.filesToZip = append(s.filesToZip, path)
+	if existing, ok := s.copies[dest]; ok {
+		if existing != src.String() {
+			s.ctx.ModuleErrorf("conflicting copy, %s copied from both %s and %s", dest, existing, src)
+			return
+		}
+	} else {
+		path := s.snapshotDir.Join(s.ctx, dest)
+		s.ctx.Build(pctx, android.BuildParams{
+			Rule:   android.Cp,
+			Input:  src,
+			Output: path,
+		})
+		s.filesToZip = append(s.filesToZip, path)
+
+		s.copies[dest] = src.String()
+	}
 }
 
 func (s *snapshotBuilder) UnzipToSnapshot(zipPath android.Path, destDir string) {
@@ -368,13 +390,22 @@
 	s.zipsToMerge = append(s.zipsToMerge, tmpZipPath)
 }
 
-func (s *snapshotBuilder) AddPrebuiltModule(name string, moduleType string) android.BpModule {
+func (s *snapshotBuilder) AddPrebuiltModule(member android.SdkMember, moduleType string) android.BpModule {
+	name := member.Name()
 	if s.prebuiltModules[name] != nil {
 		panic(fmt.Sprintf("Duplicate module detected, module %s has already been added", name))
 	}
 
 	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)
+	}
+
 	addHostDeviceSupportedProperties(&s.sdk.ModuleBase, m)
 
 	s.prebuiltModules[name] = m
diff --git a/ui/build/paths/config.go b/ui/build/paths/config.go
index 909d93c..f347a11 100644
--- a/ui/build/paths/config.go
+++ b/ui/build/paths/config.go
@@ -75,7 +75,6 @@
 
 var Configuration = map[string]PathConfig{
 	"bash":     Allowed,
-	"bc":       Allowed,
 	"dd":       Allowed,
 	"diff":     Allowed,
 	"dlv":      Allowed,