From 70cfdff3da2ea07cd5cb7f7b91474f6fa0c248e5 Mon Sep 17 00:00:00 2001 From: Paul Duffin Date: Sat, 15 May 2021 09:10:42 +0100 Subject: [PATCH] Add temporary restriction on hidden API processing Hidden API processing of a bootclasspath_fragment requires the fragment provides information, such as dependencies on other fragments and flag files to override the default flags. Failing to do so will cause hidden API generation to either fail or to generate different flags to that generated by the hidden API processing done by platform_bootclasspath which will cause the build to fail. Previously, this was handled by only performing hidden API processing for those modules that provide stub libs and relied on there only being bootclasspath_fragments defined for ART (which already supports hidden API processing), and Conscrypt and I18n neither of which provide stubs. Unfortunately, that can no longer be relied upon due to a couple of recent changes: 1. A java_sdk_library in a bootclasspath_fragment's content property is automatically treated a stub library. That avoids duplication for most bootclasspath_fragments that provide the implementation and stub libraries through the same java_sdk_library. It does not affect either ART, conscrypt or i18n as they all define the implementation separately to the stubs. 2. bootclasspath_fragment modules have been defined for a number of android modules as they are needed for reasons other than hidden API processing. In combination this meant that rules to perform hidden API processing were being created but they were not currently being used which is good because they fail. However, adding the fragment to the platform-bootclasspath will cause those rules to be used as the platform_bootclasspath module performs a consistency check on the hidden API flags generated by each of the fragments to ensure that they are consistent with those it generates itself. The dynamic bootclasspath work will need to add fragments to the platform_bootclasspath and without this change that would be blocked until all fragments had been switched to generating hidden API flags properly. This change adds a new fragments property to the bootclasspath and disables hidden API processing for everything other than ART and tests if the fragments property or stub libs is empty. Bug: 179354495 Test: - Before making this change. - Add com.android.os.statds-bootclasspath-fragment to platform-bootclasspath.fragments m out/soong/hiddenapi/hiddenapi-flags.csv - hidden API processing fails in statsd as it cannot find java.lang.Object. - After making this change, run the above command again and it should pass. Change-Id: Ifbb362f8fcfb2c06595fbd5ae39421b536e329ef --- java/bootclasspath_fragment.go | 56 ++++++++++++++++++++++++++++------ 1 file changed, 47 insertions(+), 9 deletions(-) diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go index 16aa5e2ea..b6b877b6f 100644 --- a/java/bootclasspath_fragment.go +++ b/java/bootclasspath_fragment.go @@ -112,6 +112,11 @@ type bootclasspathFragmentProperties struct { Coverage BootclasspathFragmentCoverageAffectedProperties Hidden_api HiddenAPIFlagFileProperties + + // Properties that allow a fragment to depend on other fragments. This is needed for hidden API + // processing as it needs access to all the classes used by a fragment including those provided + // by other fragments. + BootclasspathFragmentsDepsProperties } type BootclasspathFragmentModule struct { @@ -448,12 +453,54 @@ func (b *BootclasspathFragmentModule) getImageConfig(ctx android.EarlyModuleCont return imageConfig } +// canPerformHiddenAPIProcessing determines whether hidden API processing should be performed. +// +// A temporary workaround to avoid existing bootclasspath_fragments that do not provide the +// appropriate information needed for hidden API processing breaking the build. +// TODO(b/179354495): Remove this workaround. +func (b *BootclasspathFragmentModule) canPerformHiddenAPIProcessing(ctx android.ModuleContext) bool { + // Hidden API processing is always enabled in tests. + if ctx.Config().TestProductVariables != nil { + return true + } + // A module that has fragments should have access to the information it needs in order to perform + // hidden API processing. + if len(b.properties.Fragments) != 0 { + return true + } + + // The art bootclasspath fragment does not depend on any other fragments but already supports + // hidden API processing. + imageName := proptools.String(b.properties.Image_name) + if imageName == "art" { + return true + } + + // Disable it for everything else. + return false +} + // generateHiddenAPIBuildActions generates all the hidden API related build rules. func (b *BootclasspathFragmentModule) generateHiddenAPIBuildActions(ctx android.ModuleContext, contents []android.Module) { + // A temporary workaround to avoid existing bootclasspath_fragments that do not provide the + // appropriate information needed for hidden API processing breaking the build. + if !b.canPerformHiddenAPIProcessing(ctx) { + // Nothing to do. + return + } + // Convert the kind specific lists of modules into kind specific lists of jars. stubJarsByKind := hiddenAPIGatherStubLibDexJarPaths(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 { + return + } + // Store the information for use by other modules. bootclasspathApiInfo := bootclasspathApiInfo{stubJarsByKind: stubJarsByKind} ctx.SetProvider(bootclasspathApiInfoProvider, bootclasspathApiInfo) @@ -474,15 +521,6 @@ func (b *BootclasspathFragmentModule) generateHiddenAPIBuildActions(ctx android. // 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) { - // If no stubs have been provided then don't perform hidden API processing. This is a temporary - // workaround to avoid existing bootclasspath_fragments that do not provide stubs breaking the - // build. - // TODO(b/179354495): Remove this workaround. - if len(stubJarsByKind) == 0 { - // Nothing to do. - return - } - // Generate the rules to create the hidden API flags and update the supplied flagFileInfo with the // paths to the created files. hiddenAPIGenerateAllFlagsForBootclasspathFragment(ctx, contents, stubJarsByKind, flagFileInfo)