Revert^2 "Preopt APEX system server jars."
This reverts commit 92346c4832
.
Reason for revert: Fixed build error.
The build error is fixed by ag/15841934. This CL remains unchanged. This
CL will be submitted AFTER ag/15841934 is submitted.
Bug: 200024131
Test: 1. Patch this CL and ag/15841934 into internal master.
2. sudo vendor/google/build/build_test.bash
Change-Id: I5f2b8357846fc7dda56e25ebe6ffb095e8047ec8
This commit is contained in:
parent
92346c4832
commit
519c5c82e5
9 changed files with 518 additions and 54 deletions
|
@ -1659,6 +1659,20 @@ func (l *ConfiguredJarList) Append(apex string, jar string) ConfiguredJarList {
|
||||||
return ConfiguredJarList{apexes, jars}
|
return ConfiguredJarList{apexes, jars}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Append a list of (apex, jar) pairs to the list.
|
||||||
|
func (l *ConfiguredJarList) AppendList(other ConfiguredJarList) ConfiguredJarList {
|
||||||
|
apexes := make([]string, 0, l.Len()+other.Len())
|
||||||
|
jars := make([]string, 0, l.Len()+other.Len())
|
||||||
|
|
||||||
|
apexes = append(apexes, l.apexes...)
|
||||||
|
jars = append(jars, l.jars...)
|
||||||
|
|
||||||
|
apexes = append(apexes, other.apexes...)
|
||||||
|
jars = append(jars, other.jars...)
|
||||||
|
|
||||||
|
return ConfiguredJarList{apexes, jars}
|
||||||
|
}
|
||||||
|
|
||||||
// RemoveList filters out a list of (apex, jar) pairs from the receiving list of pairs.
|
// RemoveList filters out a list of (apex, jar) pairs from the receiving list of pairs.
|
||||||
func (l *ConfiguredJarList) RemoveList(list ConfiguredJarList) ConfiguredJarList {
|
func (l *ConfiguredJarList) RemoveList(list ConfiguredJarList) ConfiguredJarList {
|
||||||
apexes := make([]string, 0, l.Len())
|
apexes := make([]string, 0, l.Len())
|
||||||
|
|
|
@ -1569,6 +1569,11 @@ func apexFileForJavaModuleWithFile(ctx android.BaseModuleContext, module javaMod
|
||||||
af.jacocoReportClassesFile = module.JacocoReportClassesFile()
|
af.jacocoReportClassesFile = module.JacocoReportClassesFile()
|
||||||
af.lintDepSets = module.LintDepSets()
|
af.lintDepSets = module.LintDepSets()
|
||||||
af.customStem = module.Stem() + ".jar"
|
af.customStem = module.Stem() + ".jar"
|
||||||
|
if dexpreopter, ok := module.(java.DexpreopterInterface); ok {
|
||||||
|
for _, install := range dexpreopter.DexpreoptBuiltInstalledForApex() {
|
||||||
|
af.requiredModuleNames = append(af.requiredModuleNames, install.FullModuleName())
|
||||||
|
}
|
||||||
|
}
|
||||||
return af
|
return af
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -110,17 +110,12 @@ func dexpreoptDisabled(ctx android.PathContext, global *GlobalConfig, module *Mo
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't preopt system server jars that are updatable.
|
|
||||||
if global.ApexSystemServerJars.ContainsJar(module.Name) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// If OnlyPreoptBootImageAndSystemServer=true and module is not in boot class path skip
|
// If OnlyPreoptBootImageAndSystemServer=true and module is not in boot class path skip
|
||||||
// Also preopt system server jars since selinux prevents system server from loading anything from
|
// Also preopt system server jars since selinux prevents system server from loading anything from
|
||||||
// /data. If we don't do this they will need to be extracted which is not favorable for RAM usage
|
// /data. If we don't do this they will need to be extracted which is not favorable for RAM usage
|
||||||
// or performance. If PreoptExtractedApk is true, we ignore the only preopt boot image options.
|
// or performance. If PreoptExtractedApk is true, we ignore the only preopt boot image options.
|
||||||
if global.OnlyPreoptBootImageAndSystemServer && !global.BootJars.ContainsJar(module.Name) &&
|
if global.OnlyPreoptBootImageAndSystemServer && !global.BootJars.ContainsJar(module.Name) &&
|
||||||
!global.SystemServerJars.ContainsJar(module.Name) && !module.PreoptExtractedApk {
|
!AllSystemServerJars(ctx, global).ContainsJar(module.Name) && !module.PreoptExtractedApk {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -201,6 +196,14 @@ func bootProfileCommand(ctx android.PathContext, globalSoong *GlobalSoongConfig,
|
||||||
return profilePath
|
return profilePath
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns the dex location of a system server java library.
|
||||||
|
func GetSystemServerDexLocation(global *GlobalConfig, lib string) string {
|
||||||
|
if apex := global.ApexSystemServerJars.ApexOfJar(lib); apex != "" {
|
||||||
|
return fmt.Sprintf("/apex/%s/javalib/%s.jar", apex, lib)
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("/system/framework/%s.jar", lib)
|
||||||
|
}
|
||||||
|
|
||||||
func dexpreoptCommand(ctx android.PathContext, globalSoong *GlobalSoongConfig, global *GlobalConfig,
|
func dexpreoptCommand(ctx android.PathContext, globalSoong *GlobalSoongConfig, global *GlobalConfig,
|
||||||
module *ModuleConfig, rule *android.RuleBuilder, archIdx int, profile android.WritablePath,
|
module *ModuleConfig, rule *android.RuleBuilder, archIdx int, profile android.WritablePath,
|
||||||
appImage bool, generateDM bool) {
|
appImage bool, generateDM bool) {
|
||||||
|
@ -216,6 +219,13 @@ func dexpreoptCommand(ctx android.PathContext, globalSoong *GlobalSoongConfig, g
|
||||||
}
|
}
|
||||||
|
|
||||||
toOdexPath := func(path string) string {
|
toOdexPath := func(path string) string {
|
||||||
|
if global.ApexSystemServerJars.ContainsJar(module.Name) {
|
||||||
|
return filepath.Join(
|
||||||
|
"/system/framework/oat",
|
||||||
|
arch.String(),
|
||||||
|
strings.ReplaceAll(path[1:], "/", "@")+"@classes.odex")
|
||||||
|
}
|
||||||
|
|
||||||
return filepath.Join(
|
return filepath.Join(
|
||||||
filepath.Dir(path),
|
filepath.Dir(path),
|
||||||
"oat",
|
"oat",
|
||||||
|
@ -234,20 +244,21 @@ func dexpreoptCommand(ctx android.PathContext, globalSoong *GlobalSoongConfig, g
|
||||||
|
|
||||||
invocationPath := odexPath.ReplaceExtension(ctx, "invocation")
|
invocationPath := odexPath.ReplaceExtension(ctx, "invocation")
|
||||||
|
|
||||||
systemServerJars := NonApexSystemServerJars(ctx, global)
|
systemServerJars := AllSystemServerJars(ctx, global)
|
||||||
|
|
||||||
rule.Command().FlagWithArg("mkdir -p ", filepath.Dir(odexPath.String()))
|
rule.Command().FlagWithArg("mkdir -p ", filepath.Dir(odexPath.String()))
|
||||||
rule.Command().FlagWithOutput("rm -f ", odexPath)
|
rule.Command().FlagWithOutput("rm -f ", odexPath)
|
||||||
|
|
||||||
if jarIndex := android.IndexList(module.Name, systemServerJars); jarIndex >= 0 {
|
if jarIndex := systemServerJars.IndexOfJar(module.Name); jarIndex >= 0 {
|
||||||
// System server jars should be dexpreopted together: class loader context of each jar
|
// System server jars should be dexpreopted together: class loader context of each jar
|
||||||
// should include all preceding jars on the system server classpath.
|
// should include all preceding jars on the system server classpath.
|
||||||
|
|
||||||
var clcHost android.Paths
|
var clcHost android.Paths
|
||||||
var clcTarget []string
|
var clcTarget []string
|
||||||
for _, lib := range systemServerJars[:jarIndex] {
|
for i := 0; i < jarIndex; i++ {
|
||||||
|
lib := systemServerJars.Jar(i)
|
||||||
clcHost = append(clcHost, SystemServerDexJarHostPath(ctx, lib))
|
clcHost = append(clcHost, SystemServerDexJarHostPath(ctx, lib))
|
||||||
clcTarget = append(clcTarget, filepath.Join("/system/framework", lib+".jar"))
|
clcTarget = append(clcTarget, GetSystemServerDexLocation(global, lib))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy the system server jar to a predefined location where dex2oat will find it.
|
// Copy the system server jar to a predefined location where dex2oat will find it.
|
||||||
|
@ -362,7 +373,7 @@ func dexpreoptCommand(ctx android.PathContext, globalSoong *GlobalSoongConfig, g
|
||||||
|
|
||||||
if !android.PrefixInList(preoptFlags, "--compiler-filter=") {
|
if !android.PrefixInList(preoptFlags, "--compiler-filter=") {
|
||||||
var compilerFilter string
|
var compilerFilter string
|
||||||
if global.SystemServerJars.ContainsJar(module.Name) {
|
if systemServerJars.ContainsJar(module.Name) {
|
||||||
// Jars of system server, use the product option if it is set, speed otherwise.
|
// Jars of system server, use the product option if it is set, speed otherwise.
|
||||||
if global.SystemServerCompilerFilter != "" {
|
if global.SystemServerCompilerFilter != "" {
|
||||||
compilerFilter = global.SystemServerCompilerFilter
|
compilerFilter = global.SystemServerCompilerFilter
|
||||||
|
@ -416,7 +427,7 @@ func dexpreoptCommand(ctx android.PathContext, globalSoong *GlobalSoongConfig, g
|
||||||
|
|
||||||
// PRODUCT_SYSTEM_SERVER_DEBUG_INFO overrides WITH_DEXPREOPT_DEBUG_INFO.
|
// PRODUCT_SYSTEM_SERVER_DEBUG_INFO overrides WITH_DEXPREOPT_DEBUG_INFO.
|
||||||
// PRODUCT_OTHER_JAVA_DEBUG_INFO overrides WITH_DEXPREOPT_DEBUG_INFO.
|
// PRODUCT_OTHER_JAVA_DEBUG_INFO overrides WITH_DEXPREOPT_DEBUG_INFO.
|
||||||
if global.SystemServerJars.ContainsJar(module.Name) {
|
if systemServerJars.ContainsJar(module.Name) {
|
||||||
if global.AlwaysSystemServerDebugInfo {
|
if global.AlwaysSystemServerDebugInfo {
|
||||||
debugInfo = true
|
debugInfo = true
|
||||||
} else if global.NeverSystemServerDebugInfo {
|
} else if global.NeverSystemServerDebugInfo {
|
||||||
|
@ -518,14 +529,15 @@ func makefileMatch(pattern, s string) bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var nonApexSystemServerJarsKey = android.NewOnceKey("nonApexSystemServerJars")
|
var allSystemServerJarsKey = android.NewOnceKey("allSystemServerJars")
|
||||||
|
|
||||||
// TODO: eliminate the superficial global config parameter by moving global config definition
|
// TODO: eliminate the superficial global config parameter by moving global config definition
|
||||||
// from java subpackage to dexpreopt.
|
// from java subpackage to dexpreopt.
|
||||||
func NonApexSystemServerJars(ctx android.PathContext, global *GlobalConfig) []string {
|
func AllSystemServerJars(ctx android.PathContext, global *GlobalConfig) *android.ConfiguredJarList {
|
||||||
return ctx.Config().Once(nonApexSystemServerJarsKey, func() interface{} {
|
return ctx.Config().Once(allSystemServerJarsKey, func() interface{} {
|
||||||
return android.RemoveListFromList(global.SystemServerJars.CopyOfJars(), global.ApexSystemServerJars.CopyOfJars())
|
allSystemServerJars := global.SystemServerJars.AppendList(global.ApexSystemServerJars)
|
||||||
}).([]string)
|
return &allSystemServerJars
|
||||||
|
}).(*android.ConfiguredJarList)
|
||||||
}
|
}
|
||||||
|
|
||||||
// A predefined location for the system server dex jars. This is needed in order to generate
|
// A predefined location for the system server dex jars. This is needed in order to generate
|
||||||
|
@ -551,12 +563,12 @@ func checkSystemServerOrder(ctx android.PathContext, jarIndex int) {
|
||||||
mctx, isModule := ctx.(android.ModuleContext)
|
mctx, isModule := ctx.(android.ModuleContext)
|
||||||
if isModule {
|
if isModule {
|
||||||
config := GetGlobalConfig(ctx)
|
config := GetGlobalConfig(ctx)
|
||||||
jars := NonApexSystemServerJars(ctx, config)
|
jars := AllSystemServerJars(ctx, config)
|
||||||
mctx.WalkDeps(func(dep android.Module, parent android.Module) bool {
|
mctx.WalkDeps(func(dep android.Module, parent android.Module) bool {
|
||||||
depIndex := android.IndexList(dep.Name(), jars)
|
depIndex := jars.IndexOfJar(dep.Name())
|
||||||
if jarIndex < depIndex && !config.BrokenSuboptimalOrderOfSystemServerJars {
|
if jarIndex < depIndex && !config.BrokenSuboptimalOrderOfSystemServerJars {
|
||||||
jar := jars[jarIndex]
|
jar := jars.Jar(jarIndex)
|
||||||
dep := jars[depIndex]
|
dep := jars.Jar(depIndex)
|
||||||
mctx.ModuleErrorf("non-optimal order of jars on the system server classpath:"+
|
mctx.ModuleErrorf("non-optimal order of jars on the system server classpath:"+
|
||||||
" '%s' precedes its dependency '%s', so dexpreopt is unable to resolve any"+
|
" '%s' precedes its dependency '%s', so dexpreopt is unable to resolve any"+
|
||||||
" references from '%s' to '%s'.\n", jar, dep, jar, dep)
|
" references from '%s' to '%s'.\n", jar, dep, jar, dep)
|
||||||
|
|
|
@ -33,17 +33,35 @@ func testProductModuleConfig(ctx android.PathContext, name string) *ModuleConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
func testModuleConfig(ctx android.PathContext, name, partition string) *ModuleConfig {
|
func testModuleConfig(ctx android.PathContext, name, partition string) *ModuleConfig {
|
||||||
|
return createTestModuleConfig(
|
||||||
|
name,
|
||||||
|
fmt.Sprintf("/%s/app/test/%s.apk", partition, name),
|
||||||
|
android.PathForOutput(ctx, fmt.Sprintf("%s/%s.apk", name, name)),
|
||||||
|
android.PathForOutput(ctx, fmt.Sprintf("%s/dex/%s.jar", name, name)),
|
||||||
|
android.PathForOutput(ctx, fmt.Sprintf("%s/enforce_uses_libraries.status", name)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func testApexModuleConfig(ctx android.PathContext, name, apexName string) *ModuleConfig {
|
||||||
|
return createTestModuleConfig(
|
||||||
|
name,
|
||||||
|
fmt.Sprintf("/apex/%s/javalib/%s.jar", apexName, name),
|
||||||
|
android.PathForOutput(ctx, fmt.Sprintf("%s/dexpreopt/%s.jar", name, name)),
|
||||||
|
android.PathForOutput(ctx, fmt.Sprintf("%s/aligned/%s.jar", name, name)),
|
||||||
|
android.PathForOutput(ctx, fmt.Sprintf("%s/enforce_uses_libraries.status", name)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func createTestModuleConfig(name, dexLocation string, buildPath, dexPath, enforceUsesLibrariesStatusFile android.OutputPath) *ModuleConfig {
|
||||||
return &ModuleConfig{
|
return &ModuleConfig{
|
||||||
Name: name,
|
Name: name,
|
||||||
DexLocation: fmt.Sprintf("/%s/app/test/%s.apk", partition, name),
|
DexLocation: dexLocation,
|
||||||
BuildPath: android.PathForOutput(ctx, fmt.Sprintf("%s/%s.apk", name, name)),
|
BuildPath: buildPath,
|
||||||
DexPath: android.PathForOutput(ctx, fmt.Sprintf("%s/dex/%s.jar", name, name)),
|
DexPath: dexPath,
|
||||||
UncompressedDex: false,
|
UncompressedDex: false,
|
||||||
HasApkLibraries: false,
|
HasApkLibraries: false,
|
||||||
PreoptFlags: nil,
|
PreoptFlags: nil,
|
||||||
ProfileClassListing: android.OptionalPath{},
|
ProfileClassListing: android.OptionalPath{},
|
||||||
ProfileIsTextListing: false,
|
ProfileIsTextListing: false,
|
||||||
EnforceUsesLibrariesStatusFile: android.PathForOutput(ctx, fmt.Sprintf("%s/enforce_uses_libraries.status", name)),
|
EnforceUsesLibrariesStatusFile: enforceUsesLibrariesStatusFile,
|
||||||
EnforceUsesLibraries: false,
|
EnforceUsesLibraries: false,
|
||||||
ClassLoaderContexts: nil,
|
ClassLoaderContexts: nil,
|
||||||
Archs: []android.ArchType{android.Arm},
|
Archs: []android.ArchType{android.Arm},
|
||||||
|
@ -140,6 +158,29 @@ func TestDexPreoptSystemOther(t *testing.T) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDexPreoptApexSystemServerJars(t *testing.T) {
|
||||||
|
config := android.TestConfig("out", nil, "", nil)
|
||||||
|
ctx := android.BuilderContextForTesting(config)
|
||||||
|
globalSoong := globalSoongConfigForTests()
|
||||||
|
global := GlobalConfigForTests(ctx)
|
||||||
|
module := testApexModuleConfig(ctx, "service-A", "com.android.apex1")
|
||||||
|
|
||||||
|
global.ApexSystemServerJars = android.CreateTestConfiguredJarList(
|
||||||
|
[]string{"com.android.apex1:service-A"})
|
||||||
|
|
||||||
|
rule, err := GenerateDexpreoptRule(ctx, globalSoong, global, module)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
wantInstalls := android.RuleBuilderInstalls{
|
||||||
|
{android.PathForOutput(ctx, "service-A/dexpreopt/oat/arm/javalib.odex"), "/system/framework/oat/arm/apex@com.android.apex1@javalib@service-A.jar@classes.odex"},
|
||||||
|
{android.PathForOutput(ctx, "service-A/dexpreopt/oat/arm/javalib.vdex"), "/system/framework/oat/arm/apex@com.android.apex1@javalib@service-A.jar@classes.vdex"},
|
||||||
|
}
|
||||||
|
|
||||||
|
android.AssertStringEquals(t, "installs", wantInstalls.String(), rule.Installs().String())
|
||||||
|
}
|
||||||
|
|
||||||
func TestDexPreoptProfile(t *testing.T) {
|
func TestDexPreoptProfile(t *testing.T) {
|
||||||
config := android.TestConfig("out", nil, "", nil)
|
config := android.TestConfig("out", nil, "", nil)
|
||||||
ctx := android.BuilderContextForTesting(config)
|
ctx := android.BuilderContextForTesting(config)
|
||||||
|
|
|
@ -61,7 +61,13 @@ func (library *Library) AndroidMkEntries() []android.AndroidMkEntries {
|
||||||
var entriesList []android.AndroidMkEntries
|
var entriesList []android.AndroidMkEntries
|
||||||
|
|
||||||
if library.hideApexVariantFromMake {
|
if library.hideApexVariantFromMake {
|
||||||
// For a java library built for an APEX we don't need Make module
|
// For a java library built for an APEX, we don't need a Make module for itself. Otherwise, it
|
||||||
|
// will conflict with the platform variant because they have the same module name in the
|
||||||
|
// makefile. However, we need to add its dexpreopt outputs as sub-modules, if it is preopted.
|
||||||
|
dexpreoptEntries := library.dexpreopter.AndroidMkEntriesForApex()
|
||||||
|
if len(dexpreoptEntries) > 0 {
|
||||||
|
entriesList = append(entriesList, dexpreoptEntries...)
|
||||||
|
}
|
||||||
entriesList = append(entriesList, android.AndroidMkEntries{Disabled: true})
|
entriesList = append(entriesList, android.AndroidMkEntries{Disabled: true})
|
||||||
} else if !library.ApexModuleBase.AvailableFor(android.AvailableToPlatform) {
|
} else if !library.ApexModuleBase.AvailableFor(android.AvailableToPlatform) {
|
||||||
// Platform variant. If not available for the platform, we don't need Make module.
|
// Platform variant. If not available for the platform, we don't need Make module.
|
||||||
|
|
|
@ -15,13 +15,46 @@
|
||||||
package java
|
package java
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"android/soong/android"
|
"android/soong/android"
|
||||||
"android/soong/dexpreopt"
|
"android/soong/dexpreopt"
|
||||||
)
|
)
|
||||||
|
|
||||||
type dexpreopterInterface interface {
|
type DexpreopterInterface interface {
|
||||||
IsInstallable() bool // Structs that embed dexpreopter must implement this.
|
IsInstallable() bool // Structs that embed dexpreopter must implement this.
|
||||||
dexpreoptDisabled(ctx android.BaseModuleContext) bool
|
dexpreoptDisabled(ctx android.BaseModuleContext) bool
|
||||||
|
DexpreoptBuiltInstalledForApex() []dexpreopterInstall
|
||||||
|
AndroidMkEntriesForApex() []android.AndroidMkEntries
|
||||||
|
}
|
||||||
|
|
||||||
|
type dexpreopterInstall struct {
|
||||||
|
// A unique name to distinguish an output from others for the same java library module. Usually in
|
||||||
|
// the form of `<arch>-<encoded-path>.odex/vdex/art`.
|
||||||
|
name string
|
||||||
|
|
||||||
|
// The name of the input java module.
|
||||||
|
moduleName string
|
||||||
|
|
||||||
|
// The path to the dexpreopt output on host.
|
||||||
|
outputPathOnHost android.Path
|
||||||
|
|
||||||
|
// The directory on the device for the output to install to.
|
||||||
|
installDirOnDevice android.InstallPath
|
||||||
|
|
||||||
|
// The basename (the last segment of the path) for the output to install as.
|
||||||
|
installFileOnDevice string
|
||||||
|
}
|
||||||
|
|
||||||
|
// The full module name of the output in the makefile.
|
||||||
|
func (install *dexpreopterInstall) FullModuleName() string {
|
||||||
|
return install.moduleName + install.SubModuleName()
|
||||||
|
}
|
||||||
|
|
||||||
|
// The sub-module name of the output in the makefile (the name excluding the java module name).
|
||||||
|
func (install *dexpreopterInstall) SubModuleName() string {
|
||||||
|
return "-dexpreopt-" + install.name
|
||||||
}
|
}
|
||||||
|
|
||||||
type dexpreopter struct {
|
type dexpreopter struct {
|
||||||
|
@ -39,7 +72,9 @@ type dexpreopter struct {
|
||||||
enforceUsesLibs bool
|
enforceUsesLibs bool
|
||||||
classLoaderContexts dexpreopt.ClassLoaderContextMap
|
classLoaderContexts dexpreopt.ClassLoaderContextMap
|
||||||
|
|
||||||
builtInstalled string
|
// See the `dexpreopt` function for details.
|
||||||
|
builtInstalled string
|
||||||
|
builtInstalledForApex []dexpreopterInstall
|
||||||
|
|
||||||
// The config is used for two purposes:
|
// The config is used for two purposes:
|
||||||
// - Passing dexpreopt information about libraries from Soong to Make. This is needed when
|
// - Passing dexpreopt information about libraries from Soong to Make. This is needed when
|
||||||
|
@ -74,6 +109,17 @@ func init() {
|
||||||
dexpreopt.DexpreoptRunningInSoong = true
|
dexpreopt.DexpreoptRunningInSoong = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isApexVariant(ctx android.BaseModuleContext) bool {
|
||||||
|
apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
|
||||||
|
return !apexInfo.IsForPlatform()
|
||||||
|
}
|
||||||
|
|
||||||
|
func moduleName(ctx android.BaseModuleContext) string {
|
||||||
|
// Remove the "prebuilt_" prefix if the module is from a prebuilt because the prefix is not
|
||||||
|
// expected by dexpreopter.
|
||||||
|
return android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName())
|
||||||
|
}
|
||||||
|
|
||||||
func (d *dexpreopter) dexpreoptDisabled(ctx android.BaseModuleContext) bool {
|
func (d *dexpreopter) dexpreoptDisabled(ctx android.BaseModuleContext) bool {
|
||||||
global := dexpreopt.GetGlobalConfig(ctx)
|
global := dexpreopt.GetGlobalConfig(ctx)
|
||||||
|
|
||||||
|
@ -81,7 +127,7 @@ func (d *dexpreopter) dexpreoptDisabled(ctx android.BaseModuleContext) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
if inList(ctx.ModuleName(), global.DisablePreoptModules) {
|
if inList(moduleName(ctx), global.DisablePreoptModules) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,7 +139,7 @@ func (d *dexpreopter) dexpreoptDisabled(ctx android.BaseModuleContext) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
if !ctx.Module().(dexpreopterInterface).IsInstallable() {
|
if !ctx.Module().(DexpreopterInterface).IsInstallable() {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,9 +147,17 @@ func (d *dexpreopter) dexpreoptDisabled(ctx android.BaseModuleContext) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't preopt APEX variant module
|
if isApexVariant(ctx) {
|
||||||
if apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo); !apexInfo.IsForPlatform() {
|
// Don't preopt APEX variant module unless the module is an APEX system server jar and we are
|
||||||
return true
|
// building the entire system image.
|
||||||
|
if !global.ApexSystemServerJars.ContainsJar(moduleName(ctx)) || ctx.Config().UnbundledBuild() {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Don't preopt the platform variant of an APEX system server jar to avoid conflicts.
|
||||||
|
if global.ApexSystemServerJars.ContainsJar(moduleName(ctx)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: contains no java code
|
// TODO: contains no java code
|
||||||
|
@ -112,17 +166,40 @@ func (d *dexpreopter) dexpreoptDisabled(ctx android.BaseModuleContext) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func dexpreoptToolDepsMutator(ctx android.BottomUpMutatorContext) {
|
func dexpreoptToolDepsMutator(ctx android.BottomUpMutatorContext) {
|
||||||
if d, ok := ctx.Module().(dexpreopterInterface); !ok || d.dexpreoptDisabled(ctx) {
|
if d, ok := ctx.Module().(DexpreopterInterface); !ok || d.dexpreoptDisabled(ctx) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
dexpreopt.RegisterToolDeps(ctx)
|
dexpreopt.RegisterToolDeps(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func odexOnSystemOther(ctx android.ModuleContext, installPath android.InstallPath) bool {
|
func (d *dexpreopter) odexOnSystemOther(ctx android.ModuleContext, installPath android.InstallPath) bool {
|
||||||
return dexpreopt.OdexOnSystemOtherByName(ctx.ModuleName(), android.InstallPathToOnDevicePath(ctx, installPath), dexpreopt.GetGlobalConfig(ctx))
|
return dexpreopt.OdexOnSystemOtherByName(moduleName(ctx), android.InstallPathToOnDevicePath(ctx, installPath), dexpreopt.GetGlobalConfig(ctx))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the install path of the dex jar of a module.
|
||||||
|
//
|
||||||
|
// Do not rely on `ApexInfo.ApexVariationName` because it can be something like "apex1000", rather
|
||||||
|
// than the `name` in the path `/apex/<name>` as suggested in its comment.
|
||||||
|
//
|
||||||
|
// This function is on a best-effort basis. It cannot handle the case where an APEX jar is not a
|
||||||
|
// system server jar, which is fine because we currently only preopt system server jars for APEXes.
|
||||||
|
func (d *dexpreopter) getInstallPath(
|
||||||
|
ctx android.ModuleContext, defaultInstallPath android.InstallPath) android.InstallPath {
|
||||||
|
global := dexpreopt.GetGlobalConfig(ctx)
|
||||||
|
if global.ApexSystemServerJars.ContainsJar(moduleName(ctx)) {
|
||||||
|
dexLocation := dexpreopt.GetSystemServerDexLocation(global, moduleName(ctx))
|
||||||
|
return android.PathForModuleInPartitionInstall(ctx, "", strings.TrimPrefix(dexLocation, "/"))
|
||||||
|
}
|
||||||
|
if !d.dexpreoptDisabled(ctx) && isApexVariant(ctx) &&
|
||||||
|
filepath.Base(defaultInstallPath.PartitionDir()) != "apex" {
|
||||||
|
ctx.ModuleErrorf("unable to get the install path of the dex jar for dexpreopt")
|
||||||
|
}
|
||||||
|
return defaultInstallPath
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.WritablePath) {
|
func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.WritablePath) {
|
||||||
|
global := dexpreopt.GetGlobalConfig(ctx)
|
||||||
|
|
||||||
// TODO(b/148690468): The check on d.installPath is to bail out in cases where
|
// TODO(b/148690468): The check on d.installPath is to bail out in cases where
|
||||||
// the dexpreopter struct hasn't been fully initialized before we're called,
|
// the dexpreopter struct hasn't been fully initialized before we're called,
|
||||||
// e.g. in aar.go. This keeps the behaviour that dexpreopting is effectively
|
// e.g. in aar.go. This keeps the behaviour that dexpreopting is effectively
|
||||||
|
@ -133,7 +210,7 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Wr
|
||||||
|
|
||||||
dexLocation := android.InstallPathToOnDevicePath(ctx, d.installPath)
|
dexLocation := android.InstallPathToOnDevicePath(ctx, d.installPath)
|
||||||
|
|
||||||
providesUsesLib := ctx.ModuleName()
|
providesUsesLib := moduleName(ctx)
|
||||||
if ulib, ok := ctx.Module().(ProvidesUsesLib); ok {
|
if ulib, ok := ctx.Module().(ProvidesUsesLib); ok {
|
||||||
name := ulib.ProvidesUsesLib()
|
name := ulib.ProvidesUsesLib()
|
||||||
if name != nil {
|
if name != nil {
|
||||||
|
@ -147,9 +224,8 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Wr
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
global := dexpreopt.GetGlobalConfig(ctx)
|
isSystemServerJar := global.SystemServerJars.ContainsJar(moduleName(ctx)) ||
|
||||||
|
global.ApexSystemServerJars.ContainsJar(moduleName(ctx))
|
||||||
isSystemServerJar := global.SystemServerJars.ContainsJar(ctx.ModuleName())
|
|
||||||
|
|
||||||
bootImage := defaultBootImageConfig(ctx)
|
bootImage := defaultBootImageConfig(ctx)
|
||||||
if global.UseArtImage {
|
if global.UseArtImage {
|
||||||
|
@ -199,15 +275,15 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Wr
|
||||||
profileIsTextListing = true
|
profileIsTextListing = true
|
||||||
} else if global.ProfileDir != "" {
|
} else if global.ProfileDir != "" {
|
||||||
profileClassListing = android.ExistentPathForSource(ctx,
|
profileClassListing = android.ExistentPathForSource(ctx,
|
||||||
global.ProfileDir, ctx.ModuleName()+".prof")
|
global.ProfileDir, moduleName(ctx)+".prof")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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: ctx.ModuleName(),
|
Name: moduleName(ctx),
|
||||||
DexLocation: dexLocation,
|
DexLocation: dexLocation,
|
||||||
BuildPath: android.PathForModuleOut(ctx, "dexpreopt", ctx.ModuleName()+".jar").OutputPath,
|
BuildPath: android.PathForModuleOut(ctx, "dexpreopt", moduleName(ctx)+".jar").OutputPath,
|
||||||
DexPath: dexJarFile,
|
DexPath: dexJarFile,
|
||||||
ManifestPath: android.OptionalPathForPath(d.manifestFile),
|
ManifestPath: android.OptionalPathForPath(d.manifestFile),
|
||||||
UncompressedDex: d.uncompressedDex,
|
UncompressedDex: d.uncompressedDex,
|
||||||
|
@ -256,5 +332,53 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Wr
|
||||||
|
|
||||||
dexpreoptRule.Build("dexpreopt", "dexpreopt")
|
dexpreoptRule.Build("dexpreopt", "dexpreopt")
|
||||||
|
|
||||||
d.builtInstalled = dexpreoptRule.Installs().String()
|
if global.ApexSystemServerJars.ContainsJar(moduleName(ctx)) {
|
||||||
|
// APEX variants of java libraries are hidden from Make, so their dexpreopt outputs need special
|
||||||
|
// handling. Currently, for APEX variants of java libraries, only those in the system server
|
||||||
|
// classpath are handled here. Preopting of boot classpath jars in the ART APEX are handled in
|
||||||
|
// java/dexpreopt_bootjars.go, and other APEX jars are not preopted.
|
||||||
|
for _, install := range dexpreoptRule.Installs() {
|
||||||
|
// Remove the "/" prefix because the path should be relative to $ANDROID_PRODUCT_OUT.
|
||||||
|
installDir := strings.TrimPrefix(filepath.Dir(install.To), "/")
|
||||||
|
installBase := filepath.Base(install.To)
|
||||||
|
arch := filepath.Base(installDir)
|
||||||
|
installPath := android.PathForModuleInPartitionInstall(ctx, "", installDir)
|
||||||
|
// The installs will be handled by Make as sub-modules of the java library.
|
||||||
|
d.builtInstalledForApex = append(d.builtInstalledForApex, dexpreopterInstall{
|
||||||
|
name: arch + "-" + installBase,
|
||||||
|
moduleName: moduleName(ctx),
|
||||||
|
outputPathOnHost: install.From,
|
||||||
|
installDirOnDevice: installPath,
|
||||||
|
installFileOnDevice: installBase,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// The installs will be handled by Make as LOCAL_SOONG_BUILT_INSTALLED of the java library
|
||||||
|
// module.
|
||||||
|
d.builtInstalled = dexpreoptRule.Installs().String()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *dexpreopter) DexpreoptBuiltInstalledForApex() []dexpreopterInstall {
|
||||||
|
return d.builtInstalledForApex
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *dexpreopter) AndroidMkEntriesForApex() []android.AndroidMkEntries {
|
||||||
|
var entries []android.AndroidMkEntries
|
||||||
|
for _, install := range d.builtInstalledForApex {
|
||||||
|
install := install
|
||||||
|
entries = append(entries, android.AndroidMkEntries{
|
||||||
|
Class: "ETC",
|
||||||
|
SubName: install.SubModuleName(),
|
||||||
|
OutputFile: android.OptionalPathForPath(install.outputPathOnHost),
|
||||||
|
ExtraEntries: []android.AndroidMkExtraEntriesFunc{
|
||||||
|
func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
|
||||||
|
entries.SetString("LOCAL_MODULE_PATH", install.installDirOnDevice.ToMakePath().String())
|
||||||
|
entries.SetString("LOCAL_INSTALLED_MODULE_STEM", install.installFileOnDevice)
|
||||||
|
entries.SetString("LOCAL_NOT_AVAILABLE_FOR_PLATFORM", "false")
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return entries
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ package java
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"android/soong/android"
|
"android/soong/android"
|
||||||
|
@ -24,11 +25,17 @@ import (
|
||||||
"android/soong/dexpreopt"
|
"android/soong/dexpreopt"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
RegisterFakeRuntimeApexMutator()
|
||||||
|
}
|
||||||
|
|
||||||
func TestDexpreoptEnabled(t *testing.T) {
|
func TestDexpreoptEnabled(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
bp string
|
bp string
|
||||||
enabled bool
|
moduleName string
|
||||||
|
apexVariant bool
|
||||||
|
enabled bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "app",
|
name: "app",
|
||||||
|
@ -148,13 +155,81 @@ func TestDexpreoptEnabled(t *testing.T) {
|
||||||
}`,
|
}`,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "apex variant",
|
||||||
|
bp: `
|
||||||
|
java_library {
|
||||||
|
name: "foo",
|
||||||
|
installable: true,
|
||||||
|
srcs: ["a.java"],
|
||||||
|
apex_available: ["com.android.apex1"],
|
||||||
|
}`,
|
||||||
|
apexVariant: true,
|
||||||
|
enabled: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "apex variant of apex system server jar",
|
||||||
|
bp: `
|
||||||
|
java_library {
|
||||||
|
name: "service-foo",
|
||||||
|
installable: true,
|
||||||
|
srcs: ["a.java"],
|
||||||
|
apex_available: ["com.android.apex1"],
|
||||||
|
}`,
|
||||||
|
moduleName: "service-foo",
|
||||||
|
apexVariant: true,
|
||||||
|
enabled: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "apex variant of prebuilt apex system server jar",
|
||||||
|
bp: `
|
||||||
|
java_library {
|
||||||
|
name: "prebuilt_service-foo",
|
||||||
|
installable: true,
|
||||||
|
srcs: ["a.java"],
|
||||||
|
apex_available: ["com.android.apex1"],
|
||||||
|
}`,
|
||||||
|
moduleName: "prebuilt_service-foo",
|
||||||
|
apexVariant: true,
|
||||||
|
enabled: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "platform variant of apex system server jar",
|
||||||
|
bp: `
|
||||||
|
java_library {
|
||||||
|
name: "service-foo",
|
||||||
|
installable: true,
|
||||||
|
srcs: ["a.java"],
|
||||||
|
apex_available: ["com.android.apex1"],
|
||||||
|
}`,
|
||||||
|
moduleName: "service-foo",
|
||||||
|
apexVariant: false,
|
||||||
|
enabled: false,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.name, func(t *testing.T) {
|
||||||
ctx, _ := testJava(t, test.bp)
|
preparers := android.GroupFixturePreparers(
|
||||||
|
PrepareForTestWithJavaDefaultModules,
|
||||||
|
PrepareForTestWithFakeApexMutator,
|
||||||
|
dexpreopt.FixtureSetApexSystemServerJars("com.android.apex1:service-foo"),
|
||||||
|
)
|
||||||
|
|
||||||
dexpreopt := ctx.ModuleForTests("foo", "android_common").MaybeRule("dexpreopt")
|
result := preparers.RunTestWithBp(t, test.bp)
|
||||||
|
ctx := result.TestContext
|
||||||
|
|
||||||
|
moduleName := "foo"
|
||||||
|
if test.moduleName != "" {
|
||||||
|
moduleName = test.moduleName
|
||||||
|
}
|
||||||
|
|
||||||
|
variant := "android_common"
|
||||||
|
if test.apexVariant {
|
||||||
|
variant += "_apex1000"
|
||||||
|
}
|
||||||
|
|
||||||
|
dexpreopt := ctx.ModuleForTests(moduleName, variant).MaybeRule("dexpreopt")
|
||||||
enabled := dexpreopt.Rule != nil
|
enabled := dexpreopt.Rule != nil
|
||||||
|
|
||||||
if enabled != test.enabled {
|
if enabled != test.enabled {
|
||||||
|
@ -220,3 +295,145 @@ func TestDex2oatToolDeps(t *testing.T) {
|
||||||
testDex2oatToolDep(true, true, true, prebuiltDex2oatPath)
|
testDex2oatToolDep(true, true, true, prebuiltDex2oatPath)
|
||||||
testDex2oatToolDep(false, true, false, prebuiltDex2oatPath)
|
testDex2oatToolDep(false, true, false, prebuiltDex2oatPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDexpreoptBuiltInstalledForApex(t *testing.T) {
|
||||||
|
preparers := android.GroupFixturePreparers(
|
||||||
|
PrepareForTestWithJavaDefaultModules,
|
||||||
|
PrepareForTestWithFakeApexMutator,
|
||||||
|
dexpreopt.FixtureSetApexSystemServerJars("com.android.apex1:service-foo"),
|
||||||
|
)
|
||||||
|
|
||||||
|
// An APEX system server jar.
|
||||||
|
result := preparers.RunTestWithBp(t, `
|
||||||
|
java_library {
|
||||||
|
name: "service-foo",
|
||||||
|
installable: true,
|
||||||
|
srcs: ["a.java"],
|
||||||
|
apex_available: ["com.android.apex1"],
|
||||||
|
}`)
|
||||||
|
ctx := result.TestContext
|
||||||
|
module := ctx.ModuleForTests("service-foo", "android_common_apex1000")
|
||||||
|
library := module.Module().(*Library)
|
||||||
|
|
||||||
|
installs := library.dexpreopter.DexpreoptBuiltInstalledForApex()
|
||||||
|
|
||||||
|
android.AssertIntEquals(t, "install count", 2, len(installs))
|
||||||
|
|
||||||
|
android.AssertStringEquals(t, "installs[0] FullModuleName",
|
||||||
|
"service-foo-dexpreopt-arm64-apex@com.android.apex1@javalib@service-foo.jar@classes.odex",
|
||||||
|
installs[0].FullModuleName())
|
||||||
|
|
||||||
|
android.AssertStringEquals(t, "installs[0] SubModuleName",
|
||||||
|
"-dexpreopt-arm64-apex@com.android.apex1@javalib@service-foo.jar@classes.odex",
|
||||||
|
installs[0].SubModuleName())
|
||||||
|
|
||||||
|
android.AssertStringEquals(t, "installs[1] FullModuleName",
|
||||||
|
"service-foo-dexpreopt-arm64-apex@com.android.apex1@javalib@service-foo.jar@classes.vdex",
|
||||||
|
installs[1].FullModuleName())
|
||||||
|
|
||||||
|
android.AssertStringEquals(t, "installs[1] SubModuleName",
|
||||||
|
"-dexpreopt-arm64-apex@com.android.apex1@javalib@service-foo.jar@classes.vdex",
|
||||||
|
installs[1].SubModuleName())
|
||||||
|
|
||||||
|
// Not an APEX system server jar.
|
||||||
|
result = preparers.RunTestWithBp(t, `
|
||||||
|
java_library {
|
||||||
|
name: "foo",
|
||||||
|
installable: true,
|
||||||
|
srcs: ["a.java"],
|
||||||
|
}`)
|
||||||
|
ctx = result.TestContext
|
||||||
|
module = ctx.ModuleForTests("foo", "android_common")
|
||||||
|
library = module.Module().(*Library)
|
||||||
|
|
||||||
|
installs = library.dexpreopter.DexpreoptBuiltInstalledForApex()
|
||||||
|
|
||||||
|
android.AssertIntEquals(t, "install count", 0, len(installs))
|
||||||
|
}
|
||||||
|
|
||||||
|
func filterDexpreoptEntriesList(entriesList []android.AndroidMkEntries) []android.AndroidMkEntries {
|
||||||
|
var results []android.AndroidMkEntries
|
||||||
|
for _, entries := range entriesList {
|
||||||
|
if strings.Contains(entries.EntryMap["LOCAL_MODULE"][0], "-dexpreopt-") {
|
||||||
|
results = append(results, entries)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return results
|
||||||
|
}
|
||||||
|
|
||||||
|
func verifyEntries(t *testing.T, message string, expectedModule string,
|
||||||
|
expectedPrebuiltModuleFile string, expectedModulePath string, expectedInstalledModuleStem string,
|
||||||
|
entries android.AndroidMkEntries) {
|
||||||
|
android.AssertStringEquals(t, message+" LOCAL_MODULE", expectedModule,
|
||||||
|
entries.EntryMap["LOCAL_MODULE"][0])
|
||||||
|
|
||||||
|
android.AssertStringEquals(t, message+" LOCAL_MODULE_CLASS", "ETC",
|
||||||
|
entries.EntryMap["LOCAL_MODULE_CLASS"][0])
|
||||||
|
|
||||||
|
android.AssertStringDoesContain(t, message+" LOCAL_PREBUILT_MODULE_FILE",
|
||||||
|
entries.EntryMap["LOCAL_PREBUILT_MODULE_FILE"][0], expectedPrebuiltModuleFile)
|
||||||
|
|
||||||
|
android.AssertStringDoesContain(t, message+" LOCAL_MODULE_PATH",
|
||||||
|
entries.EntryMap["LOCAL_MODULE_PATH"][0], expectedModulePath)
|
||||||
|
|
||||||
|
android.AssertStringEquals(t, message+" LOCAL_INSTALLED_MODULE_STEM",
|
||||||
|
expectedInstalledModuleStem, entries.EntryMap["LOCAL_INSTALLED_MODULE_STEM"][0])
|
||||||
|
|
||||||
|
android.AssertStringEquals(t, message+" LOCAL_NOT_AVAILABLE_FOR_PLATFORM",
|
||||||
|
"false", entries.EntryMap["LOCAL_NOT_AVAILABLE_FOR_PLATFORM"][0])
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAndroidMkEntriesForApex(t *testing.T) {
|
||||||
|
preparers := android.GroupFixturePreparers(
|
||||||
|
PrepareForTestWithJavaDefaultModules,
|
||||||
|
PrepareForTestWithFakeApexMutator,
|
||||||
|
dexpreopt.FixtureSetApexSystemServerJars("com.android.apex1:service-foo"),
|
||||||
|
)
|
||||||
|
|
||||||
|
// An APEX system server jar.
|
||||||
|
result := preparers.RunTestWithBp(t, `
|
||||||
|
java_library {
|
||||||
|
name: "service-foo",
|
||||||
|
installable: true,
|
||||||
|
srcs: ["a.java"],
|
||||||
|
apex_available: ["com.android.apex1"],
|
||||||
|
}`)
|
||||||
|
ctx := result.TestContext
|
||||||
|
module := ctx.ModuleForTests("service-foo", "android_common_apex1000")
|
||||||
|
|
||||||
|
entriesList := android.AndroidMkEntriesForTest(t, ctx, module.Module())
|
||||||
|
entriesList = filterDexpreoptEntriesList(entriesList)
|
||||||
|
|
||||||
|
android.AssertIntEquals(t, "entries count", 2, len(entriesList))
|
||||||
|
|
||||||
|
verifyEntries(t,
|
||||||
|
"entriesList[0]",
|
||||||
|
"service-foo-dexpreopt-arm64-apex@com.android.apex1@javalib@service-foo.jar@classes.odex",
|
||||||
|
"/dexpreopt/oat/arm64/javalib.odex",
|
||||||
|
"/system/framework/oat/arm64",
|
||||||
|
"apex@com.android.apex1@javalib@service-foo.jar@classes.odex",
|
||||||
|
entriesList[0])
|
||||||
|
|
||||||
|
verifyEntries(t,
|
||||||
|
"entriesList[1]",
|
||||||
|
"service-foo-dexpreopt-arm64-apex@com.android.apex1@javalib@service-foo.jar@classes.vdex",
|
||||||
|
"/dexpreopt/oat/arm64/javalib.vdex",
|
||||||
|
"/system/framework/oat/arm64",
|
||||||
|
"apex@com.android.apex1@javalib@service-foo.jar@classes.vdex",
|
||||||
|
entriesList[1])
|
||||||
|
|
||||||
|
// Not an APEX system server jar.
|
||||||
|
result = preparers.RunTestWithBp(t, `
|
||||||
|
java_library {
|
||||||
|
name: "foo",
|
||||||
|
installable: true,
|
||||||
|
srcs: ["a.java"],
|
||||||
|
}`)
|
||||||
|
ctx = result.TestContext
|
||||||
|
module = ctx.ModuleForTests("foo", "android_common")
|
||||||
|
|
||||||
|
entriesList = android.AndroidMkEntriesForTest(t, ctx, module.Module())
|
||||||
|
entriesList = filterDexpreoptEntriesList(entriesList)
|
||||||
|
|
||||||
|
android.AssertIntEquals(t, "entries count", 0, len(entriesList))
|
||||||
|
}
|
||||||
|
|
13
java/java.go
13
java/java.go
|
@ -487,7 +487,7 @@ func shouldUncompressDex(ctx android.ModuleContext, dexpreopter *dexpreopter) bo
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store uncompressed dex files that are preopted on /system.
|
// Store uncompressed dex files that are preopted on /system.
|
||||||
if !dexpreopter.dexpreoptDisabled(ctx) && (ctx.Host() || !odexOnSystemOther(ctx, dexpreopter.installPath)) {
|
if !dexpreopter.dexpreoptDisabled(ctx) && (ctx.Host() || !dexpreopter.odexOnSystemOther(ctx, dexpreopter.installPath)) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if ctx.Config().UncompressPrivAppDex() &&
|
if ctx.Config().UncompressPrivAppDex() &&
|
||||||
|
@ -508,7 +508,8 @@ func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
||||||
}
|
}
|
||||||
|
|
||||||
j.checkSdkVersions(ctx)
|
j.checkSdkVersions(ctx)
|
||||||
j.dexpreopter.installPath = android.PathForModuleInstall(ctx, "framework", j.Stem()+".jar")
|
j.dexpreopter.installPath = j.dexpreopter.getInstallPath(
|
||||||
|
ctx, android.PathForModuleInstall(ctx, "framework", j.Stem()+".jar"))
|
||||||
j.dexpreopter.isSDKLibrary = j.deviceProperties.IsSDKLibrary
|
j.dexpreopter.isSDKLibrary = j.deviceProperties.IsSDKLibrary
|
||||||
if j.dexProperties.Uncompress_dex == nil {
|
if j.dexProperties.Uncompress_dex == nil {
|
||||||
// If the value was not force-set by the user, use reasonable default based on the module.
|
// If the value was not force-set by the user, use reasonable default based on the module.
|
||||||
|
@ -1368,7 +1369,8 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
||||||
|
|
||||||
// Dex compilation
|
// Dex compilation
|
||||||
|
|
||||||
j.dexpreopter.installPath = android.PathForModuleInstall(ctx, "framework", jarName)
|
j.dexpreopter.installPath = j.dexpreopter.getInstallPath(
|
||||||
|
ctx, android.PathForModuleInstall(ctx, "framework", jarName))
|
||||||
if j.dexProperties.Uncompress_dex == nil {
|
if j.dexProperties.Uncompress_dex == nil {
|
||||||
// If the value was not force-set by the user, use reasonable default based on the module.
|
// If the value was not force-set by the user, use reasonable default based on the module.
|
||||||
j.dexProperties.Uncompress_dex = proptools.BoolPtr(shouldUncompressDex(ctx, &j.dexpreopter))
|
j.dexProperties.Uncompress_dex = proptools.BoolPtr(shouldUncompressDex(ctx, &j.dexpreopter))
|
||||||
|
@ -1509,7 +1511,7 @@ func (j *Import) IsInstallable() bool {
|
||||||
return Bool(j.properties.Installable)
|
return Bool(j.properties.Installable)
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ dexpreopterInterface = (*Import)(nil)
|
var _ DexpreopterInterface = (*Import)(nil)
|
||||||
|
|
||||||
// java_import imports one or more `.jar` files into the build graph as if they were built by a java_library module.
|
// java_import imports one or more `.jar` files into the build graph as if they were built by a java_library module.
|
||||||
//
|
//
|
||||||
|
@ -1622,7 +1624,8 @@ func (j *DexImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
||||||
j.hideApexVariantFromMake = true
|
j.hideApexVariantFromMake = true
|
||||||
}
|
}
|
||||||
|
|
||||||
j.dexpreopter.installPath = android.PathForModuleInstall(ctx, "framework", j.Stem()+".jar")
|
j.dexpreopter.installPath = j.dexpreopter.getInstallPath(
|
||||||
|
ctx, android.PathForModuleInstall(ctx, "framework", j.Stem()+".jar"))
|
||||||
j.dexpreopter.uncompressedDex = shouldUncompressDex(ctx, &j.dexpreopter)
|
j.dexpreopter.uncompressedDex = shouldUncompressDex(ctx, &j.dexpreopter)
|
||||||
|
|
||||||
inputJar := ctx.ExpandSource(j.properties.Jars[0], "jars")
|
inputJar := ctx.ExpandSource(j.properties.Jars[0], "jars")
|
||||||
|
|
|
@ -431,3 +431,45 @@ func CheckMergedCompatConfigInputs(t *testing.T, result *android.TestResult, mes
|
||||||
output := sourceGlobalCompatConfig.Output(allOutputs[0])
|
output := sourceGlobalCompatConfig.Output(allOutputs[0])
|
||||||
android.AssertPathsRelativeToTopEquals(t, message+": inputs", expectedPaths, output.Implicits)
|
android.AssertPathsRelativeToTopEquals(t, message+": inputs", expectedPaths, output.Implicits)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Register the fake APEX mutator to `android.InitRegistrationContext` as if the real mutator exists
|
||||||
|
// at runtime. This must be called in `init()` of a test if the test is going to use the fake APEX
|
||||||
|
// mutator. Otherwise, we will be missing the runtime mutator because "soong-apex" is not a
|
||||||
|
// dependency, which will cause an inconsistency between testing and runtime mutators.
|
||||||
|
func RegisterFakeRuntimeApexMutator() {
|
||||||
|
registerFakeApexMutator(android.InitRegistrationContext)
|
||||||
|
}
|
||||||
|
|
||||||
|
var PrepareForTestWithFakeApexMutator = android.GroupFixturePreparers(
|
||||||
|
android.FixtureRegisterWithContext(registerFakeApexMutator),
|
||||||
|
)
|
||||||
|
|
||||||
|
func registerFakeApexMutator(ctx android.RegistrationContext) {
|
||||||
|
ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
|
||||||
|
ctx.BottomUp("apex", fakeApexMutator).Parallel()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
type apexModuleBase interface {
|
||||||
|
ApexAvailable() []string
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ apexModuleBase = (*Library)(nil)
|
||||||
|
var _ apexModuleBase = (*SdkLibrary)(nil)
|
||||||
|
|
||||||
|
// A fake APEX mutator that creates a platform variant and an APEX variant for modules with
|
||||||
|
// `apex_available`. It helps us avoid a dependency on the real mutator defined in "soong-apex",
|
||||||
|
// which will cause a cyclic dependency, and it provides an easy way to create an APEX variant for
|
||||||
|
// testing without dealing with all the complexities in the real mutator.
|
||||||
|
func fakeApexMutator(mctx android.BottomUpMutatorContext) {
|
||||||
|
switch mctx.Module().(type) {
|
||||||
|
case *Library, *SdkLibrary:
|
||||||
|
if len(mctx.Module().(apexModuleBase).ApexAvailable()) > 0 {
|
||||||
|
modules := mctx.CreateVariations("", "apex1000")
|
||||||
|
apexInfo := android.ApexInfo{
|
||||||
|
ApexVariationName: "apex1000",
|
||||||
|
}
|
||||||
|
mctx.SetVariationProvider(modules[1], android.ApexInfoProvider, apexInfo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue