Use classpath elements in platform_bootclasspath

Use classpath elements in newMonolithicHiddenAPIInfo. That means the
method can collate information from both fragments and libraries rather
than just fragments. So, this change moves the collation of the
classesJars into the method.

Bug: 177892522
Test: m out/soong/hiddenapi/hiddenapi-flags.csv out/soong/hiddenapi/hiddenapi-index.csv
      - make sure that this change does not affect the contents.
Merged-In: I7c2a229fab60d02bd211438735a8d7303ed83386
Change-Id: I7c2a229fab60d02bd211438735a8d7303ed83386
(cherry picked from commit 89f570ac44af4bcf5b78fa8dad3d57f24cd3ca0e)
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 1bc2514..11fed36 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -4423,6 +4423,11 @@
 		java.CheckHiddenAPIRuleInputs(t, expectedInputs, indexRule)
 	}
 
+	fragment := java.ApexVariantReference{
+		Apex:   proptools.StringPtr("myapex"),
+		Module: proptools.StringPtr("my-bootclasspath-fragment"),
+	}
+
 	t.Run("prebuilt only", func(t *testing.T) {
 		bp := `
 		prebuilt_apex {
@@ -4435,7 +4440,13 @@
 					src: "myapex-arm.apex",
 				},
 			},
-			exported_java_libs: ["libfoo", "libbar"],
+			exported_bootclasspath_fragments: ["my-bootclasspath-fragment"],
+		}
+
+		prebuilt_bootclasspath_fragment {
+			name: "my-bootclasspath-fragment",
+			contents: ["libfoo", "libbar"],
+			apex_available: ["myapex"],
 		}
 
 		java_import {
@@ -4450,10 +4461,11 @@
 				jars: ["libbar.jar"],
 			},
 			apex_available: ["myapex"],
+			shared_library: false,
 		}
 	`
 
-		ctx := testDexpreoptWithApexes(t, bp, "", preparer)
+		ctx := testDexpreoptWithApexes(t, bp, "", preparer, fragment)
 		checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar")
 		checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libbar.jar")
 
@@ -4469,7 +4481,13 @@
 		apex_set {
 			name: "myapex",
 			set: "myapex.apks",
-			exported_java_libs: ["libfoo", "libbar"],
+			exported_bootclasspath_fragments: ["my-bootclasspath-fragment"],
+		}
+
+		prebuilt_bootclasspath_fragment {
+			name: "my-bootclasspath-fragment",
+			contents: ["libfoo", "libbar"],
+			apex_available: ["myapex"],
 		}
 
 		java_import {
@@ -4484,10 +4502,11 @@
 				jars: ["libbar.jar"],
 			},
 			apex_available: ["myapex"],
+			shared_library: false,
 		}
 	`
 
-		ctx := testDexpreoptWithApexes(t, bp, "", preparer)
+		ctx := testDexpreoptWithApexes(t, bp, "", preparer, fragment)
 		checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar")
 		checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libbar.jar")
 
@@ -4510,7 +4529,13 @@
 					src: "myapex-arm.apex",
 				},
 			},
-			exported_java_libs: ["libfoo", "libbar"],
+			exported_bootclasspath_fragments: ["my-bootclasspath-fragment"],
+		}
+
+		prebuilt_bootclasspath_fragment {
+			name: "my-bootclasspath-fragment",
+			contents: ["libfoo", "libbar"],
+			apex_available: ["myapex"],
 		}
 
 		java_import {
@@ -4531,6 +4556,7 @@
 				jars: ["libbar.jar"],
 			},
 			apex_available: ["myapex"],
+			shared_library: false,
 		}
 
 		java_sdk_library {
@@ -4546,7 +4572,7 @@
 		// prebuilt_apex module always depends on the prebuilt, and so it doesn't
 		// find the dex boot jar in it. We either need to disable the source libfoo
 		// or make the prebuilt libfoo preferred.
-		testDexpreoptWithApexes(t, bp, "module libfoo does not provide a dex boot jar", preparer)
+		testDexpreoptWithApexes(t, bp, "module libfoo does not provide a dex boot jar", preparer, fragment)
 	})
 
 	t.Run("prebuilt library preferred with source", func(t *testing.T) {
@@ -4561,7 +4587,13 @@
 					src: "myapex-arm.apex",
 				},
 			},
-			exported_java_libs: ["libfoo", "libbar"],
+			exported_bootclasspath_fragments: ["my-bootclasspath-fragment"],
+		}
+
+		prebuilt_bootclasspath_fragment {
+			name: "my-bootclasspath-fragment",
+			contents: ["libfoo", "libbar"],
+			apex_available: ["myapex"],
 		}
 
 		java_import {
@@ -4584,6 +4616,7 @@
 				jars: ["libbar.jar"],
 			},
 			apex_available: ["myapex"],
+			shared_library: false,
 		}
 
 		java_sdk_library {
@@ -4594,7 +4627,7 @@
 		}
 	`
 
-		ctx := testDexpreoptWithApexes(t, bp, "", preparer)
+		ctx := testDexpreoptWithApexes(t, bp, "", preparer, fragment)
 		checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar")
 		checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libbar.jar")
 
@@ -4630,7 +4663,13 @@
 					src: "myapex-arm.apex",
 				},
 			},
-			exported_java_libs: ["libfoo", "libbar"],
+			exported_bootclasspath_fragments: ["my-bootclasspath-fragment"],
+		}
+
+		prebuilt_bootclasspath_fragment {
+			name: "my-bootclasspath-fragment",
+			contents: ["libfoo", "libbar"],
+			apex_available: ["myapex"],
 		}
 
 		java_import {
@@ -4651,6 +4690,7 @@
 				jars: ["libbar.jar"],
 			},
 			apex_available: ["myapex"],
+			shared_library: false,
 		}
 
 		java_sdk_library {
@@ -4661,7 +4701,7 @@
 		}
 	`
 
-		ctx := testDexpreoptWithApexes(t, bp, "", preparer)
+		ctx := testDexpreoptWithApexes(t, bp, "", preparer, fragment)
 		checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/libfoo/android_common_apex10000/hiddenapi/libfoo.jar")
 		checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/libbar/android_common_myapex/hiddenapi/libbar.jar")
 
@@ -4697,7 +4737,13 @@
 					src: "myapex-arm.apex",
 				},
 			},
-			exported_java_libs: ["libfoo", "libbar"],
+			exported_bootclasspath_fragments: ["my-bootclasspath-fragment"],
+		}
+
+		prebuilt_bootclasspath_fragment {
+			name: "my-bootclasspath-fragment",
+			contents: ["libfoo", "libbar"],
+			apex_available: ["myapex"],
 		}
 
 		java_import {
@@ -4720,6 +4766,7 @@
 				jars: ["libbar.jar"],
 			},
 			apex_available: ["myapex"],
+			shared_library: false,
 		}
 
 		java_sdk_library {
@@ -4730,7 +4777,7 @@
 		}
 	`
 
-		ctx := testDexpreoptWithApexes(t, bp, "", preparer)
+		ctx := testDexpreoptWithApexes(t, bp, "", preparer, fragment)
 		checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar")
 		checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libbar.jar")
 
@@ -6305,7 +6352,7 @@
 	android.AssertStringEquals(t, "myapex input", extractorOutput, copiedApex.Input.String())
 }
 
-func testNoUpdatableJarsInBootImage(t *testing.T, errmsg string, preparer android.FixturePreparer) {
+func testNoUpdatableJarsInBootImage(t *testing.T, errmsg string, preparer android.FixturePreparer, fragments ...java.ApexVariantReference) {
 	t.Helper()
 
 	bp := `
@@ -6324,6 +6371,15 @@
 			apex_available: [
 				"some-non-updatable-apex",
 			],
+			compile_dex: true,
+		}
+
+		bootclasspath_fragment {
+			name: "some-non-updatable-fragment",
+			contents: ["some-non-updatable-apex-lib"],
+			apex_available: [
+				"some-non-updatable-apex",
+			],
 		}
 
 		java_library {
@@ -6355,7 +6411,7 @@
 		apex {
 			name: "some-non-updatable-apex",
 			key: "some-non-updatable-apex.key",
-			java_libs: ["some-non-updatable-apex-lib"],
+			bootclasspath_fragments: ["some-non-updatable-fragment"],
 			updatable: false,
 		}
 
@@ -6370,7 +6426,7 @@
 		apex {
 			name: "com.android.art.debug",
 			key: "com.android.art.debug.key",
-			java_libs: ["some-art-lib"],
+			bootclasspath_fragments: ["art-bootclasspath-fragment"],
 			updatable: true,
 			min_sdk_version: "current",
 		}
@@ -6403,10 +6459,10 @@
 		}
 	`
 
-	testDexpreoptWithApexes(t, bp, errmsg, preparer)
+	testDexpreoptWithApexes(t, bp, errmsg, preparer, fragments...)
 }
 
-func testDexpreoptWithApexes(t *testing.T, bp, errmsg string, preparer android.FixturePreparer) *android.TestContext {
+func testDexpreoptWithApexes(t *testing.T, bp, errmsg string, preparer android.FixturePreparer, fragments ...java.ApexVariantReference) *android.TestContext {
 	t.Helper()
 
 	fs := android.MockFS{
@@ -6434,11 +6490,22 @@
 		PrepareForTestWithApexBuildComponents,
 		preparer,
 		fs.AddToFixture(),
-		android.FixtureAddTextFile("frameworks/base/boot/Android.bp", `
-			platform_bootclasspath {
-				name: "platform-bootclasspath",
+		android.FixtureModifyMockFS(func(fs android.MockFS) {
+			if _, ok := fs["frameworks/base/boot/Android.bp"]; !ok {
+				insert := ""
+				for _, fragment := range fragments {
+					insert += fmt.Sprintf("{apex: %q, module: %q},\n", *fragment.Apex, *fragment.Module)
+				}
+				fs["frameworks/base/boot/Android.bp"] = []byte(fmt.Sprintf(`
+					platform_bootclasspath {
+						name: "platform-bootclasspath",
+						fragments: [
+  						%s
+						],
+					}
+				`, insert))
 			}
-		`),
+		}),
 	).
 		ExtendWithErrorHandler(errorHandler).
 		RunTestWithBp(t, bp)
@@ -6505,7 +6572,11 @@
 
 	t.Run("updatable jar from ART apex in the ART boot image => ok", func(t *testing.T) {
 		preparer := java.FixtureConfigureBootJars("com.android.art.debug:some-art-lib")
-		testNoUpdatableJarsInBootImage(t, "", preparer)
+		fragment := java.ApexVariantReference{
+			Apex:   proptools.StringPtr("com.android.art.debug"),
+			Module: proptools.StringPtr("art-bootclasspath-fragment"),
+		}
+		testNoUpdatableJarsInBootImage(t, "", preparer, fragment)
 	})
 
 	t.Run("updatable jar from ART apex in the framework boot image => error", func(t *testing.T) {
@@ -6537,7 +6608,11 @@
 
 	t.Run("non-updatable jar from some other apex in the framework boot image => ok", func(t *testing.T) {
 		preparer := java.FixtureConfigureBootJars("some-non-updatable-apex:some-non-updatable-apex-lib")
-		testNoUpdatableJarsInBootImage(t, "", preparer)
+		fragment := java.ApexVariantReference{
+			Apex:   proptools.StringPtr("some-non-updatable-apex"),
+			Module: proptools.StringPtr("some-non-updatable-fragment"),
+		}
+		testNoUpdatableJarsInBootImage(t, "", preparer, fragment)
 	})
 
 	t.Run("nonexistent jar in the ART boot image => error", func(t *testing.T) {
@@ -6568,6 +6643,11 @@
 func TestDexpreoptAccessDexFilesFromPrebuiltApex(t *testing.T) {
 	preparer := java.FixtureConfigureBootJars("myapex:libfoo")
 	t.Run("prebuilt no source", func(t *testing.T) {
+		fragment := java.ApexVariantReference{
+			Apex:   proptools.StringPtr("myapex"),
+			Module: proptools.StringPtr("my-bootclasspath-fragment"),
+		}
+
 		testDexpreoptWithApexes(t, `
 			prebuilt_apex {
 				name: "myapex" ,
@@ -6579,36 +6659,21 @@
 						src: "myapex-arm.apex",
 					},
 				},
-			exported_java_libs: ["libfoo"],
-		}
+				exported_bootclasspath_fragments: ["my-bootclasspath-fragment"],
+			}
 
-		java_import {
-			name: "libfoo",
-			jars: ["libfoo.jar"],
-		}
-`, "", preparer)
-	})
+			prebuilt_bootclasspath_fragment {
+				name: "my-bootclasspath-fragment",
+				contents: ["libfoo"],
+				apex_available: ["myapex"],
+			}
 
-	t.Run("prebuilt no source", func(t *testing.T) {
-		testDexpreoptWithApexes(t, `
-			prebuilt_apex {
-				name: "myapex" ,
-				arch: {
-					arm64: {
-						src: "myapex-arm64.apex",
-					},
-					arm: {
-						src: "myapex-arm.apex",
-					},
-				},
-			exported_java_libs: ["libfoo"],
-		}
-
-		java_import {
-			name: "libfoo",
-			jars: ["libfoo.jar"],
-		}
-`, "", preparer)
+			java_import {
+				name: "libfoo",
+				jars: ["libfoo.jar"],
+				apex_available: ["myapex"],
+			}
+		`, "", preparer, fragment)
 	})
 }
 
diff --git a/apex/platform_bootclasspath_test.go b/apex/platform_bootclasspath_test.go
index 7297926..bd4a9d5 100644
--- a/apex/platform_bootclasspath_test.go
+++ b/apex/platform_bootclasspath_test.go
@@ -234,12 +234,18 @@
 		apex {
 			name: "myapex",
 			key: "myapex.key",
-			java_libs: [
-				"bar",
+			bootclasspath_fragments: [
+				"my-bootclasspath-fragment",
 			],
 			updatable: false,
 		}
 
+		bootclasspath_fragment {
+			name: "my-bootclasspath-fragment",
+			contents: ["bar"],
+			apex_available: ["myapex"],
+		}
+
 		apex_key {
 			name: "myapex.key",
 			public_key: "testkey.avbpubkey",
@@ -267,6 +273,10 @@
 					apex: "com.android.art",
 					module: "art-bootclasspath-fragment",
 				},
+				{
+					apex: "myapex",
+					module: "my-bootclasspath-fragment",
+				},
 			],
 		}
 `,
@@ -283,7 +293,8 @@
 	})
 
 	java.CheckPlatformBootclasspathFragments(t, result, "myplatform-bootclasspath", []string{
-		`com.android.art:art-bootclasspath-fragment`,
+		"com.android.art:art-bootclasspath-fragment",
+		"myapex:my-bootclasspath-fragment",
 	})
 
 	// Make sure that the myplatform-bootclasspath has the correct dependencies.
@@ -307,6 +318,7 @@
 
 		// The fragments.
 		`com.android.art:art-bootclasspath-fragment`,
+		`myapex:my-bootclasspath-fragment`,
 	})
 }
 
@@ -410,6 +422,12 @@
 
 		platform_bootclasspath {
 			name: "myplatform-bootclasspath",
+			fragments: [
+				{
+					apex: "myapex",
+					module:"mybootclasspath-fragment",
+				},
+			],
 		}
 `,
 	)
@@ -431,7 +449,7 @@
 		"platform:legacy.core.platform.api.stubs",
 
 		// Needed for generating the boot image.
-		`platform:dex2oatd`,
+		"platform:dex2oatd",
 
 		// The platform_bootclasspath intentionally adds dependencies on both source and prebuilt
 		// modules when available as it does not know which one will be preferred.
@@ -442,6 +460,9 @@
 
 		// Only a source module exists.
 		"myapex:bar",
+
+		// The fragments.
+		"myapex:mybootclasspath-fragment",
 	})
 }
 
diff --git a/java/hiddenapi_monolithic.go b/java/hiddenapi_monolithic.go
index edf4235..8a83d10 100644
--- a/java/hiddenapi_monolithic.go
+++ b/java/hiddenapi_monolithic.go
@@ -43,22 +43,37 @@
 
 	// The paths to the generated all-flags.csv files.
 	AllFlagsPaths android.Paths
+
+	// The classes jars from the libraries on the platform bootclasspath.
+	ClassesJars android.Paths
 }
 
 // newMonolithicHiddenAPIInfo creates a new MonolithicHiddenAPIInfo from the flagFilesByCategory
 // plus information provided by each of the fragments.
-func newMonolithicHiddenAPIInfo(ctx android.ModuleContext, flagFilesByCategory FlagFilesByCategory, fragments []android.Module) MonolithicHiddenAPIInfo {
+func newMonolithicHiddenAPIInfo(ctx android.ModuleContext, flagFilesByCategory FlagFilesByCategory, classpathElements ClasspathElements) MonolithicHiddenAPIInfo {
 	monolithicInfo := MonolithicHiddenAPIInfo{}
 
 	monolithicInfo.FlagsFilesByCategory = flagFilesByCategory
 
-	// Merge all the information from the fragments. The fragments form a DAG so it is possible that
-	// this will introduce duplicates so they will be resolved after processing all the fragments.
-	for _, fragment := range fragments {
-		if ctx.OtherModuleHasProvider(fragment, HiddenAPIInfoProvider) {
-			info := ctx.OtherModuleProvider(fragment, HiddenAPIInfoProvider).(HiddenAPIInfo)
-			monolithicInfo.append(&info)
+	// Merge all the information from the classpathElements. The fragments form a DAG so it is possible that
+	// this will introduce duplicates so they will be resolved after processing all the classpathElements.
+	for _, element := range classpathElements {
+		var classesJars android.Paths
+		switch e := element.(type) {
+		case *ClasspathLibraryElement:
+			classesJars = retrieveClassesJarsFromModule(e.Module())
+
+		case *ClasspathFragmentElement:
+			fragment := e.Module()
+			if ctx.OtherModuleHasProvider(fragment, HiddenAPIInfoProvider) {
+				info := ctx.OtherModuleProvider(fragment, HiddenAPIInfoProvider).(HiddenAPIInfo)
+				monolithicInfo.append(&info)
+			}
+
+			classesJars = extractClassesJarsFromModules(e.Contents)
 		}
+
+		monolithicInfo.ClassesJars = append(monolithicInfo.ClassesJars, classesJars...)
 	}
 
 	// Dedup paths.
diff --git a/java/platform_bootclasspath.go b/java/platform_bootclasspath.go
index 48da29e..46fc7b5 100644
--- a/java/platform_bootclasspath.go
+++ b/java/platform_bootclasspath.go
@@ -44,13 +44,9 @@
 	properties platformBootclasspathProperties
 
 	// The apex:module pairs obtained from the configured modules.
-	//
-	// Currently only for testing.
 	configuredModules []android.Module
 
 	// The apex:module pairs obtained from the fragments.
-	//
-	// Currently only for testing.
 	fragments []android.Module
 
 	// Path to the monolithic hiddenapi-flags.csv file.
@@ -282,7 +278,15 @@
 		return bootDexJarByModule
 	}
 
-	monolithicInfo := b.createAndProvideMonolithicHiddenAPIInfo(ctx, fragments)
+	// Construct a list of ClasspathElement objects from the modules and fragments.
+	classpathElements := CreateClasspathElements(ctx, modules, fragments)
+
+	monolithicInfo := b.createAndProvideMonolithicHiddenAPIInfo(ctx, classpathElements)
+
+	// Extract the classes jars only from those libraries that do not have corresponding fragments as
+	// the fragments will have already provided the flags that are needed.
+	classesJars := monolithicInfo.ClassesJars
+
 	// Create the input to pass to ruleToGenerateHiddenAPIStubFlagsFile
 	input := newHiddenAPIFlagInput()
 
@@ -298,9 +302,6 @@
 	rule := ruleToGenerateHiddenAPIStubFlagsFile(ctx, stubFlags, bootDexJarByModule.bootDexJars(), input)
 	rule.Build("platform-bootclasspath-monolithic-hiddenapi-stub-flags", "monolithic hidden API stub flags")
 
-	// Extract the classes jars from the contents.
-	classesJars := extractClassesJarsFromModules(modules)
-
 	// Generate the annotation-flags.csv file from all the module annotations.
 	annotationFlags := android.PathForModuleOut(ctx, "hiddenapi-monolithic", "annotation-flags.csv")
 	buildRuleToGenerateAnnotationFlags(ctx, "monolithic hiddenapi flags", classesJars, stubFlags, annotationFlags)
@@ -330,7 +331,7 @@
 
 // createAndProvideMonolithicHiddenAPIInfo creates a MonolithicHiddenAPIInfo and provides it for
 // testing.
-func (b *platformBootclasspathModule) createAndProvideMonolithicHiddenAPIInfo(ctx android.ModuleContext, fragments []android.Module) MonolithicHiddenAPIInfo {
+func (b *platformBootclasspathModule) createAndProvideMonolithicHiddenAPIInfo(ctx android.ModuleContext, classpathElements ClasspathElements) MonolithicHiddenAPIInfo {
 	// Create a temporary input structure in which to collate information provided directly by this
 	// module, either through properties or direct dependencies.
 	temporaryInput := newHiddenAPIFlagInput()
@@ -340,7 +341,7 @@
 
 	// Create the monolithic info, by starting with the flag files specified on this and then merging
 	// in information from all the fragment dependencies of this.
-	monolithicInfo := newMonolithicHiddenAPIInfo(ctx, temporaryInput.FlagFilesByCategory, fragments)
+	monolithicInfo := newMonolithicHiddenAPIInfo(ctx, temporaryInput.FlagFilesByCategory, classpathElements)
 
 	// Store the information for testing.
 	ctx.SetProvider(MonolithicHiddenAPIInfoProvider, monolithicInfo)