Merge "Remove global state from vendor public libraries"
diff --git a/android/apex.go b/android/apex.go
index 25a07b8..60da45b 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -847,7 +847,6 @@
 	"libprocpartition":                                         30,
 	"libprotobuf-java-lite":                                    30,
 	"libprotoutil":                                             30,
-	"libqemu_pipe":                                             30,
 	"libsync":                                                  30,
 	"libtextclassifier_hash_headers":                           30,
 	"libtextclassifier_hash_static":                            30,
diff --git a/android/bazel.go b/android/bazel.go
index ba5ae31..e330681 100644
--- a/android/bazel.go
+++ b/android/bazel.go
@@ -167,61 +167,69 @@
 		"bionic":                Bp2BuildDefaultTrueRecursively,
 		"external/gwp_asan":     Bp2BuildDefaultTrueRecursively,
 		"system/core/libcutils": Bp2BuildDefaultTrueRecursively,
-		"system/logging/liblog": Bp2BuildDefaultTrueRecursively,
+		"system/core/property_service/libpropertyinfoparser": Bp2BuildDefaultTrueRecursively,
+		"system/libbase":                  Bp2BuildDefaultTrueRecursively,
+		"system/logging/liblog":           Bp2BuildDefaultTrueRecursively,
+		"external/arm-optimized-routines": Bp2BuildDefaultTrueRecursively,
 	}
 
 	// Per-module denylist to always opt modules out of both bp2build and mixed builds.
 	bp2buildModuleDoNotConvertList = []string{
-		"libBionicBenchmarksUtils",      // ruperts@, cc_library_static, 'map' file not found
-		"libbionic_spawn_benchmark",     // ruperts@, cc_library_static, depends on //system/libbase
-		"libc_jemalloc_wrapper",         // ruperts@, cc_library_static, depends on //external/jemalloc_new
-		"libc_bootstrap",                // ruperts@, cc_library_static, 'private/bionic_auxv.h' file not found
-		"libc_init_static",              // ruperts@, cc_library_static, 'private/bionic_elf_tls.h' file not found
-		"libc_init_dynamic",             // ruperts@, cc_library_static, 'private/bionic_defs.h' file not found
-		"libc_tzcode",                   // ruperts@, cc_library_static, error: expected expression
-		"libc_netbsd",                   // ruperts@, cc_library_static, 'engine.c' file not found
-		"libc_fortify",                  // ruperts@, cc_library_static, 'private/bionic_fortify.h' file not found
-		"libc_bionic",                   // ruperts@, cc_library_static, 'private/bionic_asm.h' file not found
-		"libc_bionic_ndk",               // ruperts@, cc_library_static, depends on //bionic/libc/system_properties
-		"libc_bionic_systrace",          // ruperts@, cc_library_static, 'private/bionic_systrace.h' file not found
-		"libc_pthread",                  // ruperts@, cc_library_static, 'private/bionic_defs.h' file not found
-		"libc_syscalls",                 // eakammer@, cc_library_static,  'private/bionic_asm.h' file not found
-		"libc_ndk",                      // ruperts@, cc_library_static, depends on //bionic/libm:libm
-		"libc_nopthread",                // ruperts@, cc_library_static, depends on //external/arm-optimized-routines
-		"libc_common",                   // ruperts@, cc_library_static, depends on //bionic/libc:libc_nopthread
-		"libc_common_static",            // ruperts@, cc_library_static, depends on //bionic/libc:libc_common
-		"libc_common_shared",            // ruperts@, cc_library_static, depends on //bionic/libc:libc_common
-		"libc_unwind_static",            // ruperts@, cc_library_static, 'private/bionic_elf_tls.h' file not found
-		"libc_nomalloc",                 // ruperts@, cc_library_static, depends on //bionic/libc:libc_common
-		"libasync_safe",                 // ruperts@, cc_library_static, 'private/CachedProperty.h' file not found
-		"libc_malloc_debug_backtrace",   // ruperts@, cc_library_static, depends on //system/libbase
-		"libsystemproperties",           // ruperts@, cc_library_static, depends on //system/core/property_service/libpropertyinfoparser
-		"libdl_static",                  // ruperts@, cc_library_static, 'private/CFIShadow.h' file not found
-		"liblinker_main",                // ruperts@, cc_library_static, depends on //system/libbase
-		"liblinker_malloc",              // ruperts@, cc_library_static, depends on //system/logging/liblog:liblog
-		"liblinker_debuggerd_stub",      // ruperts@, cc_library_static, depends on //system/libbase
-		"libbionic_tests_headers_posix", // ruperts@, cc_library_static, 'complex.h' file not found
-		"libc_dns",                      // ruperts@, cc_library_static, 'private/android_filesystem_config.h' file not found
-		"libc_static_dispatch",          // eakammer@, cc_library_static, 'private/bionic_asm.h' file not found
-		"libc_dynamic_dispatch",         // eakammer@, cc_library_static, 'private/bionic_ifuncs.h' file not found
-		"note_memtag_heap_async",        // jingwen@, cc_library_static, 'private/bionic_asm.h' file not found (arm64)
-		"note_memtag_heap_sync",         // jingwen@, cc_library_static, 'private/bionic_asm.h' file not found (arm64)
+		// Things that transitively depend on unconverted libc_* modules.
+		"libc_common",        // ruperts@, cc_library_static, depends on //bionic/libc:libc_nopthread
+		"libc_common_static", // ruperts@, cc_library_static, depends on //bionic/libc:libc_common
+		"libc_common_shared", // ruperts@, cc_library_static, depends on //bionic/libc:libc_common
+		"libc_nomalloc",      // ruperts@, cc_library_static, depends on //bionic/libc:libc_common
+		"libc_nopthread",     // ruperts@, cc_library_static, depends on lib_bionic_ndk, libc_syscalls, libc_tzcode, libstdc++
 
-		// List of all full_cc_libraries in //bionic, with their immediate failures
-		"libc",              // jingwen@, cc_library, depends on //external/gwp_asan
-		"libc_malloc_debug", // jingwen@, cc_library, fatal error: 'assert.h' file not found
-		"libc_malloc_hooks", // jingwen@, cc_library, fatal error: 'errno.h' file not found
-		"libdl",             // jingwen@, cc_library, ld.lld: error: no input files
-		"libm",              // lberki@, cc_library, compiler error: "Unexpected token in argument list"
-		"libseccomp_policy", // lberki@, cc_library, 'linux/filter.h' not found, caused by missing -isystem bionic/libc/kernel/uapi, dunno where it comes from in Soong
-		"libstdc++",         // jingwen@, cc_library, depends on //external/gwp_asan
+		// Things that transitively depend on //system/libbase. libbase doesn't work because:
+		// fmtlib: fatal error: 'cassert' file not found
+		"libbase",                     // eakammer@, cc_library, no such target '//build/bazel/platforms/os:darwin': target 'darwin' not declared
+		"libbase_ndk",                 // eakammer@, cc_library, no such target '//build/bazel/platforms/os:darwin': target 'darwin' not declared
+		"libbionic_spawn_benchmark",   // ruperts@, cc_library_static, depends on libbase, libgoogle-benchmark
+		"libc_malloc_debug",           // ruperts@, cc_library_static, depends on libbase
+		"libc_malloc_debug_backtrace", // ruperts@, cc_library_static, depends on libbase
+		"libcutils",                   // eakammer@, cc_library, depends on libbase, liblog
+		"libcutils_sockets",           // eakammer@, cc_library, depends on libbase, liblog
+		"liblinker_debuggerd_stub",    // ruperts@, cc_library_static, depends on libbase, libz, libziparchive
+		"liblinker_main",              // ruperts@, cc_library_static, depends on libbase, libz, libziparchive
+		"liblinker_malloc",            // ruperts@, cc_library_static, depends on libziparchive, libz, libbase
+
+		// Requires non-libc targets, but otherwise works
+		"libc_jemalloc_wrapper", // ruperts@, cc_library_static, depends on //external/jemalloc_new
+
+		// Compilation error, seems to be fixable by changing the toolchain definition
+		"libc_bionic_ndk", // ruperts@, cc_library_static, error: ISO C++ requires field designators...
+		"libc_tzcode",     // ruperts@, cc_library_static, error: expected expression
+		"libm",            // jingwen@, cc_library, error: "expected register here" (and many others)
+
+		// Linker error
+		"libc_malloc_hooks", // jingwen@, cc_library, undefined symbol: __malloc_hook, etc.
+		"libstdc++",         // jingwen@, cc_library, undefined symbol: free
+
+		// Includes not found
+		"libbionic_tests_headers_posix", // ruperts@, cc_library_static, 'dirent.h' not found
+		"liblog",                        // eakammer@, cc_library, 'sys/cdefs.h' file not found, missing -isystem bionic/libc/include through the libc/libm/libdl default dependencies if system_shared_libs unset
+		"libseccomp_policy",             // jingwen@, cc_library, 'linux/filter.h' not found, missing -isystem bionic/libc/kernel/uapi/asm-arm, probably due to us not handling arch { ... { export_system_include_dirs } } correctly
+		"note_memtag_heap_async",        // lberki@, cc_library_static, error: feature.h not found, missing -isystem bionic/libc/include through the libc/libm/libdl default dependencies if system_shared_libs unset
+		"note_memtag_heap_sync",         // lberki@, cc_library_static, error: feature.h not found, missing -isystem bionic/libc/include through the libc/libm/libdl default dependencies if system_shared_libs unset
+
+		// Other
+		"libBionicBenchmarksUtils", // ruperts@, cc_library_static, 'map' file not found
+		"libc_ndk",                 // ruperts@, cc_library_static, depends on libc_bionic_ndk, libc_jemalloc_wrapper, libc_tzcode, libstdc++
+
+		"libc", // jingwen@, cc_library, depends on //external/gwp_asan
 	}
 
 	// Per-module denylist to opt modules out of mixed builds. Such modules will
 	// still be generated via bp2build.
 	mixedBuildsDisabledList = []string{
-		"libc_gdtoa",   // ruperts@, cc_library_static, OK for bp2build but undefined symbol: __strtorQ for mixed builds
-		"libc_openbsd", // ruperts@, cc_library_static, OK for bp2build but error: duplicate symbol: strcpy for mixed builds
+		"libc_gdtoa",                       // ruperts@, cc_library_static, OK for bp2build but undefined symbol: __strtorQ for mixed builds
+		"libc_netbsd",                      // lberki@, cc_library_static, version script assignment of 'LIBC_PRIVATE' to symbol 'SHA1Final' failed: symbol not defined
+		"libc_openbsd",                     // ruperts@, cc_library_static, OK for bp2build but error: duplicate symbol: strcpy for mixed builds
+		"libsystemproperties",              // cparsons@, cc_library_static, wrong include paths
+		"libpropertyinfoparser",            // cparsons@, cc_library_static, wrong include paths
+		"libarm-optimized-routines-string", // jingwen@, cc_library_static, OK for bp2build but b/186615213 (asflags not handled in  bp2build), version script assignment of 'LIBC' to symbol 'memcmp' failed: symbol not defined (also for memrchr, strnlen)
 	}
 
 	// Used for quicker lookups
diff --git a/android/bazel_paths.go b/android/bazel_paths.go
index 63e2c50..4280bc3 100644
--- a/android/bazel_paths.go
+++ b/android/bazel_paths.go
@@ -243,6 +243,14 @@
 	labels := bazel.LabelList{
 		Includes: []bazel.Label{},
 	}
+
+	// expandedExcludes contain module-dir relative paths, but root-relative paths
+	// are needed for GlobFiles later.
+	var rootRelativeExpandedExcludes []string
+	for _, e := range expandedExcludes {
+		rootRelativeExpandedExcludes = append(rootRelativeExpandedExcludes, filepath.Join(ctx.ModuleDir(), e))
+	}
+
 	for _, p := range paths {
 		if m, tag := SrcIsModuleWithTag(p); m != "" {
 			l := getOtherModuleLabel(ctx, m, tag)
@@ -253,7 +261,10 @@
 		} else {
 			var expandedPaths []bazel.Label
 			if pathtools.IsGlob(p) {
-				globbedPaths := GlobFiles(ctx, pathForModuleSrc(ctx, p).String(), expandedExcludes)
+				// e.g. turn "math/*.c" in
+				// external/arm-optimized-routines to external/arm-optimized-routines/math/*.c
+				rootRelativeGlobPath := pathForModuleSrc(ctx, p).String()
+				globbedPaths := GlobFiles(ctx, rootRelativeGlobPath, rootRelativeExpandedExcludes)
 				globbedPaths = PathsWithModuleSrcSubDir(ctx, globbedPaths, "")
 				for _, path := range globbedPaths {
 					s := path.Rel()
diff --git a/android/module.go b/android/module.go
index 9f923e2..fdb5290 100644
--- a/android/module.go
+++ b/android/module.go
@@ -213,7 +213,7 @@
 
 	// GetDirectDep returns the Module and DependencyTag for the  direct dependency with the specified
 	// name, or nil if none exists.  If there are multiple dependencies on the same module it returns
-	// the first DependencyTag.  It skips any dependencies that are not an android.Module.
+	// the first DependencyTag.
 	GetDirectDep(name string) (blueprint.Module, blueprint.DependencyTag)
 
 	// VisitDirectDepsBlueprint calls visit for each direct dependency.  If there are multiple
@@ -2244,11 +2244,12 @@
 	return aModule
 }
 
-func (b *baseModuleContext) getDirectDepInternal(name string, tag blueprint.DependencyTag) (blueprint.Module, blueprint.DependencyTag) {
-	type dep struct {
-		mod blueprint.Module
-		tag blueprint.DependencyTag
-	}
+type dep struct {
+	mod blueprint.Module
+	tag blueprint.DependencyTag
+}
+
+func (b *baseModuleContext) getDirectDepsInternal(name string, tag blueprint.DependencyTag) []dep {
 	var deps []dep
 	b.VisitDirectDepsBlueprint(func(module blueprint.Module) {
 		if aModule, _ := module.(Module); aModule != nil {
@@ -2265,6 +2266,11 @@
 			}
 		}
 	})
+	return deps
+}
+
+func (b *baseModuleContext) getDirectDepInternal(name string, tag blueprint.DependencyTag) (blueprint.Module, blueprint.DependencyTag) {
+	deps := b.getDirectDepsInternal(name, tag)
 	if len(deps) == 1 {
 		return deps[0].mod, deps[0].tag
 	} else if len(deps) >= 2 {
@@ -2275,6 +2281,25 @@
 	}
 }
 
+func (b *baseModuleContext) getDirectDepFirstTag(name string) (blueprint.Module, blueprint.DependencyTag) {
+	foundDeps := b.getDirectDepsInternal(name, nil)
+	deps := map[blueprint.Module]bool{}
+	for _, dep := range foundDeps {
+		deps[dep.mod] = true
+	}
+	if len(deps) == 1 {
+		return foundDeps[0].mod, foundDeps[0].tag
+	} else if len(deps) >= 2 {
+		// this could happen if two dependencies have the same name in different namespaces
+		// TODO(b/186554727): this should not occur if namespaces are handled within
+		// getDirectDepsInternal.
+		panic(fmt.Errorf("Multiple dependencies having same BaseModuleName() %q found from %q",
+			name, b.ModuleName()))
+	} else {
+		return nil, nil
+	}
+}
+
 func (b *baseModuleContext) GetDirectDepsWithTag(tag blueprint.DependencyTag) []Module {
 	var deps []Module
 	b.VisitDirectDepsBlueprint(func(module blueprint.Module) {
@@ -2292,8 +2317,11 @@
 	return module
 }
 
+// GetDirectDep returns the Module and DependencyTag for the direct dependency with the specified
+// name, or nil if none exists. If there are multiple dependencies on the same module it returns the
+// first DependencyTag.
 func (b *baseModuleContext) GetDirectDep(name string) (blueprint.Module, blueprint.DependencyTag) {
-	return b.getDirectDepInternal(name, nil)
+	return b.getDirectDepFirstTag(name)
 }
 
 func (b *baseModuleContext) VisitDirectDepsBlueprint(visit func(blueprint.Module)) {
diff --git a/android/neverallow.go b/android/neverallow.go
index a385bbc..41b399a 100644
--- a/android/neverallow.go
+++ b/android/neverallow.go
@@ -63,8 +63,7 @@
 }
 
 func createIncludeDirsRules() []Rule {
-	// The list of paths that cannot be referenced using include_dirs
-	paths := []string{
+	notInIncludeDir := []string{
 		"art",
 		"art/libnativebridge",
 		"art/libnativeloader",
@@ -80,12 +79,22 @@
 		"external/vixl",
 		"external/wycheproof",
 	}
+	noUseIncludeDir := []string{
+		"frameworks/av/apex",
+		"frameworks/av/tools",
+		"frameworks/native/cmds",
+		"system/apex",
+		"system/bpf",
+		"system/gatekeeper",
+		"system/hwservicemanager",
+		"system/libbase",
+		"system/libfmq",
+		"system/libvintf",
+	}
 
-	// Create a composite matcher that will match if the value starts with any of the restricted
-	// paths. A / is appended to the prefix to ensure that restricting path X does not affect paths
-	// XY.
-	rules := make([]Rule, 0, len(paths))
-	for _, path := range paths {
+	rules := make([]Rule, 0, len(notInIncludeDir)+len(noUseIncludeDir))
+
+	for _, path := range notInIncludeDir {
 		rule :=
 			NeverAllow().
 				WithMatcher("include_dirs", StartsWith(path+"/")).
@@ -95,6 +104,13 @@
 		rules = append(rules, rule)
 	}
 
+	for _, path := range noUseIncludeDir {
+		rule := NeverAllow().In(path+"/").WithMatcher("include_dirs", isSetMatcherInstance).
+			Because("include_dirs is deprecated, all usages of them in '" + path + "' have been migrated" +
+				" to use alternate mechanisms and so can no longer be used.")
+		rules = append(rules, rule)
+	}
+
 	return rules
 }
 
diff --git a/android/neverallow_test.go b/android/neverallow_test.go
index 268346a..35aadd8 100644
--- a/android/neverallow_test.go
+++ b/android/neverallow_test.go
@@ -76,7 +76,20 @@
 		},
 	},
 	{
-		name: "include_dir can reference another location",
+		name: "include_dir not allowed to reference art",
+		fs: map[string][]byte{
+			"system/libfmq/Android.bp": []byte(`
+				cc_library {
+					name: "libother",
+					include_dirs: ["any/random/file"],
+				}`),
+		},
+		expectedErrors: []string{
+			"all usages of them in 'system/libfmq' have been migrated",
+		},
+	},
+	{
+		name: "include_dir can work",
 		fs: map[string][]byte{
 			"other/Android.bp": []byte(`
 				cc_library {
diff --git a/android/override_module.go b/android/override_module.go
index 97acc5c..0a7e294 100644
--- a/android/override_module.go
+++ b/android/override_module.go
@@ -244,11 +244,11 @@
 		// See if there's a prebuilt module that overrides this override module with prefer flag,
 		// in which case we call HideFromMake on the corresponding variant later.
 		ctx.VisitDirectDepsWithTag(PrebuiltDepTag, func(dep Module) {
-			prebuilt, ok := dep.(PrebuiltInterface)
-			if !ok {
+			prebuilt := GetEmbeddedPrebuilt(dep)
+			if prebuilt == nil {
 				panic("PrebuiltDepTag leads to a non-prebuilt module " + dep.Name())
 			}
-			if prebuilt.Prebuilt().UsePrebuilt() {
+			if prebuilt.UsePrebuilt() {
 				module.setOverriddenByPrebuilt(true)
 				return
 			}
diff --git a/android/prebuilt.go b/android/prebuilt.go
index 40bcdfd..43b7cbe 100644
--- a/android/prebuilt.go
+++ b/android/prebuilt.go
@@ -242,14 +242,30 @@
 		// A source module that has been replaced by a prebuilt counterpart.
 		return false
 	}
-	if prebuilt, ok := module.(PrebuiltInterface); ok {
-		if p := prebuilt.Prebuilt(); p != nil {
-			return p.UsePrebuilt()
-		}
+	if p := GetEmbeddedPrebuilt(module); p != nil {
+		return p.UsePrebuilt()
 	}
 	return true
 }
 
+// IsModulePrebuilt returns true if the module implements PrebuiltInterface and
+// has been initialized as a prebuilt and so returns a non-nil value from the
+// PrebuiltInterface.Prebuilt() method.
+func IsModulePrebuilt(module Module) bool {
+	return GetEmbeddedPrebuilt(module) != nil
+}
+
+// GetEmbeddedPrebuilt returns a pointer to the embedded Prebuilt structure or
+// nil if the module does not implement PrebuiltInterface or has not been
+// initialized as a prebuilt module.
+func GetEmbeddedPrebuilt(module Module) *Prebuilt {
+	if p, ok := module.(PrebuiltInterface); ok {
+		return p.Prebuilt()
+	}
+
+	return nil
+}
+
 func RegisterPrebuiltsPreArchMutators(ctx RegisterMutatorsContext) {
 	ctx.BottomUp("prebuilt_rename", PrebuiltRenameMutator).Parallel()
 }
@@ -263,11 +279,12 @@
 // PrebuiltRenameMutator ensures that there always is a module with an
 // undecorated name.
 func PrebuiltRenameMutator(ctx BottomUpMutatorContext) {
-	if m, ok := ctx.Module().(PrebuiltInterface); ok && m.Prebuilt() != nil {
+	m := ctx.Module()
+	if p := GetEmbeddedPrebuilt(m); p != nil {
 		name := m.base().BaseModuleName()
 		if !ctx.OtherModuleExists(name) {
 			ctx.Rename(name)
-			m.Prebuilt().properties.PrebuiltRenamedToSource = true
+			p.properties.PrebuiltRenamedToSource = true
 		}
 	}
 }
@@ -275,14 +292,14 @@
 // PrebuiltSourceDepsMutator adds dependencies to the prebuilt module from the
 // corresponding source module, if one exists for the same variant.
 func PrebuiltSourceDepsMutator(ctx BottomUpMutatorContext) {
-	if m, ok := ctx.Module().(PrebuiltInterface); ok && m.Enabled() && m.Prebuilt() != nil {
-		p := m.Prebuilt()
-		if !p.properties.PrebuiltRenamedToSource {
-			name := m.base().BaseModuleName()
-			if ctx.OtherModuleReverseDependencyVariantExists(name) {
-				ctx.AddReverseDependency(ctx.Module(), PrebuiltDepTag, name)
-				p.properties.SourceExists = true
-			}
+	m := ctx.Module()
+	// If this module is a prebuilt, is enabled and has not been renamed to source then add a
+	// dependency onto the source if it is present.
+	if p := GetEmbeddedPrebuilt(m); p != nil && m.Enabled() && !p.properties.PrebuiltRenamedToSource {
+		name := m.base().BaseModuleName()
+		if ctx.OtherModuleReverseDependencyVariantExists(name) {
+			ctx.AddReverseDependency(ctx.Module(), PrebuiltDepTag, name)
+			p.properties.SourceExists = true
 		}
 	}
 }
@@ -290,8 +307,8 @@
 // PrebuiltSelectModuleMutator marks prebuilts that are used, either overriding source modules or
 // because the source module doesn't exist.  It also disables installing overridden source modules.
 func PrebuiltSelectModuleMutator(ctx TopDownMutatorContext) {
-	if m, ok := ctx.Module().(PrebuiltInterface); ok && m.Prebuilt() != nil {
-		p := m.Prebuilt()
+	m := ctx.Module()
+	if p := GetEmbeddedPrebuilt(m); p != nil {
 		if p.srcsSupplier == nil {
 			panic(fmt.Errorf("prebuilt module did not have InitPrebuiltModule called on it"))
 		}
@@ -299,9 +316,9 @@
 			p.properties.UsePrebuilt = p.usePrebuilt(ctx, nil, m)
 		}
 	} else if s, ok := ctx.Module().(Module); ok {
-		ctx.VisitDirectDepsWithTag(PrebuiltDepTag, func(m Module) {
-			p := m.(PrebuiltInterface).Prebuilt()
-			if p.usePrebuilt(ctx, s, m) {
+		ctx.VisitDirectDepsWithTag(PrebuiltDepTag, func(prebuiltModule Module) {
+			p := GetEmbeddedPrebuilt(prebuiltModule)
+			if p.usePrebuilt(ctx, s, prebuiltModule) {
 				p.properties.UsePrebuilt = true
 				s.ReplacedByPrebuilt()
 			}
@@ -313,8 +330,8 @@
 // prebuilt when both modules exist and the prebuilt should be used.  When the prebuilt should not
 // be used, disable installing it.
 func PrebuiltPostDepsMutator(ctx BottomUpMutatorContext) {
-	if m, ok := ctx.Module().(PrebuiltInterface); ok && m.Prebuilt() != nil {
-		p := m.Prebuilt()
+	m := ctx.Module()
+	if p := GetEmbeddedPrebuilt(m); p != nil {
 		name := m.base().BaseModuleName()
 		if p.properties.UsePrebuilt {
 			if p.properties.SourceExists {
diff --git a/android/sdk.go b/android/sdk.go
index b4ef8aa..6fc1910 100644
--- a/android/sdk.go
+++ b/android/sdk.go
@@ -171,6 +171,16 @@
 	m.AddProperties(&base.properties)
 }
 
+// IsModuleInVersionedSdk returns true if the module is an versioned sdk.
+func IsModuleInVersionedSdk(module Module) bool {
+	if s, ok := module.(SdkAware); ok {
+		if !s.ContainingSdk().Unversioned() {
+			return true
+		}
+	}
+	return false
+}
+
 // Provide support for generating the build rules which will build the snapshot.
 type SnapshotBuilder interface {
 	// Copy src to the dest (which is a snapshot relative path) and add the dest
@@ -290,7 +300,7 @@
 
 	// SdkMemberType returns the SdkMemberType that will be used to automatically add the child module
 	// to the sdk.
-	SdkMemberType() SdkMemberType
+	SdkMemberType(child Module) SdkMemberType
 
 	// ExportMember determines whether a module added to the sdk through this tag will be exported
 	// from the sdk or not.
@@ -317,7 +327,7 @@
 	export     bool
 }
 
-func (t *sdkMemberDependencyTag) SdkMemberType() SdkMemberType {
+func (t *sdkMemberDependencyTag) SdkMemberType(_ Module) SdkMemberType {
 	return t.memberType
 }
 
diff --git a/bazel/properties.go b/bazel/properties.go
index 48d9589..037150d 100644
--- a/bazel/properties.go
+++ b/bazel/properties.go
@@ -64,43 +64,6 @@
 	Excludes []Label
 }
 
-// GlobsInDir returns a list of glob expressions for a list of extensions
-// (optionally recursive) within a directory.
-func GlobsInDir(dir string, recursive bool, extensions []string) []string {
-	globs := []string{}
-
-	globInfix := ""
-	if dir == "." {
-		if recursive {
-			// e.g "**/*.h"
-			globInfix = "**/"
-		} // else e.g. "*.h"
-		for _, ext := range extensions {
-			globs = append(globs, globInfix+"*"+ext)
-		}
-	} else {
-		if recursive {
-			// e.g. "foo/bar/**/*.h"
-			dir += "/**"
-		} // else e.g. "foo/bar/*.h"
-		for _, ext := range extensions {
-			globs = append(globs, dir+"/*"+ext)
-		}
-	}
-	return globs
-}
-
-// LooseHdrsGlobs returns the list of non-recursive header globs for each parent directory of
-// each source file in this LabelList's Includes.
-func (ll *LabelList) LooseHdrsGlobs(exts []string) []string {
-	var globs []string
-	for _, parentDir := range ll.uniqueParentDirectories() {
-		globs = append(globs,
-			GlobsInDir(parentDir, false, exts)...)
-	}
-	return globs
-}
-
 // uniqueParentDirectories returns a list of the unique parent directories for
 // all files in ll.Includes.
 func (ll *LabelList) uniqueParentDirectories() []string {
@@ -220,6 +183,15 @@
 	OS_LINUX        = "linux_glibc"
 	OS_LINUX_BIONIC = "linux_bionic"
 	OS_WINDOWS      = "windows"
+
+	// This is the string representation of the default condition wherever a
+	// configurable attribute is used in a select statement, i.e.
+	// //conditions:default for Bazel.
+	//
+	// This is consistently named "conditions_default" to mirror the Soong
+	// config variable default key in an Android.bp file, although there's no
+	// integration with Soong config variables (yet).
+	CONDITIONS_DEFAULT = "conditions_default"
 )
 
 var (
@@ -231,21 +203,23 @@
 	// A map of architectures to the Bazel label of the constraint_value
 	// for the @platforms//cpu:cpu constraint_setting
 	PlatformArchMap = map[string]string{
-		ARCH_ARM:    "//build/bazel/platforms/arch:arm",
-		ARCH_ARM64:  "//build/bazel/platforms/arch:arm64",
-		ARCH_X86:    "//build/bazel/platforms/arch:x86",
-		ARCH_X86_64: "//build/bazel/platforms/arch:x86_64",
+		ARCH_ARM:           "//build/bazel/platforms/arch:arm",
+		ARCH_ARM64:         "//build/bazel/platforms/arch:arm64",
+		ARCH_X86:           "//build/bazel/platforms/arch:x86",
+		ARCH_X86_64:        "//build/bazel/platforms/arch:x86_64",
+		CONDITIONS_DEFAULT: "//conditions:default", // The default condition of as arch select map.
 	}
 
 	// A map of target operating systems to the Bazel label of the
 	// constraint_value for the @platforms//os:os constraint_setting
 	PlatformOsMap = map[string]string{
-		OS_ANDROID:      "//build/bazel/platforms/os:android",
-		OS_DARWIN:       "//build/bazel/platforms/os:darwin",
-		OS_FUCHSIA:      "//build/bazel/platforms/os:fuchsia",
-		OS_LINUX:        "//build/bazel/platforms/os:linux",
-		OS_LINUX_BIONIC: "//build/bazel/platforms/os:linux_bionic",
-		OS_WINDOWS:      "//build/bazel/platforms/os:windows",
+		OS_ANDROID:         "//build/bazel/platforms/os:android",
+		OS_DARWIN:          "//build/bazel/platforms/os:darwin",
+		OS_FUCHSIA:         "//build/bazel/platforms/os:fuchsia",
+		OS_LINUX:           "//build/bazel/platforms/os:linux",
+		OS_LINUX_BIONIC:    "//build/bazel/platforms/os:linux_bionic",
+		OS_WINDOWS:         "//build/bazel/platforms/os:windows",
+		CONDITIONS_DEFAULT: "//conditions:default", // The default condition of an os select map.
 	}
 )
 
@@ -261,6 +235,8 @@
 	Arm    LabelList
 	Arm64  LabelList
 	Common LabelList
+
+	ConditionsDefault LabelList
 }
 
 type labelListOsValues struct {
@@ -270,6 +246,8 @@
 	Linux       LabelList
 	LinuxBionic LabelList
 	Windows     LabelList
+
+	ConditionsDefault LabelList
 }
 
 // LabelListAttribute is used to represent a list of Bazel labels as an
@@ -333,10 +311,11 @@
 
 func (attrs *LabelListAttribute) archValuePtrs() map[string]*LabelList {
 	return map[string]*LabelList{
-		ARCH_X86:    &attrs.ArchValues.X86,
-		ARCH_X86_64: &attrs.ArchValues.X86_64,
-		ARCH_ARM:    &attrs.ArchValues.Arm,
-		ARCH_ARM64:  &attrs.ArchValues.Arm64,
+		ARCH_X86:           &attrs.ArchValues.X86,
+		ARCH_X86_64:        &attrs.ArchValues.X86_64,
+		ARCH_ARM:           &attrs.ArchValues.Arm,
+		ARCH_ARM64:         &attrs.ArchValues.Arm64,
+		CONDITIONS_DEFAULT: &attrs.ArchValues.ConditionsDefault,
 	}
 }
 
@@ -360,12 +339,13 @@
 
 func (attrs *LabelListAttribute) osValuePtrs() map[string]*LabelList {
 	return map[string]*LabelList{
-		OS_ANDROID:      &attrs.OsValues.Android,
-		OS_DARWIN:       &attrs.OsValues.Darwin,
-		OS_FUCHSIA:      &attrs.OsValues.Fuchsia,
-		OS_LINUX:        &attrs.OsValues.Linux,
-		OS_LINUX_BIONIC: &attrs.OsValues.LinuxBionic,
-		OS_WINDOWS:      &attrs.OsValues.Windows,
+		OS_ANDROID:         &attrs.OsValues.Android,
+		OS_DARWIN:          &attrs.OsValues.Darwin,
+		OS_FUCHSIA:         &attrs.OsValues.Fuchsia,
+		OS_LINUX:           &attrs.OsValues.Linux,
+		OS_LINUX_BIONIC:    &attrs.OsValues.LinuxBionic,
+		OS_WINDOWS:         &attrs.OsValues.Windows,
+		CONDITIONS_DEFAULT: &attrs.OsValues.ConditionsDefault,
 	}
 }
 
@@ -418,6 +398,8 @@
 	Arm    []string
 	Arm64  []string
 	Common []string
+
+	ConditionsDefault []string
 }
 
 type stringListOsValues struct {
@@ -427,6 +409,8 @@
 	Linux       []string
 	LinuxBionic []string
 	Windows     []string
+
+	ConditionsDefault []string
 }
 
 // HasConfigurableValues returns true if the attribute contains
@@ -448,10 +432,11 @@
 
 func (attrs *StringListAttribute) archValuePtrs() map[string]*[]string {
 	return map[string]*[]string{
-		ARCH_X86:    &attrs.ArchValues.X86,
-		ARCH_X86_64: &attrs.ArchValues.X86_64,
-		ARCH_ARM:    &attrs.ArchValues.Arm,
-		ARCH_ARM64:  &attrs.ArchValues.Arm64,
+		ARCH_X86:           &attrs.ArchValues.X86,
+		ARCH_X86_64:        &attrs.ArchValues.X86_64,
+		ARCH_ARM:           &attrs.ArchValues.Arm,
+		ARCH_ARM64:         &attrs.ArchValues.Arm64,
+		CONDITIONS_DEFAULT: &attrs.ArchValues.ConditionsDefault,
 	}
 }
 
@@ -475,12 +460,13 @@
 
 func (attrs *StringListAttribute) osValuePtrs() map[string]*[]string {
 	return map[string]*[]string{
-		OS_ANDROID:      &attrs.OsValues.Android,
-		OS_DARWIN:       &attrs.OsValues.Darwin,
-		OS_FUCHSIA:      &attrs.OsValues.Fuchsia,
-		OS_LINUX:        &attrs.OsValues.Linux,
-		OS_LINUX_BIONIC: &attrs.OsValues.LinuxBionic,
-		OS_WINDOWS:      &attrs.OsValues.Windows,
+		OS_ANDROID:         &attrs.OsValues.Android,
+		OS_DARWIN:          &attrs.OsValues.Darwin,
+		OS_FUCHSIA:         &attrs.OsValues.Fuchsia,
+		OS_LINUX:           &attrs.OsValues.Linux,
+		OS_LINUX_BIONIC:    &attrs.OsValues.LinuxBionic,
+		OS_WINDOWS:         &attrs.OsValues.Windows,
+		CONDITIONS_DEFAULT: &attrs.OsValues.ConditionsDefault,
 	}
 }
 
diff --git a/bp2build/build_conversion_test.go b/bp2build/build_conversion_test.go
index 21d7062..63a6c2e 100644
--- a/bp2build/build_conversion_test.go
+++ b/bp2build/build_conversion_test.go
@@ -1512,3 +1512,126 @@
 		}
 	}
 }
+
+func TestGlobExcludeSrcs(t *testing.T) {
+	testCases := []struct {
+		description                        string
+		moduleTypeUnderTest                string
+		moduleTypeUnderTestFactory         android.ModuleFactory
+		moduleTypeUnderTestBp2BuildMutator func(android.TopDownMutatorContext)
+		bp                                 string
+		expectedBazelTargets               []string
+		fs                                 map[string]string
+		dir                                string
+	}{
+		{
+			description:                        "filegroup top level exclude_srcs",
+			moduleTypeUnderTest:                "filegroup",
+			moduleTypeUnderTestFactory:         android.FileGroupFactory,
+			moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
+			bp: `filegroup {
+    name: "fg_foo",
+    srcs: ["**/*.txt"],
+    exclude_srcs: ["c.txt"],
+    bazel_module: { bp2build_available: true },
+}`,
+			expectedBazelTargets: []string{`filegroup(
+    name = "fg_foo",
+    srcs = [
+        "//dir:e.txt",
+        "//dir:f.txt",
+        "a.txt",
+        "b.txt",
+    ],
+)`,
+			},
+			fs: map[string]string{
+				"a.txt":          "",
+				"b.txt":          "",
+				"c.txt":          "",
+				"dir/Android.bp": "",
+				"dir/e.txt":      "",
+				"dir/f.txt":      "",
+			},
+		},
+		{
+			description:                        "filegroup in subdir exclude_srcs",
+			moduleTypeUnderTest:                "filegroup",
+			moduleTypeUnderTestFactory:         android.FileGroupFactory,
+			moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
+			bp:                                 "",
+			dir:                                "dir",
+			fs: map[string]string{
+				"dir/Android.bp": `filegroup {
+    name: "fg_foo",
+    srcs: ["**/*.txt"],
+    exclude_srcs: ["b.txt"],
+    bazel_module: { bp2build_available: true },
+}
+`,
+				"dir/a.txt":             "",
+				"dir/b.txt":             "",
+				"dir/subdir/Android.bp": "",
+				"dir/subdir/e.txt":      "",
+				"dir/subdir/f.txt":      "",
+			},
+			expectedBazelTargets: []string{`filegroup(
+    name = "fg_foo",
+    srcs = [
+        "//dir/subdir:e.txt",
+        "//dir/subdir:f.txt",
+        "a.txt",
+    ],
+)`,
+			},
+		},
+	}
+
+	dir := "."
+	for _, testCase := range testCases {
+		fs := make(map[string][]byte)
+		toParse := []string{
+			"Android.bp",
+		}
+		for f, content := range testCase.fs {
+			if strings.HasSuffix(f, "Android.bp") {
+				toParse = append(toParse, f)
+			}
+			fs[f] = []byte(content)
+		}
+		config := android.TestConfig(buildDir, nil, testCase.bp, fs)
+		ctx := android.NewTestContext(config)
+		ctx.RegisterModuleType(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestFactory)
+		ctx.RegisterBp2BuildMutator(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestBp2BuildMutator)
+		ctx.RegisterForBazelConversion()
+
+		_, errs := ctx.ParseFileList(dir, toParse)
+		if Errored(t, testCase.description, errs) {
+			continue
+		}
+		_, errs = ctx.ResolveDependencies(config)
+		if Errored(t, testCase.description, errs) {
+			continue
+		}
+
+		checkDir := dir
+		if testCase.dir != "" {
+			checkDir = testCase.dir
+		}
+		bazelTargets := generateBazelTargetsForDir(NewCodegenContext(config, *ctx.Context, Bp2Build), checkDir)
+		if actualCount, expectedCount := len(bazelTargets), len(testCase.expectedBazelTargets); actualCount != expectedCount {
+			t.Errorf("%s: Expected %d bazel target, got %d\n%s", testCase.description, expectedCount, actualCount, bazelTargets)
+		} else {
+			for i, target := range bazelTargets {
+				if w, g := testCase.expectedBazelTargets[i], target.content; w != g {
+					t.Errorf(
+						"%s: Expected generated Bazel target to be '%s', got '%s'",
+						testCase.description,
+						w,
+						g,
+					)
+				}
+			}
+		}
+	}
+}
diff --git a/bp2build/cc_library_conversion_test.go b/bp2build/cc_library_conversion_test.go
index 4b6e888..aa8200b 100644
--- a/bp2build/cc_library_conversion_test.go
+++ b/bp2build/cc_library_conversion_test.go
@@ -50,6 +50,7 @@
 		expectedBazelTargets               []string
 		filesystem                         map[string]string
 		dir                                string
+		depsMutators                       []android.RegisterMutatorFunc
 	}{
 		{
 			description:                        "cc_library - simple example",
@@ -114,26 +115,13 @@
         "-I.",
     ],
     deps = [":some-headers"],
-    hdrs = ["foo-dir/a.h"],
     includes = ["foo-dir"],
     linkopts = ["-Wl,--exclude-libs=bar.a"] + select({
         "//build/bazel/platforms/arch:x86": ["-Wl,--exclude-libs=baz.a"],
         "//build/bazel/platforms/arch:x86_64": ["-Wl,--exclude-libs=qux.a"],
         "//conditions:default": [],
     }),
-    srcs = [
-        "impl.cpp",
-        "header.h",
-        "foo-dir/a.h",
-        "header.hh",
-        "header.hpp",
-        "header.hxx",
-        "header.h++",
-        "header.inl",
-        "header.inc",
-        "header.ipp",
-        "header.h.generic",
-    ] + select({
+    srcs = ["impl.cpp"] + select({
         "//build/bazel/platforms/arch:x86": ["x86.cpp"],
         "//build/bazel/platforms/arch:x86_64": ["x86_64.cpp"],
         "//conditions:default": [],
@@ -209,13 +197,84 @@
         "//build/bazel/platforms/arch:x86_64": ["-Wl,--exclude-libs=libgcc_eh.a"],
         "//conditions:default": [],
     }),
-    srcs = [
-        "ld_android.cpp",
-        "linked_list.h",
-        "linker.h",
-        "linker_block_allocator.h",
-        "linker_cfi.h",
+    srcs = ["ld_android.cpp"],
+)`},
+		},
+		{
+			description:                        "cc_library exclude_srcs - trimmed example of //external/arm-optimized-routines:libarm-optimized-routines-math",
+			moduleTypeUnderTest:                "cc_library",
+			moduleTypeUnderTestFactory:         cc.LibraryFactory,
+			moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
+			dir:                                "external",
+			filesystem: map[string]string{
+				"external/math/cosf.c":      "",
+				"external/math/erf.c":       "",
+				"external/math/erf_data.c":  "",
+				"external/math/erff.c":      "",
+				"external/math/erff_data.c": "",
+				"external/Android.bp": `
+cc_library {
+    name: "fake-libarm-optimized-routines-math",
+    exclude_srcs: [
+        // Provided by:
+        // bionic/libm/upstream-freebsd/lib/msun/src/s_erf.c
+        // bionic/libm/upstream-freebsd/lib/msun/src/s_erff.c
+        "math/erf.c",
+        "math/erf_data.c",
+        "math/erff.c",
+        "math/erff_data.c",
     ],
+    srcs: [
+        "math/*.c",
+    ],
+    // arch-specific settings
+    arch: {
+        arm64: {
+            cflags: [
+                "-DHAVE_FAST_FMA=1",
+            ],
+        },
+    },
+    bazel_module: { bp2build_available: true },
+}
+`,
+			},
+			bp: soongCcLibraryPreamble,
+			expectedBazelTargets: []string{`cc_library(
+    name = "fake-libarm-optimized-routines-math",
+    copts = ["-Iexternal"] + select({
+        "//build/bazel/platforms/arch:arm64": ["-DHAVE_FAST_FMA=1"],
+        "//conditions:default": [],
+    }),
+    srcs = ["math/cosf.c"],
+)`},
+		},
+		{
+			description:                        "cc_library shared/static props",
+			moduleTypeUnderTest:                "cc_library",
+			moduleTypeUnderTestFactory:         cc.LibraryFactory,
+			moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
+			depsMutators:                       []android.RegisterMutatorFunc{cc.RegisterDepsBp2Build},
+			dir:                                "foo/bar",
+			filesystem: map[string]string{
+				"foo/bar/a.cpp": "",
+				"foo/bar/Android.bp": `
+cc_library {
+    name: "a",
+    shared: { whole_static_libs: ["b"] },
+    static: { srcs: ["a.cpp"] },
+    bazel_module: { bp2build_available: true },
+}
+
+cc_library_static { name: "b" }
+`,
+			},
+			bp: soongCcLibraryPreamble,
+			expectedBazelTargets: []string{`cc_library(
+    name = "a",
+    copts = ["-Ifoo/bar"],
+    srcs = ["a.cpp"],
+    static_deps_for_shared = [":b"],
 )`},
 		},
 	}
@@ -236,11 +295,15 @@
 		ctx := android.NewTestContext(config)
 
 		cc.RegisterCCBuildComponents(ctx)
+		ctx.RegisterModuleType("cc_library_static", cc.LibraryStaticFactory)
 		ctx.RegisterModuleType("toolchain_library", cc.ToolchainLibraryFactory)
 		ctx.RegisterModuleType("cc_library_headers", cc.LibraryHeaderFactory)
 		ctx.RegisterModuleType(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestFactory)
 		ctx.RegisterBp2BuildMutator(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestBp2BuildMutator)
 		ctx.RegisterBp2BuildConfig(bp2buildConfig) // TODO(jingwen): make this the default for all tests
+		for _, m := range testCase.depsMutators {
+			ctx.DepsBp2BuildMutators(m)
+		}
 		ctx.RegisterForBazelConversion()
 
 		_, errs := ctx.ParseFileList(dir, toParse)
diff --git a/bp2build/cc_library_headers_conversion_test.go b/bp2build/cc_library_headers_conversion_test.go
index 00042ab..0905aba 100644
--- a/bp2build/cc_library_headers_conversion_test.go
+++ b/bp2build/cc_library_headers_conversion_test.go
@@ -136,17 +136,6 @@
         ":lib-1",
         ":lib-2",
     ],
-    hdrs = [
-        "dir-1/dir1a.h",
-        "dir-1/dir1b.h",
-        "dir-2/dir2a.h",
-        "dir-2/dir2b.h",
-    ] + select({
-        "//build/bazel/platforms/arch:arm64": ["arch_arm64_exported_include_dir/a.h"],
-        "//build/bazel/platforms/arch:x86": ["arch_x86_exported_include_dir/b.h"],
-        "//build/bazel/platforms/arch:x86_64": ["arch_x86_64_exported_include_dir/c.h"],
-        "//conditions:default": [],
-    }),
     includes = [
         "dir-1",
         "dir-2",
@@ -159,18 +148,10 @@
 )`, `cc_library_headers(
     name = "lib-1",
     copts = ["-I."],
-    hdrs = [
-        "lib-1/lib1a.h",
-        "lib-1/lib1b.h",
-    ],
     includes = ["lib-1"],
 )`, `cc_library_headers(
     name = "lib-2",
     copts = ["-I."],
-    hdrs = [
-        "lib-2/lib2a.h",
-        "lib-2/lib2b.h",
-    ],
     includes = ["lib-2"],
 )`},
 		},
diff --git a/bp2build/cc_library_static_conversion_test.go b/bp2build/cc_library_static_conversion_test.go
index 00325fb..e8235d5 100644
--- a/bp2build/cc_library_static_conversion_test.go
+++ b/bp2build/cc_library_static_conversion_test.go
@@ -192,12 +192,6 @@
         ":whole_static_lib_1",
         ":whole_static_lib_2",
     ],
-    hdrs = [
-        "export_include_dir_1/export_include_dir_1_a.h",
-        "export_include_dir_1/export_include_dir_1_b.h",
-        "export_include_dir_2/export_include_dir_2_a.h",
-        "export_include_dir_2/export_include_dir_2_b.h",
-    ],
     includes = [
         "export_include_dir_1",
         "export_include_dir_2",
@@ -206,105 +200,27 @@
     srcs = [
         "foo_static1.cc",
         "foo_static2.cc",
-        "implicit_include_1.h",
-        "implicit_include_2.h",
-        "export_include_dir_1/export_include_dir_1_a.h",
-        "export_include_dir_1/export_include_dir_1_b.h",
-        "export_include_dir_2/export_include_dir_2_a.h",
-        "export_include_dir_2/export_include_dir_2_b.h",
-        "include_dir_1/include_dir_1_a.h",
-        "include_dir_1/include_dir_1_b.h",
-        "include_dir_2/include_dir_2_a.h",
-        "include_dir_2/include_dir_2_b.h",
-        "local_include_dir_1/local_include_dir_1_a.h",
-        "local_include_dir_1/local_include_dir_1_b.h",
-        "local_include_dir_2/local_include_dir_2_a.h",
-        "local_include_dir_2/local_include_dir_2_b.h",
     ],
 )`, `cc_library_static(
     name = "static_lib_1",
     copts = ["-I."],
     linkstatic = True,
-    srcs = [
-        "static_lib_1.cc",
-        "implicit_include_1.h",
-        "implicit_include_2.h",
-        "export_include_dir_1/export_include_dir_1_a.h",
-        "export_include_dir_1/export_include_dir_1_b.h",
-        "export_include_dir_2/export_include_dir_2_a.h",
-        "export_include_dir_2/export_include_dir_2_b.h",
-        "include_dir_1/include_dir_1_a.h",
-        "include_dir_1/include_dir_1_b.h",
-        "include_dir_2/include_dir_2_a.h",
-        "include_dir_2/include_dir_2_b.h",
-        "local_include_dir_1/local_include_dir_1_a.h",
-        "local_include_dir_1/local_include_dir_1_b.h",
-        "local_include_dir_2/local_include_dir_2_a.h",
-        "local_include_dir_2/local_include_dir_2_b.h",
-    ],
+    srcs = ["static_lib_1.cc"],
 )`, `cc_library_static(
     name = "static_lib_2",
     copts = ["-I."],
     linkstatic = True,
-    srcs = [
-        "static_lib_2.cc",
-        "implicit_include_1.h",
-        "implicit_include_2.h",
-        "export_include_dir_1/export_include_dir_1_a.h",
-        "export_include_dir_1/export_include_dir_1_b.h",
-        "export_include_dir_2/export_include_dir_2_a.h",
-        "export_include_dir_2/export_include_dir_2_b.h",
-        "include_dir_1/include_dir_1_a.h",
-        "include_dir_1/include_dir_1_b.h",
-        "include_dir_2/include_dir_2_a.h",
-        "include_dir_2/include_dir_2_b.h",
-        "local_include_dir_1/local_include_dir_1_a.h",
-        "local_include_dir_1/local_include_dir_1_b.h",
-        "local_include_dir_2/local_include_dir_2_a.h",
-        "local_include_dir_2/local_include_dir_2_b.h",
-    ],
+    srcs = ["static_lib_2.cc"],
 )`, `cc_library_static(
     name = "whole_static_lib_1",
     copts = ["-I."],
     linkstatic = True,
-    srcs = [
-        "whole_static_lib_1.cc",
-        "implicit_include_1.h",
-        "implicit_include_2.h",
-        "export_include_dir_1/export_include_dir_1_a.h",
-        "export_include_dir_1/export_include_dir_1_b.h",
-        "export_include_dir_2/export_include_dir_2_a.h",
-        "export_include_dir_2/export_include_dir_2_b.h",
-        "include_dir_1/include_dir_1_a.h",
-        "include_dir_1/include_dir_1_b.h",
-        "include_dir_2/include_dir_2_a.h",
-        "include_dir_2/include_dir_2_b.h",
-        "local_include_dir_1/local_include_dir_1_a.h",
-        "local_include_dir_1/local_include_dir_1_b.h",
-        "local_include_dir_2/local_include_dir_2_a.h",
-        "local_include_dir_2/local_include_dir_2_b.h",
-    ],
+    srcs = ["whole_static_lib_1.cc"],
 )`, `cc_library_static(
     name = "whole_static_lib_2",
     copts = ["-I."],
     linkstatic = True,
-    srcs = [
-        "whole_static_lib_2.cc",
-        "implicit_include_1.h",
-        "implicit_include_2.h",
-        "export_include_dir_1/export_include_dir_1_a.h",
-        "export_include_dir_1/export_include_dir_1_b.h",
-        "export_include_dir_2/export_include_dir_2_a.h",
-        "export_include_dir_2/export_include_dir_2_b.h",
-        "include_dir_1/include_dir_1_a.h",
-        "include_dir_1/include_dir_1_b.h",
-        "include_dir_2/include_dir_2_a.h",
-        "include_dir_2/include_dir_2_b.h",
-        "local_include_dir_1/local_include_dir_1_a.h",
-        "local_include_dir_1/local_include_dir_1_b.h",
-        "local_include_dir_2/local_include_dir_2_a.h",
-        "local_include_dir_2/local_include_dir_2_b.h",
-    ],
+    srcs = ["whole_static_lib_2.cc"],
 )`},
 		},
 		{
@@ -342,14 +258,6 @@
         "-I.",
     ],
     linkstatic = True,
-    srcs = [
-        "//subpackage:subpackage_header.h",
-        "//subpackage:subdirectory/subdirectory_header.h",
-        "//subpackage/subsubpackage:subsubpackage_header.h",
-        "//subpackage/subsubpackage:subdirectory/subdirectory_header.h",
-        "//subpackage/subsubpackage/subsubsubpackage:subsubsubpackage_header.h",
-        "//subpackage/subsubpackage/subsubsubpackage:subdirectory/subdirectory_header.h",
-    ],
 )`},
 		},
 		{
@@ -371,16 +279,8 @@
 			expectedBazelTargets: []string{`cc_library_static(
     name = "foo_static",
     copts = ["-I."],
-    hdrs = [
-        "//subpackage:subdirectory/subdirectory_header.h",
-        "//subpackage:subpackage_header.h",
-    ],
     includes = ["subpackage"],
     linkstatic = True,
-    srcs = [
-        "//subpackage:subpackage_header.h",
-        "//subpackage:subdirectory/subdirectory_header.h",
-    ],
 )`},
 		},
 		{
@@ -402,16 +302,8 @@
 			expectedBazelTargets: []string{`cc_library_static(
     name = "foo_static",
     copts = ["-I."],
-    hdrs = [
-        "//subpackage:subdirectory/subdirectory_header.h",
-        "//subpackage:subpackage_header.h",
-    ],
     includes = ["subpackage"],
     linkstatic = True,
-    srcs = [
-        "//subpackage:subpackage_header.h",
-        "//subpackage:subdirectory/subdirectory_header.h",
-    ],
 )`},
 		},
 		{
@@ -452,14 +344,8 @@
         "-Isubpackage/subsubpackage2",
         "-Isubpackage",
     ],
-    hdrs = ["exported_subsubpackage/header.h"],
     includes = ["./exported_subsubpackage"],
     linkstatic = True,
-    srcs = [
-        "exported_subsubpackage/header.h",
-        "subsubpackage/header.h",
-        "subsubpackage2/header.h",
-    ],
 )`},
 		},
 		{
@@ -517,11 +403,6 @@
         "-I.",
     ],
     linkstatic = True,
-    srcs = [
-        "//subpackage:subpackage_header.h",
-        "//subpackage:subdirectory/subdirectory_header.h",
-        "//subpackage2:subpackage2_header.h",
-    ],
 )`},
 		},
 		{
@@ -645,6 +526,226 @@
     linkstatic = True,
 )`},
 		},
+		{
+			description:                        "cc_library_static simple exclude_srcs",
+			moduleTypeUnderTest:                "cc_library_static",
+			moduleTypeUnderTestFactory:         cc.LibraryStaticFactory,
+			moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
+			depsMutators:                       []android.RegisterMutatorFunc{cc.RegisterDepsBp2Build},
+			filesystem: map[string]string{
+				"common.c":       "",
+				"foo-a.c":        "",
+				"foo-excluded.c": "",
+			},
+			bp: soongCcLibraryStaticPreamble + `
+cc_library_static {
+    name: "foo_static",
+    srcs: ["common.c", "foo-*.c"],
+    exclude_srcs: ["foo-excluded.c"],
+}`,
+			expectedBazelTargets: []string{`cc_library_static(
+    name = "foo_static",
+    copts = ["-I."],
+    linkstatic = True,
+    srcs = [
+        "common.c",
+        "foo-a.c",
+    ],
+)`},
+		},
+		{
+			description:                        "cc_library_static one arch specific srcs",
+			moduleTypeUnderTest:                "cc_library_static",
+			moduleTypeUnderTestFactory:         cc.LibraryStaticFactory,
+			moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
+			depsMutators:                       []android.RegisterMutatorFunc{cc.RegisterDepsBp2Build},
+			filesystem: map[string]string{
+				"common.c":  "",
+				"foo-arm.c": "",
+			},
+			bp: soongCcLibraryStaticPreamble + `
+cc_library_static {
+    name: "foo_static",
+    srcs: ["common.c"],
+    arch: { arm: { srcs: ["foo-arm.c"] } }
+}`,
+			expectedBazelTargets: []string{`cc_library_static(
+    name = "foo_static",
+    copts = ["-I."],
+    linkstatic = True,
+    srcs = ["common.c"] + select({
+        "//build/bazel/platforms/arch:arm": ["foo-arm.c"],
+        "//conditions:default": [],
+    }),
+)`},
+		},
+		{
+			description:                        "cc_library_static one arch specific srcs and exclude_srcs",
+			moduleTypeUnderTest:                "cc_library_static",
+			moduleTypeUnderTestFactory:         cc.LibraryStaticFactory,
+			moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
+			depsMutators:                       []android.RegisterMutatorFunc{cc.RegisterDepsBp2Build},
+			filesystem: map[string]string{
+				"common.c":           "",
+				"for-arm.c":          "",
+				"not-for-arm.c":      "",
+				"not-for-anything.c": "",
+			},
+			bp: soongCcLibraryStaticPreamble + `
+cc_library_static {
+    name: "foo_static",
+    srcs: ["common.c", "not-for-*.c"],
+    exclude_srcs: ["not-for-anything.c"],
+    arch: {
+        arm: { srcs: ["for-arm.c"], exclude_srcs: ["not-for-arm.c"] },
+    },
+}`,
+			expectedBazelTargets: []string{`cc_library_static(
+    name = "foo_static",
+    copts = ["-I."],
+    linkstatic = True,
+    srcs = ["common.c"] + select({
+        "//build/bazel/platforms/arch:arm": ["for-arm.c"],
+        "//conditions:default": ["not-for-arm.c"],
+    }),
+)`},
+		},
+		{
+			description:                        "cc_library_static arch specific exclude_srcs for 2 architectures",
+			moduleTypeUnderTest:                "cc_library_static",
+			moduleTypeUnderTestFactory:         cc.LibraryStaticFactory,
+			moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
+			depsMutators:                       []android.RegisterMutatorFunc{cc.RegisterDepsBp2Build},
+			filesystem: map[string]string{
+				"common.c":      "",
+				"for-arm.c":     "",
+				"for-x86.c":     "",
+				"not-for-arm.c": "",
+				"not-for-x86.c": "",
+			},
+			bp: soongCcLibraryStaticPreamble + `
+cc_library_static {
+    name: "foo_static",
+    srcs: ["common.c", "not-for-*.c"],
+    exclude_srcs: ["not-for-everything.c"],
+    arch: {
+        arm: { srcs: ["for-arm.c"], exclude_srcs: ["not-for-arm.c"] },
+        x86: { srcs: ["for-x86.c"], exclude_srcs: ["not-for-x86.c"] },
+    },
+} `,
+			expectedBazelTargets: []string{`cc_library_static(
+    name = "foo_static",
+    copts = ["-I."],
+    linkstatic = True,
+    srcs = ["common.c"] + select({
+        "//build/bazel/platforms/arch:arm": [
+            "for-arm.c",
+            "not-for-x86.c",
+        ],
+        "//build/bazel/platforms/arch:x86": [
+            "for-x86.c",
+            "not-for-arm.c",
+        ],
+        "//conditions:default": [
+            "not-for-arm.c",
+            "not-for-x86.c",
+        ],
+    }),
+)`},
+		},
+		{
+			description:                        "cc_library_static arch specific exclude_srcs for 4 architectures",
+			moduleTypeUnderTest:                "cc_library_static",
+			moduleTypeUnderTestFactory:         cc.LibraryStaticFactory,
+			moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
+			depsMutators:                       []android.RegisterMutatorFunc{cc.RegisterDepsBp2Build},
+			filesystem: map[string]string{
+				"common.c":             "",
+				"for-arm.c":            "",
+				"for-arm64.c":          "",
+				"for-x86.c":            "",
+				"for-x86_64.c":         "",
+				"not-for-arm.c":        "",
+				"not-for-arm64.c":      "",
+				"not-for-x86.c":        "",
+				"not-for-x86_64.c":     "",
+				"not-for-everything.c": "",
+			},
+			bp: soongCcLibraryStaticPreamble + `
+cc_library_static {
+    name: "foo_static",
+    srcs: ["common.c", "not-for-*.c"],
+    exclude_srcs: ["not-for-everything.c"],
+    arch: {
+        arm: { srcs: ["for-arm.c"], exclude_srcs: ["not-for-arm.c"] },
+        arm64: { srcs: ["for-arm64.c"], exclude_srcs: ["not-for-arm64.c"] },
+        x86: { srcs: ["for-x86.c"], exclude_srcs: ["not-for-x86.c"] },
+        x86_64: { srcs: ["for-x86_64.c"], exclude_srcs: ["not-for-x86_64.c"] },
+	},
+} `,
+			expectedBazelTargets: []string{`cc_library_static(
+    name = "foo_static",
+    copts = ["-I."],
+    linkstatic = True,
+    srcs = ["common.c"] + select({
+        "//build/bazel/platforms/arch:arm": [
+            "for-arm.c",
+            "not-for-arm64.c",
+            "not-for-x86.c",
+            "not-for-x86_64.c",
+        ],
+        "//build/bazel/platforms/arch:arm64": [
+            "for-arm64.c",
+            "not-for-arm.c",
+            "not-for-x86.c",
+            "not-for-x86_64.c",
+        ],
+        "//build/bazel/platforms/arch:x86": [
+            "for-x86.c",
+            "not-for-arm.c",
+            "not-for-arm64.c",
+            "not-for-x86_64.c",
+        ],
+        "//build/bazel/platforms/arch:x86_64": [
+            "for-x86_64.c",
+            "not-for-arm.c",
+            "not-for-arm64.c",
+            "not-for-x86.c",
+        ],
+        "//conditions:default": [
+            "not-for-arm.c",
+            "not-for-arm64.c",
+            "not-for-x86.c",
+            "not-for-x86_64.c",
+        ],
+    }),
+)`},
+		},
+		{
+			description:                        "cc_library_static multiple dep same name panic",
+			moduleTypeUnderTest:                "cc_library_static",
+			moduleTypeUnderTestFactory:         cc.LibraryStaticFactory,
+			moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
+			depsMutators:                       []android.RegisterMutatorFunc{cc.RegisterDepsBp2Build},
+			filesystem:                         map[string]string{},
+			bp: soongCcLibraryStaticPreamble + `
+cc_library_static { name: "static_dep" }
+cc_library_static {
+    name: "foo_static",
+    static_libs: ["static_dep"],
+    whole_static_libs: ["static_dep"],
+}`,
+			expectedBazelTargets: []string{`cc_library_static(
+    name = "foo_static",
+    copts = ["-I."],
+    deps = [":static_dep"],
+    linkstatic = True,
+)`, `cc_library_static(
+    name = "static_dep",
+    copts = ["-I."],
+    linkstatic = True,
+)`},
+		},
 	}
 
 	dir := "."
diff --git a/bp2build/cc_object_conversion_test.go b/bp2build/cc_object_conversion_test.go
index d00a1cb..9efdb53 100644
--- a/bp2build/cc_object_conversion_test.go
+++ b/bp2build/cc_object_conversion_test.go
@@ -67,11 +67,7 @@
         "-Iinclude",
         "-I.",
     ],
-    srcs = [
-        "a/b/c.c",
-        "a/b/bar.h",
-        "a/b/foo.h",
-    ],
+    srcs = ["a/b/c.c"],
 )`,
 			},
 		},
diff --git a/bp2build/configurability.go b/bp2build/configurability.go
index b9ffc04..52afb55 100644
--- a/bp2build/configurability.go
+++ b/bp2build/configurability.go
@@ -99,8 +99,15 @@
 		return "", nil
 	}
 
+	// addConditionsDefault := false
+	conditionsDefaultKey := bazel.PlatformArchMap[bazel.CONDITIONS_DEFAULT]
+
 	var selects string
 	for _, selectKey := range android.SortedStringKeys(selectMap) {
+		if selectKey == conditionsDefaultKey {
+			// Handle default condition later.
+			continue
+		}
 		value := selectMap[selectKey]
 		if isZero(value) {
 			// Ignore zero values to not generate empty lists.
@@ -125,8 +132,22 @@
 	// Create the map.
 	ret := "select({\n"
 	ret += selects
-	// default condition comes last.
-	ret += fmt.Sprintf("%s\"%s\": %s,\n", makeIndent(indent+1), "//conditions:default", defaultValue)
+
+	// Handle the default condition
+	s, err := prettyPrintSelectEntry(selectMap[conditionsDefaultKey], conditionsDefaultKey, indent)
+	if err != nil {
+		return "", err
+	}
+	if s == "" {
+		// Print an explicit empty list (the default value) even if the value is
+		// empty, to avoid errors about not finding a configuration that matches.
+		ret += fmt.Sprintf("%s\"%s\": %s,\n", makeIndent(indent+1), "//conditions:default", defaultValue)
+	} else {
+		// Print the custom default value.
+		ret += s
+		ret += ",\n"
+	}
+
 	ret += makeIndent(indent)
 	ret += "})"
 
diff --git a/cc/bp2build.go b/cc/bp2build.go
index efa2752..a4db79f 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -68,9 +68,61 @@
 		}
 	}
 
+	// Deps in the static: { .. } and shared: { .. } props of a cc_library.
+	if lib, ok := module.compiler.(*libraryDecorator); ok {
+		allDeps = append(allDeps, lib.SharedProperties.Shared.Static_libs...)
+		allDeps = append(allDeps, lib.SharedProperties.Shared.Whole_static_libs...)
+		allDeps = append(allDeps, lib.SharedProperties.Shared.Shared_libs...)
+		allDeps = append(allDeps, lib.SharedProperties.Shared.System_shared_libs...)
+
+		allDeps = append(allDeps, lib.StaticProperties.Static.Static_libs...)
+		allDeps = append(allDeps, lib.StaticProperties.Static.Whole_static_libs...)
+		allDeps = append(allDeps, lib.StaticProperties.Static.Shared_libs...)
+		allDeps = append(allDeps, lib.StaticProperties.Static.System_shared_libs...)
+	}
+
 	ctx.AddDependency(module, nil, android.SortedUniqueStrings(allDeps)...)
 }
 
+type sharedAttributes struct {
+	staticDeps bazel.LabelListAttribute
+}
+
+// bp2buildParseSharedProps returns the attributes for the shared variant of a cc_library.
+func bp2BuildParseSharedProps(ctx android.TopDownMutatorContext, module *Module) sharedAttributes {
+	lib, ok := module.compiler.(*libraryDecorator)
+	if !ok {
+		return sharedAttributes{}
+	}
+
+	var staticDeps bazel.LabelListAttribute
+
+	staticDeps.Value = android.BazelLabelForModuleDeps(ctx, lib.SharedProperties.Shared.Whole_static_libs)
+
+	return sharedAttributes{
+		staticDeps: staticDeps,
+	}
+}
+
+type staticAttributes struct {
+	srcs bazel.LabelListAttribute
+}
+
+// bp2buildParseStaticProps returns the attributes for the static variant of a cc_library.
+func bp2BuildParseStaticProps(ctx android.TopDownMutatorContext, module *Module) staticAttributes {
+	lib, ok := module.compiler.(*libraryDecorator)
+	if !ok {
+		return staticAttributes{}
+	}
+
+	var srcs bazel.LabelListAttribute
+	srcs.Value = android.BazelLabelForModuleSrc(ctx, lib.StaticProperties.Static.Srcs)
+
+	return staticAttributes{
+		srcs: srcs,
+	}
+}
+
 // Convenience struct to hold all attributes parsed from compiler properties.
 type compilerAttributes struct {
 	copts    bazel.StringListAttribute
@@ -80,7 +132,7 @@
 
 // bp2BuildParseCompilerProps returns copts, srcs and hdrs and other attributes.
 func bp2BuildParseCompilerProps(ctx android.TopDownMutatorContext, module *Module) compilerAttributes {
-	var localHdrs, srcs bazel.LabelListAttribute
+	var srcs bazel.LabelListAttribute
 	var copts bazel.StringListAttribute
 
 	// Creates the -I flag for a directory, while making the directory relative
@@ -90,11 +142,6 @@
 		return "-I" + filepath.Join(ctx.ModuleDir(), dir)
 	}
 
-	// Parse the list of srcs, excluding files from exclude_srcs.
-	parseSrcs := func(baseCompilerProps *BaseCompilerProperties) bazel.LabelList {
-		return android.BazelLabelForModuleSrcExcludes(ctx, baseCompilerProps.Srcs, baseCompilerProps.Exclude_srcs)
-	}
-
 	// Parse the list of module-relative include directories (-I).
 	parseLocalIncludeDirs := func(baseCompilerProps *BaseCompilerProperties) []string {
 		// include_dirs are root-relative, not module-relative.
@@ -111,40 +158,85 @@
 		return copts
 	}
 
+	// baseSrcs contain the list of src files that are used for every configuration.
+	var baseSrcs []string
+	// baseExcludeSrcs contain the list of src files that are excluded for every configuration.
+	var baseExcludeSrcs []string
+	// baseSrcsLabelList is a clone of the base srcs LabelList, used for computing the
+	// arch or os specific srcs later.
+	var baseSrcsLabelList bazel.LabelList
+
+	// Parse srcs from an arch or OS's props value, taking the base srcs and
+	// exclude srcs into account.
+	parseSrcs := func(baseCompilerProps *BaseCompilerProperties) bazel.LabelList {
+		// Combine the base srcs and arch-specific srcs
+		allSrcs := append(baseSrcs, baseCompilerProps.Srcs...)
+		// Combine the base exclude_srcs and configuration-specific exclude_srcs
+		allExcludeSrcs := append(baseExcludeSrcs, baseCompilerProps.Exclude_srcs...)
+		return android.BazelLabelForModuleSrcExcludes(ctx, allSrcs, allExcludeSrcs)
+	}
+
 	for _, props := range module.compiler.compilerProps() {
 		if baseCompilerProps, ok := props.(*BaseCompilerProperties); ok {
 			srcs.Value = parseSrcs(baseCompilerProps)
 			copts.Value = parseCopts(baseCompilerProps)
+
+			// Used for arch-specific srcs later.
+			baseSrcs = baseCompilerProps.Srcs
+			baseExcludeSrcs = baseCompilerProps.Exclude_srcs
+			baseSrcsLabelList = parseSrcs(baseCompilerProps)
 			break
 		}
 	}
 
+	// Handle include_build_directory prop. If the property is true, then the
+	// target has access to all headers recursively in the package, and has
+	// "-I<module-dir>" in its copts.
 	if c, ok := module.compiler.(*baseCompiler); ok && c.includeBuildDirectory() {
 		copts.Value = append(copts.Value, includeFlag("."))
-		localHdrs.Value = bp2BuildListHeadersInDir(ctx, ".")
 	} else if c, ok := module.compiler.(*libraryDecorator); ok && c.includeBuildDirectory() {
 		copts.Value = append(copts.Value, includeFlag("."))
-		localHdrs.Value = bp2BuildListHeadersInDir(ctx, ".")
 	}
 
 	for arch, props := range module.GetArchProperties(&BaseCompilerProperties{}) {
 		if baseCompilerProps, ok := props.(*BaseCompilerProperties); ok {
-			srcsList := parseSrcs(baseCompilerProps)
-			srcs.SetValueForArch(arch.Name, bazel.SubtractBazelLabelList(srcsList, srcs.Value))
+			// If there's arch specific srcs or exclude_srcs, generate a select entry for it.
+			// TODO(b/186153868): do this for OS specific srcs and exclude_srcs too.
+			if len(baseCompilerProps.Srcs) > 0 || len(baseCompilerProps.Exclude_srcs) > 0 {
+				srcsList := parseSrcs(baseCompilerProps)
+				srcs.SetValueForArch(arch.Name, srcsList)
+				// The base srcs value should not contain any arch-specific excludes.
+				srcs.Value = bazel.SubtractBazelLabelList(srcs.Value, bazel.LabelList{Includes: srcsList.Excludes})
+			}
+
 			copts.SetValueForArch(arch.Name, parseCopts(baseCompilerProps))
 		}
 	}
 
-	for os, props := range module.GetTargetProperties(&BaseCompilerProperties{}) {
-		if baseCompilerProps, ok := props.(*BaseCompilerProperties); ok {
-			srcsList := parseSrcs(baseCompilerProps)
-			srcs.SetValueForOS(os.Name, bazel.SubtractBazelLabelList(srcsList, srcs.Value))
-			copts.SetValueForOS(os.Name, parseCopts(baseCompilerProps))
+	// After going through all archs, delete the duplicate files in the arch
+	// values that are already in the base srcs.Value.
+	for arch, props := range module.GetArchProperties(&BaseCompilerProperties{}) {
+		if _, ok := props.(*BaseCompilerProperties); ok {
+			srcs.SetValueForArch(arch.Name, bazel.SubtractBazelLabelList(srcs.GetValueForArch(arch.Name), srcs.Value))
 		}
 	}
 
-	// Combine local, non-exported hdrs into srcs
-	srcs.Append(localHdrs)
+	// Now that the srcs.Value list is finalized, compare it with the original
+	// list, and put the difference into the default condition for the arch
+	// select.
+	defaultsSrcs := bazel.SubtractBazelLabelList(baseSrcsLabelList, srcs.Value)
+	// TODO(b/186153868): handle the case with multiple variant types, e.g. when arch and os are both used.
+	srcs.SetValueForArch(bazel.CONDITIONS_DEFAULT, defaultsSrcs)
+
+	// Handle OS specific props.
+	for os, props := range module.GetTargetProperties(&BaseCompilerProperties{}) {
+		if baseCompilerProps, ok := props.(*BaseCompilerProperties); ok {
+			srcsList := parseSrcs(baseCompilerProps)
+			// TODO(b/186153868): add support for os-specific srcs and exclude_srcs
+			srcs.SetValueForOS(os.Name, bazel.SubtractBazelLabelList(srcsList, baseSrcsLabelList))
+			copts.SetValueForOS(os.Name, parseCopts(baseCompilerProps))
+		}
+	}
 
 	return compilerAttributes{
 		srcs:  srcs,
@@ -207,11 +299,6 @@
 	}
 }
 
-func bp2BuildListHeadersInDir(ctx android.TopDownMutatorContext, includeDir string) bazel.LabelList {
-	globs := bazel.GlobsInDir(includeDir, true, headerExts)
-	return android.BazelLabelForModuleSrc(ctx, globs)
-}
-
 // Relativize a list of root-relative paths with respect to the module's
 // directory.
 //
@@ -236,9 +323,8 @@
 }
 
 // bp2BuildParseExportedIncludes creates a string list attribute contains the
-// exported included directories of a module, and a label list attribute
-// containing the exported headers of a module.
-func bp2BuildParseExportedIncludes(ctx android.TopDownMutatorContext, module *Module) (bazel.StringListAttribute, bazel.LabelListAttribute) {
+// exported included directories of a module.
+func bp2BuildParseExportedIncludes(ctx android.TopDownMutatorContext, module *Module) bazel.StringListAttribute {
 	libraryDecorator := module.linker.(*libraryDecorator)
 
 	// Export_system_include_dirs and export_include_dirs are already module dir
@@ -248,14 +334,6 @@
 	includeDirs = append(includeDirs, libraryDecorator.flagExporter.Properties.Export_include_dirs...)
 	includeDirsAttribute := bazel.MakeStringListAttribute(includeDirs)
 
-	var headersAttribute bazel.LabelListAttribute
-	var headers bazel.LabelList
-	for _, includeDir := range includeDirs {
-		headers.Append(bp2BuildListHeadersInDir(ctx, includeDir))
-	}
-	headers = bazel.UniqueBazelLabelList(headers)
-	headersAttribute.Value = headers
-
 	for arch, props := range module.GetArchProperties(&FlagExporterProperties{}) {
 		if flagExporterProperties, ok := props.(*FlagExporterProperties); ok {
 			archIncludeDirs := flagExporterProperties.Export_system_include_dirs
@@ -268,20 +346,6 @@
 			if len(archIncludeDirs) > 0 {
 				includeDirsAttribute.SetValueForArch(arch.Name, archIncludeDirs)
 			}
-
-			var archHeaders bazel.LabelList
-			for _, archIncludeDir := range archIncludeDirs {
-				archHeaders.Append(bp2BuildListHeadersInDir(ctx, archIncludeDir))
-			}
-			archHeaders = bazel.UniqueBazelLabelList(archHeaders)
-
-			// To avoid duplicate headers when base headers + arch headers are combined
-			// FIXME: This doesn't take conflicts between arch and os includes into account
-			archHeaders = bazel.SubtractBazelLabelList(archHeaders, headers)
-
-			if len(archHeaders.Includes) > 0 || len(archHeaders.Excludes) > 0 {
-				headersAttribute.SetValueForArch(arch.Name, archHeaders)
-			}
 		}
 	}
 
@@ -297,22 +361,8 @@
 			if len(osIncludeDirs) > 0 {
 				includeDirsAttribute.SetValueForOS(os.Name, osIncludeDirs)
 			}
-
-			var osHeaders bazel.LabelList
-			for _, osIncludeDir := range osIncludeDirs {
-				osHeaders.Append(bp2BuildListHeadersInDir(ctx, osIncludeDir))
-			}
-			osHeaders = bazel.UniqueBazelLabelList(osHeaders)
-
-			// To avoid duplicate headers when base headers + os headers are combined
-			// FIXME: This doesn't take conflicts between arch and os includes into account
-			osHeaders = bazel.SubtractBazelLabelList(osHeaders, headers)
-
-			if len(osHeaders.Includes) > 0 || len(osHeaders.Excludes) > 0 {
-				headersAttribute.SetValueForOS(os.Name, osHeaders)
-			}
 		}
 	}
 
-	return includeDirsAttribute, headersAttribute
+	return includeDirsAttribute
 }
diff --git a/cc/fuzz.go b/cc/fuzz.go
index 5219ebc..c780b6f 100644
--- a/cc/fuzz.go
+++ b/cc/fuzz.go
@@ -221,8 +221,7 @@
 	// If the same library is present both as source and a prebuilt we must pick
 	// only one to avoid a conflict. Always prefer the source since the prebuilt
 	// probably won't be built with sanitizers enabled.
-	if prebuilt, ok := dependency.(android.PrebuiltInterface); ok &&
-		prebuilt.Prebuilt() != nil && prebuilt.Prebuilt().SourceExists() {
+	if prebuilt := android.GetEmbeddedPrebuilt(dependency); prebuilt != nil && prebuilt.SourceExists() {
 		return false
 	}
 
diff --git a/cc/library.go b/cc/library.go
index 7ea12c9..3b65d8d 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -220,13 +220,14 @@
 
 // For bp2build conversion.
 type bazelCcLibraryAttributes struct {
-	Srcs            bazel.LabelListAttribute
-	Hdrs            bazel.LabelListAttribute
-	Copts           bazel.StringListAttribute
-	Linkopts        bazel.StringListAttribute
-	Deps            bazel.LabelListAttribute
-	User_link_flags bazel.StringListAttribute
-	Includes        bazel.StringListAttribute
+	Srcs                   bazel.LabelListAttribute
+	Hdrs                   bazel.LabelListAttribute
+	Copts                  bazel.StringListAttribute
+	Linkopts               bazel.StringListAttribute
+	Deps                   bazel.LabelListAttribute
+	User_link_flags        bazel.StringListAttribute
+	Includes               bazel.StringListAttribute
+	Static_deps_for_shared bazel.LabelListAttribute
 }
 
 type bazelCcLibrary struct {
@@ -257,17 +258,23 @@
 		return
 	}
 
+	sharedAttrs := bp2BuildParseSharedProps(ctx, m)
+	staticAttrs := bp2BuildParseStaticProps(ctx, m)
 	compilerAttrs := bp2BuildParseCompilerProps(ctx, m)
 	linkerAttrs := bp2BuildParseLinkerProps(ctx, m)
-	exportedIncludes, exportedIncludesHeaders := bp2BuildParseExportedIncludes(ctx, m)
+	exportedIncludes := bp2BuildParseExportedIncludes(ctx, m)
+
+	var srcs bazel.LabelListAttribute
+	srcs.Append(compilerAttrs.srcs)
+	srcs.Append(staticAttrs.srcs)
 
 	attrs := &bazelCcLibraryAttributes{
-		Srcs:     compilerAttrs.srcs,
-		Hdrs:     exportedIncludesHeaders,
-		Copts:    compilerAttrs.copts,
-		Linkopts: linkerAttrs.linkopts,
-		Deps:     linkerAttrs.deps,
-		Includes: exportedIncludes,
+		Srcs:                   srcs,
+		Copts:                  compilerAttrs.copts,
+		Linkopts:               linkerAttrs.linkopts,
+		Deps:                   linkerAttrs.deps,
+		Static_deps_for_shared: sharedAttrs.staticDeps,
+		Includes:               exportedIncludes,
 	}
 
 	props := bazel.BazelTargetModuleProperties{
@@ -403,11 +410,18 @@
 
 func (f *flagExporter) setProvider(ctx android.ModuleContext) {
 	ctx.SetProvider(FlagExporterInfoProvider, FlagExporterInfo{
-		IncludeDirs:       android.FirstUniquePaths(f.dirs),
+		// Comes from Export_include_dirs property, and those of exported transitive deps
+		IncludeDirs: android.FirstUniquePaths(f.dirs),
+		// Comes from Export_system_include_dirs property, and those of exported transitive deps
 		SystemIncludeDirs: android.FirstUniquePaths(f.systemDirs),
-		Flags:             f.flags,
-		Deps:              f.deps,
-		GeneratedHeaders:  f.headers,
+		// Used in very few places as a one-off way of adding extra defines.
+		Flags: f.flags,
+		// Used sparingly, for extra files that need to be explicitly exported to dependers,
+		// or for phony files to minimize ninja.
+		Deps: f.deps,
+		// For exported generated headers, such as exported aidl headers, proto headers, or
+		// sysprop headers.
+		GeneratedHeaders: f.headers,
 	})
 }
 
@@ -525,6 +539,8 @@
 			Direct(outputFilePath).
 			Build(),
 	})
+
+	ctx.SetProvider(FlagExporterInfoProvider, flagExporterInfoFromCcInfo(ctx, ccInfo))
 	if i, ok := handler.module.linker.(snapshotLibraryInterface); ok {
 		// Dependencies on this library will expect collectedSnapshotHeaders to
 		// be set, otherwise validation will fail. For now, set this to an empty
@@ -2202,7 +2218,7 @@
 
 	compilerAttrs := bp2BuildParseCompilerProps(ctx, module)
 	linkerAttrs := bp2BuildParseLinkerProps(ctx, module)
-	exportedIncludes, exportedIncludesHeaders := bp2BuildParseExportedIncludes(ctx, module)
+	exportedIncludes := bp2BuildParseExportedIncludes(ctx, module)
 
 	attrs := &bazelCcLibraryStaticAttributes{
 		Copts:      compilerAttrs.copts,
@@ -2210,7 +2226,6 @@
 		Deps:       linkerAttrs.deps,
 		Linkstatic: true,
 		Includes:   exportedIncludes,
-		Hdrs:       exportedIncludesHeaders,
 	}
 
 	props := bazel.BazelTargetModuleProperties{
diff --git a/cc/library_headers.go b/cc/library_headers.go
index f2cb52b..0aba8de 100644
--- a/cc/library_headers.go
+++ b/cc/library_headers.go
@@ -142,14 +142,13 @@
 		return
 	}
 
-	exportedIncludes, exportedHdrs := bp2BuildParseExportedIncludes(ctx, module)
+	exportedIncludes := bp2BuildParseExportedIncludes(ctx, module)
 	compilerAttrs := bp2BuildParseCompilerProps(ctx, module)
 	linkerAttrs := bp2BuildParseLinkerProps(ctx, module)
 
 	attrs := &bazelCcLibraryHeadersAttributes{
 		Copts:    compilerAttrs.copts,
 		Includes: exportedIncludes,
-		Hdrs:     exportedHdrs,
 		Deps:     linkerAttrs.deps,
 	}
 
diff --git a/cc/linkable.go b/cc/linkable.go
index 338137b..40a9d8b 100644
--- a/cc/linkable.go
+++ b/cc/linkable.go
@@ -280,7 +280,7 @@
 	systemIncludes := android.PathsForBazelOut(ctx, ccInfo.SystemIncludes)
 
 	return FlagExporterInfo{
-		IncludeDirs:       includes,
-		SystemIncludeDirs: systemIncludes,
+		IncludeDirs:       android.FirstUniquePaths(includes),
+		SystemIncludeDirs: android.FirstUniquePaths(systemIncludes),
 	}
 }
diff --git a/dexpreopt/config.go b/dexpreopt/config.go
index a94e7af..7397919 100644
--- a/dexpreopt/config.go
+++ b/dexpreopt/config.go
@@ -131,7 +131,6 @@
 	ClassLoaderContexts            ClassLoaderContextMap
 
 	Archs                   []android.ArchType
-	DexPreoptImages         android.Paths
 	DexPreoptImagesDeps     []android.OutputPaths
 	DexPreoptImageLocations []string
 
@@ -276,7 +275,6 @@
 	EnforceUsesLibrariesStatusFile string
 	ClassLoaderContexts            jsonClassLoaderContextMap
 
-	DexPreoptImages     []string
 	DexPreoptImagesDeps [][]string
 
 	PreoptBootClassPathDexFiles []string
@@ -302,11 +300,10 @@
 	config.ModuleConfig.ProfileClassListing = android.OptionalPathForPath(constructPath(ctx, config.ProfileClassListing))
 	config.ModuleConfig.EnforceUsesLibrariesStatusFile = constructPath(ctx, config.EnforceUsesLibrariesStatusFile)
 	config.ModuleConfig.ClassLoaderContexts = fromJsonClassLoaderContext(ctx, config.ClassLoaderContexts)
-	config.ModuleConfig.DexPreoptImages = constructPaths(ctx, config.DexPreoptImages)
 	config.ModuleConfig.PreoptBootClassPathDexFiles = constructPaths(ctx, config.PreoptBootClassPathDexFiles)
 
 	// This needs to exist, but dependencies are already handled in Make, so we don't need to pass them through JSON.
-	config.ModuleConfig.DexPreoptImagesDeps = make([]android.OutputPaths, len(config.ModuleConfig.DexPreoptImages))
+	config.ModuleConfig.DexPreoptImagesDeps = make([]android.OutputPaths, len(config.ModuleConfig.Archs))
 
 	return config.ModuleConfig, nil
 }
@@ -328,7 +325,6 @@
 		ProfileBootListing:             config.ProfileBootListing.String(),
 		EnforceUsesLibrariesStatusFile: config.EnforceUsesLibrariesStatusFile.String(),
 		ClassLoaderContexts:            toJsonClassLoaderContext(config.ClassLoaderContexts),
-		DexPreoptImages:                config.DexPreoptImages.Strings(),
 		DexPreoptImagesDeps:            pathsListToStringLists(config.DexPreoptImagesDeps),
 		PreoptBootClassPathDexFiles:    config.PreoptBootClassPathDexFiles.Strings(),
 		ModuleConfig:                   config,
@@ -408,14 +404,14 @@
 		if parent == ctx.Module() && ctx.OtherModuleDependencyTag(child) == Dex2oatDepTag {
 			// Found the source module, or prebuilt module that has replaced the source.
 			dex2oatModule = child
-			if p, ok := child.(android.PrebuiltInterface); ok && p.Prebuilt() != nil {
+			if android.IsModulePrebuilt(child) {
 				return false // If it's the prebuilt we're done.
 			} else {
 				return true // Recurse to check if the source has a prebuilt dependency.
 			}
 		}
 		if parent == dex2oatModule && ctx.OtherModuleDependencyTag(child) == android.PrebuiltDepTag {
-			if p, ok := child.(android.PrebuiltInterface); ok && p.Prebuilt() != nil && p.Prebuilt().UsePrebuilt() {
+			if p := android.GetEmbeddedPrebuilt(child); p != nil && p.UsePrebuilt() {
 				dex2oatModule = child // Found a prebuilt that should be used.
 			}
 		}
diff --git a/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go
index 3848205..628197c 100644
--- a/dexpreopt/dexpreopt.go
+++ b/dexpreopt/dexpreopt.go
@@ -134,7 +134,8 @@
 	profileInstalledPath := module.DexLocation + ".prof"
 
 	if !module.ProfileIsTextListing {
-		rule.Command().FlagWithOutput("touch ", profilePath)
+		rule.Command().Text("rm -f").Output(profilePath)
+		rule.Command().Text("touch").Output(profilePath)
 	}
 
 	cmd := rule.Command().
@@ -174,7 +175,8 @@
 	profileInstalledPath := module.DexLocation + ".bprof"
 
 	if !module.ProfileIsTextListing {
-		rule.Command().FlagWithOutput("touch ", profilePath)
+		rule.Command().Text("rm -f").Output(profilePath)
+		rule.Command().Text("touch").Output(profilePath)
 	}
 
 	cmd := rule.Command().
diff --git a/dexpreopt/dexpreopt_test.go b/dexpreopt/dexpreopt_test.go
index cd7551c..bb4e80e 100644
--- a/dexpreopt/dexpreopt_test.go
+++ b/dexpreopt/dexpreopt_test.go
@@ -47,7 +47,6 @@
 		EnforceUsesLibraries:            false,
 		ClassLoaderContexts:             nil,
 		Archs:                           []android.ArchType{android.Arm},
-		DexPreoptImages:                 android.Paths{android.PathForTesting("system/framework/arm/boot.art")},
 		DexPreoptImagesDeps:             []android.OutputPaths{android.OutputPaths{}},
 		DexPreoptImageLocations:         []string{},
 		PreoptBootClassPathDexFiles:     nil,
diff --git a/java/bootclasspath.go b/java/bootclasspath.go
index 6ca0f75..02833ab 100644
--- a/java/bootclasspath.go
+++ b/java/bootclasspath.go
@@ -15,9 +15,8 @@
 package java
 
 import (
-	"fmt"
-
 	"android/soong/android"
+
 	"github.com/google/blueprint"
 	"github.com/google/blueprint/proptools"
 )
@@ -70,13 +69,15 @@
 // addDependencyOntoApexModulePair adds a dependency onto the specified APEX specific variant or the
 // specified module.
 //
-// If apex="platform" then this adds a dependency onto the platform variant of the module. This adds
-// dependencies onto the prebuilt and source modules with the specified name, depending on which
-// ones are available. Visiting must use isActiveModule to select the preferred module when both
-// source and prebuilt modules are available.
+// If apex="platform" or "system_ext" then this adds a dependency onto the platform variant of the
+// module. This adds dependencies onto the prebuilt and source modules with the specified name,
+// depending on which ones are available. Visiting must use isActiveModule to select the preferred
+// module when both source and prebuilt modules are available.
+//
+// Use gatherApexModulePairDepsWithTag to retrieve the dependencies.
 func addDependencyOntoApexModulePair(ctx android.BottomUpMutatorContext, apex string, name string, tag blueprint.DependencyTag) {
 	var variations []blueprint.Variation
-	if apex != "platform" {
+	if apex != "platform" && apex != "system_ext" {
 		// Pick the correct apex variant.
 		variations = []blueprint.Variation{
 			{Mutator: "apex", Variation: apex},
@@ -116,15 +117,20 @@
 // reportMissingVariationDependency intentionally adds a dependency on a missing variation in order
 // to generate an appropriate error message with information about the available variations.
 func reportMissingVariationDependency(ctx android.BottomUpMutatorContext, variations []blueprint.Variation, name string) {
-	modules := ctx.AddFarVariationDependencies(variations, nil, name)
-	if len(modules) != 1 {
-		panic(fmt.Errorf("Internal Error: expected one module, found %d", len(modules)))
-		return
-	}
-	if modules[0] != nil {
-		panic(fmt.Errorf("Internal Error: expected module to be missing but was found: %q", modules[0]))
-		return
-	}
+	ctx.AddFarVariationDependencies(variations, nil, name)
+}
+
+// gatherApexModulePairDepsWithTag returns the list of dependencies with the supplied tag that was
+// added by addDependencyOntoApexModulePair.
+func gatherApexModulePairDepsWithTag(ctx android.BaseModuleContext, tag blueprint.DependencyTag) []android.Module {
+	var modules []android.Module
+	ctx.VisitDirectDepsIf(isActiveModule, func(module android.Module) {
+		t := ctx.OtherModuleDependencyTag(module)
+		if t == tag {
+			modules = append(modules, module)
+		}
+	})
+	return modules
 }
 
 // ApexVariantReference specifies a particular apex variant of a module.
@@ -133,6 +139,9 @@
 	//
 	// If this is not specified then it defaults to "platform" which will cause a dependency to be
 	// added to the module's platform variant.
+	//
+	// A value of system_ext should be used for any module that will be part of the system_ext
+	// partition.
 	Apex *string
 
 	// The name of the module.
@@ -170,3 +179,59 @@
 
 // The tag used for dependencies onto bootclasspath_fragments.
 var bootclasspathFragmentDepTag = bootclasspathDependencyTag{name: "fragment"}
+
+// BootclasspathNestedAPIProperties defines properties related to the API provided by parts of the
+// bootclasspath that are nested within the main BootclasspathAPIProperties.
+type BootclasspathNestedAPIProperties struct {
+	// java_library or preferably, java_sdk_library modules providing stub classes that define the
+	// APIs provided by this bootclasspath_fragment.
+	Stub_libs []string
+}
+
+// BootclasspathAPIProperties defines properties for defining the API provided by parts of the
+// bootclasspath.
+type BootclasspathAPIProperties struct {
+	// Api properties provide information about the APIs provided by the bootclasspath_fragment.
+	// Properties in this section apply to public, system and test api scopes. They DO NOT apply to
+	// core_platform as that is a special, ART specific scope, that does not follow the pattern and so
+	// has its own section. It is in the process of being deprecated and replaced by the system scope
+	// but this will remain for the foreseeable future to maintain backwards compatibility.
+	//
+	// Every bootclasspath_fragment must specify at least one stubs_lib in this section and must
+	// specify stubs for all the APIs provided by its contents. Failure to do so will lead to those
+	// methods being inaccessible to other parts of Android, including but not limited to
+	// applications.
+	Api BootclasspathNestedAPIProperties
+
+	// Properties related to the core platform API surface.
+	//
+	// This must only be used by the following modules:
+	// * ART
+	// * Conscrypt
+	// * I18N
+	//
+	// The bootclasspath_fragments for each of the above modules must specify at least one stubs_lib
+	// and must specify stubs for all the APIs provided by its contents. Failure to do so will lead to
+	// those methods being inaccessible to the other modules in the list.
+	Core_platform_api BootclasspathNestedAPIProperties
+}
+
+// sdkKindToStubLibs calculates the stub library modules for each relevant android.SdkKind from the
+// Stub_libs properties.
+func (p BootclasspathAPIProperties) sdkKindToStubLibs() map[android.SdkKind][]string {
+	m := map[android.SdkKind][]string{}
+	for _, kind := range []android.SdkKind{android.SdkPublic, android.SdkSystem, android.SdkTest} {
+		m[kind] = p.Api.Stub_libs
+	}
+	m[android.SdkCorePlatform] = p.Core_platform_api.Stub_libs
+	return m
+}
+
+// bootclasspathApiInfo contains paths resolved from BootclasspathAPIProperties
+type bootclasspathApiInfo struct {
+	// stubJarsByKind maps from the android.SdkKind to the paths containing dex stub jars for each
+	// kind.
+	stubJarsByKind map[android.SdkKind]android.Paths
+}
+
+var bootclasspathApiInfoProvider = blueprint.NewProvider(bootclasspathApiInfo{})
diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go
index 2e33c06..d7525ec 100644
--- a/java/bootclasspath_fragment.go
+++ b/java/bootclasspath_fragment.go
@@ -63,7 +63,7 @@
 
 // SdkMemberType causes dependencies added with this tag to be automatically added to the sdk as if
 // they were specified using java_boot_libs.
-func (b bootclasspathFragmentContentDependencyTag) SdkMemberType() android.SdkMemberType {
+func (b bootclasspathFragmentContentDependencyTag) SdkMemberType(_ android.Module) android.SdkMemberType {
 	return javaBootLibsSdkMemberType
 }
 
@@ -88,6 +88,9 @@
 	//
 	// The order of this list matters as it is the order that is used in the bootclasspath.
 	Contents []string
+
+	// The properties for specifying the API stubs provided by this fragment.
+	BootclasspathAPIProperties
 }
 
 type bootclasspathFragmentProperties struct {
@@ -150,7 +153,7 @@
 	imageName := proptools.String(m.properties.Image_name)
 	if imageName == "art" {
 		// TODO(b/177892522): Prebuilts (versioned or not) should not use the image_name property.
-		if m.MemberName() != "" {
+		if android.IsModuleInVersionedSdk(m) {
 			// The module is a versioned prebuilt so ignore it. This is done for a couple of reasons:
 			// 1. There is no way to use this at the moment so ignoring it is safe.
 			// 2. Attempting to initialize the contents property from the configuration will end up having
@@ -205,7 +208,7 @@
 	imageName := proptools.String(b.properties.Image_name)
 	if imageName == "art" {
 		// TODO(b/177892522): Prebuilts (versioned or not) should not use the image_name property.
-		if b.MemberName() != "" {
+		if android.IsModuleInVersionedSdk(b) {
 			// The module is a versioned prebuilt so ignore it. This is done for a couple of reasons:
 			// 1. There is no way to use this at the moment so ignoring it is safe.
 			// 2. Attempting to initialize the contents property from the configuration will end up having
@@ -316,6 +319,9 @@
 }
 
 func (b *BootclasspathFragmentModule) DepsMutator(ctx android.BottomUpMutatorContext) {
+	// Add dependencies onto all the modules that provide the API stubs for classes on this
+	// bootclasspath fragment.
+	hiddenAPIAddStubLibDependencies(ctx, b.properties.sdkKindToStubLibs())
 
 	if SkipDexpreoptBootJars(ctx) {
 		return
@@ -384,6 +390,13 @@
 
 	// Store the information for use by platform_bootclasspath.
 	ctx.SetProvider(hiddenAPIFlagFileInfoProvider, flagFileInfo)
+
+	// Convert the kind specific lists of modules into kind specific lists of jars.
+	stubJarsByKind := hiddenAPIGatherStubLibDexJarPaths(ctx)
+
+	// Store the information for use by other modules.
+	bootclasspathApiInfo := bootclasspathApiInfo{stubJarsByKind: stubJarsByKind}
+	ctx.SetProvider(bootclasspathApiInfoProvider, bootclasspathApiInfo)
 }
 
 type bootclasspathFragmentMemberType struct {
@@ -420,6 +433,10 @@
 	// Contents of the bootclasspath fragment
 	Contents []string
 
+	// Stub_libs properties.
+	Stub_libs               []string
+	Core_platform_stub_libs []string
+
 	// Flag files by *hiddenAPIFlagFileCategory
 	Flag_files_by_category map[*hiddenAPIFlagFileCategory]android.Paths
 }
@@ -434,6 +451,10 @@
 	mctx := ctx.SdkModuleContext()
 	flagFileInfo := mctx.OtherModuleProvider(module, hiddenAPIFlagFileInfoProvider).(hiddenAPIFlagFileInfo)
 	b.Flag_files_by_category = flagFileInfo.categoryToPaths
+
+	// Copy stub_libs properties.
+	b.Stub_libs = module.properties.Api.Stub_libs
+	b.Core_platform_stub_libs = module.properties.Core_platform_api.Stub_libs
 }
 
 func (b *bootclasspathFragmentSdkMemberProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) {
@@ -441,11 +462,22 @@
 		propertySet.AddProperty("image_name", *b.Image_name)
 	}
 
+	builder := ctx.SnapshotBuilder()
+	requiredMemberDependency := builder.SdkMemberReferencePropertyTag(true)
+
 	if len(b.Contents) > 0 {
-		propertySet.AddPropertyWithTag("contents", b.Contents, ctx.SnapshotBuilder().SdkMemberReferencePropertyTag(true))
+		propertySet.AddPropertyWithTag("contents", b.Contents, requiredMemberDependency)
 	}
 
-	builder := ctx.SnapshotBuilder()
+	if len(b.Stub_libs) > 0 {
+		apiPropertySet := propertySet.AddPropertySet("api")
+		apiPropertySet.AddPropertyWithTag("stub_libs", b.Stub_libs, requiredMemberDependency)
+	}
+	if len(b.Core_platform_stub_libs) > 0 {
+		corePlatformApiPropertySet := propertySet.AddPropertySet("core_platform_api")
+		corePlatformApiPropertySet.AddPropertyWithTag("stub_libs", b.Core_platform_stub_libs, requiredMemberDependency)
+	}
+
 	if b.Flag_files_by_category != nil {
 		hiddenAPISet := propertySet.AddPropertySet("hidden_api")
 		for _, category := range hiddenAPIFlagFileCategories {
diff --git a/java/bootclasspath_fragment_test.go b/java/bootclasspath_fragment_test.go
index 0419a46..32ed7ea 100644
--- a/java/bootclasspath_fragment_test.go
+++ b/java/bootclasspath_fragment_test.go
@@ -125,10 +125,20 @@
 			contents: [
 				"mybootlib",
 			],
+			api: {
+				stub_libs: [
+					"mysdklibrary",
+				],
+			},
 			coverage: {
 				contents: [
 					"coveragelib",
 				],
+				api: {
+					stub_libs: [
+						"mycoveragestubs",
+					],
+				},
 			},
 		}
 
@@ -147,6 +157,21 @@
 			sdk_version: "none",
 			compile_dex: true,
 		}
+
+		java_sdk_library {
+			name: "mysdklibrary",
+			srcs: ["Test.java"],
+			compile_dex: true,
+			public: {enabled: true},
+			system: {enabled: true},
+		}
+
+		java_sdk_library {
+			name: "mycoveragestubs",
+			srcs: ["Test.java"],
+			compile_dex: true,
+			public: {enabled: true},
+		}
 	`)
 
 	checkContents := func(t *testing.T, result *android.TestResult, expected ...string) {
@@ -154,20 +179,88 @@
 		android.AssertArrayString(t, "contents property", expected, module.properties.Contents)
 	}
 
+	preparer := android.GroupFixturePreparers(
+		prepareForTestWithBootclasspathFragment,
+		PrepareForTestWithJavaSdkLibraryFiles,
+		FixtureWithLastReleaseApis("mysdklibrary", "mycoveragestubs"),
+		prepareWithBp,
+	)
+
 	t.Run("without coverage", func(t *testing.T) {
-		result := android.GroupFixturePreparers(
-			prepareForTestWithBootclasspathFragment,
-			prepareWithBp,
-		).RunTest(t)
+		result := preparer.RunTest(t)
 		checkContents(t, result, "mybootlib")
 	})
 
 	t.Run("with coverage", func(t *testing.T) {
 		result := android.GroupFixturePreparers(
-			prepareForTestWithBootclasspathFragment,
 			prepareForTestWithFrameworkCoverage,
-			prepareWithBp,
+			preparer,
 		).RunTest(t)
 		checkContents(t, result, "mybootlib", "coveragelib")
 	})
 }
+
+func TestBootclasspathFragment_StubLibs(t *testing.T) {
+	result := android.GroupFixturePreparers(
+		prepareForTestWithBootclasspathFragment,
+		PrepareForTestWithJavaSdkLibraryFiles,
+		FixtureWithLastReleaseApis("mysdklibrary", "mycoreplatform"),
+	).RunTestWithBp(t, `
+		bootclasspath_fragment {
+			name: "myfragment",
+			contents: ["mysdklibrary"],
+			api: {
+				stub_libs: [
+					"mystublib",
+					"mysdklibrary",
+				],
+			},
+			core_platform_api: {
+				stub_libs: ["mycoreplatform"],
+			},
+		}
+
+		java_library {
+			name: "mystublib",
+			srcs: ["Test.java"],
+			system_modules: "none",
+			sdk_version: "none",
+			compile_dex: true,
+		}
+
+		java_sdk_library {
+			name: "mysdklibrary",
+			srcs: ["a.java"],
+			compile_dex: true,
+			public: {enabled: true},
+			system: {enabled: true},
+		}
+
+		java_sdk_library {
+			name: "mycoreplatform",
+			srcs: ["a.java"],
+			compile_dex: true,
+			public: {enabled: true},
+		}
+	`)
+
+	fragment := result.Module("myfragment", "android_common")
+	info := result.ModuleProvider(fragment, bootclasspathApiInfoProvider).(bootclasspathApiInfo)
+
+	stubsJar := "out/soong/.intermediates/mystublib/android_common/dex/mystublib.jar"
+
+	// Check that SdkPublic uses public stubs.
+	publicStubsJar := "out/soong/.intermediates/mysdklibrary.stubs/android_common/dex/mysdklibrary.stubs.jar"
+	android.AssertPathsRelativeToTopEquals(t, "public dex stubs jar", []string{stubsJar, publicStubsJar}, info.stubJarsByKind[android.SdkPublic])
+
+	// Check that SdkSystem uses system stubs.
+	systemStubsJar := "out/soong/.intermediates/mysdklibrary.stubs.system/android_common/dex/mysdklibrary.stubs.system.jar"
+	android.AssertPathsRelativeToTopEquals(t, "system dex stubs jar", []string{stubsJar, systemStubsJar}, info.stubJarsByKind[android.SdkSystem])
+
+	// Check that SdkTest also uses system stubs as the mysdklibrary does not provide test stubs.
+	android.AssertPathsRelativeToTopEquals(t, "test dex stubs jar", []string{stubsJar, systemStubsJar}, info.stubJarsByKind[android.SdkTest])
+
+	// Check that SdkCorePlatform uses public stubs from the mycoreplatform library.
+	corePlatformStubsJar := "out/soong/.intermediates/mycoreplatform.stubs/android_common/dex/mycoreplatform.stubs.jar"
+	android.AssertPathsRelativeToTopEquals(t, "core platform dex stubs jar", []string{corePlatformStubsJar}, info.stubJarsByKind[android.SdkCorePlatform])
+}
diff --git a/java/dexpreopt.go b/java/dexpreopt.go
index d00d74b..0020a2d 100644
--- a/java/dexpreopt.go
+++ b/java/dexpreopt.go
@@ -225,7 +225,6 @@
 		ClassLoaderContexts:            d.classLoaderContexts,
 
 		Archs:                   archs,
-		DexPreoptImages:         images,
 		DexPreoptImagesDeps:     imagesDeps,
 		DexPreoptImageLocations: imageLocations,
 
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index f85e1c9..8c6c9e3 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -423,25 +423,33 @@
 	writeGlobalConfigForMake(ctx, d.dexpreoptConfigForMake)
 
 	global := dexpreopt.GetGlobalConfig(ctx)
+	if !shouldBuildBootImages(ctx.Config(), global) {
+		return
+	}
 
+	// Generate the profile rule from the default boot image.
+	defaultImageConfig := defaultBootImageConfig(ctx)
+	profile := bootImageProfileRule(ctx, defaultImageConfig)
+
+	// Create the default boot image.
+	d.defaultBootImage = buildBootImage(ctx, defaultImageConfig, profile)
+
+	// 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), profile))
+
+	copyUpdatableBootJars(ctx)
+}
+
+// shouldBuildBootImages determines whether boot images should be built.
+func shouldBuildBootImages(config android.Config, global *dexpreopt.GlobalConfig) bool {
 	// Skip recompiling the boot image for the second sanitization phase. We'll get separate paths
 	// and invalidate first-stage artifacts which are crucial to SANITIZE_LITE builds.
 	// Note: this is technically incorrect. Compiled code contains stack checks which may depend
 	//       on ASAN settings.
-	if len(ctx.Config().SanitizeDevice()) == 1 &&
-		ctx.Config().SanitizeDevice()[0] == "address" &&
-		global.SanitizeLite {
-		return
+	if len(config.SanitizeDevice()) == 1 && config.SanitizeDevice()[0] == "address" && global.SanitizeLite {
+		return false
 	}
-
-	// 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)))
-
-	copyUpdatableBootJars(ctx)
-
-	dumpOatRules(ctx, d.defaultBootImage)
+	return true
 }
 
 // Inspect this module to see if it contains a bootclasspath dex jar.
@@ -549,7 +557,7 @@
 // Generate commands that will copy boot jars to predefined paths in the global config.
 func findAndCopyBootJars(ctx android.SingletonContext, bootjars android.ConfiguredJarList,
 	jarPathsPredefined android.WritablePaths,
-	getBootJar func(module android.Module) (int, android.Path)) []string {
+	getBootJar func(module android.Module) (int, android.Path)) {
 
 	// This logic is tested in the apex package to avoid import cycle apex <-> java.
 	jarPaths := make(android.Paths, bootjars.Len())
@@ -568,51 +576,52 @@
 		}
 	})
 
-	var missingDeps []string
-	// Ensure all modules were converted to paths
-	for i := range jarPaths {
-		if jarPaths[i] == nil {
-			m := bootjars.Jar(i)
-			if ctx.Config().AllowMissingDependencies() {
-				missingDeps = append(missingDeps, m)
-				jarPaths[i] = android.PathForOutput(ctx, "missing/module", m, "from/apex",
-					bootjars.Apex(i))
-			} else {
-				ctx.Errorf("failed to find a dex jar path for module '%s'"+
-					", note that some jars may be filtered out by module constraints", m)
-			}
-		}
-	}
-
 	// The paths to bootclasspath DEX files need to be known at module GenerateAndroidBuildAction
 	// time, before the boot images are built (these paths are used in dexpreopt rule generation for
 	// Java libraries and apps). Generate rules that copy bootclasspath DEX jars to the predefined
 	// paths.
 	for i := range jarPaths {
-		ctx.Build(pctx, android.BuildParams{
-			Rule:   android.Cp,
-			Input:  jarPaths[i],
-			Output: jarPathsPredefined[i],
-		})
-	}
+		input := jarPaths[i]
+		output := jarPathsPredefined[i]
+		module := bootjars.Jar(i)
+		if input == nil {
+			if ctx.Config().AllowMissingDependencies() {
+				apex := bootjars.Apex(i)
 
-	return missingDeps
+				// Create an error rule that pretends to create the output file but will actually fail if it
+				// is run.
+				ctx.Build(pctx, android.BuildParams{
+					Rule:   android.ErrorRule,
+					Output: output,
+					Args: map[string]string{
+						"error": fmt.Sprintf("missing dependencies: dex jar for %s:%s", module, apex),
+					},
+				})
+			} else {
+				ctx.Errorf("failed to find a dex jar path for module '%s'"+
+					", note that some jars may be filtered out by module constraints", module)
+			}
+
+		} else {
+			ctx.Build(pctx, android.BuildParams{
+				Rule:   android.Cp,
+				Input:  input,
+				Output: output,
+			})
+		}
+	}
 }
 
 // buildBootImage takes a bootImageConfig, creates rules to build it, and returns the image.
-func buildBootImage(ctx android.SingletonContext, image *bootImageConfig) *bootImageConfig {
+func buildBootImage(ctx android.SingletonContext, image *bootImageConfig, profile android.WritablePath) *bootImageConfig {
 	getBootJarFunc := func(module android.Module) (int, android.Path) {
 		return getBootImageJar(ctx, image, module)
 	}
-	missingDeps := findAndCopyBootJars(ctx, image.modules, image.dexPaths, getBootJarFunc)
-
-	profile := bootImageProfileRule(ctx, image, missingDeps)
-	bootFrameworkProfileRule(ctx, image, missingDeps)
-	updatableBcpPackagesRule(ctx, image, missingDeps)
+	findAndCopyBootJars(ctx, image.modules, image.dexPaths, getBootJarFunc)
 
 	var zipFiles android.Paths
 	for _, variant := range image.variants {
-		files := buildBootImageVariant(ctx, variant, profile, missingDeps)
+		files := buildBootImageVariant(ctx, variant, profile)
 		if variant.target.Os == android.Android {
 			zipFiles = append(zipFiles, files.Paths()...)
 		}
@@ -639,17 +648,11 @@
 		index, jar, _ := getBootJar(ctx, config.modules, module, "configured in updatable boot jars ")
 		return index, jar
 	}
-	missingDeps := findAndCopyBootJars(ctx, config.modules, config.dexPaths, getBootJarFunc)
-	// Ignoring missing dependencies here. Ideally they should be added to the dexpreopt rule, but
-	// that is not possible as this rule is created after dexpreopt rules (it's in a singleton
-	// context, and they are in a module context). The true fix is to add dependencies from the
-	// dexpreopted modules on updatable boot jars and avoid this copying altogether.
-	_ = missingDeps
+	findAndCopyBootJars(ctx, config.modules, config.dexPaths, getBootJarFunc)
 }
 
 // Generate boot image build rules for a specific target.
-func buildBootImageVariant(ctx android.SingletonContext, image *bootImageVariant,
-	profile android.Path, missingDeps []string) android.WritablePaths {
+func buildBootImageVariant(ctx android.SingletonContext, image *bootImageVariant, profile android.Path) android.WritablePaths {
 
 	globalSoong := dexpreopt.GetCachedGlobalSoongConfig(ctx)
 	global := dexpreopt.GetGlobalConfig(ctx)
@@ -664,7 +667,6 @@
 	imagePath := outputPath.ReplaceExtension(ctx, "art")
 
 	rule := android.NewRuleBuilder(pctx, ctx)
-	rule.MissingDeps(missingDeps)
 
 	rule.Command().Text("mkdir").Flag("-p").Flag(symbolsDir.String())
 	rule.Command().Text("rm").Flag("-f").
@@ -800,160 +802,121 @@
 It is likely that the boot classpath is inconsistent.
 Rebuild with ART_BOOT_IMAGE_EXTRA_ARGS="--runtime-arg -verbose:verifier" to see verification errors.`
 
-func bootImageProfileRule(ctx android.SingletonContext, image *bootImageConfig, missingDeps []string) android.WritablePath {
+func bootImageProfileRule(ctx android.SingletonContext, image *bootImageConfig) android.WritablePath {
 	globalSoong := dexpreopt.GetCachedGlobalSoongConfig(ctx)
 	global := dexpreopt.GetGlobalConfig(ctx)
 
 	if global.DisableGenerateProfile {
 		return nil
 	}
-	profile := ctx.Config().Once(bootImageProfileRuleKey, func() interface{} {
-		defaultProfile := "frameworks/base/config/boot-image-profile.txt"
 
-		rule := android.NewRuleBuilder(pctx, ctx)
-		rule.MissingDeps(missingDeps)
+	defaultProfile := "frameworks/base/config/boot-image-profile.txt"
 
-		var bootImageProfile android.Path
-		if len(global.BootImageProfiles) > 1 {
-			combinedBootImageProfile := image.dir.Join(ctx, "boot-image-profile.txt")
-			rule.Command().Text("cat").Inputs(global.BootImageProfiles).Text(">").Output(combinedBootImageProfile)
-			bootImageProfile = combinedBootImageProfile
-		} else if len(global.BootImageProfiles) == 1 {
-			bootImageProfile = global.BootImageProfiles[0]
-		} else if path := android.ExistentPathForSource(ctx, defaultProfile); path.Valid() {
-			bootImageProfile = path.Path()
-		} else {
-			// No profile (not even a default one, which is the case on some branches
-			// like master-art-host that don't have frameworks/base).
-			// Return nil and continue without profile.
-			return nil
-		}
+	rule := android.NewRuleBuilder(pctx, ctx)
 
-		profile := image.dir.Join(ctx, "boot.prof")
-
-		rule.Command().
-			Text(`ANDROID_LOG_TAGS="*:e"`).
-			Tool(globalSoong.Profman).
-			Flag("--output-profile-type=boot").
-			FlagWithInput("--create-profile-from=", bootImageProfile).
-			FlagForEachInput("--apk=", image.dexPathsDeps.Paths()).
-			FlagForEachArg("--dex-location=", image.getAnyAndroidVariant().dexLocationsDeps).
-			FlagWithOutput("--reference-profile-file=", profile)
-
-		rule.Install(profile, "/system/etc/boot-image.prof")
-
-		rule.Build("bootJarsProfile", "profile boot jars")
-
-		image.profileInstalls = rule.Installs()
-
-		return profile
-	})
-	if profile == nil {
-		return nil // wrap nil into a typed pointer with value nil
+	var bootImageProfile android.Path
+	if len(global.BootImageProfiles) > 1 {
+		combinedBootImageProfile := image.dir.Join(ctx, "boot-image-profile.txt")
+		rule.Command().Text("cat").Inputs(global.BootImageProfiles).Text(">").Output(combinedBootImageProfile)
+		bootImageProfile = combinedBootImageProfile
+	} else if len(global.BootImageProfiles) == 1 {
+		bootImageProfile = global.BootImageProfiles[0]
+	} else if path := android.ExistentPathForSource(ctx, defaultProfile); path.Valid() {
+		bootImageProfile = path.Path()
+	} else {
+		// No profile (not even a default one, which is the case on some branches
+		// like master-art-host that don't have frameworks/base).
+		// Return nil and continue without profile.
+		return nil
 	}
-	return profile.(android.WritablePath)
+
+	profile := image.dir.Join(ctx, "boot.prof")
+
+	rule.Command().
+		Text(`ANDROID_LOG_TAGS="*:e"`).
+		Tool(globalSoong.Profman).
+		Flag("--output-profile-type=boot").
+		FlagWithInput("--create-profile-from=", bootImageProfile).
+		FlagForEachInput("--apk=", image.dexPathsDeps.Paths()).
+		FlagForEachArg("--dex-location=", image.getAnyAndroidVariant().dexLocationsDeps).
+		FlagWithOutput("--reference-profile-file=", profile)
+
+	rule.Install(profile, "/system/etc/boot-image.prof")
+
+	rule.Build("bootJarsProfile", "profile boot jars")
+
+	image.profileInstalls = rule.Installs()
+
+	return profile
 }
 
-var bootImageProfileRuleKey = android.NewOnceKey("bootImageProfileRule")
-
-func bootFrameworkProfileRule(ctx android.SingletonContext, image *bootImageConfig, missingDeps []string) android.WritablePath {
-	globalSoong := dexpreopt.GetCachedGlobalSoongConfig(ctx)
+// bootFrameworkProfileRule generates the rule to create the boot framework profile and
+// returns a path to the generated file.
+func bootFrameworkProfileRule(ctx android.ModuleContext, image *bootImageConfig) android.WritablePath {
+	globalSoong := dexpreopt.GetGlobalSoongConfig(ctx)
 	global := dexpreopt.GetGlobalConfig(ctx)
 
 	if global.DisableGenerateProfile || ctx.Config().UnbundledBuild() {
 		return nil
 	}
-	return ctx.Config().Once(bootFrameworkProfileRuleKey, func() interface{} {
-		rule := android.NewRuleBuilder(pctx, ctx)
-		rule.MissingDeps(missingDeps)
 
-		// Some branches like master-art-host don't have frameworks/base, so manually
-		// handle the case that the default is missing.  Those branches won't attempt to build the profile rule,
-		// and if they do they'll get a missing deps error.
-		defaultProfile := "frameworks/base/config/boot-profile.txt"
-		path := android.ExistentPathForSource(ctx, defaultProfile)
-		var bootFrameworkProfile android.Path
-		if path.Valid() {
-			bootFrameworkProfile = path.Path()
-		} else {
-			missingDeps = append(missingDeps, defaultProfile)
-			bootFrameworkProfile = android.PathForOutput(ctx, "missing", defaultProfile)
-		}
+	defaultProfile := "frameworks/base/config/boot-profile.txt"
+	bootFrameworkProfile := android.PathForSource(ctx, defaultProfile)
 
-		profile := image.dir.Join(ctx, "boot.bprof")
+	profile := image.dir.Join(ctx, "boot.bprof")
 
-		rule.Command().
-			Text(`ANDROID_LOG_TAGS="*:e"`).
-			Tool(globalSoong.Profman).
-			Flag("--output-profile-type=bprof").
-			FlagWithInput("--create-profile-from=", bootFrameworkProfile).
-			FlagForEachInput("--apk=", image.dexPathsDeps.Paths()).
-			FlagForEachArg("--dex-location=", image.getAnyAndroidVariant().dexLocationsDeps).
-			FlagWithOutput("--reference-profile-file=", profile)
+	rule := android.NewRuleBuilder(pctx, ctx)
+	rule.Command().
+		Text(`ANDROID_LOG_TAGS="*:e"`).
+		Tool(globalSoong.Profman).
+		Flag("--output-profile-type=bprof").
+		FlagWithInput("--create-profile-from=", bootFrameworkProfile).
+		FlagForEachInput("--apk=", image.dexPathsDeps.Paths()).
+		FlagForEachArg("--dex-location=", image.getAnyAndroidVariant().dexLocationsDeps).
+		FlagWithOutput("--reference-profile-file=", profile)
 
-		rule.Install(profile, "/system/etc/boot-image.bprof")
-		rule.Build("bootFrameworkProfile", "profile boot framework jars")
-		image.profileInstalls = append(image.profileInstalls, rule.Installs()...)
+	rule.Install(profile, "/system/etc/boot-image.bprof")
+	rule.Build("bootFrameworkProfile", "profile boot framework jars")
+	image.profileInstalls = append(image.profileInstalls, rule.Installs()...)
 
-		return profile
-	}).(android.WritablePath)
+	return profile
 }
 
-var bootFrameworkProfileRuleKey = android.NewOnceKey("bootFrameworkProfileRule")
-
-func updatableBcpPackagesRule(ctx android.SingletonContext, image *bootImageConfig, missingDeps []string) android.WritablePath {
-	if ctx.Config().UnbundledBuild() {
-		return nil
+// generateUpdatableBcpPackagesRule generates the rule to create the updatable-bcp-packages.txt file
+// and returns a path to the generated file.
+func generateUpdatableBcpPackagesRule(ctx android.ModuleContext, image *bootImageConfig, updatableModules []android.Module) android.WritablePath {
+	// Collect `permitted_packages` for updatable boot jars.
+	var updatablePackages []string
+	for _, module := range updatableModules {
+		if j, ok := module.(PermittedPackagesForUpdatableBootJars); ok {
+			pp := j.PermittedPackagesForUpdatableBootJars()
+			if len(pp) > 0 {
+				updatablePackages = append(updatablePackages, pp...)
+			} else {
+				ctx.ModuleErrorf("Missing permitted_packages")
+			}
+		}
 	}
 
-	return ctx.Config().Once(updatableBcpPackagesRuleKey, func() interface{} {
-		global := dexpreopt.GetGlobalConfig(ctx)
-		updatableModules := global.UpdatableBootJars.CopyOfJars()
+	// Sort updatable packages to ensure deterministic ordering.
+	sort.Strings(updatablePackages)
 
-		// Collect `permitted_packages` for updatable boot jars.
-		var updatablePackages []string
-		ctx.VisitAllModules(func(module android.Module) {
-			if !isActiveModule(module) {
-				return
-			}
-			if j, ok := module.(PermittedPackagesForUpdatableBootJars); ok {
-				name := ctx.ModuleName(module)
-				if i := android.IndexList(name, updatableModules); i != -1 {
-					pp := j.PermittedPackagesForUpdatableBootJars()
-					if len(pp) > 0 {
-						updatablePackages = append(updatablePackages, pp...)
-					} else {
-						ctx.Errorf("Missing permitted_packages for %s", name)
-					}
-					// Do not match the same library repeatedly.
-					updatableModules = append(updatableModules[:i], updatableModules[i+1:]...)
-				}
-			}
-		})
+	updatableBcpPackagesName := "updatable-bcp-packages.txt"
+	updatableBcpPackages := image.dir.Join(ctx, updatableBcpPackagesName)
 
-		// Sort updatable packages to ensure deterministic ordering.
-		sort.Strings(updatablePackages)
+	// WriteFileRule automatically adds the last end-of-line.
+	android.WriteFileRule(ctx, updatableBcpPackages, strings.Join(updatablePackages, "\n"))
 
-		updatableBcpPackagesName := "updatable-bcp-packages.txt"
-		updatableBcpPackages := image.dir.Join(ctx, updatableBcpPackagesName)
+	rule := android.NewRuleBuilder(pctx, ctx)
+	rule.Install(updatableBcpPackages, "/system/etc/"+updatableBcpPackagesName)
+	// TODO: Rename `profileInstalls` to `extraInstalls`?
+	// Maybe even move the field out of the bootImageConfig into some higher level type?
+	image.profileInstalls = append(image.profileInstalls, rule.Installs()...)
 
-		// WriteFileRule automatically adds the last end-of-line.
-		android.WriteFileRule(ctx, updatableBcpPackages, strings.Join(updatablePackages, "\n"))
-
-		rule := android.NewRuleBuilder(pctx, ctx)
-		rule.MissingDeps(missingDeps)
-		rule.Install(updatableBcpPackages, "/system/etc/"+updatableBcpPackagesName)
-		// TODO: Rename `profileInstalls` to `extraInstalls`?
-		// Maybe even move the field out of the bootImageConfig into some higher level type?
-		image.profileInstalls = append(image.profileInstalls, rule.Installs()...)
-
-		return updatableBcpPackages
-	}).(android.WritablePath)
+	return updatableBcpPackages
 }
 
-var updatableBcpPackagesRuleKey = android.NewOnceKey("updatableBcpPackagesRule")
-
-func dumpOatRules(ctx android.SingletonContext, image *bootImageConfig) {
+func dumpOatRules(ctx android.ModuleContext, image *bootImageConfig) {
 	var allPhonies android.Paths
 	for _, image := range image.variants {
 		arch := image.target.Arch.ArchType
@@ -994,7 +957,6 @@
 		Inputs:      allPhonies,
 		Description: "dump-oat-boot",
 	})
-
 }
 
 func writeGlobalConfigForMake(ctx android.SingletonContext, path android.WritablePath) {
diff --git a/java/hiddenapi_modular.go b/java/hiddenapi_modular.go
index 8cc6f8f..335f5b8 100644
--- a/java/hiddenapi_modular.go
+++ b/java/hiddenapi_modular.go
@@ -33,6 +33,21 @@
 	return false
 }
 
+func (b hiddenAPIStubsDependencyTag) SdkMemberType(child android.Module) android.SdkMemberType {
+	// If the module is a java_sdk_library then treat it as if it was specific in the java_sdk_libs
+	// property, otherwise treat if it was specified in the java_header_libs property.
+	if javaSdkLibrarySdkMemberType.IsInstance(child) {
+		return javaSdkLibrarySdkMemberType
+	}
+
+	return javaHeaderLibsSdkMemberType
+}
+
+func (b hiddenAPIStubsDependencyTag) ExportMember() bool {
+	// Export the module added via this dependency tag from the sdk.
+	return true
+}
+
 // Avoid having to make stubs content explicitly visible to dependent modules.
 //
 // This is a temporary workaround to make it easier to migrate to bootclasspath_fragment modules
@@ -44,6 +59,7 @@
 var _ android.ExcludeFromVisibilityEnforcementTag = hiddenAPIStubsDependencyTag{}
 var _ android.ReplaceSourceWithPrebuilt = hiddenAPIStubsDependencyTag{}
 var _ android.ExcludeFromApexContentsTag = hiddenAPIStubsDependencyTag{}
+var _ android.SdkMemberTypeDependencyTag = hiddenAPIStubsDependencyTag{}
 
 // hiddenAPIRelevantSdkKinds lists all the android.SdkKind instances that are needed by the hidden
 // API processing.
@@ -111,7 +127,7 @@
 		tag := ctx.OtherModuleDependencyTag(module)
 		if hiddenAPIStubsTag, ok := tag.(hiddenAPIStubsDependencyTag); ok {
 			kind := hiddenAPIStubsTag.sdkKind
-			dexJar := hiddenAPIRetrieveDexJarBuildPath(ctx, module)
+			dexJar := hiddenAPIRetrieveDexJarBuildPath(ctx, module, kind)
 			if dexJar != nil {
 				m[kind] = append(m[kind], dexJar)
 			}
@@ -122,17 +138,21 @@
 
 // hiddenAPIRetrieveDexJarBuildPath retrieves the DexJarBuildPath from the specified module, if
 // available, or reports an error.
-func hiddenAPIRetrieveDexJarBuildPath(ctx android.ModuleContext, module android.Module) android.Path {
-	if j, ok := module.(UsesLibraryDependency); ok {
-		dexJar := j.DexJarBuildPath()
-		if dexJar != nil {
-			return dexJar
-		}
-		ctx.ModuleErrorf("dependency %s does not provide a dex jar, consider setting compile_dex: true", module)
+func hiddenAPIRetrieveDexJarBuildPath(ctx android.ModuleContext, module android.Module, kind android.SdkKind) android.Path {
+	var dexJar android.Path
+	if sdkLibrary, ok := module.(SdkLibraryDependency); ok {
+		dexJar = sdkLibrary.SdkApiStubDexJar(ctx, kind)
+	} else if j, ok := module.(UsesLibraryDependency); ok {
+		dexJar = j.DexJarBuildPath()
 	} else {
 		ctx.ModuleErrorf("dependency %s of module type %s does not support providing a dex jar", module, ctx.OtherModuleType(module))
+		return nil
 	}
-	return nil
+
+	if dexJar == nil {
+		ctx.ModuleErrorf("dependency %s does not provide a dex jar, consider setting compile_dex: true", module)
+	}
+	return dexJar
 }
 
 var sdkKindToHiddenapiListOption = map[android.SdkKind]string{
diff --git a/java/hiddenapi_singleton.go b/java/hiddenapi_singleton.go
index 3cc88e6..9826baf 100644
--- a/java/hiddenapi_singleton.go
+++ b/java/hiddenapi_singleton.go
@@ -186,7 +186,7 @@
 
 	// Now match the apex part of the boot image configuration.
 	requiredApex := configuredBootJars.Apex(index)
-	if requiredApex == "platform" {
+	if requiredApex == "platform" || requiredApex == "system_ext" {
 		if len(apexInfo.InApexes) != 0 {
 			// A platform variant is required but this is for an apex so ignore it.
 			return false
diff --git a/java/platform_bootclasspath.go b/java/platform_bootclasspath.go
index 05b8e2f..6bf9ea0 100644
--- a/java/platform_bootclasspath.go
+++ b/java/platform_bootclasspath.go
@@ -29,8 +29,13 @@
 	ctx.RegisterModuleType("platform_bootclasspath", platformBootclasspathFactory)
 }
 
-// The tag used for the dependency between the platform bootclasspath and any configured boot jars.
-var platformBootclasspathModuleDepTag = bootclasspathDependencyTag{name: "module"}
+// The tags used for the dependencies between the platform bootclasspath and any configured boot
+// jars.
+var (
+	platformBootclasspathArtBootJarDepTag          = bootclasspathDependencyTag{name: "art-boot-jar"}
+	platformBootclasspathNonUpdatableBootJarDepTag = bootclasspathDependencyTag{name: "non-updatable-boot-jar"}
+	platformBootclasspathUpdatableBootJarDepTag    = bootclasspathDependencyTag{name: "updatable-boot-jar"}
+)
 
 type platformBootclasspathModule struct {
 	android.ModuleBase
@@ -125,41 +130,47 @@
 func (b *platformBootclasspathModule) BootclasspathDepsMutator(ctx android.BottomUpMutatorContext) {
 	// Add dependencies on all the modules configured in the "art" boot image.
 	artImageConfig := genBootImageConfigs(ctx)[artBootImageName]
-	addDependenciesOntoBootImageModules(ctx, artImageConfig.modules)
+	addDependenciesOntoBootImageModules(ctx, artImageConfig.modules, platformBootclasspathArtBootJarDepTag)
 
-	// Add dependencies on all the modules configured in the "boot" boot image. That does not
-	// include modules configured in the "art" boot image.
+	// Add dependencies on all the non-updatable module configured in the "boot" boot image. That does
+	// not include modules configured in the "art" boot image.
 	bootImageConfig := b.getImageConfig(ctx)
-	addDependenciesOntoBootImageModules(ctx, bootImageConfig.modules)
+	addDependenciesOntoBootImageModules(ctx, bootImageConfig.modules, platformBootclasspathNonUpdatableBootJarDepTag)
 
 	// Add dependencies on all the updatable modules.
 	updatableModules := dexpreopt.GetGlobalConfig(ctx).UpdatableBootJars
-	addDependenciesOntoBootImageModules(ctx, updatableModules)
+	addDependenciesOntoBootImageModules(ctx, updatableModules, platformBootclasspathUpdatableBootJarDepTag)
 
 	// Add dependencies on all the fragments.
 	b.properties.BootclasspathFragmentsDepsProperties.addDependenciesOntoFragments(ctx)
 }
 
-func addDependenciesOntoBootImageModules(ctx android.BottomUpMutatorContext, modules android.ConfiguredJarList) {
+func addDependenciesOntoBootImageModules(ctx android.BottomUpMutatorContext, modules android.ConfiguredJarList, tag bootclasspathDependencyTag) {
 	for i := 0; i < modules.Len(); i++ {
 		apex := modules.Apex(i)
 		name := modules.Jar(i)
 
-		addDependencyOntoApexModulePair(ctx, apex, name, platformBootclasspathModuleDepTag)
+		addDependencyOntoApexModulePair(ctx, apex, name, tag)
 	}
 }
 
 func (b *platformBootclasspathModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
 	b.classpathFragmentBase().generateAndroidBuildActions(ctx)
 
-	ctx.VisitDirectDepsIf(isActiveModule, func(module android.Module) {
-		tag := ctx.OtherModuleDependencyTag(module)
-		if tag == platformBootclasspathModuleDepTag {
-			b.configuredModules = append(b.configuredModules, module)
-		} else if tag == bootclasspathFragmentDepTag {
-			b.fragments = append(b.fragments, module)
-		}
-	})
+	// Gather all the dependencies from the art, updatable and non-updatable boot jars.
+	artModules := gatherApexModulePairDepsWithTag(ctx, platformBootclasspathArtBootJarDepTag)
+	nonUpdatableModules := gatherApexModulePairDepsWithTag(ctx, platformBootclasspathNonUpdatableBootJarDepTag)
+	updatableModules := gatherApexModulePairDepsWithTag(ctx, platformBootclasspathUpdatableBootJarDepTag)
+
+	// Concatenate them all, in order as they would appear on the bootclasspath.
+	var allModules []android.Module
+	allModules = append(allModules, artModules...)
+	allModules = append(allModules, nonUpdatableModules...)
+	allModules = append(allModules, updatableModules...)
+	b.configuredModules = allModules
+
+	// Gather all the fragments dependencies.
+	b.fragments = gatherApexModulePairDepsWithTag(ctx, bootclasspathFragmentDepTag)
 
 	b.generateHiddenAPIBuildActions(ctx, b.configuredModules, b.fragments)
 
@@ -168,9 +179,7 @@
 		return
 	}
 
-	// Force the GlobalSoongConfig to be created and cached for use by the dex_bootjars
-	// GenerateSingletonBuildActions method as it cannot create it for itself.
-	dexpreopt.GetGlobalSoongConfig(ctx)
+	b.generateBootImageBuildActions(ctx, updatableModules)
 }
 
 func (b *platformBootclasspathModule) getImageConfig(ctx android.EarlyModuleContext) *bootImageConfig {
@@ -297,3 +306,28 @@
 
 	rule.Build("platform-bootclasspath-monolithic-hiddenapi-metadata", "monolithic hidden API metadata")
 }
+
+// generateBootImageBuildActions generates ninja rules related to the boot image creation.
+func (b *platformBootclasspathModule) generateBootImageBuildActions(ctx android.ModuleContext, updatableModules []android.Module) {
+	// Force the GlobalSoongConfig to be created and cached for use by the dex_bootjars
+	// GenerateSingletonBuildActions method as it cannot create it for itself.
+	dexpreopt.GetGlobalSoongConfig(ctx)
+
+	imageConfig := b.getImageConfig(ctx)
+	if imageConfig == nil {
+		return
+	}
+
+	global := dexpreopt.GetGlobalConfig(ctx)
+	if !shouldBuildBootImages(ctx.Config(), global) {
+		return
+	}
+
+	// Generate the framework profile rule
+	bootFrameworkProfileRule(ctx, imageConfig)
+
+	// Generate the updatable bootclasspath packages rule.
+	generateUpdatableBcpPackagesRule(ctx, imageConfig, updatableModules)
+
+	dumpOatRules(ctx, imageConfig)
+}
diff --git a/java/platform_bootclasspath_test.go b/java/platform_bootclasspath_test.go
index 955e387..2216b11 100644
--- a/java/platform_bootclasspath_test.go
+++ b/java/platform_bootclasspath_test.go
@@ -33,7 +33,7 @@
 func TestPlatformBootclasspath(t *testing.T) {
 	preparer := android.GroupFixturePreparers(
 		prepareForTestWithPlatformBootclasspath,
-		FixtureConfigureBootJars("platform:foo", "platform:bar"),
+		FixtureConfigureBootJars("platform:foo", "system_ext:bar"),
 		android.FixtureWithRootAndroidBp(`
 			platform_bootclasspath {
 				name: "platform-bootclasspath",
@@ -45,6 +45,7 @@
 				system_modules: "none",
 				sdk_version: "none",
 				compile_dex: true,
+				system_ext_specific: true,
 			}
 		`),
 	)
diff --git a/java/platform_compat_config.go b/java/platform_compat_config.go
index edfa146..712c2a2 100644
--- a/java/platform_compat_config.go
+++ b/java/platform_compat_config.go
@@ -226,10 +226,8 @@
 func isModulePreferredByCompatConfig(module android.Module) bool {
 	// A versioned prebuilt_platform_compat_config, i.e. foo-platform-compat-config@current should be
 	// ignored.
-	if s, ok := module.(android.SdkAware); ok {
-		if !s.ContainingSdk().Unversioned() {
-			return false
-		}
+	if android.IsModuleInVersionedSdk(module) {
+		return false
 	}
 
 	return android.IsModulePreferred(module)
diff --git a/java/sdk.go b/java/sdk.go
index 1c097d5..cbd873d 100644
--- a/java/sdk.go
+++ b/java/sdk.go
@@ -356,6 +356,7 @@
 			"frameworks-base-api-current.txt",
 			"frameworks-base-api-system-current.txt",
 			"frameworks-base-api-module-lib-current.txt",
+			"services-system-server-current.txt",
 		}
 		count := 0
 		ctx.VisitAllModules(func(module android.Module) {
@@ -369,8 +370,7 @@
 			ctx.Errorf("Could not find all the expected API modules %v, found %d\n", apiTxtFileModules, count)
 			return
 		}
-		cmd.Input(android.PathForSource(ctx, "frameworks/base/services/api/current.txt")).
-			Text("| md5sum | cut -d' ' -f1 >").
+		cmd.Text("| md5sum | cut -d' ' -f1 >").
 			Output(out)
 	} else {
 		// Unbundled build
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 05ce97a..fcc105d 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -339,12 +339,7 @@
 	})
 
 	// Register sdk member types.
-	android.RegisterSdkMemberType(&sdkLibrarySdkMemberType{
-		android.SdkMemberTypeBase{
-			PropertyName: "java_sdk_libs",
-			SupportsSdk:  true,
-		},
-	})
+	android.RegisterSdkMemberType(javaSdkLibrarySdkMemberType)
 }
 
 func RegisterSdkLibraryBuildComponents(ctx android.RegistrationContext) {
@@ -2377,6 +2372,13 @@
 	return &sdkLibrarySdkMemberProperties{}
 }
 
+var javaSdkLibrarySdkMemberType = &sdkLibrarySdkMemberType{
+	android.SdkMemberTypeBase{
+		PropertyName: "java_sdk_libs",
+		SupportsSdk:  true,
+	},
+}
+
 type sdkLibrarySdkMemberProperties struct {
 	android.SdkMemberPropertiesBase
 
diff --git a/rust/builder.go b/rust/builder.go
index 1fcce38..6db508d 100644
--- a/rust/builder.go
+++ b/rust/builder.go
@@ -47,8 +47,7 @@
 	_       = pctx.SourcePathVariable("rustdocCmd", "${config.RustBin}/rustdoc")
 	rustdoc = pctx.AndroidStaticRule("rustdoc",
 		blueprint.RuleParams{
-			Command: "rm -rf $outDir && " +
-				"$envVars $rustdocCmd $rustdocFlags $in -o $outDir && " +
+			Command: "$envVars $rustdocCmd $rustdocFlags $in -o $outDir && " +
 				"touch $out",
 			CommandDeps: []string{"$rustdocCmd"},
 		},
@@ -307,6 +306,10 @@
 	rustdocFlags := append([]string{}, flags.RustdocFlags...)
 	rustdocFlags = append(rustdocFlags, "--sysroot=/dev/null")
 
+	// Build an index for all our crates. -Z unstable options is required to use
+	// this flag.
+	rustdocFlags = append(rustdocFlags, "-Z", "unstable-options", "--enable-index-page")
+
 	targetTriple := ctx.toolchain().RustTriple()
 
 	// Collect rustc flags
@@ -315,13 +318,17 @@
 	}
 
 	crateName := ctx.RustModule().CrateName()
-	if crateName != "" {
-		rustdocFlags = append(rustdocFlags, "--crate-name "+crateName)
-	}
+	rustdocFlags = append(rustdocFlags, "--crate-name "+crateName)
 
 	rustdocFlags = append(rustdocFlags, makeLibFlags(deps)...)
 	docTimestampFile := android.PathForModuleOut(ctx, "rustdoc.timestamp")
-	docDir := android.PathForOutput(ctx, "rustdoc", ctx.ModuleName())
+
+	// Yes, the same out directory is used simultaneously by all rustdoc builds.
+	// This is what cargo does. The docs for individual crates get generated to
+	// a subdirectory named for the crate, and rustdoc synchronizes writes to
+	// shared pieces like the index and search data itself.
+	// https://github.com/rust-lang/rust/blob/master/src/librustdoc/html/render/write_shared.rs#L144-L146
+	docDir := android.PathForOutput(ctx, "rustdoc")
 
 	ctx.Build(pctx, android.BuildParams{
 		Rule:        rustdoc,
diff --git a/sdk/bootclasspath_fragment_sdk_test.go b/sdk/bootclasspath_fragment_sdk_test.go
index dcdf852..2827567 100644
--- a/sdk/bootclasspath_fragment_sdk_test.go
+++ b/sdk/bootclasspath_fragment_sdk_test.go
@@ -46,6 +46,8 @@
 				],
 			}
 		`),
+		// Needed for platform_bootclasspath
+		android.FixtureAddFile("frameworks/base/config/boot-profile.txt", nil),
 
 		java.FixtureConfigureBootJars("com.android.art:mybootlib"),
 		android.FixtureWithRootAndroidBp(`
@@ -163,15 +165,25 @@
 func TestSnapshotWithBootClasspathFragment_Contents(t *testing.T) {
 	result := android.GroupFixturePreparers(
 		prepareForSdkTestWithJava,
+		java.PrepareForTestWithJavaDefaultModules,
+		java.PrepareForTestWithJavaSdkLibraryFiles,
+		java.FixtureWithLastReleaseApis("mysdklibrary", "mycoreplatform"),
 		android.FixtureWithRootAndroidBp(`
 			sdk {
 				name: "mysdk",
 				bootclasspath_fragments: ["mybootclasspathfragment"],
+				java_sdk_libs: ["mysdklibrary", "mycoreplatform"],
 			}
 
 			bootclasspath_fragment {
 				name: "mybootclasspathfragment",
 				contents: ["mybootlib"],
+				api: {
+					stub_libs: ["mysdklibrary"],
+				},
+				core_platform_api: {
+					stub_libs: ["mycoreplatform"],
+				},
 			}
 
 			java_library {
@@ -181,6 +193,20 @@
 				sdk_version: "none",
 				compile_dex: true,
 			}
+
+			java_sdk_library {
+				name: "mysdklibrary",
+				srcs: ["Test.java"],
+				compile_dex: true,
+				public: {enabled: true},
+			}
+
+			java_sdk_library {
+				name: "mycoreplatform",
+				srcs: ["Test.java"],
+				compile_dex: true,
+				public: {enabled: true},
+			}
 		`),
 	).RunTest(t)
 
@@ -194,6 +220,12 @@
     visibility: ["//visibility:public"],
     apex_available: ["//apex_available:platform"],
     contents: ["mybootlib"],
+    api: {
+        stub_libs: ["mysdklibrary"],
+    },
+    core_platform_api: {
+        stub_libs: ["mycoreplatform"],
+    },
 }
 
 java_import {
@@ -203,6 +235,38 @@
     apex_available: ["//apex_available:platform"],
     jars: ["java/mybootlib.jar"],
 }
+
+java_sdk_library_import {
+    name: "mysdklibrary",
+    prefer: false,
+    visibility: ["//visibility:public"],
+    apex_available: ["//apex_available:platform"],
+    shared_library: true,
+    compile_dex: true,
+    public: {
+        jars: ["sdk_library/public/mysdklibrary-stubs.jar"],
+        stub_srcs: ["sdk_library/public/mysdklibrary_stub_sources"],
+        current_api: "sdk_library/public/mysdklibrary.txt",
+        removed_api: "sdk_library/public/mysdklibrary-removed.txt",
+        sdk_version: "current",
+    },
+}
+
+java_sdk_library_import {
+    name: "mycoreplatform",
+    prefer: false,
+    visibility: ["//visibility:public"],
+    apex_available: ["//apex_available:platform"],
+    shared_library: true,
+    compile_dex: true,
+    public: {
+        jars: ["sdk_library/public/mycoreplatform-stubs.jar"],
+        stub_srcs: ["sdk_library/public/mycoreplatform_stub_sources"],
+        current_api: "sdk_library/public/mycoreplatform.txt",
+        removed_api: "sdk_library/public/mycoreplatform-removed.txt",
+        sdk_version: "current",
+    },
+}
 `),
 		checkVersionedAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
@@ -213,6 +277,12 @@
     visibility: ["//visibility:public"],
     apex_available: ["//apex_available:platform"],
     contents: ["mysdk_mybootlib@current"],
+    api: {
+        stub_libs: ["mysdk_mysdklibrary@current"],
+    },
+    core_platform_api: {
+        stub_libs: ["mysdk_mycoreplatform@current"],
+    },
 }
 
 java_import {
@@ -223,15 +293,57 @@
     jars: ["java/mybootlib.jar"],
 }
 
+java_sdk_library_import {
+    name: "mysdk_mysdklibrary@current",
+    sdk_member_name: "mysdklibrary",
+    visibility: ["//visibility:public"],
+    apex_available: ["//apex_available:platform"],
+    shared_library: true,
+    compile_dex: true,
+    public: {
+        jars: ["sdk_library/public/mysdklibrary-stubs.jar"],
+        stub_srcs: ["sdk_library/public/mysdklibrary_stub_sources"],
+        current_api: "sdk_library/public/mysdklibrary.txt",
+        removed_api: "sdk_library/public/mysdklibrary-removed.txt",
+        sdk_version: "current",
+    },
+}
+
+java_sdk_library_import {
+    name: "mysdk_mycoreplatform@current",
+    sdk_member_name: "mycoreplatform",
+    visibility: ["//visibility:public"],
+    apex_available: ["//apex_available:platform"],
+    shared_library: true,
+    compile_dex: true,
+    public: {
+        jars: ["sdk_library/public/mycoreplatform-stubs.jar"],
+        stub_srcs: ["sdk_library/public/mycoreplatform_stub_sources"],
+        current_api: "sdk_library/public/mycoreplatform.txt",
+        removed_api: "sdk_library/public/mycoreplatform-removed.txt",
+        sdk_version: "current",
+    },
+}
+
 sdk_snapshot {
     name: "mysdk@current",
     visibility: ["//visibility:public"],
     bootclasspath_fragments: ["mysdk_mybootclasspathfragment@current"],
     java_boot_libs: ["mysdk_mybootlib@current"],
+    java_sdk_libs: [
+        "mysdk_mysdklibrary@current",
+        "mysdk_mycoreplatform@current",
+    ],
 }
 `),
 		checkAllCopyRules(`
 .intermediates/mybootlib/android_common/javac/mybootlib.jar -> java/mybootlib.jar
+.intermediates/mysdklibrary.stubs/android_common/javac/mysdklibrary.stubs.jar -> sdk_library/public/mysdklibrary-stubs.jar
+.intermediates/mysdklibrary.stubs.source/android_common/metalava/mysdklibrary.stubs.source_api.txt -> sdk_library/public/mysdklibrary.txt
+.intermediates/mysdklibrary.stubs.source/android_common/metalava/mysdklibrary.stubs.source_removed.txt -> sdk_library/public/mysdklibrary-removed.txt
+.intermediates/mycoreplatform.stubs/android_common/javac/mycoreplatform.stubs.jar -> sdk_library/public/mycoreplatform-stubs.jar
+.intermediates/mycoreplatform.stubs.source/android_common/metalava/mycoreplatform.stubs.source_api.txt -> sdk_library/public/mycoreplatform.txt
+.intermediates/mycoreplatform.stubs.source/android_common/metalava/mycoreplatform.stubs.source_removed.txt -> sdk_library/public/mycoreplatform-removed.txt
 `))
 }
 
diff --git a/sdk/update.go b/sdk/update.go
index 3668b46..72b02e8 100644
--- a/sdk/update.go
+++ b/sdk/update.go
@@ -120,7 +120,7 @@
 	ctx.WalkDeps(func(child android.Module, parent android.Module) bool {
 		tag := ctx.OtherModuleDependencyTag(child)
 		if memberTag, ok := tag.(android.SdkMemberTypeDependencyTag); ok {
-			memberType := memberTag.SdkMemberType()
+			memberType := memberTag.SdkMemberType(child)
 
 			// Make sure that the resolved module is allowed in the member list property.
 			if !memberType.IsInstance(child) {