diff --git a/apex/platform_bootclasspath_test.go b/apex/platform_bootclasspath_test.go index bd4a9d599..279cf54de 100644 --- a/apex/platform_bootclasspath_test.go +++ b/apex/platform_bootclasspath_test.go @@ -481,3 +481,62 @@ func CheckModuleDependencies(t *testing.T, ctx *android.TestContext, name, varia pairs := java.ApexNamePairsFromModules(ctx, modules) android.AssertDeepEquals(t, "module dependencies", expected, pairs) } + +// TestPlatformBootclasspath_IncludesRemainingApexJars verifies that any apex boot jar is present in +// platform_bootclasspath's classpaths.proto config, if the apex does not generate its own config +// by setting generate_classpaths_proto property to false. +func TestPlatformBootclasspath_IncludesRemainingApexJars(t *testing.T) { + result := android.GroupFixturePreparers( + prepareForTestWithPlatformBootclasspath, + prepareForTestWithMyapex, + java.FixtureConfigureUpdatableBootJars("myapex:foo"), + android.FixtureWithRootAndroidBp(` + platform_bootclasspath { + name: "platform-bootclasspath", + fragments: [ + { + apex: "myapex", + module:"foo-fragment", + }, + ], + } + + apex { + name: "myapex", + key: "myapex.key", + bootclasspath_fragments: ["foo-fragment"], + updatable: false, + } + + apex_key { + name: "myapex.key", + public_key: "testkey.avbpubkey", + private_key: "testkey.pem", + } + + bootclasspath_fragment { + name: "foo-fragment", + generate_classpaths_proto: false, + contents: ["foo"], + apex_available: ["myapex"], + } + + java_library { + name: "foo", + srcs: ["a.java"], + system_modules: "none", + sdk_version: "none", + compile_dex: true, + apex_available: ["myapex"], + permitted_packages: ["foo"], + } + `), + ).RunTest(t) + + java.CheckClasspathFragmentProtoContentInfoProvider(t, result, + true, // proto should be generated + "myapex:foo", // apex doesn't generate its own config, so must be in platform_bootclasspath + "bootclasspath.pb", + "out/soong/target/product/test_device/system/etc/classpaths", + ) +} diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go index 4d23820fc..c9d5917fa 100644 --- a/java/bootclasspath_fragment.go +++ b/java/bootclasspath_fragment.go @@ -496,13 +496,14 @@ func (b *BootclasspathFragmentModule) provideApexContentInfo(ctx android.ModuleC // generateClasspathProtoBuildActions generates all required build actions for classpath.proto config func (b *BootclasspathFragmentModule) generateClasspathProtoBuildActions(ctx android.ModuleContext) { var classpathJars []classpathJar + configuredJars := b.configuredJars(ctx) if "art" == proptools.String(b.properties.Image_name) { // ART and platform boot jars must have a corresponding entry in DEX2OATBOOTCLASSPATH - classpathJars = configuredJarListToClasspathJars(ctx, b.configuredJars(ctx), BOOTCLASSPATH, DEX2OATBOOTCLASSPATH) + classpathJars = configuredJarListToClasspathJars(ctx, configuredJars, BOOTCLASSPATH, DEX2OATBOOTCLASSPATH) } else { - classpathJars = configuredJarListToClasspathJars(ctx, b.configuredJars(ctx), b.classpathType) + classpathJars = configuredJarListToClasspathJars(ctx, configuredJars, b.classpathType) } - b.classpathFragmentBase().generateClasspathProtoBuildActions(ctx, classpathJars) + b.classpathFragmentBase().generateClasspathProtoBuildActions(ctx, configuredJars, classpathJars) } func (b *BootclasspathFragmentModule) configuredJars(ctx android.ModuleContext) android.ConfiguredJarList { diff --git a/java/classpath_fragment.go b/java/classpath_fragment.go index 3d7258086..f7a200ad3 100644 --- a/java/classpath_fragment.go +++ b/java/classpath_fragment.go @@ -106,7 +106,7 @@ func configuredJarListToClasspathJars(ctx android.ModuleContext, configuredJars return jars } -func (c *ClasspathFragmentBase) generateClasspathProtoBuildActions(ctx android.ModuleContext, jars []classpathJar) { +func (c *ClasspathFragmentBase) generateClasspathProtoBuildActions(ctx android.ModuleContext, configuredJars android.ConfiguredJarList, jars []classpathJar) { generateProto := proptools.BoolDefault(c.properties.Generate_classpaths_proto, true) if generateProto { outputFilename := strings.ToLower(c.classpathType.String()) + ".pb" @@ -129,6 +129,7 @@ func (c *ClasspathFragmentBase) generateClasspathProtoBuildActions(ctx android.M classpathProtoInfo := ClasspathFragmentProtoContentInfo{ ClasspathFragmentProtoGenerated: generateProto, + ClasspathFragmentProtoContents: configuredJars, ClasspathFragmentProtoInstallDir: c.installDirPath, ClasspathFragmentProtoOutput: c.outputFilepath, } @@ -177,6 +178,9 @@ type ClasspathFragmentProtoContentInfo struct { // Whether the classpaths.proto config is generated for the fragment. ClasspathFragmentProtoGenerated bool + // ClasspathFragmentProtoContents contains a list of jars that are part of this classpath fragment. + ClasspathFragmentProtoContents android.ConfiguredJarList + // ClasspathFragmentProtoOutput is an output path for the generated classpaths.proto config of this module. // // The file should be copied to a relevant place on device, see ClasspathFragmentProtoInstallDir diff --git a/java/platform_bootclasspath.go b/java/platform_bootclasspath.go index 2a6a83e74..a444de00b 100644 --- a/java/platform_bootclasspath.go +++ b/java/platform_bootclasspath.go @@ -198,13 +198,29 @@ func (b *platformBootclasspathModule) GenerateAndroidBuildActions(ctx android.Mo // Generate classpaths.proto config func (b *platformBootclasspathModule) generateClasspathProtoBuildActions(ctx android.ModuleContext) { + configuredJars := b.configuredJars(ctx) // ART and platform boot jars must have a corresponding entry in DEX2OATBOOTCLASSPATH - classpathJars := configuredJarListToClasspathJars(ctx, b.configuredJars(ctx), BOOTCLASSPATH, DEX2OATBOOTCLASSPATH) - b.classpathFragmentBase().generateClasspathProtoBuildActions(ctx, classpathJars) + classpathJars := configuredJarListToClasspathJars(ctx, configuredJars, BOOTCLASSPATH, DEX2OATBOOTCLASSPATH) + b.classpathFragmentBase().generateClasspathProtoBuildActions(ctx, configuredJars, classpathJars) } func (b *platformBootclasspathModule) configuredJars(ctx android.ModuleContext) android.ConfiguredJarList { - return b.getImageConfig(ctx).modules + // Include all non APEX jars + jars := b.getImageConfig(ctx).modules + + // Include jars from APEXes that don't populate their classpath proto config. + remainingJars := dexpreopt.GetGlobalConfig(ctx).UpdatableBootJars + for _, fragment := range b.fragments { + info := ctx.OtherModuleProvider(fragment, ClasspathFragmentProtoContentInfoProvider).(ClasspathFragmentProtoContentInfo) + if info.ClasspathFragmentProtoGenerated { + remainingJars = remainingJars.RemoveList(info.ClasspathFragmentProtoContents) + } + } + for i := 0; i < remainingJars.Len(); i++ { + jars = jars.Append(remainingJars.Apex(i), remainingJars.Jar(i)) + } + + return jars } // checkNonUpdatableModules ensures that the non-updatable modules supplied are not part of an diff --git a/java/systemserver_classpath_fragment.go b/java/systemserver_classpath_fragment.go index a0decb7e9..252c6151f 100644 --- a/java/systemserver_classpath_fragment.go +++ b/java/systemserver_classpath_fragment.go @@ -48,13 +48,14 @@ func (p *platformSystemServerClasspathModule) AndroidMkEntries() (entries []andr } func (p *platformSystemServerClasspathModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { - classpathJars := configuredJarListToClasspathJars(ctx, p.configuredJars(ctx), p.classpathType) - p.classpathFragmentBase().generateClasspathProtoBuildActions(ctx, classpathJars) + configuredJars := p.configuredJars(ctx) + classpathJars := configuredJarListToClasspathJars(ctx, configuredJars, p.classpathType) + p.classpathFragmentBase().generateClasspathProtoBuildActions(ctx, configuredJars, classpathJars) } func (p *platformSystemServerClasspathModule) configuredJars(ctx android.ModuleContext) android.ConfiguredJarList { - global := dexpreopt.GetGlobalConfig(ctx) - return global.SystemServerJars + // TODO(satayev): include any apex jars that don't populate their classpath proto config. + return dexpreopt.GetGlobalConfig(ctx).SystemServerJars } type SystemServerClasspathModule struct { @@ -94,8 +95,9 @@ func (s *SystemServerClasspathModule) GenerateAndroidBuildActions(ctx android.Mo ctx.PropertyErrorf("contents", "empty contents are not allowed") } - classpathJars := configuredJarListToClasspathJars(ctx, s.configuredJars(ctx), s.classpathType) - s.classpathFragmentBase().generateClasspathProtoBuildActions(ctx, classpathJars) + configuredJars := s.configuredJars(ctx) + classpathJars := configuredJarListToClasspathJars(ctx, configuredJars, s.classpathType) + s.classpathFragmentBase().generateClasspathProtoBuildActions(ctx, configuredJars, classpathJars) // Collect the module directory for IDE info in java/jdeps.go. s.modulePaths = append(s.modulePaths, ctx.ModuleDir()) diff --git a/java/testing.go b/java/testing.go index 7b452f762..c3803c8d4 100644 --- a/java/testing.go +++ b/java/testing.go @@ -363,6 +363,17 @@ func CheckPlatformBootclasspathModules(t *testing.T, result *android.TestResult, android.AssertDeepEquals(t, fmt.Sprintf("%s modules", "platform-bootclasspath"), expected, pairs) } +func CheckClasspathFragmentProtoContentInfoProvider(t *testing.T, result *android.TestResult, generated bool, contents, outputFilename, installDir string) { + t.Helper() + p := result.Module("platform-bootclasspath", "android_common").(*platformBootclasspathModule) + info := result.ModuleProvider(p, ClasspathFragmentProtoContentInfoProvider).(ClasspathFragmentProtoContentInfo) + + android.AssertBoolEquals(t, "classpath proto generated", generated, info.ClasspathFragmentProtoGenerated) + android.AssertStringEquals(t, "classpath proto contents", contents, info.ClasspathFragmentProtoContents.String()) + android.AssertStringEquals(t, "output filepath", outputFilename, info.ClasspathFragmentProtoOutput.Base()) + android.AssertPathRelativeToTopEquals(t, "install filepath", installDir, info.ClasspathFragmentProtoInstallDir) +} + // ApexNamePairsFromModules returns the apex:module pair for the supplied modules. func ApexNamePairsFromModules(ctx *android.TestContext, modules []android.Module) []string { pairs := []string{}