diff options
Diffstat (limited to 'apex')
-rw-r--r-- | apex/Android.bp | 2 | ||||
-rw-r--r-- | apex/apex.go | 11 | ||||
-rw-r--r-- | apex/apex_test.go | 841 | ||||
-rw-r--r-- | apex/bootclasspath_fragment_test.go | 27 | ||||
-rw-r--r-- | apex/builder.go | 1 | ||||
-rw-r--r-- | apex/deapexer.go | 84 | ||||
-rw-r--r-- | apex/dexpreopt_bootjars_test.go | 23 | ||||
-rw-r--r-- | apex/prebuilt.go | 324 | ||||
-rw-r--r-- | apex/systemserver_classpath_fragment_test.go | 8 |
9 files changed, 456 insertions, 865 deletions
diff --git a/apex/Android.bp b/apex/Android.bp index ef2f75570..4848513f2 100644 --- a/apex/Android.bp +++ b/apex/Android.bp @@ -42,4 +42,6 @@ bootstrap_go_package { "systemserver_classpath_fragment_test.go", ], pluginFor: ["soong_build"], + // Used by plugins + visibility: ["//visibility:public"], } diff --git a/apex/apex.go b/apex/apex.go index ff39597ea..ded21753c 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -49,15 +49,10 @@ func registerApexBuildComponents(ctx android.RegistrationContext) { ctx.RegisterModuleType("override_apex", OverrideApexFactory) ctx.RegisterModuleType("apex_set", apexSetFactory) - ctx.PreArchMutators(registerPreArchMutators) ctx.PreDepsMutators(RegisterPreDepsMutators) ctx.PostDepsMutators(RegisterPostDepsMutators) } -func registerPreArchMutators(ctx android.RegisterMutatorsContext) { - ctx.BottomUp("prebuilt_apex_module_creator", prebuiltApexModuleCreatorMutator).Parallel() -} - func RegisterPreDepsMutators(ctx android.RegisterMutatorsContext) { ctx.BottomUp("apex_vndk_deps", apexVndkDepsMutator).Parallel() } @@ -2759,6 +2754,12 @@ func (a *apexBundle) checkApexAvailability(ctx android.ModuleContext) { return } + // Temporarily bypass /product APEXes with a specific prefix. + // TODO: b/352818241 - Remove this after APEX availability is enforced for /product APEXes. + if a.ProductSpecific() && strings.HasPrefix(a.ApexVariationName(), "com.sdv.") { + return + } + // Coverage build adds additional dependencies for the coverage-only runtime libraries. // Requiring them and their transitive depencies with apex_available is not right // because they just add noise. diff --git a/apex/apex_test.go b/apex/apex_test.go index 2b9772821..ad0bb177d 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -3685,7 +3685,7 @@ func ensureExactContents(t *testing.T, ctx *android.TestContext, moduleName, var } func ensureExactDeapexedContents(t *testing.T, ctx *android.TestContext, moduleName string, variant string, files []string) { - deapexer := ctx.ModuleForTests(moduleName+".deapexer", variant).Description("deapex") + deapexer := ctx.ModuleForTests(moduleName, variant).Description("deapex") outputs := make([]string, 0, len(deapexer.ImplicitOutputs)+1) if deapexer.Output != nil { outputs = append(outputs, deapexer.Output.String()) @@ -4885,236 +4885,6 @@ type moduleErrorfTestCtx struct { func (ctx moduleErrorfTestCtx) ModuleErrorf(format string, args ...interface{}) { } -// 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) { - transform := android.NullFixturePreparer - - checkDexJarBuildPath := func(t *testing.T, ctx *android.TestContext, name string) { - t.Helper() - // Make sure the import has been given the correct path to the dex jar. - p := ctx.ModuleForTests(name, "android_common_myapex").Module().(java.UsesLibraryDependency) - dexJarBuildPath := p.DexJarBuildPath(moduleErrorfTestCtx{}).PathOrNil() - stem := android.RemoveOptionalPrebuiltPrefix(name) - android.AssertStringEquals(t, "DexJarBuildPath should be apex-related path.", - ".intermediates/prebuilt_myapex.deapexer/android_common/deapexer/javalib/"+stem+".jar", - android.NormalizePathForTesting(dexJarBuildPath)) - } - - checkDexJarInstallPath := func(t *testing.T, ctx *android.TestContext, name string) { - t.Helper() - // Make sure the import has been given the correct path to the dex jar. - p := ctx.ModuleForTests(name, "android_common_myapex").Module().(java.UsesLibraryDependency) - dexJarBuildPath := p.DexJarInstallPath() - stem := android.RemoveOptionalPrebuiltPrefix(name) - android.AssertStringEquals(t, "DexJarInstallPath should be apex-related path.", - "target/product/test_device/apex/myapex/javalib/"+stem+".jar", - android.NormalizePathForTesting(dexJarBuildPath)) - } - - ensureNoSourceVariant := func(t *testing.T, ctx *android.TestContext, name string) { - t.Helper() - // Make sure that an apex variant is not created for the source module. - android.AssertArrayString(t, "Check if there is no source variant", - []string{"android_common"}, - ctx.ModuleVariantsForTests(name)) - } - - t.Run("prebuilt only", func(t *testing.T) { - bp := ` - prebuilt_apex { - name: "myapex", - arch: { - arm64: { - src: "myapex-arm64.apex", - }, - arm: { - src: "myapex-arm.apex", - }, - }, - exported_java_libs: ["libfoo", "libbar"], - } - - java_import { - name: "libfoo", - jars: ["libfoo.jar"], - sdk_version: "core_current", - } - - java_sdk_library_import { - name: "libbar", - public: { - jars: ["libbar.jar"], - }, - } - ` - - // Make sure that dexpreopt can access dex implementation files from the prebuilt. - ctx := testDexpreoptWithApexes(t, bp, "", transform) - - deapexerName := deapexerModuleName("prebuilt_myapex") - android.AssertStringEquals(t, "APEX module name from deapexer name", "prebuilt_myapex", apexModuleName(deapexerName)) - - // Make sure that the deapexer has the correct input APEX. - deapexer := ctx.ModuleForTests(deapexerName, "android_common") - rule := deapexer.Rule("deapexer") - if expected, actual := []string{"myapex-arm64.apex"}, android.NormalizePathsForTesting(rule.Implicits); !reflect.DeepEqual(expected, actual) { - t.Errorf("expected: %q, found: %q", expected, actual) - } - - // Make sure that the prebuilt_apex has the correct input APEX. - prebuiltApex := ctx.ModuleForTests("myapex", "android_common_myapex") - rule = prebuiltApex.Rule("android/soong/android.Cp") - if expected, actual := "myapex-arm64.apex", android.NormalizePathForTesting(rule.Input); !reflect.DeepEqual(expected, actual) { - t.Errorf("expected: %q, found: %q", expected, actual) - } - - checkDexJarBuildPath(t, ctx, "libfoo") - checkDexJarInstallPath(t, ctx, "libfoo") - - checkDexJarBuildPath(t, ctx, "libbar") - checkDexJarInstallPath(t, ctx, "libbar") - }) - - t.Run("prebuilt with source preferred", func(t *testing.T) { - - bp := ` - apex { - name: "myapex", - key: "myapex.key", - updatable: false, - java_libs: [ - "libfoo", - "libbar", - ], - } - - apex_key { - name: "myapex.key", - public_key: "testkey.avbpubkey", - private_key: "testkey.pem", - } - - prebuilt_apex { - name: "myapex", - arch: { - arm64: { - src: "myapex-arm64.apex", - }, - arm: { - src: "myapex-arm.apex", - }, - }, - exported_java_libs: ["libfoo", "libbar"], - } - - java_import { - name: "libfoo", - jars: ["libfoo.jar"], - apex_available: [ - "myapex", - ], - compile_dex: true, - sdk_version: "core_current", - } - - java_library { - name: "libfoo", - srcs: ["foo/bar/MyClass.java"], - apex_available: [ - "myapex", - ], - compile_dex: true, - sdk_version: "core_current", - } - - java_sdk_library_import { - name: "libbar", - public: { - jars: ["libbar.jar"], - }, - apex_available: [ - "myapex", - ], - compile_dex: true, - } - - java_sdk_library { - name: "libbar", - srcs: ["foo/bar/MyClass.java"], - unsafe_ignore_missing_latest_api: true, - apex_available: [ - "myapex", - ], - compile_dex: true, - sdk_version: "core_current", - } - ` - - // Make sure that dexpreopt can access dex implementation files from the prebuilt. - ctx := testDexpreoptWithApexes(t, bp, "", transform) - - checkDexJarBuildPath(t, ctx, "prebuilt_libfoo") - checkDexJarInstallPath(t, ctx, "prebuilt_libfoo") - - checkDexJarBuildPath(t, ctx, "prebuilt_libbar") - checkDexJarInstallPath(t, ctx, "prebuilt_libbar") - }) - - t.Run("prebuilt preferred with source", func(t *testing.T) { - bp := ` - prebuilt_apex { - name: "myapex", - arch: { - arm64: { - src: "myapex-arm64.apex", - }, - arm: { - src: "myapex-arm.apex", - }, - }, - exported_java_libs: ["libfoo", "libbar"], - } - - java_import { - name: "libfoo", - prefer: true, - jars: ["libfoo.jar"], - } - - java_library { - name: "libfoo", - sdk_version: "core_current", - } - - java_sdk_library_import { - name: "libbar", - prefer: true, - public: { - jars: ["libbar.jar"], - }, - } - - java_sdk_library { - name: "libbar", - srcs: ["foo/bar/MyClass.java"], - unsafe_ignore_missing_latest_api: true, - } - ` - - // Make sure that dexpreopt can access dex implementation files from the prebuilt. - ctx := testDexpreoptWithApexes(t, bp, "", transform) - - checkDexJarBuildPath(t, ctx, "prebuilt_libfoo") - checkDexJarInstallPath(t, ctx, "prebuilt_libfoo") - ensureNoSourceVariant(t, ctx, "libfoo") - - checkDexJarBuildPath(t, ctx, "prebuilt_libbar") - checkDexJarInstallPath(t, ctx, "prebuilt_libbar") - ensureNoSourceVariant(t, ctx, "libbar") - }) -} - func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) { preparer := android.GroupFixturePreparers( java.FixtureConfigureApexBootJars("myapex:libfoo", "myapex:libbar"), @@ -5137,23 +4907,6 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) { }), ) - checkBootDexJarPath := func(t *testing.T, ctx *android.TestContext, stem string, bootDexJarPath string) { - t.Helper() - s := ctx.ModuleForTests("dex_bootjars", "android_common") - foundLibfooJar := false - base := stem + ".jar" - for _, output := range s.AllOutputs() { - if filepath.Base(output) == base { - foundLibfooJar = true - buildRule := s.Output(output) - android.AssertStringEquals(t, "boot dex jar path", bootDexJarPath, buildRule.Input.String()) - } - } - if !foundLibfooJar { - t.Errorf("Rule for libfoo.jar missing in dex_bootjars singleton outputs %q", android.StringPathsRelativeToTop(ctx.Config().SoongOutDir(), s.AllOutputs())) - } - } - checkHiddenAPIIndexFromClassesInputs := func(t *testing.T, ctx *android.TestContext, expectedIntermediateInputs string) { t.Helper() platformBootclasspath := ctx.ModuleForTests("platform-bootclasspath", "android_common") @@ -5206,12 +4959,14 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) { }, } - java_import { + java_sdk_library_import { name: "libfoo", - jars: ["libfoo.jar"], + public: { + jars: ["libfoo.jar"], + }, apex_available: ["myapex"], + shared_library: false, permitted_packages: ["foo"], - sdk_version: "core_current", } java_sdk_library_import { @@ -5226,8 +4981,6 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) { ` ctx := testDexpreoptWithApexes(t, bp, "", preparer, fragment) - checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/prebuilt_myapex.deapexer/android_common/deapexer/javalib/libfoo.jar") - checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/prebuilt_myapex.deapexer/android_common/deapexer/javalib/libbar.jar") // Verify the correct module jars contribute to the hiddenapi index file. checkHiddenAPIIndexFromClassesInputs(t, ctx, `out/soong/.intermediates/platform/foo/android_common/javac/foo.jar`) @@ -5243,18 +4996,10 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) { apex_set { name: "myapex", set: "myapex.apks", - exported_java_libs: ["myjavalib"], exported_bootclasspath_fragments: ["my-bootclasspath-fragment"], exported_systemserverclasspath_fragments: ["my-systemserverclasspath-fragment"], } - java_import { - name: "myjavalib", - jars: ["myjavalib.jar"], - apex_available: ["myapex"], - permitted_packages: ["javalib"], - } - prebuilt_bootclasspath_fragment { name: "my-bootclasspath-fragment", contents: ["libfoo", "libbar"], @@ -5275,13 +5020,17 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) { apex_available: ["myapex"], } - java_import { + java_sdk_library_import { name: "libfoo", - jars: ["libfoo.jar"], + public: { + jars: ["libfoo.jar"], + }, apex_available: ["myapex"], - permitted_packages: ["foo"], + shared_library: false, + permitted_packages: ["libfoo"], } + java_sdk_library_import { name: "libbar", public: { @@ -5304,8 +5053,6 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) { ` ctx := testDexpreoptWithApexes(t, bp, "", preparer, fragment) - checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/prebuilt_myapex.deapexer/android_common/deapexer/javalib/libfoo.jar") - checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/prebuilt_myapex.deapexer/android_common/deapexer/javalib/libbar.jar") // Verify the correct module jars contribute to the hiddenapi index file. checkHiddenAPIIndexFromClassesInputs(t, ctx, `out/soong/.intermediates/platform/foo/android_common/javac/foo.jar`) @@ -5459,13 +5206,15 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) { }, } - java_import { + java_sdk_library_import { name: "libfoo", prefer: true, - jars: ["libfoo.jar"], + public: { + jars: ["libfoo.jar"], + }, apex_available: ["myapex"], - permitted_packages: ["foo"], - sdk_version: "core_current", + shared_library: false, + permitted_packages: ["libfoo"], } java_library { @@ -5497,8 +5246,6 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) { ` ctx := testDexpreoptWithApexes(t, bp, "", preparer, fragment) - checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/prebuilt_myapex.deapexer/android_common/deapexer/javalib/libfoo.jar") - checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/prebuilt_myapex.deapexer/android_common/deapexer/javalib/libbar.jar") // Verify the correct module jars contribute to the hiddenapi index file. checkHiddenAPIIndexFromClassesInputs(t, ctx, `out/soong/.intermediates/platform/foo/android_common/javac/foo.jar`) @@ -5597,8 +5344,6 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) { ` ctx := testDexpreoptWithApexes(t, bp, "", preparer, fragment) - checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/my-bootclasspath-fragment/android_common_myapex/hiddenapi-modular/encoded/libfoo.jar") - checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/my-bootclasspath-fragment/android_common_myapex/hiddenapi-modular/encoded/libbar.jar") // Verify the correct module jars contribute to the hiddenapi index file. checkHiddenAPIIndexFromClassesInputs(t, ctx, `out/soong/.intermediates/platform/foo/android_common/javac/foo.jar`) @@ -5710,8 +5455,6 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) { ) ctx := testDexpreoptWithApexes(t, bp, "", preparer2, fragment) - checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/prebuilt_myapex.deapexer/android_common/deapexer/javalib/libfoo.jar") - checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/prebuilt_myapex.deapexer/android_common/deapexer/javalib/libbar.jar") // Verify the correct module jars contribute to the hiddenapi index file. checkHiddenAPIIndexFromClassesInputs(t, ctx, `out/soong/.intermediates/platform/foo/android_common/javac/foo.jar`) @@ -6270,6 +6013,87 @@ func TestApexAvailable_DirectDep(t *testing.T) { system_shared_libs: [], apex_available: ["otherapex"], }`) + + // 'apex_available' check is bypassed for /product apex with a specific prefix. + // TODO: b/352818241 - Remove below two cases after APEX availability is enforced for /product APEXes. + testApex(t, ` + apex { + name: "com.sdv.myapex", + key: "myapex.key", + native_shared_libs: ["libfoo"], + updatable: false, + product_specific: true, + } + + apex_key { + name: "myapex.key", + public_key: "testkey.avbpubkey", + private_key: "testkey.pem", + } + + apex { + name: "com.any.otherapex", + key: "otherapex.key", + native_shared_libs: ["libfoo"], + updatable: false, + } + + apex_key { + name: "otherapex.key", + public_key: "testkey.avbpubkey", + private_key: "testkey.pem", + } + + cc_library { + name: "libfoo", + stl: "none", + system_shared_libs: [], + apex_available: ["com.any.otherapex"], + product_specific: true, + }`, + android.FixtureMergeMockFs(android.MockFS{ + "system/sepolicy/apex/com.sdv.myapex-file_contexts": nil, + "system/sepolicy/apex/com.any.otherapex-file_contexts": nil, + })) + + // 'apex_available' check is not bypassed for non-product apex with a specific prefix. + testApexError(t, "requires \"libfoo\" that doesn't list the APEX under 'apex_available'.", ` + apex { + name: "com.sdv.myapex", + key: "myapex.key", + native_shared_libs: ["libfoo"], + updatable: false, + } + + apex_key { + name: "myapex.key", + public_key: "testkey.avbpubkey", + private_key: "testkey.pem", + } + + apex { + name: "com.any.otherapex", + key: "otherapex.key", + native_shared_libs: ["libfoo"], + updatable: false, + } + + apex_key { + name: "otherapex.key", + public_key: "testkey.avbpubkey", + private_key: "testkey.pem", + } + + cc_library { + name: "libfoo", + stl: "none", + system_shared_libs: [], + apex_available: ["com.any.otherapex"], + }`, + android.FixtureMergeMockFs(android.MockFS{ + "system/sepolicy/apex/com.sdv.myapex-file_contexts": nil, + "system/sepolicy/apex/com.any.otherapex-file_contexts": nil, + })) } func TestApexAvailable_IndirectDep(t *testing.T) { @@ -6315,6 +6139,91 @@ func TestApexAvailable_IndirectDep(t *testing.T) { stl: "none", system_shared_libs: [], }`) + + // 'apex_available' check is bypassed for /product apex with a specific prefix. + // TODO: b/352818241 - Remove below two cases after APEX availability is enforced for /product APEXes. + testApex(t, ` + apex { + name: "com.sdv.myapex", + key: "myapex.key", + native_shared_libs: ["libfoo"], + updatable: false, + product_specific: true, + } + + apex_key { + name: "myapex.key", + public_key: "testkey.avbpubkey", + private_key: "testkey.pem", + } + + cc_library { + name: "libfoo", + stl: "none", + shared_libs: ["libbar"], + system_shared_libs: [], + apex_available: ["com.sdv.myapex"], + product_specific: true, + } + + cc_library { + name: "libbar", + stl: "none", + shared_libs: ["libbaz"], + system_shared_libs: [], + apex_available: ["com.sdv.myapex"], + product_specific: true, + } + + cc_library { + name: "libbaz", + stl: "none", + system_shared_libs: [], + product_specific: true, + }`, + android.FixtureMergeMockFs(android.MockFS{ + "system/sepolicy/apex/com.sdv.myapex-file_contexts": nil, + })) + + // 'apex_available' check is not bypassed for non-product apex with a specific prefix. + testApexError(t, `requires "libbaz" that doesn't list the APEX under 'apex_available'.`, ` + apex { + name: "com.sdv.myapex", + key: "myapex.key", + native_shared_libs: ["libfoo"], + updatable: false, + } + + apex_key { + name: "myapex.key", + public_key: "testkey.avbpubkey", + private_key: "testkey.pem", + } + + cc_library { + name: "libfoo", + stl: "none", + shared_libs: ["libbar"], + system_shared_libs: [], + apex_available: ["com.sdv.myapex"], + } + + cc_library { + name: "libbar", + stl: "none", + shared_libs: ["libbaz"], + system_shared_libs: [], + apex_available: ["com.sdv.myapex"], + } + + cc_library { + name: "libbaz", + stl: "none", + system_shared_libs: [], + }`, + android.FixtureMergeMockFs(android.MockFS{ + "system/sepolicy/apex/com.sdv.myapex-file_contexts": nil, + })) } func TestApexAvailable_IndirectStaticDep(t *testing.T) { @@ -7339,7 +7248,7 @@ func TestJavaSDKLibrary_WithinApex(t *testing.T) { java_library { name: "bar", srcs: ["a.java"], - libs: ["foo"], + libs: ["foo.impl"], apex_available: ["myapex"], sdk_version: "none", system_modules: "none", @@ -7392,7 +7301,7 @@ func TestJavaSDKLibrary_CrossBoundary(t *testing.T) { java_library { name: "bar", srcs: ["a.java"], - libs: ["foo"], + libs: ["foo.stubs"], sdk_version: "none", system_modules: "none", } @@ -7446,7 +7355,7 @@ func TestJavaSDKLibrary_ImportPreferred(t *testing.T) { java_library { name: "bar", srcs: ["a.java"], - libs: ["foo"], + libs: ["foo.impl"], apex_available: ["myapex"], sdk_version: "none", system_modules: "none", @@ -8119,9 +8028,9 @@ func TestAppSetBundlePrebuilt(t *testing.T) { ctx := testApex(t, bp, prepareForTestWithSantitizeHwaddress) // Check that the extractor produces the correct output file from the correct input file. - extractorOutput := "out/soong/.intermediates/prebuilt_myapex.apex.extractor/android_common/extracted/myapex.hwasan.apks" + extractorOutput := "out/soong/.intermediates/myapex/android_common_myapex/extracted/myapex.hwasan.apks" - m := ctx.ModuleForTests("prebuilt_myapex.apex.extractor", "android_common") + m := ctx.ModuleForTests("myapex", "android_common_myapex") extractedApex := m.Output(extractorOutput) android.AssertArrayString(t, "extractor input", []string{"myapex.hwasan.apks"}, extractedApex.Inputs.Strings()) @@ -8146,10 +8055,10 @@ func TestApexSetApksModuleAssignment(t *testing.T) { } `) - m := ctx.ModuleForTests("prebuilt_myapex.apex.extractor", "android_common") + m := ctx.ModuleForTests("myapex", "android_common_myapex") // Check that the extractor produces the correct apks file from the input module - extractorOutput := "out/soong/.intermediates/prebuilt_myapex.apex.extractor/android_common/extracted/myapex.apks" + extractorOutput := "out/soong/.intermediates/myapex/android_common_myapex/extracted/myapex.apks" extractedApex := m.Output(extractorOutput) android.AssertArrayString(t, "extractor input", []string{"myapex.apks"}, extractedApex.Inputs.Strings()) @@ -8211,189 +8120,6 @@ func testDexpreoptWithApexes(t *testing.T, bp, errmsg string, preparer android.F return result.TestContext } -func TestDuplicateDeapexersFromPrebuiltApexes(t *testing.T) { - preparers := android.GroupFixturePreparers( - java.PrepareForTestWithJavaDefaultModules, - prepareForTestWithBootclasspathFragment, - dexpreopt.FixtureSetTestOnlyArtBootImageJars("com.android.art:libfoo"), - PrepareForTestWithApexBuildComponents, - ). - ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern( - "Multiple installable prebuilt APEXes provide ambiguous deapexers: prebuilt_com.android.art and prebuilt_com.mycompany.android.art")) - - bpBase := ` - apex_set { - name: "com.android.art", - installable: true, - exported_bootclasspath_fragments: ["art-bootclasspath-fragment"], - set: "myapex.apks", - } - - apex_set { - name: "com.mycompany.android.art", - apex_name: "com.android.art", - installable: true, - exported_bootclasspath_fragments: ["art-bootclasspath-fragment"], - set: "company-myapex.apks", - } - - prebuilt_bootclasspath_fragment { - name: "art-bootclasspath-fragment", - apex_available: ["com.android.art"], - hidden_api: { - annotation_flags: "my-bootclasspath-fragment/annotation-flags.csv", - metadata: "my-bootclasspath-fragment/metadata.csv", - index: "my-bootclasspath-fragment/index.csv", - stub_flags: "my-bootclasspath-fragment/stub-flags.csv", - all_flags: "my-bootclasspath-fragment/all-flags.csv", - }, - %s - } - ` - - t.Run("java_import", func(t *testing.T) { - _ = preparers.RunTestWithBp(t, fmt.Sprintf(bpBase, `contents: ["libfoo"]`)+` - java_import { - name: "libfoo", - jars: ["libfoo.jar"], - apex_available: ["com.android.art"], - } - `) - }) - - t.Run("java_sdk_library_import", func(t *testing.T) { - _ = preparers.RunTestWithBp(t, fmt.Sprintf(bpBase, `contents: ["libfoo"]`)+` - java_sdk_library_import { - name: "libfoo", - public: { - jars: ["libbar.jar"], - }, - shared_library: false, - apex_available: ["com.android.art"], - } - `) - }) - - t.Run("prebuilt_bootclasspath_fragment", func(t *testing.T) { - _ = preparers.RunTestWithBp(t, fmt.Sprintf(bpBase, ` - image_name: "art", - contents: ["libfoo"], - `)+` - java_sdk_library_import { - name: "libfoo", - public: { - jars: ["libbar.jar"], - }, - shared_library: false, - apex_available: ["com.android.art"], - } - `) - }) -} - -func TestDuplicateButEquivalentDeapexersFromPrebuiltApexes(t *testing.T) { - preparers := android.GroupFixturePreparers( - java.PrepareForTestWithJavaDefaultModules, - PrepareForTestWithApexBuildComponents, - ) - - errCtx := moduleErrorfTestCtx{} - - bpBase := ` - apex_set { - name: "com.android.myapex", - installable: true, - exported_bootclasspath_fragments: ["my-bootclasspath-fragment"], - set: "myapex.apks", - } - - apex_set { - name: "com.android.myapex_compressed", - apex_name: "com.android.myapex", - installable: true, - exported_bootclasspath_fragments: ["my-bootclasspath-fragment"], - set: "myapex_compressed.apks", - } - - prebuilt_bootclasspath_fragment { - name: "my-bootclasspath-fragment", - apex_available: [ - "com.android.myapex", - "com.android.myapex_compressed", - ], - hidden_api: { - annotation_flags: "annotation-flags.csv", - metadata: "metadata.csv", - index: "index.csv", - signature_patterns: "signature_patterns.csv", - }, - %s - } - ` - - t.Run("java_import", func(t *testing.T) { - result := preparers.RunTestWithBp(t, - fmt.Sprintf(bpBase, `contents: ["libfoo"]`)+` - java_import { - name: "libfoo", - jars: ["libfoo.jar"], - apex_available: [ - "com.android.myapex", - "com.android.myapex_compressed", - ], - } - `) - - module := result.Module("libfoo", "android_common_com.android.myapex") - usesLibraryDep := module.(java.UsesLibraryDependency) - android.AssertPathRelativeToTopEquals(t, "dex jar path", - "out/soong/.intermediates/prebuilt_com.android.myapex.deapexer/android_common/deapexer/javalib/libfoo.jar", - usesLibraryDep.DexJarBuildPath(errCtx).Path()) - }) - - t.Run("java_sdk_library_import", func(t *testing.T) { - result := preparers.RunTestWithBp(t, - fmt.Sprintf(bpBase, `contents: ["libfoo"]`)+` - java_sdk_library_import { - name: "libfoo", - public: { - jars: ["libbar.jar"], - }, - apex_available: [ - "com.android.myapex", - "com.android.myapex_compressed", - ], - compile_dex: true, - } - `) - - module := result.Module("libfoo", "android_common_com.android.myapex") - usesLibraryDep := module.(java.UsesLibraryDependency) - android.AssertPathRelativeToTopEquals(t, "dex jar path", - "out/soong/.intermediates/prebuilt_com.android.myapex.deapexer/android_common/deapexer/javalib/libfoo.jar", - usesLibraryDep.DexJarBuildPath(errCtx).Path()) - }) - - t.Run("prebuilt_bootclasspath_fragment", func(t *testing.T) { - _ = preparers.RunTestWithBp(t, fmt.Sprintf(bpBase, ` - image_name: "art", - contents: ["libfoo"], - `)+` - java_sdk_library_import { - name: "libfoo", - public: { - jars: ["libbar.jar"], - }, - apex_available: [ - "com.android.myapex", - "com.android.myapex_compressed", - ], - compile_dex: true, - } - `) - }) -} - func TestUpdatable_should_set_min_sdk_version(t *testing.T) { testApexError(t, `"myapex" .*: updatable: updatable APEXes should set min_sdk_version`, ` apex { @@ -8505,12 +8231,16 @@ func TestDexpreoptAccessDexFilesFromPrebuiltApex(t *testing.T) { }, } - java_import { - name: "libfoo", + java_sdk_library_import { + name: "libfoo", + prefer: true, + public: { jars: ["libfoo.jar"], - apex_available: ["myapex"], - permitted_packages: ["libfoo"], - } + }, + apex_available: ["myapex"], + shared_library: false, + permitted_packages: ["libfoo"], + } `, "", preparer, fragment) }) } @@ -8890,7 +8620,7 @@ func TestApexSet(t *testing.T) { }), ) - m := ctx.ModuleForTests("prebuilt_myapex.apex.extractor", "android_common") + m := ctx.ModuleForTests("myapex", "android_common_myapex") // Check extract_apks tool parameters. extractedApex := m.Output("extracted/myapex.apks") @@ -8931,7 +8661,7 @@ func TestApexSet_NativeBridge(t *testing.T) { }), ) - m := ctx.ModuleForTests("prebuilt_myapex.apex.extractor", "android_common") + m := ctx.ModuleForTests("myapex", "android_common_myapex") // Check extract_apks tool parameters. No native bridge arch expected extractedApex := m.Output("extracted/myapex.apks") @@ -9618,42 +9348,6 @@ func TestAndroidMk_DexpreoptBuiltInstalledForApex(t *testing.T) { 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") } -func TestAndroidMk_DexpreoptBuiltInstalledForApex_Prebuilt(t *testing.T) { - ctx := testApex(t, ` - prebuilt_apex { - name: "myapex", - arch: { - arm64: { - src: "myapex-arm64.apex", - }, - arm: { - src: "myapex-arm.apex", - }, - }, - exported_java_libs: ["foo"], - } - - java_import { - name: "foo", - jars: ["foo.jar"], - apex_available: ["myapex"], - } - `, - dexpreopt.FixtureSetApexSystemServerJars("myapex:foo"), - ) - - prebuilt := ctx.ModuleForTests("myapex", "android_common_myapex").Module().(*Prebuilt) - entriesList := android.AndroidMkEntriesForTest(t, ctx, prebuilt) - mainModuleEntries := entriesList[0] - android.AssertArrayString(t, - "LOCAL_REQUIRED_MODULES", - mainModuleEntries.EntryMap["LOCAL_REQUIRED_MODULES"], - []string{ - "foo-dexpreopt-arm64-apex@myapex@javalib@foo.jar@classes.odex", - "foo-dexpreopt-arm64-apex@myapex@javalib@foo.jar@classes.vdex", - }) -} - func TestAndroidMk_RequiredModules(t *testing.T) { ctx := testApex(t, ` apex { @@ -10583,14 +10277,15 @@ func TestAconfigFilesJavaDeps(t *testing.T) { mod := ctx.ModuleForTests("myapex", "android_common_myapex") s := mod.Rule("apexRule").Args["copy_commands"] copyCmds := regexp.MustCompile(" *&& *").Split(s, -1) - if len(copyCmds) != 12 { - t.Fatalf("Expected 12 commands, got %d in:\n%s", len(copyCmds), s) + if len(copyCmds) != 14 { + t.Fatalf("Expected 14 commands, got %d in:\n%s", len(copyCmds), s) } ensureListContainsMatch(t, copyCmds, "^cp -f .*/aconfig_flags.pb .*/image.apex/etc/aconfig_flags.pb") ensureListContainsMatch(t, copyCmds, "^cp -f .*/package.map .*/image.apex/etc/package.map") ensureListContainsMatch(t, copyCmds, "^cp -f .*/flag.map .*/image.apex/etc/flag.map") ensureListContainsMatch(t, copyCmds, "^cp -f .*/flag.val .*/image.apex/etc/flag.val") + ensureListContainsMatch(t, copyCmds, "^cp -f .*/flag.info.*/image.apex/etc/flag.info") inputs := []string{ "my_aconfig_declarations_foo/intermediate.pb", @@ -10600,6 +10295,7 @@ func TestAconfigFilesJavaDeps(t *testing.T) { VerifyAconfigRule(t, &mod, "create_aconfig_package_map_file", inputs, "android_common_myapex/package.map", "myapex", "package_map") VerifyAconfigRule(t, &mod, "create_aconfig_flag_map_file", inputs, "android_common_myapex/flag.map", "myapex", "flag_map") VerifyAconfigRule(t, &mod, "create_aconfig_flag_val_file", inputs, "android_common_myapex/flag.val", "myapex", "flag_val") + VerifyAconfigRule(t, &mod, "create_aconfig_flag_info_file", inputs, "android_common_myapex/flag.info", "myapex", "flag_info") } func TestAconfigFilesJavaAndCcDeps(t *testing.T) { @@ -10718,14 +10414,15 @@ func TestAconfigFilesJavaAndCcDeps(t *testing.T) { mod := ctx.ModuleForTests("myapex", "android_common_myapex") s := mod.Rule("apexRule").Args["copy_commands"] copyCmds := regexp.MustCompile(" *&& *").Split(s, -1) - if len(copyCmds) != 16 { - t.Fatalf("Expected 16 commands, got %d in:\n%s", len(copyCmds), s) + if len(copyCmds) != 18 { + t.Fatalf("Expected 18 commands, got %d in:\n%s", len(copyCmds), s) } ensureListContainsMatch(t, copyCmds, "^cp -f .*/aconfig_flags.pb .*/image.apex/etc/aconfig_flags.pb") ensureListContainsMatch(t, copyCmds, "^cp -f .*/package.map .*/image.apex/etc/package.map") ensureListContainsMatch(t, copyCmds, "^cp -f .*/flag.map .*/image.apex/etc/flag.map") ensureListContainsMatch(t, copyCmds, "^cp -f .*/flag.val .*/image.apex/etc/flag.val") + ensureListContainsMatch(t, copyCmds, "^cp -f .*/flag.info .*/image.apex/etc/flag.info") inputs := []string{ "my_aconfig_declarations_foo/intermediate.pb", @@ -10736,6 +10433,7 @@ func TestAconfigFilesJavaAndCcDeps(t *testing.T) { VerifyAconfigRule(t, &mod, "create_aconfig_package_map_file", inputs, "android_common_myapex/package.map", "myapex", "package_map") VerifyAconfigRule(t, &mod, "create_aconfig_flag_map_file", inputs, "android_common_myapex/flag.map", "myapex", "flag_map") VerifyAconfigRule(t, &mod, "create_aconfig_flag_val_file", inputs, "android_common_myapex/flag.val", "myapex", "flag_val") + VerifyAconfigRule(t, &mod, "create_aconfig_flag_info_file", inputs, "android_common_myapex/flag.info", "myapex", "flag_info") } func TestAconfigFilesRustDeps(t *testing.T) { @@ -10886,14 +10584,15 @@ func TestAconfigFilesRustDeps(t *testing.T) { mod := ctx.ModuleForTests("myapex", "android_common_myapex") s := mod.Rule("apexRule").Args["copy_commands"] copyCmds := regexp.MustCompile(" *&& *").Split(s, -1) - if len(copyCmds) != 36 { - t.Fatalf("Expected 36 commands, got %d in:\n%s", len(copyCmds), s) + if len(copyCmds) != 38 { + t.Fatalf("Expected 38 commands, got %d in:\n%s", len(copyCmds), s) } ensureListContainsMatch(t, copyCmds, "^cp -f .*/aconfig_flags.pb .*/image.apex/etc/aconfig_flags.pb") ensureListContainsMatch(t, copyCmds, "^cp -f .*/package.map .*/image.apex/etc/package.map") ensureListContainsMatch(t, copyCmds, "^cp -f .*/flag.map .*/image.apex/etc/flag.map") ensureListContainsMatch(t, copyCmds, "^cp -f .*/flag.val .*/image.apex/etc/flag.val") + ensureListContainsMatch(t, copyCmds, "^cp -f .*/flag.info .*/image.apex/etc/flag.info") inputs := []string{ "my_aconfig_declarations_foo/intermediate.pb", @@ -10905,6 +10604,7 @@ func TestAconfigFilesRustDeps(t *testing.T) { VerifyAconfigRule(t, &mod, "create_aconfig_package_map_file", inputs, "android_common_myapex/package.map", "myapex", "package_map") VerifyAconfigRule(t, &mod, "create_aconfig_flag_map_file", inputs, "android_common_myapex/flag.map", "myapex", "flag_map") VerifyAconfigRule(t, &mod, "create_aconfig_flag_val_file", inputs, "android_common_myapex/flag.val", "myapex", "flag_val") + VerifyAconfigRule(t, &mod, "create_aconfig_flag_info_file", inputs, "android_common_myapex/flag.info", "myapex", "flag_info") } func VerifyAconfigRule(t *testing.T, mod *android.TestingModule, desc string, inputs []string, output string, container string, file_type string) { @@ -11233,12 +10933,12 @@ func TestBootDexJarsMultipleApexPrebuilts(t *testing.T) { { desc: "Prebuilt apex prebuilt_com.android.foo is selected, profile should come from .prof deapexed from the prebuilt", selectedApexContributions: "foo.prebuilt.contributions", - expectedBootJar: "out/soong/.intermediates/prebuilt_com.android.foo.deapexer/android_common/deapexer/javalib/framework-foo.jar", + expectedBootJar: "out/soong/.intermediates/prebuilt_com.android.foo/android_common_com.android.foo/deapexer/javalib/framework-foo.jar", }, { desc: "Prebuilt apex prebuilt_com.android.foo.v2 is selected, profile should come from .prof deapexed from the prebuilt", selectedApexContributions: "foo.prebuilt.v2.contributions", - expectedBootJar: "out/soong/.intermediates/prebuilt_com.android.foo.v2.deapexer/android_common/deapexer/javalib/framework-foo.jar", + expectedBootJar: "out/soong/.intermediates/com.android.foo.v2/android_common_com.android.foo/deapexer/javalib/framework-foo.jar", }, } @@ -11930,3 +11630,110 @@ func TestPrebuiltStubNoinstall(t *testing.T) { ) }) } + +func TestSdkLibraryTransitiveClassLoaderContext(t *testing.T) { + // This test case tests that listing the impl lib instead of the top level java_sdk_library + // in libs of android_app and java_library does not lead to class loader context device/host + // path mismatch errors. + android.GroupFixturePreparers( + prepareForApexTest, + android.PrepareForIntegrationTestWithAndroid, + PrepareForTestWithApexBuildComponents, + android.FixtureModifyEnv(func(env map[string]string) { + env["DISABLE_CONTAINER_CHECK"] = "true" + }), + withFiles(filesForSdkLibrary), + android.FixtureMergeMockFs(android.MockFS{ + "system/sepolicy/apex/com.android.foo30-file_contexts": nil, + }), + ).RunTestWithBp(t, ` + apex { + name: "com.android.foo30", + key: "myapex.key", + updatable: true, + bootclasspath_fragments: [ + "foo-bootclasspath-fragment", + ], + java_libs: [ + "bar", + ], + apps: [ + "bar-app", + ], + min_sdk_version: "30", + } + apex_key { + name: "myapex.key", + public_key: "testkey.avbpubkey", + private_key: "testkey.pem", + } + bootclasspath_fragment { + name: "foo-bootclasspath-fragment", + contents: [ + "framework-foo", + ], + apex_available: [ + "com.android.foo30", + ], + hidden_api: { + split_packages: ["*"] + }, + } + + java_sdk_library { + name: "framework-foo", + srcs: [ + "A.java" + ], + unsafe_ignore_missing_latest_api: true, + apex_available: [ + "com.android.foo30", + ], + compile_dex: true, + sdk_version: "core_current", + shared_library: false, + } + + java_library { + name: "bar", + srcs: [ + "A.java" + ], + libs: [ + "framework-foo.impl", + ], + apex_available: [ + "com.android.foo30", + ], + sdk_version: "core_current", + } + + java_library { + name: "baz", + srcs: [ + "A.java" + ], + libs: [ + "bar", + ], + sdk_version: "core_current", + } + + android_app { + name: "bar-app", + srcs: [ + "A.java" + ], + libs: [ + "baz", + "framework-foo.impl", + ], + apex_available: [ + "com.android.foo30", + ], + sdk_version: "core_current", + min_sdk_version: "30", + manifest: "AndroidManifest.xml", + } + `) +} diff --git a/apex/bootclasspath_fragment_test.go b/apex/bootclasspath_fragment_test.go index df7857f29..e44d3f552 100644 --- a/apex/bootclasspath_fragment_test.go +++ b/apex/bootclasspath_fragment_test.go @@ -398,11 +398,20 @@ func TestBootclasspathFragmentInArtApex(t *testing.T) { // Make sure that a preferred prebuilt with consistent contents doesn't affect the apex. addPrebuilt(true, "foo", "bar"), + android.FixtureMergeMockFs(android.MockFS{ + "apex_contributions/Android.bp": []byte(` + apex_contributions { + name: "prebuilt_art_contributions", + contents: ["prebuilt_com.android.art"], + api_domain: "com.android.art", + } + `)}), + android.PrepareForTestWithBuildFlag("RELEASE_APEX_CONTRIBUTIONS_ART", "prebuilt_art_contributions"), java.FixtureSetBootImageInstallDirOnDevice("art", "apex/com.android.art/javalib"), ).RunTest(t) - ensureExactDeapexedContents(t, result.TestContext, "prebuilt_com.android.art", "android_common", []string{ + ensureExactDeapexedContents(t, result.TestContext, "prebuilt_com.android.art", "android_common_com.android.art", []string{ "etc/boot-image.prof", "javalib/bar.jar", "javalib/foo.jar", @@ -495,6 +504,7 @@ func TestBootclasspathFragmentInPrebuiltArtApex(t *testing.T) { java.FixtureConfigureBootJars("com.android.art:foo", "com.android.art:bar"), dexpreopt.FixtureSetTestOnlyArtBootImageJars("com.android.art:foo", "com.android.art:bar"), java.FixtureSetBootImageInstallDirOnDevice("art", "apex/com.android.art/javalib"), + android.PrepareForTestWithBuildFlag("RELEASE_APEX_CONTRIBUTIONS_ART", "prebuilt_art_contributions"), ) bp := ` @@ -552,6 +562,12 @@ func TestBootclasspathFragmentInPrebuiltArtApex(t *testing.T) { src: "com.mycompany.android.art.apex", exported_bootclasspath_fragments: ["art-bootclasspath-fragment"], } + + apex_contributions { + name: "prebuilt_art_contributions", + contents: ["prebuilt_com.android.art"], + api_domain: "com.android.art", + } ` t.Run("disabled alternative APEX", func(t *testing.T) { @@ -561,27 +577,18 @@ func TestBootclasspathFragmentInPrebuiltArtApex(t *testing.T) { `all_apex_contributions`, `dex2oatd`, `prebuilt_art-bootclasspath-fragment`, - `prebuilt_com.android.art.apex.selector`, - `prebuilt_com.android.art.deapexer`, }) java.CheckModuleDependencies(t, result.TestContext, "art-bootclasspath-fragment", "android_common_com.android.art", []string{ `all_apex_contributions`, `dex2oatd`, `prebuilt_bar`, - `prebuilt_com.android.art.deapexer`, `prebuilt_foo`, }) module := result.ModuleForTests("dex_bootjars", "android_common") checkCopiesToPredefinedLocationForArt(t, result.Config, module, "bar", "foo") }) - - t.Run("enabled alternative APEX", func(t *testing.T) { - preparers.ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern( - "Multiple installable prebuilt APEXes provide ambiguous deapexers: prebuilt_com.android.art and prebuilt_com.mycompany.android.art")). - RunTestWithBp(t, fmt.Sprintf(bp, "")) - }) } // checkCopiesToPredefinedLocationForArt checks that the supplied modules are copied to the diff --git a/apex/builder.go b/apex/builder.go index da9e47ea3..244119bdd 100644 --- a/apex/builder.go +++ b/apex/builder.go @@ -96,6 +96,7 @@ var createStorageInfo = []createStorageStruct{ {"package.map", "create_aconfig_package_map_file", "package_map"}, {"flag.map", "create_aconfig_flag_map_file", "flag_map"}, {"flag.val", "create_aconfig_flag_val_file", "flag_val"}, + {"flag.info", "create_aconfig_flag_info_file", "flag_info"}, } var ( diff --git a/apex/deapexer.go b/apex/deapexer.go index a6731080c..3b8233d33 100644 --- a/apex/deapexer.go +++ b/apex/deapexer.go @@ -15,37 +15,9 @@ package apex import ( - "strings" - "android/soong/android" ) -// Contains 'deapexer' a private module type used by 'prebuilt_apex' to make dex files contained -// within a .apex file referenced by `prebuilt_apex` available for use by their associated -// `java_import` modules. -// -// An 'apex' module references `java_library` modules from which .dex files are obtained that are -// stored in the resulting `.apex` file. The resulting `.apex` file is then made available as a -// prebuilt by referencing it from a `prebuilt_apex`. For each such `java_library` that is used by -// modules outside the `.apex` file a `java_import` prebuilt is made available referencing a jar -// that contains the Java classes. -// -// When building a Java module type, e.g. `java_module` or `android_app` against such prebuilts the -// `java_import` provides the classes jar (jar containing `.class` files) against which the -// module's `.java` files are compiled. That classes jar usually contains only stub classes. The -// resulting classes jar is converted into a dex jar (jar containing `.dex` files). Then if -// necessary the dex jar is further processed by `dexpreopt` to produce an optimized form of the -// library specific to the current Android version. This process requires access to implementation -// dex jars for each `java_import`. The `java_import` will obtain the implementation dex jar from -// the `.apex` file in the associated `prebuilt_apex`. -// -// This is intentionally not registered by name as it is not intended to be used from within an -// `Android.bp` file. - -// DeapexerProperties specifies the properties supported by the deapexer module. -// -// As these are never intended to be supplied in a .bp file they use a different naming convention -// to make it clear that they are different. type DeapexerProperties struct { // List of common modules that may need access to files exported by this module. // @@ -72,46 +44,9 @@ type SelectedApexProperties struct { Selected_apex *string `android:"path" blueprint:"mutated"` } -type Deapexer struct { - android.ModuleBase - - properties DeapexerProperties - selectedApexProperties SelectedApexProperties - - inputApex android.Path -} - -// Returns the name of the deapexer module corresponding to an APEX module with the given name. -func deapexerModuleName(apexModuleName string) string { - return apexModuleName + ".deapexer" -} - -// Returns the name of the APEX module corresponding to an deapexer module with -// the given name. This reverses deapexerModuleName. -func apexModuleName(deapexerModuleName string) string { - return strings.TrimSuffix(deapexerModuleName, ".deapexer") -} - -func privateDeapexerFactory() android.Module { - module := &Deapexer{} - module.AddProperties(&module.properties, &module.selectedApexProperties) - android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon) - return module -} - -func (p *Deapexer) DepsMutator(ctx android.BottomUpMutatorContext) { - // Add dependencies from the java modules to which this exports files from the `.apex` file onto - // this module so that they can access the `DeapexerInfo` object that this provides. - // TODO: b/308174306 - Once all the mainline modules have been flagged, drop this dependency edge - for _, lib := range p.properties.CommonModules { - dep := prebuiltApexExportedModuleName(ctx, lib) - ctx.AddReverseDependency(ctx.Module(), android.DeapexerTag, dep) - } -} - -func (p *Deapexer) GenerateAndroidBuildActions(ctx android.ModuleContext) { - p.inputApex = android.OptionalPathForModuleSrc(ctx, p.selectedApexProperties.Selected_apex).Path() - +// deapex creates the build rules to deapex a prebuilt .apex file +// it returns a pointer to a DeapexerInfo object +func deapex(ctx android.ModuleContext, apexFile android.Path, deapexerProps DeapexerProperties) *android.DeapexerInfo { // Create and remember the directory into which the .apex file's contents will be unpacked. deapexerOutput := android.PathForModuleOut(ctx, "deapexer") @@ -119,7 +54,7 @@ func (p *Deapexer) GenerateAndroidBuildActions(ctx android.ModuleContext) { // Create mappings from apex relative path to the extracted file's path. exportedPaths := make(android.Paths, 0, len(exports)) - for _, path := range p.properties.ExportedFiles { + for _, path := range deapexerProps.ExportedFiles { // Populate the exports that this makes available. extractedPath := deapexerOutput.Join(ctx, path) exports[path] = extractedPath @@ -131,9 +66,8 @@ func (p *Deapexer) GenerateAndroidBuildActions(ctx android.ModuleContext) { // apex relative path to extracted file path available for other modules. if len(exports) > 0 { // Make the information available for other modules. - di := android.NewDeapexerInfo(apexModuleName(ctx.ModuleName()), exports, p.properties.CommonModules) - di.AddDexpreoptProfileGuidedExportedModuleNames(p.properties.DexpreoptProfileGuidedModules...) - android.SetProvider(ctx, android.DeapexerProvider, di) + di := android.NewDeapexerInfo(ctx.ModuleName(), exports, deapexerProps.CommonModules) + di.AddDexpreoptProfileGuidedExportedModuleNames(deapexerProps.DexpreoptProfileGuidedModules...) // Create a sorted list of the files that this exports. exportedPaths = android.SortedUniquePaths(exportedPaths) @@ -147,11 +81,13 @@ func (p *Deapexer) GenerateAndroidBuildActions(ctx android.ModuleContext) { BuiltTool("deapexer"). BuiltTool("debugfs"). BuiltTool("fsck.erofs"). - Input(p.inputApex). + Input(apexFile). Text(deapexerOutput.String()) for _, p := range exportedPaths { command.Output(p.(android.WritablePath)) } - builder.Build("deapexer", "deapex "+apexModuleName(ctx.ModuleName())) + builder.Build("deapexer", "deapex "+ctx.ModuleName()) + return &di } + return nil } diff --git a/apex/dexpreopt_bootjars_test.go b/apex/dexpreopt_bootjars_test.go index d8ee4ba6c..4feade8ca 100644 --- a/apex/dexpreopt_bootjars_test.go +++ b/apex/dexpreopt_bootjars_test.go @@ -127,16 +127,29 @@ func testDexpreoptBoot(t *testing.T, ruleFile string, expectedInputs, expectedOu src: "com.android.art-arm.apex", exported_bootclasspath_fragments: ["art-bootclasspath-fragment"], } + + apex_contributions { + name: "prebuilt_art_contributions", + contents: ["prebuilt_com.android.art"], + api_domain: "com.android.art", + } ` - result := android.GroupFixturePreparers( + fixture := android.GroupFixturePreparers( java.PrepareForTestWithDexpreopt, java.PrepareForTestWithJavaSdkLibraryFiles, java.FixtureWithLastReleaseApis("foo"), java.FixtureConfigureBootJars("com.android.art:core-oj", "platform:foo", "system_ext:bar", "platform:baz"), PrepareForTestWithApexBuildComponents, prepareForTestWithArtApex, - ).RunTestWithBp(t, fmt.Sprintf(bp, preferPrebuilt)) + ) + if preferPrebuilt { + fixture = android.GroupFixturePreparers( + fixture, + android.PrepareForTestWithBuildFlag("RELEASE_APEX_CONTRIBUTIONS_ART", "prebuilt_art_contributions"), + ) + } + result := fixture.RunTestWithBp(t, fmt.Sprintf(bp, preferPrebuilt)) dexBootJars := result.ModuleForTests("dex_bootjars", "android_common") rule := dexBootJars.Output(ruleFile) @@ -200,7 +213,7 @@ func TestDexpreoptBootJarsWithPrebuiltArtApex(t *testing.T) { "out/soong/dexpreopt_arm64/dex_bootjars_input/foo.jar", "out/soong/dexpreopt_arm64/dex_bootjars_input/bar.jar", "out/soong/dexpreopt_arm64/dex_bootjars_input/baz.jar", - "out/soong/.intermediates/prebuilt_com.android.art.deapexer/android_common/deapexer/etc/boot-image.prof", + "out/soong/.intermediates/prebuilt_com.android.art/android_common_com.android.art/deapexer/etc/boot-image.prof", "out/soong/.intermediates/default/java/dex_bootjars/android_common/boot/boot.prof", "out/soong/dexpreopt/uffd_gc_flag.txt", } @@ -384,12 +397,12 @@ func TestDexpreoptProfileWithMultiplePrebuiltArtApexes(t *testing.T) { { desc: "Prebuilt apex prebuilt_com.android.art is selected, profile should come from .prof deapexed from the prebuilt", selectedArtApexContributions: "art.prebuilt.contributions", - expectedProfile: "out/soong/.intermediates/prebuilt_com.android.art.deapexer/android_common/deapexer/etc/boot-image.prof", + expectedProfile: "out/soong/.intermediates/prebuilt_com.android.art/android_common_com.android.art/deapexer/etc/boot-image.prof", }, { desc: "Prebuilt apex prebuilt_com.android.art.v2 is selected, profile should come from .prof deapexed from the prebuilt", selectedArtApexContributions: "art.prebuilt.v2.contributions", - expectedProfile: "out/soong/.intermediates/prebuilt_com.android.art.v2.deapexer/android_common/deapexer/etc/boot-image.prof", + expectedProfile: "out/soong/.intermediates/com.android.art.v2/android_common_com.android.art/deapexer/etc/boot-image.prof", }, } for _, tc := range testCases { diff --git a/apex/prebuilt.go b/apex/prebuilt.go index 792b57188..9cd5688ba 100644 --- a/apex/prebuilt.go +++ b/apex/prebuilt.go @@ -107,11 +107,6 @@ type PrebuiltCommonProperties struct { // from PRODUCT_PACKAGES. Overrides []string - // List of java libraries that are embedded inside this prebuilt APEX bundle and for which this - // APEX bundle will create an APEX variant and provide dex implementation jars for use by - // dexpreopt and boot jars package check. - Exported_java_libs []string - // List of bootclasspath fragments inside this prebuilt APEX bundle and for which this APEX // bundle will create an APEX variant. Exported_bootclasspath_fragments []string @@ -199,9 +194,8 @@ func (p *prebuiltCommon) initApexFilesForAndroidMk(ctx android.ModuleContext) { } // If this prebuilt has system server jar, create the rules to dexpreopt it and install it alongside the prebuilt apex -func (p *prebuiltCommon) dexpreoptSystemServerJars(ctx android.ModuleContext) { - // If this apex does not export anything, return - if !p.hasExportedDeps() { +func (p *prebuiltCommon) dexpreoptSystemServerJars(ctx android.ModuleContext, di *android.DeapexerInfo) { + if di == nil { return } // If this prebuilt apex has not been selected, return @@ -210,10 +204,7 @@ func (p *prebuiltCommon) dexpreoptSystemServerJars(ctx android.ModuleContext) { } // Use apex_name to determine the api domain of this prebuilt apex apexName := p.ApexVariationName() - di, err := android.FindDeapexerProviderForModule(ctx) - if err != nil { - ctx.ModuleErrorf(err.Error()) - } + // TODO: do not compute twice dc := dexpreopt.GetGlobalConfig(ctx) systemServerJarList := dc.AllApexSystemServerJars(ctx) @@ -262,29 +253,8 @@ func (p *prebuiltCommon) AndroidMkEntries() []android.AndroidMkEntries { return entriesList } -// prebuiltApexModuleCreator defines the methods that need to be implemented by prebuilt_apex and -// apex_set in order to create the modules needed to provide access to the prebuilt .apex file. -type prebuiltApexModuleCreator interface { - createPrebuiltApexModules(ctx android.BottomUpMutatorContext) -} - -// prebuiltApexModuleCreatorMutator is the mutator responsible for invoking the -// prebuiltApexModuleCreator's createPrebuiltApexModules method. -// -// It is registered as a pre-arch mutator as it must run after the ComponentDepsMutator because it -// will need to access dependencies added by that (exported modules) but must run before the -// DepsMutator so that the deapexer module it creates can add dependencies onto itself from the -// exported modules. -func prebuiltApexModuleCreatorMutator(ctx android.BottomUpMutatorContext) { - module := ctx.Module() - if creator, ok := module.(prebuiltApexModuleCreator); ok { - creator.createPrebuiltApexModules(ctx) - } -} - func (p *prebuiltCommon) hasExportedDeps() bool { - return len(p.prebuiltCommonProperties.Exported_java_libs) > 0 || - len(p.prebuiltCommonProperties.Exported_bootclasspath_fragments) > 0 || + return len(p.prebuiltCommonProperties.Exported_bootclasspath_fragments) > 0 || len(p.prebuiltCommonProperties.Exported_systemserverclasspath_fragments) > 0 } @@ -292,11 +262,6 @@ func (p *prebuiltCommon) hasExportedDeps() bool { func (p *prebuiltCommon) prebuiltApexContentsDeps(ctx android.BottomUpMutatorContext) { module := ctx.Module() - for _, dep := range p.prebuiltCommonProperties.Exported_java_libs { - prebuiltDep := android.PrebuiltNameFromSource(dep) - ctx.AddDependency(module, exportedJavaLibTag, prebuiltDep) - } - for _, dep := range p.prebuiltCommonProperties.Exported_bootclasspath_fragments { prebuiltDep := android.PrebuiltNameFromSource(dep) ctx.AddDependency(module, exportedBootclasspathFragmentTag, prebuiltDep) @@ -414,34 +379,6 @@ func (p *prebuiltCommon) apexInfoMutator(mctx android.TopDownMutatorContext) { } } -// prebuiltApexSelectorModule is a private module type that is only created by the prebuilt_apex -// module. It selects the apex to use and makes it available for use by prebuilt_apex and the -// deapexer. -type prebuiltApexSelectorModule struct { - android.ModuleBase - - apexFileProperties ApexFileProperties - - inputApex android.Path -} - -func privateApexSelectorModuleFactory() android.Module { - module := &prebuiltApexSelectorModule{} - module.AddProperties( - &module.apexFileProperties, - ) - android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon) - return module -} - -func (p *prebuiltApexSelectorModule) Srcs() android.Paths { - return android.Paths{p.inputApex} -} - -func (p *prebuiltApexSelectorModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { - p.inputApex = android.SingleSourcePathFromSupplier(ctx, p.apexFileProperties.prebuiltApexSelector, "src") -} - type Prebuilt struct { prebuiltCommon @@ -484,11 +421,11 @@ type ApexFileProperties struct { // to use methods on it that are specific to the current module. // // See the ApexFileProperties.Src property. -func (p *ApexFileProperties) prebuiltApexSelector(ctx android.BaseModuleContext, prebuilt android.Module) []string { +func (p *ApexFileProperties) prebuiltApexSelector(ctx android.BaseModuleContext, prebuilt android.Module) string { multiTargets := prebuilt.MultiTargets() if len(multiTargets) != 1 { ctx.OtherModuleErrorf(prebuilt, "compile_multilib shouldn't be \"both\" for prebuilt_apex") - return nil + return "" } var src string switch multiTargets[0].Arch.ArchType { @@ -521,7 +458,7 @@ func (p *ApexFileProperties) prebuiltApexSelector(ctx android.BaseModuleContext, // logic from reporting a more general, less useful message. } - return []string{src} + return src } type PrebuiltProperties struct { @@ -538,35 +475,19 @@ func (a *Prebuilt) hasSanitizedSource(sanitizer string) bool { func PrebuiltFactory() android.Module { module := &Prebuilt{} module.AddProperties(&module.properties) - module.initPrebuiltCommon(module, &module.properties.PrebuiltCommonProperties) + module.prebuiltCommon.prebuiltCommonProperties = &module.properties.PrebuiltCommonProperties - return module -} - -func createApexSelectorModule(ctx android.BottomUpMutatorContext, name string, apexFileProperties *ApexFileProperties) { - props := struct { - Name *string - }{ - Name: proptools.StringPtr(name), - } + // init the module as a prebuilt + // even though this module type has srcs, use `InitPrebuiltModuleWithoutSrcs`, since the existing + // InitPrebuiltModule* are not friendly with Sources of Configurable type. + // The actual src will be evaluated in GenerateAndroidBuildActions. + android.InitPrebuiltModuleWithoutSrcs(module) + android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon) - ctx.CreateModule(privateApexSelectorModuleFactory, - &props, - apexFileProperties, - ) + return module } -// createDeapexerModuleIfNeeded will create a deapexer module if it is needed. -// -// A deapexer module is only needed when the prebuilt apex specifies one or more modules in either -// the `exported_java_libs` or `exported_bootclasspath_fragments` properties as that indicates that -// the listed modules need access to files from within the prebuilt .apex file. -func (p *prebuiltCommon) createDeapexerModuleIfNeeded(ctx android.BottomUpMutatorContext, deapexerName string, apexFileSource string) { - // Only create the deapexer module if it is needed. - if !p.hasExportedDeps() { - return - } - +func (p *prebuiltCommon) getDeapexerPropertiesIfNeeded(ctx android.ModuleContext) DeapexerProperties { // Compute the deapexer properties from the transitive dependencies of this module. commonModules := []string{} dexpreoptProfileGuidedModules := []string{} @@ -600,7 +521,7 @@ func (p *prebuiltCommon) createDeapexerModuleIfNeeded(ctx android.BottomUpMutato }) // Create properties for deapexer module. - deapexerProperties := &DeapexerProperties{ + deapexerProperties := DeapexerProperties{ // Remove any duplicates from the common modules lists as a module may be included via a direct // dependency as well as transitive ones. CommonModules: android.SortedUniqueStrings(commonModules), @@ -609,22 +530,7 @@ func (p *prebuiltCommon) createDeapexerModuleIfNeeded(ctx android.BottomUpMutato // Populate the exported files property in a fixed order. deapexerProperties.ExportedFiles = android.SortedUniqueStrings(exportedFiles) - - props := struct { - Name *string - Selected_apex *string - }{ - Name: proptools.StringPtr(deapexerName), - Selected_apex: proptools.StringPtr(apexFileSource), - } - ctx.CreateModule(privateDeapexerFactory, - &props, - deapexerProperties, - ) -} - -func apexSelectorModuleName(baseModuleName string) string { - return baseModuleName + ".apex.selector" + return deapexerProperties } func prebuiltApexExportedModuleName(ctx android.BottomUpMutatorContext, name string) string { @@ -666,97 +572,50 @@ func (t exportedDependencyTag) RequiresFilesFromPrebuiltApex() {} var _ android.RequiresFilesFromPrebuiltApexTag = exportedDependencyTag{} var ( - exportedJavaLibTag = exportedDependencyTag{name: "exported_java_libs"} exportedBootclasspathFragmentTag = exportedDependencyTag{name: "exported_bootclasspath_fragments"} exportedSystemserverclasspathFragmentTag = exportedDependencyTag{name: "exported_systemserverclasspath_fragments"} ) -var _ prebuiltApexModuleCreator = (*Prebuilt)(nil) - -// createPrebuiltApexModules creates modules necessary to export files from the prebuilt apex to the -// build. -// -// If this needs to make files from within a `.apex` file available for use by other Soong modules, -// e.g. make dex implementation jars available for java_import modules listed in exported_java_libs, -// it does so as follows: -// -// 1. It creates a `deapexer` module that actually extracts the files from the `.apex` file and -// makes them available for use by other modules, at both Soong and ninja levels. -// -// 2. It adds a dependency onto those modules and creates an apex specific variant similar to what -// an `apex` module does. That ensures that code which looks for specific apex variant, e.g. -// dexpreopt, will work the same way from source and prebuilt. -// -// 3. The `deapexer` module adds a dependency from the modules that require the exported files onto -// itself so that they can retrieve the file paths to those files. -// -// It also creates a child module `selector` that is responsible for selecting the appropriate -// input apex for both the prebuilt_apex and the deapexer. That is needed for a couple of reasons: -// -// 1. To dedup the selection logic so it only runs in one module. -// -// 2. To allow the deapexer to be wired up to a different source for the input apex, e.g. an -// `apex_set`. -// -// prebuilt_apex -// / | \ -// / | \ -// V V V -// selector <--- deapexer <--- exported java lib -func (p *Prebuilt) createPrebuiltApexModules(ctx android.BottomUpMutatorContext) { - apexSelectorModuleName := apexSelectorModuleName(p.Name()) - createApexSelectorModule(ctx, apexSelectorModuleName, &p.properties.ApexFileProperties) - - apexFileSource := ":" + apexSelectorModuleName - p.createDeapexerModuleIfNeeded(ctx, deapexerModuleName(p.Name()), apexFileSource) - - // Add a source reference to retrieve the selected apex from the selector module. - p.prebuiltCommonProperties.Selected_apex = proptools.StringPtr(apexFileSource) -} - func (p *Prebuilt) ComponentDepsMutator(ctx android.BottomUpMutatorContext) { p.prebuiltApexContentsDeps(ctx) } -func (p *prebuiltCommon) DepsMutator(ctx android.BottomUpMutatorContext) { - if p.hasExportedDeps() { - // Create a dependency from the prebuilt apex (prebuilt_apex/apex_set) to the internal deapexer module - // The deapexer will return a provider which will be used to determine the exported artfifacts from this prebuilt. - ctx.AddDependency(ctx.Module(), android.DeapexerTag, deapexerModuleName(p.Name())) - } -} - var _ ApexInfoMutator = (*Prebuilt)(nil) func (p *Prebuilt) ApexInfoMutator(mctx android.TopDownMutatorContext) { p.apexInfoMutator(mctx) } +// creates the build rules to deapex the prebuilt, and returns a deapexerInfo +func (p *prebuiltCommon) getDeapexerInfo(ctx android.ModuleContext, apexFile android.Path) *android.DeapexerInfo { + if !p.hasExportedDeps() { + // nothing to do + return nil + } + deapexerProps := p.getDeapexerPropertiesIfNeeded(ctx) + return deapex(ctx, apexFile, deapexerProps) +} + // Set a provider containing information about the jars and .prof provided by the apex // Apexes built from prebuilts retrieve this information by visiting its internal deapexer module // Used by dex_bootjars to generate the boot image -func (p *prebuiltCommon) provideApexExportsInfo(ctx android.ModuleContext) { - if !p.hasExportedDeps() { - // nothing to do +func (p *prebuiltCommon) provideApexExportsInfo(ctx android.ModuleContext, di *android.DeapexerInfo) { + if di == nil { return } - if di, err := android.FindDeapexerProviderForModule(ctx); err == nil { - javaModuleToDexPath := map[string]android.Path{} - for _, commonModule := range di.GetExportedModuleNames() { - if dex := di.PrebuiltExportPath(java.ApexRootRelativePathToJavaLib(commonModule)); dex != nil { - javaModuleToDexPath[commonModule] = dex - } + javaModuleToDexPath := map[string]android.Path{} + for _, commonModule := range di.GetExportedModuleNames() { + if dex := di.PrebuiltExportPath(java.ApexRootRelativePathToJavaLib(commonModule)); dex != nil { + javaModuleToDexPath[commonModule] = dex } + } - exports := android.ApexExportsInfo{ - ApexName: p.ApexVariationName(), - ProfilePathOnHost: di.PrebuiltExportPath(java.ProfileInstallPathInApex), - LibraryNameToDexJarPathOnHost: javaModuleToDexPath, - } - android.SetProvider(ctx, android.ApexExportsInfoProvider, exports) - } else { - ctx.ModuleErrorf(err.Error()) + exports := android.ApexExportsInfo{ + ApexName: p.ApexVariationName(), + ProfilePathOnHost: di.PrebuiltExportPath(java.ProfileInstallPathInApex), + LibraryNameToDexJarPathOnHost: javaModuleToDexPath, } + android.SetProvider(ctx, android.ApexExportsInfoProvider, exports) } // Set prebuiltInfoProvider. This will be used by `apex_prebuiltinfo_singleton` to print out a metadata file @@ -792,7 +651,7 @@ func (p *Prebuilt) GenerateAndroidBuildActions(ctx android.ModuleContext) { p.apexKeysPath = writeApexKeys(ctx, p) // TODO(jungjw): Check the key validity. - p.inputApex = android.OptionalPathForModuleSrc(ctx, p.prebuiltCommonProperties.Selected_apex).Path() + p.inputApex = android.PathForModuleSrc(ctx, p.properties.prebuiltApexSelector(ctx, ctx.Module())) p.installDir = android.PathForModuleInstall(ctx, "apex") p.installFilename = p.InstallFilename() if !strings.HasSuffix(p.installFilename, imageApexSuffix) { @@ -810,11 +669,13 @@ func (p *Prebuilt) GenerateAndroidBuildActions(ctx android.ModuleContext) { return } + deapexerInfo := p.getDeapexerInfo(ctx, p.inputApex) + // dexpreopt any system server jars if present - p.dexpreoptSystemServerJars(ctx) + p.dexpreoptSystemServerJars(ctx, deapexerInfo) // provide info used for generating the boot image - p.provideApexExportsInfo(ctx) + p.provideApexExportsInfo(ctx, deapexerInfo) p.providePrebuiltInfo(ctx) @@ -850,26 +711,11 @@ type prebuiltApexExtractorModule struct { extractedApex android.WritablePath } -func privateApexExtractorModuleFactory() android.Module { - module := &prebuiltApexExtractorModule{} - module.AddProperties( - &module.properties, - ) - android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon) - return module -} - -func (p *prebuiltApexExtractorModule) Srcs() android.Paths { - return android.Paths{p.extractedApex} -} - -func (p *prebuiltApexExtractorModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { - srcsSupplier := func(ctx android.BaseModuleContext, prebuilt android.Module) []string { - return p.properties.prebuiltSrcs(ctx) - } +// 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 { defaultAllowPrerelease := ctx.Config().IsEnvTrue("SOONG_ALLOW_PRERELEASE_APEXES") - apexSet := android.SingleSourcePathFromSupplier(ctx, srcsSupplier, "set") - p.extractedApex = android.PathForModuleOut(ctx, "extracted", apexSet.Base()) + extractedApex := android.PathForModuleOut(ctx, "extracted", apexSet.Base()) // Filter out NativeBridge archs (b/260115309) abis := java.SupportedAbis(ctx, true) ctx.Build(pctx, @@ -877,14 +723,16 @@ func (p *prebuiltApexExtractorModule) GenerateAndroidBuildActions(ctx android.Mo Rule: extractMatchingApex, Description: "Extract an apex from an apex set", Inputs: android.Paths{apexSet}, - Output: p.extractedApex, + Output: extractedApex, Args: map[string]string{ "abis": strings.Join(abis, ","), - "allow-prereleased": strconv.FormatBool(proptools.BoolDefault(p.properties.Prerelease, defaultAllowPrerelease)), + "allow-prereleased": strconv.FormatBool(proptools.BoolDefault(prerelease, defaultAllowPrerelease)), "sdk-version": ctx.Config().PlatformSdkVersion().String(), "skip-sdk-check": strconv.FormatBool(ctx.Config().IsEnvTrue("SOONG_SKIP_APPSET_SDK_CHECK")), }, - }) + }, + ) + return extractedApex } type ApexSet struct { @@ -953,46 +801,16 @@ func (a *ApexSet) hasSanitizedSource(sanitizer string) bool { func apexSetFactory() android.Module { module := &ApexSet{} module.AddProperties(&module.properties) - module.initPrebuiltCommon(module, &module.properties.PrebuiltCommonProperties) + module.prebuiltCommon.prebuiltCommonProperties = &module.properties.PrebuiltCommonProperties - return module -} - -func createApexExtractorModule(ctx android.BottomUpMutatorContext, name string, apexExtractorProperties *ApexExtractorProperties) { - props := struct { - Name *string - }{ - Name: proptools.StringPtr(name), - } - - ctx.CreateModule(privateApexExtractorModuleFactory, - &props, - apexExtractorProperties, - ) -} - -func apexExtractorModuleName(baseModuleName string) string { - return baseModuleName + ".apex.extractor" -} - -var _ prebuiltApexModuleCreator = (*ApexSet)(nil) + // init the module as a prebuilt + // even though this module type has srcs, use `InitPrebuiltModuleWithoutSrcs`, since the existing + // InitPrebuiltModule* are not friendly with Sources of Configurable type. + // The actual src will be evaluated in GenerateAndroidBuildActions. + android.InitPrebuiltModuleWithoutSrcs(module) + android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon) -// createPrebuiltApexModules creates modules necessary to export files from the apex set to other -// modules. -// -// This effectively does for apex_set what Prebuilt.createPrebuiltApexModules does for a -// prebuilt_apex except that instead of creating a selector module which selects one .apex file -// from those provided this creates an extractor module which extracts the appropriate .apex file -// from the zip file containing them. -func (a *ApexSet) createPrebuiltApexModules(ctx android.BottomUpMutatorContext) { - apexExtractorModuleName := apexExtractorModuleName(a.Name()) - createApexExtractorModule(ctx, apexExtractorModuleName, &a.properties.ApexExtractorProperties) - - apexFileSource := ":" + apexExtractorModuleName - a.createDeapexerModuleIfNeeded(ctx, deapexerModuleName(a.Name()), apexFileSource) - - // After passing the arch specific src properties to the creating the apex selector module - a.prebuiltCommonProperties.Selected_apex = proptools.StringPtr(apexFileSource) + return module } func (a *ApexSet) ComponentDepsMutator(ctx android.BottomUpMutatorContext) { @@ -1017,7 +835,15 @@ func (a *ApexSet) GenerateAndroidBuildActions(ctx android.ModuleContext) { ctx.ModuleErrorf("filename should end in %s or %s for apex_set", imageApexSuffix, imageCapexSuffix) } - inputApex := android.OptionalPathForModuleSrc(ctx, a.prebuiltCommonProperties.Selected_apex).Path() + var apexSet android.Path + if srcs := a.properties.prebuiltSrcs(ctx); len(srcs) == 1 { + apexSet = android.PathForModuleSrc(ctx, srcs[0]) + } else { + ctx.ModuleErrorf("Expected exactly one source apex_set file, found %v\n", srcs) + } + + extractedApex := extract(ctx, apexSet, a.properties.Prerelease) + a.outputApex = android.PathForModuleOut(ctx, a.installFilename) // Build the output APEX. If compression is not enabled, make sure the output is not compressed even if the input is compressed @@ -1027,7 +853,7 @@ func (a *ApexSet) GenerateAndroidBuildActions(ctx android.ModuleContext) { } ctx.Build(pctx, android.BuildParams{ Rule: buildRule, - Input: inputApex, + Input: extractedApex, Output: a.outputApex, }) @@ -1036,11 +862,13 @@ func (a *ApexSet) GenerateAndroidBuildActions(ctx android.ModuleContext) { return } + deapexerInfo := a.getDeapexerInfo(ctx, extractedApex) + // dexpreopt any system server jars if present - a.dexpreoptSystemServerJars(ctx) + a.dexpreoptSystemServerJars(ctx, deapexerInfo) // provide info used for generating the boot image - a.provideApexExportsInfo(ctx) + a.provideApexExportsInfo(ctx, deapexerInfo) a.providePrebuiltInfo(ctx) diff --git a/apex/systemserver_classpath_fragment_test.go b/apex/systemserver_classpath_fragment_test.go index fd9020b7f..acb364973 100644 --- a/apex/systemserver_classpath_fragment_test.go +++ b/apex/systemserver_classpath_fragment_test.go @@ -277,8 +277,6 @@ func TestPrebuiltSystemserverclasspathFragmentContents(t *testing.T) { java.CheckModuleDependencies(t, ctx, "myapex", "android_common_myapex", []string{ `all_apex_contributions`, `dex2oatd`, - `prebuilt_myapex.apex.selector`, - `prebuilt_myapex.deapexer`, `prebuilt_mysystemserverclasspathfragment`, }) @@ -286,10 +284,9 @@ func TestPrebuiltSystemserverclasspathFragmentContents(t *testing.T) { `all_apex_contributions`, `prebuilt_bar`, `prebuilt_foo`, - `prebuilt_myapex.deapexer`, }) - ensureExactDeapexedContents(t, ctx, "prebuilt_myapex", "android_common", []string{ + ensureExactDeapexedContents(t, ctx, "myapex", "android_common_myapex", []string{ "javalib/foo.jar", "javalib/bar.jar", "javalib/bar.jar.prof", @@ -439,10 +436,9 @@ func TestPrebuiltStandaloneSystemserverclasspathFragmentContents(t *testing.T) { `all_apex_contributions`, `prebuilt_bar`, `prebuilt_foo`, - `prebuilt_myapex.deapexer`, }) - ensureExactDeapexedContents(t, ctx, "prebuilt_myapex", "android_common", []string{ + ensureExactDeapexedContents(t, ctx, "myapex", "android_common_myapex", []string{ "javalib/foo.jar", "javalib/bar.jar", "javalib/bar.jar.prof", |