java_sdk_library: Create separate impl library

Most dependencies on java_sdk_library instances (JSL) simply reference
them by name and rely on the build to pick the correct part, impl,
stubs for a specific scope, headers or implementation jars or dex jars.
Generally, the build gets that decision right. If it does not the for
most of the components of the JSL there is a way to reference them
directly. However, that is not true for the implementation library as
that is created the JSL itself.

Access to the implementation library should be avoided as it opens up
the possibility that use will be made of an API that is not tracked and
maintained which could lead to compatibility issues. However, there is
a case where use of the implementation library is required and safe.
That is when it is being used from other libraries within the same APEX
as the JSL. In that case the JSL and its dependencies will be updated
together so compatibility is not an issue.

This change adds a new <module>.impl java_library that compiles the
implementation library in the same way as the JSL itself does. This will
allow the modules that are blocked from converting to JSL because of
this limitation to progress. Initially the library is only for use
for compiling but follow up changes will switch the rest of the build
from using the implementation library created by JSL to the separate
module.

It also adds the ability to give the separate .impl library a more
restrictive visibility than the JSL further limiting misuse.

Bug: 156618935
Test: m droid, flash, atest CtsProviderTestCases - sniff test
      tested that it fixes compilation issues with mainline module
Merged-In: Ifc4799feb4ada9dec8021efc13fe6a953bf2edd3
Change-Id: Ifc4799feb4ada9dec8021efc13fe6a953bf2edd3
(cherry picked from commit 5df793011db8ee729e3c7888d563d909d44da0c5)
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 43a340e..fec5866 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -348,6 +348,10 @@
 }
 
 type sdkLibraryProperties struct {
+	// Visibility for impl library module. If not specified then defaults to the
+	// visibility property.
+	Impl_library_visibility []string
+
 	// Visibility for stubs library modules. If not specified then defaults to the
 	// visibility property.
 	Stubs_library_visibility []string
@@ -910,6 +914,8 @@
 	return false
 }
 
+var implLibraryTag = dependencyTag{name: "impl-library"}
+
 func (module *SdkLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
 	for _, apiScope := range module.getGeneratedApiScopes(ctx) {
 		// Add dependencies to the stubs library
@@ -928,6 +934,9 @@
 	}
 
 	if module.requiresRuntimeImplementationLibrary() {
+		// Add dependency to the rule for generating the implementation library.
+		ctx.AddDependency(module, implLibraryTag, module.implLibraryModuleName())
+
 		if module.sharedLibrary() {
 			// Add dependency to the rule for generating the xml permissions file
 			ctx.AddDependency(module, xmlPermissionsFileTag, module.xmlFileName())
@@ -982,8 +991,8 @@
 }
 
 // Module name of the runtime implementation library
-func (module *SdkLibrary) implName() string {
-	return module.BaseModuleName()
+func (module *SdkLibrary) implLibraryModuleName() string {
+	return module.BaseModuleName() + ".impl"
 }
 
 // Module name of the XML file for the lib
@@ -1027,6 +1036,27 @@
 	return ":" + module.BaseModuleName() + "-removed.api." + apiScope.name + ".latest"
 }
 
+// Creates the implementation java library
+func (module *SdkLibrary) createImplLibrary(mctx android.DefaultableHookContext) {
+	props := struct {
+		Name       *string
+		Visibility []string
+	}{
+		Name:       proptools.StringPtr(module.implLibraryModuleName()),
+		Visibility: module.sdkLibraryProperties.Impl_library_visibility,
+	}
+
+	properties := []interface{}{
+		&module.properties,
+		&module.protoProperties,
+		&module.deviceProperties,
+		&module.dexpreoptProperties,
+		&props,
+		module.sdkComponentPropertiesForChildLibrary(),
+	}
+	mctx.CreateModule(LibraryFactory, properties...)
+}
+
 // Creates a static java library that has API stubs
 func (module *SdkLibrary) createStubsLibrary(mctx android.DefaultableHookContext, apiScope *apiScope) {
 	props := struct {
@@ -1436,6 +1466,14 @@
 	}
 
 	if module.requiresRuntimeImplementationLibrary() {
+		// Create child module to create an implementation library.
+		//
+		// This temporarily creates a second implementation library that can be explicitly
+		// referenced.
+		//
+		// TODO(b/156618935) - update comment once only one implementation library is created.
+		module.createImplLibrary(mctx)
+
 		// Only create an XML permissions file that declares the library as being usable
 		// as a shared library if required.
 		if module.sharedLibrary() {
@@ -1543,6 +1581,7 @@
 	module.scopeToProperties = scopeToProperties
 
 	// Add the properties containing visibility rules so that they are checked.
+	android.AddVisibilityProperty(module, "impl_library_visibility", &module.sdkLibraryProperties.Impl_library_visibility)
 	android.AddVisibilityProperty(module, "stubs_library_visibility", &module.sdkLibraryProperties.Stubs_library_visibility)
 	android.AddVisibilityProperty(module, "stubs_source_visibility", &module.sdkLibraryProperties.Stubs_source_visibility)