Merge "more no include_dir"
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 49fc0ad..f50b31d 100644
--- a/android/bazel.go
+++ b/android/bazel.go
@@ -167,6 +167,8 @@
 		"bionic":                Bp2BuildDefaultTrueRecursively,
 		"external/gwp_asan":     Bp2BuildDefaultTrueRecursively,
 		"system/core/libcutils": Bp2BuildDefaultTrueRecursively,
+		"system/core/property_service/libpropertyinfoparser": Bp2BuildDefaultTrueRecursively,
+		"system/libbase":        Bp2BuildDefaultTrueRecursively,
 		"system/logging/liblog": Bp2BuildDefaultTrueRecursively,
 	}
 
@@ -181,17 +183,20 @@
 		"libc_nopthread",     // ruperts@, cc_library_static, depends on //external/arm-optimized-routine
 
 		// Things that transitively depend on //system/libbase. libbase doesn't work because:
-		// "Multiple dependencies having same BaseModuleName() "fmtlib" found from "libbase""
+		// 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
-		"libsystemproperties",   // ruperts@, cc_library_static, depends on //system/core/property_service/libpropertyinfoparser
 
 		// Compilation error, seems to be fixable by changing the toolchain definition
 		"libc_bionic_ndk", // ruperts@, cc_library_static, error: ISO C++ requires field designators...
@@ -200,20 +205,19 @@
 
 		// Linker error
 		"libc_malloc_hooks", // jingwen@, cc_library, undefined symbol: __malloc_hook, etc.
-		"libdl",             // jingwen@, cc_library, no input files
+		"libdl",             // jingwen@, cc_library, clang failed
 		"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_syscalls",            // ruperts@, cc_library_static, mutator panic cannot get direct dep syscalls-arm64.S of libc_syscalls
-		"libc_ndk",                 // ruperts@, cc_library_static, depends on libc_bionic_ndk, libc_jemalloc_wrapper, libc_syscalls, libc_tzcode, libstdc++
-		"libdl_static",             // ruperts@, cc_library_static, conflicts with libdl
+		"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
 	}
@@ -221,10 +225,11 @@
 	// Per-module denylist to opt modules out of mixed builds. Such modules will
 	// still be generated via bp2build.
 	mixedBuildsDisabledList = []string{
-		"libasync_safe", // lberki@, cc_library_static, 'async_safe/log.h not found' for out/combined-aosp_arm64.ninja out/soong/.intermediates/system/unwinding/libbacktrace/libbacktrace/android_arm64_armv8-a_shared/obj/system/unwinding/libbacktrace/ThreadEntry.o
-		"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
+		"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
 	}
 
 	// Used for quicker lookups
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/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/bp2build/cc_library_static_conversion_test.go b/bp2build/cc_library_static_conversion_test.go
index 9d23cc5..e8235d5 100644
--- a/bp2build/cc_library_static_conversion_test.go
+++ b/bp2build/cc_library_static_conversion_test.go
@@ -721,6 +721,31 @@
     }),
 )`},
 		},
+		{
+			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/cc/cc.go b/cc/cc.go
index 4d8f4e1..c35f628 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -1121,13 +1121,6 @@
 	return c.VendorProperties.IsLLNDK && !c.VendorProperties.IsVNDKPrivate
 }
 
-func (c *Module) IsLlndkHeaders() bool {
-	if _, ok := c.linker.(*llndkHeadersDecorator); ok {
-		return true
-	}
-	return false
-}
-
 func (c *Module) IsLlndkLibrary() bool {
 	if _, ok := c.linker.(*llndkStubDecorator); ok {
 		return true
@@ -1608,8 +1601,7 @@
 	}
 
 	llndk := c.IsLlndk()
-	_, llndkHeader := c.linker.(*llndkHeadersDecorator)
-	if llndk || llndkHeader || (c.UseVndk() && c.HasNonSystemVariants()) {
+	if llndk || (c.UseVndk() && c.HasNonSystemVariants()) {
 		// .vendor.{version} suffix is added for vendor variant or .product.{version} suffix is
 		// added for product variant only when we have vendor and product variants with core
 		// variant. The suffix is not added for vendor-only or product-only module.
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 3d2160f..49fffc9 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -557,8 +557,11 @@
 			export_llndk_headers: ["libllndk_headers"],
 		}
 
-		llndk_headers {
+		cc_library_headers {
 			name: "libllndk_headers",
+			llndk: {
+				llndk_headers: true,
+			},
 			export_include_dirs: ["include"],
 		}
 
@@ -903,8 +906,11 @@
 			export_llndk_headers: ["libllndk_headers"],
 		}
 
-		llndk_headers {
+		cc_library_headers {
 			name: "libllndk_headers",
+			llndk: {
+				symbol_file: "libllndk.map.txt",
+			},
 			export_include_dirs: ["include"],
 		}
 	`)
@@ -2920,17 +2926,19 @@
 
 func TestLlndkHeaders(t *testing.T) {
 	ctx := testCc(t, `
-	llndk_headers {
+	cc_library_headers {
 		name: "libllndk_headers",
 		export_include_dirs: ["my_include"],
-	}
-	llndk_library {
-		name: "libllndk.llndk",
-		export_llndk_headers: ["libllndk_headers"],
+		llndk: {
+			llndk_headers: true,
+		},
 	}
 	cc_library {
 		name: "libllndk",
-		llndk_stubs: "libllndk.llndk",
+		llndk: {
+			symbol_file: "libllndk.map.txt",
+			export_llndk_headers: ["libllndk_headers"],
+		}
 	}
 
 	cc_library {
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/image.go b/cc/image.go
index 6265b13..66b02d9 100644
--- a/cc/image.go
+++ b/cc/image.go
@@ -437,7 +437,7 @@
 		productVndkVersion = platformVndkVersion
 	}
 
-	if m.IsLlndkLibrary() || m.IsLlndkHeaders() || m.NeedsLlndkVariants() {
+	if m.IsLlndkLibrary() || m.NeedsLlndkVariants() {
 		// This is an LLNDK library.  The implementation of the library will be on /system,
 		// and vendor and product variants will be created with LLNDK stubs.
 		// The LLNDK libraries need vendor variants even if there is no VNDK.
diff --git a/cc/library.go b/cc/library.go
index 3ac7e11..73215ed 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -402,11 +402,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,
 	})
 }
 
@@ -524,6 +531,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
diff --git a/cc/linkable.go b/cc/linkable.go
index 8fe0b4a..7b5b446 100644
--- a/cc/linkable.go
+++ b/cc/linkable.go
@@ -106,9 +106,6 @@
 	// IsLlndkPublic returns true only for LLNDK (public) libs.
 	IsLlndkPublic() bool
 
-	// IsLlndkHeaders returns true if this module is an LLNDK headers module.
-	IsLlndkHeaders() bool
-
 	// IsLlndkLibrary returns true if this module is an LLNDK library module.
 	IsLlndkLibrary() bool
 
@@ -283,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/cc/llndk_library.go b/cc/llndk_library.go
index ad19e47..88f3118 100644
--- a/cc/llndk_library.go
+++ b/cc/llndk_library.go
@@ -166,40 +166,6 @@
 	return ok
 }
 
-type llndkHeadersDecorator struct {
-	*libraryDecorator
-}
-
-func (llndk *llndkHeadersDecorator) linkerDeps(ctx DepsContext, deps Deps) Deps {
-	deps.HeaderLibs = append(deps.HeaderLibs, llndk.Properties.Llndk.Export_llndk_headers...)
-	deps.ReexportHeaderLibHeaders = append(deps.ReexportHeaderLibHeaders,
-		llndk.Properties.Llndk.Export_llndk_headers...)
-	return deps
-}
-
-// llndk_headers contains a set of c/c++ llndk headers files which are imported
-// by other soongs cc modules.
-func llndkHeadersFactory() android.Module {
-	module, library := NewLibrary(android.DeviceSupported)
-	library.HeaderOnly()
-	module.stl = nil
-	module.sanitize = nil
-
-	decorator := &llndkHeadersDecorator{
-		libraryDecorator: library,
-	}
-
-	module.compiler = nil
-	module.linker = decorator
-	module.installer = nil
-	module.library = decorator
-
-	module.Init()
-
-	return module
-}
-
 func init() {
 	android.RegisterModuleType("llndk_library", LlndkLibraryFactory)
-	android.RegisterModuleType("llndk_headers", llndkHeadersFactory)
 }
diff --git a/cc/testing.go b/cc/testing.go
index ff32bff..bf89f62 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -569,7 +569,6 @@
 		ctx.RegisterModuleType("cc_fuzz", FuzzFactory)
 		ctx.RegisterModuleType("cc_test", TestFactory)
 		ctx.RegisterModuleType("cc_test_library", TestLibraryFactory)
-		ctx.RegisterModuleType("llndk_headers", llndkHeadersFactory)
 		ctx.RegisterModuleType("vendor_public_library", vendorPublicLibraryFactory)
 		ctx.RegisterModuleType("vndk_prebuilt_shared", VndkPrebuiltSharedFactory)
 
@@ -686,7 +685,6 @@
 	ctx.RegisterModuleType("cc_fuzz", FuzzFactory)
 	ctx.RegisterModuleType("cc_test", TestFactory)
 	ctx.RegisterModuleType("cc_test_library", TestLibraryFactory)
-	ctx.RegisterModuleType("llndk_headers", llndkHeadersFactory)
 	ctx.RegisterModuleType("vendor_public_library", vendorPublicLibraryFactory)
 	ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
 	ctx.RegisterModuleType("vndk_prebuilt_shared", VndkPrebuiltSharedFactory)
diff --git a/cc/vendor_snapshot.go b/cc/vendor_snapshot.go
index 2f68cca..c0082fb 100644
--- a/cc/vendor_snapshot.go
+++ b/cc/vendor_snapshot.go
@@ -180,16 +180,13 @@
 	if _, ok := m.linker.(*kernelHeadersDecorator); ok {
 		return false
 	}
-	// skip llndk_library and llndk_headers which are backward compatible
+	// skip LLNDK libraries which are backward compatible
 	if m.IsLlndk() {
 		return false
 	}
 	if _, ok := m.linker.(*llndkStubDecorator); ok {
 		return false
 	}
-	if _, ok := m.linker.(*llndkHeadersDecorator); ok {
-		return false
-	}
 
 	// Libraries
 	if l, ok := m.linker.(snapshotLibraryInterface); ok {
diff --git a/dexpreopt/config.go b/dexpreopt/config.go
index 8a656ed..7397919 100644
--- a/dexpreopt/config.go
+++ b/dexpreopt/config.go
@@ -404,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/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go
index 2e33c06..5c1c5f0 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
 }
 
@@ -150,7 +150,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 +205,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
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index e3b5487..8a6f3d1 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -423,14 +423,7 @@
 	writeGlobalConfigForMake(ctx, d.dexpreoptConfigForMake)
 
 	global := dexpreopt.GetGlobalConfig(ctx)
-
-	// 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 {
+	if !shouldBuildBootImages(ctx.Config(), global) {
 		return
 	}
 
@@ -438,9 +431,6 @@
 	defaultImageConfig := defaultBootImageConfig(ctx)
 	profile := bootImageProfileRule(ctx, defaultImageConfig)
 
-	// Generate the framework profile rule
-	bootFrameworkProfileRule(ctx, defaultImageConfig)
-
 	// Generate the updatable bootclasspath packages rule.
 	updatableBcpPackagesRule(ctx, defaultImageConfig)
 
@@ -455,6 +445,18 @@
 	dumpOatRules(ctx, d.defaultBootImage)
 }
 
+// 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(config.SanitizeDevice()) == 1 && config.SanitizeDevice()[0] == "address" && global.SanitizeLite {
+		return false
+	}
+	return true
+}
+
 // Inspect this module to see if it contains a bootclasspath dex jar.
 // Note that the same jar may occur in multiple modules.
 // This logic is tested in the apex package to avoid import cycle apex <-> java.
@@ -853,32 +855,22 @@
 	return profile
 }
 
-func bootFrameworkProfileRule(ctx android.SingletonContext, image *bootImageConfig) 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
 	}
 
-	// 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
-	var missingDeps []string
-	if path.Valid() {
-		bootFrameworkProfile = path.Path()
-	} else {
-		missingDeps = append(missingDeps, defaultProfile)
-		bootFrameworkProfile = android.PathForOutput(ctx, "missing", defaultProfile)
-	}
+	bootFrameworkProfile := android.PathForSource(ctx, defaultProfile)
 
 	profile := image.dir.Join(ctx, "boot.bprof")
 
 	rule := android.NewRuleBuilder(pctx, ctx)
-	rule.MissingDeps(missingDeps)
 	rule.Command().
 		Text(`ANDROID_LOG_TAGS="*:e"`).
 		Tool(globalSoong.Profman).
@@ -901,29 +893,39 @@
 	}
 
 	global := dexpreopt.GetGlobalConfig(ctx)
+	var modules []android.Module
 	updatableModules := global.UpdatableBootJars.CopyOfJars()
-
-	// 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:]...)
-			}
+		name := ctx.ModuleName(module)
+		if i := android.IndexList(name, updatableModules); i != -1 {
+			modules = append(modules, module)
+			// Do not match the same library repeatedly.
+			updatableModules = append(updatableModules[:i], updatableModules[i+1:]...)
 		}
 	})
 
+	return generateUpdatableBcpPackagesRule(ctx, image, modules)
+}
+
+// generateUpdatableBcpPackagesRule generates the rule to create the updatable-bcp-packages.txt file
+// and returns a path to the generated file.
+func generateUpdatableBcpPackagesRule(ctx android.SingletonContext, 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.Errorf("Missing permitted_packages for %s", ctx.ModuleName(module))
+			}
+		}
+	}
+
 	// Sort updatable packages to ensure deterministic ordering.
 	sort.Strings(updatablePackages)
 
diff --git a/java/hiddenapi_modular.go b/java/hiddenapi_modular.go
index 8cc6f8f..793d63a 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.
diff --git a/java/platform_bootclasspath.go b/java/platform_bootclasspath.go
index 05b8e2f..6503eca 100644
--- a/java/platform_bootclasspath.go
+++ b/java/platform_bootclasspath.go
@@ -168,9 +168,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)
 }
 
 func (b *platformBootclasspathModule) getImageConfig(ctx android.EarlyModuleContext) *bootImageConfig {
@@ -297,3 +295,23 @@
 
 	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) {
+	// 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)
+}
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/rust/rust.go b/rust/rust.go
index e1a69c0..74d2828 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -262,10 +262,6 @@
 	return false
 }
 
-func (m *Module) IsLlndkHeaders() bool {
-	return false
-}
-
 func (m *Module) IsLlndkLibrary() bool {
 	return false
 }
diff --git a/sdk/bootclasspath_fragment_sdk_test.go b/sdk/bootclasspath_fragment_sdk_test.go
index dcdf852..5658f16 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(`
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) {