Merge "Use trimmed lint database for mainline modules" into sc-dev
diff --git a/android/sdk.go b/android/sdk.go
index e644806..42c8ffa 100644
--- a/android/sdk.go
+++ b/android/sdk.go
@@ -359,6 +359,8 @@
 
 	// SdkMemberType returns the SdkMemberType that will be used to automatically add the child module
 	// to the sdk.
+	//
+	// Returning nil will prevent the module being added to the sdk.
 	SdkMemberType(child Module) SdkMemberType
 
 	// ExportMember determines whether a module added to the sdk through this tag will be exported
diff --git a/apex/apex.go b/apex/apex.go
index e731702..bea54bc 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -177,6 +177,12 @@
 	// used in tests.
 	Test_only_force_compression *bool
 
+	// Canonical name of this APEX bundle. Used to determine the path to the
+	// activated APEX on device (i.e. /apex/<apexVariationName>), and used for the
+	// apex mutator variations. For override_apex modules, this is the name of the
+	// overridden base module.
+	ApexVariationName string `blueprint:"mutated"`
+
 	IsCoverageVariant bool `blueprint:"mutated"`
 
 	// List of sanitizer names that this APEX is enabled for
@@ -808,6 +814,10 @@
 
 var _ ApexInfoMutator = (*apexBundle)(nil)
 
+func (a *apexBundle) ApexVariationName() string {
+	return a.properties.ApexVariationName
+}
+
 // ApexInfoMutator is responsible for collecting modules that need to have apex variants. They are
 // identified by doing a graph walk starting from an apexBundle. Basically, all the (direct and
 // indirect) dependencies are collected. But a few types of modules that shouldn't be included in
@@ -896,15 +906,15 @@
 	// This is the main part of this mutator. Mark the collected dependencies that they need to
 	// be built for this apexBundle.
 
-	// Note that there are many different names.
-	// ApexVariationName: this is the name of the apex variation
+	apexVariationName := proptools.StringDefault(a.properties.Apex_name, mctx.ModuleName()) // could be com.android.foo
+	a.properties.ApexVariationName = apexVariationName
 	apexInfo := android.ApexInfo{
-		ApexVariationName: mctx.ModuleName(), // could be com.android.foo
+		ApexVariationName: apexVariationName,
 		MinSdkVersion:     minSdkVersion,
 		RequiredSdks:      a.RequiredSdks(),
 		Updatable:         a.Updatable(),
-		InApexVariants:    []string{mctx.ModuleName()}, // could be com.android.foo
-		InApexModules:     []string{a.Name()},          // could be com.mycompany.android.foo
+		InApexVariants:    []string{apexVariationName},
+		InApexModules:     []string{a.Name()}, // could be com.mycompany.android.foo
 		ApexContents:      []*android.ApexContents{apexContents},
 	}
 	mctx.WalkDeps(func(child, parent android.Module) bool {
@@ -917,6 +927,10 @@
 }
 
 type ApexInfoMutator interface {
+	// ApexVariationName returns the name of the APEX variation to use in the apex
+	// mutator etc. It is the same name as ApexInfo.ApexVariationName.
+	ApexVariationName() string
+
 	// ApexInfoMutator implementations must call BuildForApex(ApexInfo) on any modules that are
 	// depended upon by an apex and which require an apex specific variant.
 	ApexInfoMutator(android.TopDownMutatorContext)
@@ -1042,10 +1056,8 @@
 	}
 
 	// apexBundle itself is mutated so that it and its dependencies have the same apex variant.
-	// TODO(jiyong): document the reason why the VNDK APEX is an exception here.
-	unprefixedModuleName := android.RemoveOptionalPrebuiltPrefix(mctx.ModuleName())
-	if apexModuleTypeRequiresVariant(mctx.Module()) {
-		apexBundleName := unprefixedModuleName
+	if ai, ok := mctx.Module().(ApexInfoMutator); ok && apexModuleTypeRequiresVariant(ai) {
+		apexBundleName := ai.ApexVariationName()
 		mctx.CreateVariations(apexBundleName)
 		if strings.HasPrefix(apexBundleName, "com.android.art") {
 			// Create an alias from the platform variant. This is done to make
@@ -1068,6 +1080,7 @@
 		// apex variant name. This name matches the name used to create the variations of modules for
 		// which apexModuleTypeRequiresVariant return true.
 		// TODO(b/191269918): Remove this workaround.
+		unprefixedModuleName := android.RemoveOptionalPrebuiltPrefix(mctx.ModuleName())
 		mctx.SetDefaultDependencyVariation(&unprefixedModuleName)
 		mctx.CreateVariations(apexBundleName)
 		if strings.HasPrefix(apexBundleName, "com.android.art") {
@@ -1079,18 +1092,13 @@
 
 // apexModuleTypeRequiresVariant determines whether the module supplied requires an apex specific
 // variant.
-func apexModuleTypeRequiresVariant(module android.Module) bool {
+func apexModuleTypeRequiresVariant(module ApexInfoMutator) bool {
 	if a, ok := module.(*apexBundle); ok {
+		// TODO(jiyong): document the reason why the VNDK APEX is an exception here.
 		return !a.vndkApex
 	}
 
-	// Match apex_set and prebuilt_apex. Would also match apexBundle but that is handled specially
-	// above.
-	if _, ok := module.(ApexInfoMutator); ok {
-		return true
-	}
-
-	return false
+	return true
 }
 
 // See android.UpdateDirectlyInAnyApex
diff --git a/apex/apex_test.go b/apex/apex_test.go
index c50c4a9..4829029 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -3670,13 +3670,13 @@
 		}
 	`)
 
-	module := ctx.ModuleForTests("myapex", "android_common_myapex_image")
+	module := ctx.ModuleForTests("myapex", "android_common_com.android.myapex_image")
 	apexManifestRule := module.Rule("apexManifestRule")
 	ensureContains(t, apexManifestRule.Args["opt"], "-v name com.android.myapex")
 	apexRule := module.Rule("apexRule")
 	ensureContains(t, apexRule.Args["opt_flags"], "--do_not_check_keyname")
 
-	apexBundle := ctx.ModuleForTests("myapex", "android_common_myapex_image").Module().(*apexBundle)
+	apexBundle := module.Module().(*apexBundle)
 	data := android.AndroidMkDataForTest(t, ctx, apexBundle)
 	name := apexBundle.BaseModuleName()
 	prefix := "TARGET_"
@@ -4219,6 +4219,59 @@
 	}
 }
 
+func TestPrebuiltApexName(t *testing.T) {
+	testApex(t, `
+		prebuilt_apex {
+			name: "com.company.android.myapex",
+			apex_name: "com.android.myapex",
+			src: "company-myapex-arm.apex",
+		}
+	`).ModuleForTests("com.company.android.myapex", "android_common_com.android.myapex")
+
+	testApex(t, `
+		apex_set {
+			name: "com.company.android.myapex",
+			apex_name: "com.android.myapex",
+			set: "company-myapex.apks",
+		}
+	`).ModuleForTests("com.company.android.myapex", "android_common_com.android.myapex")
+}
+
+func TestPrebuiltApexNameWithPlatformBootclasspath(t *testing.T) {
+	_ = android.GroupFixturePreparers(
+		java.PrepareForTestWithJavaDefaultModules,
+		PrepareForTestWithApexBuildComponents,
+		android.FixtureWithRootAndroidBp(`
+			platform_bootclasspath {
+				name: "platform-bootclasspath",
+				fragments: [
+					{
+						apex: "com.android.art",
+						module: "art-bootclasspath-fragment",
+					},
+				],
+			}
+
+			prebuilt_apex {
+				name: "com.company.android.art",
+				apex_name: "com.android.art",
+				src: "com.company.android.art-arm.apex",
+				exported_bootclasspath_fragments: ["art-bootclasspath-fragment"],
+			}
+
+			prebuilt_bootclasspath_fragment {
+				name: "art-bootclasspath-fragment",
+				contents: ["core-oj"],
+			}
+
+			java_import {
+				name: "core-oj",
+				jars: ["prebuilt.jar"],
+			}
+		`),
+	).RunTest(t)
+}
+
 // These tests verify that the prebuilt_apex/deapexer to java_import wiring allows for the
 // propagation of paths to dex implementation jars from the former to the latter.
 func TestPrebuiltExportDexImplementationJars(t *testing.T) {
diff --git a/apex/bootclasspath_fragment_test.go b/apex/bootclasspath_fragment_test.go
index 66bc9e0..8554c19 100644
--- a/apex/bootclasspath_fragment_test.go
+++ b/apex/bootclasspath_fragment_test.go
@@ -22,6 +22,7 @@
 
 	"android/soong/android"
 	"android/soong/java"
+	"github.com/google/blueprint/proptools"
 )
 
 // Contains tests for bootclasspath_fragment logic from java/bootclasspath_fragment.go as the ART
@@ -216,9 +217,9 @@
 `,
 	)
 
-	checkSdkKindStubs := func(message string, info java.HiddenAPIInfo, kind android.SdkKind, expectedPaths ...string) {
+	checkAPIScopeStubs := func(message string, info java.HiddenAPIInfo, apiScope *java.HiddenAPIScope, expectedPaths ...string) {
 		t.Helper()
-		android.AssertPathsRelativeToTopEquals(t, fmt.Sprintf("%s %s", message, kind), expectedPaths, info.TransitiveStubDexJarsByKind[kind])
+		android.AssertPathsRelativeToTopEquals(t, fmt.Sprintf("%s %s", message, apiScope), expectedPaths, info.TransitiveStubDexJarsByScope[apiScope])
 	}
 
 	// Check stub dex paths exported by art.
@@ -229,10 +230,10 @@
 	bazSystemStubs := "out/soong/.intermediates/baz.stubs.system/android_common/dex/baz.stubs.system.jar"
 	bazTestStubs := "out/soong/.intermediates/baz.stubs.test/android_common/dex/baz.stubs.test.jar"
 
-	checkSdkKindStubs("art", artInfo, android.SdkPublic, bazPublicStubs)
-	checkSdkKindStubs("art", artInfo, android.SdkSystem, bazSystemStubs)
-	checkSdkKindStubs("art", artInfo, android.SdkTest, bazTestStubs)
-	checkSdkKindStubs("art", artInfo, android.SdkCorePlatform)
+	checkAPIScopeStubs("art", artInfo, java.PublicHiddenAPIScope, bazPublicStubs)
+	checkAPIScopeStubs("art", artInfo, java.SystemHiddenAPIScope, bazSystemStubs)
+	checkAPIScopeStubs("art", artInfo, java.TestHiddenAPIScope, bazTestStubs)
+	checkAPIScopeStubs("art", artInfo, java.CorePlatformHiddenAPIScope)
 
 	// Check stub dex paths exported by other.
 	otherFragment := result.Module("other-bootclasspath-fragment", "android_common")
@@ -241,10 +242,10 @@
 	fooPublicStubs := "out/soong/.intermediates/foo.stubs/android_common/dex/foo.stubs.jar"
 	fooSystemStubs := "out/soong/.intermediates/foo.stubs.system/android_common/dex/foo.stubs.system.jar"
 
-	checkSdkKindStubs("other", otherInfo, android.SdkPublic, bazPublicStubs, fooPublicStubs)
-	checkSdkKindStubs("other", otherInfo, android.SdkSystem, bazSystemStubs, fooSystemStubs)
-	checkSdkKindStubs("other", otherInfo, android.SdkTest, bazTestStubs, fooSystemStubs)
-	checkSdkKindStubs("other", otherInfo, android.SdkCorePlatform)
+	checkAPIScopeStubs("other", otherInfo, java.PublicHiddenAPIScope, bazPublicStubs, fooPublicStubs)
+	checkAPIScopeStubs("other", otherInfo, java.SystemHiddenAPIScope, bazSystemStubs, fooSystemStubs)
+	checkAPIScopeStubs("other", otherInfo, java.TestHiddenAPIScope, bazTestStubs, fooSystemStubs)
+	checkAPIScopeStubs("other", otherInfo, java.CorePlatformHiddenAPIScope)
 }
 
 func checkBootclasspathFragment(t *testing.T, result *android.TestResult, moduleName, variantName string, expectedConfiguredModules string, expectedBootclasspathFragmentFiles string) {
@@ -718,4 +719,480 @@
 	checkFragmentExportedDexJar("bar", "out/soong/.intermediates/mybootclasspathfragment/android_common_apex10000/hiddenapi-modular/encoded/bar.jar")
 }
 
+func getDexJarPath(result *android.TestResult, name string) string {
+	module := result.Module(name, "android_common")
+	return module.(java.UsesLibraryDependency).DexJarBuildPath().RelativeToTop().String()
+}
+
+// TestBootclasspathFragment_HiddenAPIList checks to make sure that the correct parameters are
+// passed to the hiddenapi list tool.
+func TestBootclasspathFragment_HiddenAPIList(t *testing.T) {
+	result := android.GroupFixturePreparers(
+		prepareForTestWithBootclasspathFragment,
+		prepareForTestWithArtApex,
+		prepareForTestWithMyapex,
+		// Configure bootclasspath jars to ensure that hidden API encoding is performed on them.
+		java.FixtureConfigureBootJars("com.android.art:baz", "com.android.art:quuz"),
+		java.FixtureConfigureUpdatableBootJars("myapex:foo", "myapex:bar"),
+		// Make sure that the frameworks/base/Android.bp file exists as otherwise hidden API encoding
+		// is disabled.
+		android.FixtureAddTextFile("frameworks/base/Android.bp", ""),
+
+		java.PrepareForTestWithJavaSdkLibraryFiles,
+		java.FixtureWithLastReleaseApis("foo", "quuz"),
+	).RunTestWithBp(t, `
+		apex {
+			name: "com.android.art",
+			key: "com.android.art.key",
+			bootclasspath_fragments: ["art-bootclasspath-fragment"],
+			updatable: false,
+		}
+
+		apex_key {
+			name: "com.android.art.key",
+			public_key: "com.android.art.avbpubkey",
+			private_key: "com.android.art.pem",
+		}
+
+		java_library {
+			name: "baz",
+			apex_available: [
+				"com.android.art",
+			],
+			srcs: ["b.java"],
+			compile_dex: true,
+		}
+
+		java_sdk_library {
+			name: "quuz",
+			apex_available: [
+				"com.android.art",
+			],
+			srcs: ["b.java"],
+			compile_dex: true,
+			public: {enabled: true},
+			system: {enabled: true},
+			test: {enabled: true},
+			module_lib: {enabled: true},
+		}
+
+		bootclasspath_fragment {
+			name: "art-bootclasspath-fragment",
+			image_name: "art",
+			// Must match the "com.android.art:" entries passed to FixtureConfigureBootJars above.
+			contents: ["baz", "quuz"],
+			apex_available: [
+				"com.android.art",
+			],
+		}
+
+		apex {
+			name: "myapex",
+			key: "myapex.key",
+			bootclasspath_fragments: [
+				"mybootclasspathfragment",
+			],
+			updatable: false,
+		}
+
+		apex_key {
+			name: "myapex.key",
+			public_key: "testkey.avbpubkey",
+			private_key: "testkey.pem",
+		}
+
+		java_sdk_library {
+			name: "foo",
+			srcs: ["b.java"],
+			shared_library: false,
+			public: {enabled: true},
+			apex_available: [
+				"myapex",
+			],
+		}
+
+		java_library {
+			name: "bar",
+			srcs: ["b.java"],
+			installable: true,
+			apex_available: [
+				"myapex",
+			],
+		}
+
+		bootclasspath_fragment {
+			name: "mybootclasspathfragment",
+			contents: [
+				"foo",
+				"bar",
+			],
+			apex_available: [
+				"myapex",
+			],
+			fragments: [
+				{
+					apex: "com.android.art",
+					module: "art-bootclasspath-fragment",
+				},
+			],
+		}
+	`)
+
+	java.CheckModuleDependencies(t, result.TestContext, "mybootclasspathfragment", "android_common_apex10000", []string{
+		"art-bootclasspath-fragment",
+		"bar",
+		"dex2oatd",
+		"foo",
+	})
+
+	fooStubs := getDexJarPath(result, "foo.stubs")
+	quuzPublicStubs := getDexJarPath(result, "quuz.stubs")
+	quuzSystemStubs := getDexJarPath(result, "quuz.stubs.system")
+	quuzTestStubs := getDexJarPath(result, "quuz.stubs.test")
+	quuzModuleLibStubs := getDexJarPath(result, "quuz.stubs.module_lib")
+
+	// Make sure that the fragment uses the quuz stub dex jars when generating the hidden API flags.
+	fragment := result.ModuleForTests("mybootclasspathfragment", "android_common_apex10000")
+
+	rule := fragment.Rule("modularHiddenAPIStubFlagsFile")
+	command := rule.RuleParams.Command
+	android.AssertStringDoesContain(t, "check correct rule", command, "hiddenapi list")
+
+	// Make sure that the quuz stubs are available for resolving references from the implementation
+	// boot dex jars provided by this module.
+	android.AssertStringDoesContain(t, "quuz widest", command, "--dependency-stub-dex="+quuzModuleLibStubs)
+
+	// Make sure that the quuz stubs are available for resolving references from the different API
+	// stubs provided by this module.
+	android.AssertStringDoesContain(t, "public", command, "--public-stub-classpath="+quuzPublicStubs+":"+fooStubs)
+	android.AssertStringDoesContain(t, "system", command, "--system-stub-classpath="+quuzSystemStubs+":"+fooStubs)
+	android.AssertStringDoesContain(t, "test", command, "--test-stub-classpath="+quuzTestStubs+":"+fooStubs)
+}
+
+// TestBootclasspathFragment_AndroidNonUpdatable checks to make sure that setting
+// additional_stubs: ["android-non-updatable"] causes the source android-non-updatable modules to be
+// added to the hiddenapi list tool.
+func TestBootclasspathFragment_AndroidNonUpdatable(t *testing.T) {
+	result := android.GroupFixturePreparers(
+		prepareForTestWithBootclasspathFragment,
+		prepareForTestWithArtApex,
+		prepareForTestWithMyapex,
+		// Configure bootclasspath jars to ensure that hidden API encoding is performed on them.
+		java.FixtureConfigureBootJars("com.android.art:baz", "com.android.art:quuz", "myapex:foo", "myapex:bar"),
+		// Make sure that the frameworks/base/Android.bp file exists as otherwise hidden API encoding
+		// is disabled.
+		android.FixtureAddTextFile("frameworks/base/Android.bp", ""),
+
+		java.PrepareForTestWithJavaSdkLibraryFiles,
+		java.FixtureWithLastReleaseApis("foo", "android-non-updatable"),
+	).RunTestWithBp(t, `
+		java_sdk_library {
+			name: "android-non-updatable",
+			srcs: ["b.java"],
+			compile_dex: true,
+			public: {
+				enabled: true,
+			},
+			system: {
+				enabled: true,
+			},
+			test: {
+				enabled: true,
+			},
+			module_lib: {
+				enabled: true,
+			},
+		}
+
+		apex {
+			name: "com.android.art",
+			key: "com.android.art.key",
+			bootclasspath_fragments: ["art-bootclasspath-fragment"],
+ 			java_libs: [
+				"baz",
+				"quuz",
+			],
+			updatable: false,
+		}
+
+		apex_key {
+			name: "com.android.art.key",
+			public_key: "com.android.art.avbpubkey",
+			private_key: "com.android.art.pem",
+		}
+
+		java_library {
+			name: "baz",
+			apex_available: [
+				"com.android.art",
+			],
+			srcs: ["b.java"],
+			compile_dex: true,
+		}
+
+		java_library {
+			name: "quuz",
+			apex_available: [
+				"com.android.art",
+			],
+			srcs: ["b.java"],
+			compile_dex: true,
+		}
+
+		bootclasspath_fragment {
+			name: "art-bootclasspath-fragment",
+			image_name: "art",
+			// Must match the "com.android.art:" entries passed to FixtureConfigureBootJars above.
+			contents: ["baz", "quuz"],
+			apex_available: [
+				"com.android.art",
+			],
+		}
+
+		apex {
+			name: "myapex",
+			key: "myapex.key",
+			bootclasspath_fragments: [
+				"mybootclasspathfragment",
+			],
+			updatable: false,
+		}
+
+		apex_key {
+			name: "myapex.key",
+			public_key: "testkey.avbpubkey",
+			private_key: "testkey.pem",
+		}
+
+		java_sdk_library {
+			name: "foo",
+			srcs: ["b.java"],
+			shared_library: false,
+			public: {enabled: true},
+			apex_available: [
+				"myapex",
+			],
+		}
+
+		java_library {
+			name: "bar",
+			srcs: ["b.java"],
+			installable: true,
+			apex_available: [
+				"myapex",
+			],
+		}
+
+		bootclasspath_fragment {
+			name: "mybootclasspathfragment",
+			contents: [
+				"foo",
+				"bar",
+			],
+			apex_available: [
+				"myapex",
+			],
+			additional_stubs: ["android-non-updatable"],
+			fragments: [
+				{
+					apex: "com.android.art",
+					module: "art-bootclasspath-fragment",
+				},
+			],
+		}
+	`)
+
+	java.CheckModuleDependencies(t, result.TestContext, "mybootclasspathfragment", "android_common_apex10000", []string{
+		"android-non-updatable.stubs",
+		"android-non-updatable.stubs.module_lib",
+		"android-non-updatable.stubs.system",
+		"android-non-updatable.stubs.test",
+		"art-bootclasspath-fragment",
+		"bar",
+		"dex2oatd",
+		"foo",
+	})
+
+	nonUpdatablePublicStubs := getDexJarPath(result, "android-non-updatable.stubs")
+	nonUpdatableSystemStubs := getDexJarPath(result, "android-non-updatable.stubs.system")
+	nonUpdatableTestStubs := getDexJarPath(result, "android-non-updatable.stubs.test")
+	nonUpdatableModuleLibStubs := getDexJarPath(result, "android-non-updatable.stubs.module_lib")
+
+	// Make sure that the fragment uses the android-non-updatable modules when generating the hidden
+	// API flags.
+	fragment := result.ModuleForTests("mybootclasspathfragment", "android_common_apex10000")
+
+	rule := fragment.Rule("modularHiddenAPIStubFlagsFile")
+	command := rule.RuleParams.Command
+	android.AssertStringDoesContain(t, "check correct rule", command, "hiddenapi list")
+
+	// Make sure that the module_lib non-updatable stubs are available for resolving references from
+	// the implementation boot dex jars provided by this module.
+	android.AssertStringDoesContain(t, "android-non-updatable widest", command, "--dependency-stub-dex="+nonUpdatableModuleLibStubs)
+
+	// Make sure that the appropriate non-updatable stubs are available for resolving references from
+	// the different API stubs provided by this module.
+	android.AssertStringDoesContain(t, "public", command, "--public-stub-classpath="+nonUpdatablePublicStubs)
+	android.AssertStringDoesContain(t, "system", command, "--system-stub-classpath="+nonUpdatableSystemStubs)
+	android.AssertStringDoesContain(t, "test", command, "--test-stub-classpath="+nonUpdatableTestStubs)
+}
+
+// TestBootclasspathFragment_AndroidNonUpdatable_AlwaysUsePrebuiltSdks checks to make sure that
+// setting additional_stubs: ["android-non-updatable"] causes the prebuilt android-non-updatable
+// modules to be added to the hiddenapi list tool.
+func TestBootclasspathFragment_AndroidNonUpdatable_AlwaysUsePrebuiltSdks(t *testing.T) {
+	result := android.GroupFixturePreparers(
+		prepareForTestWithBootclasspathFragment,
+		java.PrepareForTestWithJavaDefaultModules,
+		prepareForTestWithArtApex,
+		prepareForTestWithMyapex,
+		// Configure bootclasspath jars to ensure that hidden API encoding is performed on them.
+		java.FixtureConfigureBootJars("com.android.art:baz", "com.android.art:quuz", "myapex:foo", "myapex:bar"),
+		// Make sure that the frameworks/base/Android.bp file exists as otherwise hidden API encoding
+		// is disabled.
+		android.FixtureAddTextFile("frameworks/base/Android.bp", ""),
+
+		android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+			variables.Always_use_prebuilt_sdks = proptools.BoolPtr(true)
+		}),
+
+		java.PrepareForTestWithJavaSdkLibraryFiles,
+		java.FixtureWithPrebuiltApis(map[string][]string{
+			"current": {"android-non-updatable"},
+			"30":      {"foo"},
+		}),
+	).RunTestWithBp(t, `
+		apex {
+			name: "com.android.art",
+			key: "com.android.art.key",
+			bootclasspath_fragments: ["art-bootclasspath-fragment"],
+ 			java_libs: [
+				"baz",
+				"quuz",
+			],
+			updatable: false,
+		}
+
+		apex_key {
+			name: "com.android.art.key",
+			public_key: "com.android.art.avbpubkey",
+			private_key: "com.android.art.pem",
+		}
+
+		java_library {
+			name: "baz",
+			apex_available: [
+				"com.android.art",
+			],
+			srcs: ["b.java"],
+			compile_dex: true,
+		}
+
+		java_library {
+			name: "quuz",
+			apex_available: [
+				"com.android.art",
+			],
+			srcs: ["b.java"],
+			compile_dex: true,
+		}
+
+		bootclasspath_fragment {
+			name: "art-bootclasspath-fragment",
+			image_name: "art",
+			// Must match the "com.android.art:" entries passed to FixtureConfigureBootJars above.
+			contents: ["baz", "quuz"],
+			apex_available: [
+				"com.android.art",
+			],
+		}
+
+		apex {
+			name: "myapex",
+			key: "myapex.key",
+			bootclasspath_fragments: [
+				"mybootclasspathfragment",
+			],
+			updatable: false,
+		}
+
+		apex_key {
+			name: "myapex.key",
+			public_key: "testkey.avbpubkey",
+			private_key: "testkey.pem",
+		}
+
+		java_sdk_library {
+			name: "foo",
+			srcs: ["b.java"],
+			shared_library: false,
+			public: {enabled: true},
+			apex_available: [
+				"myapex",
+			],
+		}
+
+		java_library {
+			name: "bar",
+			srcs: ["b.java"],
+			installable: true,
+			apex_available: [
+				"myapex",
+			],
+		}
+
+		bootclasspath_fragment {
+			name: "mybootclasspathfragment",
+			contents: [
+				"foo",
+				"bar",
+			],
+			apex_available: [
+				"myapex",
+			],
+			additional_stubs: ["android-non-updatable"],
+			fragments: [
+				{
+					apex: "com.android.art",
+					module: "art-bootclasspath-fragment",
+				},
+			],
+		}
+	`)
+
+	java.CheckModuleDependencies(t, result.TestContext, "mybootclasspathfragment", "android_common_apex10000", []string{
+		"art-bootclasspath-fragment",
+		"bar",
+		"dex2oatd",
+		"foo",
+		"prebuilt_sdk_module-lib_current_android-non-updatable",
+		"prebuilt_sdk_public_current_android-non-updatable",
+		"prebuilt_sdk_system_current_android-non-updatable",
+		"prebuilt_sdk_test_current_android-non-updatable",
+	})
+
+	nonUpdatablePublicStubs := getDexJarPath(result, "sdk_public_current_android-non-updatable")
+	nonUpdatableSystemStubs := getDexJarPath(result, "sdk_system_current_android-non-updatable")
+	nonUpdatableTestStubs := getDexJarPath(result, "sdk_test_current_android-non-updatable")
+	nonUpdatableModuleLibStubs := getDexJarPath(result, "sdk_module-lib_current_android-non-updatable")
+
+	// Make sure that the fragment uses the android-non-updatable modules when generating the hidden
+	// API flags.
+	fragment := result.ModuleForTests("mybootclasspathfragment", "android_common_apex10000")
+
+	rule := fragment.Rule("modularHiddenAPIStubFlagsFile")
+	command := rule.RuleParams.Command
+	android.AssertStringDoesContain(t, "check correct rule", command, "hiddenapi list")
+
+	// Make sure that the module_lib non-updatable stubs are available for resolving references from
+	// the implementation boot dex jars provided by this module.
+	android.AssertStringDoesContain(t, "android-non-updatable widest", command, "--dependency-stub-dex="+nonUpdatableModuleLibStubs)
+
+	// Make sure that the appropriate non-updatable stubs are available for resolving references from
+	// the different API stubs provided by this module.
+	android.AssertStringDoesContain(t, "public", command, "--public-stub-classpath="+nonUpdatablePublicStubs)
+	android.AssertStringDoesContain(t, "system", command, "--system-stub-classpath="+nonUpdatableSystemStubs)
+	android.AssertStringDoesContain(t, "test", command, "--test-stub-classpath="+nonUpdatableTestStubs)
+}
+
 // TODO(b/177892522) - add test for host apex.
diff --git a/apex/prebuilt.go b/apex/prebuilt.go
index 9504b07..548cf4c 100644
--- a/apex/prebuilt.go
+++ b/apex/prebuilt.go
@@ -23,7 +23,6 @@
 	"android/soong/android"
 	"android/soong/java"
 	"github.com/google/blueprint"
-
 	"github.com/google/blueprint/proptools"
 )
 
@@ -75,6 +74,10 @@
 type PrebuiltCommonProperties struct {
 	SelectedApexProperties
 
+	// Canonical name of this APEX. Used to determine the path to the activated APEX on
+	// device (/apex/<apex_name>). If unspecified, follows the name property.
+	Apex_name *string
+
 	ForceDisable bool `blueprint:"mutated"`
 
 	// whether the extracted apex file is installable.
@@ -109,6 +112,10 @@
 	android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
 }
 
+func (p *prebuiltCommon) ApexVariationName() string {
+	return proptools.StringDefault(p.prebuiltCommonProperties.Apex_name, p.ModuleBase.BaseModuleName())
+}
+
 func (p *prebuiltCommon) Prebuilt() *android.Prebuilt {
 	return &p.prebuilt
 }
@@ -389,11 +396,11 @@
 	})
 
 	// Create an ApexInfo for the prebuilt_apex.
-	apexVariationName := android.RemoveOptionalPrebuiltPrefix(mctx.ModuleName())
+	apexVariationName := p.ApexVariationName()
 	apexInfo := android.ApexInfo{
 		ApexVariationName: apexVariationName,
 		InApexVariants:    []string{apexVariationName},
-		InApexModules:     []string{apexVariationName},
+		InApexModules:     []string{p.ModuleBase.BaseModuleName()}, // BaseModuleName() to avoid the prebuilt_ prefix.
 		ApexContents:      []*android.ApexContents{apexContents},
 		ForPrebuiltApex:   true,
 	}
diff --git a/java/bootclasspath.go b/java/bootclasspath.go
index eddcc83..d754fe6 100644
--- a/java/bootclasspath.go
+++ b/java/bootclasspath.go
@@ -225,13 +225,13 @@
 	Core_platform_api BootclasspathNestedAPIProperties
 }
 
-// sdkKindToStubLibs calculates the stub library modules for each relevant android.SdkKind from the
+// apiScopeToStubLibs calculates the stub library modules for each relevant *HiddenAPIScope 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
+func (p BootclasspathAPIProperties) apiScopeToStubLibs() map[*HiddenAPIScope][]string {
+	m := map[*HiddenAPIScope][]string{}
+	for _, apiScope := range hiddenAPISdkLibrarySupportedScopes {
+		m[apiScope] = p.Api.Stub_libs
 	}
-	m[android.SdkCorePlatform] = p.Core_platform_api.Stub_libs
+	m[CorePlatformHiddenAPIScope] = p.Core_platform_api.Stub_libs
 	return m
 }
diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go
index 03faf34..62760c1 100644
--- a/java/bootclasspath_fragment.go
+++ b/java/bootclasspath_fragment.go
@@ -121,8 +121,18 @@
 	BootclasspathFragmentCoverageAffectedProperties
 	Coverage BootclasspathFragmentCoverageAffectedProperties
 
+	// Hidden API related properties.
 	Hidden_api HiddenAPIFlagFileProperties
 
+	// The list of additional stub libraries which this fragment's contents use but which are not
+	// provided by another bootclasspath_fragment.
+	//
+	// Note, "android-non-updatable" is treated specially. While no such module exists it is treated
+	// as if it was a java_sdk_library. So, when public API stubs are needed then it will be replaced
+	// with "android-non-updatable.stubs", with "androidn-non-updatable.system.stubs" when the system
+	// stubs are needed and so on.
+	Additional_stubs []string
+
 	// Properties that allow a fragment to depend on other fragments. This is needed for hidden API
 	// processing as it needs access to all the classes used by a fragment including those provided
 	// by other fragments.
@@ -375,7 +385,16 @@
 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())
+	hiddenAPIAddStubLibDependencies(ctx, b.properties.apiScopeToStubLibs())
+
+	for _, additionalStubModule := range b.properties.Additional_stubs {
+		for _, apiScope := range hiddenAPISdkLibrarySupportedScopes {
+			// Add a dependency onto a possibly scope specific stub library.
+			scopeSpecificDependency := apiScope.scopeSpecificStubModule(ctx, additionalStubModule)
+			tag := hiddenAPIStubsDependencyTag{apiScope: apiScope, fromAdditionalDependency: true}
+			ctx.AddVariationDependencies(nil, tag, scopeSpecificDependency)
+		}
+	}
 
 	if SkipDexpreoptBootJars(ctx) {
 		return
@@ -588,7 +607,7 @@
 		// Other bootclasspath_fragments that depend on this need the transitive set of stub dex jars
 		// from this to resolve any references from their code to classes provided by this fragment
 		// and the fragments this depends upon.
-		TransitiveStubDexJarsByKind: input.transitiveStubDexJarsByKind(),
+		TransitiveStubDexJarsByScope: input.transitiveStubDexJarsByScope(),
 	}
 
 	// The monolithic hidden API processing also needs access to all the output files produced by
@@ -632,8 +651,8 @@
 	// Populate with flag file paths from the properties.
 	input.extractFlagFilesFromProperties(ctx, &b.properties.Hidden_api)
 
-	// Store the stub dex jars from this module's fragment dependencies.
-	input.DependencyStubDexJarsByKind = dependencyHiddenApiInfo.TransitiveStubDexJarsByKind
+	// Add the stub dex jars from this module's fragment dependencies.
+	input.DependencyStubDexJarsByScope.append(dependencyHiddenApiInfo.TransitiveStubDexJarsByScope)
 
 	return input
 }
diff --git a/java/bootclasspath_fragment_test.go b/java/bootclasspath_fragment_test.go
index fba7d1a..aa1c59f 100644
--- a/java/bootclasspath_fragment_test.go
+++ b/java/bootclasspath_fragment_test.go
@@ -245,17 +245,17 @@
 	otherPublicStubsJar := "out/soong/.intermediates/myothersdklibrary.stubs/android_common/dex/myothersdklibrary.stubs.jar"
 
 	// Check that SdkPublic uses public stubs for all sdk libraries.
-	android.AssertPathsRelativeToTopEquals(t, "public dex stubs jar", []string{otherPublicStubsJar, publicStubsJar, stubsJar}, info.TransitiveStubDexJarsByKind[android.SdkPublic])
+	android.AssertPathsRelativeToTopEquals(t, "public dex stubs jar", []string{otherPublicStubsJar, publicStubsJar, stubsJar}, info.TransitiveStubDexJarsByScope[PublicHiddenAPIScope])
 
 	// Check that SdkSystem uses system stubs for mysdklibrary and public stubs for myothersdklibrary
 	// as it does not provide system stubs.
-	android.AssertPathsRelativeToTopEquals(t, "system dex stubs jar", []string{otherPublicStubsJar, systemStubsJar, stubsJar}, info.TransitiveStubDexJarsByKind[android.SdkSystem])
+	android.AssertPathsRelativeToTopEquals(t, "system dex stubs jar", []string{otherPublicStubsJar, systemStubsJar, stubsJar}, info.TransitiveStubDexJarsByScope[SystemHiddenAPIScope])
 
 	// Check that SdkTest also uses system stubs for mysdklibrary as it does not provide test stubs
 	// and public stubs for myothersdklibrary as it does not provide test stubs either.
-	android.AssertPathsRelativeToTopEquals(t, "test dex stubs jar", []string{otherPublicStubsJar, systemStubsJar, stubsJar}, info.TransitiveStubDexJarsByKind[android.SdkTest])
+	android.AssertPathsRelativeToTopEquals(t, "test dex stubs jar", []string{otherPublicStubsJar, systemStubsJar, stubsJar}, info.TransitiveStubDexJarsByScope[TestHiddenAPIScope])
 
 	// 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.TransitiveStubDexJarsByKind[android.SdkCorePlatform])
+	android.AssertPathsRelativeToTopEquals(t, "core platform dex stubs jar", []string{corePlatformStubsJar}, info.TransitiveStubDexJarsByScope[CorePlatformHiddenAPIScope])
 }
diff --git a/java/hiddenapi_modular.go b/java/hiddenapi_modular.go
index 6e22614..ba53ea6 100644
--- a/java/hiddenapi_modular.go
+++ b/java/hiddenapi_modular.go
@@ -25,9 +25,160 @@
 
 // Contains support for processing hiddenAPI in a modular fashion.
 
+// HiddenAPIScope encapsulates all the information that the hidden API processing needs about API
+// scopes, i.e. what is called android.SdkKind and apiScope. It does not just use those as they do
+// not provide the information needed by hidden API processing.
+type HiddenAPIScope struct {
+	// The name of the scope, used for debug purposes.
+	name string
+
+	// The corresponding android.SdkKind, used for retrieving paths from java_sdk_library* modules.
+	sdkKind android.SdkKind
+
+	// The option needed to passed to "hiddenapi list".
+	hiddenAPIListOption string
+
+	// The name sof the source stub library modules that contain the API provided by the platform,
+	// i.e. by modules that are not in an APEX.
+	nonUpdatableSourceModule string
+
+	// The names of the prebuilt stub library modules that contain the API provided by the platform,
+	// i.e. by modules that are not in an APEX.
+	nonUpdatablePrebuiltModule string
+}
+
+// initHiddenAPIScope initializes the scope.
+func initHiddenAPIScope(apiScope *HiddenAPIScope) *HiddenAPIScope {
+	sdkKind := apiScope.sdkKind
+	// The platform does not provide a core platform API.
+	if sdkKind != android.SdkCorePlatform {
+		kindAsString := sdkKind.String()
+		var insert string
+		if sdkKind == android.SdkPublic {
+			insert = ""
+		} else {
+			insert = "." + strings.ReplaceAll(kindAsString, "-", "_")
+		}
+
+		nonUpdatableModule := "android-non-updatable"
+
+		// Construct the name of the android-non-updatable source module for this scope.
+		apiScope.nonUpdatableSourceModule = fmt.Sprintf("%s.stubs%s", nonUpdatableModule, insert)
+
+		prebuiltModuleName := func(name string, kind string) string {
+			return fmt.Sprintf("sdk_%s_current_%s", kind, name)
+		}
+
+		// Construct the name of the android-non-updatable prebuilt module for this scope.
+		apiScope.nonUpdatablePrebuiltModule = prebuiltModuleName(nonUpdatableModule, kindAsString)
+	}
+
+	return apiScope
+}
+
+// android-non-updatable takes the name of a module and returns a possibly scope specific name of
+// the module.
+func (l *HiddenAPIScope) scopeSpecificStubModule(ctx android.BaseModuleContext, name string) string {
+	// The android-non-updatable is not a java_sdk_library but there are separate stub libraries for
+	// each scope.
+	// TODO(b/192067200): Remove special handling of android-non-updatable.
+	if name == "android-non-updatable" {
+		if ctx.Config().AlwaysUsePrebuiltSdks() {
+			return l.nonUpdatablePrebuiltModule
+		} else {
+			return l.nonUpdatableSourceModule
+		}
+	} else {
+		// Assume that the module is either a java_sdk_library (or equivalent) and so will provide
+		// separate stub jars for each scope or is a java_library (or equivalent) in which case it will
+		// have the same stub jar for each scope.
+		return name
+	}
+}
+
+func (l *HiddenAPIScope) String() string {
+	return fmt.Sprintf("HiddenAPIScope{%s}", l.name)
+}
+
+var (
+	PublicHiddenAPIScope = initHiddenAPIScope(&HiddenAPIScope{
+		name:                "public",
+		sdkKind:             android.SdkPublic,
+		hiddenAPIListOption: "--public-stub-classpath",
+	})
+	SystemHiddenAPIScope = initHiddenAPIScope(&HiddenAPIScope{
+		name:                "system",
+		sdkKind:             android.SdkSystem,
+		hiddenAPIListOption: "--system-stub-classpath",
+	})
+	TestHiddenAPIScope = initHiddenAPIScope(&HiddenAPIScope{
+		name:                "test",
+		sdkKind:             android.SdkTest,
+		hiddenAPIListOption: "--test-stub-classpath",
+	})
+	ModuleLibHiddenAPIScope = initHiddenAPIScope(&HiddenAPIScope{
+		name:    "module-lib",
+		sdkKind: android.SdkModule,
+	})
+	CorePlatformHiddenAPIScope = initHiddenAPIScope(&HiddenAPIScope{
+		name:                "core-platform",
+		sdkKind:             android.SdkCorePlatform,
+		hiddenAPIListOption: "--core-platform-stub-classpath",
+	})
+
+	// hiddenAPIRelevantSdkKinds lists all the android.SdkKind instances that are needed by the hidden
+	// API processing.
+	//
+	// These are roughly in order from narrowest API surface to widest. Widest means the API stubs
+	// with the biggest API surface, e.g. test is wider than system is wider than public.
+	//
+	// Core platform is considered wider than system/module-lib because those modules that provide
+	// core platform APIs either do not have any system/module-lib APIs at all, or if they do it is
+	// because the core platform API is being converted to system/module-lib APIs. In either case the
+	// system/module-lib APIs are subsets of the core platform API.
+	//
+	// This is not strictly in order from narrowest to widest as the Test API is wider than system but
+	// is neither wider or narrower than the module-lib or core platform APIs. However, this works
+	// well enough at the moment.
+	// TODO(b/191644675): Correctly reflect the sub/superset relationships between APIs.
+	hiddenAPIScopes = []*HiddenAPIScope{
+		PublicHiddenAPIScope,
+		SystemHiddenAPIScope,
+		TestHiddenAPIScope,
+		ModuleLibHiddenAPIScope,
+		CorePlatformHiddenAPIScope,
+	}
+
+	// The HiddenAPIScope instances that are supported by a java_sdk_library.
+	//
+	// CorePlatformHiddenAPIScope is not used as the java_sdk_library does not have special support
+	// for core_platform API, instead it is implemented as a customized form of PublicHiddenAPIScope.
+	hiddenAPISdkLibrarySupportedScopes = []*HiddenAPIScope{
+		PublicHiddenAPIScope,
+		SystemHiddenAPIScope,
+		TestHiddenAPIScope,
+		ModuleLibHiddenAPIScope,
+	}
+
+	// The HiddenAPIScope instances that are supported by the `hiddenapi list`.
+	hiddenAPIFlagScopes = []*HiddenAPIScope{
+		PublicHiddenAPIScope,
+		SystemHiddenAPIScope,
+		TestHiddenAPIScope,
+		CorePlatformHiddenAPIScope,
+	}
+)
+
 type hiddenAPIStubsDependencyTag struct {
 	blueprint.BaseDependencyTag
-	sdkKind android.SdkKind
+
+	// The api scope for which this dependency was added.
+	apiScope *HiddenAPIScope
+
+	// Indicates that the dependency is not for an API provided by the current bootclasspath fragment
+	// but is an additional API provided by a module that is not part of the current bootclasspath
+	// fragment.
+	fromAdditionalDependency bool
 }
 
 func (b hiddenAPIStubsDependencyTag) ExcludeFromApexContents() {
@@ -38,6 +189,11 @@
 }
 
 func (b hiddenAPIStubsDependencyTag) SdkMemberType(child android.Module) android.SdkMemberType {
+	// Do not add additional dependencies to the sdk.
+	if b.fromAdditionalDependency {
+		return nil
+	}
+
 	// 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) {
@@ -65,24 +221,9 @@
 var _ android.ExcludeFromApexContentsTag = hiddenAPIStubsDependencyTag{}
 var _ android.SdkMemberTypeDependencyTag = hiddenAPIStubsDependencyTag{}
 
-// hiddenAPIRelevantSdkKinds lists all the android.SdkKind instances that are needed by the hidden
-// API processing.
-//
-// These are in order from narrowest API surface to widest. Widest means the API stubs with the
-// biggest API surface, e.g. test is wider than system is wider than public. Core platform is
-// considered wider than test even though it has no relationship with test because the libraries
-// that provide core platform API don't provide test. While the core platform API is being converted
-// to a system API the system API is still a subset of core platform.
-var hiddenAPIRelevantSdkKinds = []android.SdkKind{
-	android.SdkPublic,
-	android.SdkSystem,
-	android.SdkTest,
-	android.SdkCorePlatform,
-}
-
 // hiddenAPIComputeMonolithicStubLibModules computes the set of module names that provide stubs
 // needed to produce the hidden API monolithic stub flags file.
-func hiddenAPIComputeMonolithicStubLibModules(config android.Config) map[android.SdkKind][]string {
+func hiddenAPIComputeMonolithicStubLibModules(config android.Config) map[*HiddenAPIScope][]string {
 	var publicStubModules []string
 	var systemStubModules []string
 	var testStubModules []string
@@ -115,22 +256,22 @@
 		testStubModules = append(testStubModules, "jacoco-stubs")
 	}
 
-	m := map[android.SdkKind][]string{}
-	m[android.SdkPublic] = publicStubModules
-	m[android.SdkSystem] = systemStubModules
-	m[android.SdkTest] = testStubModules
-	m[android.SdkCorePlatform] = corePlatformStubModules
+	m := map[*HiddenAPIScope][]string{}
+	m[PublicHiddenAPIScope] = publicStubModules
+	m[SystemHiddenAPIScope] = systemStubModules
+	m[TestHiddenAPIScope] = testStubModules
+	m[CorePlatformHiddenAPIScope] = corePlatformStubModules
 	return m
 }
 
 // hiddenAPIAddStubLibDependencies adds dependencies onto the modules specified in
-// sdkKindToStubLibModules. It adds them in a well known order and uses an SdkKind specific tag to
-// identify the source of the dependency.
-func hiddenAPIAddStubLibDependencies(ctx android.BottomUpMutatorContext, sdkKindToStubLibModules map[android.SdkKind][]string) {
+// apiScopeToStubLibModules. It adds them in a well known order and uses a HiddenAPIScope specific
+// tag to identify the source of the dependency.
+func hiddenAPIAddStubLibDependencies(ctx android.BottomUpMutatorContext, apiScopeToStubLibModules map[*HiddenAPIScope][]string) {
 	module := ctx.Module()
-	for _, sdkKind := range hiddenAPIRelevantSdkKinds {
-		modules := sdkKindToStubLibModules[sdkKind]
-		ctx.AddDependency(module, hiddenAPIStubsDependencyTag{sdkKind: sdkKind}, modules...)
+	for _, apiScope := range hiddenAPIScopes {
+		modules := apiScopeToStubLibModules[apiScope]
+		ctx.AddDependency(module, hiddenAPIStubsDependencyTag{apiScope: apiScope}, modules...)
 	}
 }
 
@@ -153,33 +294,21 @@
 	return dexJar
 }
 
-var sdkKindToHiddenapiListOption = map[android.SdkKind]string{
-	android.SdkPublic:       "public-stub-classpath",
-	android.SdkSystem:       "system-stub-classpath",
-	android.SdkTest:         "test-stub-classpath",
-	android.SdkCorePlatform: "core-platform-stub-classpath",
-}
-
-// ruleToGenerateHiddenAPIStubFlagsFile creates a rule to create a hidden API stub flags file.
+// buildRuleToGenerateHiddenAPIStubFlagsFile creates a rule to create a hidden API stub flags file.
 //
 // The rule is initialized but not built so that the caller can modify it and select an appropriate
 // name.
-func ruleToGenerateHiddenAPIStubFlagsFile(ctx android.BuilderContext, outputPath android.WritablePath, bootDexJars android.Paths, input HiddenAPIFlagInput) *android.RuleBuilder {
+func buildRuleToGenerateHiddenAPIStubFlagsFile(ctx android.BuilderContext, name, desc string, outputPath android.WritablePath, bootDexJars android.Paths, input HiddenAPIFlagInput, moduleStubFlagsPaths android.Paths) {
 	// Singleton rule which applies hiddenapi on all boot class path dex files.
 	rule := android.NewRuleBuilder(pctx, ctx)
 
 	tempPath := tempPathForRestat(ctx, outputPath)
 
 	// Find the widest API stubs provided by the fragments on which this depends, if any.
-	var dependencyStubDexJars android.Paths
-	for i := len(hiddenAPIRelevantSdkKinds) - 1; i >= 0; i-- {
-		kind := hiddenAPIRelevantSdkKinds[i]
-		stubsForKind := input.DependencyStubDexJarsByKind[kind]
-		if len(stubsForKind) != 0 {
-			dependencyStubDexJars = stubsForKind
-			break
-		}
-	}
+	dependencyStubDexJars := input.DependencyStubDexJarsByScope.stubDexJarsForWidestAPIScope()
+
+	// Add widest API stubs from the additional dependencies of this, if any.
+	dependencyStubDexJars = append(dependencyStubDexJars, input.AdditionalStubDexJarsByScope.stubDexJarsForWidestAPIScope()...)
 
 	command := rule.Command().
 		Tool(ctx.Config().HostToolPath(ctx, "hiddenapi")).
@@ -187,24 +316,39 @@
 		FlagForEachInput("--dependency-stub-dex=", dependencyStubDexJars).
 		FlagForEachInput("--boot-dex=", bootDexJars)
 
-	// Iterate over the sdk kinds in a fixed order.
-	for _, sdkKind := range hiddenAPIRelevantSdkKinds {
-		// Merge in the stub dex jar paths for this kind from the fragments on which it depends. They
-		// will be needed to resolve dependencies from this fragment's stubs to classes in the other
-		// fragment's APIs.
-		dependencyPaths := input.DependencyStubDexJarsByKind[sdkKind]
-		paths := append(dependencyPaths, input.StubDexJarsByKind[sdkKind]...)
+	// Iterate over the api scopes in a fixed order.
+	for _, apiScope := range hiddenAPIFlagScopes {
+		// Merge in the stub dex jar paths for this api scope from the fragments on which it depends.
+		// They will be needed to resolve dependencies from this fragment's stubs to classes in the
+		// other fragment's APIs.
+		var paths android.Paths
+		paths = append(paths, input.DependencyStubDexJarsByScope[apiScope]...)
+		paths = append(paths, input.AdditionalStubDexJarsByScope[apiScope]...)
+		paths = append(paths, input.StubDexJarsByScope[apiScope]...)
 		if len(paths) > 0 {
-			option := sdkKindToHiddenapiListOption[sdkKind]
-			command.FlagWithInputList("--"+option+"=", paths, ":")
+			option := apiScope.hiddenAPIListOption
+			command.FlagWithInputList(option+"=", paths, ":")
 		}
 	}
 
 	// Add the output path.
 	command.FlagWithOutput("--out-api-flags=", tempPath)
 
+	// If there are stub flag files that have been generated by fragments on which this depends then
+	// use them to validate the stub flag file generated by the rules created by this method.
+	if len(moduleStubFlagsPaths) > 0 {
+		validFile := buildRuleValidateOverlappingCsvFiles(ctx, name, desc, outputPath, moduleStubFlagsPaths)
+
+		// Add the file that indicates that the file generated by this is valid.
+		//
+		// This will cause the validation rule above to be run any time that the output of this rule
+		// changes but the validation will run in parallel with other rules that depend on this file.
+		command.Validation(validFile)
+	}
+
 	commitChangeForRestat(rule, tempPath, outputPath)
-	return rule
+
+	rule.Build(name, desc)
 }
 
 // HiddenAPIFlagFileProperties contains paths to the flag files that can be used to augment the
@@ -377,8 +521,8 @@
 	// that category.
 	FlagFilesByCategory FlagFilesByCategory
 
-	// The paths to the stub dex jars for each of the android.SdkKind in hiddenAPIRelevantSdkKinds.
-	TransitiveStubDexJarsByKind StubDexJarsByKind
+	// The paths to the stub dex jars for each of the *HiddenAPIScope in hiddenAPIScopes.
+	TransitiveStubDexJarsByScope StubDexJarsByScope
 
 	// The output from the hidden API processing needs to be made available to other modules.
 	HiddenAPIFlagOutput
@@ -386,8 +530,8 @@
 
 func newHiddenAPIInfo() *HiddenAPIInfo {
 	info := HiddenAPIInfo{
-		FlagFilesByCategory:         FlagFilesByCategory{},
-		TransitiveStubDexJarsByKind: StubDexJarsByKind{},
+		FlagFilesByCategory:          FlagFilesByCategory{},
+		TransitiveStubDexJarsByScope: StubDexJarsByScope{},
 	}
 	return &info
 }
@@ -398,36 +542,50 @@
 	for _, fragment := range fragments {
 		if ctx.OtherModuleHasProvider(fragment, HiddenAPIInfoProvider) {
 			info := ctx.OtherModuleProvider(fragment, HiddenAPIInfoProvider).(HiddenAPIInfo)
-			i.TransitiveStubDexJarsByKind.append(info.TransitiveStubDexJarsByKind)
+			i.TransitiveStubDexJarsByScope.append(info.TransitiveStubDexJarsByScope)
 		}
 	}
 
 	// Dedup and sort paths.
-	i.TransitiveStubDexJarsByKind.dedupAndSort()
+	i.TransitiveStubDexJarsByScope.dedupAndSort()
 }
 
 var HiddenAPIInfoProvider = blueprint.NewProvider(HiddenAPIInfo{})
 
-// StubDexJarsByKind maps an android.SdkKind to the paths to stub dex jars appropriate for that
-// level. See hiddenAPIRelevantSdkKinds for a list of the acceptable android.SdkKind values.
-type StubDexJarsByKind map[android.SdkKind]android.Paths
+// StubDexJarsByScope maps a *HiddenAPIScope to the paths to stub dex jars appropriate for that
+// scope. See hiddenAPIScopes for a list of the acceptable *HiddenAPIScope values.
+type StubDexJarsByScope map[*HiddenAPIScope]android.Paths
 
-// append appends the supplied kind specific stub dex jar pargs to the corresponding kind in this
+// append appends the API scope specific stub dex jar args to the corresponding scope in this
 // map.
-func (s StubDexJarsByKind) append(other StubDexJarsByKind) {
-	for _, kind := range hiddenAPIRelevantSdkKinds {
-		s[kind] = append(s[kind], other[kind]...)
+func (s StubDexJarsByScope) append(other StubDexJarsByScope) {
+	for _, scope := range hiddenAPIScopes {
+		s[scope] = append(s[scope], other[scope]...)
 	}
 }
 
 // dedupAndSort removes duplicates in the stub dex jar paths and sorts them into a consistent and
 // deterministic order.
-func (s StubDexJarsByKind) dedupAndSort() {
-	for kind, paths := range s {
-		s[kind] = android.SortedUniquePaths(paths)
+func (s StubDexJarsByScope) dedupAndSort() {
+	for apiScope, paths := range s {
+		s[apiScope] = android.SortedUniquePaths(paths)
 	}
 }
 
+// stubDexJarsForWidestAPIScope returns the stub dex jars for the widest API scope provided by this
+// map. The relative width of APIs is determined by their order in hiddenAPIScopes.
+func (s StubDexJarsByScope) stubDexJarsForWidestAPIScope() android.Paths {
+	for i := len(hiddenAPIScopes) - 1; i >= 0; i-- {
+		apiScope := hiddenAPIScopes[i]
+		stubsForAPIScope := s[apiScope]
+		if len(stubsForAPIScope) != 0 {
+			return stubsForAPIScope
+		}
+	}
+
+	return nil
+}
+
 // HiddenAPIFlagInput encapsulates information obtained from a module and its dependencies that are
 // needed for hidden API flag generation.
 type HiddenAPIFlagInput struct {
@@ -435,14 +593,21 @@
 	// from the stub dex files.
 	FlagFilesByCategory FlagFilesByCategory
 
-	// StubDexJarsByKind contains the stub dex jars for different android.SdkKind and which determine
+	// StubDexJarsByScope contains the stub dex jars for different *HiddenAPIScope and which determine
 	// the initial flags for each dex member.
-	StubDexJarsByKind StubDexJarsByKind
+	StubDexJarsByScope StubDexJarsByScope
 
-	// DependencyStubDexJarsByKind contains the stub dex jars provided by the fragments on which this
-	// depends. It is the result of merging HiddenAPIInfo.TransitiveStubDexJarsByKind from each
+	// DependencyStubDexJarsByScope contains the stub dex jars provided by the fragments on which this
+	// depends. It is the result of merging HiddenAPIInfo.TransitiveStubDexJarsByScope from each
 	// fragment on which this depends.
-	DependencyStubDexJarsByKind StubDexJarsByKind
+	DependencyStubDexJarsByScope StubDexJarsByScope
+
+	// AdditionalStubDexJarsByScope contains stub dex jars provided by other modules in addition to
+	// the ones that are obtained from fragments on which this depends.
+	//
+	// These are kept separate from stub dex jars in HiddenAPIFlagInput.DependencyStubDexJarsByScope
+	// as there are not propagated transitively to other fragments that depend on this.
+	AdditionalStubDexJarsByScope StubDexJarsByScope
 
 	// RemovedTxtFiles is the list of removed.txt files provided by java_sdk_library modules that are
 	// specified in the bootclasspath_fragment's stub_libs and contents properties.
@@ -452,8 +617,10 @@
 // newHiddenAPIFlagInput creates a new initialize HiddenAPIFlagInput struct.
 func newHiddenAPIFlagInput() HiddenAPIFlagInput {
 	input := HiddenAPIFlagInput{
-		FlagFilesByCategory: FlagFilesByCategory{},
-		StubDexJarsByKind:   StubDexJarsByKind{},
+		FlagFilesByCategory:          FlagFilesByCategory{},
+		StubDexJarsByScope:           StubDexJarsByScope{},
+		DependencyStubDexJarsByScope: StubDexJarsByScope{},
+		AdditionalStubDexJarsByScope: StubDexJarsByScope{},
 	}
 
 	return input
@@ -469,7 +636,7 @@
 	// required as the whole point of adding something to the bootclasspath fragment is to add it to
 	// the bootclasspath in order to be used by something else in the system. Without any stubs it
 	// cannot do that.
-	if len(i.StubDexJarsByKind) == 0 {
+	if len(i.StubDexJarsByScope) == 0 {
 		return false
 	}
 
@@ -500,14 +667,15 @@
 //
 // That includes paths to the stub dex jars as well as paths to the *removed.txt files.
 func (i *HiddenAPIFlagInput) gatherStubLibInfo(ctx android.ModuleContext, contents []android.Module) {
-	addFromModule := func(ctx android.ModuleContext, module android.Module, kind android.SdkKind) {
-		dexJar := hiddenAPIRetrieveDexJarBuildPath(ctx, module, kind)
+	addFromModule := func(ctx android.ModuleContext, module android.Module, apiScope *HiddenAPIScope) {
+		sdkKind := apiScope.sdkKind
+		dexJar := hiddenAPIRetrieveDexJarBuildPath(ctx, module, sdkKind)
 		if dexJar != nil {
-			i.StubDexJarsByKind[kind] = append(i.StubDexJarsByKind[kind], dexJar)
+			i.StubDexJarsByScope[apiScope] = append(i.StubDexJarsByScope[apiScope], dexJar)
 		}
 
 		if sdkLibrary, ok := module.(SdkLibraryDependency); ok {
-			removedTxtFile := sdkLibrary.SdkRemovedTxtFile(ctx, kind)
+			removedTxtFile := sdkLibrary.SdkRemovedTxtFile(ctx, sdkKind)
 			i.RemovedTxtFiles = append(i.RemovedTxtFiles, removedTxtFile.AsPaths()...)
 		}
 	}
@@ -515,11 +683,9 @@
 	// If the contents includes any java_sdk_library modules then add them to the stubs.
 	for _, module := range contents {
 		if _, ok := module.(SdkLibraryDependency); ok {
-			// Add information for every possible kind needed by hidden API. SdkCorePlatform is not used
-			// as the java_sdk_library does not have special support for core_platform API, instead it is
-			// implemented as a customized form of SdkPublic.
-			for _, kind := range []android.SdkKind{android.SdkPublic, android.SdkSystem, android.SdkTest} {
-				addFromModule(ctx, module, kind)
+			// Add information for every possible API scope needed by hidden API.
+			for _, apiScope := range hiddenAPISdkLibrarySupportedScopes {
+				addFromModule(ctx, module, apiScope)
 			}
 		}
 	}
@@ -527,13 +693,21 @@
 	ctx.VisitDirectDeps(func(module android.Module) {
 		tag := ctx.OtherModuleDependencyTag(module)
 		if hiddenAPIStubsTag, ok := tag.(hiddenAPIStubsDependencyTag); ok {
-			kind := hiddenAPIStubsTag.sdkKind
-			addFromModule(ctx, module, kind)
+			apiScope := hiddenAPIStubsTag.apiScope
+			if hiddenAPIStubsTag.fromAdditionalDependency {
+				dexJar := hiddenAPIRetrieveDexJarBuildPath(ctx, module, apiScope.sdkKind)
+				if dexJar != nil {
+					i.AdditionalStubDexJarsByScope[apiScope] = append(i.AdditionalStubDexJarsByScope[apiScope], dexJar)
+				}
+			} else {
+				addFromModule(ctx, module, apiScope)
+			}
 		}
 	})
 
 	// Normalize the paths, i.e. remove duplicates and sort.
-	i.StubDexJarsByKind.dedupAndSort()
+	i.StubDexJarsByScope.dedupAndSort()
+	i.DependencyStubDexJarsByScope.dedupAndSort()
 	i.RemovedTxtFiles = android.SortedUniquePaths(i.RemovedTxtFiles)
 }
 
@@ -546,9 +720,9 @@
 	}
 }
 
-func (i *HiddenAPIFlagInput) transitiveStubDexJarsByKind() StubDexJarsByKind {
-	transitive := i.DependencyStubDexJarsByKind
-	transitive.append(i.StubDexJarsByKind)
+func (i *HiddenAPIFlagInput) transitiveStubDexJarsByScope() StubDexJarsByScope {
+	transitive := i.DependencyStubDexJarsByScope
+	transitive.append(i.StubDexJarsByScope)
 	return transitive
 }
 
@@ -637,28 +811,6 @@
 	outputPath android.WritablePath, baseFlagsPath android.Path, annotationFlagPaths android.Paths,
 	flagFilesByCategory FlagFilesByCategory, allFlagsPaths android.Paths, generatedRemovedDexSignatures android.OptionalPath) {
 
-	// The file which is used to record that the flags file is valid.
-	var validFile android.WritablePath
-
-	// If there are flag files that have been generated by fragments on which this depends then use
-	// them to validate the flag file generated by the rules created by this method.
-	if len(allFlagsPaths) > 0 {
-		// The flags file generated by the rule created by this method needs to be validated to ensure
-		// that it is consistent with the flag files generated by the individual fragments.
-
-		validFile = pathForValidation(ctx, outputPath)
-
-		// Create a rule to validate the output from the following rule.
-		rule := android.NewRuleBuilder(pctx, ctx)
-		rule.Command().
-			BuiltTool("verify_overlaps").
-			Input(outputPath).
-			Inputs(allFlagsPaths).
-			// If validation passes then update the file that records that.
-			Text("&& touch").Output(validFile)
-		rule.Build(name+"Validation", desc+" validation")
-	}
-
 	// Create the rule that will generate the flag files.
 	tempPath := tempPathForRestat(ctx, outputPath)
 	rule := android.NewRuleBuilder(pctx, ctx)
@@ -684,7 +836,11 @@
 
 	commitChangeForRestat(rule, tempPath, outputPath)
 
-	if validFile != nil {
+	// If there are flag files that have been generated by fragments on which this depends then use
+	// them to validate the flag file generated by the rules created by this method.
+	if len(allFlagsPaths) > 0 {
+		validFile := buildRuleValidateOverlappingCsvFiles(ctx, name, desc, outputPath, allFlagsPaths)
+
 		// Add the file that indicates that the file generated by this is valid.
 		//
 		// This will cause the validation rule above to be run any time that the output of this rule
@@ -695,6 +851,25 @@
 	rule.Build(name, desc)
 }
 
+// buildRuleValidateOverlappingCsvFiles checks that the modular CSV files, i.e. the files generated
+// by the individual bootclasspath_fragment modules are subsets of the monolithic CSV file.
+func buildRuleValidateOverlappingCsvFiles(ctx android.BuilderContext, name string, desc string, monolithicFilePath android.WritablePath, modularFilePaths android.Paths) android.WritablePath {
+	// The file which is used to record that the flags file is valid.
+	validFile := pathForValidation(ctx, monolithicFilePath)
+
+	// Create a rule to validate the output from the following rule.
+	rule := android.NewRuleBuilder(pctx, ctx)
+	rule.Command().
+		BuiltTool("verify_overlaps").
+		Input(monolithicFilePath).
+		Inputs(modularFilePaths).
+		// If validation passes then update the file that records that.
+		Text("&& touch").Output(validFile)
+	rule.Build(name+"Validation", desc+" validation")
+
+	return validFile
+}
+
 // hiddenAPIRulesForBootclasspathFragment will generate all the flags for a fragment of the
 // bootclasspath and then encode the flags into the boot dex files.
 //
@@ -718,8 +893,7 @@
 
 	// Generate the stub-flags.csv.
 	stubFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "stub-flags.csv")
-	rule := ruleToGenerateHiddenAPIStubFlagsFile(ctx, stubFlagsCSV, bootDexInfoByModule.bootDexJars(), input)
-	rule.Build("modularHiddenAPIStubFlagsFile", "modular hiddenapi stub flags")
+	buildRuleToGenerateHiddenAPIStubFlagsFile(ctx, "modularHiddenAPIStubFlagsFile", "modular hiddenapi stub flags", stubFlagsCSV, bootDexInfoByModule.bootDexJars(), input, nil)
 
 	// Extract the classes jars from the contents.
 	classesJars := extractClassesJarsFromModules(contents)
diff --git a/java/platform_bootclasspath.go b/java/platform_bootclasspath.go
index 7b651ba..41b5f1e 100644
--- a/java/platform_bootclasspath.go
+++ b/java/platform_bootclasspath.go
@@ -119,8 +119,8 @@
 	}
 
 	// Add dependencies onto the stub lib modules.
-	sdkKindToStubLibModules := hiddenAPIComputeMonolithicStubLibModules(ctx.Config())
-	hiddenAPIAddStubLibDependencies(ctx, sdkKindToStubLibModules)
+	apiLevelToStubLibModules := hiddenAPIComputeMonolithicStubLibModules(ctx.Config())
+	hiddenAPIAddStubLibDependencies(ctx, apiLevelToStubLibModules)
 }
 
 func (b *platformBootclasspathModule) BootclasspathDepsMutator(ctx android.BottomUpMutatorContext) {
@@ -287,7 +287,7 @@
 	// the fragments will have already provided the flags that are needed.
 	classesJars := monolithicInfo.ClassesJars
 
-	// Create the input to pass to ruleToGenerateHiddenAPIStubFlagsFile
+	// Create the input to pass to buildRuleToGenerateHiddenAPIStubFlagsFile
 	input := newHiddenAPIFlagInput()
 
 	// Gather stub library information from the dependencies on modules provided by
@@ -299,8 +299,7 @@
 
 	// Generate the monolithic stub-flags.csv file.
 	stubFlags := hiddenAPISingletonPaths(ctx).stubFlags
-	rule := ruleToGenerateHiddenAPIStubFlagsFile(ctx, stubFlags, bootDexJarByModule.bootDexJars(), input)
-	rule.Build("platform-bootclasspath-monolithic-hiddenapi-stub-flags", "monolithic hidden API stub flags")
+	buildRuleToGenerateHiddenAPIStubFlagsFile(ctx, "platform-bootclasspath-monolithic-hiddenapi-stub-flags", "monolithic hidden API stub flags", stubFlags, bootDexJarByModule.bootDexJars(), input, monolithicInfo.StubFlagsPaths)
 
 	// Generate the annotation-flags.csv file from all the module annotations.
 	annotationFlags := android.PathForModuleOut(ctx, "hiddenapi-monolithic", "annotation-flags-from-classes.csv")
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 56c40f0..7413640 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -684,6 +684,15 @@
 	return true
 }
 
+// uniqueApexVariations provides common implementation of the ApexModule.UniqueApexVariations
+// method.
+func (c *commonToSdkLibraryAndImport) uniqueApexVariations() bool {
+	// A java_sdk_library that is a shared library produces an XML file that makes the shared library
+	// usable from an AndroidManifest.xml's <uses-library> entry. That XML file contains the name of
+	// the APEX and so it needs a unique variation per APEX.
+	return c.sharedLibrary()
+}
+
 func (c *commonToSdkLibraryAndImport) generateCommonBuildActions(ctx android.ModuleContext) {
 	c.doctagPaths = android.PathsForModuleSrc(ctx, c.commonSdkLibraryProperties.Doctag_files)
 }
@@ -1528,6 +1537,7 @@
 	mctx.CreateModule(DroidstubsFactory, &props)
 }
 
+// Implements android.ApexModule
 func (module *SdkLibrary) DepIsInSameApex(mctx android.BaseModuleContext, dep android.Module) bool {
 	depTag := mctx.OtherModuleDependencyTag(dep)
 	if depTag == xmlPermissionsFileTag {
@@ -1536,6 +1546,11 @@
 	return module.Library.DepIsInSameApex(mctx, dep)
 }
 
+// Implements android.ApexModule
+func (module *SdkLibrary) UniqueApexVariations() bool {
+	return module.uniqueApexVariations()
+}
+
 // Creates the xml file that publicizes the runtime library
 func (module *SdkLibrary) createXmlFile(mctx android.DefaultableHookContext) {
 	props := struct {
@@ -2086,6 +2101,11 @@
 	return nil
 }
 
+// Implements android.ApexModule
+func (module *SdkLibraryImport) UniqueApexVariations() bool {
+	return module.uniqueApexVariations()
+}
+
 func (module *SdkLibraryImport) OutputFiles(tag string) (android.Paths, error) {
 	return module.commonOutputFiles(tag)
 }
diff --git a/scripts/hiddenapi/verify_overlaps.py b/scripts/hiddenapi/verify_overlaps.py
index c8e3879..bb0917e 100755
--- a/scripts/hiddenapi/verify_overlaps.py
+++ b/scripts/hiddenapi/verify_overlaps.py
@@ -47,9 +47,9 @@
             if signature in allFlagsBySignature:
                 allFlags = allFlagsBySignature.get(signature)
                 if allFlags != row:
-                    mismatchingSignatures.append((signature, row[None], allFlags[None]))
+                    mismatchingSignatures.append((signature, row.get(None, []), allFlags.get(None, [])))
             else:
-                mismatchingSignatures.append((signature, row[None], []))
+                mismatchingSignatures.append((signature, row.get(None, []), []))
 
 
     if mismatchingSignatures:
@@ -60,7 +60,7 @@
         for mismatch in mismatchingSignatures:
             print()
             print("< " + mismatch[0] + "," + ",".join(mismatch[1]))
-            if mismatch[2] != None:
+            if mismatch[2] != []:
                 print("> " + mismatch[0] + "," + ",".join(mismatch[2]))
             else:
                 print("> " + mismatch[0] + " - missing")
diff --git a/sdk/bootclasspath_fragment_sdk_test.go b/sdk/bootclasspath_fragment_sdk_test.go
index 378f7cf..5e4b3fe 100644
--- a/sdk/bootclasspath_fragment_sdk_test.go
+++ b/sdk/bootclasspath_fragment_sdk_test.go
@@ -273,7 +273,7 @@
 				name: "myothersdklibrary",
 				apex_available: ["myapex"],
 				srcs: ["Test.java"],
-				shared_library: false,
+				compile_dex: true,
 				public: {enabled: true},
 				min_sdk_version: "2",
 				permitted_packages: ["myothersdklibrary"],
@@ -283,7 +283,7 @@
 				name: "mycoreplatform",
 				apex_available: ["myapex"],
 				srcs: ["Test.java"],
-				shared_library: false,
+				compile_dex: true,
 				public: {enabled: true},
 				min_sdk_version: "2",
 			}
@@ -334,7 +334,8 @@
     prefer: false,
     visibility: ["//visibility:public"],
     apex_available: ["myapex"],
-    shared_library: false,
+    shared_library: true,
+    compile_dex: true,
     public: {
         jars: ["sdk_library/public/myothersdklibrary-stubs.jar"],
         stub_srcs: ["sdk_library/public/myothersdklibrary_stub_sources"],
@@ -364,7 +365,8 @@
     prefer: false,
     visibility: ["//visibility:public"],
     apex_available: ["myapex"],
-    shared_library: false,
+    shared_library: true,
+    compile_dex: true,
     public: {
         jars: ["sdk_library/public/mycoreplatform-stubs.jar"],
         stub_srcs: ["sdk_library/public/mycoreplatform_stub_sources"],
@@ -414,7 +416,8 @@
     sdk_member_name: "myothersdklibrary",
     visibility: ["//visibility:public"],
     apex_available: ["myapex"],
-    shared_library: false,
+    shared_library: true,
+    compile_dex: true,
     public: {
         jars: ["sdk_library/public/myothersdklibrary-stubs.jar"],
         stub_srcs: ["sdk_library/public/myothersdklibrary_stub_sources"],
@@ -444,7 +447,8 @@
     sdk_member_name: "mycoreplatform",
     visibility: ["//visibility:public"],
     apex_available: ["myapex"],
-    shared_library: false,
+    shared_library: true,
+    compile_dex: true,
     public: {
         jars: ["sdk_library/public/mycoreplatform-stubs.jar"],
         stub_srcs: ["sdk_library/public/mycoreplatform_stub_sources"],
diff --git a/sdk/update.go b/sdk/update.go
index 13c2484..84f0e4e 100644
--- a/sdk/update.go
+++ b/sdk/update.go
@@ -148,6 +148,11 @@
 		if memberTag, ok := tag.(android.SdkMemberTypeDependencyTag); ok {
 			memberType := memberTag.SdkMemberType(child)
 
+			// If a nil SdkMemberType was returned then this module should not be added to the sdk.
+			if memberType == nil {
+				return false
+			}
+
 			// Make sure that the resolved module is allowed in the member list property.
 			if !memberType.IsInstance(child) {
 				ctx.ModuleErrorf("module %q is not valid in property %s", ctx.OtherModuleName(child), memberType.SdkPropertyName())