Merge "Add preprocessed property for android_test_import" into rvc-dev
diff --git a/android/neverallow.go b/android/neverallow.go
index f9fc03c..9e075b7 100644
--- a/android/neverallow.go
+++ b/android/neverallow.go
@@ -55,6 +55,7 @@
 	AddNeverAllowRules(createMediaRules()...)
 	AddNeverAllowRules(createJavaDeviceForHostRules()...)
 	AddNeverAllowRules(createCcSdkVariantRules()...)
+	AddNeverAllowRules(createUncompressDexRules()...)
 }
 
 // Add a NeverAllow rule to the set of rules to apply.
@@ -210,6 +211,15 @@
 	}
 }
 
+func createUncompressDexRules() []Rule {
+	return []Rule{
+		NeverAllow().
+			NotIn("art").
+			WithMatcher("uncompress_dex", isSetMatcherInstance).
+			Because("uncompress_dex is only allowed for certain jars for test in art."),
+	}
+}
+
 func neverallowMutator(ctx BottomUpMutatorContext) {
 	m, ok := ctx.Module().(Module)
 	if !ok {
diff --git a/android/neverallow_test.go b/android/neverallow_test.go
index 2fc42e3..85c8c59 100644
--- a/android/neverallow_test.go
+++ b/android/neverallow_test.go
@@ -303,6 +303,29 @@
 			`module "outside_whitelist": violates neverallow`,
 		},
 	},
+	{
+		name: "uncompress_dex inside art",
+		fs: map[string][]byte{
+			"art/Android.bp": []byte(`
+				java_library {
+					name: "inside_art_libraries",
+					uncompress_dex: true,
+				}`),
+		},
+	},
+	{
+		name: "uncompress_dex outside art",
+		fs: map[string][]byte{
+			"other/Android.bp": []byte(`
+				java_library {
+					name: "outside_art_libraries",
+					uncompress_dex: true,
+				}`),
+		},
+		expectedErrors: []string{
+			"module \"outside_art_libraries\": violates neverallow",
+		},
+	},
 }
 
 func TestNeverallow(t *testing.T) {
@@ -396,8 +419,9 @@
 }
 
 type mockJavaLibraryProperties struct {
-	Libs        []string
-	Sdk_version *string
+	Libs           []string
+	Sdk_version    *string
+	Uncompress_dex *bool
 }
 
 type mockJavaLibraryModule struct {
diff --git a/apex/apex.go b/apex/apex.go
index 7f153dc..dbbfe78 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -244,7 +244,14 @@
 	// Module separator
 	//
 	m["com.android.extservices"] = []string{
+		"error_prone_annotations",
+		"ExtServices-core",
+		"ExtServices",
+		"libtextclassifier-java",
 		"libz_current",
+		"textclassifier-statsd",
+		"TextClassifierNotificationLibNoManifest",
+		"TextClassifierServiceLibNoManifest",
 	}
 	//
 	// Module separator
@@ -292,7 +299,10 @@
 		"android.hidl.token@1.0",
 		"android.hidl.token@1.0-utils",
 		"bionic_libc_platform_headers",
+		"exoplayer2-extractor",
+		"exoplayer2-extractor-annotation-stubs",
 		"gl_headers",
+		"jsr305",
 		"libEGL",
 		"libEGL_blobCache",
 		"libEGL_getProcAddress",
@@ -549,12 +559,8 @@
 	// Module separator
 	//
 	m["com.android.permission"] = []string{
-		"androidx.annotation_annotation",
-		"androidx.annotation_annotation-nodeps",
-		"androidx.lifecycle_lifecycle-common",
-		"androidx.lifecycle_lifecycle-common-java8",
-		"androidx.lifecycle_lifecycle-common-java8-nodeps",
-		"androidx.lifecycle_lifecycle-common-nodeps",
+		"car-ui-lib",
+		"iconloader",
 		"kotlin-annotations",
 		"kotlin-stdlib",
 		"kotlin-stdlib-jdk7",
@@ -566,6 +572,15 @@
 		"permissioncontroller-statsd",
 		"GooglePermissionController",
 		"PermissionController",
+		"SettingsLibActionBarShadow",
+		"SettingsLibAppPreference",
+		"SettingsLibBarChartPreference",
+		"SettingsLibLayoutPreference",
+		"SettingsLibProgressBar",
+		"SettingsLibSearchWidget",
+		"SettingsLibSettingsTheme",
+		"SettingsLibRestrictedLockUtils",
+		"SettingsLibHelpUtils",
 	}
 	//
 	// Module separator
@@ -627,13 +642,21 @@
 	// Module separator
 	//
 	m["com.android.tethering"] = []string{
-		"libnativehelper_compat_libc++",
-		"android.hardware.tetheroffload.config@1.0",
+		"android.hardware.tetheroffload.config-V1.0-java",
+		"android.hardware.tetheroffload.control-V1.0-java",
+		"android.hidl.base-V1.0-java",
+		"ipmemorystore-aidl-interfaces-java",
 		"libcgrouprc",
 		"libcgrouprc_format",
+		"libnativehelper_compat_libc++",
 		"libtetherutilsjni",
 		"libvndksupport",
+		"net-utils-framework-common",
+		"netd_aidl_interface-V3-java",
+		"netlink-client",
+		"networkstack-aidl-interfaces-java",
 		"tethering-aidl-interfaces-java",
+		"TetheringApiCurrentLib",
 	}
 	//
 	// Module separator
@@ -657,8 +680,6 @@
 		"android.hidl.manager-V1.0-java",
 		"android.hidl.manager-V1.1-java",
 		"android.hidl.manager-V1.2-java",
-		"androidx.annotation_annotation",
-		"androidx.annotation_annotation-nodeps",
 		"bouncycastle-unbundled",
 		"dnsresolver_aidl_interface-V2-java",
 		"error_prone_annotations",
@@ -680,7 +701,6 @@
 		"wifi-nano-protos",
 		"wifi-service-pre-jarjar",
 		"wifi-service-resources",
-		"prebuilt_androidx.annotation_annotation-nodeps",
 	}
 	//
 	// Module separator
@@ -700,6 +720,15 @@
 	// Module separator
 	//
 	m[android.AvailableToAnyApex] = []string{
+		// TODO(b/156996905) Set apex_available/min_sdk_version for androidx/extras support libraries
+		"androidx",
+		"androidx-constraintlayout_constraintlayout",
+		"androidx-constraintlayout_constraintlayout-nodeps",
+		"androidx-constraintlayout_constraintlayout-solver",
+		"androidx-constraintlayout_constraintlayout-solver-nodeps",
+		"com.google.android.material_material",
+		"com.google.android.material_material-nodeps",
+
 		"libatomic",
 		"libclang_rt",
 		"libgcc_stripped",
@@ -2240,6 +2269,10 @@
 		// We don't want to list them all
 		moduleName = "libclang_rt"
 	}
+	if strings.HasPrefix(moduleName, "androidx.") {
+		// TODO(b/156996905) Set apex_available/min_sdk_version for androidx support libraries
+		moduleName = "androidx"
+	}
 	return moduleName
 }
 
diff --git a/apex/apex_test.go b/apex/apex_test.go
index ad46c30..3979149 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -19,6 +19,7 @@
 	"os"
 	"path"
 	"reflect"
+	"regexp"
 	"sort"
 	"strings"
 	"testing"
@@ -4020,6 +4021,15 @@
 	}
 }
 
+var filesForSdkLibrary = map[string][]byte{
+	"api/current.txt":        nil,
+	"api/removed.txt":        nil,
+	"api/system-current.txt": nil,
+	"api/system-removed.txt": nil,
+	"api/test-current.txt":   nil,
+	"api/test-removed.txt":   nil,
+}
+
 func TestJavaSDKLibrary(t *testing.T) {
 	ctx, _ := testApex(t, `
 		apex {
@@ -4040,14 +4050,7 @@
 			api_packages: ["foo"],
 			apex_available: [ "myapex" ],
 		}
-	`, withFiles(map[string][]byte{
-		"api/current.txt":        nil,
-		"api/removed.txt":        nil,
-		"api/system-current.txt": nil,
-		"api/system-removed.txt": nil,
-		"api/test-current.txt":   nil,
-		"api/test-removed.txt":   nil,
-	}))
+	`, withFiles(filesForSdkLibrary))
 
 	// java_sdk_library installs both impl jar and permission XML
 	ensureExactContents(t, ctx, "myapex", "android_common_myapex_image", []string{
@@ -4059,6 +4062,98 @@
 	ensureContains(t, sdkLibrary.RuleParams.Command, `<library name=\"foo\" file=\"/apex/myapex/javalib/foo.jar\"`)
 }
 
+func TestJavaSDKLibrary_WithinApex(t *testing.T) {
+	ctx, _ := testApex(t, `
+		apex {
+			name: "myapex",
+			key: "myapex.key",
+			java_libs: ["foo", "bar"],
+		}
+
+		apex_key {
+			name: "myapex.key",
+			public_key: "testkey.avbpubkey",
+			private_key: "testkey.pem",
+		}
+
+		java_sdk_library {
+			name: "foo",
+			srcs: ["a.java"],
+			api_packages: ["foo"],
+			apex_available: ["myapex"],
+			sdk_version: "none",
+			system_modules: "none",
+		}
+
+		java_library {
+			name: "bar",
+			srcs: ["a.java"],
+			libs: ["foo"],
+			apex_available: ["myapex"],
+			sdk_version: "none",
+			system_modules: "none",
+		}
+	`, withFiles(filesForSdkLibrary))
+
+	// java_sdk_library installs both impl jar and permission XML
+	ensureExactContents(t, ctx, "myapex", "android_common_myapex_image", []string{
+		"javalib/bar.jar",
+		"javalib/foo.jar",
+		"etc/permissions/foo.xml",
+	})
+
+	// The bar library should depend on the implementation jar.
+	barLibrary := ctx.ModuleForTests("bar", "android_common_myapex").Rule("javac")
+	if expected, actual := `^-classpath /[^:]*/turbine-combined/foo\.jar$`, barLibrary.Args["classpath"]; !regexp.MustCompile(expected).MatchString(actual) {
+		t.Errorf("expected %q, found %#q", expected, actual)
+	}
+}
+
+func TestJavaSDKLibrary_CrossBoundary(t *testing.T) {
+	ctx, _ := testApex(t, `
+		apex {
+			name: "myapex",
+			key: "myapex.key",
+			java_libs: ["foo"],
+		}
+
+		apex_key {
+			name: "myapex.key",
+			public_key: "testkey.avbpubkey",
+			private_key: "testkey.pem",
+		}
+
+		java_sdk_library {
+			name: "foo",
+			srcs: ["a.java"],
+			api_packages: ["foo"],
+			apex_available: ["myapex"],
+			sdk_version: "none",
+			system_modules: "none",
+		}
+
+		java_library {
+			name: "bar",
+			srcs: ["a.java"],
+			libs: ["foo"],
+			sdk_version: "none",
+			system_modules: "none",
+		}
+	`, withFiles(filesForSdkLibrary))
+
+	// java_sdk_library installs both impl jar and permission XML
+	ensureExactContents(t, ctx, "myapex", "android_common_myapex_image", []string{
+		"javalib/foo.jar",
+		"etc/permissions/foo.xml",
+	})
+
+	// The bar library should depend on the stubs jar.
+	barLibrary := ctx.ModuleForTests("bar", "android_common").Rule("javac")
+	if expected, actual := `^-classpath /[^:]*/turbine-combined/foo\.stubs\.jar$`, barLibrary.Args["classpath"]; !regexp.MustCompile(expected).MatchString(actual) {
+		t.Errorf("expected %q, found %#q", expected, actual)
+	}
+}
+
 func TestCompatConfig(t *testing.T) {
 	ctx, _ := testApex(t, `
 		apex {
diff --git a/cmd/extract_apks/main.go b/cmd/extract_apks/main.go
index a638db2..e9a850e 100644
--- a/cmd/extract_apks/main.go
+++ b/cmd/extract_apks/main.go
@@ -374,6 +374,10 @@
 			regexp.MustCompile(`^.*/` + selected.moduleName + `(-.*\.apk)$`),
 			config.stem + `$1`,
 		},
+		{
+			regexp.MustCompile(`^universal\.apk$`),
+			config.stem + ".apk",
+		},
 	}
 	renamer := func(path string) (string, bool) {
 		for _, rr := range renameRules {
diff --git a/cmd/extract_apks/main_test.go b/cmd/extract_apks/main_test.go
index bc4d377..bdd4bec 100644
--- a/cmd/extract_apks/main_test.go
+++ b/cmd/extract_apks/main_test.go
@@ -24,19 +24,19 @@
 	"android/soong/third_party/zip"
 )
 
-type TestConfigDesc struct {
+type testConfigDesc struct {
 	name         string
 	targetConfig TargetConfig
 	expected     SelectionResult
 }
 
-type TestDesc struct {
+type testDesc struct {
 	protoText string
-	configs   []TestConfigDesc
+	configs   []testConfigDesc
 }
 
 func TestSelectApks_ApkSet(t *testing.T) {
-	testCases := []TestDesc{
+	testCases := []testDesc{
 		{
 			protoText: `
 variant {
@@ -117,7 +117,7 @@
   version: "0.10.3" }
 
 `,
-			configs: []TestConfigDesc{
+			configs: []testConfigDesc{
 				{
 					name: "one",
 					targetConfig: TargetConfig{
@@ -209,7 +209,7 @@
           value { min { value: 21 } } } }
       path: "splits/base-master.apk"
       split_apk_metadata { is_master_split: true } } } }`,
-			configs: []TestConfigDesc{
+			configs: []testConfigDesc{
 				{
 					name: "Prerelease",
 					targetConfig: TargetConfig{
@@ -225,6 +225,30 @@
 				},
 			},
 		},
+		{
+			protoText: `
+variant {
+  targeting {
+    sdk_version_targeting {
+      value { min { value: 29 } } } }
+  apk_set {
+    module_metadata {
+      name: "base" targeting {} delivery_type: INSTALL_TIME }
+    apk_description {
+      targeting {}
+      path: "universal.apk"
+      standalone_apk_metadata { fused_module_name: "base" } } } }`,
+			configs: []testConfigDesc{
+				{
+					name:         "Universal",
+					targetConfig: TargetConfig{sdkVersion: 30},
+					expected: SelectionResult{
+						"base",
+						[]string{"universal.apk"},
+					},
+				},
+			},
+		},
 	}
 	for _, testCase := range testCases {
 		var toc bp.BuildApksResult
@@ -241,7 +265,7 @@
 }
 
 func TestSelectApks_ApexSet(t *testing.T) {
-	testCases := []TestDesc{
+	testCases := []testDesc{
 		{
 			protoText: `
 variant {
@@ -300,7 +324,7 @@
   version: "0.10.3" }
 
 `,
-			configs: []TestConfigDesc{
+			configs: []testConfigDesc{
 				{
 					name: "order matches priorities",
 					targetConfig: TargetConfig{
@@ -406,24 +430,48 @@
 	return nil
 }
 
-func TestWriteZip(t *testing.T) {
+type testCaseWriteZip struct {
+	name       string
+	moduleName string
+	stem       string
 	// what we write from what
-	expected := map[string]string{
-		"Foo.apk":       "splits/mybase-master.apk",
-		"Foo-xhdpi.apk": "splits/mybase-xhdpi.apk",
+	expected map[string]string
+}
+
+func TestWriteZip(t *testing.T) {
+	testCases := []testCaseWriteZip{
+		{
+			name:       "splits",
+			moduleName: "mybase",
+			stem:       "Foo",
+			expected: map[string]string{
+				"Foo.apk":       "splits/mybase-master.apk",
+				"Foo-xhdpi.apk": "splits/mybase-xhdpi.apk",
+			},
+		},
+		{
+			name:       "universal",
+			moduleName: "base",
+			stem:       "Bar",
+			expected: map[string]string{
+				"Bar.apk": "universal.apk",
+			},
+		},
 	}
-	apkSet := ApkSet{entries: make(map[string]*zip.File)}
-	sel := SelectionResult{moduleName: "mybase"}
-	for _, in := range expected {
-		apkSet.entries[in] = &zip.File{FileHeader: zip.FileHeader{Name: in}}
-		sel.entries = append(sel.entries, in)
-	}
-	writer := testZip2ZipWriter{make(map[string]string)}
-	config := TargetConfig{stem: "Foo"}
-	if err := apkSet.writeApks(sel, config, writer); err != nil {
-		t.Error(err)
-	}
-	if !reflect.DeepEqual(expected, writer.entries) {
-		t.Errorf("expected %v, got %v", expected, writer.entries)
+	for _, testCase := range testCases {
+		apkSet := ApkSet{entries: make(map[string]*zip.File)}
+		sel := SelectionResult{moduleName: testCase.moduleName}
+		for _, in := range testCase.expected {
+			apkSet.entries[in] = &zip.File{FileHeader: zip.FileHeader{Name: in}}
+			sel.entries = append(sel.entries, in)
+		}
+		writer := testZip2ZipWriter{make(map[string]string)}
+		config := TargetConfig{stem: testCase.stem}
+		if err := apkSet.writeApks(sel, config, writer); err != nil {
+			t.Error(err)
+		}
+		if !reflect.DeepEqual(testCase.expected, writer.entries) {
+			t.Errorf("expected %v, got %v", testCase.expected, writer.entries)
+		}
 	}
 }
diff --git a/java/aar.go b/java/aar.go
index 6e3b9e6..c8daf83 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -379,8 +379,11 @@
 				sharedLibs = append(sharedLibs, exportPackage)
 			}
 
-			if _, ok := module.(SdkLibraryDependency); ok {
-				sdkLibraries = append(sdkLibraries, ctx.OtherModuleName(module))
+			// If the module is (or possibly could be) a component of a java_sdk_library
+			// (including the java_sdk_library) itself then append any implicit sdk library
+			// names to the list of sdk libraries to be added to the manifest.
+			if component, ok := module.(SdkLibraryComponentDependency); ok {
+				sdkLibraries = append(sdkLibraries, component.OptionalImplicitSdkLibrary()...)
 			}
 
 		case frameworkResTag:
@@ -513,6 +516,7 @@
 
 	module.androidLibraryProperties.BuildAAR = true
 
+	android.InitApexModule(module)
 	InitJavaModule(module, android.DeviceSupported)
 	return module
 }
@@ -537,8 +541,12 @@
 type AARImport struct {
 	android.ModuleBase
 	android.DefaultableModuleBase
+	android.ApexModuleBase
 	prebuilt android.Prebuilt
 
+	// Functionality common to Module and Import.
+	embeddableInModuleAndImport
+
 	properties AARImportProperties
 
 	classpathFile         android.WritablePath
@@ -742,6 +750,10 @@
 	return nil, nil
 }
 
+func (a *AARImport) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
+	return a.depIsInSameApex(ctx, dep)
+}
+
 var _ android.PrebuiltInterface = (*Import)(nil)
 
 // android_library_import imports an `.aar` file into the build graph as if it was built with android_library.
@@ -754,6 +766,7 @@
 	module.AddProperties(&module.properties)
 
 	android.InitPrebuiltModule(module, &module.properties.Aars)
+	android.InitApexModule(module)
 	InitJavaModule(module, android.DeviceSupported)
 	return module
 }
diff --git a/java/androidmk.go b/java/androidmk.go
index 41a3dc7..861bb5e 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -211,6 +211,11 @@
 }
 
 func (prebuilt *AARImport) AndroidMkEntries() []android.AndroidMkEntries {
+	if !prebuilt.IsForPlatform() {
+		return []android.AndroidMkEntries{{
+			Disabled: true,
+		}}
+	}
 	return []android.AndroidMkEntries{android.AndroidMkEntries{
 		Class:      "JAVA_LIBRARIES",
 		OutputFile: android.OptionalPathForPath(prebuilt.classpathFile),
@@ -416,6 +421,11 @@
 }
 
 func (a *AndroidLibrary) AndroidMkEntries() []android.AndroidMkEntries {
+	if !a.IsForPlatform() {
+		return []android.AndroidMkEntries{{
+			Disabled: true,
+		}}
+	}
 	entriesList := a.Library.AndroidMkEntries()
 	entries := &entriesList[0]
 
diff --git a/java/app.go b/java/app.go
index 5d45d33..1fc18fb 100755
--- a/java/app.go
+++ b/java/app.go
@@ -540,16 +540,17 @@
 		installDir = filepath.Join("app", a.installApkName)
 	}
 	a.dexpreopter.installPath = android.PathForModuleInstall(ctx, installDir, a.installApkName+".apk")
-	a.dexpreopter.uncompressedDex = a.shouldUncompressDex(ctx)
-
+	if a.deviceProperties.Uncompress_dex == nil {
+		// If the value was not force-set by the user, use reasonable default based on the module.
+		a.deviceProperties.Uncompress_dex = proptools.BoolPtr(a.shouldUncompressDex(ctx))
+	}
+	a.dexpreopter.uncompressedDex = *a.deviceProperties.Uncompress_dex
 	a.dexpreopter.enforceUsesLibs = a.usesLibrary.enforceUsesLibraries()
 	a.dexpreopter.usesLibs = a.usesLibrary.usesLibraryProperties.Uses_libs
 	a.dexpreopter.optionalUsesLibs = a.usesLibrary.presentOptionalUsesLibs(ctx)
 	a.dexpreopter.libraryPaths = a.usesLibrary.usesLibraryPaths(ctx)
 	a.dexpreopter.manifestFile = a.mergedManifestFile
 
-	a.deviceProperties.UncompressDex = a.dexpreopter.uncompressedDex
-
 	if ctx.ModuleName() != "framework-res" {
 		a.Module.compile(ctx, a.aaptSrcJar)
 	}
@@ -1648,6 +1649,9 @@
 	// module name in the form ":module".
 	Certificate *string
 
+	// Name of the signing certificate lineage file.
+	Lineage *string
+
 	// optional theme name. If specified, the overlay package will be applied
 	// only when the ro.boot.vendor.overlay.theme system property is set to the same value.
 	Theme *string
@@ -1713,7 +1717,11 @@
 	_, certificates := collectAppDeps(ctx, r, false, false)
 	certificates = processMainCert(r.ModuleBase, String(r.properties.Certificate), certificates, ctx)
 	signed := android.PathForModuleOut(ctx, "signed", r.Name()+".apk")
-	SignAppPackage(ctx, signed, r.aapt.exportPackage, certificates, nil, nil)
+	var lineageFile android.Path
+	if lineage := String(r.properties.Lineage); lineage != "" {
+		lineageFile = android.PathForModuleSrc(ctx, lineage)
+	}
+	SignAppPackage(ctx, signed, r.aapt.exportPackage, certificates, nil, lineageFile)
 	r.certificate = certificates[0]
 
 	r.outputFile = signed
diff --git a/java/app_test.go b/java/app_test.go
index b10fefa..8afd97d 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -2422,6 +2422,20 @@
 		}
 
 		java_sdk_library {
+			name: "qux",
+			srcs: ["a.java"],
+			api_packages: ["qux"],
+			sdk_version: "current",
+		}
+
+		java_sdk_library {
+			name: "quuz",
+			srcs: ["a.java"],
+			api_packages: ["quuz"],
+			sdk_version: "current",
+		}
+
+		java_sdk_library {
 			name: "bar",
 			srcs: ["a.java"],
 			api_packages: ["bar"],
@@ -2431,6 +2445,7 @@
 		android_app {
 			name: "app",
 			srcs: ["a.java"],
+			libs: ["qux", "quuz.stubs"],
 			uses_libs: ["foo"],
 			sdk_version: "current",
 			optional_uses_libs: [
@@ -2461,6 +2476,15 @@
 	app := ctx.ModuleForTests("app", "android_common")
 	prebuilt := ctx.ModuleForTests("prebuilt", "android_common")
 
+	// Test that implicit dependencies on java_sdk_library instances are passed to the manifest.
+	manifestFixerArgs := app.Output("manifest_fixer/AndroidManifest.xml").Args["args"]
+	if w := "--uses-library qux"; !strings.Contains(manifestFixerArgs, w) {
+		t.Errorf("unexpected manifest_fixer args: wanted %q in %q", w, manifestFixerArgs)
+	}
+	if w := "--uses-library quuz"; !strings.Contains(manifestFixerArgs, w) {
+		t.Errorf("unexpected manifest_fixer args: wanted %q in %q", w, manifestFixerArgs)
+	}
+
 	// Test that all libraries are verified
 	cmd := app.Rule("verify_uses_libraries").RuleParams.Command
 	if w := "--uses-library foo"; !strings.Contains(cmd, w) {
@@ -2721,6 +2745,32 @@
 			uncompressedPlatform:  true,
 			uncompressedUnbundled: true,
 		},
+		{
+			name: "normal_uncompress_dex_true",
+			bp: `
+				android_app {
+					name: "foo",
+					srcs: ["a.java"],
+					sdk_version: "current",
+					uncompress_dex: true,
+				}
+			`,
+			uncompressedPlatform:  true,
+			uncompressedUnbundled: true,
+		},
+		{
+			name: "normal_uncompress_dex_false",
+			bp: `
+				android_app {
+					name: "foo",
+					srcs: ["a.java"],
+					sdk_version: "current",
+					uncompress_dex: false,
+				}
+			`,
+			uncompressedPlatform:  false,
+			uncompressedUnbundled: false,
+		},
 	}
 
 	test := func(t *testing.T, bp string, want bool, unbundled bool) {
@@ -2784,6 +2834,7 @@
 		runtime_resource_overlay {
 			name: "foo",
 			certificate: "platform",
+			lineage: "lineage.bin",
 			product_specific: true,
 			static_libs: ["bar"],
 			resource_libs: ["baz"],
@@ -2838,6 +2889,11 @@
 
 	// Check cert signing flag.
 	signedApk := m.Output("signed/foo.apk")
+	lineageFlag := signedApk.Args["flags"]
+	expectedLineageFlag := "--lineage lineage.bin"
+	if expectedLineageFlag != lineageFlag {
+		t.Errorf("Incorrect signing lineage flags, expected: %q, got: %q", expectedLineageFlag, lineageFlag)
+	}
 	signingFlag := signedApk.Args["certificates"]
 	expected := "build/make/target/product/security/platform.x509.pem build/make/target/product/security/platform.pk8"
 	if expected != signingFlag {
diff --git a/java/dex.go b/java/dex.go
index 6afdb6d..62f17c6 100644
--- a/java/dex.go
+++ b/java/dex.go
@@ -18,6 +18,7 @@
 	"strings"
 
 	"github.com/google/blueprint"
+	"github.com/google/blueprint/proptools"
 
 	"android/soong/android"
 )
@@ -177,7 +178,7 @@
 	outDir := android.PathForModuleOut(ctx, "dex")
 
 	zipFlags := "--ignore_missing_files"
-	if j.deviceProperties.UncompressDex {
+	if proptools.Bool(j.deviceProperties.Uncompress_dex) {
 		zipFlags += " -L 0"
 	}
 
@@ -214,7 +215,7 @@
 			},
 		})
 	}
-	if j.deviceProperties.UncompressDex {
+	if proptools.Bool(j.deviceProperties.Uncompress_dex) {
 		alignedJavalibJar := android.PathForModuleOut(ctx, "aligned", jarName)
 		TransformZipAlign(ctx, alignedJavalibJar, javalibJar)
 		javalibJar = alignedJavalibJar
diff --git a/java/droiddoc.go b/java/droiddoc.go
index 62a6661..cf4c892 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -350,11 +350,16 @@
 	ApiFilePath() android.Path
 }
 
+type ApiStubsSrcProvider interface {
+	StubsSrcJar() android.Path
+}
+
 // Provider of information about API stubs, used by java_sdk_library.
 type ApiStubsProvider interface {
 	ApiFilePath
 	RemovedApiFilePath() android.Path
-	StubsSrcJar() android.Path
+
+	ApiStubsSrcProvider
 }
 
 //
@@ -540,7 +545,7 @@
 		case libTag:
 			switch dep := module.(type) {
 			case SdkLibraryDependency:
-				deps.classpath = append(deps.classpath, dep.SdkImplementationJars(ctx, j.sdkVersion())...)
+				deps.classpath = append(deps.classpath, dep.SdkHeaderJars(ctx, j.sdkVersion())...)
 			case Dependency:
 				deps.classpath = append(deps.classpath, dep.HeaderJars()...)
 				deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, dep.AidlIncludeDirs()...)
@@ -1308,13 +1313,10 @@
 		d.annotationsZip = android.PathForModuleOut(ctx, ctx.ModuleName()+"_annotations.zip")
 		cmd.FlagWithOutput("--extract-annotations ", d.annotationsZip)
 
-		if len(d.properties.Merge_annotations_dirs) == 0 {
-			ctx.PropertyErrorf("merge_annotations_dirs",
-				"has to be non-empty if annotations was enabled!")
+		if len(d.properties.Merge_annotations_dirs) != 0 {
+			d.mergeAnnoDirFlags(ctx, cmd)
 		}
 
-		d.mergeAnnoDirFlags(ctx, cmd)
-
 		// TODO(tnorbye): find owners to fix these warnings when annotation was enabled.
 		cmd.FlagWithArg("--hide ", "HiddenTypedefConstant").
 			FlagWithArg("--hide ", "SuperfluousPrefix").
@@ -1915,6 +1917,10 @@
 	}
 }
 
+func (d *PrebuiltStubsSources) StubsSrcJar() android.Path {
+	return d.stubsSrcJar
+}
+
 func (p *PrebuiltStubsSources) GenerateAndroidBuildActions(ctx android.ModuleContext) {
 	p.stubsSrcJar = android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"stubs.srcjar")
 
diff --git a/java/java.go b/java/java.go
index da9bd3d..da6879d 100644
--- a/java/java.go
+++ b/java/java.go
@@ -342,8 +342,13 @@
 	// set the name of the output
 	Stem *string
 
-	UncompressDex bool `blueprint:"mutated"`
-	IsSDKLibrary  bool `blueprint:"mutated"`
+	// Keep the data uncompressed. We always need uncompressed dex for execution,
+	// so this might actually save space by avoiding storing the same data twice.
+	// This defaults to reasonable value based on module and should not be set.
+	// It exists only to support ART tests.
+	Uncompress_dex *bool
+
+	IsSDKLibrary bool `blueprint:"mutated"`
 
 	// If true, generate the signature file of APK Signing Scheme V4, along side the signed APK file.
 	// Defaults to false.
@@ -355,7 +360,17 @@
 }
 
 // Functionality common to Module and Import
+//
+// It is embedded in Module so its functionality can be used by methods in Module
+// but it is currently only initialized by Import and Library.
 type embeddableInModuleAndImport struct {
+
+	// Functionality related to this being used as a component of a java_sdk_library.
+	EmbeddableSdkLibraryComponent
+}
+
+func (e *embeddableInModuleAndImport) initModuleAndImport(moduleBase *android.ModuleBase) {
+	e.initSdkLibraryComponent(moduleBase)
 }
 
 // Module/Import's DepIsInSameApex(...) delegates to this method.
@@ -496,11 +511,6 @@
 	JacocoReportClassesFile() android.Path
 }
 
-type SdkLibraryDependency interface {
-	SdkHeaderJars(ctx android.BaseModuleContext, sdkVersion sdkSpec) android.Paths
-	SdkImplementationJars(ctx android.BaseModuleContext, sdkVersion sdkSpec) android.Paths
-}
-
 type xref interface {
 	XrefJavaFiles() android.Paths
 }
@@ -827,41 +837,42 @@
 }
 
 func (m *Module) getLinkType(name string) (ret linkType, stubs bool) {
-	ver := m.sdkVersion()
-	switch {
-	case name == "core.current.stubs" || name == "core.platform.api.stubs" ||
-		name == "stub-annotations" || name == "private-stub-annotations-jar" ||
-		name == "core-lambda-stubs" || name == "core-generated-annotation-stubs":
+	switch name {
+	case "core.current.stubs", "core.platform.api.stubs", "stub-annotations",
+		"private-stub-annotations-jar", "core-lambda-stubs", "core-generated-annotation-stubs":
 		return javaCore, true
-	case ver.kind == sdkCore:
-		return javaCore, false
-	case name == "android_system_stubs_current":
-		return javaSystem, true
-	case ver.kind == sdkSystem:
-		return javaSystem, false
-	case name == "android_test_stubs_current":
-		return javaSystem, true
-	case ver.kind == sdkTest:
-		return javaPlatform, false
-	case name == "android_stubs_current":
+	case "android_stubs_current":
 		return javaSdk, true
-	case ver.kind == sdkPublic:
-		return javaSdk, false
-	case name == "android_module_lib_stubs_current":
+	case "android_system_stubs_current":
+		return javaSystem, true
+	case "android_module_lib_stubs_current":
 		return javaModule, true
-	case ver.kind == sdkModule:
-		return javaModule, false
-	case name == "android_system_server_stubs_current":
+	case "android_system_server_stubs_current":
 		return javaSystemServer, true
-	case ver.kind == sdkSystemServer:
-		return javaSystemServer, false
-	case ver.kind == sdkPrivate || ver.kind == sdkNone || ver.kind == sdkCorePlatform:
-		return javaPlatform, false
-	case !ver.valid():
-		panic(fmt.Errorf("sdk_version is invalid. got %q", ver.raw))
-	default:
-		return javaSdk, false
+	case "android_test_stubs_current":
+		return javaSystem, true
 	}
+
+	ver := m.sdkVersion()
+	switch ver.kind {
+	case sdkCore:
+		return javaCore, false
+	case sdkSystem:
+		return javaSystem, false
+	case sdkPublic:
+		return javaSdk, false
+	case sdkModule:
+		return javaModule, false
+	case sdkSystemServer:
+		return javaSystemServer, false
+	case sdkPrivate, sdkNone, sdkCorePlatform, sdkTest:
+		return javaPlatform, false
+	}
+
+	if !ver.valid() {
+		panic(fmt.Errorf("sdk_version is invalid. got %q", ver.raw))
+	}
+	return javaSdk, false
 }
 
 func checkLinkType(ctx android.ModuleContext, from *Module, to linkTypeContext, tag dependencyTag) {
@@ -930,6 +941,12 @@
 		}
 	}
 
+	// If this is a component library (stubs, etc.) for a java_sdk_library then
+	// add the name of that java_sdk_library to the exported sdk libs to make sure
+	// that, if necessary, a <uses-library> element for that java_sdk_library is
+	// added to the Android manifest.
+	j.exportedSdkLibs = append(j.exportedSdkLibs, j.OptionalImplicitSdkLibrary()...)
+
 	ctx.VisitDirectDeps(func(module android.Module) {
 		otherName := ctx.OtherModuleName(module)
 		tag := ctx.OtherModuleDependencyTag(module)
@@ -949,7 +966,7 @@
 			case libTag:
 				deps.classpath = append(deps.classpath, dep.SdkHeaderJars(ctx, j.sdkVersion())...)
 				// names of sdk libs that are directly depended are exported
-				j.exportedSdkLibs = append(j.exportedSdkLibs, otherName)
+				j.exportedSdkLibs = append(j.exportedSdkLibs, dep.OptionalImplicitSdkLibrary()...)
 			case staticLibTag:
 				ctx.ModuleErrorf("dependency on java_sdk_library %q can only be in libs", otherName)
 			}
@@ -1560,7 +1577,7 @@
 
 		// Hidden API CSV generation and dex encoding
 		dexOutputFile = j.hiddenAPI.hiddenAPI(ctx, dexOutputFile, j.implementationJarFile,
-			j.deviceProperties.UncompressDex)
+			proptools.Bool(j.deviceProperties.Uncompress_dex))
 
 		// merge dex jar with resources if necessary
 		if j.resourceJar != nil {
@@ -1568,7 +1585,7 @@
 			combinedJar := android.PathForModuleOut(ctx, "dex-withres", jarName)
 			TransformJarsToJar(ctx, combinedJar, "for dex resources", jars, android.OptionalPath{},
 				false, nil, nil)
-			if j.deviceProperties.UncompressDex {
+			if *j.deviceProperties.Uncompress_dex {
 				combinedAlignedJar := android.PathForModuleOut(ctx, "dex-withres-aligned", jarName)
 				TransformZipAlign(ctx, combinedAlignedJar, combinedJar)
 				dexOutputFile = combinedAlignedJar
@@ -1845,8 +1862,11 @@
 	j.checkSdkVersions(ctx)
 	j.dexpreopter.installPath = android.PathForModuleInstall(ctx, "framework", j.Stem()+".jar")
 	j.dexpreopter.isSDKLibrary = j.deviceProperties.IsSDKLibrary
-	j.dexpreopter.uncompressedDex = shouldUncompressDex(ctx, &j.dexpreopter)
-	j.deviceProperties.UncompressDex = j.dexpreopter.uncompressedDex
+	if j.deviceProperties.Uncompress_dex == nil {
+		// If the value was not force-set by the user, use reasonable default based on the module.
+		j.deviceProperties.Uncompress_dex = proptools.BoolPtr(shouldUncompressDex(ctx, &j.dexpreopter))
+	}
+	j.dexpreopter.uncompressedDex = *j.deviceProperties.Uncompress_dex
 	j.compile(ctx, nil)
 
 	exclusivelyForApex := android.InAnyApex(ctx.ModuleName()) && !j.IsForPlatform()
@@ -1990,6 +2010,8 @@
 		&module.Module.protoProperties,
 		&module.libraryProperties)
 
+	module.initModuleAndImport(&module.ModuleBase)
+
 	android.InitApexModule(module)
 	android.InitSdkAwareModule(module)
 	InitJavaModule(module, android.HostAndDeviceSupported)
@@ -2451,6 +2473,12 @@
 	}
 	j.combinedClasspathFile = outputFile
 
+	// If this is a component library (impl, stubs, etc.) for a java_sdk_library then
+	// add the name of that java_sdk_library to the exported sdk libs to make sure
+	// that, if necessary, a <uses-library> element for that java_sdk_library is
+	// added to the Android manifest.
+	j.exportedSdkLibs = append(j.exportedSdkLibs, j.OptionalImplicitSdkLibrary()...)
+
 	ctx.VisitDirectDeps(func(module android.Module) {
 		otherName := ctx.OtherModuleName(module)
 		tag := ctx.OtherModuleDependencyTag(module)
@@ -2567,6 +2595,8 @@
 
 	module.AddProperties(&module.properties)
 
+	module.initModuleAndImport(&module.ModuleBase)
+
 	android.InitPrebuiltModule(module, &module.properties.Jars)
 	android.InitApexModule(module)
 	android.InitSdkAwareModule(module)
diff --git a/java/java_test.go b/java/java_test.go
index 01ddccf..385fe6a 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -19,6 +19,8 @@
 	"os"
 	"path/filepath"
 	"reflect"
+	"regexp"
+	"sort"
 	"strconv"
 	"strings"
 	"testing"
@@ -575,6 +577,7 @@
 			},
 			test: {
 				jars: ["c.jar"],
+				stub_srcs: ["c.java"],
 			},
 		}
 		`)
@@ -1152,13 +1155,42 @@
 		java_library {
 			name: "baz",
 			srcs: ["c.java"],
-			libs: ["foo", "bar"],
+			libs: ["foo", "bar.stubs"],
 			sdk_version: "system_current",
 		}
+		java_sdk_library {
+			name: "barney",
+			srcs: ["c.java"],
+			api_only: true,
+		}
+		java_sdk_library {
+			name: "betty",
+			srcs: ["c.java"],
+			shared_library: false,
+		}
+		java_sdk_library_import {
+		    name: "quuz",
+				public: {
+					jars: ["c.jar"],
+				},
+		}
+		java_sdk_library_import {
+		    name: "fred",
+				public: {
+					jars: ["b.jar"],
+				},
+		}
+		java_sdk_library_import {
+		    name: "wilma",
+				public: {
+					jars: ["b.jar"],
+				},
+				shared_library: false,
+		}
 		java_library {
 		    name: "qux",
 		    srcs: ["c.java"],
-		    libs: ["baz"],
+		    libs: ["baz", "fred", "quuz.stubs", "wilma", "barney", "betty"],
 		    sdk_version: "system_current",
 		}
 		java_library {
@@ -1223,12 +1255,145 @@
 	qux := ctx.ModuleForTests("qux", "android_common")
 	if quxLib, ok := qux.Module().(*Library); ok {
 		sdkLibs := quxLib.ExportedSdkLibs()
-		if len(sdkLibs) != 2 || !android.InList("foo", sdkLibs) || !android.InList("bar", sdkLibs) {
-			t.Errorf("qux should export \"foo\" and \"bar\" but exports %v", sdkLibs)
+		sort.Strings(sdkLibs)
+		if w := []string{"bar", "foo", "fred", "quuz"}; !reflect.DeepEqual(w, sdkLibs) {
+			t.Errorf("qux should export %q but exports %q", w, sdkLibs)
 		}
 	}
 }
 
+func TestJavaSdkLibrary_DoNotAccessImplWhenItIsNotBuilt(t *testing.T) {
+	ctx, _ := testJava(t, `
+		java_sdk_library {
+			name: "foo",
+			srcs: ["a.java"],
+			api_only: true,
+			public: {
+				enabled: true,
+			},
+		}
+
+		java_library {
+			name: "bar",
+			srcs: ["b.java"],
+			libs: ["foo"],
+		}
+		`)
+
+	// The bar library should depend on the stubs jar.
+	barLibrary := ctx.ModuleForTests("bar", "android_common").Rule("javac")
+	if expected, actual := `^-classpath .*:/[^:]*/turbine-combined/foo\.stubs\.jar$`, barLibrary.Args["classpath"]; !regexp.MustCompile(expected).MatchString(actual) {
+		t.Errorf("expected %q, found %#q", expected, actual)
+	}
+}
+
+func TestJavaSdkLibrary_UseSourcesFromAnotherSdkLibrary(t *testing.T) {
+	testJava(t, `
+		java_sdk_library {
+			name: "foo",
+			srcs: ["a.java"],
+			api_packages: ["foo"],
+			public: {
+				enabled: true,
+			},
+		}
+
+		java_library {
+			name: "bar",
+			srcs: ["b.java", ":foo{.public.stubs.source}"],
+		}
+		`)
+}
+
+func TestJavaSdkLibrary_AccessOutputFiles_MissingScope(t *testing.T) {
+	testJavaError(t, `"foo" does not provide api scope system`, `
+		java_sdk_library {
+			name: "foo",
+			srcs: ["a.java"],
+			api_packages: ["foo"],
+			public: {
+				enabled: true,
+			},
+		}
+
+		java_library {
+			name: "bar",
+			srcs: ["b.java", ":foo{.system.stubs.source}"],
+		}
+		`)
+}
+
+func TestJavaSdkLibraryImport_AccessOutputFiles(t *testing.T) {
+	testJava(t, `
+		java_sdk_library_import {
+			name: "foo",
+			public: {
+				jars: ["a.jar"],
+				stub_srcs: ["a.java"],
+				current_api: "api/current.txt",
+				removed_api: "api/removed.txt",
+			},
+		}
+
+		java_library {
+			name: "bar",
+			srcs: [":foo{.public.stubs.source}"],
+			java_resources: [
+				":foo{.public.api.txt}",
+				":foo{.public.removed-api.txt}",
+			],
+		}
+		`)
+}
+
+func TestJavaSdkLibraryImport_AccessOutputFiles_Invalid(t *testing.T) {
+	bp := `
+		java_sdk_library_import {
+			name: "foo",
+			public: {
+				jars: ["a.jar"],
+			},
+		}
+		`
+
+	t.Run("stubs.source", func(t *testing.T) {
+		testJavaError(t, `stubs.source not available for api scope public`, bp+`
+		java_library {
+			name: "bar",
+			srcs: [":foo{.public.stubs.source}"],
+			java_resources: [
+				":foo{.public.api.txt}",
+				":foo{.public.removed-api.txt}",
+			],
+		}
+		`)
+	})
+
+	t.Run("api.txt", func(t *testing.T) {
+		testJavaError(t, `api.txt not available for api scope public`, bp+`
+		java_library {
+			name: "bar",
+			srcs: ["a.java"],
+			java_resources: [
+				":foo{.public.api.txt}",
+			],
+		}
+		`)
+	})
+
+	t.Run("removed-api.txt", func(t *testing.T) {
+		testJavaError(t, `removed-api.txt not available for api scope public`, bp+`
+		java_library {
+			name: "bar",
+			srcs: ["a.java"],
+			java_resources: [
+				":foo{.public.removed-api.txt}",
+			],
+		}
+		`)
+	})
+}
+
 func TestJavaSdkLibrary_InvalidScopes(t *testing.T) {
 	testJavaError(t, `module "foo": enabled api scope "system" depends on disabled scope "public"`, `
 		java_sdk_library {
@@ -1261,6 +1426,45 @@
 		`)
 }
 
+func TestJavaSdkLibrary_MissingScope(t *testing.T) {
+	testJavaError(t, `requires api scope module-lib from foo but it only has \[\] available`, `
+		java_sdk_library {
+			name: "foo",
+			srcs: ["a.java"],
+			public: {
+				enabled: false,
+			},
+		}
+
+		java_library {
+			name: "baz",
+			srcs: ["a.java"],
+			libs: ["foo"],
+			sdk_version: "module_current",
+		}
+		`)
+}
+
+func TestJavaSdkLibrary_FallbackScope(t *testing.T) {
+	testJava(t, `
+		java_sdk_library {
+			name: "foo",
+			srcs: ["a.java"],
+			system: {
+				enabled: true,
+			},
+		}
+
+		java_library {
+			name: "baz",
+			srcs: ["a.java"],
+			libs: ["foo"],
+			// foo does not have module-lib scope so it should fallback to system
+			sdk_version: "module_current",
+		}
+		`)
+}
+
 var compilerFlagsTestCases = []struct {
 	in  string
 	out bool
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 61bb106..43a340e 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -19,6 +19,7 @@
 	"path"
 	"path/filepath"
 	"reflect"
+	"regexp"
 	"sort"
 	"strings"
 	"sync"
@@ -145,6 +146,8 @@
 // Initialize a scope, creating and adding appropriate dependency tags
 func initApiScope(scope *apiScope) *apiScope {
 	name := scope.name
+	scopeByName[name] = scope
+	allScopeNames = append(allScopeNames, name)
 	scope.propertyName = strings.ReplaceAll(name, "-", "_")
 	scope.fieldName = proptools.FieldNameForProperty(scope.propertyName)
 	scope.stubsTag = scopeDependencyTag{
@@ -217,6 +220,8 @@
 }
 
 var (
+	scopeByName    = make(map[string]*apiScope)
+	allScopeNames  []string
 	apiScopePublic = initApiScope(&apiScope{
 		name: "public",
 
@@ -367,7 +372,10 @@
 	// Defaults to "api".
 	Api_dir *string
 
-	// If set to true there is no runtime library.
+	// Determines whether a runtime implementation library is built; defaults to false.
+	//
+	// If true then it also prevents the module from being used as a shared module, i.e.
+	// it is as is shared_library: false, was set.
 	Api_only *bool
 
 	// local files that are used within user customized droiddoc options.
@@ -433,12 +441,30 @@
 	//Html_doc *bool
 }
 
+// Paths to outputs from java_sdk_library and java_sdk_library_import.
+//
+// Fields that are android.Paths are always set (during GenerateAndroidBuildActions).
+// OptionalPaths are always set by java_sdk_library but may not be set by
+// java_sdk_library_import as not all instances provide that information.
 type scopePaths struct {
-	stubsHeaderPath    android.Paths
-	stubsImplPath      android.Paths
-	currentApiFilePath android.Path
-	removedApiFilePath android.Path
-	stubsSrcJar        android.Path
+	// The path (represented as Paths for convenience when returning) to the stubs header jar.
+	//
+	// That is the jar that is created by turbine.
+	stubsHeaderPath android.Paths
+
+	// The path (represented as Paths for convenience when returning) to the stubs implementation jar.
+	//
+	// This is not the implementation jar, it still only contains stubs.
+	stubsImplPath android.Paths
+
+	// The API specification file, e.g. system_current.txt.
+	currentApiFilePath android.OptionalPath
+
+	// The specification of API elements removed since the last release.
+	removedApiFilePath android.OptionalPath
+
+	// The stubs source jar.
+	stubsSrcJar android.OptionalPath
 }
 
 func (paths *scopePaths) extractStubsLibraryInfoFromDependency(dep android.Module) error {
@@ -460,9 +486,18 @@
 	}
 }
 
+func (paths *scopePaths) treatDepAsApiStubsSrcProvider(dep android.Module, action func(provider ApiStubsSrcProvider)) error {
+	if apiStubsProvider, ok := dep.(ApiStubsSrcProvider); ok {
+		action(apiStubsProvider)
+		return nil
+	} else {
+		return fmt.Errorf("expected module that implements ApiStubsSrcProvider, e.g. droidstubs")
+	}
+}
+
 func (paths *scopePaths) extractApiInfoFromApiStubsProvider(provider ApiStubsProvider) {
-	paths.currentApiFilePath = provider.ApiFilePath()
-	paths.removedApiFilePath = provider.RemovedApiFilePath()
+	paths.currentApiFilePath = android.OptionalPathForPath(provider.ApiFilePath())
+	paths.removedApiFilePath = android.OptionalPathForPath(provider.RemovedApiFilePath())
 }
 
 func (paths *scopePaths) extractApiInfoFromDep(dep android.Module) error {
@@ -471,12 +506,12 @@
 	})
 }
 
-func (paths *scopePaths) extractStubsSourceInfoFromApiStubsProviders(provider ApiStubsProvider) {
-	paths.stubsSrcJar = provider.StubsSrcJar()
+func (paths *scopePaths) extractStubsSourceInfoFromApiStubsProviders(provider ApiStubsSrcProvider) {
+	paths.stubsSrcJar = android.OptionalPathForPath(provider.StubsSrcJar())
 }
 
 func (paths *scopePaths) extractStubsSourceInfoFromDep(dep android.Module) error {
-	return paths.treatDepAsApiStubsProvider(dep, func(provider ApiStubsProvider) {
+	return paths.treatDepAsApiStubsSrcProvider(dep, func(provider ApiStubsSrcProvider) {
 		paths.extractStubsSourceInfoFromApiStubsProviders(provider)
 	})
 }
@@ -500,6 +535,13 @@
 	//
 	// TODO(b/155480189) - Remove once naming inconsistencies have been resolved.
 	Naming_scheme *string
+
+	// Specifies whether this module can be used as an Android shared library; defaults
+	// to true.
+	//
+	// An Android shared library is one that can be referenced in a <uses-library> element
+	// in an AndroidManifest.xml.
+	Shared_library *bool
 }
 
 // Common code between sdk library and sdk library import
@@ -510,17 +552,23 @@
 
 	namingScheme sdkLibraryComponentNamingScheme
 
-	commonProperties commonToSdkLibraryAndImportProperties
+	commonSdkLibraryProperties commonToSdkLibraryAndImportProperties
+
+	// Functionality related to this being used as a component of a java_sdk_library.
+	EmbeddableSdkLibraryComponent
 }
 
 func (c *commonToSdkLibraryAndImport) initCommon(moduleBase *android.ModuleBase) {
 	c.moduleBase = moduleBase
 
-	moduleBase.AddProperties(&c.commonProperties)
+	moduleBase.AddProperties(&c.commonSdkLibraryProperties)
+
+	// Initialize this as an sdk library component.
+	c.initSdkLibraryComponent(moduleBase)
 }
 
 func (c *commonToSdkLibraryAndImport) initCommonAfterDefaultsApplied(ctx android.DefaultableHookContext) bool {
-	schemeProperty := proptools.StringDefault(c.commonProperties.Naming_scheme, "default")
+	schemeProperty := proptools.StringDefault(c.commonSdkLibraryProperties.Naming_scheme, "default")
 	switch schemeProperty {
 	case "default":
 		c.namingScheme = &defaultNamingScheme{}
@@ -531,6 +579,12 @@
 		return false
 	}
 
+	// Only track this sdk library if this can be used as a shared library.
+	if c.sharedLibrary() {
+		// Use the name specified in the module definition as the owner.
+		c.sdkLibraryComponentProperties.SdkLibraryToImplicitlyTrack = proptools.StringPtr(c.moduleBase.BaseModuleName())
+	}
+
 	return true
 }
 
@@ -551,7 +605,83 @@
 	return c.namingScheme.apiModuleName(apiScope, c.moduleBase.BaseModuleName())
 }
 
-func (c *commonToSdkLibraryAndImport) getScopePaths(scope *apiScope) *scopePaths {
+// The component names for different outputs of the java_sdk_library.
+//
+// They are similar to the names used for the child modules it creates
+const (
+	stubsSourceComponentName = "stubs.source"
+
+	apiTxtComponentName = "api.txt"
+
+	removedApiTxtComponentName = "removed-api.txt"
+)
+
+// A regular expression to match tags that reference a specific stubs component.
+//
+// It will only match if given a valid scope and a valid component. It is verfy strict
+// to ensure it does not accidentally match a similar looking tag that should be processed
+// by the embedded Library.
+var tagSplitter = func() *regexp.Regexp {
+	// Given a list of literal string items returns a regular expression that will
+	// match any one of the items.
+	choice := func(items ...string) string {
+		return `\Q` + strings.Join(items, `\E|\Q`) + `\E`
+	}
+
+	// Regular expression to match one of the scopes.
+	scopesRegexp := choice(allScopeNames...)
+
+	// Regular expression to match one of the components.
+	componentsRegexp := choice(stubsSourceComponentName, apiTxtComponentName, removedApiTxtComponentName)
+
+	// Regular expression to match any combination of one scope and one component.
+	return regexp.MustCompile(fmt.Sprintf(`^\.(%s)\.(%s)$`, scopesRegexp, componentsRegexp))
+}()
+
+// For OutputFileProducer interface
+//
+// .<scope>.stubs.source
+// .<scope>.api.txt
+// .<scope>.removed-api.txt
+func (c *commonToSdkLibraryAndImport) commonOutputFiles(tag string) (android.Paths, error) {
+	if groups := tagSplitter.FindStringSubmatch(tag); groups != nil {
+		scopeName := groups[1]
+		component := groups[2]
+
+		if scope, ok := scopeByName[scopeName]; ok {
+			paths := c.findScopePaths(scope)
+			if paths == nil {
+				return nil, fmt.Errorf("%q does not provide api scope %s", c.moduleBase.BaseModuleName(), scopeName)
+			}
+
+			switch component {
+			case stubsSourceComponentName:
+				if paths.stubsSrcJar.Valid() {
+					return android.Paths{paths.stubsSrcJar.Path()}, nil
+				}
+
+			case apiTxtComponentName:
+				if paths.currentApiFilePath.Valid() {
+					return android.Paths{paths.currentApiFilePath.Path()}, nil
+				}
+
+			case removedApiTxtComponentName:
+				if paths.removedApiFilePath.Valid() {
+					return android.Paths{paths.removedApiFilePath.Path()}, nil
+				}
+			}
+
+			return nil, fmt.Errorf("%s not available for api scope %s", component, scopeName)
+		} else {
+			return nil, fmt.Errorf("unknown scope %s in %s", scope, tag)
+		}
+
+	} else {
+		return nil, nil
+	}
+}
+
+func (c *commonToSdkLibraryAndImport) getScopePathsCreateIfNeeded(scope *apiScope) *scopePaths {
 	if c.scopePaths == nil {
 		c.scopePaths = make(map[*apiScope]*scopePaths)
 	}
@@ -564,6 +694,147 @@
 	return paths
 }
 
+func (c *commonToSdkLibraryAndImport) findScopePaths(scope *apiScope) *scopePaths {
+	if c.scopePaths == nil {
+		return nil
+	}
+
+	return c.scopePaths[scope]
+}
+
+// If this does not support the requested api scope then find the closest available
+// scope it does support. Returns nil if no such scope is available.
+func (c *commonToSdkLibraryAndImport) findClosestScopePath(scope *apiScope) *scopePaths {
+	for s := scope; s != nil; s = s.extends {
+		if paths := c.findScopePaths(s); paths != nil {
+			return paths
+		}
+	}
+
+	// This should never happen outside tests as public should be the base scope for every
+	// scope and is enabled by default.
+	return nil
+}
+
+func (c *commonToSdkLibraryAndImport) selectHeaderJarsForSdkVersion(ctx android.BaseModuleContext, sdkVersion sdkSpec) android.Paths {
+
+	// If a specific numeric version has been requested then use prebuilt versions of the sdk.
+	if sdkVersion.version.isNumbered() {
+		return PrebuiltJars(ctx, c.moduleBase.BaseModuleName(), sdkVersion)
+	}
+
+	var apiScope *apiScope
+	switch sdkVersion.kind {
+	case sdkSystem:
+		apiScope = apiScopeSystem
+	case sdkModule:
+		apiScope = apiScopeModuleLib
+	case sdkTest:
+		apiScope = apiScopeTest
+	default:
+		apiScope = apiScopePublic
+	}
+
+	paths := c.findClosestScopePath(apiScope)
+	if paths == nil {
+		var scopes []string
+		for _, s := range allApiScopes {
+			if c.findScopePaths(s) != nil {
+				scopes = append(scopes, s.name)
+			}
+		}
+		ctx.ModuleErrorf("requires api scope %s from %s but it only has %q available", apiScope.name, c.moduleBase.BaseModuleName(), scopes)
+		return nil
+	}
+
+	return paths.stubsHeaderPath
+}
+
+func (c *commonToSdkLibraryAndImport) sdkComponentPropertiesForChildLibrary() interface{} {
+	componentProps := &struct {
+		SdkLibraryToImplicitlyTrack *string
+	}{}
+
+	if c.sharedLibrary() {
+		// Mark the stubs library as being components of this java_sdk_library so that
+		// any app that includes code which depends (directly or indirectly) on the stubs
+		// library will have the appropriate <uses-library> invocation inserted into its
+		// manifest if necessary.
+		componentProps.SdkLibraryToImplicitlyTrack = proptools.StringPtr(c.moduleBase.BaseModuleName())
+	}
+
+	return componentProps
+}
+
+// Check if this can be used as a shared library.
+func (c *commonToSdkLibraryAndImport) sharedLibrary() bool {
+	return proptools.BoolDefault(c.commonSdkLibraryProperties.Shared_library, true)
+}
+
+// Properties related to the use of a module as an component of a java_sdk_library.
+type SdkLibraryComponentProperties struct {
+
+	// The name of the java_sdk_library/_import to add to a <uses-library> entry
+	// in the AndroidManifest.xml of any Android app that includes code that references
+	// this module. If not set then no java_sdk_library/_import is tracked.
+	SdkLibraryToImplicitlyTrack *string `blueprint:"mutated"`
+}
+
+// Structure to be embedded in a module struct that needs to support the
+// SdkLibraryComponentDependency interface.
+type EmbeddableSdkLibraryComponent struct {
+	sdkLibraryComponentProperties SdkLibraryComponentProperties
+}
+
+func (e *EmbeddableSdkLibraryComponent) initSdkLibraryComponent(moduleBase *android.ModuleBase) {
+	moduleBase.AddProperties(&e.sdkLibraryComponentProperties)
+}
+
+// to satisfy SdkLibraryComponentDependency
+func (e *EmbeddableSdkLibraryComponent) OptionalImplicitSdkLibrary() []string {
+	if e.sdkLibraryComponentProperties.SdkLibraryToImplicitlyTrack != nil {
+		return []string{*e.sdkLibraryComponentProperties.SdkLibraryToImplicitlyTrack}
+	}
+	return nil
+}
+
+// Implemented by modules that are (or possibly could be) a component of a java_sdk_library
+// (including the java_sdk_library) itself.
+type SdkLibraryComponentDependency interface {
+	// The optional name of the sdk library that should be implicitly added to the
+	// AndroidManifest of an app that contains code which references the sdk library.
+	//
+	// Returns an array containing 0 or 1 items rather than a *string to make it easier
+	// to append this to the list of exported sdk libraries.
+	OptionalImplicitSdkLibrary() []string
+}
+
+// Make sure that all the module types that are components of java_sdk_library/_import
+// and which can be referenced (directly or indirectly) from an android app implement
+// the SdkLibraryComponentDependency interface.
+var _ SdkLibraryComponentDependency = (*Library)(nil)
+var _ SdkLibraryComponentDependency = (*Import)(nil)
+var _ SdkLibraryComponentDependency = (*SdkLibrary)(nil)
+var _ SdkLibraryComponentDependency = (*sdkLibraryImport)(nil)
+
+// Provides access to sdk_version related header and implentation jars.
+type SdkLibraryDependency interface {
+	SdkLibraryComponentDependency
+
+	// Get the header jars appropriate for the supplied sdk_version.
+	//
+	// These are turbine generated jars so they only change if the externals of the
+	// class changes but it does not contain and implementation or JavaDoc.
+	SdkHeaderJars(ctx android.BaseModuleContext, sdkVersion sdkSpec) android.Paths
+
+	// Get the implementation jars appropriate for the supplied sdk version.
+	//
+	// These are either the implementation jar for the whole sdk library or the implementation
+	// jars for the stubs. The latter should only be needed when generating JavaDoc as otherwise
+	// they are identical to the corresponding header jars.
+	SdkImplementationJars(ctx android.BaseModuleContext, sdkVersion sdkSpec) android.Paths
+}
+
 type SdkLibrary struct {
 	Library
 
@@ -656,17 +927,29 @@
 		}
 	}
 
-	if !proptools.Bool(module.sdkLibraryProperties.Api_only) {
-		// Add dependency to the rule for generating the xml permissions file
-		ctx.AddDependency(module, xmlPermissionsFileTag, module.xmlFileName())
-	}
+	if module.requiresRuntimeImplementationLibrary() {
+		if module.sharedLibrary() {
+			// Add dependency to the rule for generating the xml permissions file
+			ctx.AddDependency(module, xmlPermissionsFileTag, module.xmlFileName())
+		}
 
-	module.Library.deps(ctx)
+		// Only add the deps for the library if it is actually going to be built.
+		module.Library.deps(ctx)
+	}
+}
+
+func (module *SdkLibrary) OutputFiles(tag string) (android.Paths, error) {
+	paths, err := module.commonOutputFiles(tag)
+	if paths == nil && err == nil {
+		return module.Library.OutputFiles(tag)
+	} else {
+		return paths, err
+	}
 }
 
 func (module *SdkLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
-	// Don't build an implementation library if this is api only.
-	if !proptools.Bool(module.sdkLibraryProperties.Api_only) {
+	// Only build an implementation library if required.
+	if module.requiresRuntimeImplementationLibrary() {
 		module.Library.GenerateAndroidBuildActions(ctx)
 	}
 
@@ -679,7 +962,7 @@
 		// Extract information from any of the scope specific dependencies.
 		if scopeTag, ok := tag.(scopeDependencyTag); ok {
 			apiScope := scopeTag.apiScope
-			scopePaths := module.getScopePaths(apiScope)
+			scopePaths := module.getScopePathsCreateIfNeeded(apiScope)
 
 			// Extract information from the dependency. The exact information extracted
 			// is determined by the nature of the dependency which is determined by the tag.
@@ -689,7 +972,7 @@
 }
 
 func (module *SdkLibrary) AndroidMkEntries() []android.AndroidMkEntries {
-	if proptools.Bool(module.sdkLibraryProperties.Api_only) {
+	if !module.requiresRuntimeImplementationLibrary() {
 		return nil
 	}
 	entriesList := module.Library.AndroidMkEntries()
@@ -792,7 +1075,9 @@
 	props.Product_variables.Pdk.Enabled = proptools.BoolPtr(false)
 	props.Openjdk9.Srcs = module.properties.Openjdk9.Srcs
 	props.Openjdk9.Javacflags = module.properties.Openjdk9.Javacflags
-	props.Java_version = module.properties.Java_version
+	// We compile the stubs for 1.8 in line with the main android.jar stubs, and potential
+	// interop with older developer tools that don't support 1.9.
+	props.Java_version = proptools.StringPtr("1.8")
 	if module.deviceProperties.Compile_dex != nil {
 		props.Compile_dex = module.deviceProperties.Compile_dex
 	}
@@ -805,7 +1090,7 @@
 		props.Dist.Tag = proptools.StringPtr(".jar")
 	}
 
-	mctx.CreateModule(LibraryFactory, &props)
+	mctx.CreateModule(LibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary())
 }
 
 // Creates a droidstubs module that creates stubs source files from the given full source
@@ -1010,41 +1295,43 @@
 	return android.Paths{jarPath.Path()}
 }
 
-func (module *SdkLibrary) sdkJars(
-	ctx android.BaseModuleContext,
-	sdkVersion sdkSpec,
-	headerJars bool) android.Paths {
+// Get the apex name for module, "" if it is for platform.
+func getApexNameForModule(module android.Module) string {
+	if apex, ok := module.(android.ApexModule); ok {
+		return apex.ApexName()
+	}
 
-	// If a specific numeric version has been requested then use prebuilt versions of the sdk.
-	if sdkVersion.version.isNumbered() {
-		return PrebuiltJars(ctx, module.BaseModuleName(), sdkVersion)
-	} else {
-		if !sdkVersion.specified() {
+	return ""
+}
+
+// Check to see if the other module is within the same named APEX as this module.
+//
+// If either this or the other module are on the platform then this will return
+// false.
+func (module *SdkLibrary) withinSameApexAs(other android.Module) bool {
+	name := module.ApexName()
+	return name != "" && getApexNameForModule(other) == name
+}
+
+func (module *SdkLibrary) sdkJars(ctx android.BaseModuleContext, sdkVersion sdkSpec, headerJars bool) android.Paths {
+
+	// Only provide access to the implementation library if it is actually built.
+	if module.requiresRuntimeImplementationLibrary() {
+		// Check any special cases for java_sdk_library.
+		//
+		// Only allow access to the implementation library in the following condition:
+		// * No sdk_version specified on the referencing module.
+		// * The referencing module is in the same apex as this.
+		if sdkVersion.kind == sdkPrivate || module.withinSameApexAs(ctx.Module()) {
 			if headerJars {
 				return module.HeaderJars()
 			} else {
 				return module.ImplementationJars()
 			}
 		}
-		var apiScope *apiScope
-		switch sdkVersion.kind {
-		case sdkSystem:
-			apiScope = apiScopeSystem
-		case sdkTest:
-			apiScope = apiScopeTest
-		case sdkPrivate:
-			return module.HeaderJars()
-		default:
-			apiScope = apiScopePublic
-		}
-
-		paths := module.getScopePaths(apiScope)
-		if headerJars {
-			return paths.stubsHeaderPath
-		} else {
-			return paths.stubsImplPath
-		}
 	}
+
+	return module.selectHeaderJarsForSdkVersion(ctx, sdkVersion)
 }
 
 // to satisfy SdkLibraryDependency interface
@@ -1148,9 +1435,12 @@
 		module.createStubsLibrary(mctx, scope)
 	}
 
-	if !proptools.Bool(module.sdkLibraryProperties.Api_only) {
-		// for runtime
-		module.createXmlFile(mctx)
+	if module.requiresRuntimeImplementationLibrary() {
+		// Only create an XML permissions file that declares the library as being usable
+		// as a shared library if required.
+		if module.sharedLibrary() {
+			module.createXmlFile(mctx)
+		}
 
 		// record java_sdk_library modules so that they are exported to make
 		javaSdkLibraries := javaSdkLibraries(mctx.Config())
@@ -1169,10 +1459,16 @@
 		&module.protoProperties,
 	)
 
+	module.initSdkLibraryComponent(&module.ModuleBase)
+
 	module.properties.Installable = proptools.BoolPtr(true)
 	module.deviceProperties.IsSDKLibrary = true
 }
 
+func (module *SdkLibrary) requiresRuntimeImplementationLibrary() bool {
+	return !proptools.Bool(module.sdkLibraryProperties.Api_only)
+}
+
 // Defines how to name the individual component modules the sdk library creates.
 type sdkLibraryComponentNamingScheme interface {
 	stubsLibraryModuleName(scope *apiScope, baseName string) string
@@ -1251,6 +1547,18 @@
 	android.AddVisibilityProperty(module, "stubs_source_visibility", &module.sdkLibraryProperties.Stubs_source_visibility)
 
 	module.SetDefaultableHook(func(ctx android.DefaultableHookContext) {
+		// If no implementation is required then it cannot be used as a shared library
+		// either.
+		if !module.requiresRuntimeImplementationLibrary() {
+			// If shared_library has been explicitly set to true then it is incompatible
+			// with api_only: true.
+			if proptools.Bool(module.commonSdkLibraryProperties.Shared_library) {
+				ctx.PropertyErrorf("api_only/shared_library", "inconsistent settings, shared_library and api_only cannot both be true")
+			}
+			// Set shared_library: false.
+			module.commonSdkLibraryProperties.Shared_library = proptools.BoolPtr(false)
+		}
+
 		if module.initCommonAfterDefaultsApplied(ctx) {
 			module.CreateInternalModules(ctx)
 		}
@@ -1275,10 +1583,10 @@
 	Stub_srcs []string `android:"path"`
 
 	// The current.txt
-	Current_api string `android:"path"`
+	Current_api *string `android:"path"`
 
 	// The removed.txt
-	Removed_api string `android:"path"`
+	Removed_api *string `android:"path"`
 }
 
 type sdkLibraryImportProperties struct {
@@ -1388,7 +1696,9 @@
 
 		module.createJavaImportForStubs(mctx, apiScope, scopeProperties)
 
-		module.createPrebuiltStubsSources(mctx, apiScope, scopeProperties)
+		if len(scopeProperties.Stub_srcs) > 0 {
+			module.createPrebuiltStubsSources(mctx, apiScope, scopeProperties)
+		}
 	}
 
 	javaSdkLibraries := javaSdkLibraries(mctx.Config())
@@ -1415,7 +1725,8 @@
 
 	// The imports are preferred if the java_sdk_library_import is preferred.
 	props.Prefer = proptools.BoolPtr(module.prebuilt.Prefer())
-	mctx.CreateModule(ImportFactory, &props)
+
+	mctx.CreateModule(ImportFactory, &props, module.sdkComponentPropertiesForChildLibrary())
 }
 
 func (module *sdkLibraryImport) createPrebuiltStubsSources(mctx android.DefaultableHookContext, apiScope *apiScope, scopeProperties *sdkLibraryScopeProperties) {
@@ -1440,45 +1751,48 @@
 
 		// Add dependencies to the prebuilt stubs library
 		ctx.AddVariationDependencies(nil, apiScope.stubsTag, module.stubsLibraryModuleName(apiScope))
+
+		if len(scopeProperties.Stub_srcs) > 0 {
+			// Add dependencies to the prebuilt stubs source library
+			ctx.AddVariationDependencies(nil, apiScope.stubsSourceTag, module.stubsSourceModuleName(apiScope))
+		}
 	}
 }
 
+func (module *sdkLibraryImport) OutputFiles(tag string) (android.Paths, error) {
+	return module.commonOutputFiles(tag)
+}
+
 func (module *sdkLibraryImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
-	// Record the paths to the prebuilt stubs library.
+	// Record the paths to the prebuilt stubs library and stubs source.
 	ctx.VisitDirectDeps(func(to android.Module) {
 		tag := ctx.OtherModuleDependencyTag(to)
 
-		if lib, ok := to.(Dependency); ok {
-			if scopeTag, ok := tag.(scopeDependencyTag); ok {
-				apiScope := scopeTag.apiScope
-				scopePaths := module.getScopePaths(apiScope)
-				scopePaths.stubsHeaderPath = lib.HeaderJars()
-			}
+		// Extract information from any of the scope specific dependencies.
+		if scopeTag, ok := tag.(scopeDependencyTag); ok {
+			apiScope := scopeTag.apiScope
+			scopePaths := module.getScopePathsCreateIfNeeded(apiScope)
+
+			// Extract information from the dependency. The exact information extracted
+			// is determined by the nature of the dependency which is determined by the tag.
+			scopeTag.extractDepInfo(ctx, to, scopePaths)
 		}
 	})
+
+	// Populate the scope paths with information from the properties.
+	for apiScope, scopeProperties := range module.scopeProperties {
+		if len(scopeProperties.Jars) == 0 {
+			continue
+		}
+
+		paths := module.getScopePathsCreateIfNeeded(apiScope)
+		paths.currentApiFilePath = android.OptionalPathForModuleSrc(ctx, scopeProperties.Current_api)
+		paths.removedApiFilePath = android.OptionalPathForModuleSrc(ctx, scopeProperties.Removed_api)
+	}
 }
 
-func (module *sdkLibraryImport) sdkJars(
-	ctx android.BaseModuleContext,
-	sdkVersion sdkSpec) android.Paths {
-
-	// If a specific numeric version has been requested then use prebuilt versions of the sdk.
-	if sdkVersion.version.isNumbered() {
-		return PrebuiltJars(ctx, module.BaseModuleName(), sdkVersion)
-	}
-
-	var apiScope *apiScope
-	switch sdkVersion.kind {
-	case sdkSystem:
-		apiScope = apiScopeSystem
-	case sdkTest:
-		apiScope = apiScopeTest
-	default:
-		apiScope = apiScopePublic
-	}
-
-	paths := module.getScopePaths(apiScope)
-	return paths.stubsHeaderPath
+func (module *sdkLibraryImport) sdkJars(ctx android.BaseModuleContext, sdkVersion sdkSpec) android.Paths {
+	return module.selectHeaderJarsForSdkVersion(ctx, sdkVersion)
 }
 
 // to satisfy SdkLibraryDependency interface
@@ -1651,21 +1965,25 @@
 
 	s.Scopes = make(map[*apiScope]scopeProperties)
 	for _, apiScope := range allApiScopes {
-		paths := sdk.getScopePaths(apiScope)
+		paths := sdk.findScopePaths(apiScope)
+		if paths == nil {
+			continue
+		}
+
 		jars := paths.stubsImplPath
 		if len(jars) > 0 {
 			properties := scopeProperties{}
 			properties.Jars = jars
 			properties.SdkVersion = sdk.sdkVersionForStubsLibrary(ctx.SdkModuleContext(), apiScope)
-			properties.StubsSrcJar = paths.stubsSrcJar
-			properties.CurrentApiFile = paths.currentApiFilePath
-			properties.RemovedApiFile = paths.removedApiFilePath
+			properties.StubsSrcJar = paths.stubsSrcJar.Path()
+			properties.CurrentApiFile = paths.currentApiFilePath.Path()
+			properties.RemovedApiFile = paths.removedApiFilePath.Path()
 			s.Scopes[apiScope] = properties
 		}
 	}
 
 	s.Libs = sdk.properties.Libs
-	s.Naming_scheme = sdk.commonProperties.Naming_scheme
+	s.Naming_scheme = sdk.commonSdkLibraryProperties.Naming_scheme
 }
 
 func (s *sdkLibrarySdkMemberProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) {