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

Commit 1352f7c4 authored by Paul Duffin's avatar Paul Duffin
Browse files

Separate input to flag generation from hiddenAPIFlagFileInfo

Encapsulating the information needed by hidden API processing in a
struct makes it easy to add additional information in future and allows
the code to populate that struct from various different sources to be
grouped together.

Bug: 179354495
Test: m com.android.art com.android.ipsec com.android.os.statsd com.android.conscrypt
      - verify that this does not change the contents of the apex files
Change-Id: I53805737dff36a3ae87aca5aad51cf46ae1361fe
parent 1e6f5c4e
Loading
Loading
Loading
Loading
+33 −17
Original line number Diff line number Diff line
@@ -133,8 +133,8 @@ type BootclasspathFragmentModule struct {
type commonBootclasspathFragment interface {
	// produceHiddenAPIAllFlagsFile produces the all-flags.csv and intermediate files.
	//
	// Updates the supplied flagFileInfo with the paths to the generated files set.
	produceHiddenAPIAllFlagsFile(ctx android.ModuleContext, contents []hiddenAPIModule, stubJarsByKind map[android.SdkKind]android.Paths, flagFileInfo *hiddenAPIFlagFileInfo) *HiddenAPIFlagOutput
	// Updates the supplied hiddenAPIInfo with the paths to the generated files set.
	produceHiddenAPIAllFlagsFile(ctx android.ModuleContext, contents []hiddenAPIModule, input HiddenAPIFlagInput) *HiddenAPIFlagOutput
}

var _ commonBootclasspathFragment = (*BootclasspathFragmentModule)(nil)
@@ -538,45 +538,61 @@ func (b *BootclasspathFragmentModule) generateHiddenAPIBuildActions(ctx android.
		return nil
	}

	// Convert the kind specific lists of modules into kind specific lists of jars.
	stubJarsByKind := hiddenAPIGatherStubLibDexJarPaths(ctx, contents)
	// Create hidden API input structure.
	input := b.createHiddenAPIFlagInput(ctx, contents)

	// Performing hidden API processing without stubs is not supported and it is unlikely to ever be
	// required as the whole point of adding something to the bootclasspath fragment is to add it to
	// the bootclasspath in order to be used by something else in the system. Without any stubs it
	// cannot do that.
	if len(stubJarsByKind) == 0 {
	if len(input.StubDexJarsByKind) == 0 {
		return nil
	}

	// Store the information for use by other modules.
	bootclasspathApiInfo := bootclasspathApiInfo{stubJarsByKind: stubJarsByKind}
	bootclasspathApiInfo := bootclasspathApiInfo{stubJarsByKind: input.StubDexJarsByKind}
	ctx.SetProvider(bootclasspathApiInfoProvider, bootclasspathApiInfo)

	// Resolve the properties to paths.
	flagFileInfo := b.properties.Hidden_api.hiddenAPIFlagFileInfo(ctx)

	hiddenAPIModules := gatherHiddenAPIModuleFromContents(ctx, contents)

	// Delegate the production of the hidden API all flags file to a module type specific method.
	common := ctx.Module().(commonBootclasspathFragment)
	output := common.produceHiddenAPIAllFlagsFile(ctx, hiddenAPIModules, stubJarsByKind, &flagFileInfo)
	output := common.produceHiddenAPIAllFlagsFile(ctx, hiddenAPIModules, input)

	// Copy the output into the flagFileInfo
	flagFileInfo.HiddenAPIFlagOutput = *output
	// Initialize a hiddenAPIFlagFileInfo structure and provide it for use by other modules.
	flagFileInfo := hiddenAPIFlagFileInfo{
		// The monolithic hidden API processing needs access to the flag files from all the fragments.
		FlagFilesByCategory: input.FlagFilesByCategory,

	// Store the information for use by platform_bootclasspath.
		// The monolithic hidden API processing also needs access to all the output files produced by
		// hidden API processing of this fragment.
		HiddenAPIFlagOutput: *output,
	}
	ctx.SetProvider(hiddenAPIFlagFileInfoProvider, flagFileInfo)

	return output
}

// createHiddenAPIFlagInput creates a HiddenAPIFlagInput struct and initializes it with information derived
// from the properties on this module and its dependencies.
func (b *BootclasspathFragmentModule) createHiddenAPIFlagInput(ctx android.ModuleContext, contents []android.Module) HiddenAPIFlagInput {
	input := newHiddenAPIFlagInput()

	// Update the input structure with information obtained from the stub libraries.
	input.gatherStubLibInfo(ctx, contents)

	// Populate with flag file paths from the properties.
	input.extractFlagFilesFromProperties(ctx, &b.properties.Hidden_api)

	return input
}

// produceHiddenAPIAllFlagsFile produces the hidden API all-flags.csv file (and supporting files)
// for the fragment.
func (b *BootclasspathFragmentModule) produceHiddenAPIAllFlagsFile(ctx android.ModuleContext, contents []hiddenAPIModule, stubJarsByKind map[android.SdkKind]android.Paths, flagFileInfo *hiddenAPIFlagFileInfo) *HiddenAPIFlagOutput {
	// Generate the rules to create the hidden API flags and update the supplied flagFileInfo with the
func (b *BootclasspathFragmentModule) produceHiddenAPIAllFlagsFile(ctx android.ModuleContext, contents []hiddenAPIModule, input HiddenAPIFlagInput) *HiddenAPIFlagOutput {
	// Generate the rules to create the hidden API flags and update the supplied hiddenAPIInfo with the
	// paths to the created files.
	return hiddenAPIGenerateAllFlagsForBootclasspathFragment(ctx, contents, stubJarsByKind, flagFileInfo)
	return hiddenAPIGenerateAllFlagsForBootclasspathFragment(ctx, contents, input)
}

// generateBootImageBuildActions generates ninja rules to create the boot image if required for this
@@ -800,7 +816,7 @@ func (module *prebuiltBootclasspathFragmentModule) Name() string {

// produceHiddenAPIAllFlagsFile returns a path to the prebuilt all-flags.csv or nil if none is
// specified.
func (module *prebuiltBootclasspathFragmentModule) produceHiddenAPIAllFlagsFile(ctx android.ModuleContext, contents []hiddenAPIModule, stubJarsByKind map[android.SdkKind]android.Paths, flagFileInfo *hiddenAPIFlagFileInfo) *HiddenAPIFlagOutput {
func (module *prebuiltBootclasspathFragmentModule) produceHiddenAPIAllFlagsFile(ctx android.ModuleContext, contents []hiddenAPIModule, _ HiddenAPIFlagInput) *HiddenAPIFlagOutput {
	pathForOptionalSrc := func(src *string) android.Path {
		if src == nil {
			// TODO(b/179354495): Fail if this is not provided once prebuilts have been updated.
+95 −51
Original line number Diff line number Diff line
@@ -127,42 +127,6 @@ func hiddenAPIAddStubLibDependencies(ctx android.BottomUpMutatorContext, sdkKind
	}
}

// hiddenAPIGatherStubLibDexJarPaths gathers the paths to the dex jars from the dependencies added
// in hiddenAPIAddStubLibDependencies.
func hiddenAPIGatherStubLibDexJarPaths(ctx android.ModuleContext, contents []android.Module) map[android.SdkKind]android.Paths {
	m := map[android.SdkKind]android.Paths{}

	// If the contents includes any java_sdk_library modules then add them to the stubs.
	for _, module := range contents {
		if _, ok := module.(SdkLibraryDependency); ok {
			for _, kind := range []android.SdkKind{android.SdkPublic, android.SdkSystem, android.SdkTest} {
				dexJar := hiddenAPIRetrieveDexJarBuildPath(ctx, module, kind)
				if dexJar != nil {
					m[kind] = append(m[kind], dexJar)
				}
			}
		}
	}

	ctx.VisitDirectDepsIf(isActiveModule, func(module android.Module) {
		tag := ctx.OtherModuleDependencyTag(module)
		if hiddenAPIStubsTag, ok := tag.(hiddenAPIStubsDependencyTag); ok {
			kind := hiddenAPIStubsTag.sdkKind
			dexJar := hiddenAPIRetrieveDexJarBuildPath(ctx, module, kind)
			if dexJar != nil {
				m[kind] = append(m[kind], dexJar)
			}
		}
	})

	// Normalize the paths, i.e. remove duplicates and sort.
	for k, v := range m {
		m[k] = android.SortedUniquePaths(v)
	}

	return m
}

// hiddenAPIRetrieveDexJarBuildPath retrieves the DexJarBuildPath from the specified module, if
// available, or reports an error.
func hiddenAPIRetrieveDexJarBuildPath(ctx android.ModuleContext, module android.Module, kind android.SdkKind) android.Path {
@@ -193,7 +157,7 @@ var sdkKindToHiddenapiListOption = map[android.SdkKind]string{
//
// 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.WritablePath, bootDexJars android.Paths, sdkKindToPathList map[android.SdkKind]android.Paths) *android.RuleBuilder {
func ruleToGenerateHiddenAPIStubFlagsFile(ctx android.BuilderContext, outputPath android.WritablePath, bootDexJars android.Paths, input HiddenAPIFlagInput) *android.RuleBuilder {
	// Singleton rule which applies hiddenapi on all boot class path dex files.
	rule := android.NewRuleBuilder(pctx, ctx)

@@ -206,7 +170,7 @@ func ruleToGenerateHiddenAPIStubFlagsFile(ctx android.BuilderContext, outputPath

	// Iterate over the sdk kinds in a fixed order.
	for _, sdkKind := range hiddenAPIRelevantSdkKinds {
		paths := sdkKindToPathList[sdkKind]
		paths := input.StubDexJarsByKind[sdkKind]
		if len(paths) > 0 {
			option := sdkKindToHiddenapiListOption[sdkKind]
			command.FlagWithInputList("--"+option+"=", paths, ":")
@@ -260,15 +224,6 @@ type HiddenAPIFlagFileProperties struct {
	Unsupported_packages []string `android:"path"`
}

func (p *HiddenAPIFlagFileProperties) hiddenAPIFlagFileInfo(ctx android.ModuleContext) hiddenAPIFlagFileInfo {
	info := hiddenAPIFlagFileInfo{FlagFilesByCategory: FlagFilesByCategory{}}
	for _, category := range hiddenAPIFlagFileCategories {
		paths := android.PathsForModuleSrc(ctx, category.propertyValueReader(p))
		info.FlagFilesByCategory[category] = paths
	}
	return info
}

type hiddenAPIFlagFileCategory struct {
	// propertyName is the name of the property for this category.
	propertyName string
@@ -400,6 +355,93 @@ type hiddenAPIFlagFileInfo struct {

var hiddenAPIFlagFileInfoProvider = blueprint.NewProvider(hiddenAPIFlagFileInfo{})

// StubDexJarsByKind maps an android.SdkKind to the paths to stub dex jars appropriate for that
// level. See hiddenAPIRelevantSdkKinds for a list of the acceptable android.SdkKind values.
type StubDexJarsByKind map[android.SdkKind]android.Paths

// append appends the supplied kind specific stub dex jar pargs to the corresponding kind in this
// map.
func (s StubDexJarsByKind) append(other StubDexJarsByKind) {
	for _, kind := range hiddenAPIRelevantSdkKinds {
		s[kind] = append(s[kind], other[kind]...)
	}
}

// dedupAndSort removes duplicates in the stub dex jar paths and sorts them into a consistent and
// deterministic order.
func (s StubDexJarsByKind) dedupAndSort() {
	for kind, paths := range s {
		s[kind] = android.SortedUniquePaths(paths)
	}
}

// HiddenAPIFlagInput encapsulates information obtained from a module and its dependencies that are
// needed for hidden API flag generation.
type HiddenAPIFlagInput struct {
	// FlagFilesByCategory contains the flag files that override the initial flags that are derived
	// from the stub dex files.
	FlagFilesByCategory FlagFilesByCategory

	// StubDexJarsByKind contains the stub dex jars for different android.SdkKind and which determine
	// the initial flags for each dex member.
	StubDexJarsByKind StubDexJarsByKind
}

// newHiddenAPIFlagInput creates a new initialize HiddenAPIFlagInput struct.
func newHiddenAPIFlagInput() HiddenAPIFlagInput {
	input := HiddenAPIFlagInput{
		FlagFilesByCategory: FlagFilesByCategory{},
		StubDexJarsByKind:   StubDexJarsByKind{},
	}

	return input
}

// gatherStubLibInfo gathers information from the stub libs needed by hidden API processing from the
// dependencies added in hiddenAPIAddStubLibDependencies.
//
// That includes paths to the stub dex jars as well as paths to the *removed.txt files.
func (i *HiddenAPIFlagInput) gatherStubLibInfo(ctx android.ModuleContext, contents []android.Module) {
	addFromModule := func(ctx android.ModuleContext, module android.Module, kind android.SdkKind) {
		dexJar := hiddenAPIRetrieveDexJarBuildPath(ctx, module, kind)
		if dexJar != nil {
			i.StubDexJarsByKind[kind] = append(i.StubDexJarsByKind[kind], dexJar)
		}
	}

	// If the contents includes any java_sdk_library modules then add them to the stubs.
	for _, module := range contents {
		if _, ok := module.(SdkLibraryDependency); ok {
			// Add information for every possible kind needed by hidden API. SdkCorePlatform is not used
			// as the java_sdk_library does not have special support for core_platform API, instead it is
			// implemented as a customized form of SdkPublic.
			for _, kind := range []android.SdkKind{android.SdkPublic, android.SdkSystem, android.SdkTest} {
				addFromModule(ctx, module, kind)
			}
		}
	}

	ctx.VisitDirectDepsIf(isActiveModule, func(module android.Module) {
		tag := ctx.OtherModuleDependencyTag(module)
		if hiddenAPIStubsTag, ok := tag.(hiddenAPIStubsDependencyTag); ok {
			kind := hiddenAPIStubsTag.sdkKind
			addFromModule(ctx, module, kind)
		}
	})

	// Normalize the paths, i.e. remove duplicates and sort.
	i.StubDexJarsByKind.dedupAndSort()
}

// extractFlagFilesFromProperties extracts the paths to flag files that are specified in the
// supplied properties and stores them in this struct.
func (i *HiddenAPIFlagInput) extractFlagFilesFromProperties(ctx android.ModuleContext, p *HiddenAPIFlagFileProperties) {
	for _, category := range hiddenAPIFlagFileCategories {
		paths := android.PathsForModuleSrc(ctx, category.propertyValueReader(p))
		i.FlagFilesByCategory[category] = paths
	}
}

// HiddenAPIFlagOutput contains paths to output files from the hidden API flag generation for a
// bootclasspath_fragment module.
type HiddenAPIFlagOutput struct {
@@ -510,13 +552,15 @@ func buildRuleToGenerateHiddenApiFlags(ctx android.BuilderContext, name, desc st
// * metadata.csv
// * index.csv
// * all-flags.csv
func hiddenAPIGenerateAllFlagsForBootclasspathFragment(ctx android.ModuleContext, contents []hiddenAPIModule, stubJarsByKind map[android.SdkKind]android.Paths, flagFileInfo *hiddenAPIFlagFileInfo) *HiddenAPIFlagOutput {
func hiddenAPIGenerateAllFlagsForBootclasspathFragment(ctx android.ModuleContext, contents []hiddenAPIModule, input HiddenAPIFlagInput) *HiddenAPIFlagOutput {
	hiddenApiSubDir := "modular-hiddenapi"

	// Generate the stub-flags.csv.
	// Gather the dex files for the boot libraries provided by this fragment.
	bootDexJars := extractBootDexJarsFromHiddenAPIModules(ctx, contents)

	// Generate the stub-flags.csv.
	stubFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "stub-flags.csv")
	rule := ruleToGenerateHiddenAPIStubFlagsFile(ctx, stubFlagsCSV, bootDexJars, stubJarsByKind)
	rule := ruleToGenerateHiddenAPIStubFlagsFile(ctx, stubFlagsCSV, bootDexJars, input)
	rule.Build("modularHiddenAPIStubFlagsFile", "modular hiddenapi stub flags")

	// Extract the classes jars from the contents.
@@ -544,7 +588,7 @@ func hiddenAPIGenerateAllFlagsForBootclasspathFragment(ctx android.ModuleContext
	// Generate the all-flags.csv which are the flags that will, in future, be encoded into the dex
	// files.
	outputPath := android.PathForModuleOut(ctx, hiddenApiSubDir, "all-flags.csv")
	buildRuleToGenerateHiddenApiFlags(ctx, "modularHiddenApiAllFlags", "modular hiddenapi all flags", outputPath, stubFlagsCSV, annotationFlagsCSV, flagFileInfo.FlagFilesByCategory, nil)
	buildRuleToGenerateHiddenApiFlags(ctx, "modularHiddenApiAllFlags", "modular hiddenapi all flags", outputPath, stubFlagsCSV, annotationFlagsCSV, input.FlagFilesByCategory, nil)

	// Store the paths in the info for use by other modules and sdk snapshot generation.
	output := HiddenAPIFlagOutput{
+20 −4
Original line number Diff line number Diff line
@@ -281,14 +281,22 @@ func (b *platformBootclasspathModule) generateHiddenAPIBuildActions(ctx android.

	monolithicInfo := b.createAndProvideMonolithicHiddenAPIInfo(ctx, fragments)

	sdkKindToStubPaths := hiddenAPIGatherStubLibDexJarPaths(ctx, nil)
	// Create the input to pass to ruleToGenerateHiddenAPIStubFlagsFile
	input := newHiddenAPIFlagInput()

	// Gather stub library information from the dependencies on modules provided by
	// hiddenAPIComputeMonolithicStubLibModules.
	input.gatherStubLibInfo(ctx, nil)

	// Use the flag files from this module and all the fragments.
	input.FlagFilesByCategory = monolithicInfo.FlagsFilesByCategory

	hiddenAPIModules := gatherHiddenAPIModuleFromContents(ctx, modules)

	// Generate the monolithic stub-flags.csv file.
	bootDexJars := extractBootDexJarsFromHiddenAPIModules(ctx, hiddenAPIModules)
	stubFlags := hiddenAPISingletonPaths(ctx).stubFlags
	rule := ruleToGenerateHiddenAPIStubFlagsFile(ctx, stubFlags, bootDexJars, sdkKindToStubPaths)
	rule := ruleToGenerateHiddenAPIStubFlagsFile(ctx, stubFlags, bootDexJars, input)
	rule.Build("platform-bootclasspath-monolithic-hiddenapi-stub-flags", "monolithic hidden API stub flags")

	// Extract the classes jars from the contents.
@@ -322,8 +330,16 @@ func (b *platformBootclasspathModule) generateHiddenAPIBuildActions(ctx android.
// createAndProvideMonolithicHiddenAPIInfo creates a MonolithicHiddenAPIInfo and provides it for
// testing.
func (b *platformBootclasspathModule) createAndProvideMonolithicHiddenAPIInfo(ctx android.ModuleContext, fragments []android.Module) MonolithicHiddenAPIInfo {
	flagFileInfo := b.properties.Hidden_api.hiddenAPIFlagFileInfo(ctx)
	monolithicInfo := newMonolithicHiddenAPIInfo(ctx, flagFileInfo.FlagFilesByCategory, fragments)
	// Create a temporary input structure in which to collate information provided directly by this
	// module, either through properties or direct dependencies.
	temporaryInput := newHiddenAPIFlagInput()

	// Create paths to the flag files specified in the properties.
	temporaryInput.extractFlagFilesFromProperties(ctx, &b.properties.Hidden_api)

	// 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)

	// Store the information for testing.
	ctx.SetProvider(monolithicHiddenAPIInfoProvider, monolithicInfo)