Merge changes Ic32f02a6,Ibe358542

* changes:
  Export classesJars initialized in hiddenAPIExtractInformation
  Generalize the platformBootclasspathDepsMutator
diff --git a/android/arch.go b/android/arch.go
index 9f93752..d7b12bc 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -412,6 +412,54 @@
 	}
 }
 
+func registerBp2buildArchPathDepsMutator(ctx RegisterMutatorsContext) {
+	ctx.BottomUp("bp2build-arch-pathdeps", bp2buildArchPathDepsMutator).Parallel()
+}
+
+// add dependencies for architecture specific properties tagged with `android:"path"`
+func bp2buildArchPathDepsMutator(ctx BottomUpMutatorContext) {
+	var module Module
+	module = ctx.Module()
+
+	m := module.base()
+	if !m.ArchSpecific() {
+		return
+	}
+
+	// addPathDepsForProps does not descend into sub structs, so we need to descend into the
+	// arch-specific properties ourselves
+	properties := []interface{}{}
+	for _, archProperties := range m.archProperties {
+		for _, archProps := range archProperties {
+			archPropValues := reflect.ValueOf(archProps).Elem()
+			// there are three "arch" variations, descend into each
+			for _, variant := range []string{"Arch", "Multilib", "Target"} {
+				// The properties are an interface, get the value (a pointer) that it points to
+				archProps := archPropValues.FieldByName(variant).Elem()
+				if archProps.IsNil() {
+					continue
+				}
+				// And then a pointer to a struct
+				archProps = archProps.Elem()
+				for i := 0; i < archProps.NumField(); i += 1 {
+					f := archProps.Field(i)
+					// If the value of the field is a struct (as opposed to a pointer to a struct) then step
+					// into the BlueprintEmbed field.
+					if f.Kind() == reflect.Struct {
+						f = f.FieldByName("BlueprintEmbed")
+					}
+					if f.IsZero() {
+						continue
+					}
+					props := f.Interface().(interface{})
+					properties = append(properties, props)
+				}
+			}
+		}
+	}
+	addPathDepsForProps(ctx, properties)
+}
+
 // osMutator splits an arch-specific module into a variant for each OS that is enabled for the
 // module.  It uses the HostOrDevice value passed to InitAndroidArchModule and the
 // device_supported and host_supported properties to determine which OsTypes are enabled for this
@@ -617,7 +665,7 @@
 	}
 
 	// only the primary arch in the ramdisk / vendor_ramdisk / recovery partition
-	if os == Android && (module.InstallInRecovery() || module.InstallInRamdisk() || module.InstallInVendorRamdisk() || module.InstallInDebugRamdisk()) {
+	if os == Android && (module.InstallInRecovery() || module.InstallInRamdisk() || module.InstallInVendorRamdisk()) {
 		osTargets = []Target{osTargets[0]}
 	}
 
@@ -899,13 +947,17 @@
 		if string(field.Tag) != `android:"`+strings.Join(values, ",")+`"` {
 			panic(fmt.Errorf("unexpected tag format %q", field.Tag))
 		}
+		// don't delete path tag as it is needed for bp2build
 		// these tags don't need to be present in the runtime generated struct type.
-		values = RemoveListFromList(values, []string{"arch_variant", "variant_prepend", "path"})
-		if len(values) > 0 {
+		values = RemoveListFromList(values, []string{"arch_variant", "variant_prepend"})
+		if len(values) > 0 && values[0] != "path" {
 			panic(fmt.Errorf("unknown tags %q in field %q", values, prefix+field.Name))
+		} else if len(values) == 1 {
+			field.Tag = reflect.StructTag(`android:"` + strings.Join(values, ",") + `"`)
+		} else {
+			field.Tag = ``
 		}
 
-		field.Tag = ""
 		return true, field
 	}
 	return false, field
diff --git a/android/arch_test.go b/android/arch_test.go
index 633ddaa..3aa4779 100644
--- a/android/arch_test.go
+++ b/android/arch_test.go
@@ -66,9 +66,9 @@
 			}{},
 			out: &struct {
 				A *string
-				B *string
-				C *string
-				D *string
+				B *string `android:"path"`
+				C *string `android:"path"`
+				D *string `android:"path"`
 			}{},
 			filtered: true,
 		},
diff --git a/android/bazel.go b/android/bazel.go
index 6800c91..ba5ae31 100644
--- a/android/bazel.go
+++ b/android/bazel.go
@@ -185,7 +185,7 @@
 		"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",                 // ruperts@, cc_library_static, mutator panic cannot get direct dep syscalls-arm64.S of libc_syscalls
+		"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
@@ -212,8 +212,8 @@
 		"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",              // jingwen@, cc_library, fatal error: 'freebsd-compat.h' file not found
-		"libseccomp_policy", // jingwen@, cc_library, fatal error: 'seccomp_policy.h' file not found
+		"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
 	}
 
diff --git a/android/bazel_paths.go b/android/bazel_paths.go
index 9727cc7..63e2c50 100644
--- a/android/bazel_paths.go
+++ b/android/bazel_paths.go
@@ -351,3 +351,13 @@
 		OutputPath: outputPath.withRel(validatedExecRootPath),
 	}
 }
+
+// PathsForBazelOut returns a list of paths representing the paths under an output directory
+// dedicated to Bazel-owned outputs.
+func PathsForBazelOut(ctx PathContext, paths []string) Paths {
+	outs := make(Paths, 0, len(paths))
+	for _, p := range paths {
+		outs = append(outs, PathForBazelOut(ctx, p))
+	}
+	return outs
+}
diff --git a/android/image.go b/android/image.go
index bdb9be0..1a1a423 100644
--- a/android/image.go
+++ b/android/image.go
@@ -30,11 +30,6 @@
 	// vendor ramdisk partition).
 	VendorRamdiskVariantNeeded(ctx BaseModuleContext) bool
 
-	// DebugRamdiskVariantNeeded should return true if the module needs a debug ramdisk variant (installed on the
-	// debug ramdisk partition: $(PRODUCT_OUT)/debug_ramdisk/first_stage_ramdisk if BOARD_USES_RECOVERY_AS_ROOT is
-	// true, $(PRODUCT_OUT)/debug_ramdisk otherise).
-	DebugRamdiskVariantNeeded(ctx BaseModuleContext) bool
-
 	// RecoveryVariantNeeded should return true if the module needs a recovery variant (installed on the
 	// recovery partition).
 	RecoveryVariantNeeded(ctx BaseModuleContext) bool
@@ -65,9 +60,6 @@
 
 	// VendorRamdiskVariation means a module to be installed to vendor ramdisk image.
 	VendorRamdiskVariation string = "vendor_ramdisk"
-
-	// DebugRamdiskVariation means a module to be installed to debug ramdisk image.
-	DebugRamdiskVariation string = "debug_ramdisk"
 )
 
 // imageMutator creates variants for modules that implement the ImageInterface that
@@ -91,9 +83,6 @@
 		if m.VendorRamdiskVariantNeeded(ctx) {
 			variations = append(variations, VendorRamdiskVariation)
 		}
-		if m.DebugRamdiskVariantNeeded(ctx) {
-			variations = append(variations, DebugRamdiskVariation)
-		}
 		if m.RecoveryVariantNeeded(ctx) {
 			variations = append(variations, RecoveryVariation)
 		}
diff --git a/android/module.go b/android/module.go
index 942e071..9f923e2 100644
--- a/android/module.go
+++ b/android/module.go
@@ -393,7 +393,6 @@
 	InstallInSanitizerDir() bool
 	InstallInRamdisk() bool
 	InstallInVendorRamdisk() bool
-	InstallInDebugRamdisk() bool
 	InstallInRecovery() bool
 	InstallInRoot() bool
 	InstallBypassMake() bool
@@ -451,7 +450,6 @@
 	InstallInSanitizerDir() bool
 	InstallInRamdisk() bool
 	InstallInVendorRamdisk() bool
-	InstallInDebugRamdisk() bool
 	InstallInRecovery() bool
 	InstallInRoot() bool
 	InstallBypassMake() bool
@@ -755,9 +753,6 @@
 	// Whether this module is installed to vendor ramdisk
 	Vendor_ramdisk *bool
 
-	// Whether this module is installed to debug ramdisk
-	Debug_ramdisk *bool
-
 	// Whether this module is built for non-native architectures (also known as native bridge binary)
 	Native_bridge_supported *bool `android:"arch_variant"`
 
@@ -1545,10 +1540,6 @@
 	return Bool(m.commonProperties.Vendor_ramdisk)
 }
 
-func (m *ModuleBase) InstallInDebugRamdisk() bool {
-	return Bool(m.commonProperties.Debug_ramdisk)
-}
-
 func (m *ModuleBase) InstallInRecovery() bool {
 	return Bool(m.commonProperties.Recovery)
 }
@@ -1602,10 +1593,6 @@
 	return m.base().commonProperties.ImageVariation == VendorRamdiskVariation
 }
 
-func (m *ModuleBase) InDebugRamdisk() bool {
-	return m.base().commonProperties.ImageVariation == DebugRamdiskVariation
-}
-
 func (m *ModuleBase) InRecovery() bool {
 	return m.base().commonProperties.ImageVariation == RecoveryVariation
 }
@@ -2561,10 +2548,6 @@
 	return m.module.InstallInVendorRamdisk()
 }
 
-func (m *moduleContext) InstallInDebugRamdisk() bool {
-	return m.module.InstallInDebugRamdisk()
-}
-
 func (m *moduleContext) InstallInRecovery() bool {
 	return m.module.InstallInRecovery()
 }
diff --git a/android/mutator.go b/android/mutator.go
index e25e2e8..365bf29 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -55,6 +55,7 @@
 	bp2buildDepsMutators = append([]RegisterMutatorFunc{
 		registerDepsMutatorBp2Build,
 		registerPathDepsMutator,
+		registerBp2buildArchPathDepsMutator,
 	}, depsMutators...)
 
 	for _, f := range bp2buildDepsMutators {
diff --git a/android/path_properties.go b/android/path_properties.go
index 2c8d27c..4446773 100644
--- a/android/path_properties.go
+++ b/android/path_properties.go
@@ -34,7 +34,10 @@
 // ":module" module reference syntax in a property that is tagged with `android:"path"`.
 func pathDepsMutator(ctx BottomUpMutatorContext) {
 	props := ctx.Module().base().generalProperties
+	addPathDepsForProps(ctx, props)
+}
 
+func addPathDepsForProps(ctx BottomUpMutatorContext, props []interface{}) {
 	// Iterate through each property struct of the module extracting the contents of all properties
 	// tagged with `android:"path"`.
 	var pathProperties []string
diff --git a/android/paths.go b/android/paths.go
index 026cb87..93c5684 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -106,7 +106,6 @@
 	InstallInSanitizerDir() bool
 	InstallInRamdisk() bool
 	InstallInVendorRamdisk() bool
-	InstallInDebugRamdisk() bool
 	InstallInRecovery() bool
 	InstallInRoot() bool
 	InstallBypassMake() bool
@@ -1690,16 +1689,6 @@
 			if !ctx.InstallInRoot() {
 				partition += "/system"
 			}
-		} else if ctx.InstallInDebugRamdisk() {
-			// The module is only available after switching root into
-			// /first_stage_ramdisk. To expose the module before switching root
-			// on a device without a dedicated recovery partition, install the
-			// recovery variant.
-			if ctx.DeviceConfig().BoardUsesRecoveryAsBoot() {
-				partition = "debug_ramdisk/first_stage_ramdisk"
-			} else {
-				partition = "debug_ramdisk"
-			}
 		} else if ctx.InstallInRecovery() {
 			if ctx.InstallInRoot() {
 				partition = "recovery/root"
@@ -1870,7 +1859,6 @@
 	inSanitizerDir  bool
 	inRamdisk       bool
 	inVendorRamdisk bool
-	inDebugRamdisk  bool
 	inRecovery      bool
 	inRoot          bool
 	forceOS         *OsType
@@ -1903,10 +1891,6 @@
 	return m.inVendorRamdisk
 }
 
-func (m testModuleInstallPathContext) InstallInDebugRamdisk() bool {
-	return m.inDebugRamdisk
-}
-
 func (m testModuleInstallPathContext) InstallInRecovery() bool {
 	return m.inRecovery
 }
diff --git a/android/paths_test.go b/android/paths_test.go
index cb9138b..6ec75b4 100644
--- a/android/paths_test.go
+++ b/android/paths_test.go
@@ -395,19 +395,6 @@
 			partitionDir: "target/product/test_device/vendor_ramdisk",
 		},
 		{
-			name: "debug_ramdisk binary",
-			ctx: &testModuleInstallPathContext{
-				baseModuleContext: baseModuleContext{
-					os:     deviceTarget.Os,
-					target: deviceTarget,
-				},
-				inDebugRamdisk: true,
-			},
-			in:           []string{"my_test"},
-			out:          "target/product/test_device/debug_ramdisk/my_test",
-			partitionDir: "target/product/test_device/debug_ramdisk",
-		},
-		{
 			name: "system native test binary",
 			ctx: &testModuleInstallPathContext{
 				baseModuleContext: baseModuleContext{
@@ -746,19 +733,6 @@
 			out:          "target/product/test_device/vendor_ramdisk/first_stage_ramdisk/my_test",
 			partitionDir: "target/product/test_device/vendor_ramdisk/first_stage_ramdisk",
 		},
-		{
-			name: "debug_ramdisk binary",
-			ctx: &testModuleInstallPathContext{
-				baseModuleContext: baseModuleContext{
-					os:     deviceTarget.Os,
-					target: deviceTarget,
-				},
-				inDebugRamdisk: true,
-			},
-			in:           []string{"my_test"},
-			out:          "target/product/test_device/debug_ramdisk/first_stage_ramdisk/my_test",
-			partitionDir: "target/product/test_device/debug_ramdisk/first_stage_ramdisk",
-		},
 	}
 
 	for _, tc := range testCases {
diff --git a/apex/deapexer.go b/apex/deapexer.go
index 1db13f9..9bc5720 100644
--- a/apex/deapexer.go
+++ b/apex/deapexer.go
@@ -44,9 +44,13 @@
 // module.`
 type DeapexerProperties struct {
 	// List of java libraries that are embedded inside this prebuilt APEX bundle and for which this
-	// APEX bundle will provide dex implementation jars for use by dexpreopt and boot jars package
-	// check.
+	// APEX bundle will create an APEX variant and provide dex implementation jars for use by
+	// dexpreopt and boot jars package check.
 	Exported_java_libs []string
+
+	// List of bootclasspath fragments inside this prebuiltd APEX bundle and for which this APEX
+	// bundle will create an APEX variant.
+	Exported_bootclasspath_fragments []string
 }
 
 type SelectedApexProperties struct {
diff --git a/apex/prebuilt.go b/apex/prebuilt.go
index a9d24a7..7830f95 100644
--- a/apex/prebuilt.go
+++ b/apex/prebuilt.go
@@ -97,10 +97,17 @@
 func (p *prebuiltCommon) deapexerDeps(ctx android.BottomUpMutatorContext) {
 	// Add dependencies onto the java modules that represent the java libraries that are provided by
 	// and exported from this prebuilt apex.
-	for _, lib := range p.deapexerProperties.Exported_java_libs {
-		dep := prebuiltApexExportedModuleName(ctx, lib)
+	for _, exported := range p.deapexerProperties.Exported_java_libs {
+		dep := prebuiltApexExportedModuleName(ctx, exported)
 		ctx.AddFarVariationDependencies(ctx.Config().AndroidCommonTarget.Variations(), exportedJavaLibTag, dep)
 	}
+
+	// Add dependencies onto the bootclasspath fragment modules that are exported from this prebuilt
+	// apex.
+	for _, exported := range p.deapexerProperties.Exported_bootclasspath_fragments {
+		dep := prebuiltApexExportedModuleName(ctx, exported)
+		ctx.AddFarVariationDependencies(ctx.Config().AndroidCommonTarget.Variations(), exportedBootclasspathFragmentTag, dep)
+	}
 }
 
 // apexInfoMutator marks any modules for which this apex exports a file as requiring an apex
@@ -137,18 +144,19 @@
 	var dependencies []android.ApexModule
 	mctx.VisitDirectDeps(func(m android.Module) {
 		tag := mctx.OtherModuleDependencyTag(m)
-		if tag == exportedJavaLibTag {
+		if exportedTag, ok := tag.(exportedDependencyTag); ok {
+			propertyName := exportedTag.name
 			depName := mctx.OtherModuleName(m)
 
 			// It is an error if the other module is not a prebuilt.
 			if _, ok := m.(android.PrebuiltInterface); !ok {
-				mctx.PropertyErrorf("exported_java_libs", "%q is not a prebuilt module", depName)
+				mctx.PropertyErrorf(propertyName, "%q is not a prebuilt module", depName)
 				return
 			}
 
 			// It is an error if the other module is not an ApexModule.
 			if _, ok := m.(android.ApexModule); !ok {
-				mctx.PropertyErrorf("exported_java_libs", "%q is not usable within an apex", depName)
+				mctx.PropertyErrorf(propertyName, "%q is not usable within an apex", depName)
 				return
 			}
 
@@ -451,7 +459,8 @@
 func (t exportedDependencyTag) ExcludeFromVisibilityEnforcement() {}
 
 var (
-	exportedJavaLibTag = exportedDependencyTag{name: "exported_java_lib"}
+	exportedJavaLibTag               = exportedDependencyTag{name: "exported_java_libs"}
+	exportedBootclasspathFragmentTag = exportedDependencyTag{name: "exported_bootclasspath_fragments"}
 )
 
 func (p *Prebuilt) DepsMutator(ctx android.BottomUpMutatorContext) {
diff --git a/bazel/cquery/request_type.go b/bazel/cquery/request_type.go
index 8049108..c30abeb 100644
--- a/bazel/cquery/request_type.go
+++ b/bazel/cquery/request_type.go
@@ -14,6 +14,8 @@
 	OutputFiles          []string
 	CcObjectFiles        []string
 	CcStaticLibraryFiles []string
+	Includes             []string
+	SystemIncludes       []string
 }
 
 type getOutputFilesRequestType struct{}
@@ -63,6 +65,9 @@
 	return `
 outputFiles = [f.path for f in target.files.to_list()]
 
+includes = providers(target)["CcInfo"].compilation_context.includes.to_list()
+system_includes = providers(target)["CcInfo"].compilation_context.system_includes.to_list()
+
 ccObjectFiles = []
 staticLibraries = []
 linker_inputs = providers(target)["CcInfo"].linking_context.linker_inputs.to_list()
@@ -78,6 +83,8 @@
   outputFiles,
   staticLibraries,
   ccObjectFiles,
+  includes,
+  system_includes,
 ]
 
 return "|".join([", ".join(r) for r in returns])`
@@ -91,7 +98,7 @@
 	var ccObjects []string
 
 	splitString := strings.Split(rawString, "|")
-	if expectedLen := 3; len(splitString) != expectedLen {
+	if expectedLen := 5; len(splitString) != expectedLen {
 		return CcInfo{}, fmt.Errorf("Expected %d items, got %q", expectedLen, splitString)
 	}
 	outputFilesString := splitString[0]
@@ -100,10 +107,14 @@
 	outputFiles = splitOrEmpty(outputFilesString, ", ")
 	ccStaticLibraries := splitOrEmpty(ccStaticLibrariesString, ", ")
 	ccObjects = splitOrEmpty(ccObjectsString, ", ")
+	includes := splitOrEmpty(splitString[3], ", ")
+	systemIncludes := splitOrEmpty(splitString[4], ", ")
 	return CcInfo{
 		OutputFiles:          outputFiles,
 		CcObjectFiles:        ccObjects,
 		CcStaticLibraryFiles: ccStaticLibraries,
+		Includes:             includes,
+		SystemIncludes:       systemIncludes,
 	}, nil
 }
 
diff --git a/bazel/cquery/request_type_test.go b/bazel/cquery/request_type_test.go
index 48edb90..6369999 100644
--- a/bazel/cquery/request_type_test.go
+++ b/bazel/cquery/request_type_test.go
@@ -3,6 +3,7 @@
 import (
 	"fmt"
 	"reflect"
+	"strings"
 	"testing"
 )
 
@@ -45,42 +46,48 @@
 	}{
 		{
 			description: "no result",
-			input:       "||",
+			input:       "||||",
 			expectedOutput: CcInfo{
 				OutputFiles:          []string{},
 				CcObjectFiles:        []string{},
 				CcStaticLibraryFiles: []string{},
+				Includes:             []string{},
+				SystemIncludes:       []string{},
 			},
 		},
 		{
 			description: "only output",
-			input:       "test||",
+			input:       "test||||",
 			expectedOutput: CcInfo{
 				OutputFiles:          []string{"test"},
 				CcObjectFiles:        []string{},
 				CcStaticLibraryFiles: []string{},
+				Includes:             []string{},
+				SystemIncludes:       []string{},
 			},
 		},
 		{
 			description: "all items set",
-			input:       "out1, out2|static_lib1, static_lib2|object1, object2",
+			input:       "out1, out2|static_lib1, static_lib2|object1, object2|., dir/subdir|system/dir, system/other/dir",
 			expectedOutput: CcInfo{
 				OutputFiles:          []string{"out1", "out2"},
 				CcObjectFiles:        []string{"object1", "object2"},
 				CcStaticLibraryFiles: []string{"static_lib1", "static_lib2"},
+				Includes:             []string{".", "dir/subdir"},
+				SystemIncludes:       []string{"system/dir", "system/other/dir"},
 			},
 		},
 		{
 			description:          "too few result splits",
 			input:                "|",
 			expectedOutput:       CcInfo{},
-			expectedErrorMessage: fmt.Sprintf("Expected %d items, got %q", 3, []string{"", ""}),
+			expectedErrorMessage: fmt.Sprintf("Expected %d items, got %q", 5, []string{"", ""}),
 		},
 		{
 			description:          "too many result splits",
-			input:                "|||",
+			input:                strings.Repeat("|", 8),
 			expectedOutput:       CcInfo{},
-			expectedErrorMessage: fmt.Sprintf("Expected %d items, got %q", 3, []string{"", "", "", ""}),
+			expectedErrorMessage: fmt.Sprintf("Expected %d items, got %q", 5, make([]string, 9)),
 		},
 	}
 	for _, tc := range testCases {
diff --git a/bp2build/build_conversion_test.go b/bp2build/build_conversion_test.go
index 1ede442..21d7062 100644
--- a/bp2build/build_conversion_test.go
+++ b/bp2build/build_conversion_test.go
@@ -204,8 +204,9 @@
 
 func TestGenerateBazelTargetModules(t *testing.T) {
 	testCases := []struct {
-		bp                  string
-		expectedBazelTarget string
+		name                 string
+		bp                   string
+		expectedBazelTargets []string
 	}{
 		{
 			bp: `custom {
@@ -214,7 +215,7 @@
     string_prop: "a",
     bazel_module: { bp2build_available: true },
 }`,
-			expectedBazelTarget: `custom(
+			expectedBazelTargets: []string{`custom(
     name = "foo",
     string_list_prop = [
         "a",
@@ -222,6 +223,7 @@
     ],
     string_prop = "a",
 )`,
+			},
 		},
 		{
 			bp: `custom {
@@ -230,7 +232,7 @@
     string_prop: "a\t\n\r",
     bazel_module: { bp2build_available: true },
 }`,
-			expectedBazelTarget: `custom(
+			expectedBazelTargets: []string{`custom(
     name = "control_characters",
     string_list_prop = [
         "\t",
@@ -238,6 +240,77 @@
     ],
     string_prop = "a\t\n\r",
 )`,
+			},
+		},
+		{
+			bp: `custom {
+  name: "has_dep",
+  arch_paths: [":dep"],
+  bazel_module: { bp2build_available: true },
+}
+
+custom {
+  name: "dep",
+  arch_paths: ["abc"],
+  bazel_module: { bp2build_available: true },
+}`,
+			expectedBazelTargets: []string{`custom(
+    name = "dep",
+    arch_paths = ["abc"],
+)`,
+				`custom(
+    name = "has_dep",
+    arch_paths = [":dep"],
+)`,
+			},
+		},
+		{
+			bp: `custom {
+    name: "arch_paths",
+    arch: {
+      x86: {
+        arch_paths: ["abc"],
+      },
+    },
+    bazel_module: { bp2build_available: true },
+}`,
+			expectedBazelTargets: []string{`custom(
+    name = "arch_paths",
+    arch_paths = select({
+        "//build/bazel/platforms/arch:x86": ["abc"],
+        "//conditions:default": [],
+    }),
+)`,
+			},
+		},
+		{
+			bp: `custom {
+  name: "has_dep",
+  arch: {
+    x86: {
+      arch_paths: [":dep"],
+    },
+  },
+  bazel_module: { bp2build_available: true },
+}
+
+custom {
+    name: "dep",
+    arch_paths: ["abc"],
+    bazel_module: { bp2build_available: true },
+}`,
+			expectedBazelTargets: []string{`custom(
+    name = "dep",
+    arch_paths = ["abc"],
+)`,
+				`custom(
+    name = "has_dep",
+    arch_paths = select({
+        "//build/bazel/platforms/arch:x86": [":dep"],
+        "//conditions:default": [],
+    }),
+)`,
+			},
 		},
 	}
 
@@ -262,16 +335,18 @@
 		codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
 		bazelTargets := generateBazelTargetsForDir(codegenCtx, dir)
 
-		if actualCount, expectedCount := len(bazelTargets), 1; actualCount != expectedCount {
+		if actualCount, expectedCount := len(bazelTargets), len(testCase.expectedBazelTargets); actualCount != expectedCount {
 			t.Errorf("Expected %d bazel target, got %d", expectedCount, actualCount)
 		} else {
-			actualBazelTarget := bazelTargets[0]
-			if actualBazelTarget.content != testCase.expectedBazelTarget {
-				t.Errorf(
-					"Expected generated Bazel target to be '%s', got '%s'",
-					testCase.expectedBazelTarget,
-					actualBazelTarget.content,
-				)
+			for i, expectedBazelTarget := range testCase.expectedBazelTargets {
+				actualBazelTarget := bazelTargets[i]
+				if actualBazelTarget.content != expectedBazelTarget {
+					t.Errorf(
+						"Expected generated Bazel target to be '%s', got '%s'",
+						expectedBazelTarget,
+						actualBazelTarget.content,
+					)
+				}
 			}
 		}
 	}
diff --git a/bp2build/bzl_conversion_test.go b/bp2build/bzl_conversion_test.go
index 30c1a5b..32b12e4 100644
--- a/bp2build/bzl_conversion_test.go
+++ b/bp2build/bzl_conversion_test.go
@@ -86,6 +86,7 @@
         "soong_module_name": attr.string(mandatory = True),
         "soong_module_variant": attr.string(),
         "soong_module_deps": attr.label_list(providers = [SoongModuleInfo]),
+        "arch_paths": attr.string_list(),
         # bazel_module start
 #         "label": attr.string(),
 #         "bp2build_available": attr.bool(),
@@ -114,6 +115,7 @@
         "soong_module_name": attr.string(mandatory = True),
         "soong_module_variant": attr.string(),
         "soong_module_deps": attr.label_list(providers = [SoongModuleInfo]),
+        "arch_paths": attr.string_list(),
         "bool_prop": attr.bool(),
         "bool_ptr_prop": attr.bool(),
         "int64_ptr_prop": attr.int(),
@@ -138,6 +140,7 @@
         "soong_module_name": attr.string(mandatory = True),
         "soong_module_variant": attr.string(),
         "soong_module_deps": attr.label_list(providers = [SoongModuleInfo]),
+        "arch_paths": attr.string_list(),
         "bool_prop": attr.bool(),
         "bool_ptr_prop": attr.bool(),
         "int64_ptr_prop": attr.int(),
diff --git a/bp2build/testing.go b/bp2build/testing.go
index c4661ea..452f6ed 100644
--- a/bp2build/testing.go
+++ b/bp2build/testing.go
@@ -28,6 +28,8 @@
 
 	Nested_props     nestedProps
 	Nested_props_ptr *nestedProps
+
+	Arch_paths []string `android:"path,arch_variant"`
 }
 
 type customModule struct {
@@ -56,7 +58,7 @@
 
 func customModuleFactory() android.Module {
 	m := customModuleFactoryBase()
-	android.InitAndroidModule(m)
+	android.InitAndroidArchModule(m, android.HostAndDeviceSupported, android.MultilibBoth)
 	return m
 }
 
@@ -114,6 +116,7 @@
 type customBazelModuleAttributes struct {
 	String_prop      string
 	String_list_prop []string
+	Arch_paths       bazel.LabelListAttribute
 }
 
 type customBazelModule struct {
@@ -137,9 +140,18 @@
 			return
 		}
 
+		paths := bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrc(ctx, m.props.Arch_paths))
+
+		for arch, props := range m.GetArchProperties(&customProps{}) {
+			if archProps, ok := props.(*customProps); ok && archProps.Arch_paths != nil {
+				paths.SetValueForArch(arch.Name, android.BazelLabelForModuleSrc(ctx, archProps.Arch_paths))
+			}
+		}
+
 		attrs := &customBazelModuleAttributes{
 			String_prop:      m.props.String_prop,
 			String_list_prop: m.props.String_list_prop,
+			Arch_paths:       paths,
 		}
 
 		props := bazel.BazelTargetModuleProperties{
diff --git a/cc/androidmk.go b/cc/androidmk.go
index 536efa4..8f3a652 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -191,17 +191,31 @@
 }
 
 func (library *libraryDecorator) androidMkWriteExportedFlags(entries *android.AndroidMkEntries) {
-	exportedFlags := library.flagExporter.flags
-	for _, dir := range library.flagExporter.dirs {
+	var exportedFlags []string
+	var includeDirs android.Paths
+	var systemIncludeDirs android.Paths
+	var exportedDeps android.Paths
+
+	if library.flagExporterInfo != nil {
+		exportedFlags = library.flagExporterInfo.Flags
+		includeDirs = library.flagExporterInfo.IncludeDirs
+		systemIncludeDirs = library.flagExporterInfo.SystemIncludeDirs
+		exportedDeps = library.flagExporterInfo.Deps
+	} else {
+		exportedFlags = library.flagExporter.flags
+		includeDirs = library.flagExporter.dirs
+		systemIncludeDirs = library.flagExporter.systemDirs
+		exportedDeps = library.flagExporter.deps
+	}
+	for _, dir := range includeDirs {
 		exportedFlags = append(exportedFlags, "-I"+dir.String())
 	}
-	for _, dir := range library.flagExporter.systemDirs {
+	for _, dir := range systemIncludeDirs {
 		exportedFlags = append(exportedFlags, "-isystem "+dir.String())
 	}
 	if len(exportedFlags) > 0 {
 		entries.AddStrings("LOCAL_EXPORT_CFLAGS", exportedFlags...)
 	}
-	exportedDeps := library.flagExporter.deps
 	if len(exportedDeps) > 0 {
 		entries.AddStrings("LOCAL_EXPORT_C_INCLUDE_DEPS", exportedDeps.Strings()...)
 	}
diff --git a/cc/genrule.go b/cc/genrule.go
index 82d7205..ca4fda7 100644
--- a/cc/genrule.go
+++ b/cc/genrule.go
@@ -75,10 +75,6 @@
 	return Bool(g.Vendor_ramdisk_available)
 }
 
-func (g *GenruleExtraProperties) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
-	return false
-}
-
 func (g *GenruleExtraProperties) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool {
 	// If the build is using a snapshot, the recovery variant under AOSP directories
 	// is not needed.
diff --git a/cc/image.go b/cc/image.go
index bf662c6..c1e5dfe 100644
--- a/cc/image.go
+++ b/cc/image.go
@@ -601,10 +601,6 @@
 	return c.Properties.VendorRamdiskVariantNeeded
 }
 
-func (c *Module) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
-	return false
-}
-
 func (c *Module) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool {
 	return c.Properties.RecoveryVariantNeeded
 }
diff --git a/cc/library.go b/cc/library.go
index 8acd7c7..af92b24 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -426,7 +426,8 @@
 	tocFile android.OptionalPath
 
 	flagExporter
-	stripper Stripper
+	flagExporterInfo *FlagExporterInfo
+	stripper         Stripper
 
 	// For whole_static_libs
 	objects Objects
diff --git a/cc/library_headers.go b/cc/library_headers.go
index 078242f..f2cb52b 100644
--- a/cc/library_headers.go
+++ b/cc/library_headers.go
@@ -43,6 +43,52 @@
 	ctx.RegisterModuleType("cc_prebuilt_library_headers", prebuiltLibraryHeaderFactory)
 }
 
+type libraryHeaderBazelHander struct {
+	bazelHandler
+
+	module  *Module
+	library *libraryDecorator
+}
+
+func (h *libraryHeaderBazelHander) generateBazelBuildActions(ctx android.ModuleContext, label string) bool {
+	bazelCtx := ctx.Config().BazelContext
+	ccInfo, ok, err := bazelCtx.GetCcInfo(label, ctx.Arch().ArchType)
+	if err != nil {
+		ctx.ModuleErrorf("Error getting Bazel CcInfo: %s", err)
+		return false
+	}
+	if !ok {
+		return false
+	}
+
+	outputPaths := ccInfo.OutputFiles
+	if len(outputPaths) != 1 {
+		ctx.ModuleErrorf("expected exactly one output file for %q, but got %q", label, outputPaths)
+		return false
+	}
+
+	outputPath := android.PathForBazelOut(ctx, outputPaths[0])
+	h.module.outputFile = android.OptionalPathForPath(outputPath)
+
+	// HeaderLibraryInfo is an empty struct to indicate to dependencies that this is a header library
+	ctx.SetProvider(HeaderLibraryInfoProvider, HeaderLibraryInfo{})
+
+	flagExporterInfo := flagExporterInfoFromCcInfo(ctx, ccInfo)
+	// Store flag info to be passed along to androimk
+	// TODO(b/184387147): Androidmk should be done in Bazel, not Soong.
+	h.library.flagExporterInfo = &flagExporterInfo
+	// flag exporters consolidates properties like includes, flags, dependencies that should be
+	// exported from this module to other modules
+	ctx.SetProvider(FlagExporterInfoProvider, flagExporterInfo)
+
+	// Dependencies on this library will expect collectedSnapshotHeaders to be set, otherwise
+	// validation will fail. For now, set this to an empty list.
+	// TODO(cparsons): More closely mirror the collectHeadersForSnapshot implementation.
+	h.library.collectedSnapshotHeaders = android.Paths{}
+
+	return true
+}
+
 // cc_library_headers contains a set of c/c++ headers which are imported by
 // other soong cc modules using the header_libs property. For best practices,
 // use export_include_dirs property or LOCAL_EXPORT_C_INCLUDE_DIRS for
@@ -51,6 +97,7 @@
 	module, library := NewLibrary(android.HostAndDeviceSupported)
 	library.HeaderOnly()
 	module.sdkMemberTypes = []android.SdkMemberType{headersLibrarySdkMemberType}
+	module.bazelHandler = &libraryHeaderBazelHander{module: module, library: library}
 	return module.Init()
 }
 
diff --git a/cc/library_sdk_member.go b/cc/library_sdk_member.go
index d5f2adf..9010a1a 100644
--- a/cc/library_sdk_member.go
+++ b/cc/library_sdk_member.go
@@ -162,9 +162,16 @@
 	return &nativeLibInfoProperties{memberType: mt}
 }
 
+func isBazelOutDirectory(p android.Path) bool {
+	_, bazel := p.(android.BazelOutPath)
+	return bazel
+}
+
 func isGeneratedHeaderDirectory(p android.Path) bool {
 	_, gen := p.(android.WritablePath)
-	return gen
+	// TODO(b/183213331): Here we assume that bazel-based headers are not generated; we need
+	// to support generated headers in mixed builds.
+	return gen && !isBazelOutDirectory(p)
 }
 
 type includeDirsProperty struct {
diff --git a/cc/linkable.go b/cc/linkable.go
index 0fb9c09..2fa12f6 100644
--- a/cc/linkable.go
+++ b/cc/linkable.go
@@ -2,6 +2,7 @@
 
 import (
 	"android/soong/android"
+	"android/soong/bazel/cquery"
 
 	"github.com/google/blueprint"
 )
@@ -274,3 +275,15 @@
 }
 
 var FlagExporterInfoProvider = blueprint.NewProvider(FlagExporterInfo{})
+
+// flagExporterInfoFromCcInfo populates FlagExporterInfo provider with information from Bazel.
+func flagExporterInfoFromCcInfo(ctx android.ModuleContext, ccInfo cquery.CcInfo) FlagExporterInfo {
+
+	includes := android.PathsForBazelOut(ctx, ccInfo.Includes)
+	systemIncludes := android.PathsForBazelOut(ctx, ccInfo.SystemIncludes)
+
+	return FlagExporterInfo{
+		IncludeDirs:       includes,
+		SystemIncludeDirs: systemIncludes,
+	}
+}
diff --git a/cc/snapshot_prebuilt.go b/cc/snapshot_prebuilt.go
index 885a0ce..c12ad79 100644
--- a/cc/snapshot_prebuilt.go
+++ b/cc/snapshot_prebuilt.go
@@ -308,10 +308,6 @@
 	return false
 }
 
-func (s *snapshot) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
-	return false
-}
-
 func (s *snapshot) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool {
 	return false
 }
diff --git a/etc/prebuilt_etc.go b/etc/prebuilt_etc.go
index 3204e70..6e502b7 100644
--- a/etc/prebuilt_etc.go
+++ b/etc/prebuilt_etc.go
@@ -84,13 +84,6 @@
 	// the recovery variant instead.
 	Vendor_ramdisk_available *bool
 
-	// Make this module available when building for debug ramdisk.
-	// On device without a dedicated recovery partition, the module is only
-	// available after switching root into
-	// /first_stage_ramdisk. To expose the module before switching root, install
-	// the recovery variant instead.
-	Debug_ramdisk_available *bool
-
 	// Make this module available when building for recovery.
 	Recovery_available *bool
 
@@ -166,18 +159,6 @@
 	return p.inVendorRamdisk()
 }
 
-func (p *PrebuiltEtc) inDebugRamdisk() bool {
-	return p.ModuleBase.InDebugRamdisk() || p.ModuleBase.InstallInDebugRamdisk()
-}
-
-func (p *PrebuiltEtc) onlyInDebugRamdisk() bool {
-	return p.ModuleBase.InstallInDebugRamdisk()
-}
-
-func (p *PrebuiltEtc) InstallInDebugRamdisk() bool {
-	return p.inDebugRamdisk()
-}
-
 func (p *PrebuiltEtc) inRecovery() bool {
 	return p.ModuleBase.InRecovery() || p.ModuleBase.InstallInRecovery()
 }
@@ -196,7 +177,7 @@
 
 func (p *PrebuiltEtc) CoreVariantNeeded(ctx android.BaseModuleContext) bool {
 	return !p.ModuleBase.InstallInRecovery() && !p.ModuleBase.InstallInRamdisk() &&
-		!p.ModuleBase.InstallInVendorRamdisk() && !p.ModuleBase.InstallInDebugRamdisk()
+		!p.ModuleBase.InstallInVendorRamdisk()
 }
 
 func (p *PrebuiltEtc) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
@@ -207,10 +188,6 @@
 	return proptools.Bool(p.properties.Vendor_ramdisk_available) || p.ModuleBase.InstallInVendorRamdisk()
 }
 
-func (p *PrebuiltEtc) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
-	return proptools.Bool(p.properties.Debug_ramdisk_available) || p.ModuleBase.InstallInDebugRamdisk()
-}
-
 func (p *PrebuiltEtc) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool {
 	return proptools.Bool(p.properties.Recovery_available) || p.ModuleBase.InstallInRecovery()
 }
@@ -336,9 +313,6 @@
 	if p.inVendorRamdisk() && !p.onlyInVendorRamdisk() {
 		nameSuffix = ".vendor_ramdisk"
 	}
-	if p.inDebugRamdisk() && !p.onlyInDebugRamdisk() {
-		nameSuffix = ".debug_ramdisk"
-	}
 	if p.inRecovery() && !p.onlyInRecovery() {
 		nameSuffix = ".recovery"
 	}
diff --git a/genrule/genrule.go b/genrule/genrule.go
index 77dae75..b426b20 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -626,7 +626,6 @@
 func (x noopImageInterface) CoreVariantNeeded(android.BaseModuleContext) bool            { return false }
 func (x noopImageInterface) RamdiskVariantNeeded(android.BaseModuleContext) bool         { return false }
 func (x noopImageInterface) VendorRamdiskVariantNeeded(android.BaseModuleContext) bool   { return false }
-func (x noopImageInterface) DebugRamdiskVariantNeeded(android.BaseModuleContext) bool    { return false }
 func (x noopImageInterface) RecoveryVariantNeeded(android.BaseModuleContext) bool        { return false }
 func (x noopImageInterface) ExtraImageVariations(ctx android.BaseModuleContext) []string { return nil }
 func (x noopImageInterface) SetImageVariation(ctx android.BaseModuleContext, variation string, module android.Module) {
diff --git a/java/boot_image.go b/java/boot_image.go
index d0862a9..6f50c27 100644
--- a/java/boot_image.go
+++ b/java/boot_image.go
@@ -124,8 +124,22 @@
 	if m.properties.Image_name != nil && len(contents) != 0 {
 		ctx.ModuleErrorf(`both of the "image_name" and "contents" properties have been supplied, please supply exactly one`)
 	}
+
 	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() != "" {
+			// 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
+			//    the versioned prebuilt depending on the unversioned prebuilt. That will cause problems
+			//    as the unversioned prebuilt could end up with an APEX variant created for the source
+			//    APEX which will prevent it from having an APEX variant for the prebuilt APEX which in
+			//    turn will prevent it from accessing the dex implementation jar from that which will
+			//    break hidden API processing, amongst others.
+			return
+		}
+
 		// Get the configuration for the art apex jars. Do not use getImageConfig(ctx) here as this is
 		// too early in the Soong processing for that to work.
 		global := dexpreopt.GetGlobalConfig(ctx)
diff --git a/java/dexpreopt_config.go b/java/dexpreopt_config.go
index 656f5ef..0ab6502 100644
--- a/java/dexpreopt_config.go
+++ b/java/dexpreopt_config.go
@@ -236,9 +236,5 @@
 }
 
 func dexpreoptConfigMakevars(ctx android.MakeVarsContext) {
-	ctx.Strict("PRODUCT_BOOTCLASSPATH", strings.Join(defaultBootclasspath(ctx), ":"))
-	ctx.Strict("PRODUCT_DEX2OAT_BOOTCLASSPATH", strings.Join(defaultBootImageConfig(ctx).getAnyAndroidVariant().dexLocationsDeps, ":"))
-	ctx.Strict("PRODUCT_SYSTEM_SERVER_CLASSPATH", strings.Join(systemServerClasspath(ctx), ":"))
-
 	ctx.Strict("DEXPREOPT_BOOT_JARS_MODULES", strings.Join(defaultBootImageConfig(ctx).modules.CopyOfApexJarPairs(), ":"))
 }
diff --git a/java/lint.go b/java/lint.go
index 862c9b4..5e39274 100644
--- a/java/lint.go
+++ b/java/lint.go
@@ -261,6 +261,7 @@
 	cmd.FlagForEachArg("--fatal_check ", l.properties.Lint.Fatal_checks)
 
 	if BoolDefault(l.properties.Lint.Strict_updatability_linting, false) {
+		// Verify the module does not baseline issues that endanger safe updatability.
 		if baselinePath := l.getBaselineFilepath(ctx); baselinePath.Valid() {
 			cmd.FlagWithInput("--baseline ", baselinePath.Path())
 			cmd.FlagForEachArg("--disallowed_issues ", updatabilityChecks)
diff --git a/rust/image.go b/rust/image.go
index 900842e..7eb49d9 100644
--- a/rust/image.go
+++ b/rust/image.go
@@ -97,10 +97,6 @@
 	return mod.InRamdisk()
 }
 
-func (mod *Module) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
-	return false
-}
-
 func (mod *Module) RecoveryVariantNeeded(android.BaseModuleContext) bool {
 	return mod.InRecovery()
 }
diff --git a/scripts/lint_project_xml.py b/scripts/lint_project_xml.py
index 74aebc1..3b0158d 100755
--- a/scripts/lint_project_xml.py
+++ b/scripts/lint_project_xml.py
@@ -144,12 +144,12 @@
   if issues_element.tagName != 'issues':
     raise RuntimeError('expected issues tag at root')
   issues = issues_element.getElementsByTagName('issue')
-  disallwed = set()
+  disallowed = set()
   for issue in issues:
     id = issue.getAttribute('id')
     if id in forced_checks:
-      disallwed.add(id)
-  return disallwed
+      disallowed.add(id)
+  return disallowed
 
 
 def main():
@@ -158,10 +158,10 @@
 
   if args.baseline_path:
     baseline = minidom.parse(args.baseline_path)
-    diallowed_issues = check_baseline_for_disallowed_issues(baseline, args.disallowed_issues)
-    if bool(diallowed_issues):
+    disallowed_issues = check_baseline_for_disallowed_issues(baseline, args.disallowed_issues)
+    if bool(disallowed_issues):
       raise RuntimeError('disallowed issues %s found in lint baseline file %s for module %s'
-                         % (diallowed_issues, args.baseline_path, args.name))
+                         % (disallowed_issues, args.baseline_path, args.name))
 
   if args.project_out:
     with open(args.project_out, 'w') as f:
diff --git a/sdk/bootclasspath_fragment_sdk_test.go b/sdk/bootclasspath_fragment_sdk_test.go
index 0ce4351..ef4d7cd 100644
--- a/sdk/bootclasspath_fragment_sdk_test.go
+++ b/sdk/bootclasspath_fragment_sdk_test.go
@@ -24,6 +24,7 @@
 func TestSnapshotWithBootclasspathFragment_ImageName(t *testing.T) {
 	result := android.GroupFixturePreparers(
 		prepareForSdkTestWithJava,
+		java.PrepareForTestWithJavaDefaultModules,
 		prepareForSdkTestWithApex,
 
 		// Some additional files needed for the art apex.
@@ -32,6 +33,20 @@
 			"com.android.art.pem":                                nil,
 			"system/sepolicy/apex/com.android.art-file_contexts": nil,
 		}),
+
+		// platform_bootclasspath that depends on the fragment.
+		android.FixtureAddTextFile("frameworks/base/boot/Android.bp", `
+			platform_bootclasspath {
+				name: "platform-bootclasspath",
+				fragments: [
+					{
+						apex: "com.android.art",
+						module: "mybootclasspathfragment",
+					},
+				],
+			}
+		`),
+
 		java.FixtureConfigureBootJars("com.android.art:mybootlib"),
 		android.FixtureWithRootAndroidBp(`
 			sdk {
@@ -72,6 +87,23 @@
 		`),
 	).RunTest(t)
 
+	// A preparer to add a prebuilt apex to the test fixture.
+	prepareWithPrebuiltApex := android.GroupFixturePreparers(
+		android.FixtureAddTextFile("prebuilts/apex/Android.bp", `
+				prebuilt_apex {
+					name: "com.android.art",
+					src: "art.apex",
+					exported_java_libs: [
+						"mybootlib",
+					],
+					exported_bootclasspath_fragments: [
+						"mybootclasspathfragment",
+					],
+				}
+			`),
+		android.FixtureAddFile("prebuilts/apex/art.apex", nil),
+	)
+
 	CheckSnapshot(t, result, "mysdk", "",
 		checkUnversionedAndroidBpContents(`
 // This is auto-generated. DO NOT EDIT.
@@ -121,19 +153,9 @@
 		checkAllCopyRules(`
 .intermediates/mybootlib/android_common/javac/mybootlib.jar -> java/mybootlib.jar
 `),
-		snapshotTestPreparer(checkSnapshotPreferredWithSource, android.GroupFixturePreparers(
-			android.FixtureAddTextFile("prebuilts/apex/Android.bp", `
-				prebuilt_apex {
-					name: "com.android.art",
-					src: "art.apex",
-					exported_java_libs: [
-						"mybootlib",
-					],
-				}
-			`),
-			android.FixtureAddFile("prebuilts/apex/art.apex", nil),
-		),
-		),
+		snapshotTestPreparer(checkSnapshotWithoutSource, prepareWithPrebuiltApex),
+		snapshotTestPreparer(checkSnapshotWithSourcePreferred, prepareWithPrebuiltApex),
+		snapshotTestPreparer(checkSnapshotPreferredWithSource, prepareWithPrebuiltApex),
 	)
 }
 
diff --git a/sdk/testing.go b/sdk/testing.go
index bf59aed..f4e85c0 100644
--- a/sdk/testing.go
+++ b/sdk/testing.go
@@ -254,6 +254,7 @@
 	snapshotPreparer := android.GroupFixturePreparers(sourcePreparers, fs.AddToFixture())
 
 	var runSnapshotTestWithCheckers = func(t *testing.T, testConfig snapshotTest, extraPreparer android.FixturePreparer) {
+		t.Helper()
 		customization := snapshotBuildInfo.snapshotTestCustomization(testConfig)
 		customizedPreparers := android.GroupFixturePreparers(customization.preparers...)
 
diff --git a/sh/sh_binary.go b/sh/sh_binary.go
index 42d5680..6623381 100644
--- a/sh/sh_binary.go
+++ b/sh/sh_binary.go
@@ -210,10 +210,6 @@
 	return proptools.Bool(s.properties.Vendor_ramdisk_available) || s.ModuleBase.InstallInVendorRamdisk()
 }
 
-func (s *ShBinary) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
-	return false
-}
-
 func (s *ShBinary) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool {
 	return proptools.Bool(s.properties.Recovery_available) || s.ModuleBase.InstallInRecovery()
 }