diff options
Diffstat (limited to 'apex/prebuilt.go')
| -rw-r--r-- | apex/prebuilt.go | 269 |
1 files changed, 182 insertions, 87 deletions
diff --git a/apex/prebuilt.go b/apex/prebuilt.go index 0d83830f1..65c23d34b 100644 --- a/apex/prebuilt.go +++ b/apex/prebuilt.go @@ -22,6 +22,7 @@ import ( "strings" "android/soong/android" + "android/soong/dexpreopt" "android/soong/java" "android/soong/provenance" @@ -50,6 +51,7 @@ type prebuilt interface { type prebuiltCommon struct { android.ModuleBase + java.Dexpreopter prebuilt android.Prebuilt // Properties common to both prebuilt_apex and apex_set. @@ -60,6 +62,9 @@ type prebuiltCommon struct { installedFile android.InstallPath outputApex android.WritablePath + // fragment for this apex for apexkeys.txt + apexKeysPath android.WritablePath + // A list of apexFile objects created in prebuiltCommon.initApexFilesForAndroidMk which are used // to create make modules in prebuiltCommon.AndroidMkEntries. apexFilesForAndroidMk []apexFile @@ -82,6 +87,12 @@ type PrebuiltCommonProperties struct { // device (/apex/<apex_name>). If unspecified, follows the name property. Apex_name *string + // Name of the source APEX that gets shadowed by this prebuilt + // e.g. com.mycompany.android.myapex + // If unspecified, follows the naming convention that the source apex of + // the prebuilt is Name() without "prebuilt_" prefix + Source_apex_name *string + ForceDisable bool `blueprint:"mutated"` // whether the extracted apex file is installable. @@ -110,6 +121,11 @@ type PrebuiltCommonProperties struct { // List of systemserverclasspath fragments inside this prebuilt APEX bundle and for which this // APEX bundle will create an APEX variant. Exported_systemserverclasspath_fragments []string + + // Path to the .prebuilt_info file of the prebuilt apex. + // In case of mainline modules, the .prebuilt_info file contains the build_id that was used to + // generate the prebuilt. + Prebuilt_info *string `android:"path"` } // initPrebuiltCommon initializes the prebuiltCommon structure and performs initialization of the @@ -121,7 +137,11 @@ func (p *prebuiltCommon) initPrebuiltCommon(module android.Module, properties *P } func (p *prebuiltCommon) ApexVariationName() string { - return proptools.StringDefault(p.prebuiltCommonProperties.Apex_name, p.ModuleBase.BaseModuleName()) + return proptools.StringDefault(p.prebuiltCommonProperties.Apex_name, p.BaseModuleName()) +} + +func (p *prebuiltCommon) BaseModuleName() string { + return proptools.StringDefault(p.prebuiltCommonProperties.Source_apex_name, p.ModuleBase.BaseModuleName()) } func (p *prebuiltCommon) Prebuilt() *android.Prebuilt { @@ -133,9 +153,7 @@ func (p *prebuiltCommon) isForceDisabled() bool { } func (p *prebuiltCommon) checkForceDisable(ctx android.ModuleContext) bool { - // If the device is configured to use flattened APEX, force disable the prebuilt because - // the prebuilt is a non-flattened one. - forceDisable := ctx.Config().FlattenApex() + forceDisable := false // Force disable the prebuilts when we are doing unbundled build. We do unbundled build // to build the prebuilts themselves. @@ -169,50 +187,47 @@ func (p *prebuiltCommon) installable() bool { return proptools.BoolDefault(p.prebuiltCommonProperties.Installable, true) } -// initApexFilesForAndroidMk initializes the prebuiltCommon.apexFilesForAndroidMk field from the -// modules that this depends upon. +// To satisfy java.DexpreopterInterface +func (p *prebuiltCommon) IsInstallable() bool { + return p.installable() +} + +// initApexFilesForAndroidMk initializes the prebuiltCommon.requiredModuleNames field with the install only deps of the prebuilt apex func (p *prebuiltCommon) initApexFilesForAndroidMk(ctx android.ModuleContext) { - // Walk the dependencies of this module looking for the java modules that it exports. - ctx.WalkDeps(func(child, parent android.Module) bool { - tag := ctx.OtherModuleDependencyTag(child) + // If this apex contains a system server jar, then the dexpreopt artifacts should be added as required + for _, install := range p.Dexpreopter.DexpreoptBuiltInstalledForApex() { + p.requiredModuleNames = append(p.requiredModuleNames, install.FullModuleName()) + install.PackageFile(ctx) + } +} - name := android.RemoveOptionalPrebuiltPrefix(ctx.OtherModuleName(child)) - if java.IsBootclasspathFragmentContentDepTag(tag) || - java.IsSystemServerClasspathFragmentContentDepTag(tag) || tag == exportedJavaLibTag { - // If the exported java module provides a dex jar path then add it to the list of apexFiles. - path := child.(interface { - DexJarBuildPath() java.OptionalDexJarPath - }).DexJarBuildPath() - if path.IsSet() { - af := apexFile{ - module: child, - moduleDir: ctx.OtherModuleDir(child), - androidMkModuleName: name, - builtFile: path.Path(), - class: javaSharedLib, - } - if module, ok := child.(java.DexpreopterInterface); ok { - for _, install := range module.DexpreoptBuiltInstalledForApex() { - af.requiredModuleNames = append(af.requiredModuleNames, install.FullModuleName()) - } - } - p.apexFilesForAndroidMk = append(p.apexFilesForAndroidMk, af) - } - } else if tag == exportedBootclasspathFragmentTag { - _, ok := child.(*java.PrebuiltBootclasspathFragmentModule) - if !ok { - ctx.PropertyErrorf("exported_bootclasspath_fragments", "%q is not a prebuilt_bootclasspath_fragment module", name) - return false - } - // Visit the children of the bootclasspath_fragment. - return true - } else if tag == exportedSystemserverclasspathFragmentTag { - // Visit the children of the systemserver_fragment. - return true +// If this prebuilt has system server jar, create the rules to dexpreopt it and install it alongside the prebuilt apex +func (p *prebuiltCommon) dexpreoptSystemServerJars(ctx android.ModuleContext) { + // If this apex does not export anything, return + if !p.hasExportedDeps() { + return + } + // If this prebuilt apex has not been selected, return + if p.IsHideFromMake() { + return + } + // Use apex_name to determine the api domain of this prebuilt apex + apexName := p.ApexVariationName() + di, err := android.FindDeapexerProviderForModule(ctx) + if err != nil { + ctx.ModuleErrorf(err.Error()) + } + dc := dexpreopt.GetGlobalConfig(ctx) + systemServerJarList := dc.AllApexSystemServerJars(ctx) + + for i := 0; i < systemServerJarList.Len(); i++ { + sscpApex := systemServerJarList.Apex(i) + sscpJar := systemServerJarList.Jar(i) + if apexName != sscpApex { + continue } - - return false - }) + p.Dexpreopter.DexpreoptPrebuiltApexSystemServerJars(ctx, sscpJar, di) + } } func (p *prebuiltCommon) addRequiredModules(entries *android.AndroidMkEntries) { @@ -231,20 +246,28 @@ func (p *prebuiltCommon) AndroidMkEntries() []android.AndroidMkEntries { OutputFile: android.OptionalPathForPath(p.outputApex), Include: "$(BUILD_PREBUILT)", Host_required: p.hostRequired, + OverrideName: p.BaseModuleName(), ExtraEntries: []android.AndroidMkExtraEntriesFunc{ func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) { entries.SetString("LOCAL_MODULE_PATH", p.installDir.String()) entries.SetString("LOCAL_MODULE_STEM", p.installFilename) entries.SetPath("LOCAL_SOONG_INSTALLED_MODULE", p.installedFile) entries.SetString("LOCAL_SOONG_INSTALL_PAIRS", p.outputApex.String()+":"+p.installedFile.String()) + entries.AddStrings("LOCAL_SOONG_INSTALL_SYMLINKS", p.compatSymlinks.Strings()...) entries.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", !p.installable()) entries.AddStrings("LOCAL_OVERRIDES_MODULES", p.prebuiltCommonProperties.Overrides...) + entries.SetString("LOCAL_APEX_KEY_PATH", p.apexKeysPath.String()) p.addRequiredModules(entries) }, }, }, } + // Add the dexpreopt artifacts to androidmk + for _, install := range p.Dexpreopter.DexpreoptBuiltInstalledForApex() { + entriesList = append(entriesList, install.ToMakeEntries()) + } + // Iterate over the apexFilesForAndroidMk list and create an AndroidMkEntries struct for each // file. This provides similar behavior to that provided in apexBundle.AndroidMk() as it makes the // apex specific variants of the exported java modules available for use from within make. @@ -425,7 +448,7 @@ func (p *prebuiltCommon) apexInfoMutator(mctx android.TopDownMutatorContext) { // Create contents for the prebuilt_apex and store it away for later use. apexContents := android.NewApexContents(contents) - mctx.SetProvider(ApexBundleInfoProvider, ApexBundleInfo{ + android.SetProvider(mctx, android.ApexBundleInfoProvider, android.ApexBundleInfo{ Contents: apexContents, }) @@ -434,7 +457,7 @@ func (p *prebuiltCommon) apexInfoMutator(mctx android.TopDownMutatorContext) { apexInfo := android.ApexInfo{ ApexVariationName: apexVariationName, InApexVariants: []string{apexVariationName}, - InApexModules: []string{p.ModuleBase.BaseModuleName()}, // BaseModuleName() to avoid the prebuilt_ prefix. + InApexModules: []string{p.BaseModuleName()}, // BaseModuleName() to avoid the prebuilt_ prefix. ApexContents: []*android.ApexContents{apexContents}, ForPrebuiltApex: true, } @@ -565,15 +588,6 @@ func (a *Prebuilt) hasSanitizedSource(sanitizer string) bool { return false } -func (p *Prebuilt) OutputFiles(tag string) (android.Paths, error) { - switch tag { - case "": - return android.Paths{p.outputApex}, nil - default: - return nil, fmt.Errorf("unsupported module reference tag %q", tag) - } -} - // prebuilt_apex imports an `.apex` file into the build graph as if it was built with apex. func PrebuiltFactory() android.Module { module := &Prebuilt{} @@ -609,6 +623,7 @@ func (p *prebuiltCommon) createDeapexerModuleIfNeeded(ctx android.TopDownMutator // Compute the deapexer properties from the transitive dependencies of this module. commonModules := []string{} + dexpreoptProfileGuidedModules := []string{} exportedFiles := []string{} ctx.WalkDeps(func(child, parent android.Module) bool { tag := ctx.OtherModuleDependencyTag(child) @@ -618,13 +633,18 @@ func (p *prebuiltCommon) createDeapexerModuleIfNeeded(ctx android.TopDownMutator return false } - name := android.RemoveOptionalPrebuiltPrefix(ctx.OtherModuleName(child)) + name := java.ModuleStemForDeapexing(child) if _, ok := tag.(android.RequiresFilesFromPrebuiltApexTag); ok { commonModules = append(commonModules, name) - requiredFiles := child.(android.RequiredFilesFromPrebuiltApex).RequiredFilesFromPrebuiltApex(ctx) + extract := child.(android.RequiredFilesFromPrebuiltApex) + requiredFiles := extract.RequiredFilesFromPrebuiltApex(ctx) exportedFiles = append(exportedFiles, requiredFiles...) + if extract.UseProfileGuidedDexpreopt() { + dexpreoptProfileGuidedModules = append(dexpreoptProfileGuidedModules, name) + } + // Visit the dependencies of this module just in case they also require files from the // prebuilt apex. return true @@ -637,7 +657,8 @@ func (p *prebuiltCommon) createDeapexerModuleIfNeeded(ctx android.TopDownMutator deapexerProperties := &DeapexerProperties{ // Remove any duplicates from the common modules lists as a module may be included via a direct // dependency as well as transitive ones. - CommonModules: android.SortedUniqueStrings(commonModules), + CommonModules: android.SortedUniqueStrings(commonModules), + DexpreoptProfileGuidedModules: android.SortedUniqueStrings(dexpreoptProfileGuidedModules), } // Populate the exported files property in a fixed order. @@ -737,13 +758,11 @@ var _ prebuiltApexModuleCreator = (*Prebuilt)(nil) // V V V // selector <--- deapexer <--- exported java lib func (p *Prebuilt) createPrebuiltApexModules(ctx android.TopDownMutatorContext) { - baseModuleName := p.BaseModuleName() - - apexSelectorModuleName := apexSelectorModuleName(baseModuleName) + apexSelectorModuleName := apexSelectorModuleName(p.Name()) createApexSelectorModule(ctx, apexSelectorModuleName, &p.properties.ApexFileProperties) apexFileSource := ":" + apexSelectorModuleName - p.createDeapexerModuleIfNeeded(ctx, deapexerModuleName(baseModuleName), apexFileSource) + p.createDeapexerModuleIfNeeded(ctx, deapexerModuleName(p.Name()), apexFileSource) // Add a source reference to retrieve the selected apex from the selector module. p.prebuiltCommonProperties.Selected_apex = proptools.StringPtr(apexFileSource) @@ -753,13 +772,79 @@ func (p *Prebuilt) ComponentDepsMutator(ctx android.BottomUpMutatorContext) { p.prebuiltApexContentsDeps(ctx) } +func (p *prebuiltCommon) DepsMutator(ctx android.BottomUpMutatorContext) { + if p.hasExportedDeps() { + // Create a dependency from the prebuilt apex (prebuilt_apex/apex_set) to the internal deapexer module + // The deapexer will return a provider that will be bubbled up to the rdeps of apexes (e.g. dex_bootjars) + ctx.AddDependency(ctx.Module(), android.DeapexerTag, deapexerModuleName(p.Name())) + } +} + var _ ApexInfoMutator = (*Prebuilt)(nil) func (p *Prebuilt) ApexInfoMutator(mctx android.TopDownMutatorContext) { p.apexInfoMutator(mctx) } +// Set a provider containing information about the jars and .prof provided by the apex +// Apexes built from prebuilts retrieve this information by visiting its internal deapexer module +// Used by dex_bootjars to generate the boot image +func (p *prebuiltCommon) provideApexExportsInfo(ctx android.ModuleContext) { + if !p.hasExportedDeps() { + // nothing to do + return + } + if di, err := android.FindDeapexerProviderForModule(ctx); err == nil { + javaModuleToDexPath := map[string]android.Path{} + for _, commonModule := range di.GetExportedModuleNames() { + if dex := di.PrebuiltExportPath(java.ApexRootRelativePathToJavaLib(commonModule)); dex != nil { + javaModuleToDexPath[commonModule] = dex + } + } + + exports := android.ApexExportsInfo{ + ApexName: p.ApexVariationName(), + ProfilePathOnHost: di.PrebuiltExportPath(java.ProfileInstallPathInApex), + LibraryNameToDexJarPathOnHost: javaModuleToDexPath, + } + android.SetProvider(ctx, android.ApexExportsInfoProvider, exports) + } else { + ctx.ModuleErrorf(err.Error()) + } +} + +// Set prebuiltInfoProvider. This will be used by `apex_prebuiltinfo_singleton` to print out a metadata file +// with information about whether source or prebuilt of an apex was used during the build. +func (p *prebuiltCommon) providePrebuiltInfo(ctx android.ModuleContext) { + info := android.PrebuiltInfo{ + Name: p.BaseModuleName(), + Is_prebuilt: true, + } + // If Prebuilt_info information is available in the soong module definition, add it to prebuilt_info.json. + if p.prebuiltCommonProperties.Prebuilt_info != nil { + info.Prebuilt_info_file_path = android.PathForModuleSrc(ctx, *p.prebuiltCommonProperties.Prebuilt_info).String() + } + android.SetProvider(ctx, android.PrebuiltInfoProvider, info) +} + +// Uses an object provided by its deps to validate that the contents of bcpf have been added to the global +// PRODUCT_APEX_BOOT_JARS +// This validation will only run on the apex which is active for this product/release_config +func validateApexClasspathFragments(ctx android.ModuleContext) { + ctx.VisitDirectDeps(func(m android.Module) { + if info, exists := android.OtherModuleProvider(ctx, m, java.ClasspathFragmentValidationInfoProvider); exists { + ctx.ModuleErrorf("%s in contents of %s must also be declared in PRODUCT_APEX_BOOT_JARS", info.UnknownJars, info.ClasspathFragmentModuleName) + } + }) +} + func (p *Prebuilt) GenerateAndroidBuildActions(ctx android.ModuleContext) { + // Validate contents of classpath fragments + if !p.IsHideFromMake() { + validateApexClasspathFragments(ctx) + } + + p.apexKeysPath = writeApexKeys(ctx, p) // TODO(jungjw): Check the key validity. p.inputApex = android.OptionalPathForModuleSrc(ctx, p.prebuiltCommonProperties.Selected_apex).Path() p.installDir = android.PathForModuleInstall(ctx, "apex") @@ -779,20 +864,30 @@ func (p *Prebuilt) GenerateAndroidBuildActions(ctx android.ModuleContext) { return } + // dexpreopt any system server jars if present + p.dexpreoptSystemServerJars(ctx) + + // provide info used for generating the boot image + p.provideApexExportsInfo(ctx) + + p.providePrebuiltInfo(ctx) + // Save the files that need to be made available to Make. p.initApexFilesForAndroidMk(ctx) // in case that prebuilt_apex replaces source apex (using prefer: prop) - p.compatSymlinks = makeCompatSymlinks(p.BaseModuleName(), ctx, true) + p.compatSymlinks = makeCompatSymlinks(p.BaseModuleName(), ctx) // or that prebuilt_apex overrides other apexes (using overrides: prop) for _, overridden := range p.prebuiltCommonProperties.Overrides { - p.compatSymlinks = append(p.compatSymlinks, makeCompatSymlinks(overridden, ctx, true)...) + p.compatSymlinks = append(p.compatSymlinks, makeCompatSymlinks(overridden, ctx)...) } if p.installable() { - p.installedFile = ctx.InstallFile(p.installDir, p.installFilename, p.inputApex, p.compatSymlinks.Paths()...) + p.installedFile = ctx.InstallFile(p.installDir, p.installFilename, p.inputApex, p.compatSymlinks...) p.provenanceMetaDataFile = provenance.GenerateArtifactProvenanceMetaData(ctx, p.inputApex, p.installedFile) } + + ctx.SetOutputFiles(android.Paths{p.outputApex}, "") } func (p *Prebuilt) ProvenanceMetaDataFile() android.OutputPath { @@ -878,12 +973,7 @@ func (e *ApexExtractorProperties) prebuiltSrcs(ctx android.BaseModuleContext) [] srcs = append(srcs, *e.Set) } - var sanitizers []string - if ctx.Host() { - sanitizers = ctx.Config().SanitizeHost() - } else { - sanitizers = ctx.Config().SanitizeDevice() - } + sanitizers := ctx.Config().SanitizeDevice() if android.InList("address", sanitizers) && e.Sanitized.Address.Set != nil { srcs = append(srcs, *e.Sanitized.Address.Set) @@ -913,15 +1003,6 @@ func (a *ApexSet) hasSanitizedSource(sanitizer string) bool { return false } -func (a *ApexSet) OutputFiles(tag string) (android.Paths, error) { - switch tag { - case "": - return android.Paths{a.outputApex}, nil - default: - return nil, fmt.Errorf("unsupported module reference tag %q", tag) - } -} - // prebuilt_apex imports an `.apex` file into the build graph as if it was built with apex. func apexSetFactory() android.Module { module := &ApexSet{} @@ -958,13 +1039,11 @@ var _ prebuiltApexModuleCreator = (*ApexSet)(nil) // from those provided this creates an extractor module which extracts the appropriate .apex file // from the zip file containing them. func (a *ApexSet) createPrebuiltApexModules(ctx android.TopDownMutatorContext) { - baseModuleName := a.BaseModuleName() - - apexExtractorModuleName := apexExtractorModuleName(baseModuleName) + apexExtractorModuleName := apexExtractorModuleName(a.Name()) createApexExtractorModule(ctx, apexExtractorModuleName, &a.properties.ApexExtractorProperties) apexFileSource := ":" + apexExtractorModuleName - a.createDeapexerModuleIfNeeded(ctx, deapexerModuleName(baseModuleName), apexFileSource) + a.createDeapexerModuleIfNeeded(ctx, deapexerModuleName(a.Name()), apexFileSource) // After passing the arch specific src properties to the creating the apex selector module a.prebuiltCommonProperties.Selected_apex = proptools.StringPtr(apexFileSource) @@ -981,6 +1060,12 @@ func (a *ApexSet) ApexInfoMutator(mctx android.TopDownMutatorContext) { } func (a *ApexSet) GenerateAndroidBuildActions(ctx android.ModuleContext) { + // Validate contents of classpath fragments + if !a.IsHideFromMake() { + validateApexClasspathFragments(ctx) + } + + a.apexKeysPath = writeApexKeys(ctx, a) a.installFilename = a.InstallFilename() if !strings.HasSuffix(a.installFilename, imageApexSuffix) && !strings.HasSuffix(a.installFilename, imageCapexSuffix) { ctx.ModuleErrorf("filename should end in %s or %s for apex_set", imageApexSuffix, imageCapexSuffix) @@ -999,6 +1084,14 @@ func (a *ApexSet) GenerateAndroidBuildActions(ctx android.ModuleContext) { return } + // dexpreopt any system server jars if present + a.dexpreoptSystemServerJars(ctx) + + // provide info used for generating the boot image + a.provideApexExportsInfo(ctx) + + a.providePrebuiltInfo(ctx) + // Save the files that need to be made available to Make. a.initApexFilesForAndroidMk(ctx) @@ -1008,11 +1101,13 @@ func (a *ApexSet) GenerateAndroidBuildActions(ctx android.ModuleContext) { } // in case that apex_set replaces source apex (using prefer: prop) - a.compatSymlinks = makeCompatSymlinks(a.BaseModuleName(), ctx, true) + a.compatSymlinks = makeCompatSymlinks(a.BaseModuleName(), ctx) // or that apex_set overrides other apexes (using overrides: prop) for _, overridden := range a.prebuiltCommonProperties.Overrides { - a.compatSymlinks = append(a.compatSymlinks, makeCompatSymlinks(overridden, ctx, true)...) + a.compatSymlinks = append(a.compatSymlinks, makeCompatSymlinks(overridden, ctx)...) } + + ctx.SetOutputFiles(android.Paths{a.outputApex}, "") } type systemExtContext struct { |