Additional fixes for java_sdk_library

This change fixes several problems found while re-defining some libs
using java_sdk_library module type.

1) A phony module whose name is the same as the java_sdk_library name is
defined. It is used to support installing the runtime library via
PRODUCT_PACKAGES (even when there is no dependency from other modules).

2) A bug that package names whose depth is >= 2 is ignored in
droiddoc.srcs_lib_whitelist_pkgs is fixed. A package name foo.bar.baz is
now converted to a path foo/bar/baz following the Java convention.

3) A make variable JAVA_SDK_LIBRARIES that is the list of java_sdk_library
module names is exported to make. This can be used to distinguish SDK
libraries from ordinary libs.

4) When running doclava, some framework sources in the 'android' package
and the same packages as the SDK library are automatically added to the
sources list. This is required for the case when API class is extending
from the framework class. In that case, doclava needs to know whether
the base class is hidde nor not. Since that visibility info is encoded
as @hide string in the comment, we need source files for the classes,
not the compiled ones. Also there are rare cases where part of SDK
library is implemented in the framework (e.g. org.apache.http.legacy).
In that case, we need framework source to make API stubs, though the
sources are not required to build the runtime library.

5) The stubs libs are disabled for PDK builds as well.

Bug: 77575606
Test: m -j

Change-Id: I360cf15fe5339e46644fb16d0dabe2548aa315f9
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 301ec61..13a9275 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -18,8 +18,11 @@
 	"android/soong/android"
 	"android/soong/genrule"
 	"fmt"
+	"io"
 	"path"
+	"sort"
 	"strings"
+	"sync"
 
 	"github.com/google/blueprint"
 	"github.com/google/blueprint/proptools"
@@ -43,6 +46,10 @@
 	systemApiStubsTag = dependencyTag{name: "system"}
 )
 
+var (
+	javaSdkLibrariesLock sync.Mutex
+)
+
 // java_sdk_library is to make a Java library that implements optional platform APIs to apps.
 // It is actually a wrapper of several modules: 1) stubs library that clients are linked against
 // to, 2) droiddoc module that internally generates API stubs source files, 3) the real runtime
@@ -62,6 +69,12 @@
 	android.PreArchMutators(func(ctx android.RegisterMutatorsContext) {
 		ctx.TopDown("java_sdk_library", sdkLibraryMutator).Parallel()
 	})
+
+	android.RegisterMakeVarsProvider(pctx, func(ctx android.MakeVarsContext) {
+		javaSdkLibraries := javaSdkLibraries(ctx.Config())
+		sort.Strings(*javaSdkLibraries)
+		ctx.Strict("JAVA_SDK_LIBRARIES", strings.Join(*javaSdkLibraries, " "))
+	})
 }
 
 type sdkLibraryProperties struct {
@@ -120,6 +133,20 @@
 	})
 }
 
+func (module *sdkLibrary) AndroidMk() android.AndroidMkData {
+	// Create a phony module that installs the impl library, for the case when this lib is
+	// in PRODUCT_PACKAGES.
+	return android.AndroidMkData{
+		Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
+			fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)")
+			fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir)
+			fmt.Fprintln(w, "LOCAL_MODULE :=", name)
+			fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES := "+module.implName())
+			fmt.Fprintln(w, "include $(BUILD_PHONY_PACKAGE)")
+		},
+	}
+}
+
 // Module name of the stubs library
 func (module *sdkLibrary) stubsName(forSystemApi bool) string {
 	stubsName := module.BaseModuleName() + sdkStubsLibrarySuffix
@@ -210,6 +237,9 @@
 			Unbundled_build struct {
 				Enabled *bool
 			}
+			Pdk struct {
+				Enabled *bool
+			}
 		}
 	}{}
 
@@ -219,6 +249,7 @@
 	props.Sdk_version = proptools.StringPtr(module.sdkVersion(forSystemApi))
 	// Unbundled apps will use the prebult one from /prebuilts/sdk
 	props.Product_variables.Unbundled_build.Enabled = proptools.BoolPtr(false)
+	props.Product_variables.Pdk.Enabled = proptools.BoolPtr(false)
 
 	if module.SocSpecific() {
 		props.Soc_specific = proptools.BoolPtr(true)
@@ -281,17 +312,25 @@
 	props.Api_filename = proptools.StringPtr(currentApiFileName)
 	props.Removed_api_filename = proptools.StringPtr(removedApiFileName)
 
-	// Includes the main framework source to ensure that doclava has access to the
-	// visibility information for the base classes of the mock classes. Without it
-	// otherwise hidden methods could be visible.
-	// TODO: remove the need for this
+	// Include the part of the framework source. This is required for the case when
+	// API class is extending from the framework class. In that case, doclava needs
+	// to know whether the base class is hidden or not. Since that information is
+	// encoded as @hide string in the comment, we need source files for the classes,
+	// not the compiled ones. Also there are rare cases where part of SDK library is
+	// implemented in the framework (e.g. org.apache.http.legacy). In that case,
+	// we need framework source to make API stubs, though the sources are not
+	// required to build the runtime library.
 	props.Srcs_lib = proptools.StringPtr("framework")
 	props.Srcs_lib_whitelist_dirs = []string{"core/java"}
-	props.Srcs_lib_whitelist_pkgs = []string{"android"}
-	// These libs are required by doclava to parse the sources from framework.
+	props.Srcs_lib_whitelist_pkgs = module.properties.Api_packages
+	// Add android.annotation package to give access to the framework-defined
+	// annotations such as SystemApi, NonNull, etc.
+	props.Srcs_lib_whitelist_pkgs = append(props.Srcs_lib_whitelist_pkgs, "android.annotation")
+	// These libs are required by doclava to parse the framework sources add via
+	// Src_lib and Src_lib_whitelist_* properties just above.
 	// If we don't add them to the classpath, errors messages are generated by doclava,
 	// though they don't break the build.
-	props.Libs = append(props.Libs, "conscrypt", "bouncycastle", "okhttp")
+	props.Libs = append(props.Libs, "conscrypt", "bouncycastle", "okhttp", "framework")
 
 	mctx.CreateModule(android.ModuleFactoryAdaptor(DroiddocFactory), &props)
 }
@@ -397,6 +436,12 @@
 	}
 }
 
+func javaSdkLibraries(config android.Config) *[]string {
+	return config.Once("javaSdkLibraries", func() interface{} {
+		return &[]string{}
+	}).(*[]string)
+}
+
 // For a java_sdk_library module, create internal modules for stubs, docs,
 // runtime libs and xml file. If requested, the stubs and docs are created twice
 // once for public API level and once for system API level
@@ -413,6 +458,12 @@
 		// for runtime
 		module.createXmlFile(mctx)
 		module.createImplLibrary(mctx)
+
+		// record java_sdk_library modules so that they are exported to make
+		javaSdkLibraries := javaSdkLibraries(mctx.Config())
+		javaSdkLibrariesLock.Lock()
+		defer javaSdkLibrariesLock.Unlock()
+		*javaSdkLibraries = append(*javaSdkLibraries, module.BaseModuleName())
 	}
 }