Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 74431d57 authored by Paul Duffin's avatar Paul Duffin
Browse files

Move monolithic stub flags generation to platform_bootclasspath

As part of that this change:
* Moves code that will be common to platform_bootclasspath and
  bootclasspath_fragment from hiddenapi_singleton.go into
  hiddenapi_modular.go.
* Fixes the tests in hiddenapi_singleton_test.go but intentionally
  does not rename them or move them into a more appropriate place so
  as to make it easier to see the differences. A TODO has been added
  and these will be cleaned up in a follow up change.

Bug: 179354495
Test: verified that the monolithic out/soong/hiddenapi/... files are
      unchanged by this change
Change-Id: I680e4dab2e6bdf4a655fa9f255c195175904667e
parent 3e7fcc3f
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -137,9 +137,12 @@ func TestPlatformBootclasspathDependencies(t *testing.T) {
	)

	java.CheckPlatformBootclasspathModules(t, result, "myplatform-bootclasspath", []string{
		// The configured contents of BootJars.
		"com.android.art:baz",
		"com.android.art:quuz",
		"platform:foo",

		// The configured contents of UpdatableBootJars.
		"myapex:bar",
	})

@@ -149,11 +152,24 @@ func TestPlatformBootclasspathDependencies(t *testing.T) {

	// Make sure that the myplatform-bootclasspath has the correct dependencies.
	CheckModuleDependencies(t, result.TestContext, "myplatform-bootclasspath", "android_common", []string{
		// The following are stubs.
		`platform:android_stubs_current`,
		`platform:android_system_stubs_current`,
		`platform:android_test_stubs_current`,
		`platform:legacy.core.platform.api.stubs`,

		// Needed for generating the boot image.
		`platform:dex2oatd`,

		// The configured contents of BootJars.
		`com.android.art:baz`,
		`com.android.art:quuz`,
		`platform:foo`,

		// The configured contents of UpdatableBootJars.
		`myapex:bar`,

		// The fragments.
		`com.android.art:art-bootclasspath-fragment`,
	})
}
+143 −0
Original line number Diff line number Diff line
@@ -21,6 +21,30 @@ import (

// Contains support for processing hiddenAPI in a modular fashion.

type hiddenAPIStubsDependencyTag struct {
	blueprint.BaseDependencyTag
	sdkKind android.SdkKind
}

func (b hiddenAPIStubsDependencyTag) ExcludeFromApexContents() {
}

func (b hiddenAPIStubsDependencyTag) ReplaceSourceWithPrebuilt() bool {
	return false
}

// Avoid having to make stubs content explicitly visible to dependent modules.
//
// This is a temporary workaround to make it easier to migrate to bootclasspath_fragment modules
// with proper dependencies.
// TODO(b/177892522): Remove this and add needed visibility.
func (b hiddenAPIStubsDependencyTag) ExcludeFromVisibilityEnforcement() {
}

var _ android.ExcludeFromVisibilityEnforcementTag = hiddenAPIStubsDependencyTag{}
var _ android.ReplaceSourceWithPrebuilt = hiddenAPIStubsDependencyTag{}
var _ android.ExcludeFromApexContentsTag = hiddenAPIStubsDependencyTag{}

// hiddenAPIRelevantSdkKinds lists all the android.SdkKind instances that are needed by the hidden
// API processing.
var hiddenAPIRelevantSdkKinds = []android.SdkKind{
@@ -30,6 +54,125 @@ var hiddenAPIRelevantSdkKinds = []android.SdkKind{
	android.SdkCorePlatform,
}

// hiddenAPIComputeMonolithicStubLibModules computes the set of module names that provide stubs
// needed to produce the hidden API monolithic stub flags file.
func hiddenAPIComputeMonolithicStubLibModules(config android.Config) map[android.SdkKind][]string {
	var publicStubModules []string
	var systemStubModules []string
	var testStubModules []string
	var corePlatformStubModules []string

	if config.AlwaysUsePrebuiltSdks() {
		// Build configuration mandates using prebuilt stub modules
		publicStubModules = append(publicStubModules, "sdk_public_current_android")
		systemStubModules = append(systemStubModules, "sdk_system_current_android")
		testStubModules = append(testStubModules, "sdk_test_current_android")
	} else {
		// Use stub modules built from source
		publicStubModules = append(publicStubModules, "android_stubs_current")
		systemStubModules = append(systemStubModules, "android_system_stubs_current")
		testStubModules = append(testStubModules, "android_test_stubs_current")
	}
	// We do not have prebuilts of the core platform api yet
	corePlatformStubModules = append(corePlatformStubModules, "legacy.core.platform.api.stubs")

	// Allow products to define their own stubs for custom product jars that apps can use.
	publicStubModules = append(publicStubModules, config.ProductHiddenAPIStubs()...)
	systemStubModules = append(systemStubModules, config.ProductHiddenAPIStubsSystem()...)
	testStubModules = append(testStubModules, config.ProductHiddenAPIStubsTest()...)
	if config.IsEnvTrue("EMMA_INSTRUMENT") {
		publicStubModules = append(publicStubModules, "jacoco-stubs")
	}

	m := map[android.SdkKind][]string{}
	m[android.SdkPublic] = publicStubModules
	m[android.SdkSystem] = systemStubModules
	m[android.SdkTest] = testStubModules
	m[android.SdkCorePlatform] = corePlatformStubModules
	return m
}

// hiddenAPIAddStubLibDependencies adds dependencies onto the modules specified in
// sdkKindToStubLibModules. It adds them in a well known order and uses an SdkKind specific tag to
// identify the source of the dependency.
func hiddenAPIAddStubLibDependencies(ctx android.BottomUpMutatorContext, sdkKindToStubLibModules map[android.SdkKind][]string) {
	module := ctx.Module()
	for _, sdkKind := range hiddenAPIRelevantSdkKinds {
		modules := sdkKindToStubLibModules[sdkKind]
		ctx.AddDependency(module, hiddenAPIStubsDependencyTag{sdkKind: sdkKind}, modules...)
	}
}

// hiddenAPIGatherStubLibDexJarPaths gathers the paths to the dex jars from the dependencies added
// in hiddenAPIAddStubLibDependencies.
func hiddenAPIGatherStubLibDexJarPaths(ctx android.ModuleContext) map[android.SdkKind]android.Paths {
	m := map[android.SdkKind]android.Paths{}
	ctx.VisitDirectDepsIf(isActiveModule, func(module android.Module) {
		tag := ctx.OtherModuleDependencyTag(module)
		if hiddenAPIStubsTag, ok := tag.(hiddenAPIStubsDependencyTag); ok {
			kind := hiddenAPIStubsTag.sdkKind
			dexJar := hiddenAPIRetrieveDexJarBuildPath(ctx, module)
			if dexJar != nil {
				m[kind] = append(m[kind], dexJar)
			}
		}
	})
	return m
}

// hiddenAPIRetrieveDexJarBuildPath retrieves the DexJarBuildPath from the specified module, if
// available, or reports an error.
func hiddenAPIRetrieveDexJarBuildPath(ctx android.ModuleContext, module android.Module) android.Path {
	if j, ok := module.(UsesLibraryDependency); ok {
		dexJar := j.DexJarBuildPath()
		if dexJar != nil {
			return dexJar
		}
		ctx.ModuleErrorf("dependency %s does not provide a dex jar, consider setting compile_dex: true", module)
	} else {
		ctx.ModuleErrorf("dependency %s of module type %s does not support providing a dex jar", module, ctx.OtherModuleType(module))
	}
	return nil
}

var sdkKindToHiddenapiListOption = map[android.SdkKind]string{
	android.SdkPublic:       "public-stub-classpath",
	android.SdkSystem:       "system-stub-classpath",
	android.SdkTest:         "test-stub-classpath",
	android.SdkCorePlatform: "core-platform-stub-classpath",
}

// ruleToGenerateHiddenAPIStubFlagsFile creates a rule to create a hidden API stub flags file.
//
// The rule is initialized but not built so that the caller can modify it and select an appropriate
// name.
func ruleToGenerateHiddenAPIStubFlagsFile(ctx android.BuilderContext, outputPath android.OutputPath, bootDexJars android.Paths, sdkKindToPathList map[android.SdkKind]android.Paths) *android.RuleBuilder {
	// Singleton rule which applies hiddenapi on all boot class path dex files.
	rule := android.NewRuleBuilder(pctx, ctx)

	tempPath := tempPathForRestat(ctx, outputPath)

	command := rule.Command().
		Tool(ctx.Config().HostToolPath(ctx, "hiddenapi")).
		Text("list").
		FlagForEachInput("--boot-dex=", bootDexJars)

	// Iterate over the sdk kinds in a fixed order.
	for _, sdkKind := range hiddenAPIRelevantSdkKinds {
		paths := sdkKindToPathList[sdkKind]
		if len(paths) > 0 {
			option := sdkKindToHiddenapiListOption[sdkKind]
			command.FlagWithInputList("--"+option+"=", paths, ":")
		}
	}

	// Add the output path.
	command.FlagWithOutput("--out-api-flags=", tempPath)

	commitChangeForRestat(rule, tempPath, outputPath)
	return rule
}

// HiddenAPIFlagFileProperties contains paths to the flag files that can be used to augment the
// information obtained from annotations within the source code in order to create the complete set
// of flags that should be applied to the dex implementation jars on the bootclasspath.
+0 −133
Original line number Diff line number Diff line
@@ -127,8 +127,6 @@ func (h *hiddenAPISingleton) GenerateBuildActions(ctx android.SingletonContext)
		return
	}

	stubFlagsRule(ctx)

	// If there is a prebuilt hiddenapi dir, generate rules to use the
	// files within. Generally, we build the hiddenapi files from source
	// during the build, ensuring consistency. It's possible, in a split
@@ -160,137 +158,6 @@ func (h *hiddenAPISingleton) MakeVars(ctx android.MakeVarsContext) {
	ctx.Strict("INTERNAL_PLATFORM_HIDDENAPI_FLAGS", h.flags.String())
}

// hiddenAPIComputeMonolithicStubLibModules computes the set of module names that provide stubs
// needed to produce the hidden API monolithic stub flags file.
func hiddenAPIComputeMonolithicStubLibModules(ctx android.BuilderContext) map[android.SdkKind][]string {
	var publicStubModules []string
	var systemStubModules []string
	var testStubModules []string
	var corePlatformStubModules []string

	if ctx.Config().AlwaysUsePrebuiltSdks() {
		// Build configuration mandates using prebuilt stub modules
		publicStubModules = append(publicStubModules, "sdk_public_current_android")
		systemStubModules = append(systemStubModules, "sdk_system_current_android")
		testStubModules = append(testStubModules, "sdk_test_current_android")
	} else {
		// Use stub modules built from source
		publicStubModules = append(publicStubModules, "android_stubs_current")
		systemStubModules = append(systemStubModules, "android_system_stubs_current")
		testStubModules = append(testStubModules, "android_test_stubs_current")
	}
	// We do not have prebuilts of the core platform api yet
	corePlatformStubModules = append(corePlatformStubModules, "legacy.core.platform.api.stubs")

	// Allow products to define their own stubs for custom product jars that apps can use.
	publicStubModules = append(publicStubModules, ctx.Config().ProductHiddenAPIStubs()...)
	systemStubModules = append(systemStubModules, ctx.Config().ProductHiddenAPIStubsSystem()...)
	testStubModules = append(testStubModules, ctx.Config().ProductHiddenAPIStubsTest()...)
	if ctx.Config().IsEnvTrue("EMMA_INSTRUMENT") {
		publicStubModules = append(publicStubModules, "jacoco-stubs")
	}

	m := map[android.SdkKind][]string{}
	m[android.SdkPublic] = publicStubModules
	m[android.SdkSystem] = systemStubModules
	m[android.SdkTest] = testStubModules
	m[android.SdkCorePlatform] = corePlatformStubModules
	return m
}

// stubFlagsRule creates the rule to build hiddenapi-stub-flags.txt out of dex jars from stub modules and boot image
// modules.
func stubFlagsRule(ctx android.SingletonContext) {

	sdkKindToModules := hiddenAPIComputeMonolithicStubLibModules(ctx)

	// Create a set of path slices into which the DexJarBuildPath from the stub modules can be stored.
	sdkKindToPathList := map[android.SdkKind]android.Paths{}
	for sdkKind, modules := range sdkKindToModules {
		sdkKindToPathList[sdkKind] = make(android.Paths, len(modules))
	}

	var bootDexJars android.Paths
	ctx.VisitAllModules(func(module android.Module) {
		// Collect dex jar paths for the modules listed above.
		if j, ok := module.(UsesLibraryDependency); ok {
			name := ctx.ModuleName(module)
			for _, sdkKind := range hiddenAPIRelevantSdkKinds {
				if i := android.IndexList(name, sdkKindToModules[sdkKind]); i != -1 {
					sdkKindToPathList[sdkKind][i] = j.DexJarBuildPath()
				}
			}
		}

		// Collect dex jar paths for modules that had hiddenapi encode called on them.
		if h, ok := module.(hiddenAPIIntf); ok {
			if jar := h.bootDexJar(); jar != nil {
				bootDexJars = append(bootDexJars, jar)
			}
		}
	})

	var missingDeps []string
	// Ensure all modules were converted to paths
	for _, sdkKind := range hiddenAPIRelevantSdkKinds {
		pathList := sdkKindToPathList[sdkKind]
		for i := range pathList {
			if pathList[i] == nil {
				moduleName := sdkKindToModules[sdkKind][i]
				pathList[i] = android.PathForOutput(ctx, "missing/module", moduleName)
				if ctx.Config().AllowMissingDependencies() {
					missingDeps = append(missingDeps, moduleName)
				} else {
					ctx.Errorf("failed to find dex jar path for module %q", moduleName)
				}
			}
		}
	}

	outputPath := hiddenAPISingletonPaths(ctx).stubFlags
	rule := ruleToGenerateHiddenAPIStubFlagsFile(ctx, outputPath, bootDexJars, sdkKindToPathList)
	rule.MissingDeps(missingDeps)
	rule.Build("hiddenAPIStubFlagsFile", "hiddenapi stub flags")
}

var sdkKindToHiddenapiListOption = map[android.SdkKind]string{
	android.SdkPublic:       "public-stub-classpath",
	android.SdkSystem:       "system-stub-classpath",
	android.SdkTest:         "test-stub-classpath",
	android.SdkCorePlatform: "core-platform-stub-classpath",
}

// ruleToGenerateHiddenAPIStubFlagsFile creates a rule to create a hidden API stub flags file.
//
// The rule is initialized but not built so that the caller can modify it and select an appropriate
// name.
func ruleToGenerateHiddenAPIStubFlagsFile(ctx android.SingletonContext, outputPath android.OutputPath, bootDexJars android.Paths, sdkKindToPathList map[android.SdkKind]android.Paths) *android.RuleBuilder {
	// Singleton rule which applies hiddenapi on all boot class path dex files.
	rule := android.NewRuleBuilder(pctx, ctx)

	tempPath := tempPathForRestat(ctx, outputPath)

	command := rule.Command().
		Tool(ctx.Config().HostToolPath(ctx, "hiddenapi")).
		Text("list").
		FlagForEachInput("--boot-dex=", bootDexJars)

	// Iterate over the sdk
	for _, sdkKind := range hiddenAPIRelevantSdkKinds {
		paths := sdkKindToPathList[sdkKind]
		if len(paths) > 0 {
			option := sdkKindToHiddenapiListOption[sdkKind]
			command.FlagWithInputList("--"+option+"=", paths, ":")
		}
	}

	// Add the output path.
	command.FlagWithOutput("--out-api-flags=", tempPath)

	commitChangeForRestat(rule, tempPath, outputPath)
	return rule
}

// Checks to see whether the supplied module variant is in the list of boot jars.
//
// This is similar to logic in getBootImageJar() so any changes needed here are likely to be needed
+24 −10
Original line number Diff line number Diff line
@@ -23,12 +23,20 @@ import (
	"github.com/google/blueprint/proptools"
)

// TODO(b/177892522): Move these tests into a more appropriate place.

func fixtureSetPrebuiltHiddenApiDirProductVariable(prebuiltHiddenApiDir *string) android.FixturePreparer {
	return android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
		variables.PrebuiltHiddenApiDir = prebuiltHiddenApiDir
	})
}

var prepareForTestWithDefaultPlatformBootclasspath = android.FixtureAddTextFile("frameworks/base/boot/Android.bp", `
	platform_bootclasspath {
		name: "platform-bootclasspath",
	}
`)

var hiddenApiFixtureFactory = android.GroupFixturePreparers(
	prepareForJavaTest, PrepareForTestWithHiddenApiBuildComponents)

@@ -36,6 +44,7 @@ func TestHiddenAPISingleton(t *testing.T) {
	result := android.GroupFixturePreparers(
		hiddenApiFixtureFactory,
		FixtureConfigureBootJars("platform:foo"),
		prepareForTestWithDefaultPlatformBootclasspath,
	).RunTestWithBp(t, `
		java_library {
			name: "foo",
@@ -44,8 +53,8 @@ func TestHiddenAPISingleton(t *testing.T) {
		}
	`)

	hiddenAPI := result.SingletonForTests("hiddenapi")
	hiddenapiRule := hiddenAPI.Rule("hiddenapi")
	hiddenAPI := result.ModuleForTests("platform-bootclasspath", "android_common")
	hiddenapiRule := hiddenAPI.Rule("platform-bootclasspath-monolithic-hiddenapi-stub-flags")
	want := "--boot-dex=out/soong/.intermediates/foo/android_common/aligned/foo.jar"
	android.AssertStringDoesContain(t, "hiddenapi command", hiddenapiRule.RuleParams.Command, want)
}
@@ -59,6 +68,7 @@ func TestHiddenAPISingletonWithSourceAndPrebuiltPreferredButNoDex(t *testing.T)
	android.GroupFixturePreparers(
		hiddenApiFixtureFactory,
		FixtureConfigureBootJars("platform:foo"),
		prepareForTestWithDefaultPlatformBootclasspath,
	).ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(expectedErrorMessage)).
		RunTestWithBp(t, `
		java_library {
@@ -79,6 +89,7 @@ func TestHiddenAPISingletonWithPrebuilt(t *testing.T) {
	result := android.GroupFixturePreparers(
		hiddenApiFixtureFactory,
		FixtureConfigureBootJars("platform:foo"),
		prepareForTestWithDefaultPlatformBootclasspath,
	).RunTestWithBp(t, `
		java_import {
			name: "foo",
@@ -87,8 +98,8 @@ func TestHiddenAPISingletonWithPrebuilt(t *testing.T) {
	}
	`)

	hiddenAPI := result.SingletonForTests("hiddenapi")
	hiddenapiRule := hiddenAPI.Rule("hiddenapi")
	hiddenAPI := result.ModuleForTests("platform-bootclasspath", "android_common")
	hiddenapiRule := hiddenAPI.Rule("platform-bootclasspath-monolithic-hiddenapi-stub-flags")
	want := "--boot-dex=out/soong/.intermediates/foo/android_common/aligned/foo.jar"
	android.AssertStringDoesContain(t, "hiddenapi command", hiddenapiRule.RuleParams.Command, want)
}
@@ -97,6 +108,7 @@ func TestHiddenAPISingletonWithPrebuiltUseSource(t *testing.T) {
	result := android.GroupFixturePreparers(
		hiddenApiFixtureFactory,
		FixtureConfigureBootJars("platform:foo"),
		prepareForTestWithDefaultPlatformBootclasspath,
	).RunTestWithBp(t, `
		java_library {
			name: "foo",
@@ -112,8 +124,8 @@ func TestHiddenAPISingletonWithPrebuiltUseSource(t *testing.T) {
		}
	`)

	hiddenAPI := result.SingletonForTests("hiddenapi")
	hiddenapiRule := hiddenAPI.Rule("hiddenapi")
	hiddenAPI := result.ModuleForTests("platform-bootclasspath", "android_common")
	hiddenapiRule := hiddenAPI.Rule("platform-bootclasspath-monolithic-hiddenapi-stub-flags")
	fromSourceJarArg := "--boot-dex=out/soong/.intermediates/foo/android_common/aligned/foo.jar"
	android.AssertStringDoesContain(t, "hiddenapi command", hiddenapiRule.RuleParams.Command, fromSourceJarArg)

@@ -125,6 +137,7 @@ func TestHiddenAPISingletonWithPrebuiltOverrideSource(t *testing.T) {
	result := android.GroupFixturePreparers(
		hiddenApiFixtureFactory,
		FixtureConfigureBootJars("platform:foo"),
		prepareForTestWithDefaultPlatformBootclasspath,
	).RunTestWithBp(t, `
		java_library {
			name: "foo",
@@ -140,8 +153,8 @@ func TestHiddenAPISingletonWithPrebuiltOverrideSource(t *testing.T) {
		}
	`)

	hiddenAPI := result.SingletonForTests("hiddenapi")
	hiddenapiRule := hiddenAPI.Rule("hiddenapi")
	hiddenAPI := result.ModuleForTests("platform-bootclasspath", "android_common")
	hiddenapiRule := hiddenAPI.Rule("platform-bootclasspath-monolithic-hiddenapi-stub-flags")
	prebuiltJarArg := "--boot-dex=out/soong/.intermediates/prebuilt_foo/android_common/dex/foo.jar"
	android.AssertStringDoesContain(t, "hiddenapi command", hiddenapiRule.RuleParams.Command, prebuiltJarArg)

@@ -184,13 +197,14 @@ func TestHiddenAPISingletonSdks(t *testing.T) {
			result := android.GroupFixturePreparers(
				hiddenApiFixtureFactory,
				tc.preparer,
				prepareForTestWithDefaultPlatformBootclasspath,
				android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
					variables.Always_use_prebuilt_sdks = proptools.BoolPtr(tc.unbundledBuild)
				}),
			).RunTest(t)

			hiddenAPI := result.SingletonForTests("hiddenapi")
			hiddenapiRule := hiddenAPI.Rule("hiddenapi")
			hiddenAPI := result.ModuleForTests("platform-bootclasspath", "android_common")
			hiddenapiRule := hiddenAPI.Rule("platform-bootclasspath-monolithic-hiddenapi-stub-flags")
			wantPublicStubs := "--public-stub-classpath=" + generateSdkDexPath(tc.publicStub, tc.unbundledBuild)
			android.AssertStringDoesContain(t, "hiddenapi command", hiddenapiRule.RuleParams.Command, wantPublicStubs)

+26 −0
Original line number Diff line number Diff line
@@ -140,6 +140,8 @@ func (b *platformBootclasspathModule) OutputFiles(tag string) (android.Paths, er
}

func (b *platformBootclasspathModule) DepsMutator(ctx android.BottomUpMutatorContext) {
	b.hiddenAPIDepsMutator(ctx)

	if SkipDexpreoptBootJars(ctx) {
		return
	}
@@ -149,6 +151,16 @@ func (b *platformBootclasspathModule) DepsMutator(ctx android.BottomUpMutatorCon
	dexpreopt.RegisterToolDeps(ctx)
}

func (b *platformBootclasspathModule) hiddenAPIDepsMutator(ctx android.BottomUpMutatorContext) {
	if ctx.Config().IsEnvTrue("UNSAFE_DISABLE_HIDDENAPI_FLAGS") {
		return
	}

	// Add dependencies onto the stub lib modules.
	sdkKindToStubLibModules := hiddenAPIComputeMonolithicStubLibModules(ctx.Config())
	hiddenAPIAddStubLibDependencies(ctx, sdkKindToStubLibModules)
}

func platformBootclasspathDepsMutator(ctx android.BottomUpMutatorContext) {
	m := ctx.Module()
	if p, ok := m.(*platformBootclasspathModule); ok {
@@ -353,10 +365,24 @@ func (b *platformBootclasspathModule) generateHiddenAPIBuildActions(ctx android.
	baseFlagsPath := hiddenAPISingletonPaths(ctx).stubFlags
	ruleToGenerateHiddenApiFlags(ctx, outputPath, baseFlagsPath, moduleSpecificFlagsPaths, flagFileInfo)

	b.generateHiddenAPIStubFlagsRules(ctx, hiddenAPISupportingModules)
	b.generateHiddenAPIIndexRules(ctx, hiddenAPISupportingModules)
	b.generatedHiddenAPIMetadataRules(ctx, hiddenAPISupportingModules)
}

func (b *platformBootclasspathModule) generateHiddenAPIStubFlagsRules(ctx android.ModuleContext, modules []hiddenAPISupportingModule) {
	bootDexJars := android.Paths{}
	for _, module := range modules {
		bootDexJars = append(bootDexJars, module.bootDexJar())
	}

	sdkKindToStubPaths := hiddenAPIGatherStubLibDexJarPaths(ctx)

	outputPath := hiddenAPISingletonPaths(ctx).stubFlags
	rule := ruleToGenerateHiddenAPIStubFlagsFile(ctx, outputPath, bootDexJars, sdkKindToStubPaths)
	rule.Build("platform-bootclasspath-monolithic-hiddenapi-stub-flags", "monolithic hidden API stub flags")
}

func (b *platformBootclasspathModule) generateHiddenAPIIndexRules(ctx android.ModuleContext, modules []hiddenAPISupportingModule) {
	indexes := android.Paths{}
	for _, module := range modules {