Loading apex/apex.go +32 −10 Original line number Diff line number Diff line Loading @@ -1756,7 +1756,9 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) { ctx.PropertyErrorf("systemserverclasspath_fragments", "%q is not a systemserverclasspath_fragment module", depName) return false } filesInfo = append(filesInfo, apexClasspathFragmentProtoFile(ctx, child)) if af := apexClasspathFragmentProtoFile(ctx, child); af != nil { filesInfo = append(filesInfo, *af) } return true } case javaLibTag: Loading Loading @@ -2159,17 +2161,23 @@ func apexBootclasspathFragmentFiles(ctx android.ModuleContext, module blueprint. } // Add classpaths.proto config. filesToAdd = append(filesToAdd, apexClasspathFragmentProtoFile(ctx, module)) if af := apexClasspathFragmentProtoFile(ctx, module); af != nil { filesToAdd = append(filesToAdd, *af) } return filesToAdd } // apexClasspathFragmentProtoFile returns apexFile structure defining the classpath.proto config that // the module contributes to the apex. func apexClasspathFragmentProtoFile(ctx android.ModuleContext, module blueprint.Module) apexFile { fragmentInfo := ctx.OtherModuleProvider(module, java.ClasspathFragmentProtoContentInfoProvider).(java.ClasspathFragmentProtoContentInfo) classpathProtoOutput := fragmentInfo.ClasspathFragmentProtoOutput return newApexFile(ctx, classpathProtoOutput, classpathProtoOutput.Base(), fragmentInfo.ClasspathFragmentProtoInstallDir.Rel(), etc, nil) // apexClasspathFragmentProtoFile returns *apexFile structure defining the classpath.proto config that // the module contributes to the apex; or nil if the proto config was not generated. func apexClasspathFragmentProtoFile(ctx android.ModuleContext, module blueprint.Module) *apexFile { info := ctx.OtherModuleProvider(module, java.ClasspathFragmentProtoContentInfoProvider).(java.ClasspathFragmentProtoContentInfo) if !info.ClasspathFragmentProtoGenerated { return nil } classpathProtoOutput := info.ClasspathFragmentProtoOutput af := newApexFile(ctx, classpathProtoOutput, classpathProtoOutput.Base(), info.ClasspathFragmentProtoInstallDir.Rel(), etc, nil) return &af } // apexFileForBootclasspathFragmentContentModule creates an apexFile for a bootclasspath_fragment Loading Loading @@ -2355,16 +2363,30 @@ func (a *apexBundle) checkStaticLinkingToStubLibraries(ctx android.ModuleContext }) } // Enforce that Java deps of the apex are using stable SDKs to compile // checkUpdatable enforces APEX and its transitive dep properties to have desired values for updatable APEXes. func (a *apexBundle) checkUpdatable(ctx android.ModuleContext) { if a.Updatable() { if String(a.properties.Min_sdk_version) == "" { ctx.PropertyErrorf("updatable", "updatable APEXes should set min_sdk_version as well") } a.checkJavaStableSdkVersion(ctx) a.checkClasspathFragments(ctx) } } // checkClasspathFragments enforces that all classpath fragments in deps generate classpaths.proto config. func (a *apexBundle) checkClasspathFragments(ctx android.ModuleContext) { ctx.VisitDirectDeps(func(module android.Module) { if tag := ctx.OtherModuleDependencyTag(module); tag == bcpfTag || tag == sscpfTag { info := ctx.OtherModuleProvider(module, java.ClasspathFragmentProtoContentInfoProvider).(java.ClasspathFragmentProtoContentInfo) if !info.ClasspathFragmentProtoGenerated { ctx.OtherModuleErrorf(module, "is included in updatable apex %v, it must not set generate_classpaths_proto to false", ctx.ModuleName()) } } }) } // checkJavaStableSdkVersion enforces that all Java deps are using stable SDKs to compile. func (a *apexBundle) checkJavaStableSdkVersion(ctx android.ModuleContext) { // Visit direct deps only. As long as we guarantee top-level deps are using stable SDKs, // java's checkLinkType guarantees correct usage for transitive deps Loading @@ -2383,7 +2405,7 @@ func (a *apexBundle) checkJavaStableSdkVersion(ctx android.ModuleContext) { }) } // Ensures that the all the dependencies are marked as available for this APEX // checkApexAvailability ensures that the all the dependencies are marked as available for this APEX. func (a *apexBundle) checkApexAvailability(ctx android.ModuleContext) { // Let's be practical. Availability for test, host, and the VNDK apex isn't important if ctx.Host() || a.testApex || a.vndkApex { Loading apex/apex_test.go +41 −0 Original line number Diff line number Diff line Loading @@ -6700,6 +6700,47 @@ func TestUpdatableDefault_should_set_min_sdk_version(t *testing.T) { `) } func TestUpdatable_should_not_set_generate_classpaths_proto(t *testing.T) { testApexError(t, `"mysystemserverclasspathfragment" .* it must not set generate_classpaths_proto to false`, ` apex { name: "myapex", key: "myapex.key", systemserverclasspath_fragments: [ "mysystemserverclasspathfragment", ], min_sdk_version: "29", updatable: true, } apex_key { name: "myapex.key", public_key: "testkey.avbpubkey", private_key: "testkey.pem", } java_library { name: "foo", srcs: ["b.java"], min_sdk_version: "29", installable: true, apex_available: [ "myapex", ], } systemserverclasspath_fragment { name: "mysystemserverclasspathfragment", generate_classpaths_proto: false, contents: [ "foo", ], apex_available: [ "myapex", ], } `) } func TestNoUpdatableJarsInBootImage(t *testing.T) { // Set the BootJars in dexpreopt.GlobalConfig and productVariables to the same value. This can // result in an invalid configuration as it does not set the ArtApexJars and allows art apex Loading apex/systemserver_classpath_fragment_test.go +51 −0 Original line number Diff line number Diff line Loading @@ -76,3 +76,54 @@ func TestSystemserverclasspathFragmentContents(t *testing.T) { `mysystemserverclasspathfragment`, }) } func TestSystemserverclasspathFragmentNoGeneratedProto(t *testing.T) { result := android.GroupFixturePreparers( prepareForTestWithSystemserverclasspathFragment, prepareForTestWithMyapex, ).RunTestWithBp(t, ` apex { name: "myapex", key: "myapex.key", systemserverclasspath_fragments: [ "mysystemserverclasspathfragment", ], updatable: false, } apex_key { name: "myapex.key", public_key: "testkey.avbpubkey", private_key: "testkey.pem", } java_library { name: "foo", srcs: ["b.java"], installable: true, apex_available: [ "myapex", ], } systemserverclasspath_fragment { name: "mysystemserverclasspathfragment", generate_classpaths_proto: false, contents: [ "foo", ], apex_available: [ "myapex", ], } `) ensureExactContents(t, result.TestContext, "myapex", "android_common_myapex_image", []string{ "javalib/foo.jar", }) java.CheckModuleDependencies(t, result.TestContext, "myapex", "android_common_myapex_image", []string{ `myapex.key`, `mysystemserverclasspathfragment`, }) } java/classpath_fragment.go +29 −16 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package java import ( "fmt" "github.com/google/blueprint" "github.com/google/blueprint/proptools" "strings" "android/soong/android" Loading @@ -44,6 +45,11 @@ func (c classpathType) String() string { } type classpathFragmentProperties struct { // Whether to generated classpaths.proto config instance for the fragment. If the config is not // generated, then relevant boot jars are added to platform classpath, i.e. platform_bootclasspath // or platform_systemserverclasspath. This is useful for non-updatable APEX boot jars, to keep // them as part of dexopt on device. Defaults to true. Generate_classpaths_proto *bool } // classpathFragment interface is implemented by a module that contributes jars to a *CLASSPATH Loading Loading @@ -101,6 +107,8 @@ func configuredJarListToClasspathJars(ctx android.ModuleContext, configuredJars } func (c *ClasspathFragmentBase) generateClasspathProtoBuildActions(ctx android.ModuleContext, jars []classpathJar) { generateProto := proptools.BoolDefault(c.properties.Generate_classpaths_proto, true) if generateProto { outputFilename := strings.ToLower(c.classpathType.String()) + ".pb" c.outputFilepath = android.PathForModuleOut(ctx, outputFilename).OutputPath c.installDirPath = android.PathForModuleInstall(ctx, "etc", "classpaths") Loading @@ -117,8 +125,10 @@ func (c *ClasspathFragmentBase) generateClasspathProtoBuildActions(ctx android.M FlagWithOutput("--output=", c.outputFilepath) rule.Build("classpath_fragment", "Compiling "+c.outputFilepath.String()) } classpathProtoInfo := ClasspathFragmentProtoContentInfo{ ClasspathFragmentProtoGenerated: generateProto, ClasspathFragmentProtoInstallDir: c.installDirPath, ClasspathFragmentProtoOutput: c.outputFilepath, } Loading Loading @@ -164,6 +174,9 @@ func (c *ClasspathFragmentBase) androidMkEntries() []android.AndroidMkEntries { var ClasspathFragmentProtoContentInfoProvider = blueprint.NewProvider(ClasspathFragmentProtoContentInfo{}) type ClasspathFragmentProtoContentInfo struct { // Whether the classpaths.proto config is generated for the fragment. ClasspathFragmentProtoGenerated bool // 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 Loading Loading
apex/apex.go +32 −10 Original line number Diff line number Diff line Loading @@ -1756,7 +1756,9 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) { ctx.PropertyErrorf("systemserverclasspath_fragments", "%q is not a systemserverclasspath_fragment module", depName) return false } filesInfo = append(filesInfo, apexClasspathFragmentProtoFile(ctx, child)) if af := apexClasspathFragmentProtoFile(ctx, child); af != nil { filesInfo = append(filesInfo, *af) } return true } case javaLibTag: Loading Loading @@ -2159,17 +2161,23 @@ func apexBootclasspathFragmentFiles(ctx android.ModuleContext, module blueprint. } // Add classpaths.proto config. filesToAdd = append(filesToAdd, apexClasspathFragmentProtoFile(ctx, module)) if af := apexClasspathFragmentProtoFile(ctx, module); af != nil { filesToAdd = append(filesToAdd, *af) } return filesToAdd } // apexClasspathFragmentProtoFile returns apexFile structure defining the classpath.proto config that // the module contributes to the apex. func apexClasspathFragmentProtoFile(ctx android.ModuleContext, module blueprint.Module) apexFile { fragmentInfo := ctx.OtherModuleProvider(module, java.ClasspathFragmentProtoContentInfoProvider).(java.ClasspathFragmentProtoContentInfo) classpathProtoOutput := fragmentInfo.ClasspathFragmentProtoOutput return newApexFile(ctx, classpathProtoOutput, classpathProtoOutput.Base(), fragmentInfo.ClasspathFragmentProtoInstallDir.Rel(), etc, nil) // apexClasspathFragmentProtoFile returns *apexFile structure defining the classpath.proto config that // the module contributes to the apex; or nil if the proto config was not generated. func apexClasspathFragmentProtoFile(ctx android.ModuleContext, module blueprint.Module) *apexFile { info := ctx.OtherModuleProvider(module, java.ClasspathFragmentProtoContentInfoProvider).(java.ClasspathFragmentProtoContentInfo) if !info.ClasspathFragmentProtoGenerated { return nil } classpathProtoOutput := info.ClasspathFragmentProtoOutput af := newApexFile(ctx, classpathProtoOutput, classpathProtoOutput.Base(), info.ClasspathFragmentProtoInstallDir.Rel(), etc, nil) return &af } // apexFileForBootclasspathFragmentContentModule creates an apexFile for a bootclasspath_fragment Loading Loading @@ -2355,16 +2363,30 @@ func (a *apexBundle) checkStaticLinkingToStubLibraries(ctx android.ModuleContext }) } // Enforce that Java deps of the apex are using stable SDKs to compile // checkUpdatable enforces APEX and its transitive dep properties to have desired values for updatable APEXes. func (a *apexBundle) checkUpdatable(ctx android.ModuleContext) { if a.Updatable() { if String(a.properties.Min_sdk_version) == "" { ctx.PropertyErrorf("updatable", "updatable APEXes should set min_sdk_version as well") } a.checkJavaStableSdkVersion(ctx) a.checkClasspathFragments(ctx) } } // checkClasspathFragments enforces that all classpath fragments in deps generate classpaths.proto config. func (a *apexBundle) checkClasspathFragments(ctx android.ModuleContext) { ctx.VisitDirectDeps(func(module android.Module) { if tag := ctx.OtherModuleDependencyTag(module); tag == bcpfTag || tag == sscpfTag { info := ctx.OtherModuleProvider(module, java.ClasspathFragmentProtoContentInfoProvider).(java.ClasspathFragmentProtoContentInfo) if !info.ClasspathFragmentProtoGenerated { ctx.OtherModuleErrorf(module, "is included in updatable apex %v, it must not set generate_classpaths_proto to false", ctx.ModuleName()) } } }) } // checkJavaStableSdkVersion enforces that all Java deps are using stable SDKs to compile. func (a *apexBundle) checkJavaStableSdkVersion(ctx android.ModuleContext) { // Visit direct deps only. As long as we guarantee top-level deps are using stable SDKs, // java's checkLinkType guarantees correct usage for transitive deps Loading @@ -2383,7 +2405,7 @@ func (a *apexBundle) checkJavaStableSdkVersion(ctx android.ModuleContext) { }) } // Ensures that the all the dependencies are marked as available for this APEX // checkApexAvailability ensures that the all the dependencies are marked as available for this APEX. func (a *apexBundle) checkApexAvailability(ctx android.ModuleContext) { // Let's be practical. Availability for test, host, and the VNDK apex isn't important if ctx.Host() || a.testApex || a.vndkApex { Loading
apex/apex_test.go +41 −0 Original line number Diff line number Diff line Loading @@ -6700,6 +6700,47 @@ func TestUpdatableDefault_should_set_min_sdk_version(t *testing.T) { `) } func TestUpdatable_should_not_set_generate_classpaths_proto(t *testing.T) { testApexError(t, `"mysystemserverclasspathfragment" .* it must not set generate_classpaths_proto to false`, ` apex { name: "myapex", key: "myapex.key", systemserverclasspath_fragments: [ "mysystemserverclasspathfragment", ], min_sdk_version: "29", updatable: true, } apex_key { name: "myapex.key", public_key: "testkey.avbpubkey", private_key: "testkey.pem", } java_library { name: "foo", srcs: ["b.java"], min_sdk_version: "29", installable: true, apex_available: [ "myapex", ], } systemserverclasspath_fragment { name: "mysystemserverclasspathfragment", generate_classpaths_proto: false, contents: [ "foo", ], apex_available: [ "myapex", ], } `) } func TestNoUpdatableJarsInBootImage(t *testing.T) { // Set the BootJars in dexpreopt.GlobalConfig and productVariables to the same value. This can // result in an invalid configuration as it does not set the ArtApexJars and allows art apex Loading
apex/systemserver_classpath_fragment_test.go +51 −0 Original line number Diff line number Diff line Loading @@ -76,3 +76,54 @@ func TestSystemserverclasspathFragmentContents(t *testing.T) { `mysystemserverclasspathfragment`, }) } func TestSystemserverclasspathFragmentNoGeneratedProto(t *testing.T) { result := android.GroupFixturePreparers( prepareForTestWithSystemserverclasspathFragment, prepareForTestWithMyapex, ).RunTestWithBp(t, ` apex { name: "myapex", key: "myapex.key", systemserverclasspath_fragments: [ "mysystemserverclasspathfragment", ], updatable: false, } apex_key { name: "myapex.key", public_key: "testkey.avbpubkey", private_key: "testkey.pem", } java_library { name: "foo", srcs: ["b.java"], installable: true, apex_available: [ "myapex", ], } systemserverclasspath_fragment { name: "mysystemserverclasspathfragment", generate_classpaths_proto: false, contents: [ "foo", ], apex_available: [ "myapex", ], } `) ensureExactContents(t, result.TestContext, "myapex", "android_common_myapex_image", []string{ "javalib/foo.jar", }) java.CheckModuleDependencies(t, result.TestContext, "myapex", "android_common_myapex_image", []string{ `myapex.key`, `mysystemserverclasspathfragment`, }) }
java/classpath_fragment.go +29 −16 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package java import ( "fmt" "github.com/google/blueprint" "github.com/google/blueprint/proptools" "strings" "android/soong/android" Loading @@ -44,6 +45,11 @@ func (c classpathType) String() string { } type classpathFragmentProperties struct { // Whether to generated classpaths.proto config instance for the fragment. If the config is not // generated, then relevant boot jars are added to platform classpath, i.e. platform_bootclasspath // or platform_systemserverclasspath. This is useful for non-updatable APEX boot jars, to keep // them as part of dexopt on device. Defaults to true. Generate_classpaths_proto *bool } // classpathFragment interface is implemented by a module that contributes jars to a *CLASSPATH Loading Loading @@ -101,6 +107,8 @@ func configuredJarListToClasspathJars(ctx android.ModuleContext, configuredJars } func (c *ClasspathFragmentBase) generateClasspathProtoBuildActions(ctx android.ModuleContext, jars []classpathJar) { generateProto := proptools.BoolDefault(c.properties.Generate_classpaths_proto, true) if generateProto { outputFilename := strings.ToLower(c.classpathType.String()) + ".pb" c.outputFilepath = android.PathForModuleOut(ctx, outputFilename).OutputPath c.installDirPath = android.PathForModuleInstall(ctx, "etc", "classpaths") Loading @@ -117,8 +125,10 @@ func (c *ClasspathFragmentBase) generateClasspathProtoBuildActions(ctx android.M FlagWithOutput("--output=", c.outputFilepath) rule.Build("classpath_fragment", "Compiling "+c.outputFilepath.String()) } classpathProtoInfo := ClasspathFragmentProtoContentInfo{ ClasspathFragmentProtoGenerated: generateProto, ClasspathFragmentProtoInstallDir: c.installDirPath, ClasspathFragmentProtoOutput: c.outputFilepath, } Loading Loading @@ -164,6 +174,9 @@ func (c *ClasspathFragmentBase) androidMkEntries() []android.AndroidMkEntries { var ClasspathFragmentProtoContentInfoProvider = blueprint.NewProvider(ClasspathFragmentProtoContentInfo{}) type ClasspathFragmentProtoContentInfo struct { // Whether the classpaths.proto config is generated for the fragment. ClasspathFragmentProtoGenerated bool // 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 Loading