diff --git a/apex/apex_test.go b/apex/apex_test.go index 03db524b4..8b97467f9 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -6564,6 +6564,7 @@ func testNoUpdatableJarsInBootImage(t *testing.T, errmsg string, preparer androi "com.android.art.debug", ], hostdex: true, + compile_dex: true, } apex { diff --git a/apex/bootclasspath_fragment_test.go b/apex/bootclasspath_fragment_test.go index d77c47d62..1971dcd63 100644 --- a/apex/bootclasspath_fragment_test.go +++ b/apex/bootclasspath_fragment_test.go @@ -82,6 +82,7 @@ func TestBootclasspathFragments(t *testing.T) { "com.android.art", ], srcs: ["b.java"], + compile_dex: true, } java_library { @@ -90,6 +91,7 @@ func TestBootclasspathFragments(t *testing.T) { "com.android.art", ], srcs: ["b.java"], + compile_dex: true, } bootclasspath_fragment { @@ -318,6 +320,7 @@ func TestBootclasspathFragmentInArtApex(t *testing.T) { apex_available: [ "com.android.art", ], + compile_dex: true, } java_import { @@ -326,6 +329,7 @@ func TestBootclasspathFragmentInArtApex(t *testing.T) { apex_available: [ "com.android.art", ], + compile_dex: true, } `), ) @@ -489,7 +493,7 @@ func TestBootclasspathFragmentInPrebuiltArtApex(t *testing.T) { src: "com.android.art-arm.apex", }, }, - exported_java_libs: ["foo", "bar"], + exported_bootclasspath_fragments: ["mybootclasspathfragment"], } java_import { @@ -521,8 +525,7 @@ func TestBootclasspathFragmentInPrebuiltArtApex(t *testing.T) { java.CheckModuleDependencies(t, result.TestContext, "com.android.art", "android_common_com.android.art", []string{ `com.android.art.apex.selector`, - `prebuilt_bar`, - `prebuilt_foo`, + `prebuilt_mybootclasspathfragment`, }) java.CheckModuleDependencies(t, result.TestContext, "mybootclasspathfragment", "android_common", []string{ diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go index a6f65050e..3ceffd2f9 100644 --- a/java/bootclasspath_fragment.go +++ b/java/bootclasspath_fragment.go @@ -137,10 +137,13 @@ type BootclasspathFragmentModule struct { // commonBootclasspathFragment defines the methods that are implemented by both source and prebuilt // bootclasspath fragment modules. type commonBootclasspathFragment interface { - // produceHiddenAPIAllFlagsFile produces the all-flags.csv and intermediate files. + // produceHiddenAPIOutput produces the all-flags.csv and intermediate files and encodes the flags + // into dex files. // - // Updates the supplied hiddenAPIInfo with the paths to the generated files set. - produceHiddenAPIAllFlagsFile(ctx android.ModuleContext, contents []android.Module, input HiddenAPIFlagInput) *HiddenAPIFlagOutput + // 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 } var _ commonBootclasspathFragment = (*BootclasspathFragmentModule)(nil) @@ -292,9 +295,9 @@ type BootclasspathFragmentApexContentInfo struct { // Map from arch type to the boot image files. bootImageFilesByArch map[android.ArchType]android.OutputPaths - // Map from the name of the context module (as returned by Name()) to the hidden API encoded dex - // jar path. - contentModuleDexJarPaths map[string]android.Path + // Map from the base module name (without prebuilt_ prefix) of a fragment's contents module to the + // hidden API encoded dex jar path. + contentModuleDexJarPaths bootDexJarByModule } func (i BootclasspathFragmentApexContentInfo) Modules() android.ConfiguredJarList { @@ -312,6 +315,8 @@ func (i BootclasspathFragmentApexContentInfo) AndroidBootImageFilesByArchType() // // The dex boot jar is one which has had hidden API encoding performed on it. func (i BootclasspathFragmentApexContentInfo) DexBootJarPathForContentModule(module android.Module) (android.Path, error) { + // A bootclasspath_fragment cannot use a prebuilt library so Name() will return the base name + // without a prebuilt_ prefix so is safe to use as the key for the contentModuleDexJarPaths. name := module.Name() if dexJar, ok := i.contentModuleDexJarPaths[name]; ok { return dexJar, nil @@ -400,28 +405,34 @@ func (b *BootclasspathFragmentModule) GenerateAndroidBuildActions(ctx android.Mo fragments := gatherApexModulePairDepsWithTag(ctx, bootclasspathFragmentDepTag) - // Perform hidden API processing. - hiddenAPIFlagOutput := b.generateHiddenAPIBuildActions(ctx, contents, fragments) - // Verify that the image_name specified on a bootclasspath_fragment is valid even if this is a // prebuilt which will not use the image config. imageConfig := b.getImageConfig(ctx) - // A prebuilt fragment cannot contribute to the apex. - if !android.IsModulePrebuilt(ctx.Module()) { - // Provide the apex content info. - b.provideApexContentInfo(ctx, imageConfig, contents, hiddenAPIFlagOutput) + // A versioned prebuilt_bootclasspath_fragment cannot and does not need to perform hidden API + // processing. It cannot do it because it is not part of a prebuilt_apex and so has no access to + // the correct dex implementation jar. It does not need to because the platform-bootclasspath + // always references the latest bootclasspath_fragments. + if !android.IsModuleInVersionedSdk(ctx.Module()) { + // Perform hidden API processing. + hiddenAPIOutput := b.generateHiddenAPIBuildActions(ctx, contents, fragments) + + // A prebuilt fragment cannot contribute to an apex. + if !android.IsModulePrebuilt(ctx.Module()) { + // Provide the apex content info. + b.provideApexContentInfo(ctx, imageConfig, contents, hiddenAPIOutput) + } } } // provideApexContentInfo creates, initializes and stores the apex content info for use by other // modules. -func (b *BootclasspathFragmentModule) provideApexContentInfo(ctx android.ModuleContext, imageConfig *bootImageConfig, contents []android.Module, hiddenAPIFlagOutput *HiddenAPIFlagOutput) { +func (b *BootclasspathFragmentModule) provideApexContentInfo(ctx android.ModuleContext, imageConfig *bootImageConfig, contents []android.Module, hiddenAPIOutput *HiddenAPIOutput) { // Construct the apex content info from the config. - info := BootclasspathFragmentApexContentInfo{} - - // Populate the apex content info with paths to the dex jars. - b.populateApexContentInfoDexJars(ctx, &info, contents, hiddenAPIFlagOutput) + info := BootclasspathFragmentApexContentInfo{ + // Populate the apex content info with paths to the dex jars. + contentModuleDexJarPaths: hiddenAPIOutput.EncodedBootDexFilesByModule, + } if imageConfig != nil { info.modules = imageConfig.modules @@ -451,38 +462,6 @@ func (b *BootclasspathFragmentModule) provideApexContentInfo(ctx android.ModuleC ctx.SetProvider(BootclasspathFragmentApexContentInfoProvider, info) } -// populateApexContentInfoDexJars adds paths to the dex jars provided by this fragment to the -// apex content info. -func (b *BootclasspathFragmentModule) populateApexContentInfoDexJars(ctx android.ModuleContext, info *BootclasspathFragmentApexContentInfo, contents []android.Module, hiddenAPIFlagOutput *HiddenAPIFlagOutput) { - - info.contentModuleDexJarPaths = map[string]android.Path{} - if hiddenAPIFlagOutput != nil { - // Hidden API encoding has been performed. - flags := hiddenAPIFlagOutput.AllFlagsPath - for _, m := range contents { - h := m.(hiddenAPIModule) - unencodedDex := h.bootDexJar() - if unencodedDex == nil { - // This is an error. Sometimes Soong will report the error directly, other times it will - // defer the error reporting to happen only when trying to use the missing file in ninja. - // Either way it is handled by extractBootDexJarsFromModules which must have been - // called before this as it generates the flags that are used to encode these files. - continue - } - - outputDir := android.PathForModuleOut(ctx, "hiddenapi-modular/encoded").OutputPath - encodedDex := hiddenAPIEncodeDex(ctx, unencodedDex, flags, *h.uncompressDex(), outputDir) - info.contentModuleDexJarPaths[m.Name()] = encodedDex - } - } else { - for _, m := range contents { - j := m.(UsesLibraryDependency) - dexJar := j.DexJarBuildPath() - info.contentModuleDexJarPaths[m.Name()] = dexJar - } - } -} - // generateClasspathProtoBuildActions generates all required build actions for classpath.proto config func (b *BootclasspathFragmentModule) generateClasspathProtoBuildActions(ctx android.ModuleContext) { var classpathJars []classpathJar @@ -548,12 +527,12 @@ func (b *BootclasspathFragmentModule) getImageConfig(ctx android.EarlyModuleCont } // generateHiddenAPIBuildActions generates all the hidden API related build rules. -func (b *BootclasspathFragmentModule) generateHiddenAPIBuildActions(ctx android.ModuleContext, contents []android.Module, fragments []android.Module) *HiddenAPIFlagOutput { +func (b *BootclasspathFragmentModule) generateHiddenAPIBuildActions(ctx android.ModuleContext, contents []android.Module, fragments []android.Module) *HiddenAPIOutput { // Create hidden API input structure. input := b.createHiddenAPIFlagInput(ctx, contents, fragments) - var output *HiddenAPIFlagOutput + var output *HiddenAPIOutput // Hidden API processing is conditional as a temporary workaround as not all // bootclasspath_fragments provide the appropriate information needed for hidden API processing @@ -563,7 +542,14 @@ func (b *BootclasspathFragmentModule) generateHiddenAPIBuildActions(ctx android. if input.canPerformHiddenAPIProcessing(ctx, b.properties) { // Delegate the production of the hidden API all-flags.csv file to a module type specific method. common := ctx.Module().(commonBootclasspathFragment) - output = common.produceHiddenAPIAllFlagsFile(ctx, contents, input) + output = common.produceHiddenAPIOutput(ctx, contents, input) + } else { + // As hidden API processing cannot be performed fall back to trying to retrieve the legacy + // encoded boot dex files, i.e. those files encoded by the individual libraries and returned + // from the DexJarBuildPath() method. + output = &HiddenAPIOutput{ + EncodedBootDexFilesByModule: retrieveLegacyEncodedBootDexFiles(ctx, contents), + } } // Initialize a HiddenAPIInfo structure. @@ -580,11 +566,9 @@ func (b *BootclasspathFragmentModule) generateHiddenAPIBuildActions(ctx android. TransitiveStubDexJarsByKind: input.transitiveStubDexJarsByKind(), } - if output != nil { - // The monolithic hidden API processing also needs access to all the output files produced by - // hidden API processing of this fragment. - hiddenAPIInfo.HiddenAPIFlagOutput = *output - } + // The monolithic hidden API processing also needs access to all the output files produced by + // hidden API processing of this fragment. + hiddenAPIInfo.HiddenAPIFlagOutput = (*output).HiddenAPIFlagOutput // Provide it for use by other modules. ctx.SetProvider(HiddenAPIInfoProvider, hiddenAPIInfo) @@ -592,6 +576,21 @@ func (b *BootclasspathFragmentModule) generateHiddenAPIBuildActions(ctx android. return output } +// retrieveLegacyEncodedBootDexFiles attempts to retrieve the legacy encoded boot dex jar files. +func retrieveLegacyEncodedBootDexFiles(ctx android.ModuleContext, contents []android.Module) bootDexJarByModule { + // If the current bootclasspath_fragment is the active module or a source module then retrieve the + // encoded dex files, otherwise return an empty map. + // + // An inactive (i.e. not preferred) bootclasspath_fragment needs to retrieve the encoded dex jars + // as they are still needed by an apex. An inactive prebuilt_bootclasspath_fragment does not need + // to do so and may not yet have access to dex boot jars from a prebuilt_apex/apex_set. + if isActiveModule(ctx.Module()) || !android.IsModulePrebuilt(ctx.Module()) { + return extractEncodedDexJarsFromModules(ctx, contents) + } else { + return nil + } +} + // 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, fragments []android.Module) HiddenAPIFlagInput { @@ -615,12 +614,12 @@ func (b *BootclasspathFragmentModule) createHiddenAPIFlagInput(ctx android.Modul 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 []android.Module, input HiddenAPIFlagInput) *HiddenAPIFlagOutput { +// 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 { // 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, input) + return hiddenAPIRulesForBootclasspathFragment(ctx, contents, input) } // generateBootImageBuildActions generates ninja rules to create the boot image if required for this @@ -836,9 +835,8 @@ func (module *prebuiltBootclasspathFragmentModule) Name() string { return module.prebuilt.Name(module.ModuleBase.Name()) } -// produceHiddenAPIAllFlagsFile returns a path to the prebuilt all-flags.csv or nil if none is -// specified. -func (module *prebuiltBootclasspathFragmentModule) produceHiddenAPIAllFlagsFile(ctx android.ModuleContext, contents []android.Module, _ HiddenAPIFlagInput) *HiddenAPIFlagOutput { +// 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 { pathForOptionalSrc := func(src *string) android.Path { if src == nil { // TODO(b/179354495): Fail if this is not provided once prebuilts have been updated. @@ -847,12 +845,19 @@ func (module *prebuiltBootclasspathFragmentModule) produceHiddenAPIAllFlagsFile( return android.PathForModuleSrc(ctx, *src) } - output := HiddenAPIFlagOutput{ - StubFlagsPath: pathForOptionalSrc(module.prebuiltProperties.Hidden_api.Stub_flags), - AnnotationFlagsPath: pathForOptionalSrc(module.prebuiltProperties.Hidden_api.Annotation_flags), - MetadataPath: pathForOptionalSrc(module.prebuiltProperties.Hidden_api.Metadata), - IndexPath: pathForOptionalSrc(module.prebuiltProperties.Hidden_api.Index), - AllFlagsPath: pathForOptionalSrc(module.prebuiltProperties.Hidden_api.All_flags), + // Retrieve the dex files directly from the content modules. They in turn should retrieve the + // encoded dex jars from the prebuilt .apex files. + encodedBootDexJarsByModule := extractEncodedDexJarsFromModules(ctx, contents) + + output := HiddenAPIOutput{ + HiddenAPIFlagOutput: HiddenAPIFlagOutput{ + StubFlagsPath: pathForOptionalSrc(module.prebuiltProperties.Hidden_api.Stub_flags), + AnnotationFlagsPath: pathForOptionalSrc(module.prebuiltProperties.Hidden_api.Annotation_flags), + MetadataPath: pathForOptionalSrc(module.prebuiltProperties.Hidden_api.Metadata), + IndexPath: pathForOptionalSrc(module.prebuiltProperties.Hidden_api.Index), + AllFlagsPath: pathForOptionalSrc(module.prebuiltProperties.Hidden_api.All_flags), + }, + EncodedBootDexFilesByModule: encodedBootDexJarsByModule, } return &output diff --git a/java/hiddenapi_modular.go b/java/hiddenapi_modular.go index 643c5cba2..60300afe1 100644 --- a/java/hiddenapi_modular.go +++ b/java/hiddenapi_modular.go @@ -580,6 +580,23 @@ func (b bootDexJarByModule) addPath(module android.Module, path android.Path) { b[android.RemoveOptionalPrebuiltPrefix(module.Name())] = path } +// bootDexJars returns the boot dex jar paths sorted by their keys. +func (b bootDexJarByModule) bootDexJars() android.Paths { + paths := android.Paths{} + for _, k := range android.SortedStringKeys(b) { + paths = append(paths, b[k]) + } + return paths +} + +// HiddenAPIOutput encapsulates the output from the hidden API processing. +type HiddenAPIOutput struct { + HiddenAPIFlagOutput + + // The map from base module name to the path to the encoded boot dex file. + EncodedBootDexFilesByModule bootDexJarByModule +} + // pathForValidation creates a path of the same type as the supplied type but with a name of // .valid. // @@ -665,8 +682,8 @@ func buildRuleToGenerateHiddenApiFlags(ctx android.BuilderContext, name, desc st rule.Build(name, desc) } -// hiddenAPIGenerateAllFlagsForBootclasspathFragment will generate all the flags for a fragment -// of the bootclasspath. +// hiddenAPIRulesForBootclasspathFragment will generate all the flags for a fragment of the +// bootclasspath and then encode the flags into the boot dex files. // // It takes: // * Map from android.SdkKind to stub dex jar paths defining the API for that sdk kind. @@ -679,15 +696,16 @@ func buildRuleToGenerateHiddenApiFlags(ctx android.BuilderContext, name, desc st // * metadata.csv // * index.csv // * all-flags.csv -func hiddenAPIGenerateAllFlagsForBootclasspathFragment(ctx android.ModuleContext, contents []android.Module, input HiddenAPIFlagInput) *HiddenAPIFlagOutput { +// * encoded boot dex files +func hiddenAPIRulesForBootclasspathFragment(ctx android.ModuleContext, contents []android.Module, input HiddenAPIFlagInput) *HiddenAPIOutput { hiddenApiSubDir := "modular-hiddenapi" - // Gather the dex files for the boot libraries provided by this fragment. - bootDexJars := extractBootDexJarsFromModules(ctx, contents) + // Gather information about the boot dex files for the boot libraries provided by this fragment. + bootDexInfoByModule := extractBootDexInfoFromModules(ctx, contents) // Generate the stub-flags.csv. stubFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "stub-flags.csv") - rule := ruleToGenerateHiddenAPIStubFlagsFile(ctx, stubFlagsCSV, bootDexJars, input) + rule := ruleToGenerateHiddenAPIStubFlagsFile(ctx, stubFlagsCSV, bootDexInfoByModule.bootDexJars(), input) rule.Build("modularHiddenAPIStubFlagsFile", "modular hiddenapi stub flags") // Extract the classes jars from the contents. @@ -715,16 +733,29 @@ 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, input.FlagFilesByCategory, nil, removedDexSignatures) + allFlagsCSV := android.PathForModuleOut(ctx, hiddenApiSubDir, "all-flags.csv") + buildRuleToGenerateHiddenApiFlags(ctx, "modularHiddenApiAllFlags", "modular hiddenapi all flags", allFlagsCSV, stubFlagsCSV, annotationFlagsCSV, input.FlagFilesByCategory, nil, removedDexSignatures) + + // Encode the flags into the boot dex files. + encodedBootDexJarsByModule := map[string]android.Path{} + outputDir := android.PathForModuleOut(ctx, "hiddenapi-modular/encoded").OutputPath + for _, name := range android.SortedStringKeys(bootDexInfoByModule) { + bootDexInfo := bootDexInfoByModule[name] + unencodedDex := bootDexInfo.path + encodedDex := hiddenAPIEncodeDex(ctx, unencodedDex, allFlagsCSV, bootDexInfo.uncompressDex, outputDir) + encodedBootDexJarsByModule[name] = encodedDex + } // Store the paths in the info for use by other modules and sdk snapshot generation. - output := HiddenAPIFlagOutput{ - StubFlagsPath: stubFlagsCSV, - AnnotationFlagsPath: annotationFlagsCSV, - MetadataPath: metadataCSV, - IndexPath: indexCSV, - AllFlagsPath: outputPath, + output := HiddenAPIOutput{ + HiddenAPIFlagOutput: HiddenAPIFlagOutput{ + StubFlagsPath: stubFlagsCSV, + AnnotationFlagsPath: annotationFlagsCSV, + MetadataPath: metadataCSV, + IndexPath: indexCSV, + AllFlagsPath: allFlagsCSV, + }, + EncodedBootDexFilesByModule: encodedBootDexJarsByModule, } return &output } @@ -747,37 +778,15 @@ func buildRuleToGenerateRemovedDexSignatures(ctx android.ModuleContext, removedT } // extractBootDexJarsFromModules extracts the boot dex jars from the supplied modules. -func extractBootDexJarsFromModules(ctx android.ModuleContext, contents []android.Module) android.Paths { - bootDexJars := android.Paths{} +func extractBootDexJarsFromModules(ctx android.ModuleContext, contents []android.Module) bootDexJarByModule { + bootDexJars := bootDexJarByModule{} for _, module := range contents { hiddenAPIModule := hiddenAPIModuleFromModule(ctx, module) if hiddenAPIModule == nil { continue } - bootDexJar := hiddenAPIModule.bootDexJar() - if bootDexJar == nil { - if ctx.Config().AlwaysUsePrebuiltSdks() { - // TODO(b/179354495): Remove this workaround when it is unnecessary. - // Prebuilt modules like framework-wifi do not yet provide dex implementation jars. So, - // create a fake one that will cause a build error only if it is used. - fake := android.PathForModuleOut(ctx, "fake/boot-dex/%s.jar", module.Name()) - - // Create an error rule that pretends to create the output file but will actually fail if it - // is run. - ctx.Build(pctx, android.BuildParams{ - Rule: android.ErrorRule, - Output: fake, - Args: map[string]string{ - "error": fmt.Sprintf("missing dependencies: boot dex jar for %s", module), - }, - }) - bootDexJars = append(bootDexJars, fake) - } else { - ctx.ModuleErrorf("module %s does not provide a dex jar", module) - } - } else { - bootDexJars = append(bootDexJars, bootDexJar) - } + bootDexJar := retrieveBootDexJarFromHiddenAPIModule(ctx, hiddenAPIModule) + bootDexJars.addPath(module, bootDexJar) } return bootDexJars } @@ -794,6 +803,60 @@ func hiddenAPIModuleFromModule(ctx android.BaseModuleContext, module android.Mod return nil } +// bootDexInfo encapsulates both the path and uncompressDex status retrieved from a hiddenAPIModule. +type bootDexInfo struct { + // The path to the dex jar that has not had hidden API flags encoded into it. + path android.Path + + // Indicates whether the dex jar needs uncompressing before encoding. + uncompressDex bool +} + +// bootDexInfoByModule is a map from module name (as returned by module.Name()) to the boot dex +// path (as returned by hiddenAPIModule.bootDexJar()) and the uncompressDex flag. +type bootDexInfoByModule map[string]bootDexInfo + +// bootDexJars returns the boot dex jar paths sorted by their keys. +func (b bootDexInfoByModule) bootDexJars() android.Paths { + paths := android.Paths{} + for _, m := range android.SortedStringKeys(b) { + paths = append(paths, b[m].path) + } + return paths +} + +// extractBootDexInfoFromModules extracts the boot dex jar and uncompress dex state from +// each of the supplied modules which must implement hiddenAPIModule. +func extractBootDexInfoFromModules(ctx android.ModuleContext, contents []android.Module) bootDexInfoByModule { + bootDexJarsByModule := bootDexInfoByModule{} + for _, module := range contents { + hiddenAPIModule := module.(hiddenAPIModule) + bootDexJar := retrieveBootDexJarFromHiddenAPIModule(ctx, hiddenAPIModule) + bootDexJarsByModule[module.Name()] = bootDexInfo{ + path: bootDexJar, + uncompressDex: *hiddenAPIModule.uncompressDex(), + } + } + + return bootDexJarsByModule +} + +// retrieveBootDexJarFromHiddenAPIModule retrieves the boot dex jar from the hiddenAPIModule. +// +// If the module does not provide a boot dex jar, i.e. the returned boot dex jar is nil, then that +// create a fake path and either report an error immediately or defer reporting of the error until +// the path is actually used. +func retrieveBootDexJarFromHiddenAPIModule(ctx android.ModuleContext, module hiddenAPIModule) android.Path { + bootDexJar := module.bootDexJar() + if bootDexJar == nil { + fake := android.PathForModuleOut(ctx, fmt.Sprintf("fake/boot-dex/%s.jar", module.Name())) + bootDexJar = fake + + handleMissingDexBootFile(ctx, module, fake) + } + return bootDexJar +} + // extractClassesJarsFromModules extracts the class jars from the supplied modules. func extractClassesJarsFromModules(contents []android.Module) android.Paths { classesJars := android.Paths{} @@ -822,6 +885,11 @@ func deferReportingMissingBootDexJar(ctx android.ModuleContext, module android.M return true } + // Any missing dependency should be allowed. + if ctx.Config().AllowMissingDependencies() { + return true + } + // This is called for both platform_bootclasspath and bootclasspath_fragment modules. // // A bootclasspath_fragment module should only use the APEX variant of source or prebuilt modules. diff --git a/java/platform_bootclasspath.go b/java/platform_bootclasspath.go index 1a4f9b7ec..1ba463ce9 100644 --- a/java/platform_bootclasspath.go +++ b/java/platform_bootclasspath.go @@ -291,9 +291,9 @@ func (b *platformBootclasspathModule) generateHiddenAPIBuildActions(ctx android. input.FlagFilesByCategory = monolithicInfo.FlagsFilesByCategory // Generate the monolithic stub-flags.csv file. - bootDexJars := extractBootDexJarsFromModules(ctx, modules) + bootDexJarByModule := extractBootDexJarsFromModules(ctx, modules) stubFlags := hiddenAPISingletonPaths(ctx).stubFlags - rule := ruleToGenerateHiddenAPIStubFlagsFile(ctx, stubFlags, bootDexJars, input) + 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.