summaryrefslogtreecommitdiff
path: root/apex/prebuilt.go
diff options
context:
space:
mode:
Diffstat (limited to 'apex/prebuilt.go')
-rw-r--r--apex/prebuilt.go269
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 {