Merge changes I3323d993,I01cea895 into main am: 349ef87505 am: 2c5f3c7fc1

Original change: https://android-review.googlesource.com/c/platform/build/soong/+/2876754

Change-Id: Ib096242d10e90818fcf1e37e17ac98190a9922c2
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Spandan Das
2023-12-19 19:21:45 +00:00
committed by Automerger Merge Worker
14 changed files with 159 additions and 94 deletions

View File

@@ -15,6 +15,7 @@
package android package android
import ( import (
"fmt"
"strings" "strings"
"github.com/google/blueprint" "github.com/google/blueprint"
@@ -146,10 +147,16 @@ type RequiresFilesFromPrebuiltApexTag interface {
// FindDeapexerProviderForModule searches through the direct dependencies of the current context // FindDeapexerProviderForModule searches through the direct dependencies of the current context
// module for a DeapexerTag dependency and returns its DeapexerInfo. If a single nonambiguous // module for a DeapexerTag dependency and returns its DeapexerInfo. If a single nonambiguous
// deapexer module isn't found then errors are reported with ctx.ModuleErrorf and nil is returned. // deapexer module isn't found then it returns it an error
func FindDeapexerProviderForModule(ctx ModuleContext) *DeapexerInfo { // clients should check the value of error and call ctx.ModuleErrof if a non nil error is received
func FindDeapexerProviderForModule(ctx ModuleContext) (*DeapexerInfo, error) {
var di *DeapexerInfo var di *DeapexerInfo
var err error
ctx.VisitDirectDepsWithTag(DeapexerTag, func(m Module) { ctx.VisitDirectDepsWithTag(DeapexerTag, func(m Module) {
if err != nil {
// An err has been found. Do not visit further.
return
}
c, _ := OtherModuleProvider(ctx, m, DeapexerProvider) c, _ := OtherModuleProvider(ctx, m, DeapexerProvider)
p := &c p := &c
if di != nil { if di != nil {
@@ -159,17 +166,18 @@ func FindDeapexerProviderForModule(ctx ModuleContext) *DeapexerInfo {
di = selected di = selected
return return
} }
ctx.ModuleErrorf("Multiple installable prebuilt APEXes provide ambiguous deapexers: %s and %s", err = fmt.Errorf("Multiple installable prebuilt APEXes provide ambiguous deapexers: %s and %s", di.ApexModuleName(), p.ApexModuleName())
di.ApexModuleName(), p.ApexModuleName())
} }
di = p di = p
}) })
if err != nil {
return nil, err
}
if di != nil { if di != nil {
return di return di, nil
} }
ai, _ := ModuleProvider(ctx, ApexInfoProvider) ai, _ := ModuleProvider(ctx, ApexInfoProvider)
ctx.ModuleErrorf("No prebuilt APEX provides a deapexer module for APEX variant %s", ai.ApexVariationName) return nil, fmt.Errorf("No prebuilt APEX provides a deapexer module for APEX variant %s", ai.ApexVariationName)
return nil
} }
// removeCompressedApexSuffix removes the _compressed suffix from the name if present. // removeCompressedApexSuffix removes the _compressed suffix from the name if present.

View File

@@ -3725,7 +3725,7 @@ func ensureExactContents(t *testing.T, ctx *android.TestContext, moduleName, var
} }
func ensureExactDeapexedContents(t *testing.T, ctx *android.TestContext, moduleName string, variant string, files []string) { func ensureExactDeapexedContents(t *testing.T, ctx *android.TestContext, moduleName string, variant string, files []string) {
deapexer := ctx.ModuleForTests(moduleName+".deapexer", variant).Rule("deapexer") deapexer := ctx.ModuleForTests(moduleName+".deapexer", variant).Description("deapex")
outputs := make([]string, 0, len(deapexer.ImplicitOutputs)+1) outputs := make([]string, 0, len(deapexer.ImplicitOutputs)+1)
if deapexer.Output != nil { if deapexer.Output != nil {
outputs = append(outputs, deapexer.Output.String()) outputs = append(outputs, deapexer.Output.String())
@@ -8432,6 +8432,13 @@ func TestDuplicateDeapexersFromPrebuiltApexes(t *testing.T) {
prebuilt_bootclasspath_fragment { prebuilt_bootclasspath_fragment {
name: "my-bootclasspath-fragment", name: "my-bootclasspath-fragment",
apex_available: ["com.android.myapex"], apex_available: ["com.android.myapex"],
hidden_api: {
annotation_flags: "my-bootclasspath-fragment/annotation-flags.csv",
metadata: "my-bootclasspath-fragment/metadata.csv",
index: "my-bootclasspath-fragment/index.csv",
stub_flags: "my-bootclasspath-fragment/stub-flags.csv",
all_flags: "my-bootclasspath-fragment/all-flags.csv",
},
%s %s
} }
` `
@@ -8453,6 +8460,7 @@ func TestDuplicateDeapexersFromPrebuiltApexes(t *testing.T) {
public: { public: {
jars: ["libbar.jar"], jars: ["libbar.jar"],
}, },
shared_library: false,
apex_available: ["com.android.myapex"], apex_available: ["com.android.myapex"],
} }
`) `)
@@ -8468,6 +8476,7 @@ func TestDuplicateDeapexersFromPrebuiltApexes(t *testing.T) {
public: { public: {
jars: ["libbar.jar"], jars: ["libbar.jar"],
}, },
shared_library: false,
apex_available: ["com.android.myapex"], apex_available: ["com.android.myapex"],
} }
`) `)

View File

@@ -530,6 +530,8 @@ func TestBootclasspathFragmentInPrebuiltArtApex(t *testing.T) {
java.CheckModuleDependencies(t, result.TestContext, "com.android.art", "android_common_com.android.art", []string{ java.CheckModuleDependencies(t, result.TestContext, "com.android.art", "android_common_com.android.art", []string{
`com.android.art.apex.selector`, `com.android.art.apex.selector`,
`com.android.art.deapexer`,
`dex2oatd`,
`prebuilt_art-bootclasspath-fragment`, `prebuilt_art-bootclasspath-fragment`,
}) })

View File

@@ -22,6 +22,7 @@ import (
"strings" "strings"
"android/soong/android" "android/soong/android"
"android/soong/dexpreopt"
"android/soong/java" "android/soong/java"
"android/soong/provenance" "android/soong/provenance"
@@ -50,6 +51,7 @@ type prebuilt interface {
type prebuiltCommon struct { type prebuiltCommon struct {
android.ModuleBase android.ModuleBase
java.Dexpreopter
prebuilt android.Prebuilt prebuilt android.Prebuilt
// Properties common to both prebuilt_apex and apex_set. // Properties common to both prebuilt_apex and apex_set.
@@ -170,50 +172,42 @@ func (p *prebuiltCommon) installable() bool {
return proptools.BoolDefault(p.prebuiltCommonProperties.Installable, true) return proptools.BoolDefault(p.prebuiltCommonProperties.Installable, true)
} }
// initApexFilesForAndroidMk initializes the prebuiltCommon.apexFilesForAndroidMk field from the // To satisfy java.DexpreopterInterface
// modules that this depends upon. 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) { func (p *prebuiltCommon) initApexFilesForAndroidMk(ctx android.ModuleContext) {
// Walk the dependencies of this module looking for the java modules that it exports. // If this apex contains a system server jar, then the dexpreopt artifacts should be added as required
ctx.WalkDeps(func(child, parent android.Module) bool { for _, install := range p.Dexpreopter.DexpreoptBuiltInstalledForApex() {
tag := ctx.OtherModuleDependencyTag(child) p.requiredModuleNames = append(p.requiredModuleNames, install.FullModuleName())
}
}
name := android.RemoveOptionalPrebuiltPrefix(ctx.OtherModuleName(child)) // If this prebuilt has system server jar, create the rules to dexpreopt it and install it alongside the prebuilt apex
if java.IsBootclasspathFragmentContentDepTag(tag) || func (p *prebuiltCommon) dexpreoptSystemServerJars(ctx android.ModuleContext) {
java.IsSystemServerClasspathFragmentContentDepTag(tag) || tag == exportedJavaLibTag { // If this apex does not export anything, return
// If the exported java module provides a dex jar path then add it to the list of apexFiles. if !p.hasExportedDeps() {
path := child.(interface { return
DexJarBuildPath() java.OptionalDexJarPath }
}).DexJarBuildPath() // Use apex_name to determine the api domain of this prebuilt apex
if path.IsSet() { apexName := p.ApexVariationName()
af := apexFile{ di, err := android.FindDeapexerProviderForModule(ctx)
module: child, if err != nil {
moduleDir: ctx.OtherModuleDir(child), ctx.ModuleErrorf(err.Error())
androidMkModuleName: name, }
builtFile: path.Path(), dc := dexpreopt.GetGlobalConfig(ctx)
class: javaSharedLib, systemServerJarList := dc.AllApexSystemServerJars(ctx)
}
if module, ok := child.(java.DexpreopterInterface); ok { for i := 0; i < systemServerJarList.Len(); i++ {
for _, install := range module.DexpreoptBuiltInstalledForApex() { sscpApex := systemServerJarList.Apex(i)
af.requiredModuleNames = append(af.requiredModuleNames, install.FullModuleName()) sscpJar := systemServerJarList.Jar(i)
} if apexName != sscpApex {
} continue
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
} }
p.Dexpreopter.DexpreoptPrebuiltApexSystemServerJars(ctx, sscpJar, di)
return false }
})
} }
func (p *prebuiltCommon) addRequiredModules(entries *android.AndroidMkEntries) { func (p *prebuiltCommon) addRequiredModules(entries *android.AndroidMkEntries) {
@@ -248,6 +242,11 @@ func (p *prebuiltCommon) AndroidMkEntries() []android.AndroidMkEntries {
}, },
} }
// 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 // 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 // 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. // apex specific variants of the exported java modules available for use from within make.
@@ -756,6 +755,14 @@ func (p *Prebuilt) ComponentDepsMutator(ctx android.BottomUpMutatorContext) {
p.prebuiltApexContentsDeps(ctx) 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.BaseModuleName()))
}
}
var _ ApexInfoMutator = (*Prebuilt)(nil) var _ ApexInfoMutator = (*Prebuilt)(nil)
func (p *Prebuilt) ApexInfoMutator(mctx android.TopDownMutatorContext) { func (p *Prebuilt) ApexInfoMutator(mctx android.TopDownMutatorContext) {
@@ -783,6 +790,9 @@ func (p *Prebuilt) GenerateAndroidBuildActions(ctx android.ModuleContext) {
return return
} }
// dexpreopt any system server jars if present
p.dexpreoptSystemServerJars(ctx)
// Save the files that need to be made available to Make. // Save the files that need to be made available to Make.
p.initApexFilesForAndroidMk(ctx) p.initApexFilesForAndroidMk(ctx)
@@ -999,6 +1009,9 @@ func (a *ApexSet) GenerateAndroidBuildActions(ctx android.ModuleContext) {
return return
} }
// dexpreopt any system server jars if present
a.dexpreoptSystemServerJars(ctx)
// Save the files that need to be made available to Make. // Save the files that need to be made available to Make.
a.initApexFilesForAndroidMk(ctx) a.initApexFilesForAndroidMk(ctx)

View File

@@ -272,7 +272,9 @@ func TestPrebuiltSystemserverclasspathFragmentContents(t *testing.T) {
ctx := result.TestContext ctx := result.TestContext
java.CheckModuleDependencies(t, ctx, "myapex", "android_common_myapex", []string{ java.CheckModuleDependencies(t, ctx, "myapex", "android_common_myapex", []string{
`dex2oatd`,
`myapex.apex.selector`, `myapex.apex.selector`,
`myapex.deapexer`,
`prebuilt_mysystemserverclasspathfragment`, `prebuilt_mysystemserverclasspathfragment`,
}) })

View File

@@ -207,11 +207,7 @@ func (j *TestHelperLibrary) AndroidMkEntries() []android.AndroidMkEntries {
func (prebuilt *Import) AndroidMkEntries() []android.AndroidMkEntries { func (prebuilt *Import) AndroidMkEntries() []android.AndroidMkEntries {
if prebuilt.hideApexVariantFromMake { if prebuilt.hideApexVariantFromMake {
// For a library imported from a prebuilt APEX, we don't need a Make module for itself, as we return []android.AndroidMkEntries{}
// don't need to install it. However, we need to add its dexpreopt outputs as sub-modules, if it
// is preopted.
dexpreoptEntries := prebuilt.dexpreopter.AndroidMkEntriesForApex()
return append(dexpreoptEntries, android.AndroidMkEntries{Disabled: true})
} }
return []android.AndroidMkEntries{android.AndroidMkEntries{ return []android.AndroidMkEntries{android.AndroidMkEntries{
Class: "JAVA_LIBRARIES", Class: "JAVA_LIBRARIES",

View File

@@ -40,8 +40,8 @@ func TestAndroidAppImport(t *testing.T) {
variant := ctx.ModuleForTests("foo", "android_common") variant := ctx.ModuleForTests("foo", "android_common")
// Check dexpreopt outputs. // Check dexpreopt outputs.
if variant.MaybeOutput("dexpreopt/oat/arm64/package.vdex").Rule == nil || if variant.MaybeOutput("dexpreopt/foo/oat/arm64/package.vdex").Rule == nil ||
variant.MaybeOutput("dexpreopt/oat/arm64/package.odex").Rule == nil { variant.MaybeOutput("dexpreopt/foo/oat/arm64/package.odex").Rule == nil {
t.Errorf("can't find dexpreopt outputs") t.Errorf("can't find dexpreopt outputs")
} }
@@ -74,8 +74,8 @@ func TestAndroidAppImport_NoDexPreopt(t *testing.T) {
variant := ctx.ModuleForTests("foo", "android_common") variant := ctx.ModuleForTests("foo", "android_common")
// Check dexpreopt outputs. They shouldn't exist. // Check dexpreopt outputs. They shouldn't exist.
if variant.MaybeOutput("dexpreopt/oat/arm64/package.vdex").Rule != nil || if variant.MaybeOutput("dexpreopt/foo/oat/arm64/package.vdex").Rule != nil ||
variant.MaybeOutput("dexpreopt/oat/arm64/package.odex").Rule != nil { variant.MaybeOutput("dexpreopt/foo/oat/arm64/package.odex").Rule != nil {
t.Errorf("dexpreopt shouldn't have run.") t.Errorf("dexpreopt shouldn't have run.")
} }
@@ -101,8 +101,8 @@ func TestAndroidAppImport_Presigned(t *testing.T) {
variant := ctx.ModuleForTests("foo", "android_common") variant := ctx.ModuleForTests("foo", "android_common")
// Check dexpreopt outputs. // Check dexpreopt outputs.
if variant.MaybeOutput("dexpreopt/oat/arm64/package.vdex").Rule == nil || if variant.MaybeOutput("dexpreopt/foo/oat/arm64/package.vdex").Rule == nil ||
variant.MaybeOutput("dexpreopt/oat/arm64/package.odex").Rule == nil { variant.MaybeOutput("dexpreopt/foo/oat/arm64/package.odex").Rule == nil {
t.Errorf("can't find dexpreopt outputs") t.Errorf("can't find dexpreopt outputs")
} }
// Make sure signing was skipped and aligning was done. // Make sure signing was skipped and aligning was done.
@@ -210,8 +210,8 @@ func TestAndroidAppImport_DefaultDevCert(t *testing.T) {
variant := ctx.ModuleForTests("foo", "android_common") variant := ctx.ModuleForTests("foo", "android_common")
// Check dexpreopt outputs. // Check dexpreopt outputs.
if variant.MaybeOutput("dexpreopt/oat/arm64/package.vdex").Rule == nil || if variant.MaybeOutput("dexpreopt/foo/oat/arm64/package.vdex").Rule == nil ||
variant.MaybeOutput("dexpreopt/oat/arm64/package.odex").Rule == nil { variant.MaybeOutput("dexpreopt/foo/oat/arm64/package.odex").Rule == nil {
t.Errorf("can't find dexpreopt outputs") t.Errorf("can't find dexpreopt outputs")
} }

View File

@@ -3357,7 +3357,7 @@ func TestUsesLibraries(t *testing.T) {
cmd := app.Rule("dexpreopt").RuleParams.Command cmd := app.Rule("dexpreopt").RuleParams.Command
android.AssertStringDoesContain(t, "dexpreopt app cmd context", cmd, "--context-json=") android.AssertStringDoesContain(t, "dexpreopt app cmd context", cmd, "--context-json=")
android.AssertStringDoesContain(t, "dexpreopt app cmd product_packages", cmd, android.AssertStringDoesContain(t, "dexpreopt app cmd product_packages", cmd,
"--product-packages=out/soong/.intermediates/app/android_common/dexpreopt/product_packages.txt") "--product-packages=out/soong/.intermediates/app/android_common/dexpreopt/app/product_packages.txt")
} }
func TestDexpreoptBcp(t *testing.T) { func TestDexpreoptBcp(t *testing.T) {

View File

@@ -240,7 +240,8 @@ type BootclasspathFragmentModule struct {
sourceOnlyProperties SourceOnlyBootclasspathProperties sourceOnlyProperties SourceOnlyBootclasspathProperties
// Path to the boot image profile. // Path to the boot image profile.
profilePath android.WritablePath profilePath android.WritablePath
profilePathErr error
} }
// commonBootclasspathFragment defines the methods that are implemented by both source and prebuilt // commonBootclasspathFragment defines the methods that are implemented by both source and prebuilt
@@ -1065,8 +1066,11 @@ func (module *PrebuiltBootclasspathFragmentModule) produceBootImageProfile(ctx a
return nil return nil
} }
di := android.FindDeapexerProviderForModule(ctx) di, err := android.FindDeapexerProviderForModule(ctx)
if di == nil { if err != nil {
// An error was found, possibly due to multiple apexes in the tree that export this library
// Defer the error till a client tries to call getProfilePath
module.profilePathErr = err
return nil // An error has been reported by FindDeapexerProviderForModule. return nil // An error has been reported by FindDeapexerProviderForModule.
} }
@@ -1074,6 +1078,9 @@ func (module *PrebuiltBootclasspathFragmentModule) produceBootImageProfile(ctx a
} }
func (b *PrebuiltBootclasspathFragmentModule) getProfilePath() android.Path { func (b *PrebuiltBootclasspathFragmentModule) getProfilePath() android.Path {
if b.profilePathErr != nil {
panic(b.profilePathErr.Error())
}
return b.profilePath return b.profilePath
} }

View File

@@ -79,18 +79,25 @@ func (install *dexpreopterInstall) SubModuleName() string {
func (install dexpreopterInstall) ToMakeEntries() android.AndroidMkEntries { func (install dexpreopterInstall) ToMakeEntries() android.AndroidMkEntries {
return android.AndroidMkEntries{ return android.AndroidMkEntries{
Class: "ETC", Class: "ETC",
SubName: install.SubModuleName(),
OutputFile: android.OptionalPathForPath(install.outputPathOnHost), OutputFile: android.OptionalPathForPath(install.outputPathOnHost),
ExtraEntries: []android.AndroidMkExtraEntriesFunc{ ExtraEntries: []android.AndroidMkExtraEntriesFunc{
func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) { func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
entries.SetString("LOCAL_MODULE", install.FullModuleName())
entries.SetString("LOCAL_MODULE_PATH", install.installDirOnDevice.String()) entries.SetString("LOCAL_MODULE_PATH", install.installDirOnDevice.String())
entries.SetString("LOCAL_INSTALLED_MODULE_STEM", install.installFileOnDevice) entries.SetString("LOCAL_INSTALLED_MODULE_STEM", install.installFileOnDevice)
entries.SetString("LOCAL_NOT_AVAILABLE_FOR_PLATFORM", "false") entries.SetString("LOCAL_NOT_AVAILABLE_FOR_PLATFORM", "false")
// Unset LOCAL_SOONG_INSTALLED_MODULE so that this does not default to the primary .apex file
// Without this, installation of the dexpreopt artifacts get skipped
entries.SetString("LOCAL_SOONG_INSTALLED_MODULE", "")
}, },
}, },
} }
} }
type Dexpreopter struct {
dexpreopter
}
type dexpreopter struct { type dexpreopter struct {
dexpreoptProperties DexpreoptProperties dexpreoptProperties DexpreoptProperties
importDexpreoptProperties ImportDexpreoptProperties importDexpreoptProperties ImportDexpreoptProperties
@@ -258,6 +265,17 @@ func (d *dexpreopter) getInstallPath(
return defaultInstallPath return defaultInstallPath
} }
// DexpreoptPrebuiltApexSystemServerJars generates the dexpreopt artifacts from a jar file that has been deapexed from a prebuilt apex
func (d *Dexpreopter) DexpreoptPrebuiltApexSystemServerJars(ctx android.ModuleContext, libraryName string, di *android.DeapexerInfo) {
// A single prebuilt apex can have multiple apex system jars
// initialize the output path for this dex jar
dc := dexpreopt.GetGlobalConfig(ctx)
d.installPath = android.PathForModuleInPartitionInstall(ctx, "", strings.TrimPrefix(dexpreopt.GetSystemServerDexLocation(ctx, dc, libraryName), "/"))
// generate the rules for creating the .odex and .vdex files for this system server jar
dexJarFile := di.PrebuiltExportPath(apexRootRelativePathToJavaLib(libraryName))
d.dexpreopt(ctx, dexJarFile)
}
func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.WritablePath) { func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.WritablePath) {
global := dexpreopt.GetGlobalConfig(ctx) global := dexpreopt.GetGlobalConfig(ctx)
@@ -346,11 +364,15 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Wr
d.dexpreoptProperties.Dex_preopt_result.Profile_guided = profileClassListing.Valid() d.dexpreoptProperties.Dex_preopt_result.Profile_guided = profileClassListing.Valid()
// A single apex can have multiple system server jars
// Use the dexJar to create a unique scope for each
dexJarStem := strings.TrimSuffix(dexJarFile.Base(), dexJarFile.Ext())
// Full dexpreopt config, used to create dexpreopt build rules. // Full dexpreopt config, used to create dexpreopt build rules.
dexpreoptConfig := &dexpreopt.ModuleConfig{ dexpreoptConfig := &dexpreopt.ModuleConfig{
Name: moduleName(ctx), Name: moduleName(ctx),
DexLocation: dexLocation, DexLocation: dexLocation,
BuildPath: android.PathForModuleOut(ctx, "dexpreopt", moduleName(ctx)+".jar").OutputPath, BuildPath: android.PathForModuleOut(ctx, "dexpreopt", dexJarStem, moduleName(ctx)+".jar").OutputPath,
DexPath: dexJarFile, DexPath: dexJarFile,
ManifestPath: android.OptionalPathForPath(d.manifestFile), ManifestPath: android.OptionalPathForPath(d.manifestFile),
UncompressedDex: d.uncompressedDex, UncompressedDex: d.uncompressedDex,
@@ -380,7 +402,7 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Wr
PresignedPrebuilt: d.isPresignedPrebuilt, PresignedPrebuilt: d.isPresignedPrebuilt,
} }
d.configPath = android.PathForModuleOut(ctx, "dexpreopt", "dexpreopt.config") d.configPath = android.PathForModuleOut(ctx, "dexpreopt", dexJarStem, "dexpreopt.config")
dexpreopt.WriteModuleConfig(ctx, dexpreoptConfig, d.configPath) dexpreopt.WriteModuleConfig(ctx, dexpreoptConfig, d.configPath)
if d.dexpreoptDisabled(ctx) { if d.dexpreoptDisabled(ctx) {
@@ -394,7 +416,7 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Wr
// dependencies to create a per-app list, and use `rsync --checksum` to prevent the file's mtime // dependencies to create a per-app list, and use `rsync --checksum` to prevent the file's mtime
// from being changed if the contents don't change. This avoids unnecessary dexpreopt reruns. // from being changed if the contents don't change. This avoids unnecessary dexpreopt reruns.
productPackages := android.PathForModuleInPartitionInstall(ctx, "", "product_packages.txt") productPackages := android.PathForModuleInPartitionInstall(ctx, "", "product_packages.txt")
appProductPackages := android.PathForModuleOut(ctx, "dexpreopt", "product_packages.txt") appProductPackages := android.PathForModuleOut(ctx, "dexpreopt", dexJarStem, "product_packages.txt")
appProductPackagesStaging := appProductPackages.ReplaceExtension(ctx, "txt.tmp") appProductPackagesStaging := appProductPackages.ReplaceExtension(ctx, "txt.tmp")
clcNames, _ := dexpreopt.ComputeClassLoaderContextDependencies(dexpreoptConfig.ClassLoaderContexts) clcNames, _ := dexpreopt.ComputeClassLoaderContextDependencies(dexpreoptConfig.ClassLoaderContexts)
sort.Strings(clcNames) // The order needs to be deterministic. sort.Strings(clcNames) // The order needs to be deterministic.
@@ -416,7 +438,7 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Wr
Text("rsync --checksum"). Text("rsync --checksum").
Input(appProductPackagesStaging). Input(appProductPackagesStaging).
Output(appProductPackages) Output(appProductPackages)
productPackagesRule.Restat().Build("product_packages", "dexpreopt product_packages") productPackagesRule.Restat().Build("product_packages."+dexJarStem, "dexpreopt product_packages")
dexpreoptRule, err := dexpreopt.GenerateDexpreoptRule( dexpreoptRule, err := dexpreopt.GenerateDexpreoptRule(
ctx, globalSoong, global, dexpreoptConfig, appProductPackages) ctx, globalSoong, global, dexpreoptConfig, appProductPackages)
@@ -425,9 +447,11 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Wr
return return
} }
dexpreoptRule.Build("dexpreopt", "dexpreopt") dexpreoptRule.Build("dexpreopt"+"."+dexJarStem, "dexpreopt")
isApexSystemServerJar := global.AllApexSystemServerJars(ctx).ContainsJar(moduleName(ctx)) // The current ctx might be of a deapexer module created by a prebuilt apex
// Use the path of the dex file to determine the library name
isApexSystemServerJar := global.AllApexSystemServerJars(ctx).ContainsJar(dexJarStem)
for _, install := range dexpreoptRule.Installs() { for _, install := range dexpreoptRule.Installs() {
// Remove the "/" prefix because the path should be relative to $ANDROID_PRODUCT_OUT. // Remove the "/" prefix because the path should be relative to $ANDROID_PRODUCT_OUT.
@@ -452,7 +476,7 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Wr
// The installs will be handled by Make as sub-modules of the java library. // The installs will be handled by Make as sub-modules of the java library.
d.builtInstalledForApex = append(d.builtInstalledForApex, dexpreopterInstall{ d.builtInstalledForApex = append(d.builtInstalledForApex, dexpreopterInstall{
name: arch + "-" + installBase, name: arch + "-" + installBase,
moduleName: moduleName(ctx), moduleName: dexJarStem,
outputPathOnHost: install.From, outputPathOnHost: install.From,
installDirOnDevice: installPath, installDirOnDevice: installPath,
installFileOnDevice: installBase, installFileOnDevice: installBase,

View File

@@ -410,7 +410,7 @@ func TestAndroidMkEntriesForApex(t *testing.T) {
verifyEntries(t, verifyEntries(t,
"entriesList[0]", "entriesList[0]",
"service-foo-dexpreopt-arm64-apex@com.android.apex1@javalib@service-foo.jar@classes.odex", "service-foo-dexpreopt-arm64-apex@com.android.apex1@javalib@service-foo.jar@classes.odex",
"/dexpreopt/oat/arm64/javalib.odex", "/dexpreopt/service-foo/oat/arm64/javalib.odex",
"/system/framework/oat/arm64", "/system/framework/oat/arm64",
"apex@com.android.apex1@javalib@service-foo.jar@classes.odex", "apex@com.android.apex1@javalib@service-foo.jar@classes.odex",
entriesList[0]) entriesList[0])
@@ -418,7 +418,7 @@ func TestAndroidMkEntriesForApex(t *testing.T) {
verifyEntries(t, verifyEntries(t,
"entriesList[1]", "entriesList[1]",
"service-foo-dexpreopt-arm64-apex@com.android.apex1@javalib@service-foo.jar@classes.vdex", "service-foo-dexpreopt-arm64-apex@com.android.apex1@javalib@service-foo.jar@classes.vdex",
"/dexpreopt/oat/arm64/javalib.vdex", "/dexpreopt/service-foo/oat/arm64/javalib.vdex",
"/system/framework/oat/arm64", "/system/framework/oat/arm64",
"apex@com.android.apex1@javalib@service-foo.jar@classes.vdex", "apex@com.android.apex1@javalib@service-foo.jar@classes.vdex",
entriesList[1]) entriesList[1])
@@ -459,7 +459,7 @@ func TestGenerateProfileEvenIfDexpreoptIsDisabled(t *testing.T) {
ctx := result.TestContext ctx := result.TestContext
dexpreopt := ctx.ModuleForTests("foo", "android_common").MaybeRule("dexpreopt") dexpreopt := ctx.ModuleForTests("foo", "android_common").MaybeRule("dexpreopt")
expected := []string{"out/soong/.intermediates/foo/android_common/dexpreopt/profile.prof"} expected := []string{"out/soong/.intermediates/foo/android_common/dexpreopt/foo/profile.prof"}
android.AssertArrayString(t, "outputs", expected, dexpreopt.AllOutputs()) android.AssertArrayString(t, "outputs", expected, dexpreopt.AllOutputs())
} }

View File

@@ -2100,6 +2100,7 @@ type Import struct {
// output file containing classes.dex and resources // output file containing classes.dex and resources
dexJarFile OptionalDexJarPath dexJarFile OptionalDexJarPath
dexJarFileErr error
dexJarInstallFile android.Path dexJarInstallFile android.Path
combinedClasspathFile android.Path combinedClasspathFile android.Path
@@ -2250,9 +2251,12 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) {
ai, _ := android.ModuleProvider(ctx, android.ApexInfoProvider) ai, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
if ai.ForPrebuiltApex { if ai.ForPrebuiltApex {
// Get the path of the dex implementation jar from the `deapexer` module. // Get the path of the dex implementation jar from the `deapexer` module.
di := android.FindDeapexerProviderForModule(ctx) di, err := android.FindDeapexerProviderForModule(ctx)
if di == nil { if err != nil {
return // An error has been reported by FindDeapexerProviderForModule. // An error was found, possibly due to multiple apexes in the tree that export this library
// Defer the error till a client tries to call DexJarBuildPath
j.dexJarFileErr = err
return
} }
dexJarFileApexRootRelative := apexRootRelativePathToJavaLib(j.BaseModuleName()) dexJarFileApexRootRelative := apexRootRelativePathToJavaLib(j.BaseModuleName())
if dexOutputPath := di.PrebuiltExportPath(dexJarFileApexRootRelative); dexOutputPath != nil { if dexOutputPath := di.PrebuiltExportPath(dexJarFileApexRootRelative); dexOutputPath != nil {
@@ -2375,6 +2379,9 @@ func (j *Import) ImplementationAndResourcesJars() android.Paths {
} }
func (j *Import) DexJarBuildPath() OptionalDexJarPath { func (j *Import) DexJarBuildPath() OptionalDexJarPath {
if j.dexJarFileErr != nil {
panic(j.dexJarFileErr.Error())
}
return j.dexJarFile return j.dexJarFile
} }

View File

@@ -618,8 +618,6 @@ func TestPrebuilts(t *testing.T) {
android.AssertStringEquals(t, "unexpected LOCAL_SOONG_MODULE_TYPE", "java_library", entries.EntryMap["LOCAL_SOONG_MODULE_TYPE"][0]) android.AssertStringEquals(t, "unexpected LOCAL_SOONG_MODULE_TYPE", "java_library", entries.EntryMap["LOCAL_SOONG_MODULE_TYPE"][0])
entries = android.AndroidMkEntriesForTest(t, ctx, barModule.Module())[0] entries = android.AndroidMkEntriesForTest(t, ctx, barModule.Module())[0]
android.AssertStringEquals(t, "unexpected LOCAL_SOONG_MODULE_TYPE", "java_import", entries.EntryMap["LOCAL_SOONG_MODULE_TYPE"][0]) android.AssertStringEquals(t, "unexpected LOCAL_SOONG_MODULE_TYPE", "java_import", entries.EntryMap["LOCAL_SOONG_MODULE_TYPE"][0])
entries = android.AndroidMkEntriesForTest(t, ctx, ctx.ModuleForTests("sdklib", "android_common").Module())[0]
android.AssertStringEquals(t, "unexpected LOCAL_SOONG_MODULE_TYPE", "java_sdk_library_import", entries.EntryMap["LOCAL_SOONG_MODULE_TYPE"][0])
} }
func assertDeepEquals(t *testing.T, message string, expected interface{}, actual interface{}) { func assertDeepEquals(t *testing.T, message string, expected interface{}, actual interface{}) {

View File

@@ -2378,7 +2378,8 @@ type SdkLibraryImport struct {
xmlPermissionsFileModule *sdkLibraryXml xmlPermissionsFileModule *sdkLibraryXml
// Build path to the dex implementation jar obtained from the prebuilt_apex, if any. // Build path to the dex implementation jar obtained from the prebuilt_apex, if any.
dexJarFile OptionalDexJarPath dexJarFile OptionalDexJarPath
dexJarFileErr error
// Expected install file path of the source module(sdk_library) // Expected install file path of the source module(sdk_library)
// or dex implementation jar obtained from the prebuilt_apex, if any. // or dex implementation jar obtained from the prebuilt_apex, if any.
@@ -2591,14 +2592,6 @@ func (module *SdkLibraryImport) DepsMutator(ctx android.BottomUpMutatorContext)
} }
} }
func (module *SdkLibraryImport) AndroidMkEntries() []android.AndroidMkEntries {
// For an SDK library imported from a prebuilt APEX, we don't need a Make module for itself, as we
// don't need to install it. However, we need to add its dexpreopt outputs as sub-modules, if it
// is preopted.
dexpreoptEntries := module.dexpreopter.AndroidMkEntriesForApex()
return append(dexpreoptEntries, android.AndroidMkEntries{Disabled: true})
}
var _ android.ApexModule = (*SdkLibraryImport)(nil) var _ android.ApexModule = (*SdkLibraryImport)(nil)
// Implements android.ApexModule // Implements android.ApexModule
@@ -2695,9 +2688,12 @@ func (module *SdkLibraryImport) GenerateAndroidBuildActions(ctx android.ModuleCo
ai, _ := android.ModuleProvider(ctx, android.ApexInfoProvider) ai, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
if ai.ForPrebuiltApex { if ai.ForPrebuiltApex {
// Get the path of the dex implementation jar from the `deapexer` module. // Get the path of the dex implementation jar from the `deapexer` module.
di := android.FindDeapexerProviderForModule(ctx) di, err := android.FindDeapexerProviderForModule(ctx)
if di == nil { if err != nil {
return // An error has been reported by FindDeapexerProviderForModule. // An error was found, possibly due to multiple apexes in the tree that export this library
// Defer the error till a client tries to call DexJarBuildPath
module.dexJarFileErr = err
return
} }
dexJarFileApexRootRelative := apexRootRelativePathToJavaLib(module.BaseModuleName()) dexJarFileApexRootRelative := apexRootRelativePathToJavaLib(module.BaseModuleName())
if dexOutputPath := di.PrebuiltExportPath(dexJarFileApexRootRelative); dexOutputPath != nil { if dexOutputPath := di.PrebuiltExportPath(dexJarFileApexRootRelative); dexOutputPath != nil {
@@ -2759,6 +2755,9 @@ func (module *SdkLibraryImport) SdkImplementationJars(ctx android.BaseModuleCont
func (module *SdkLibraryImport) DexJarBuildPath() OptionalDexJarPath { func (module *SdkLibraryImport) DexJarBuildPath() OptionalDexJarPath {
// The dex implementation jar extracted from the .apex file should be used in preference to the // The dex implementation jar extracted from the .apex file should be used in preference to the
// source. // source.
if module.dexJarFileErr != nil {
panic(module.dexJarFileErr.Error())
}
if module.dexJarFile.IsSet() { if module.dexJarFile.IsSet() {
return module.dexJarFile return module.dexJarFile
} }