diff options
Diffstat (limited to 'apex')
| -rw-r--r-- | apex/apex.go | 54 | ||||
| -rw-r--r-- | apex/apex_test.go | 333 | ||||
| -rw-r--r-- | apex/bootclasspath_fragment_test.go | 498 | ||||
| -rw-r--r-- | apex/platform_bootclasspath_test.go | 59 | ||||
| -rw-r--r-- | apex/prebuilt.go | 19 |
5 files changed, 884 insertions, 79 deletions
diff --git a/apex/apex.go b/apex/apex.go index 7ffa6cc81..baaf87475 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -130,6 +130,10 @@ type apexBundleProperties struct { // symlinking to the system libs. Default is true. Updatable *bool + // Whether this APEX can use platform APIs or not. Can be set to true only when `updatable: + // false`. Default is false. + Platform_apis *bool + // Whether this APEX is installable to one of the partitions like system, vendor, etc. // Default: true. Installable *bool @@ -182,6 +186,12 @@ type apexBundleProperties struct { // used in tests. Test_only_force_compression *bool + // Canonical name of this APEX bundle. Used to determine the path to the + // activated APEX on device (i.e. /apex/<apexVariationName>), and used for the + // apex mutator variations. For override_apex modules, this is the name of the + // overridden base module. + ApexVariationName string `blueprint:"mutated"` + IsCoverageVariant bool `blueprint:"mutated"` // List of sanitizer names that this APEX is enabled for @@ -824,6 +834,10 @@ var ApexBundleInfoProvider = blueprint.NewMutatorProvider(ApexBundleInfo{}, "ape var _ ApexInfoMutator = (*apexBundle)(nil) +func (a *apexBundle) ApexVariationName() string { + return a.properties.ApexVariationName +} + // ApexInfoMutator is responsible for collecting modules that need to have apex variants. They are // identified by doing a graph walk starting from an apexBundle. Basically, all the (direct and // indirect) dependencies are collected. But a few types of modules that shouldn't be included in @@ -912,15 +926,16 @@ func (a *apexBundle) ApexInfoMutator(mctx android.TopDownMutatorContext) { // This is the main part of this mutator. Mark the collected dependencies that they need to // be built for this apexBundle. - // Note that there are many different names. - // ApexVariationName: this is the name of the apex variation + apexVariationName := proptools.StringDefault(a.properties.Apex_name, mctx.ModuleName()) // could be com.android.foo + a.properties.ApexVariationName = apexVariationName apexInfo := android.ApexInfo{ - ApexVariationName: mctx.ModuleName(), // could be com.android.foo + ApexVariationName: apexVariationName, MinSdkVersion: minSdkVersion, RequiredSdks: a.RequiredSdks(), Updatable: a.Updatable(), - InApexVariants: []string{mctx.ModuleName()}, // could be com.android.foo - InApexModules: []string{a.Name()}, // could be com.mycompany.android.foo + UsePlatformApis: a.UsePlatformApis(), + InApexVariants: []string{apexVariationName}, + InApexModules: []string{a.Name()}, // could be com.mycompany.android.foo ApexContents: []*android.ApexContents{apexContents}, } mctx.WalkDeps(func(child, parent android.Module) bool { @@ -933,6 +948,10 @@ func (a *apexBundle) ApexInfoMutator(mctx android.TopDownMutatorContext) { } type ApexInfoMutator interface { + // ApexVariationName returns the name of the APEX variation to use in the apex + // mutator etc. It is the same name as ApexInfo.ApexVariationName. + ApexVariationName() string + // ApexInfoMutator implementations must call BuildForApex(ApexInfo) on any modules that are // depended upon by an apex and which require an apex specific variant. ApexInfoMutator(android.TopDownMutatorContext) @@ -1058,10 +1077,8 @@ func apexMutator(mctx android.BottomUpMutatorContext) { } // apexBundle itself is mutated so that it and its dependencies have the same apex variant. - // TODO(jiyong): document the reason why the VNDK APEX is an exception here. - unprefixedModuleName := android.RemoveOptionalPrebuiltPrefix(mctx.ModuleName()) - if apexModuleTypeRequiresVariant(mctx.Module()) { - apexBundleName := unprefixedModuleName + if ai, ok := mctx.Module().(ApexInfoMutator); ok && apexModuleTypeRequiresVariant(ai) { + apexBundleName := ai.ApexVariationName() mctx.CreateVariations(apexBundleName) if strings.HasPrefix(apexBundleName, "com.android.art") { // Create an alias from the platform variant. This is done to make @@ -1084,6 +1101,7 @@ func apexMutator(mctx android.BottomUpMutatorContext) { // apex variant name. This name matches the name used to create the variations of modules for // which apexModuleTypeRequiresVariant return true. // TODO(b/191269918): Remove this workaround. + unprefixedModuleName := android.RemoveOptionalPrebuiltPrefix(mctx.ModuleName()) mctx.SetDefaultDependencyVariation(&unprefixedModuleName) mctx.CreateVariations(apexBundleName) if strings.HasPrefix(apexBundleName, "com.android.art") { @@ -1095,18 +1113,13 @@ func apexMutator(mctx android.BottomUpMutatorContext) { // apexModuleTypeRequiresVariant determines whether the module supplied requires an apex specific // variant. -func apexModuleTypeRequiresVariant(module android.Module) bool { +func apexModuleTypeRequiresVariant(module ApexInfoMutator) bool { if a, ok := module.(*apexBundle); ok { + // TODO(jiyong): document the reason why the VNDK APEX is an exception here. return !a.vndkApex } - // Match apex_set and prebuilt_apex. Would also match apexBundle but that is handled specially - // above. - if _, ok := module.(ApexInfoMutator); ok { - return true - } - - return false + return true } // See android.UpdateDirectlyInAnyApex @@ -1321,6 +1334,10 @@ func (a *apexBundle) Updatable() bool { return proptools.BoolDefault(a.properties.Updatable, true) } +func (a *apexBundle) UsePlatformApis() bool { + return proptools.BoolDefault(a.properties.Platform_apis, false) +} + // getCertString returns the name of the cert that should be used to sign this APEX. This is // basically from the "certificate" property, but could be overridden by the device config. func (a *apexBundle) getCertString(ctx android.BaseModuleContext) string { @@ -2374,6 +2391,9 @@ func (a *apexBundle) checkUpdatable(ctx android.ModuleContext) { if String(a.properties.Min_sdk_version) == "" { ctx.PropertyErrorf("updatable", "updatable APEXes should set min_sdk_version as well") } + if a.UsePlatformApis() { + ctx.PropertyErrorf("updatable", "updatable APEXes can't use platform APIs") + } a.checkJavaStableSdkVersion(ctx) a.checkClasspathFragments(ctx) } diff --git a/apex/apex_test.go b/apex/apex_test.go index 88da21bdc..b5b1d4401 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -839,6 +839,7 @@ func TestApexWithStubs(t *testing.T) { name: "myapex", key: "myapex.key", native_shared_libs: ["mylib", "mylib3"], + binaries: ["foo.rust"], updatable: false, } @@ -887,6 +888,25 @@ func TestApexWithStubs(t *testing.T) { stl: "none", apex_available: [ "myapex" ], } + + rust_binary { + name: "foo.rust", + srcs: ["foo.rs"], + shared_libs: ["libfoo.shared_from_rust"], + prefer_rlib: true, + apex_available: ["myapex"], + } + + cc_library_shared { + name: "libfoo.shared_from_rust", + srcs: ["mylib.cpp"], + system_shared_libs: [], + stl: "none", + stubs: { + versions: ["10", "11", "12"], + }, + } + `) apexRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("apexRule") @@ -924,7 +944,90 @@ func TestApexWithStubs(t *testing.T) { "lib64/mylib.so", "lib64/mylib3.so", "lib64/mylib4.so", + "bin/foo.rust", + "lib64/libc++.so", // by the implicit dependency from foo.rust + "lib64/liblog.so", // by the implicit dependency from foo.rust }) + + // Ensure that stub dependency from a rust module is not included + ensureNotContains(t, copyCmds, "image.apex/lib64/libfoo.shared_from_rust.so") + // The rust module is linked to the stub cc library + rustDeps := ctx.ModuleForTests("foo.rust", "android_arm64_armv8-a_apex10000").Rule("rustc").Args["linkFlags"] + ensureContains(t, rustDeps, "libfoo.shared_from_rust/android_arm64_armv8-a_shared_current/libfoo.shared_from_rust.so") + ensureNotContains(t, rustDeps, "libfoo.shared_from_rust/android_arm64_armv8-a_shared/libfoo.shared_from_rust.so") +} + +func TestApexCanUsePrivateApis(t *testing.T) { + ctx := testApex(t, ` + apex { + name: "myapex", + key: "myapex.key", + native_shared_libs: ["mylib"], + binaries: ["foo.rust"], + updatable: false, + platform_apis: true, + } + + apex_key { + name: "myapex.key", + public_key: "testkey.avbpubkey", + private_key: "testkey.pem", + } + + cc_library { + name: "mylib", + srcs: ["mylib.cpp"], + shared_libs: ["mylib2"], + system_shared_libs: [], + stl: "none", + apex_available: [ "myapex" ], + } + + cc_library { + name: "mylib2", + srcs: ["mylib.cpp"], + cflags: ["-include mylib.h"], + system_shared_libs: [], + stl: "none", + stubs: { + versions: ["1", "2", "3"], + }, + } + + rust_binary { + name: "foo.rust", + srcs: ["foo.rs"], + shared_libs: ["libfoo.shared_from_rust"], + prefer_rlib: true, + apex_available: ["myapex"], + } + + cc_library_shared { + name: "libfoo.shared_from_rust", + srcs: ["mylib.cpp"], + system_shared_libs: [], + stl: "none", + stubs: { + versions: ["10", "11", "12"], + }, + } + `) + + apexRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("apexRule") + copyCmds := apexRule.Args["copy_commands"] + + // Ensure that indirect stubs dep is not included + ensureNotContains(t, copyCmds, "image.apex/lib64/mylib2.so") + ensureNotContains(t, copyCmds, "image.apex/lib64/libfoo.shared_from_rust.so") + + // Ensure that we are using non-stub variants of mylib2 and libfoo.shared_from_rust (because + // of the platform_apis: true) + mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_apex10000_private").Rule("ld").Args["libFlags"] + ensureNotContains(t, mylibLdFlags, "mylib2/android_arm64_armv8-a_shared_current/mylib2.so") + ensureContains(t, mylibLdFlags, "mylib2/android_arm64_armv8-a_shared/mylib2.so") + rustDeps := ctx.ModuleForTests("foo.rust", "android_arm64_armv8-a_apex10000_private").Rule("rustc").Args["linkFlags"] + ensureNotContains(t, rustDeps, "libfoo.shared_from_rust/android_arm64_armv8-a_shared_current/libfoo.shared_from_rust.so") + ensureContains(t, rustDeps, "libfoo.shared_from_rust/android_arm64_armv8-a_shared/libfoo.shared_from_rust.so") } func TestApexWithStubsWithMinSdkVersion(t *testing.T) { @@ -1695,6 +1798,36 @@ func TestApexMinSdkVersion_SupportsCodeNames(t *testing.T) { expectNoLink("libx", "shared_apex10000", "libz", "shared") } +func TestApexMinSdkVersion_SupportsCodeNames_JavaLibs(t *testing.T) { + testApex(t, ` + apex { + name: "myapex", + key: "myapex.key", + java_libs: ["libx"], + min_sdk_version: "S", + } + + apex_key { + name: "myapex.key", + public_key: "testkey.avbpubkey", + private_key: "testkey.pem", + } + + java_library { + name: "libx", + srcs: ["a.java"], + apex_available: [ "myapex" ], + sdk_version: "current", + min_sdk_version: "S", // should be okay + } + `, + android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { + variables.Platform_version_active_codenames = []string{"S"} + variables.Platform_sdk_codename = proptools.StringPtr("S") + }), + ) +} + func TestApexMinSdkVersion_DefaultsToLatest(t *testing.T) { ctx := testApex(t, ` apex { @@ -3338,60 +3471,109 @@ func ensureExactContents(t *testing.T, ctx *android.TestContext, moduleName, var } func TestVndkApexCurrent(t *testing.T) { - ctx := testApex(t, ` - apex_vndk { - name: "com.android.vndk.current", - key: "com.android.vndk.current.key", - updatable: false, - } - - apex_key { - name: "com.android.vndk.current.key", - public_key: "testkey.avbpubkey", - private_key: "testkey.pem", - } - - cc_library { - name: "libvndk", - srcs: ["mylib.cpp"], - vendor_available: true, - product_available: true, - vndk: { - enabled: true, - }, - system_shared_libs: [], - stl: "none", - apex_available: [ "com.android.vndk.current" ], - } - - cc_library { - name: "libvndksp", - srcs: ["mylib.cpp"], - vendor_available: true, - product_available: true, - vndk: { - enabled: true, - support_system_process: true, - }, - system_shared_libs: [], - stl: "none", - apex_available: [ "com.android.vndk.current" ], - } - `+vndkLibrariesTxtFiles("current")) - - ensureExactContents(t, ctx, "com.android.vndk.current", "android_common_image", []string{ - "lib/libvndk.so", - "lib/libvndksp.so", + commonFiles := []string{ "lib/libc++.so", - "lib64/libvndk.so", - "lib64/libvndksp.so", "lib64/libc++.so", "etc/llndk.libraries.29.txt", "etc/vndkcore.libraries.29.txt", "etc/vndksp.libraries.29.txt", "etc/vndkprivate.libraries.29.txt", "etc/vndkproduct.libraries.29.txt", - }) + } + testCases := []struct { + vndkVersion string + expectedFiles []string + }{ + { + vndkVersion: "current", + expectedFiles: append(commonFiles, + "lib/libvndk.so", + "lib/libvndksp.so", + "lib64/libvndk.so", + "lib64/libvndksp.so"), + }, + { + vndkVersion: "", + expectedFiles: append(commonFiles, + // Legacy VNDK APEX contains only VNDK-SP files (of core variant) + "lib/libvndksp.so", + "lib64/libvndksp.so"), + }, + } + for _, tc := range testCases { + t.Run("VNDK.current with DeviceVndkVersion="+tc.vndkVersion, func(t *testing.T) { + ctx := testApex(t, ` + apex_vndk { + name: "com.android.vndk.current", + key: "com.android.vndk.current.key", + updatable: false, + } + + apex_key { + name: "com.android.vndk.current.key", + public_key: "testkey.avbpubkey", + private_key: "testkey.pem", + } + + cc_library { + name: "libvndk", + srcs: ["mylib.cpp"], + vendor_available: true, + product_available: true, + vndk: { + enabled: true, + }, + system_shared_libs: [], + stl: "none", + apex_available: [ "com.android.vndk.current" ], + } + + cc_library { + name: "libvndksp", + srcs: ["mylib.cpp"], + vendor_available: true, + product_available: true, + vndk: { + enabled: true, + support_system_process: true, + }, + system_shared_libs: [], + stl: "none", + apex_available: [ "com.android.vndk.current" ], + } + + // VNDK-Ext should not cause any problems + + cc_library { + name: "libvndk.ext", + srcs: ["mylib2.cpp"], + vendor: true, + vndk: { + enabled: true, + extends: "libvndk", + }, + system_shared_libs: [], + stl: "none", + } + + cc_library { + name: "libvndksp.ext", + srcs: ["mylib2.cpp"], + vendor: true, + vndk: { + enabled: true, + support_system_process: true, + extends: "libvndksp", + }, + system_shared_libs: [], + stl: "none", + } + `+vndkLibrariesTxtFiles("current"), android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { + variables.DeviceVndkVersion = proptools.StringPtr(tc.vndkVersion) + })) + ensureExactContents(t, ctx, "com.android.vndk.current", "android_common_image", tc.expectedFiles) + }) + } } func TestVndkApexWithPrebuilt(t *testing.T) { @@ -3893,13 +4075,13 @@ func TestApexName(t *testing.T) { } `) - module := ctx.ModuleForTests("myapex", "android_common_myapex_image") + module := ctx.ModuleForTests("myapex", "android_common_com.android.myapex_image") apexManifestRule := module.Rule("apexManifestRule") ensureContains(t, apexManifestRule.Args["opt"], "-v name com.android.myapex") apexRule := module.Rule("apexRule") ensureContains(t, apexRule.Args["opt_flags"], "--do_not_check_keyname") - apexBundle := ctx.ModuleForTests("myapex", "android_common_myapex_image").Module().(*apexBundle) + apexBundle := module.Module().(*apexBundle) data := android.AndroidMkDataForTest(t, ctx, apexBundle) name := apexBundle.BaseModuleName() prefix := "TARGET_" @@ -4442,6 +4624,59 @@ func TestPrebuiltOverrides(t *testing.T) { } } +func TestPrebuiltApexName(t *testing.T) { + testApex(t, ` + prebuilt_apex { + name: "com.company.android.myapex", + apex_name: "com.android.myapex", + src: "company-myapex-arm.apex", + } + `).ModuleForTests("com.company.android.myapex", "android_common_com.android.myapex") + + testApex(t, ` + apex_set { + name: "com.company.android.myapex", + apex_name: "com.android.myapex", + set: "company-myapex.apks", + } + `).ModuleForTests("com.company.android.myapex", "android_common_com.android.myapex") +} + +func TestPrebuiltApexNameWithPlatformBootclasspath(t *testing.T) { + _ = android.GroupFixturePreparers( + java.PrepareForTestWithJavaDefaultModules, + PrepareForTestWithApexBuildComponents, + android.FixtureWithRootAndroidBp(` + platform_bootclasspath { + name: "platform-bootclasspath", + fragments: [ + { + apex: "com.android.art", + module: "art-bootclasspath-fragment", + }, + ], + } + + prebuilt_apex { + name: "com.company.android.art", + apex_name: "com.android.art", + src: "com.company.android.art-arm.apex", + exported_bootclasspath_fragments: ["art-bootclasspath-fragment"], + } + + prebuilt_bootclasspath_fragment { + name: "art-bootclasspath-fragment", + contents: ["core-oj"], + } + + java_import { + name: "core-oj", + jars: ["prebuilt.jar"], + } + `), + ).RunTest(t) +} + // These tests verify that the prebuilt_apex/deapexer to java_import wiring allows for the // propagation of paths to dex implementation jars from the former to the latter. func TestPrebuiltExportDexImplementationJars(t *testing.T) { diff --git a/apex/bootclasspath_fragment_test.go b/apex/bootclasspath_fragment_test.go index 66bc9e069..4b1600e1c 100644 --- a/apex/bootclasspath_fragment_test.go +++ b/apex/bootclasspath_fragment_test.go @@ -22,6 +22,7 @@ import ( "android/soong/android" "android/soong/java" + "github.com/google/blueprint/proptools" ) // Contains tests for bootclasspath_fragment logic from java/bootclasspath_fragment.go as the ART @@ -216,9 +217,10 @@ func TestBootclasspathFragments_FragmentDependency(t *testing.T) { `, ) - checkSdkKindStubs := func(message string, info java.HiddenAPIInfo, kind android.SdkKind, expectedPaths ...string) { + checkAPIScopeStubs := func(message string, info java.HiddenAPIInfo, apiScope *java.HiddenAPIScope, expectedPaths ...string) { t.Helper() - android.AssertPathsRelativeToTopEquals(t, fmt.Sprintf("%s %s", message, kind), expectedPaths, info.TransitiveStubDexJarsByKind[kind]) + paths := info.TransitiveStubDexJarsByScope.StubDexJarsForScope(apiScope) + android.AssertPathsRelativeToTopEquals(t, fmt.Sprintf("%s %s", message, apiScope), expectedPaths, paths) } // Check stub dex paths exported by art. @@ -229,10 +231,10 @@ func TestBootclasspathFragments_FragmentDependency(t *testing.T) { bazSystemStubs := "out/soong/.intermediates/baz.stubs.system/android_common/dex/baz.stubs.system.jar" bazTestStubs := "out/soong/.intermediates/baz.stubs.test/android_common/dex/baz.stubs.test.jar" - checkSdkKindStubs("art", artInfo, android.SdkPublic, bazPublicStubs) - checkSdkKindStubs("art", artInfo, android.SdkSystem, bazSystemStubs) - checkSdkKindStubs("art", artInfo, android.SdkTest, bazTestStubs) - checkSdkKindStubs("art", artInfo, android.SdkCorePlatform) + checkAPIScopeStubs("art", artInfo, java.PublicHiddenAPIScope, bazPublicStubs) + checkAPIScopeStubs("art", artInfo, java.SystemHiddenAPIScope, bazSystemStubs) + checkAPIScopeStubs("art", artInfo, java.TestHiddenAPIScope, bazTestStubs) + checkAPIScopeStubs("art", artInfo, java.CorePlatformHiddenAPIScope) // Check stub dex paths exported by other. otherFragment := result.Module("other-bootclasspath-fragment", "android_common") @@ -241,10 +243,10 @@ func TestBootclasspathFragments_FragmentDependency(t *testing.T) { fooPublicStubs := "out/soong/.intermediates/foo.stubs/android_common/dex/foo.stubs.jar" fooSystemStubs := "out/soong/.intermediates/foo.stubs.system/android_common/dex/foo.stubs.system.jar" - checkSdkKindStubs("other", otherInfo, android.SdkPublic, bazPublicStubs, fooPublicStubs) - checkSdkKindStubs("other", otherInfo, android.SdkSystem, bazSystemStubs, fooSystemStubs) - checkSdkKindStubs("other", otherInfo, android.SdkTest, bazTestStubs, fooSystemStubs) - checkSdkKindStubs("other", otherInfo, android.SdkCorePlatform) + checkAPIScopeStubs("other", otherInfo, java.PublicHiddenAPIScope, bazPublicStubs, fooPublicStubs) + checkAPIScopeStubs("other", otherInfo, java.SystemHiddenAPIScope, bazSystemStubs, fooSystemStubs) + checkAPIScopeStubs("other", otherInfo, java.TestHiddenAPIScope, bazTestStubs, fooSystemStubs) + checkAPIScopeStubs("other", otherInfo, java.CorePlatformHiddenAPIScope) } func checkBootclasspathFragment(t *testing.T, result *android.TestResult, moduleName, variantName string, expectedConfiguredModules string, expectedBootclasspathFragmentFiles string) { @@ -718,4 +720,480 @@ func TestBootclasspathFragmentContentsNoName(t *testing.T) { checkFragmentExportedDexJar("bar", "out/soong/.intermediates/mybootclasspathfragment/android_common_apex10000/hiddenapi-modular/encoded/bar.jar") } +func getDexJarPath(result *android.TestResult, name string) string { + module := result.Module(name, "android_common") + return module.(java.UsesLibraryDependency).DexJarBuildPath().RelativeToTop().String() +} + +// TestBootclasspathFragment_HiddenAPIList checks to make sure that the correct parameters are +// passed to the hiddenapi list tool. +func TestBootclasspathFragment_HiddenAPIList(t *testing.T) { + result := android.GroupFixturePreparers( + prepareForTestWithBootclasspathFragment, + prepareForTestWithArtApex, + prepareForTestWithMyapex, + // Configure bootclasspath jars to ensure that hidden API encoding is performed on them. + java.FixtureConfigureBootJars("com.android.art:baz", "com.android.art:quuz"), + java.FixtureConfigureUpdatableBootJars("myapex:foo", "myapex:bar"), + // Make sure that the frameworks/base/Android.bp file exists as otherwise hidden API encoding + // is disabled. + android.FixtureAddTextFile("frameworks/base/Android.bp", ""), + + java.PrepareForTestWithJavaSdkLibraryFiles, + java.FixtureWithLastReleaseApis("foo", "quuz"), + ).RunTestWithBp(t, ` + apex { + name: "com.android.art", + key: "com.android.art.key", + bootclasspath_fragments: ["art-bootclasspath-fragment"], + updatable: false, + } + + apex_key { + name: "com.android.art.key", + public_key: "com.android.art.avbpubkey", + private_key: "com.android.art.pem", + } + + java_library { + name: "baz", + apex_available: [ + "com.android.art", + ], + srcs: ["b.java"], + compile_dex: true, + } + + java_sdk_library { + name: "quuz", + apex_available: [ + "com.android.art", + ], + srcs: ["b.java"], + compile_dex: true, + public: {enabled: true}, + system: {enabled: true}, + test: {enabled: true}, + module_lib: {enabled: true}, + } + + bootclasspath_fragment { + name: "art-bootclasspath-fragment", + image_name: "art", + // Must match the "com.android.art:" entries passed to FixtureConfigureBootJars above. + contents: ["baz", "quuz"], + apex_available: [ + "com.android.art", + ], + } + + apex { + name: "myapex", + key: "myapex.key", + bootclasspath_fragments: [ + "mybootclasspathfragment", + ], + updatable: false, + } + + apex_key { + name: "myapex.key", + public_key: "testkey.avbpubkey", + private_key: "testkey.pem", + } + + java_sdk_library { + name: "foo", + srcs: ["b.java"], + shared_library: false, + public: {enabled: true}, + apex_available: [ + "myapex", + ], + } + + java_library { + name: "bar", + srcs: ["b.java"], + installable: true, + apex_available: [ + "myapex", + ], + } + + bootclasspath_fragment { + name: "mybootclasspathfragment", + contents: [ + "foo", + "bar", + ], + apex_available: [ + "myapex", + ], + fragments: [ + { + apex: "com.android.art", + module: "art-bootclasspath-fragment", + }, + ], + } + `) + + java.CheckModuleDependencies(t, result.TestContext, "mybootclasspathfragment", "android_common_apex10000", []string{ + "art-bootclasspath-fragment", + "bar", + "dex2oatd", + "foo", + }) + + fooStubs := getDexJarPath(result, "foo.stubs") + quuzPublicStubs := getDexJarPath(result, "quuz.stubs") + quuzSystemStubs := getDexJarPath(result, "quuz.stubs.system") + quuzTestStubs := getDexJarPath(result, "quuz.stubs.test") + quuzModuleLibStubs := getDexJarPath(result, "quuz.stubs.module_lib") + + // Make sure that the fragment uses the quuz stub dex jars when generating the hidden API flags. + fragment := result.ModuleForTests("mybootclasspathfragment", "android_common_apex10000") + + rule := fragment.Rule("modularHiddenAPIStubFlagsFile") + command := rule.RuleParams.Command + android.AssertStringDoesContain(t, "check correct rule", command, "hiddenapi list") + + // Make sure that the quuz stubs are available for resolving references from the implementation + // boot dex jars provided by this module. + android.AssertStringDoesContain(t, "quuz widest", command, "--dependency-stub-dex="+quuzModuleLibStubs) + + // Make sure that the quuz stubs are available for resolving references from the different API + // stubs provided by this module. + android.AssertStringDoesContain(t, "public", command, "--public-stub-classpath="+quuzPublicStubs+":"+fooStubs) + android.AssertStringDoesContain(t, "system", command, "--system-stub-classpath="+quuzSystemStubs+":"+fooStubs) + android.AssertStringDoesContain(t, "test", command, "--test-stub-classpath="+quuzTestStubs+":"+fooStubs) +} + +// TestBootclasspathFragment_AndroidNonUpdatable checks to make sure that setting +// additional_stubs: ["android-non-updatable"] causes the source android-non-updatable modules to be +// added to the hiddenapi list tool. +func TestBootclasspathFragment_AndroidNonUpdatable(t *testing.T) { + result := android.GroupFixturePreparers( + prepareForTestWithBootclasspathFragment, + prepareForTestWithArtApex, + prepareForTestWithMyapex, + // Configure bootclasspath jars to ensure that hidden API encoding is performed on them. + java.FixtureConfigureBootJars("com.android.art:baz", "com.android.art:quuz", "myapex:foo", "myapex:bar"), + // Make sure that the frameworks/base/Android.bp file exists as otherwise hidden API encoding + // is disabled. + android.FixtureAddTextFile("frameworks/base/Android.bp", ""), + + java.PrepareForTestWithJavaSdkLibraryFiles, + java.FixtureWithLastReleaseApis("foo", "android-non-updatable"), + ).RunTestWithBp(t, ` + java_sdk_library { + name: "android-non-updatable", + srcs: ["b.java"], + compile_dex: true, + public: { + enabled: true, + }, + system: { + enabled: true, + }, + test: { + enabled: true, + }, + module_lib: { + enabled: true, + }, + } + + apex { + name: "com.android.art", + key: "com.android.art.key", + bootclasspath_fragments: ["art-bootclasspath-fragment"], + java_libs: [ + "baz", + "quuz", + ], + updatable: false, + } + + apex_key { + name: "com.android.art.key", + public_key: "com.android.art.avbpubkey", + private_key: "com.android.art.pem", + } + + java_library { + name: "baz", + apex_available: [ + "com.android.art", + ], + srcs: ["b.java"], + compile_dex: true, + } + + java_library { + name: "quuz", + apex_available: [ + "com.android.art", + ], + srcs: ["b.java"], + compile_dex: true, + } + + bootclasspath_fragment { + name: "art-bootclasspath-fragment", + image_name: "art", + // Must match the "com.android.art:" entries passed to FixtureConfigureBootJars above. + contents: ["baz", "quuz"], + apex_available: [ + "com.android.art", + ], + } + + apex { + name: "myapex", + key: "myapex.key", + bootclasspath_fragments: [ + "mybootclasspathfragment", + ], + updatable: false, + } + + apex_key { + name: "myapex.key", + public_key: "testkey.avbpubkey", + private_key: "testkey.pem", + } + + java_sdk_library { + name: "foo", + srcs: ["b.java"], + shared_library: false, + public: {enabled: true}, + apex_available: [ + "myapex", + ], + } + + java_library { + name: "bar", + srcs: ["b.java"], + installable: true, + apex_available: [ + "myapex", + ], + } + + bootclasspath_fragment { + name: "mybootclasspathfragment", + contents: [ + "foo", + "bar", + ], + apex_available: [ + "myapex", + ], + additional_stubs: ["android-non-updatable"], + fragments: [ + { + apex: "com.android.art", + module: "art-bootclasspath-fragment", + }, + ], + } + `) + + java.CheckModuleDependencies(t, result.TestContext, "mybootclasspathfragment", "android_common_apex10000", []string{ + "android-non-updatable.stubs", + "android-non-updatable.stubs.module_lib", + "android-non-updatable.stubs.system", + "android-non-updatable.stubs.test", + "art-bootclasspath-fragment", + "bar", + "dex2oatd", + "foo", + }) + + nonUpdatablePublicStubs := getDexJarPath(result, "android-non-updatable.stubs") + nonUpdatableSystemStubs := getDexJarPath(result, "android-non-updatable.stubs.system") + nonUpdatableTestStubs := getDexJarPath(result, "android-non-updatable.stubs.test") + nonUpdatableModuleLibStubs := getDexJarPath(result, "android-non-updatable.stubs.module_lib") + + // Make sure that the fragment uses the android-non-updatable modules when generating the hidden + // API flags. + fragment := result.ModuleForTests("mybootclasspathfragment", "android_common_apex10000") + + rule := fragment.Rule("modularHiddenAPIStubFlagsFile") + command := rule.RuleParams.Command + android.AssertStringDoesContain(t, "check correct rule", command, "hiddenapi list") + + // Make sure that the module_lib non-updatable stubs are available for resolving references from + // the implementation boot dex jars provided by this module. + android.AssertStringDoesContain(t, "android-non-updatable widest", command, "--dependency-stub-dex="+nonUpdatableModuleLibStubs) + + // Make sure that the appropriate non-updatable stubs are available for resolving references from + // the different API stubs provided by this module. + android.AssertStringDoesContain(t, "public", command, "--public-stub-classpath="+nonUpdatablePublicStubs) + android.AssertStringDoesContain(t, "system", command, "--system-stub-classpath="+nonUpdatableSystemStubs) + android.AssertStringDoesContain(t, "test", command, "--test-stub-classpath="+nonUpdatableTestStubs) +} + +// TestBootclasspathFragment_AndroidNonUpdatable_AlwaysUsePrebuiltSdks checks to make sure that +// setting additional_stubs: ["android-non-updatable"] causes the prebuilt android-non-updatable +// modules to be added to the hiddenapi list tool. +func TestBootclasspathFragment_AndroidNonUpdatable_AlwaysUsePrebuiltSdks(t *testing.T) { + result := android.GroupFixturePreparers( + prepareForTestWithBootclasspathFragment, + java.PrepareForTestWithJavaDefaultModules, + prepareForTestWithArtApex, + prepareForTestWithMyapex, + // Configure bootclasspath jars to ensure that hidden API encoding is performed on them. + java.FixtureConfigureBootJars("com.android.art:baz", "com.android.art:quuz", "myapex:foo", "myapex:bar"), + // Make sure that the frameworks/base/Android.bp file exists as otherwise hidden API encoding + // is disabled. + android.FixtureAddTextFile("frameworks/base/Android.bp", ""), + + android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) { + variables.Always_use_prebuilt_sdks = proptools.BoolPtr(true) + }), + + java.PrepareForTestWithJavaSdkLibraryFiles, + java.FixtureWithPrebuiltApis(map[string][]string{ + "current": {"android-non-updatable"}, + "30": {"foo"}, + }), + ).RunTestWithBp(t, ` + apex { + name: "com.android.art", + key: "com.android.art.key", + bootclasspath_fragments: ["art-bootclasspath-fragment"], + java_libs: [ + "baz", + "quuz", + ], + updatable: false, + } + + apex_key { + name: "com.android.art.key", + public_key: "com.android.art.avbpubkey", + private_key: "com.android.art.pem", + } + + java_library { + name: "baz", + apex_available: [ + "com.android.art", + ], + srcs: ["b.java"], + compile_dex: true, + } + + java_library { + name: "quuz", + apex_available: [ + "com.android.art", + ], + srcs: ["b.java"], + compile_dex: true, + } + + bootclasspath_fragment { + name: "art-bootclasspath-fragment", + image_name: "art", + // Must match the "com.android.art:" entries passed to FixtureConfigureBootJars above. + contents: ["baz", "quuz"], + apex_available: [ + "com.android.art", + ], + } + + apex { + name: "myapex", + key: "myapex.key", + bootclasspath_fragments: [ + "mybootclasspathfragment", + ], + updatable: false, + } + + apex_key { + name: "myapex.key", + public_key: "testkey.avbpubkey", + private_key: "testkey.pem", + } + + java_sdk_library { + name: "foo", + srcs: ["b.java"], + shared_library: false, + public: {enabled: true}, + apex_available: [ + "myapex", + ], + } + + java_library { + name: "bar", + srcs: ["b.java"], + installable: true, + apex_available: [ + "myapex", + ], + } + + bootclasspath_fragment { + name: "mybootclasspathfragment", + contents: [ + "foo", + "bar", + ], + apex_available: [ + "myapex", + ], + additional_stubs: ["android-non-updatable"], + fragments: [ + { + apex: "com.android.art", + module: "art-bootclasspath-fragment", + }, + ], + } + `) + + java.CheckModuleDependencies(t, result.TestContext, "mybootclasspathfragment", "android_common_apex10000", []string{ + "art-bootclasspath-fragment", + "bar", + "dex2oatd", + "foo", + "prebuilt_sdk_module-lib_current_android-non-updatable", + "prebuilt_sdk_public_current_android-non-updatable", + "prebuilt_sdk_system_current_android-non-updatable", + "prebuilt_sdk_test_current_android-non-updatable", + }) + + nonUpdatablePublicStubs := getDexJarPath(result, "sdk_public_current_android-non-updatable") + nonUpdatableSystemStubs := getDexJarPath(result, "sdk_system_current_android-non-updatable") + nonUpdatableTestStubs := getDexJarPath(result, "sdk_test_current_android-non-updatable") + nonUpdatableModuleLibStubs := getDexJarPath(result, "sdk_module-lib_current_android-non-updatable") + + // Make sure that the fragment uses the android-non-updatable modules when generating the hidden + // API flags. + fragment := result.ModuleForTests("mybootclasspathfragment", "android_common_apex10000") + + rule := fragment.Rule("modularHiddenAPIStubFlagsFile") + command := rule.RuleParams.Command + android.AssertStringDoesContain(t, "check correct rule", command, "hiddenapi list") + + // Make sure that the module_lib non-updatable stubs are available for resolving references from + // the implementation boot dex jars provided by this module. + android.AssertStringDoesContain(t, "android-non-updatable widest", command, "--dependency-stub-dex="+nonUpdatableModuleLibStubs) + + // Make sure that the appropriate non-updatable stubs are available for resolving references from + // the different API stubs provided by this module. + android.AssertStringDoesContain(t, "public", command, "--public-stub-classpath="+nonUpdatablePublicStubs) + android.AssertStringDoesContain(t, "system", command, "--system-stub-classpath="+nonUpdatableSystemStubs) + android.AssertStringDoesContain(t, "test", command, "--test-stub-classpath="+nonUpdatableTestStubs) +} + // TODO(b/177892522) - add test for host apex. 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/apex/prebuilt.go b/apex/prebuilt.go index ea06d45cb..1bb0fb582 100644 --- a/apex/prebuilt.go +++ b/apex/prebuilt.go @@ -24,7 +24,6 @@ import ( "android/soong/java" "github.com/google/blueprint" - "github.com/google/blueprint/proptools" ) @@ -76,6 +75,10 @@ type sanitizedPrebuilt interface { type PrebuiltCommonProperties struct { SelectedApexProperties + // Canonical name of this APEX. Used to determine the path to the activated APEX on + // device (/apex/<apex_name>). If unspecified, follows the name property. + Apex_name *string + ForceDisable bool `blueprint:"mutated"` // whether the extracted apex file is installable. @@ -110,6 +113,10 @@ func (p *prebuiltCommon) initPrebuiltCommon(module android.Module, properties *P android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon) } +func (p *prebuiltCommon) ApexVariationName() string { + return proptools.StringDefault(p.prebuiltCommonProperties.Apex_name, p.ModuleBase.BaseModuleName()) +} + func (p *prebuiltCommon) Prebuilt() *android.Prebuilt { return &p.prebuilt } @@ -369,6 +376,12 @@ func (p *prebuiltCommon) apexInfoMutator(mctx android.TopDownMutatorContext) { } } + // Ignore any modules that do not implement ApexModule as they cannot have an APEX specific + // variant. + if _, ok := child.(android.ApexModule); !ok { + return false + } + // Strip off the prebuilt_ prefix if present before storing content to ensure consistent // behavior whether there is a corresponding source module present or not. depName = android.RemoveOptionalPrebuiltPrefix(depName) @@ -390,11 +403,11 @@ func (p *prebuiltCommon) apexInfoMutator(mctx android.TopDownMutatorContext) { }) // Create an ApexInfo for the prebuilt_apex. - apexVariationName := android.RemoveOptionalPrebuiltPrefix(mctx.ModuleName()) + apexVariationName := p.ApexVariationName() apexInfo := android.ApexInfo{ ApexVariationName: apexVariationName, InApexVariants: []string{apexVariationName}, - InApexModules: []string{apexVariationName}, + InApexModules: []string{p.ModuleBase.BaseModuleName()}, // BaseModuleName() to avoid the prebuilt_ prefix. ApexContents: []*android.ApexContents{apexContents}, ForPrebuiltApex: true, } |