Exclude unsupported libraries from sdk snapshot

When an sdk snapshot is targeted at release X then it cannot include
bootclasspath fragment libraries which are not present in that build as
otherwise it causes build failures. It should also not include any
unsupported libraries, i.e. libraries that cannot work on that release.

This change causes sdk snapshot to exclude libraries that have a
    min_sdk_version > target build release

It also ensures that hidden API flags do not include any information
from excluded libraries.

Bug: 240406019
Test: BUILD_NUMBER=fixed packages/modules/common/build/mainline_modules_sdks.sh
      # Ran the previous command with and without this change to make
      # sure that this change excludes framework-connectivity-t library from the
      # tethering sdk snapshot for S, including from the hidden API flag files.
Change-Id: I57969b85a12e9e5a3fc76c055b260cec5d5f7d7f
diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go
index 919181d..62683a4 100644
--- a/java/bootclasspath_fragment.go
+++ b/java/bootclasspath_fragment.go
@@ -257,7 +257,7 @@
 	// Returns a *HiddenAPIOutput containing the paths for the generated files. Returns nil if the
 	// module cannot contribute to hidden API processing, e.g. because it is a prebuilt module in a
 	// versioned sdk.
-	produceHiddenAPIOutput(ctx android.ModuleContext, contents []android.Module, input HiddenAPIFlagInput) *HiddenAPIOutput
+	produceHiddenAPIOutput(ctx android.ModuleContext, contents []android.Module, fragments []android.Module, input HiddenAPIFlagInput) *HiddenAPIOutput
 
 	// produceBootImageFiles will attempt to produce rules to create the boot image files at the paths
 	// predefined in the bootImageConfig.
@@ -761,7 +761,7 @@
 
 	// Delegate the production of the hidden API all-flags.csv file to a module type specific method.
 	common := ctx.Module().(commonBootclasspathFragment)
-	output := common.produceHiddenAPIOutput(ctx, contents, input)
+	output := common.produceHiddenAPIOutput(ctx, contents, fragments, input)
 
 	// If the source or prebuilts module does not provide a signature patterns file then generate one
 	// from the flags.
@@ -769,7 +769,7 @@
 	//  their own.
 	if output.SignaturePatternsPath == nil {
 		output.SignaturePatternsPath = buildRuleSignaturePatternsFile(
-			ctx, output.AllFlagsPath, []string{"*"}, nil, nil)
+			ctx, output.AllFlagsPath, []string{"*"}, nil, nil, "")
 	}
 
 	// Initialize a HiddenAPIInfo structure.
@@ -863,7 +863,7 @@
 func (b *BootclasspathFragmentModule) generateHiddenApiFlagRules(ctx android.ModuleContext, contents []android.Module, input HiddenAPIFlagInput, bootDexInfoByModule bootDexInfoByModule, suffix string) HiddenAPIFlagOutput {
 	// Generate the rules to create the hidden API flags and update the supplied hiddenAPIInfo with the
 	// paths to the created files.
-	flagOutput := hiddenAPIFlagRulesForBootclasspathFragment(ctx, bootDexInfoByModule, contents, input)
+	flagOutput := hiddenAPIFlagRulesForBootclasspathFragment(ctx, bootDexInfoByModule, contents, input, suffix)
 
 	// If the module specifies split_packages or package_prefixes then use those to generate the
 	// signature patterns.
@@ -872,7 +872,7 @@
 	singlePackages := input.SinglePackages
 	if splitPackages != nil || packagePrefixes != nil || singlePackages != nil {
 		flagOutput.SignaturePatternsPath = buildRuleSignaturePatternsFile(
-			ctx, flagOutput.AllFlagsPath, splitPackages, packagePrefixes, singlePackages)
+			ctx, flagOutput.AllFlagsPath, splitPackages, packagePrefixes, singlePackages, suffix)
 	} else if !b.isTestFragment() {
 		ctx.ModuleErrorf(`Must specify at least one of the split_packages, package_prefixes and single_packages properties
   If this is a new bootclasspath_fragment or you are unsure what to do add the
@@ -889,7 +889,7 @@
 
 // produceHiddenAPIOutput produces the hidden API all-flags.csv file (and supporting files)
 // for the fragment as well as encoding the flags in the boot dex jars.
-func (b *BootclasspathFragmentModule) produceHiddenAPIOutput(ctx android.ModuleContext, contents []android.Module, input HiddenAPIFlagInput) *HiddenAPIOutput {
+func (b *BootclasspathFragmentModule) produceHiddenAPIOutput(ctx android.ModuleContext, contents []android.Module, fragments []android.Module, input HiddenAPIFlagInput) *HiddenAPIOutput {
 	// Gather information about the boot dex files for the boot libraries provided by this fragment.
 	bootDexInfoByModule := extractBootDexInfoFromModules(ctx, contents)
 
@@ -905,7 +905,41 @@
 		EncodedBootDexFilesByModule: encodedBootDexFilesByModule,
 	}
 
-	flagFilesByCategory := input.FlagFilesByCategory
+	// Get the ApiLevel associated with SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE, defaulting to current
+	// if not set.
+	config := ctx.Config()
+	targetApiLevel := android.ApiLevelOrPanic(ctx,
+		config.GetenvWithDefault("SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE", "current"))
+
+	// Filter the contents list to remove any modules that do not support the target build release.
+	// The current build release supports all the modules.
+	contentsForSdkSnapshot := []android.Module{}
+	for _, module := range contents {
+		// If the module has a min_sdk_version that is higher than the target build release then it will
+		// not work on the target build release and so must not be included in the sdk snapshot.
+		minApiLevel := android.MinApiLevelForSdkSnapshot(ctx, module)
+		if minApiLevel.GreaterThan(targetApiLevel) {
+			continue
+		}
+
+		contentsForSdkSnapshot = append(contentsForSdkSnapshot, module)
+	}
+
+	var flagFilesByCategory FlagFilesByCategory
+	if len(contentsForSdkSnapshot) != len(contents) {
+		// The sdk snapshot has different contents to the runtime fragment so it is not possible to
+		// reuse the hidden API information generated for the fragment. So, recompute that information
+		// for the sdk snapshot.
+		filteredInput := b.createHiddenAPIFlagInput(ctx, contentsForSdkSnapshot, fragments)
+
+		// Gather information about the boot dex files for the boot libraries provided by this fragment.
+		filteredBootDexInfoByModule := extractBootDexInfoFromModules(ctx, contentsForSdkSnapshot)
+		flagOutput = b.generateHiddenApiFlagRules(ctx, contentsForSdkSnapshot, filteredInput, filteredBootDexInfoByModule, "-for-sdk-snapshot")
+		flagFilesByCategory = filteredInput.FlagFilesByCategory
+	} else {
+		// The sdk snapshot has the same contents as the runtime fragment so reuse that information.
+		flagFilesByCategory = input.FlagFilesByCategory
+	}
 
 	// Make the information available for the sdk snapshot.
 	ctx.SetProvider(HiddenAPIInfoForSdkProvider, HiddenAPIInfoForSdk{
@@ -1219,7 +1253,7 @@
 }
 
 // produceHiddenAPIOutput returns a path to the prebuilt all-flags.csv or nil if none is specified.
-func (module *PrebuiltBootclasspathFragmentModule) produceHiddenAPIOutput(ctx android.ModuleContext, contents []android.Module, input HiddenAPIFlagInput) *HiddenAPIOutput {
+func (module *PrebuiltBootclasspathFragmentModule) produceHiddenAPIOutput(ctx android.ModuleContext, contents []android.Module, fragments []android.Module, input HiddenAPIFlagInput) *HiddenAPIOutput {
 	pathForOptionalSrc := func(src *string, defaultPath android.Path) android.Path {
 		if src == nil {
 			return defaultPath
diff --git a/java/hiddenapi_modular.go b/java/hiddenapi_modular.go
index af11889..5474ae1 100644
--- a/java/hiddenapi_modular.go
+++ b/java/hiddenapi_modular.go
@@ -1041,8 +1041,11 @@
 // patterns that will select a subset of the monolithic flags.
 func buildRuleSignaturePatternsFile(
 	ctx android.ModuleContext, flagsPath android.Path,
-	splitPackages []string, packagePrefixes []string, singlePackages []string) android.Path {
-	patternsFile := android.PathForModuleOut(ctx, "modular-hiddenapi", "signature-patterns.csv")
+	splitPackages []string, packagePrefixes []string, singlePackages []string,
+	suffix string) android.Path {
+	hiddenApiSubDir := "modular-hiddenapi" + suffix
+
+	patternsFile := android.PathForModuleOut(ctx, hiddenApiSubDir, "signature-patterns.csv")
 	// Create a rule to validate the output from the following rule.
 	rule := android.NewRuleBuilder(pctx, ctx)
 
@@ -1059,7 +1062,7 @@
 		FlagForEachArg("--package-prefix ", packagePrefixes).
 		FlagForEachArg("--single-package ", singlePackages).
 		FlagWithOutput("--output ", patternsFile)
-	rule.Build("hiddenAPISignaturePatterns", "hidden API signature patterns")
+	rule.Build("hiddenAPISignaturePatterns"+suffix, "hidden API signature patterns"+suffix)
 
 	return patternsFile
 }
@@ -1147,27 +1150,27 @@
 // * metadata.csv
 // * index.csv
 // * all-flags.csv
-func hiddenAPIFlagRulesForBootclasspathFragment(ctx android.ModuleContext, bootDexInfoByModule bootDexInfoByModule, contents []android.Module, input HiddenAPIFlagInput) HiddenAPIFlagOutput {
-	hiddenApiSubDir := "modular-hiddenapi"
+func hiddenAPIFlagRulesForBootclasspathFragment(ctx android.ModuleContext, bootDexInfoByModule bootDexInfoByModule, contents []android.Module, input HiddenAPIFlagInput, suffix string) HiddenAPIFlagOutput {
+	hiddenApiSubDir := "modular-hiddenapi" + suffix
 
 	// Generate the stub-flags.csv.
 	stubFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "stub-flags.csv")
-	buildRuleToGenerateHiddenAPIStubFlagsFile(ctx, "modularHiddenAPIStubFlagsFile", "modular hiddenapi stub flags", stubFlagsCSV, bootDexInfoByModule.bootDexJars(), input, nil)
+	buildRuleToGenerateHiddenAPIStubFlagsFile(ctx, "modularHiddenAPIStubFlagsFile"+suffix, "modular hiddenapi stub flags", stubFlagsCSV, bootDexInfoByModule.bootDexJars(), input, nil)
 
 	// Extract the classes jars from the contents.
 	classesJars := extractClassesJarsFromModules(contents)
 
 	// Generate the set of flags from the annotations in the source code.
 	annotationFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "annotation-flags.csv")
-	buildRuleToGenerateAnnotationFlags(ctx, "modular hiddenapi annotation flags", classesJars, stubFlagsCSV, annotationFlagsCSV)
+	buildRuleToGenerateAnnotationFlags(ctx, "modular hiddenapi annotation flags"+suffix, classesJars, stubFlagsCSV, annotationFlagsCSV)
 
 	// Generate the metadata from the annotations in the source code.
 	metadataCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "metadata.csv")
-	buildRuleToGenerateMetadata(ctx, "modular hiddenapi metadata", classesJars, stubFlagsCSV, metadataCSV)
+	buildRuleToGenerateMetadata(ctx, "modular hiddenapi metadata"+suffix, classesJars, stubFlagsCSV, metadataCSV)
 
 	// Generate the index file from the CSV files in the classes jars.
 	indexCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "index.csv")
-	buildRuleToGenerateIndex(ctx, "modular hiddenapi index", classesJars, indexCSV)
+	buildRuleToGenerateIndex(ctx, "modular hiddenapi index"+suffix, classesJars, indexCSV)
 
 	// Removed APIs need to be marked and in order to do that the hiddenAPIInfo needs to specify files
 	// containing dex signatures of all the removed APIs. In the monolithic files that is done by
@@ -1175,25 +1178,25 @@
 	// signatures, see the combined-removed-dex module. This does that automatically by using the
 	// *removed.txt files retrieved from the java_sdk_library modules that are specified in the
 	// stub_libs and contents properties of a bootclasspath_fragment.
-	removedDexSignatures := buildRuleToGenerateRemovedDexSignatures(ctx, input.RemovedTxtFiles)
+	removedDexSignatures := buildRuleToGenerateRemovedDexSignatures(ctx, suffix, input.RemovedTxtFiles)
 
 	// Generate the all-flags.csv which are the flags that will, in future, be encoded into the dex
 	// files.
 	allFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "all-flags.csv")
-	buildRuleToGenerateHiddenApiFlags(ctx, "modularHiddenApiAllFlags", "modular hiddenapi all flags", allFlagsCSV, stubFlagsCSV, android.Paths{annotationFlagsCSV}, input.FlagFilesByCategory, nil, removedDexSignatures)
+	buildRuleToGenerateHiddenApiFlags(ctx, "modularHiddenApiAllFlags"+suffix, "modular hiddenapi all flags"+suffix, allFlagsCSV, stubFlagsCSV, android.Paths{annotationFlagsCSV}, input.FlagFilesByCategory, nil, removedDexSignatures)
 
 	// Generate the filtered-stub-flags.csv file which contains the filtered stub flags that will be
 	// compared against the monolithic stub flags.
 	filteredStubFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "filtered-stub-flags.csv")
-	buildRuleRemoveSignaturesWithImplementationFlags(ctx, "modularHiddenApiFilteredStubFlags",
-		"modular hiddenapi filtered stub flags", stubFlagsCSV, filteredStubFlagsCSV,
+	buildRuleRemoveSignaturesWithImplementationFlags(ctx, "modularHiddenApiFilteredStubFlags"+suffix,
+		"modular hiddenapi filtered stub flags"+suffix, stubFlagsCSV, filteredStubFlagsCSV,
 		HIDDENAPI_STUB_FLAGS_IMPL_FLAGS)
 
 	// Generate the filtered-flags.csv file which contains the filtered flags that will be compared
 	// against the monolithic flags.
 	filteredFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "filtered-flags.csv")
-	buildRuleRemoveSignaturesWithImplementationFlags(ctx, "modularHiddenApiFilteredFlags",
-		"modular hiddenapi filtered flags", allFlagsCSV, filteredFlagsCSV,
+	buildRuleRemoveSignaturesWithImplementationFlags(ctx, "modularHiddenApiFilteredFlags"+suffix,
+		"modular hiddenapi filtered flags"+suffix, allFlagsCSV, filteredFlagsCSV,
 		HIDDENAPI_FLAGS_CSV_IMPL_FLAGS)
 
 	// Store the paths in the info for use by other modules and sdk snapshot generation.
@@ -1223,12 +1226,12 @@
 	return encodedBootDexJarsByModule
 }
 
-func buildRuleToGenerateRemovedDexSignatures(ctx android.ModuleContext, removedTxtFiles android.Paths) android.OptionalPath {
+func buildRuleToGenerateRemovedDexSignatures(ctx android.ModuleContext, suffix string, removedTxtFiles android.Paths) android.OptionalPath {
 	if len(removedTxtFiles) == 0 {
 		return android.OptionalPath{}
 	}
 
-	output := android.PathForModuleOut(ctx, "modular-hiddenapi/removed-dex-signatures.txt")
+	output := android.PathForModuleOut(ctx, "module-hiddenapi"+suffix, "removed-dex-signatures.txt")
 
 	rule := android.NewRuleBuilder(pctx, ctx)
 	rule.Command().
@@ -1236,7 +1239,7 @@
 		Flag("--no-banner").
 		Inputs(removedTxtFiles).
 		FlagWithOutput("--dex-api ", output)
-	rule.Build("modular-hiddenapi-removed-dex-signatures", "modular hiddenapi removed dex signatures")
+	rule.Build("modular-hiddenapi-removed-dex-signatures"+suffix, "modular hiddenapi removed dex signatures"+suffix)
 	return android.OptionalPathForPath(output)
 }