Loading apex/platform_bootclasspath_test.go +136 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import ( "android/soong/android" "android/soong/java" "github.com/google/blueprint" "github.com/google/blueprint/proptools" ) // Contains tests for platform_bootclasspath logic from java/platform_bootclasspath.go that requires Loading Loading @@ -174,6 +175,141 @@ func TestPlatformBootclasspathDependencies(t *testing.T) { }) } // TestPlatformBootclasspath_AlwaysUsePrebuiltSdks verifies that the build does not fail when // AlwaysUsePrebuiltSdk() returns true. The structure of the modules in this test matches what // currently exists in some places in the Android build but it is not the intended structure. It is // in fact an invalid structure that should cause build failures. However, fixing that structure // will take too long so in the meantime this tests the workarounds to avoid build breakages. // // The main issues with this structure are: // 1. There is no prebuilt_bootclasspath_fragment referencing the "foo" java_sdk_library_import. // 2. There is no prebuilt_apex/apex_set which makes the dex implementation jar available to the // prebuilt_bootclasspath_fragment and the "foo" java_sdk_library_import. // // Together these cause the following symptoms: // 1. The "foo" java_sdk_library_import does not have a dex implementation jar. // 2. The "foo" java_sdk_library_import does not have a myapex variant. // // TODO(b/179354495): Fix the structure in this test once the main Android build has been fixed. func TestPlatformBootclasspath_AlwaysUsePrebuiltSdks(t *testing.T) { result := android.GroupFixturePreparers( prepareForTestWithPlatformBootclasspath, prepareForTestWithMyapex, // Configure two libraries, the first is a java_sdk_library whose prebuilt will be used because // of AlwaysUsePrebuiltsSdk() but does not have an appropriate apex variant and does not provide // a boot dex jar. The second is a normal library that is unaffected. The order matters because // if the dependency on myapex:foo is filtered out because of either of those conditions then // the dependencies resolved by the platform_bootclasspath will not match the configured list // and so will fail the test. java.FixtureConfigureUpdatableBootJars("myapex:foo", "myapex:bar"), java.PrepareForTestWithJavaSdkLibraryFiles, android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { variables.Always_use_prebuilt_sdks = proptools.BoolPtr(true) }), java.FixtureWithPrebuiltApis(map[string][]string{ "current": {}, "30": {"foo"}, }), ).RunTestWithBp(t, ` apex { name: "myapex", key: "myapex.key", bootclasspath_fragments: [ "mybootclasspath-fragment", ], updatable: false, } apex_key { name: "myapex.key", public_key: "testkey.avbpubkey", private_key: "testkey.pem", } java_library { name: "bar", srcs: ["b.java"], installable: true, apex_available: ["myapex"], permitted_packages: ["bar"], } java_sdk_library { name: "foo", srcs: ["b.java"], shared_library: false, public: { enabled: true, }, apex_available: ["myapex"], permitted_packages: ["foo"], } // A prebuilt java_sdk_library_import that is not preferred by default but will be preferred // because AlwaysUsePrebuiltSdks() is true. java_sdk_library_import { name: "foo", prefer: false, shared_library: false, public: { jars: ["sdk_library/public/foo-stubs.jar"], stub_srcs: ["sdk_library/public/foo_stub_sources"], current_api: "sdk_library/public/foo.txt", removed_api: "sdk_library/public/foo-removed.txt", sdk_version: "current", }, apex_available: ["myapex"], } // This always depends on the source foo module, its dependencies are not affected by the // AlwaysUsePrebuiltSdks(). bootclasspath_fragment { name: "mybootclasspath-fragment", apex_available: [ "myapex", ], contents: [ "foo", "bar", ], } platform_bootclasspath { name: "myplatform-bootclasspath", } `, ) java.CheckPlatformBootclasspathModules(t, result, "myplatform-bootclasspath", []string{ // The configured contents of BootJars. "platform:prebuilt_foo", // Note: This is the platform not myapex variant. "myapex:bar", }) // Make sure that the myplatform-bootclasspath has the correct dependencies. CheckModuleDependencies(t, result.TestContext, "myplatform-bootclasspath", "android_common", []string{ // The following are stubs. "platform:prebuilt_sdk_public_current_android", "platform:prebuilt_sdk_system_current_android", "platform:prebuilt_sdk_test_current_android", // Not a prebuilt as no prebuilt existed when it was added. "platform:legacy.core.platform.api.stubs", // Needed for generating the boot image. `platform:dex2oatd`, // The platform_bootclasspath intentionally adds dependencies on both source and prebuilt // modules when available as it does not know which one will be preferred. // // The source module has an APEX variant but the prebuilt does not. "myapex:foo", "platform:prebuilt_foo", // Only a source module exists. "myapex:bar", }) } // CheckModuleDependencies checks the dependencies of the selected module against the expected list. // // The expected list must be a list of strings of the form "<apex>:<module>", where <apex> is the Loading java/bootclasspath.go +10 −1 Original line number Diff line number Diff line Loading @@ -29,7 +29,7 @@ func init() { func registerBootclasspathBuildComponents(ctx android.RegistrationContext) { ctx.FinalDepsMutators(func(ctx android.RegisterMutatorsContext) { ctx.BottomUp("bootclasspath_deps", bootclasspathDepsMutator) ctx.BottomUp("bootclasspath_deps", bootclasspathDepsMutator).Parallel() }) } Loading Loading @@ -95,6 +95,15 @@ func addDependencyOntoApexModulePair(ctx android.BottomUpMutatorContext, apex st if ctx.OtherModuleDependencyVariantExists(variations, prebuiltName) { ctx.AddVariationDependencies(variations, tag, prebuiltName) addedDep = true } else if ctx.Config().AlwaysUsePrebuiltSdks() && len(variations) > 0 { // TODO(b/179354495): Remove this code path once the Android build has been fully migrated to // use bootclasspath_fragment properly. // Some prebuilt java_sdk_library modules do not yet have an APEX variations so try and add a // dependency on the non-APEX variant. if ctx.OtherModuleDependencyVariantExists(nil, prebuiltName) { ctx.AddVariationDependencies(nil, tag, prebuiltName) addedDep = true } } // If no appropriate variant existing for this, so no dependency could be added, then it is an Loading java/dexpreopt_bootjars.go +1 −1 Original line number Diff line number Diff line Loading @@ -766,7 +766,7 @@ func generateUpdatableBcpPackagesRule(ctx android.ModuleContext, image *bootImag if len(pp) > 0 { updatablePackages = append(updatablePackages, pp...) } else { ctx.ModuleErrorf("Missing permitted_packages") ctx.OtherModuleErrorf(module, "Missing permitted_packages") } } } Loading java/hiddenapi_modular.go +20 −1 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ package java import ( "fmt" "strings" "android/soong/android" Loading Loading @@ -560,7 +561,25 @@ func extractBootDexJarsFromHiddenAPIModules(ctx android.ModuleContext, contents for _, module := range contents { bootDexJar := module.bootDexJar() if bootDexJar == nil { if ctx.Config().AlwaysUsePrebuiltSdks() { // TODO(b/179354495): Remove this work around when it is unnecessary. // Prebuilt modules like framework-wifi do not yet provide dex implementation jars. So, // create a fake one that will cause a build error only if it is used. fake := android.PathForModuleOut(ctx, "fake/boot-dex/%s.jar", module.Name()) // Create an error rule that pretends to create the output file but will actually fail if it // is run. ctx.Build(pctx, android.BuildParams{ Rule: android.ErrorRule, Output: fake, Args: map[string]string{ "error": fmt.Sprintf("missing dependencies: boot dex jar for %s", module), }, }) bootDexJars = append(bootDexJars, fake) } else { ctx.ModuleErrorf("module %s does not provide a dex jar", module) } } else { bootDexJars = append(bootDexJars, bootDexJar) } Loading java/platform_bootclasspath.go +9 −2 Original line number Diff line number Diff line Loading @@ -242,8 +242,15 @@ func (b *platformBootclasspathModule) checkUpdatableModules(ctx android.ModuleCo } else { name := ctx.OtherModuleName(m) if apexInfo.IsForPlatform() { // If AlwaysUsePrebuiltSdks() returns true then it is possible that the updatable list will // include platform variants of a prebuilt module due to workarounds elsewhere. In that case // do not treat this as an error. // TODO(b/179354495): Always treat this as an error when migration to bootclasspath_fragment // modules is complete. if !ctx.Config().AlwaysUsePrebuiltSdks() { // error: this jar is part of the platform ctx.ModuleErrorf("module %q from platform is not allowed in the updatable boot jars list", name) } } else { // TODO(b/177892522): Treat this as an error. // Cannot do that at the moment because framework-wifi and framework-tethering are in the Loading Loading
apex/platform_bootclasspath_test.go +136 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import ( "android/soong/android" "android/soong/java" "github.com/google/blueprint" "github.com/google/blueprint/proptools" ) // Contains tests for platform_bootclasspath logic from java/platform_bootclasspath.go that requires Loading Loading @@ -174,6 +175,141 @@ func TestPlatformBootclasspathDependencies(t *testing.T) { }) } // TestPlatformBootclasspath_AlwaysUsePrebuiltSdks verifies that the build does not fail when // AlwaysUsePrebuiltSdk() returns true. The structure of the modules in this test matches what // currently exists in some places in the Android build but it is not the intended structure. It is // in fact an invalid structure that should cause build failures. However, fixing that structure // will take too long so in the meantime this tests the workarounds to avoid build breakages. // // The main issues with this structure are: // 1. There is no prebuilt_bootclasspath_fragment referencing the "foo" java_sdk_library_import. // 2. There is no prebuilt_apex/apex_set which makes the dex implementation jar available to the // prebuilt_bootclasspath_fragment and the "foo" java_sdk_library_import. // // Together these cause the following symptoms: // 1. The "foo" java_sdk_library_import does not have a dex implementation jar. // 2. The "foo" java_sdk_library_import does not have a myapex variant. // // TODO(b/179354495): Fix the structure in this test once the main Android build has been fixed. func TestPlatformBootclasspath_AlwaysUsePrebuiltSdks(t *testing.T) { result := android.GroupFixturePreparers( prepareForTestWithPlatformBootclasspath, prepareForTestWithMyapex, // Configure two libraries, the first is a java_sdk_library whose prebuilt will be used because // of AlwaysUsePrebuiltsSdk() but does not have an appropriate apex variant and does not provide // a boot dex jar. The second is a normal library that is unaffected. The order matters because // if the dependency on myapex:foo is filtered out because of either of those conditions then // the dependencies resolved by the platform_bootclasspath will not match the configured list // and so will fail the test. java.FixtureConfigureUpdatableBootJars("myapex:foo", "myapex:bar"), java.PrepareForTestWithJavaSdkLibraryFiles, android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { variables.Always_use_prebuilt_sdks = proptools.BoolPtr(true) }), java.FixtureWithPrebuiltApis(map[string][]string{ "current": {}, "30": {"foo"}, }), ).RunTestWithBp(t, ` apex { name: "myapex", key: "myapex.key", bootclasspath_fragments: [ "mybootclasspath-fragment", ], updatable: false, } apex_key { name: "myapex.key", public_key: "testkey.avbpubkey", private_key: "testkey.pem", } java_library { name: "bar", srcs: ["b.java"], installable: true, apex_available: ["myapex"], permitted_packages: ["bar"], } java_sdk_library { name: "foo", srcs: ["b.java"], shared_library: false, public: { enabled: true, }, apex_available: ["myapex"], permitted_packages: ["foo"], } // A prebuilt java_sdk_library_import that is not preferred by default but will be preferred // because AlwaysUsePrebuiltSdks() is true. java_sdk_library_import { name: "foo", prefer: false, shared_library: false, public: { jars: ["sdk_library/public/foo-stubs.jar"], stub_srcs: ["sdk_library/public/foo_stub_sources"], current_api: "sdk_library/public/foo.txt", removed_api: "sdk_library/public/foo-removed.txt", sdk_version: "current", }, apex_available: ["myapex"], } // This always depends on the source foo module, its dependencies are not affected by the // AlwaysUsePrebuiltSdks(). bootclasspath_fragment { name: "mybootclasspath-fragment", apex_available: [ "myapex", ], contents: [ "foo", "bar", ], } platform_bootclasspath { name: "myplatform-bootclasspath", } `, ) java.CheckPlatformBootclasspathModules(t, result, "myplatform-bootclasspath", []string{ // The configured contents of BootJars. "platform:prebuilt_foo", // Note: This is the platform not myapex variant. "myapex:bar", }) // Make sure that the myplatform-bootclasspath has the correct dependencies. CheckModuleDependencies(t, result.TestContext, "myplatform-bootclasspath", "android_common", []string{ // The following are stubs. "platform:prebuilt_sdk_public_current_android", "platform:prebuilt_sdk_system_current_android", "platform:prebuilt_sdk_test_current_android", // Not a prebuilt as no prebuilt existed when it was added. "platform:legacy.core.platform.api.stubs", // Needed for generating the boot image. `platform:dex2oatd`, // The platform_bootclasspath intentionally adds dependencies on both source and prebuilt // modules when available as it does not know which one will be preferred. // // The source module has an APEX variant but the prebuilt does not. "myapex:foo", "platform:prebuilt_foo", // Only a source module exists. "myapex:bar", }) } // CheckModuleDependencies checks the dependencies of the selected module against the expected list. // // The expected list must be a list of strings of the form "<apex>:<module>", where <apex> is the Loading
java/bootclasspath.go +10 −1 Original line number Diff line number Diff line Loading @@ -29,7 +29,7 @@ func init() { func registerBootclasspathBuildComponents(ctx android.RegistrationContext) { ctx.FinalDepsMutators(func(ctx android.RegisterMutatorsContext) { ctx.BottomUp("bootclasspath_deps", bootclasspathDepsMutator) ctx.BottomUp("bootclasspath_deps", bootclasspathDepsMutator).Parallel() }) } Loading Loading @@ -95,6 +95,15 @@ func addDependencyOntoApexModulePair(ctx android.BottomUpMutatorContext, apex st if ctx.OtherModuleDependencyVariantExists(variations, prebuiltName) { ctx.AddVariationDependencies(variations, tag, prebuiltName) addedDep = true } else if ctx.Config().AlwaysUsePrebuiltSdks() && len(variations) > 0 { // TODO(b/179354495): Remove this code path once the Android build has been fully migrated to // use bootclasspath_fragment properly. // Some prebuilt java_sdk_library modules do not yet have an APEX variations so try and add a // dependency on the non-APEX variant. if ctx.OtherModuleDependencyVariantExists(nil, prebuiltName) { ctx.AddVariationDependencies(nil, tag, prebuiltName) addedDep = true } } // If no appropriate variant existing for this, so no dependency could be added, then it is an Loading
java/dexpreopt_bootjars.go +1 −1 Original line number Diff line number Diff line Loading @@ -766,7 +766,7 @@ func generateUpdatableBcpPackagesRule(ctx android.ModuleContext, image *bootImag if len(pp) > 0 { updatablePackages = append(updatablePackages, pp...) } else { ctx.ModuleErrorf("Missing permitted_packages") ctx.OtherModuleErrorf(module, "Missing permitted_packages") } } } Loading
java/hiddenapi_modular.go +20 −1 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ package java import ( "fmt" "strings" "android/soong/android" Loading Loading @@ -560,7 +561,25 @@ func extractBootDexJarsFromHiddenAPIModules(ctx android.ModuleContext, contents for _, module := range contents { bootDexJar := module.bootDexJar() if bootDexJar == nil { if ctx.Config().AlwaysUsePrebuiltSdks() { // TODO(b/179354495): Remove this work around when it is unnecessary. // Prebuilt modules like framework-wifi do not yet provide dex implementation jars. So, // create a fake one that will cause a build error only if it is used. fake := android.PathForModuleOut(ctx, "fake/boot-dex/%s.jar", module.Name()) // Create an error rule that pretends to create the output file but will actually fail if it // is run. ctx.Build(pctx, android.BuildParams{ Rule: android.ErrorRule, Output: fake, Args: map[string]string{ "error": fmt.Sprintf("missing dependencies: boot dex jar for %s", module), }, }) bootDexJars = append(bootDexJars, fake) } else { ctx.ModuleErrorf("module %s does not provide a dex jar", module) } } else { bootDexJars = append(bootDexJars, bootDexJar) } Loading
java/platform_bootclasspath.go +9 −2 Original line number Diff line number Diff line Loading @@ -242,8 +242,15 @@ func (b *platformBootclasspathModule) checkUpdatableModules(ctx android.ModuleCo } else { name := ctx.OtherModuleName(m) if apexInfo.IsForPlatform() { // If AlwaysUsePrebuiltSdks() returns true then it is possible that the updatable list will // include platform variants of a prebuilt module due to workarounds elsewhere. In that case // do not treat this as an error. // TODO(b/179354495): Always treat this as an error when migration to bootclasspath_fragment // modules is complete. if !ctx.Config().AlwaysUsePrebuiltSdks() { // error: this jar is part of the platform ctx.ModuleErrorf("module %q from platform is not allowed in the updatable boot jars list", name) } } else { // TODO(b/177892522): Treat this as an error. // Cannot do that at the moment because framework-wifi and framework-tethering are in the Loading