Add default_to_stubs option to java_sdk_library

Previously, when a lib that doesn't have sdk_version property set
depends on a java_sdk_library, the impl library was used for linking.
This might be too permissive because the client lib might be using empty
sdk_version because it needed some private APIs from the platform, but
not from the java_sdk_library. This actually happend for some of the CTS
tests. They don't set sdk_version, but were directly depending on
android.test.[base|runner|mock].stubs libraries. If we switch the
references to the stub libraries into the corresponding java_sdk_library
modules (e.g. aandroid.test.[base|runner|mock]), then we would be
allowing private APIs to the CTS tests, which is not good.

To solve this problem, default_to_stub property is introduced. It when set
to true prevents the impl lib from being used for linking. When a module
that doesn't have sdk_version depends on it, the widest API surface that
the java_sdk_library provides is linked instead.

Bug: 157007292
Test: m
Change-Id: Id2acc3cafb71d1e90d4fdc9c0c70a73983355e0f
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 237be10..bf0d3d6 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -435,6 +435,14 @@
 	// disabled by default.
 	Module_lib ApiScopeProperties
 
+	// Determines if the stubs are preferred over the implementation library
+	// for linking, even when the client doesn't specify sdk_version. When this
+	// is set to true, such clients are provided with the widest API surface that
+	// this lib provides. Note however that this option doesn't affect the clients
+	// that are in the same APEX as this library. In that case, the clients are
+	// always linked with the implementation library. Default is false.
+	Default_to_stubs *bool
+
 	// Properties related to api linting.
 	Api_lint struct {
 		// Enable api linting.
@@ -1342,6 +1350,13 @@
 }
 
 func (module *SdkLibrary) sdkJars(ctx android.BaseModuleContext, sdkVersion sdkSpec, headerJars bool) android.Paths {
+	// If the client doesn't set sdk_version, but if this library prefers stubs over
+	// the impl library, let's provide the widest API surface possible. To do so,
+	// force override sdk_version to module_current so that the closest possible API
+	// surface could be found in selectHeaderJarsForSdkVersion
+	if module.defaultsToStubs() && !sdkVersion.specified() {
+		sdkVersion = sdkSpecFrom("module_current")
+	}
 
 	// Only provide access to the implementation library if it is actually built.
 	if module.requiresRuntimeImplementationLibrary() {
@@ -1505,6 +1520,10 @@
 	return !proptools.Bool(module.sdkLibraryProperties.Api_only)
 }
 
+func (module *SdkLibrary) defaultsToStubs() bool {
+	return proptools.Bool(module.sdkLibraryProperties.Default_to_stubs)
+}
+
 // Defines how to name the individual component modules the sdk library creates.
 type sdkLibraryComponentNamingScheme interface {
 	stubsLibraryModuleName(scope *apiScope, baseName string) string