Add support for specifying api provided by bootclasspath_fragment

The hidden API processing needs access to dex stub jars for the API
scopes provided by the bootclasspath_fragment so that it can mark the
corresponding dex members as being part of that API. This change adds
the ability to specify the modules that provide those jars, resolve the
modules to dex jar stubs and make them available for other modules and
tests to use.

While the stubs are only needed for hidden API at the moment these were
not added to the hidden_api properties section as there are other parts
of the build that may need to access the stubs in future, e.g. api
fingerprint and aidl generation.

The stubs properties can be affected by coverage as when coverage is
enabled the jacoco-stubs needs adding to the list, just like how
jacocoagent is added to the contents.

Bug: 177892522
Test: m nothing
Change-Id: I31097d1ca45c84adeba4cbb38f693698cb289e99
diff --git a/java/bootclasspath_fragment_test.go b/java/bootclasspath_fragment_test.go
index 0419a46..dbdf6c4 100644
--- a/java/bootclasspath_fragment_test.go
+++ b/java/bootclasspath_fragment_test.go
@@ -171,3 +171,68 @@
 		checkContents(t, result, "mybootlib", "coveragelib")
 	})
 }
+
+func TestBootclasspathFragment_StubLibs(t *testing.T) {
+	result := android.GroupFixturePreparers(
+		prepareForTestWithBootclasspathFragment,
+		PrepareForTestWithJavaSdkLibraryFiles,
+		FixtureWithLastReleaseApis("mysdklibrary", "mycoreplatform"),
+	).RunTestWithBp(t, `
+		bootclasspath_fragment {
+			name: "myfragment",
+			contents: ["mysdklibrary"],
+			api: {
+				stub_libs: [
+					"mystublib",
+					"mysdklibrary",
+				],
+			},
+			core_platform_api: {
+				stub_libs: ["mycoreplatform"],
+			},
+		}
+
+		java_library {
+			name: "mystublib",
+			srcs: ["Test.java"],
+			system_modules: "none",
+			sdk_version: "none",
+			compile_dex: true,
+		}
+
+		java_sdk_library {
+			name: "mysdklibrary",
+			srcs: ["a.java"],
+			compile_dex: true,
+			public: {enabled: true},
+			system: {enabled: true},
+		}
+
+		java_sdk_library {
+			name: "mycoreplatform",
+			srcs: ["a.java"],
+			compile_dex: true,
+			public: {enabled: true},
+		}
+	`)
+
+	fragment := result.Module("myfragment", "android_common")
+	info := result.ModuleProvider(fragment, bootclasspathApiInfoProvider).(bootclasspathApiInfo)
+
+	stubsJar := "out/soong/.intermediates/mystublib/android_common/dex/mystublib.jar"
+
+	// Check that SdkPublic uses public stubs.
+	publicStubsJar := "out/soong/.intermediates/mysdklibrary.stubs/android_common/dex/mysdklibrary.stubs.jar"
+	android.AssertPathsRelativeToTopEquals(t, "public dex stubs jar", []string{stubsJar, publicStubsJar}, info.stubJarsByKind[android.SdkPublic])
+
+	// Check that SdkSystem uses system stubs.
+	systemStubsJar := "out/soong/.intermediates/mysdklibrary.stubs.system/android_common/dex/mysdklibrary.stubs.system.jar"
+	android.AssertPathsRelativeToTopEquals(t, "system dex stubs jar", []string{stubsJar, systemStubsJar}, info.stubJarsByKind[android.SdkSystem])
+
+	// Check that SdkTest also uses system stubs as the mysdklibrary does not provide test stubs.
+	android.AssertPathsRelativeToTopEquals(t, "test dex stubs jar", []string{stubsJar, systemStubsJar}, info.stubJarsByKind[android.SdkTest])
+
+	// Check that SdkCorePlatform uses public stubs from the mycoreplatform library.
+	corePlatformStubsJar := "out/soong/.intermediates/mycoreplatform.stubs/android_common/dex/mycoreplatform.stubs.jar"
+	android.AssertPathsRelativeToTopEquals(t, "core platform dex stubs jar", []string{corePlatformStubsJar}, info.stubJarsByKind[android.SdkCorePlatform])
+}