diff options
author | 2025-01-28 14:00:12 -0800 | |
---|---|---|
committer | 2025-02-03 22:19:24 -0800 | |
commit | 388c6618a8a4a5bedd42ffc4874e2f6663e01289 (patch) | |
tree | dc1947fc3a719fcc9bc8824eb963ec004345e878 | |
parent | 90d7df966c7c79a5d0c7380d4d3dc59bd339baad (diff) |
Move installation of dexpreopted system server classpath libraries into apex
System server jars in apexes currently use a heuristic to determine
whether or not they are the "main" variant in order to create rules
that copy their dexpreopt artifacts to the final installed location
and their dex jars to a known location for other modules to reference.
The heuristic depends on knowing all apexes that depend on the
module, which will not be possible when the apex info mutator is
rewritten to support future incremental analysis.
Instead, export the dexpreopt artifacts and dex jars, and let the
apex decide whether or not to install them.
Bug: 372543712
Test: all soong tests pass
Change-Id: I478bc2edceca4614e08e9a695b05d091e5437ba1
-rw-r--r-- | android/defs.go | 10 | ||||
-rw-r--r-- | apex/androidmk.go | 6 | ||||
-rw-r--r-- | apex/apex.go | 64 | ||||
-rw-r--r-- | apex/apex_test.go | 11 | ||||
-rw-r--r-- | apex/bootclasspath_fragment_test.go | 3 | ||||
-rw-r--r-- | apex/builder.go | 64 | ||||
-rw-r--r-- | apex/prebuilt.go | 95 | ||||
-rw-r--r-- | apex/systemserver_classpath_fragment_test.go | 2 | ||||
-rw-r--r-- | dexpreopt/dexpreopt.go | 26 | ||||
-rw-r--r-- | dexpreopt/dexpreopt_gen/dexpreopt_gen.go | 3 | ||||
-rw-r--r-- | dexpreopt/dexpreopt_test.go | 34 | ||||
-rw-r--r-- | java/androidmk.go | 6 | ||||
-rw-r--r-- | java/dexpreopt.go | 127 | ||||
-rw-r--r-- | java/dexpreopt_test.go | 130 | ||||
-rw-r--r-- | java/java.go | 11 | ||||
-rw-r--r-- | java/sdk_library.go | 14 |
16 files changed, 283 insertions, 323 deletions
diff --git a/android/defs.go b/android/defs.go index 4dd267a89..57fcc9b13 100644 --- a/android/defs.go +++ b/android/defs.go @@ -143,3 +143,13 @@ func init() { return ctx.Config().RBEWrapper() }) } + +// CopyFileRule creates a ninja rule to copy path to outPath. +func CopyFileRule(ctx ModuleContext, path Path, outPath OutputPath) { + ctx.Build(pctx, BuildParams{ + Rule: Cp, + Input: path, + Output: outPath, + Description: "copy " + outPath.Base(), + }) +} diff --git a/apex/androidmk.go b/apex/androidmk.go index ec5ca15a9..3a81ee4e6 100644 --- a/apex/androidmk.go +++ b/apex/androidmk.go @@ -226,11 +226,6 @@ func (a *apexBundle) writeRequiredModules(w io.Writer, moduleNames []string) { required = append(required, a.required...) targetRequired = append(targetRequired, a.TargetRequiredModuleNames()...) hostRequired = append(hostRequired, a.HostRequiredModuleNames()...) - for _, fi := range a.filesInfo { - required = append(required, fi.requiredModuleNames...) - targetRequired = append(targetRequired, fi.targetRequiredModuleNames...) - hostRequired = append(hostRequired, fi.hostRequiredModuleNames...) - } android.AndroidMkEmitAssignList(w, "LOCAL_REQUIRED_MODULES", moduleNames, a.makeModulesToInstall, required) android.AndroidMkEmitAssignList(w, "LOCAL_TARGET_REQUIRED_MODULES", targetRequired) android.AndroidMkEmitAssignList(w, "LOCAL_HOST_REQUIRED_MODULES", hostRequired) @@ -261,6 +256,7 @@ func (a *apexBundle) androidMkForType() android.AndroidMkData { fmt.Fprintln(w, "LOCAL_SOONG_INSTALLED_MODULE :=", a.installedFile.String()) fmt.Fprintln(w, "LOCAL_SOONG_INSTALL_PAIRS :=", a.outputFile.String()+":"+a.installedFile.String()) fmt.Fprintln(w, "LOCAL_SOONG_INSTALL_SYMLINKS := ", strings.Join(a.compatSymlinks.Strings(), " ")) + fmt.Fprintln(w, "LOCAL_SOONG_INSTALL_PAIRS +=", a.extraInstalledPairs.String()) } fmt.Fprintln(w, "LOCAL_APEX_KEY_PATH := ", a.apexKeysPath.String()) diff --git a/apex/apex.go b/apex/apex.go index d98cfae32..a3106717a 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -415,6 +415,30 @@ type overridableProperties struct { Min_sdk_version *string } +// installPair stores a path to a built object and its install location. It is used for holding +// the installation location of the dexpreopt artifacts for system server jars in apexes that need +// to be installed when the apex is installed. +type installPair struct { + from android.Path + to android.InstallPath +} + +type installPairs []installPair + +// String converts a list of installPair structs to the form accepted by LOCAL_SOONG_INSTALL_PAIRS. +func (p installPairs) String() string { + sb := &strings.Builder{} + for i, pair := range p { + if i != 0 { + sb.WriteByte(' ') + } + sb.WriteString(pair.from.String()) + sb.WriteByte(':') + sb.WriteString(pair.to.String()) + } + return sb.String() +} + type apexBundle struct { // Inherited structs android.ModuleBase @@ -496,6 +520,12 @@ type apexBundle struct { // Path where this APEX was installed. installedFile android.InstallPath + // Extra files that are installed alongside this APEX. + extraInstalledFiles android.InstallPaths + + // The source and install locations for extraInstalledFiles for use in LOCAL_SOONG_INSTALL_PAIRS. + extraInstalledPairs installPairs + // fragment for this apex for apexkeys.txt apexKeysPath android.WritablePath @@ -570,13 +600,15 @@ type apexFile struct { // Info for Android.mk Module name of `module` in AndroidMk. Note the generated AndroidMk // module for apexFile is named something like <AndroidMk module name>.<apex name>[<apex // suffix>] - androidMkModuleName string // becomes LOCAL_MODULE - class apexFileClass // becomes LOCAL_MODULE_CLASS - moduleDir string // becomes LOCAL_PATH - requiredModuleNames []string // becomes LOCAL_REQUIRED_MODULES - targetRequiredModuleNames []string // becomes LOCAL_TARGET_REQUIRED_MODULES - hostRequiredModuleNames []string // becomes LOCAL_HOST_REQUIRED_MODULES - dataPaths []android.DataPath // becomes LOCAL_TEST_DATA + androidMkModuleName string // becomes LOCAL_MODULE + class apexFileClass // becomes LOCAL_MODULE_CLASS + moduleDir string // becomes LOCAL_PATH + dataPaths []android.DataPath // becomes LOCAL_TEST_DATA + + // systemServerDexpreoptInstalls stores the list of dexpreopt artifacts for a system server jar. + systemServerDexpreoptInstalls []java.DexpreopterInstall + // systemServerDexJars stores the list of dexjars for a system server jar. + systemServerDexJars android.Paths jacocoReportClassesFile android.Path // only for javalibs and apps lintInfo *java.LintInfo // only for javalibs and apps @@ -892,6 +924,12 @@ func (a *apexBundle) DepsMutator(ctx android.BottomUpMutatorContext) { // Add a reverse dependency to all_apex_certs singleton module. // all_apex_certs will use this dependency to collect the certificate of this apex. ctx.AddReverseDependency(ctx.Module(), allApexCertsDepTag, "all_apex_certs") + + // TODO: When all branches contain this singleton module, make this strict + // TODO: Add this dependency only for mainline prebuilts and not every prebuilt module + if ctx.OtherModuleExists("all_apex_contributions") { + ctx.AddDependency(ctx.Module(), android.AcDepTag, "all_apex_contributions") + } } type allApexCertsDependencyTag struct { @@ -1501,16 +1539,15 @@ func apexFileForJavaModuleWithFile(ctx android.ModuleContext, module javaModule, af.lintInfo = lintInfo } af.customStem = module.Stem() + ".jar" + // Collect any system server dex jars and dexpreopt artifacts for installation alongside the apex. // TODO: b/338641779 - Remove special casing of sdkLibrary once bcpf and sscpf depends // on the implementation library if sdkLib, ok := module.(*java.SdkLibrary); ok { - for _, install := range sdkLib.BuiltInstalledForApex() { - af.requiredModuleNames = append(af.requiredModuleNames, install.FullModuleName()) - } + af.systemServerDexpreoptInstalls = append(af.systemServerDexpreoptInstalls, sdkLib.ApexSystemServerDexpreoptInstalls()...) + af.systemServerDexJars = append(af.systemServerDexJars, sdkLib.ApexSystemServerDexJars()...) } else if dexpreopter, ok := module.(java.DexpreopterInterface); ok { - for _, install := range dexpreopter.DexpreoptBuiltInstalledForApex() { - af.requiredModuleNames = append(af.requiredModuleNames, install.FullModuleName()) - } + af.systemServerDexpreoptInstalls = append(af.systemServerDexpreoptInstalls, dexpreopter.ApexSystemServerDexpreoptInstalls()...) + af.systemServerDexJars = append(af.systemServerDexJars, dexpreopter.ApexSystemServerDexJars()...) } return af } @@ -2258,6 +2295,7 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) { //////////////////////////////////////////////////////////////////////////////////////////// // 4) generate the build rules to create the APEX. This is done in builder.go. a.buildManifest(ctx, vctx.provideNativeLibs, vctx.requireNativeLibs) + a.installApexSystemServerFiles(ctx) a.buildApex(ctx) a.buildApexDependencyInfo(ctx) a.buildLintReports(ctx) diff --git a/apex/apex_test.go b/apex/apex_test.go index a5b66c10e..1382f6903 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -9803,7 +9803,16 @@ func TestAndroidMk_DexpreoptBuiltInstalledForApex(t *testing.T) { var builder strings.Builder data.Custom(&builder, apexBundle.BaseModuleName(), "TARGET_", "", data) androidMk := builder.String() - ensureContains(t, androidMk, "LOCAL_REQUIRED_MODULES := foo.myapex foo-dexpreopt-arm64-apex@myapex@javalib@foo.jar@classes.odex foo-dexpreopt-arm64-apex@myapex@javalib@foo.jar@classes.vdex\n") + out := ctx.Config().OutDir() + ensureContains(t, androidMk, "LOCAL_SOONG_INSTALL_PAIRS += "+ + filepath.Join(out, "soong/.intermediates/foo/android_common_apex10000/dexpreopt/foo/oat/arm64/javalib.odex")+ + ":"+ + filepath.Join(out, "target/product/test_device/system/framework/oat/arm64/apex@myapex@javalib@foo.jar@classes.odex")+ + " "+ + filepath.Join(out, "soong/.intermediates/foo/android_common_apex10000/dexpreopt/foo/oat/arm64/javalib.vdex")+ + ":"+ + filepath.Join(out, "target/product/test_device/system/framework/oat/arm64/apex@myapex@javalib@foo.jar@classes.vdex")+ + "\n") } func TestAndroidMk_RequiredModules(t *testing.T) { diff --git a/apex/bootclasspath_fragment_test.go b/apex/bootclasspath_fragment_test.go index 71a8246a7..d0bff625d 100644 --- a/apex/bootclasspath_fragment_test.go +++ b/apex/bootclasspath_fragment_test.go @@ -320,6 +320,7 @@ func TestBootclasspathFragmentInArtApex(t *testing.T) { }) java.CheckModuleDependencies(t, result.TestContext, "com.android.art", "android_common_com.android.art", []string{ + `all_apex_contributions`, `art-bootclasspath-fragment`, `com.android.art.key`, `dex2oatd`, @@ -425,6 +426,7 @@ func TestBootclasspathFragmentInArtApex(t *testing.T) { }) java.CheckModuleDependencies(t, result.TestContext, "com.android.art", "android_common_com.android.art", []string{ + `all_apex_contributions`, `art-bootclasspath-fragment`, `com.android.art.key`, `dex2oatd`, @@ -698,6 +700,7 @@ func TestBootclasspathFragmentContentsNoName(t *testing.T) { }) java.CheckModuleDependencies(t, result.TestContext, "myapex", "android_common_myapex", []string{ + `all_apex_contributions`, `dex2oatd`, `myapex.key`, `mybootclasspathfragment`, diff --git a/apex/builder.go b/apex/builder.go index b3174727f..31d8557f8 100644 --- a/apex/builder.go +++ b/apex/builder.go @@ -20,12 +20,14 @@ import ( "path" "path/filepath" "runtime" + "slices" "sort" "strconv" "strings" "android/soong/aconfig" "android/soong/android" + "android/soong/dexpreopt" "android/soong/java" "github.com/google/blueprint" @@ -542,6 +544,64 @@ func runAssembleVintf(ctx android.ModuleContext, vintfFragment android.Path) and return processed } +// installApexSystemServerFiles installs dexpreopt and dexjar files for system server classpath entries +// provided by the apex. They are installed here instead of in library module because there may be multiple +// variants of the library, generally one for the "main" apex and another with a different min_sdk_version +// for the Android Go version of the apex. Both variants would attempt to install to the same locations, +// and the library variants cannot determine which one should. The apex module is better equipped to determine +// if it is "selected". +// This assumes that the jars produced by different min_sdk_version values are identical, which is currently +// true but may not be true if the min_sdk_version difference between the variants spans version that changed +// the dex format. +func (a *apexBundle) installApexSystemServerFiles(ctx android.ModuleContext) { + // If performInstalls is set this module is responsible for creating the install rules. + performInstalls := a.GetOverriddenBy() == "" && !a.testApex && a.installable() + // TODO(b/234351700): Remove once ART does not have separated debug APEX, or make the selection + // explicit in the ART Android.bp files. + if ctx.Config().UseDebugArt() { + if ctx.ModuleName() == "com.android.art" { + performInstalls = false + } + } else { + if ctx.ModuleName() == "com.android.art.debug" { + performInstalls = false + } + } + + psi := android.PrebuiltSelectionInfoMap{} + ctx.VisitDirectDeps(func(am android.Module) { + if info, exists := android.OtherModuleProvider(ctx, am, android.PrebuiltSelectionInfoProvider); exists { + psi = info + } + }) + + if len(psi.GetSelectedModulesForApiDomain(ctx.ModuleName())) > 0 { + performInstalls = false + } + + for _, fi := range a.filesInfo { + for _, install := range fi.systemServerDexpreoptInstalls { + var installedFile android.InstallPath + if performInstalls { + installedFile = ctx.InstallFile(install.InstallDirOnDevice, install.InstallFileOnDevice, install.OutputPathOnHost) + } else { + // Another module created the install rules, but this module should still depend on + // the installed locations. + installedFile = install.InstallDirOnDevice.Join(ctx, install.InstallFileOnDevice) + } + a.extraInstalledFiles = append(a.extraInstalledFiles, installedFile) + a.extraInstalledPairs = append(a.extraInstalledPairs, installPair{install.OutputPathOnHost, installedFile}) + } + if performInstalls { + for _, dexJar := range fi.systemServerDexJars { + // Copy the system server dex jar to a predefined location where dex2oat will find it. + android.CopyFileRule(ctx, dexJar, + android.PathForOutput(ctx, dexpreopt.SystemServerDexjarsDir, dexJar.Base())) + } + } + } +} + // buildApex creates build rules to build an APEX using apexer. func (a *apexBundle) buildApex(ctx android.ModuleContext) { suffix := imageApexSuffix @@ -985,9 +1045,9 @@ func (a *apexBundle) buildApex(ctx android.ModuleContext) { a.SkipInstall() } + installDeps := slices.Concat(a.compatSymlinks, a.extraInstalledFiles) // Install to $OUT/soong/{target,host}/.../apex. - a.installedFile = ctx.InstallFile(a.installDir, a.Name()+installSuffix, a.outputFile, - a.compatSymlinks...) + a.installedFile = ctx.InstallFile(a.installDir, a.Name()+installSuffix, a.outputFile, installDeps...) // installed-files.txt is dist'ed a.installedFilesFile = a.buildInstalledFilesFile(ctx, a.outputFile, imageDir) diff --git a/apex/prebuilt.go b/apex/prebuilt.go index aaf2cb77d..4fa43bada 100644 --- a/apex/prebuilt.go +++ b/apex/prebuilt.go @@ -15,6 +15,7 @@ package apex import ( + "slices" "strconv" "strings" @@ -59,10 +60,12 @@ type prebuiltCommon struct { // Properties common to both prebuilt_apex and apex_set. prebuiltCommonProperties *PrebuiltCommonProperties - installDir android.InstallPath - installFilename string - installedFile android.InstallPath - outputApex android.WritablePath + installDir android.InstallPath + installFilename string + installedFile android.InstallPath + extraInstalledFiles android.InstallPaths + extraInstalledPairs installPairs + outputApex android.WritablePath // fragment for this apex for apexkeys.txt apexKeysPath android.WritablePath @@ -70,8 +73,12 @@ type prebuiltCommon struct { // Installed locations of symlinks for backward compatibility. compatSymlinks android.InstallPaths - hostRequired []string - requiredModuleNames []string + // systemServerDexpreoptInstalls stores the list of dexpreopt artifacts for a system server jar. + systemServerDexpreoptInstalls []java.DexpreopterInstall + + // systemServerDexJars stores the list of dexjars for system server jars in the prebuilt for use when + // dexpreopting system server jars that are later in the system server classpath. + systemServerDexJars android.Paths } type sanitizedPrebuilt interface { @@ -188,9 +195,8 @@ func (p *prebuiltCommon) IsInstallable() bool { // initApexFilesForAndroidMk initializes the prebuiltCommon.requiredModuleNames field with the install only deps of the prebuilt apex func (p *prebuiltCommon) initApexFilesForAndroidMk(ctx android.ModuleContext) { // 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()) - } + p.systemServerDexpreoptInstalls = append(p.systemServerDexpreoptInstalls, p.Dexpreopter.ApexSystemServerDexpreoptInstalls()...) + p.systemServerDexJars = append(p.systemServerDexJars, p.Dexpreopter.ApexSystemServerDexJars()...) } // If this prebuilt has system server jar, create the rules to dexpreopt it and install it alongside the prebuilt apex @@ -218,38 +224,58 @@ func (p *prebuiltCommon) dexpreoptSystemServerJars(ctx android.ModuleContext, di } } -func (p *prebuiltCommon) addRequiredModules(entries *android.AndroidMkEntries) { - entries.AddStrings("LOCAL_REQUIRED_MODULES", p.requiredModuleNames...) +// installApexSystemServerFiles installs dexpreopt files for system server classpath entries +// provided by the apex. They are installed here instead of in library module because there may be multiple +// variants of the library, generally one for the "main" apex and another with a different min_sdk_version +// for the Android Go version of the apex. Both variants would attempt to install to the same locations, +// and the library variants cannot determine which one should. The apex module is better equipped to determine +// if it is "selected". +// This assumes that the jars produced by different min_sdk_version values are identical, which is currently +// true but may not be true if the min_sdk_version difference between the variants spans version that changed +// the dex format. +func (p *prebuiltCommon) installApexSystemServerFiles(ctx android.ModuleContext) { + performInstalls := android.IsModulePreferred(ctx.Module()) + + for _, install := range p.systemServerDexpreoptInstalls { + var installedFile android.InstallPath + if performInstalls { + installedFile = ctx.InstallFile(install.InstallDirOnDevice, install.InstallFileOnDevice, install.OutputPathOnHost) + } else { + installedFile = install.InstallDirOnDevice.Join(ctx, install.InstallFileOnDevice) + } + p.extraInstalledFiles = append(p.extraInstalledFiles, installedFile) + p.extraInstalledPairs = append(p.extraInstalledPairs, installPair{install.OutputPathOnHost, installedFile}) + } + + for _, dexJar := range p.systemServerDexJars { + // Copy the system server dex jar to a predefined location where dex2oat will find it. + android.CopyFileRule(ctx, dexJar, + android.PathForOutput(ctx, dexpreopt.SystemServerDexjarsDir, dexJar.Base())) + } } func (p *prebuiltCommon) AndroidMkEntries() []android.AndroidMkEntries { entriesList := []android.AndroidMkEntries{ { - Class: "ETC", - OutputFile: android.OptionalPathForPath(p.outputApex), - Include: "$(BUILD_PREBUILT)", - Host_required: p.hostRequired, + Class: "ETC", + OutputFile: android.OptionalPathForPath(p.outputApex), + Include: "$(BUILD_PREBUILT)", 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()) + installPairs := append(installPairs{{p.outputApex, p.installedFile}}, p.extraInstalledPairs...) + entries.SetString("LOCAL_SOONG_INSTALL_PAIRS", installPairs.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()) - } - return entriesList } @@ -679,7 +705,9 @@ func (p *Prebuilt) GenerateAndroidBuildActions(ctx android.ModuleContext) { } if p.installable() { - p.installedFile = ctx.InstallFile(p.installDir, p.installFilename, p.inputApex, p.compatSymlinks...) + p.installApexSystemServerFiles(ctx) + installDeps := slices.Concat(p.compatSymlinks, p.extraInstalledFiles) + p.installedFile = ctx.InstallFile(p.installDir, p.installFilename, p.inputApex, installDeps...) p.provenanceMetaDataFile = provenance.GenerateArtifactProvenanceMetaData(ctx, p.inputApex, p.installedFile) } @@ -690,16 +718,6 @@ func (p *Prebuilt) ProvenanceMetaDataFile() android.Path { return p.provenanceMetaDataFile } -// prebuiltApexExtractorModule is a private module type that is only created by the prebuilt_apex -// module. It extracts the correct apex to use and makes it available for use by apex_set. -type prebuiltApexExtractorModule struct { - android.ModuleBase - - properties ApexExtractorProperties - - extractedApex android.WritablePath -} - // extract registers the build actions to extract an apex from .apks file // returns the path of the extracted apex func extract(ctx android.ModuleContext, apexSet android.Path, prerelease *bool) android.Path { @@ -866,7 +884,8 @@ func (a *ApexSet) GenerateAndroidBuildActions(ctx android.ModuleContext) { a.installDir = android.PathForModuleInstall(ctx, "apex") if a.installable() { - a.installedFile = ctx.InstallFile(a.installDir, a.installFilename, a.outputApex) + a.installApexSystemServerFiles(ctx) + a.installedFile = ctx.InstallFile(a.installDir, a.installFilename, a.outputApex, a.extraInstalledFiles...) } // in case that apex_set replaces source apex (using prefer: prop) @@ -878,11 +897,3 @@ func (a *ApexSet) GenerateAndroidBuildActions(ctx android.ModuleContext) { ctx.SetOutputFiles(android.Paths{a.outputApex}, "") } - -type systemExtContext struct { - android.ModuleContext -} - -func (*systemExtContext) SystemExtSpecific() bool { - return true -} diff --git a/apex/systemserver_classpath_fragment_test.go b/apex/systemserver_classpath_fragment_test.go index 7dbac5fde..c643a8c98 100644 --- a/apex/systemserver_classpath_fragment_test.go +++ b/apex/systemserver_classpath_fragment_test.go @@ -108,6 +108,7 @@ func TestSystemserverclasspathFragmentContents(t *testing.T) { }) java.CheckModuleDependencies(t, ctx, "myapex", "android_common_myapex", []string{ + `all_apex_contributions`, `dex2oatd`, `myapex.key`, `mysystemserverclasspathfragment`, @@ -166,6 +167,7 @@ func TestSystemserverclasspathFragmentNoGeneratedProto(t *testing.T) { }) java.CheckModuleDependencies(t, result.TestContext, "myapex", "android_common_myapex", []string{ + `all_apex_contributions`, `dex2oatd`, `myapex.key`, `mysystemserverclasspathfragment`, diff --git a/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go index 7a39fa1d7..e882470ac 100644 --- a/dexpreopt/dexpreopt.go +++ b/dexpreopt/dexpreopt.go @@ -46,13 +46,14 @@ import ( const SystemPartition = "/system/" const SystemOtherPartition = "/system_other/" +const SystemServerDexjarsDir = "system_server_dexjars" var DexpreoptRunningInSoong = false // GenerateDexpreoptRule generates a set of commands that will preopt a module based on a GlobalConfig and a // ModuleConfig. The produced files and their install locations will be available through rule.Installs(). func GenerateDexpreoptRule(ctx android.BuilderContext, globalSoong *GlobalSoongConfig, - global *GlobalConfig, module *ModuleConfig, productPackages android.Path, copyApexSystemServerJarDex bool) ( + global *GlobalConfig, module *ModuleConfig, productPackages android.Path) ( rule *android.RuleBuilder, err error) { defer func() { @@ -83,7 +84,7 @@ func GenerateDexpreoptRule(ctx android.BuilderContext, globalSoong *GlobalSoongC if !dexpreoptDisabled(ctx, global, module) { if valid, err := validateClassLoaderContext(module.ClassLoaderContexts); err != nil { - android.ReportPathErrorf(ctx, err.Error()) + android.ReportPathErrorf(ctx, "%s", err.Error()) } else if valid { fixClassLoaderContext(module.ClassLoaderContexts) @@ -94,7 +95,7 @@ func GenerateDexpreoptRule(ctx android.BuilderContext, globalSoong *GlobalSoongC for archIdx, _ := range module.Archs { dexpreoptCommand(ctx, globalSoong, global, module, rule, archIdx, profile, appImage, - generateDM, productPackages, copyApexSystemServerJarDex) + generateDM, productPackages) } } } @@ -231,7 +232,7 @@ func ToOdexPath(path string, arch android.ArchType, partition string) string { func dexpreoptCommand(ctx android.BuilderContext, globalSoong *GlobalSoongConfig, global *GlobalConfig, module *ModuleConfig, rule *android.RuleBuilder, archIdx int, - profile android.WritablePath, appImage bool, generateDM bool, productPackages android.Path, copyApexSystemServerJarDex bool) { + profile android.WritablePath, appImage bool, generateDM bool, productPackages android.Path) { arch := module.Archs[archIdx] @@ -279,19 +280,6 @@ func dexpreoptCommand(ctx android.BuilderContext, globalSoong *GlobalSoongConfig clcTarget = append(clcTarget, GetSystemServerDexLocation(ctx, global, lib)) } - if DexpreoptRunningInSoong && copyApexSystemServerJarDex { - // Copy the system server jar to a predefined location where dex2oat will find it. - dexPathHost := SystemServerDexJarHostPath(ctx, module.Name) - rule.Command().Text("mkdir -p").Flag(filepath.Dir(dexPathHost.String())) - rule.Command().Text("cp -f").Input(module.DexPath).Output(dexPathHost) - } else { - // For Make modules the copy rule is generated in the makefiles, not in dexpreopt.sh. - // This is necessary to expose the rule to Ninja, otherwise it has rules that depend on - // the jar (namely, dexpreopt commands for all subsequent system server jars that have - // this one in their class loader context), but no rule that creates it (because Ninja - // cannot see the rule in the generated dexpreopt.sh script). - } - clcHostString := "PCL[" + strings.Join(clcHost.Strings(), ":") + "]" clcTargetString := "PCL[" + strings.Join(clcTarget, ":") + "]" @@ -581,11 +569,11 @@ func makefileMatch(pattern, s string) bool { func SystemServerDexJarHostPath(ctx android.PathContext, jar string) android.OutputPath { if DexpreoptRunningInSoong { // Soong module, just use the default output directory $OUT/soong. - return android.PathForOutput(ctx, "system_server_dexjars", jar+".jar") + return android.PathForOutput(ctx, SystemServerDexjarsDir, jar+".jar") } else { // Make module, default output directory is $OUT (passed via the "null config" created // by dexpreopt_gen). Append Soong subdirectory to match Soong module paths. - return android.PathForOutput(ctx, "soong", "system_server_dexjars", jar+".jar") + return android.PathForOutput(ctx, "soong", SystemServerDexjarsDir, jar+".jar") } } diff --git a/dexpreopt/dexpreopt_gen/dexpreopt_gen.go b/dexpreopt/dexpreopt_gen/dexpreopt_gen.go index 75120052e..8033b48e5 100644 --- a/dexpreopt/dexpreopt_gen/dexpreopt_gen.go +++ b/dexpreopt/dexpreopt_gen/dexpreopt_gen.go @@ -205,9 +205,8 @@ func writeScripts(ctx android.BuilderContext, globalSoong *dexpreopt.GlobalSoong panic(err) } } - cpApexSscpServerJar := false // dexpreopt_gen operates on make modules, and since sscp libraries are in soong, this should be a noop dexpreoptRule, err := dexpreopt.GenerateDexpreoptRule( - ctx, globalSoong, global, module, android.PathForTesting(productPackagesPath), cpApexSscpServerJar) + ctx, globalSoong, global, module, android.PathForTesting(productPackagesPath)) if err != nil { panic(err) } diff --git a/dexpreopt/dexpreopt_test.go b/dexpreopt/dexpreopt_test.go index 1f188d500..f9b8880f5 100644 --- a/dexpreopt/dexpreopt_test.go +++ b/dexpreopt/dexpreopt_test.go @@ -104,7 +104,7 @@ func TestDexPreopt(t *testing.T) { module := testSystemModuleConfig(ctx, "test") productPackages := android.PathForTesting("product_packages.txt") - rule, err := GenerateDexpreoptRule(ctx, globalSoong, global, module, productPackages, true) + rule, err := GenerateDexpreoptRule(ctx, globalSoong, global, module, productPackages) if err != nil { t.Fatal(err) } @@ -164,7 +164,7 @@ func TestDexPreoptSystemOther(t *testing.T) { for _, test := range tests { global.PatternsOnSystemOther = test.patterns for _, mt := range test.moduleTests { - rule, err := GenerateDexpreoptRule(ctx, globalSoong, global, mt.module, productPackages, true) + rule, err := GenerateDexpreoptRule(ctx, globalSoong, global, mt.module, productPackages) if err != nil { t.Fatal(err) } @@ -199,7 +199,7 @@ func TestDexPreoptApexSystemServerJars(t *testing.T) { global.ApexSystemServerJars = android.CreateTestConfiguredJarList( []string{"com.android.apex1:service-A"}) - rule, err := GenerateDexpreoptRule(ctx, globalSoong, global, module, productPackages, true) + rule, err := GenerateDexpreoptRule(ctx, globalSoong, global, module, productPackages) if err != nil { t.Fatal(err) } @@ -211,15 +211,6 @@ func TestDexPreoptApexSystemServerJars(t *testing.T) { android.AssertStringEquals(t, "installs", wantInstalls.String(), rule.Installs().String()) - android.AssertStringListContains(t, "apex sscp jar copy", rule.Outputs().Strings(), "out/soong/system_server_dexjars/service-A.jar") - - // rule with apex sscp cp as false - rule, err = GenerateDexpreoptRule(ctx, globalSoong, global, module, productPackages, false) - if err != nil { - t.Fatal(err) - } - android.AssertStringListDoesNotContain(t, "apex sscp jar copy", rule.Outputs().Strings(), "out/soong/system_server_dexjars/service-A.jar") - // cleanup the global variable for test DexpreoptRunningInSoong = oldDexpreoptRunningInSoong } @@ -242,7 +233,7 @@ func TestDexPreoptApexSystemServerJarsSystemExt(t *testing.T) { global.ApexSystemServerJars = android.CreateTestConfiguredJarList( []string{"com.android.apex1:service-A"}) - rule, err := GenerateDexpreoptRule(ctx, globalSoong, global, module, productPackages, true) + rule, err := GenerateDexpreoptRule(ctx, globalSoong, global, module, productPackages) if err != nil { t.Fatal(err) } @@ -254,15 +245,6 @@ func TestDexPreoptApexSystemServerJarsSystemExt(t *testing.T) { android.AssertStringEquals(t, "installs", wantInstalls.String(), rule.Installs().String()) - android.AssertStringListContains(t, "apex sscp jar copy", rule.Outputs().Strings(), "out/soong/system_server_dexjars/service-A.jar") - - // rule with apex sscp cp as false - rule, err = GenerateDexpreoptRule(ctx, globalSoong, global, module, productPackages, false) - if err != nil { - t.Fatal(err) - } - android.AssertStringListDoesNotContain(t, "apex sscp jar copy", rule.Outputs().Strings(), "out/soong/system_server_dexjars/service-A.jar") - // cleanup the global variable for test DexpreoptRunningInSoong = oldDexpreoptRunningInSoong } @@ -278,7 +260,7 @@ func TestDexPreoptStandaloneSystemServerJars(t *testing.T) { global.StandaloneSystemServerJars = android.CreateTestConfiguredJarList( []string{"platform:service-A"}) - rule, err := GenerateDexpreoptRule(ctx, globalSoong, global, module, productPackages, true) + rule, err := GenerateDexpreoptRule(ctx, globalSoong, global, module, productPackages) if err != nil { t.Fatal(err) } @@ -302,7 +284,7 @@ func TestDexPreoptSystemExtSystemServerJars(t *testing.T) { global.StandaloneSystemServerJars = android.CreateTestConfiguredJarList( []string{"system_ext:service-A"}) - rule, err := GenerateDexpreoptRule(ctx, globalSoong, global, module, productPackages, true) + rule, err := GenerateDexpreoptRule(ctx, globalSoong, global, module, productPackages) if err != nil { t.Fatal(err) } @@ -326,7 +308,7 @@ func TestDexPreoptApexStandaloneSystemServerJars(t *testing.T) { global.ApexStandaloneSystemServerJars = android.CreateTestConfiguredJarList( []string{"com.android.apex1:service-A"}) - rule, err := GenerateDexpreoptRule(ctx, globalSoong, global, module, productPackages, true) + rule, err := GenerateDexpreoptRule(ctx, globalSoong, global, module, productPackages) if err != nil { t.Fatal(err) } @@ -349,7 +331,7 @@ func TestDexPreoptProfile(t *testing.T) { module.ProfileClassListing = android.OptionalPathForPath(android.PathForTesting("profile")) - rule, err := GenerateDexpreoptRule(ctx, globalSoong, global, module, productPackages, true) + rule, err := GenerateDexpreoptRule(ctx, globalSoong, global, module, productPackages) if err != nil { t.Fatal(err) } diff --git a/java/androidmk.go b/java/androidmk.go index fe3c7a217..f069e7590 100644 --- a/java/androidmk.go +++ b/java/androidmk.go @@ -70,11 +70,7 @@ func (library *Library) AndroidMkEntries() []android.AndroidMkEntries { if library.hideApexVariantFromMake { // 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...) - } + // makefile. entriesList = append(entriesList, android.AndroidMkEntries{Disabled: true}) } else if !library.ApexModuleBase.AvailableFor(android.AvailableToPlatform) { // Platform variant. If not available for the platform, we don't need Make module. diff --git a/java/dexpreopt.go b/java/dexpreopt.go index f52ce5d10..15e40ba0d 100644 --- a/java/dexpreopt.go +++ b/java/dexpreopt.go @@ -36,69 +36,24 @@ type DexpreopterInterface interface { // If the java module is to be installed into an APEX, this list contains information about the // dexpreopt outputs to be installed on devices. Note that these dexpreopt outputs are installed // outside of the APEX. - DexpreoptBuiltInstalledForApex() []dexpreopterInstall + ApexSystemServerDexpreoptInstalls() []DexpreopterInstall - // The Make entries to install the dexpreopt outputs. Derived from - // `DexpreoptBuiltInstalledForApex`. - AndroidMkEntriesForApex() []android.AndroidMkEntries + // ApexSystemServerDexJars returns the list of dex jars if this is an apex system server jar. + ApexSystemServerDexJars() android.Paths // See `dexpreopter.outputProfilePathOnHost`. OutputProfilePathOnHost() android.Path } -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 - +type DexpreopterInstall struct { // The path to the dexpreopt output on host. - outputPathOnHost android.Path + OutputPathOnHost android.Path // The directory on the device for the output to install to. - installDirOnDevice android.InstallPath + 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 -} - -// Returns Make entries for installing the file. -// -// This function uses a value receiver rather than a pointer receiver to ensure that the object is -// safe to use in `android.AndroidMkExtraEntriesFunc`. -func (install dexpreopterInstall) ToMakeEntries() android.AndroidMkEntries { - return android.AndroidMkEntries{ - OverrideName: install.FullModuleName(), - Class: "ETC", - OutputFile: android.OptionalPathForPath(install.outputPathOnHost), - ExtraEntries: []android.AndroidMkExtraEntriesFunc{ - func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) { - entries.SetString("LOCAL_MODULE_PATH", install.installDirOnDevice.String()) - entries.SetString("LOCAL_INSTALLED_MODULE_STEM", install.installFileOnDevice) - entries.SetString("LOCAL_NOT_AVAILABLE_FOR_PLATFORM", "false") - }, - }, - } -} - -func (install dexpreopterInstall) AddModuleInfoJSONForApex(ctx android.ModuleContext) { - moduleInfoJSON := ctx.ExtraModuleInfoJSON() - moduleInfoJSON.RegisterNameOverride = install.FullModuleName() - moduleInfoJSON.ModuleNameOverride = install.FullModuleName() - moduleInfoJSON.Class = []string{"ETC"} - moduleInfoJSON.SystemSharedLibs = []string{"none"} + InstallFileOnDevice string } type Dexpreopter struct { @@ -128,8 +83,9 @@ type dexpreopter struct { classLoaderContexts dexpreopt.ClassLoaderContextMap // See the `dexpreopt` function for details. - builtInstalled string - builtInstalledForApex []dexpreopterInstall + builtInstalled string + apexSystemServerDexpreoptInstalls []DexpreopterInstall + apexSystemServerDexJars android.Paths // The config is used for two purposes: // - Passing dexpreopt information about libraries from Soong to Make. This is needed when @@ -286,20 +242,6 @@ func (d *dexpreopter) dexpreoptDisabled(ctx android.BaseModuleContext, libName s if !isApexSystemServerJar { return true } - ai, _ := android.ModuleProvider(ctx, android.ApexInfoProvider) - allApexInfos := []android.ApexInfo{} - if allApexInfosProvider, ok := android.ModuleProvider(ctx, android.AllApexInfoProvider); ok { - allApexInfos = allApexInfosProvider.ApexInfos - } - if len(allApexInfos) > 0 && !ai.MinSdkVersion.EqualTo(allApexInfos[0].MinSdkVersion) { - // Apex system server jars are dexpreopted and installed on to the system image. - // Since we can have BigAndroid and Go variants of system server jar providing apexes, - // and these two variants can have different min_sdk_versions, hide one of the apex variants - // from make to prevent collisions. - // - // Unlike cc, min_sdk_version does not have an effect on the build actions of java libraries. - ctx.Module().MakeUninstallable() - } } else { // Don't preopt the platform variant of an APEX system server jar to avoid conflicts. if isApexSystemServerJar { @@ -550,12 +492,8 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, libName string, dexJa Output(appProductPackages) productPackagesRule.Restat().Build("product_packages."+dexJarStem, "dexpreopt product_packages") - // Prebuilts are active, do not copy the dexpreopt'd source javalib to out/soong/system_server_dexjars - // The javalib from the deapexed prebuilt will be copied to this location. - // TODO (b/331665856): Implement a principled solution for this. - copyApexSystemServerJarDex := !disableSourceApexVariant(ctx) && !ctx.Module().IsHideFromMake() dexpreoptRule, err := dexpreopt.GenerateDexpreoptRule( - ctx, globalSoong, global, dexpreoptConfig, appProductPackages, copyApexSystemServerJarDex) + ctx, globalSoong, global, dexpreoptConfig, appProductPackages) if err != nil { ctx.ModuleErrorf("error generating dexpreopt rule: %s", err.Error()) return @@ -588,7 +526,6 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, libName string, dexJa partition = "" } installBase := filepath.Base(install.To) - arch := filepath.Base(installDir) installPath := android.PathForModuleInPartitionInstall(ctx, partition, installDir) isProfile := strings.HasSuffix(installBase, ".prof") @@ -604,16 +541,13 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, libName string, dexJa // 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. - // The installs will be handled by Make as sub-modules of the java library. - di := dexpreopterInstall{ - name: arch + "-" + installBase, - moduleName: libName, - outputPathOnHost: install.From, - installDirOnDevice: installPath, - installFileOnDevice: installBase, + // The installs will be handled the apex module that includes this library. + di := DexpreopterInstall{ + OutputPathOnHost: install.From, + InstallDirOnDevice: installPath, + InstallFileOnDevice: installBase, } - ctx.InstallFile(di.installDirOnDevice, di.installFileOnDevice, di.outputPathOnHost) - d.builtInstalledForApex = append(d.builtInstalledForApex, di) + d.apexSystemServerDexpreoptInstalls = append(d.apexSystemServerDexpreoptInstalls, di) } } else if !d.preventInstall { @@ -622,6 +556,15 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, libName string, dexJa } } + if isApexSystemServerJar { + // Store the dex jar location for system server jars in apexes, the apex will copy the file into + // a known location for dex2oat. + d.apexSystemServerDexJars = append(d.apexSystemServerDexJars, dexJarFile) + } else if isSystemServerJar && !d.preventInstall { + // Copy the dex jar into a known location for dex2oat for non-apex system server jars. + android.CopyFileRule(ctx, dexJarFile, android.PathForOutput(ctx, dexpreopt.SystemServerDexjarsDir, dexJarFile.Base())) + } + if !isApexSystemServerJar { d.builtInstalled = dexpreoptRule.Installs().String() } @@ -656,22 +599,12 @@ func installFile(ctx android.ModuleContext, install android.RuleBuilderInstall) } } -func (d *dexpreopter) DexpreoptBuiltInstalledForApex() []dexpreopterInstall { - return d.builtInstalledForApex +func (d *dexpreopter) ApexSystemServerDexpreoptInstalls() []DexpreopterInstall { + return d.apexSystemServerDexpreoptInstalls } -func (d *dexpreopter) AndroidMkEntriesForApex() []android.AndroidMkEntries { - var entries []android.AndroidMkEntries - for _, install := range d.builtInstalledForApex { - entries = append(entries, install.ToMakeEntries()) - } - return entries -} - -func (d *dexpreopter) ModuleInfoJSONForApex(ctx android.ModuleContext) { - for _, install := range d.builtInstalledForApex { - install.AddModuleInfoJSONForApex(ctx) - } +func (d *dexpreopter) ApexSystemServerDexJars() android.Paths { + return d.apexSystemServerDexJars } func (d *dexpreopter) OutputProfilePathOnHost() android.Path { diff --git a/java/dexpreopt_test.go b/java/dexpreopt_test.go index 53a0d71fd..bf660475f 100644 --- a/java/dexpreopt_test.go +++ b/java/dexpreopt_test.go @@ -17,7 +17,6 @@ package java import ( "fmt" "runtime" - "strings" "testing" "android/soong/android" @@ -309,7 +308,7 @@ func TestDex2oatToolDeps(t *testing.T) { testDex2oatToolDep(false, true, false, prebuiltDex2oatPath) } -func TestDexpreoptBuiltInstalledForApex(t *testing.T) { +func TestApexSystemServerDexpreoptInstalls(t *testing.T) { preparers := android.GroupFixturePreparers( PrepareForTestWithDexpreopt, PrepareForTestWithFakeApexMutator, @@ -329,114 +328,35 @@ func TestDexpreoptBuiltInstalledForApex(t *testing.T) { module := ctx.ModuleForTests("service-foo", "android_common_apex1000") library := module.Module().(*Library) - installs := library.dexpreopter.DexpreoptBuiltInstalledForApex() + installs := library.dexpreopter.ApexSystemServerDexpreoptInstalls() + dexJars := library.dexpreopter.ApexSystemServerDexJars() android.AssertIntEquals(t, "install count", 2, len(installs)) + android.AssertIntEquals(t, "dexjar count", 1, len(dexJars)) - android.AssertStringEquals(t, "installs[0] FullModuleName", - "service-foo-dexpreopt-arm64-apex@com.android.apex1@javalib@service-foo.jar@classes.odex", - installs[0].FullModuleName()) + android.AssertPathRelativeToTopEquals(t, "installs[0] OutputPathOnHost", + "out/soong/.intermediates/service-foo/android_common_apex1000/dexpreopt/service-foo/oat/arm64/javalib.odex", + installs[0].OutputPathOnHost) - android.AssertStringEquals(t, "installs[0] SubModuleName", - "-dexpreopt-arm64-apex@com.android.apex1@javalib@service-foo.jar@classes.odex", - installs[0].SubModuleName()) + android.AssertPathRelativeToTopEquals(t, "installs[0] InstallDirOnDevice", + "out/target/product/test_device/system/framework/oat/arm64", + installs[0].InstallDirOnDevice) - 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"], - sdk_version: "current", - }`) - 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( - PrepareForTestWithDexpreopt, - 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"], - sdk_version: "current", - }`) - ctx := result.TestContext - module := ctx.ModuleForTests("service-foo", "android_common_apex1000") - - entriesList := android.AndroidMkEntriesForTest(t, ctx, module.Module()) - entriesList = filterDexpreoptEntriesList(entriesList) + android.AssertStringEquals(t, "installs[0] InstallFileOnDevice", + "apex@com.android.apex1@javalib@service-foo.jar@classes.odex", + installs[0].InstallFileOnDevice) - android.AssertIntEquals(t, "entries count", 2, len(entriesList)) + android.AssertPathRelativeToTopEquals(t, "installs[1] OutputPathOnHost", + "out/soong/.intermediates/service-foo/android_common_apex1000/dexpreopt/service-foo/oat/arm64/javalib.vdex", + installs[1].OutputPathOnHost) - verifyEntries(t, - "entriesList[0]", - "service-foo-dexpreopt-arm64-apex@com.android.apex1@javalib@service-foo.jar@classes.odex", - "/dexpreopt/service-foo/oat/arm64/javalib.odex", - "/system/framework/oat/arm64", - "apex@com.android.apex1@javalib@service-foo.jar@classes.odex", - entriesList[0]) + android.AssertPathRelativeToTopEquals(t, "installs[1] InstallDirOnDevice", + "out/target/product/test_device/system/framework/oat/arm64", + installs[1].InstallDirOnDevice) - verifyEntries(t, - "entriesList[1]", - "service-foo-dexpreopt-arm64-apex@com.android.apex1@javalib@service-foo.jar@classes.vdex", - "/dexpreopt/service-foo/oat/arm64/javalib.vdex", - "/system/framework/oat/arm64", + android.AssertStringEquals(t, "installs[1] InstallFileOnDevice", "apex@com.android.apex1@javalib@service-foo.jar@classes.vdex", - entriesList[1]) + installs[1].InstallFileOnDevice) // Not an APEX system server jar. result = preparers.RunTestWithBp(t, ` @@ -448,11 +368,13 @@ func TestAndroidMkEntriesForApex(t *testing.T) { }`) ctx = result.TestContext module = ctx.ModuleForTests("foo", "android_common") + library = module.Module().(*Library) - entriesList = android.AndroidMkEntriesForTest(t, ctx, module.Module()) - entriesList = filterDexpreoptEntriesList(entriesList) + installs = library.dexpreopter.ApexSystemServerDexpreoptInstalls() + dexJars = library.dexpreopter.ApexSystemServerDexJars() - android.AssertIntEquals(t, "entries count", 0, len(entriesList)) + android.AssertIntEquals(t, "install count", 0, len(installs)) + android.AssertIntEquals(t, "dexjar count", 0, len(dexJars)) } func TestGenerateProfileEvenIfDexpreoptIsDisabled(t *testing.T) { diff --git a/java/java.go b/java/java.go index 8d10e3bd2..9f0de46ce 100644 --- a/java/java.go +++ b/java/java.go @@ -402,7 +402,12 @@ type JavaInfo struct { BuiltInstalled string - BuiltInstalledForApex []dexpreopterInstall + // ApexSystemServerDexpreoptInstalls stores the list of dexpreopt artifacts if this is a system server + // jar in an apex. + ApexSystemServerDexpreoptInstalls []DexpreopterInstall + + // ApexSystemServerDexJars stores the list of dex jars if this is a system server jar in an apex. + ApexSystemServerDexJars android.Paths // The config is used for two purposes: // - Passing dexpreopt information about libraries from Soong to Make. This is needed when @@ -1129,7 +1134,8 @@ func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) { javaInfo.BootDexJarPath = j.bootDexJarPath javaInfo.UncompressDexState = j.uncompressDexState javaInfo.Active = j.active - javaInfo.BuiltInstalledForApex = j.builtInstalledForApex + javaInfo.ApexSystemServerDexpreoptInstalls = j.apexSystemServerDexpreoptInstalls + javaInfo.ApexSystemServerDexJars = j.apexSystemServerDexJars javaInfo.BuiltInstalled = j.builtInstalled javaInfo.ConfigPath = j.configPath javaInfo.OutputProfilePathOnHost = j.outputProfilePathOnHost @@ -1170,7 +1176,6 @@ func (j *Library) javaLibraryModuleInfoJSON(ctx android.ModuleContext) *android. if j.hideApexVariantFromMake { moduleInfoJSON.Disabled = true - j.dexpreopter.ModuleInfoJSONForApex(ctx) } return moduleInfoJSON } diff --git a/java/sdk_library.go b/java/sdk_library.go index 05a5b4920..07f059928 100644 --- a/java/sdk_library.go +++ b/java/sdk_library.go @@ -1246,7 +1246,8 @@ type SdkLibrary struct { commonToSdkLibraryAndImport - builtInstalledForApex []dexpreopterInstall + apexSystemServerDexpreoptInstalls []DexpreopterInstall + apexSystemServerDexJars android.Paths } func (module *SdkLibrary) generateTestAndSystemScopesByDefault() bool { @@ -1501,7 +1502,8 @@ func (module *SdkLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) module.dexJarFile = makeDexJarPathFromPath(module.implLibraryInfo.DexJarFile.Path()) module.headerJarFile = module.implLibraryInfo.HeaderJars[0] module.implementationAndResourcesJar = module.implLibraryInfo.ImplementationAndResourcesJars[0] - module.builtInstalledForApex = module.implLibraryInfo.BuiltInstalledForApex + module.apexSystemServerDexpreoptInstalls = module.implLibraryInfo.ApexSystemServerDexpreoptInstalls + module.apexSystemServerDexJars = module.implLibraryInfo.ApexSystemServerDexJars module.dexpreopter.configPath = module.implLibraryInfo.ConfigPath module.dexpreopter.outputProfilePathOnHost = module.implLibraryInfo.OutputProfilePathOnHost @@ -1584,8 +1586,12 @@ func setOutputFilesFromJavaInfo(ctx android.ModuleContext, info *JavaInfo) { ctx.SetOutputFiles(info.GeneratedSrcjars, ".generated_srcjars") } -func (module *SdkLibrary) BuiltInstalledForApex() []dexpreopterInstall { - return module.builtInstalledForApex +func (module *SdkLibrary) ApexSystemServerDexpreoptInstalls() []DexpreopterInstall { + return module.apexSystemServerDexpreoptInstalls +} + +func (module *SdkLibrary) ApexSystemServerDexJars() android.Paths { + return module.apexSystemServerDexJars } func (module *SdkLibrary) AndroidMkEntries() []android.AndroidMkEntries { |