Merge changes from topic "disable_shared_library" into rvc-dev

* changes:
  Retry: "java_sdk_library: Control shared library use"
  Retry: "Improve tracking of exported sdk libraries"
diff --git a/java/aar.go b/java/aar.go
index 0e103f2..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:
diff --git a/java/app_test.go b/java/app_test.go
index c731a17..12b935e 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -2383,6 +2383,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"],
@@ -2392,6 +2406,7 @@
 		android_app {
 			name: "app",
 			srcs: ["a.java"],
+			libs: ["qux", "quuz.stubs"],
 			uses_libs: ["foo"],
 			sdk_version: "current",
 			optional_uses_libs: [
@@ -2422,6 +2437,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) {
diff --git a/java/java.go b/java/java.go
index da9bd3d..00b11f7 100644
--- a/java/java.go
+++ b/java/java.go
@@ -355,7 +355,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 +506,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
 }
@@ -930,6 +935,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 +960,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)
 			}
@@ -1990,6 +2001,8 @@
 		&module.Module.protoProperties,
 		&module.libraryProperties)
 
+	module.initModuleAndImport(&module.ModuleBase)
+
 	android.InitApexModule(module)
 	android.InitSdkAwareModule(module)
 	InitJavaModule(module, android.HostAndDeviceSupported)
@@ -2451,6 +2464,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 +2586,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 4f3a803..0ab541a 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -19,6 +19,7 @@
 	"os"
 	"path/filepath"
 	"reflect"
+	"sort"
 	"strconv"
 	"strings"
 	"testing"
@@ -1153,13 +1154,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 {
@@ -1224,8 +1254,9 @@
 	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)
 		}
 	}
 }
diff --git a/java/sdk_library.go b/java/sdk_library.go
index adbb5d2..0598e81 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -372,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.
@@ -532,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
@@ -542,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{}
@@ -563,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
 }
 
@@ -728,6 +750,91 @@
 	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
 
@@ -820,12 +927,15 @@
 		}
 	}
 
-	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) {
@@ -838,8 +948,8 @@
 }
 
 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)
 	}
 
@@ -862,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()
@@ -980,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
@@ -1302,9 +1412,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())
@@ -1323,10 +1436,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
@@ -1405,6 +1524,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)
 		}
@@ -1571,7 +1702,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) {
@@ -1828,7 +1960,7 @@
 	}
 
 	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) {