aboutsummaryrefslogtreecommitdiff
path: root/apex/apex_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'apex/apex_test.go')
-rw-r--r--apex/apex_test.go1072
1 files changed, 799 insertions, 273 deletions
diff --git a/apex/apex_test.go b/apex/apex_test.go
index abf6b1534..9dc77c28d 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -790,6 +790,79 @@ func TestApexManifestMinSdkVersion(t *testing.T) {
}
}
+func TestApexWithDessertSha(t *testing.T) {
+ ctx := testApex(t, `
+ apex_defaults {
+ name: "my_defaults",
+ key: "myapex.key",
+ product_specific: true,
+ file_contexts: ":my-file-contexts",
+ updatable: false,
+ }
+ apex {
+ name: "myapex_30",
+ min_sdk_version: "30",
+ defaults: ["my_defaults"],
+ }
+
+ apex {
+ name: "myapex_current",
+ min_sdk_version: "current",
+ defaults: ["my_defaults"],
+ }
+
+ apex {
+ name: "myapex_none",
+ defaults: ["my_defaults"],
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ filegroup {
+ name: "my-file-contexts",
+ srcs: ["product_specific_file_contexts"],
+ }
+ `, withFiles(map[string][]byte{
+ "product_specific_file_contexts": nil,
+ }), android.FixtureModifyProductVariables(
+ func(variables android.FixtureProductVariables) {
+ variables.Unbundled_build = proptools.BoolPtr(true)
+ variables.Always_use_prebuilt_sdks = proptools.BoolPtr(false)
+ }), android.FixtureMergeEnv(map[string]string{
+ "UNBUNDLED_BUILD_TARGET_SDK_WITH_DESSERT_SHA": "UpsideDownCake.abcdefghijklmnopqrstuvwxyz123456",
+ }))
+
+ testCases := []struct {
+ module string
+ minSdkVersion string
+ }{
+ {
+ module: "myapex_30",
+ minSdkVersion: "30",
+ },
+ {
+ module: "myapex_current",
+ minSdkVersion: "UpsideDownCake.abcdefghijklmnopqrstuvwxyz123456",
+ },
+ {
+ module: "myapex_none",
+ minSdkVersion: "UpsideDownCake.abcdefghijklmnopqrstuvwxyz123456",
+ },
+ }
+ for _, tc := range testCases {
+ module := ctx.ModuleForTests(tc.module, "android_common_"+tc.module)
+ args := module.Rule("apexRule").Args
+ optFlags := args["opt_flags"]
+ if !strings.Contains(optFlags, "--min_sdk_version "+tc.minSdkVersion) {
+ t.Errorf("%s: Expected min_sdk_version=%s, got: %s", tc.module, tc.minSdkVersion, optFlags)
+ }
+ }
+}
+
func TestFileContexts(t *testing.T) {
for _, vendor := range []bool{true, false} {
prop := ""
@@ -1455,6 +1528,7 @@ func TestRuntimeApexShouldInstallHwasanIfLibcDependsOnIt(t *testing.T) {
name: "libc",
no_libcrt: true,
nocrt: true,
+ no_crt_pad_segment: true,
stl: "none",
system_shared_libs: [],
stubs: { versions: ["1"] },
@@ -1469,6 +1543,7 @@ func TestRuntimeApexShouldInstallHwasanIfLibcDependsOnIt(t *testing.T) {
name: "libclang_rt.hwasan",
no_libcrt: true,
nocrt: true,
+ no_crt_pad_segment: true,
stl: "none",
system_shared_libs: [],
srcs: [""],
@@ -1511,6 +1586,7 @@ func TestRuntimeApexShouldInstallHwasanIfHwaddressSanitized(t *testing.T) {
name: "libc",
no_libcrt: true,
nocrt: true,
+ no_crt_pad_segment: true,
stl: "none",
system_shared_libs: [],
stubs: { versions: ["1"] },
@@ -1521,6 +1597,7 @@ func TestRuntimeApexShouldInstallHwasanIfHwaddressSanitized(t *testing.T) {
name: "libclang_rt.hwasan",
no_libcrt: true,
nocrt: true,
+ no_crt_pad_segment: true,
stl: "none",
system_shared_libs: [],
srcs: [""],
@@ -3725,7 +3802,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).Rule("deapexer")
+ deapexer := ctx.ModuleForTests(moduleName+".deapexer", variant).Description("deapex")
outputs := make([]string, 0, len(deapexer.ImplicitOutputs)+1)
if deapexer.Output != nil {
outputs = append(outputs, deapexer.Output.String())
@@ -3768,13 +3845,6 @@ func TestVndkApexCurrent(t *testing.T) {
"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) {
@@ -4976,6 +5046,7 @@ func TestApexWithShBinary(t *testing.T) {
key: "myapex.key",
sh_binaries: ["myscript"],
updatable: false,
+ compile_multilib: "both",
}
apex_key {
@@ -5355,6 +5426,13 @@ func TestPrebuiltApexNameWithPlatformBootclasspath(t *testing.T) {
).RunTest(t)
}
+// A minimal context object for use with DexJarBuildPath
+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) {
@@ -5364,10 +5442,10 @@ func TestPrebuiltExportDexImplementationJars(t *testing.T) {
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().PathOrNil()
+ dexJarBuildPath := p.DexJarBuildPath(moduleErrorfTestCtx{}).PathOrNil()
stem := android.RemoveOptionalPrebuiltPrefix(name)
android.AssertStringEquals(t, "DexJarBuildPath should be apex-related path.",
- ".intermediates/myapex.deapexer/android_common/deapexer/javalib/"+stem+".jar",
+ ".intermediates/prebuilt_myapex.deapexer/android_common/deapexer/javalib/"+stem+".jar",
android.NormalizePathForTesting(dexJarBuildPath))
}
@@ -5421,8 +5499,8 @@ func TestPrebuiltExportDexImplementationJars(t *testing.T) {
// Make sure that dexpreopt can access dex implementation files from the prebuilt.
ctx := testDexpreoptWithApexes(t, bp, "", transform)
- deapexerName := deapexerModuleName("myapex")
- android.AssertStringEquals(t, "APEX module name from deapexer name", "myapex", apexModuleName(deapexerName))
+ 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")
@@ -5645,8 +5723,8 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) {
`
ctx := testDexpreoptWithApexes(t, bp, "", preparer, fragment)
- checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar")
- checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libbar.jar")
+ 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, ``)
@@ -5723,8 +5801,8 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) {
`
ctx := testDexpreoptWithApexes(t, bp, "", preparer, fragment)
- checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar")
- checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libbar.jar")
+ 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, ``)
@@ -5737,7 +5815,7 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) {
myApex := ctx.ModuleForTests("myapex", "android_common_myapex").Module()
overrideNames := []string{
- "",
+ "myapex",
"myjavalib.myapex",
"libfoo.myapex",
"libbar.myapex",
@@ -5912,8 +5990,8 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) {
`
ctx := testDexpreoptWithApexes(t, bp, "", preparer, fragment)
- checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar")
- checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libbar.jar")
+ 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, ``)
@@ -6109,8 +6187,8 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) {
`
ctx := testDexpreoptWithApexes(t, bp, "", preparer, fragment)
- checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar")
- checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libbar.jar")
+ 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, ``)
@@ -6120,6 +6198,84 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) {
out/soong/.intermediates/packages/modules/com.android.art/art-bootclasspath-fragment/android_common_apex10000/modular-hiddenapi/index.csv
`)
})
+
+ t.Run("Co-existing unflagged apexes should create a duplicate module error", func(t *testing.T) {
+ bp := `
+ // Source
+ apex {
+ name: "myapex",
+ enabled: false,
+ key: "myapex.key",
+ bootclasspath_fragments: ["my-bootclasspath-fragment"],
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ // Prebuilt
+ prebuilt_apex {
+ name: "myapex.v1",
+ source_apex_name: "myapex",
+ arch: {
+ arm64: {
+ src: "myapex-arm64.apex",
+ },
+ arm: {
+ src: "myapex-arm.apex",
+ },
+ },
+ exported_bootclasspath_fragments: ["my-bootclasspath-fragment"],
+ prefer: true,
+ }
+ prebuilt_apex {
+ name: "myapex.v2",
+ source_apex_name: "myapex",
+ arch: {
+ arm64: {
+ src: "myapex-arm64.apex",
+ },
+ arm: {
+ src: "myapex-arm.apex",
+ },
+ },
+ exported_bootclasspath_fragments: ["my-bootclasspath-fragment"],
+ prefer: true,
+ }
+
+ prebuilt_bootclasspath_fragment {
+ name: "my-bootclasspath-fragment",
+ contents: ["libfoo", "libbar"],
+ apex_available: ["myapex"],
+ 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",
+ },
+ prefer: true,
+ }
+
+ java_import {
+ name: "libfoo",
+ jars: ["libfoo.jar"],
+ apex_available: ["myapex"],
+ prefer: true,
+ }
+ java_import {
+ name: "libbar",
+ jars: ["libbar.jar"],
+ apex_available: ["myapex"],
+ prefer: true,
+ }
+ `
+
+ testDexpreoptWithApexes(t, bp, "Multiple prebuilt modules prebuilt_myapex.v1 and prebuilt_myapex.v2 have been marked as preferred for this source module", preparer, fragment)
+ })
+
}
func TestApexWithTests(t *testing.T) {
@@ -8313,9 +8469,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/myapex.apex.extractor/android_common/extracted/myapex.hwasan.apks"
+ extractorOutput := "out/soong/.intermediates/prebuilt_myapex.apex.extractor/android_common/extracted/myapex.hwasan.apks"
- m := ctx.ModuleForTests("myapex.apex.extractor", "android_common")
+ m := ctx.ModuleForTests("prebuilt_myapex.apex.extractor", "android_common")
extractedApex := m.Output(extractorOutput)
android.AssertArrayString(t, "extractor input", []string{"myapex.hwasan.apks"}, extractedApex.Inputs.Strings())
@@ -8340,10 +8496,10 @@ func TestApexSetApksModuleAssignment(t *testing.T) {
}
`)
- m := ctx.ModuleForTests("myapex.apex.extractor", "android_common")
+ m := ctx.ModuleForTests("prebuilt_myapex.apex.extractor", "android_common")
// Check that the extractor produces the correct apks file from the input module
- extractorOutput := "out/soong/.intermediates/myapex.apex.extractor/android_common/extracted/myapex.apks"
+ extractorOutput := "out/soong/.intermediates/prebuilt_myapex.apex.extractor/android_common/extracted/myapex.apks"
extractedApex := m.Output(extractorOutput)
android.AssertArrayString(t, "extractor input", []string{"myapex.apks"}, extractedApex.Inputs.Strings())
@@ -8408,30 +8564,39 @@ func testDexpreoptWithApexes(t *testing.T, bp, errmsg string, preparer android.F
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: com.android.myapex and com.mycompany.android.myapex"))
+ "Multiple installable prebuilt APEXes provide ambiguous deapexers: prebuilt_com.android.art and prebuilt_com.mycompany.android.art"))
bpBase := `
apex_set {
- name: "com.android.myapex",
+ name: "com.android.art",
installable: true,
- exported_bootclasspath_fragments: ["my-bootclasspath-fragment"],
+ exported_bootclasspath_fragments: ["art-bootclasspath-fragment"],
set: "myapex.apks",
}
apex_set {
- name: "com.mycompany.android.myapex",
- apex_name: "com.android.myapex",
+ name: "com.mycompany.android.art",
+ apex_name: "com.android.art",
installable: true,
- exported_bootclasspath_fragments: ["my-bootclasspath-fragment"],
+ exported_bootclasspath_fragments: ["art-bootclasspath-fragment"],
set: "company-myapex.apks",
}
prebuilt_bootclasspath_fragment {
- name: "my-bootclasspath-fragment",
- apex_available: ["com.android.myapex"],
+ 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
}
`
@@ -8441,7 +8606,7 @@ func TestDuplicateDeapexersFromPrebuiltApexes(t *testing.T) {
java_import {
name: "libfoo",
jars: ["libfoo.jar"],
- apex_available: ["com.android.myapex"],
+ apex_available: ["com.android.art"],
}
`)
})
@@ -8453,7 +8618,8 @@ func TestDuplicateDeapexersFromPrebuiltApexes(t *testing.T) {
public: {
jars: ["libbar.jar"],
},
- apex_available: ["com.android.myapex"],
+ shared_library: false,
+ apex_available: ["com.android.art"],
}
`)
})
@@ -8468,7 +8634,8 @@ func TestDuplicateDeapexersFromPrebuiltApexes(t *testing.T) {
public: {
jars: ["libbar.jar"],
},
- apex_available: ["com.android.myapex"],
+ shared_library: false,
+ apex_available: ["com.android.art"],
}
`)
})
@@ -8480,6 +8647,8 @@ func TestDuplicateButEquivalentDeapexersFromPrebuiltApexes(t *testing.T) {
PrepareForTestWithApexBuildComponents,
)
+ errCtx := moduleErrorfTestCtx{}
+
bpBase := `
apex_set {
name: "com.android.myapex",
@@ -8528,8 +8697,8 @@ func TestDuplicateButEquivalentDeapexersFromPrebuiltApexes(t *testing.T) {
module := result.Module("libfoo", "android_common_com.android.myapex")
usesLibraryDep := module.(java.UsesLibraryDependency)
android.AssertPathRelativeToTopEquals(t, "dex jar path",
- "out/soong/.intermediates/com.android.myapex.deapexer/android_common/deapexer/javalib/libfoo.jar",
- usesLibraryDep.DexJarBuildPath().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) {
@@ -8551,8 +8720,8 @@ func TestDuplicateButEquivalentDeapexersFromPrebuiltApexes(t *testing.T) {
module := result.Module("libfoo", "android_common_com.android.myapex")
usesLibraryDep := module.(java.UsesLibraryDependency)
android.AssertPathRelativeToTopEquals(t, "dex jar path",
- "out/soong/.intermediates/com.android.myapex.deapexer/android_common/deapexer/javalib/libfoo.jar",
- usesLibraryDep.DexJarBuildPath().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) {
@@ -9124,7 +9293,7 @@ func TestApexSet(t *testing.T) {
}),
)
- m := ctx.ModuleForTests("myapex.apex.extractor", "android_common")
+ m := ctx.ModuleForTests("prebuilt_myapex.apex.extractor", "android_common")
// Check extract_apks tool parameters.
extractedApex := m.Output("extracted/myapex.apks")
@@ -9165,7 +9334,7 @@ func TestApexSet_NativeBridge(t *testing.T) {
}),
)
- m := ctx.ModuleForTests("myapex.apex.extractor", "android_common")
+ m := ctx.ModuleForTests("prebuilt_myapex.apex.extractor", "android_common")
// Check extract_apks tool parameters. No native bridge arch expected
extractedApex := m.Output("extracted/myapex.apks")
@@ -10175,188 +10344,196 @@ func ensureDoesNotContainRequiredDeps(t *testing.T, ctx *android.TestContext, mo
}
}
-// TODO(b/193460475): Re-enable this test
-//func TestApexStrictUpdtabilityLint(t *testing.T) {
-// bpTemplate := `
-// apex {
-// name: "myapex",
-// key: "myapex.key",
-// java_libs: ["myjavalib"],
-// updatable: %v,
-// min_sdk_version: "29",
-// }
-// apex_key {
-// name: "myapex.key",
-// }
-// java_library {
-// name: "myjavalib",
-// srcs: ["MyClass.java"],
-// apex_available: [ "myapex" ],
-// lint: {
-// strict_updatability_linting: %v,
-// },
-// sdk_version: "current",
-// min_sdk_version: "29",
-// }
-// `
-// fs := android.MockFS{
-// "lint-baseline.xml": nil,
-// }
-//
-// testCases := []struct {
-// testCaseName string
-// apexUpdatable bool
-// javaStrictUpdtabilityLint bool
-// lintFileExists bool
-// disallowedFlagExpected bool
-// }{
-// {
-// testCaseName: "lint-baseline.xml does not exist, no disallowed flag necessary in lint cmd",
-// apexUpdatable: true,
-// javaStrictUpdtabilityLint: true,
-// lintFileExists: false,
-// disallowedFlagExpected: false,
-// },
-// {
-// testCaseName: "non-updatable apex respects strict_updatability of javalib",
-// apexUpdatable: false,
-// javaStrictUpdtabilityLint: false,
-// lintFileExists: true,
-// disallowedFlagExpected: false,
-// },
-// {
-// testCaseName: "non-updatable apex respects strict updatability of javalib",
-// apexUpdatable: false,
-// javaStrictUpdtabilityLint: true,
-// lintFileExists: true,
-// disallowedFlagExpected: true,
-// },
-// {
-// testCaseName: "updatable apex sets strict updatability of javalib to true",
-// apexUpdatable: true,
-// javaStrictUpdtabilityLint: false, // will be set to true by mutator
-// lintFileExists: true,
-// disallowedFlagExpected: true,
-// },
-// }
-//
-// for _, testCase := range testCases {
-// bp := fmt.Sprintf(bpTemplate, testCase.apexUpdatable, testCase.javaStrictUpdtabilityLint)
-// fixtures := []android.FixturePreparer{}
-// if testCase.lintFileExists {
-// fixtures = append(fixtures, fs.AddToFixture())
-// }
-//
-// result := testApex(t, bp, fixtures...)
-// myjavalib := result.ModuleForTests("myjavalib", "android_common_apex29")
-// sboxProto := android.RuleBuilderSboxProtoForTests(t, myjavalib.Output("lint.sbox.textproto"))
-// disallowedFlagActual := strings.Contains(*sboxProto.Commands[0].Command, "--baseline lint-baseline.xml --disallowed_issues NewApi")
-//
-// if disallowedFlagActual != testCase.disallowedFlagExpected {
-// t.Errorf("Failed testcase: %v \nActual lint cmd: %v", testCase.testCaseName, *sboxProto.Commands[0].Command)
-// }
-// }
-//}
-//
-//func TestUpdatabilityLintSkipLibcore(t *testing.T) {
-// bp := `
-// apex {
-// name: "myapex",
-// key: "myapex.key",
-// java_libs: ["myjavalib"],
-// updatable: true,
-// min_sdk_version: "29",
-// }
-// apex_key {
-// name: "myapex.key",
-// }
-// java_library {
-// name: "myjavalib",
-// srcs: ["MyClass.java"],
-// apex_available: [ "myapex" ],
-// sdk_version: "current",
-// min_sdk_version: "29",
-// }
-// `
-//
-// testCases := []struct {
-// testCaseName string
-// moduleDirectory string
-// disallowedFlagExpected bool
-// }{
-// {
-// testCaseName: "lintable module defined outside libcore",
-// moduleDirectory: "",
-// disallowedFlagExpected: true,
-// },
-// {
-// testCaseName: "lintable module defined in libcore root directory",
-// moduleDirectory: "libcore/",
-// disallowedFlagExpected: false,
-// },
-// {
-// testCaseName: "lintable module defined in libcore child directory",
-// moduleDirectory: "libcore/childdir/",
-// disallowedFlagExpected: true,
-// },
-// }
-//
-// for _, testCase := range testCases {
-// lintFileCreator := android.FixtureAddTextFile(testCase.moduleDirectory+"lint-baseline.xml", "")
-// bpFileCreator := android.FixtureAddTextFile(testCase.moduleDirectory+"Android.bp", bp)
-// result := testApex(t, "", lintFileCreator, bpFileCreator)
-// myjavalib := result.ModuleForTests("myjavalib", "android_common_apex29")
-// sboxProto := android.RuleBuilderSboxProtoForTests(t, myjavalib.Output("lint.sbox.textproto"))
-// cmdFlags := fmt.Sprintf("--baseline %vlint-baseline.xml --disallowed_issues NewApi", testCase.moduleDirectory)
-// disallowedFlagActual := strings.Contains(*sboxProto.Commands[0].Command, cmdFlags)
-//
-// if disallowedFlagActual != testCase.disallowedFlagExpected {
-// t.Errorf("Failed testcase: %v \nActual lint cmd: %v", testCase.testCaseName, *sboxProto.Commands[0].Command)
-// }
-// }
-//}
-//
-//// checks transtive deps of an apex coming from bootclasspath_fragment
-//func TestApexStrictUpdtabilityLintBcpFragmentDeps(t *testing.T) {
-// bp := `
-// apex {
-// name: "myapex",
-// key: "myapex.key",
-// bootclasspath_fragments: ["mybootclasspathfragment"],
-// updatable: true,
-// min_sdk_version: "29",
-// }
-// apex_key {
-// name: "myapex.key",
-// }
-// bootclasspath_fragment {
-// name: "mybootclasspathfragment",
-// contents: ["myjavalib"],
-// apex_available: ["myapex"],
-// hidden_api: {
-// split_packages: ["*"],
-// },
-// }
-// java_library {
-// name: "myjavalib",
-// srcs: ["MyClass.java"],
-// apex_available: [ "myapex" ],
-// sdk_version: "current",
-// min_sdk_version: "29",
-// compile_dex: true,
-// }
-// `
-// fs := android.MockFS{
-// "lint-baseline.xml": nil,
-// }
-//
-// result := testApex(t, bp, dexpreopt.FixtureSetApexBootJars("myapex:myjavalib"), fs.AddToFixture())
-// myjavalib := result.ModuleForTests("myjavalib", "android_common_apex29")
-// sboxProto := android.RuleBuilderSboxProtoForTests(t, myjavalib.Output("lint.sbox.textproto"))
-// if !strings.Contains(*sboxProto.Commands[0].Command, "--baseline lint-baseline.xml --disallowed_issues NewApi") {
-// t.Errorf("Strict updabality lint missing in myjavalib coming from bootclasspath_fragment mybootclasspath-fragment\nActual lint cmd: %v", *sboxProto.Commands[0].Command)
-// }
-//}
+func TestApexStrictUpdtabilityLint(t *testing.T) {
+ bpTemplate := `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ java_libs: ["myjavalib"],
+ updatable: %v,
+ min_sdk_version: "29",
+ }
+ apex_key {
+ name: "myapex.key",
+ }
+ java_library {
+ name: "myjavalib",
+ srcs: ["MyClass.java"],
+ apex_available: [ "myapex" ],
+ lint: {
+ strict_updatability_linting: %v,
+ %s
+ },
+ sdk_version: "current",
+ min_sdk_version: "29",
+ }
+ `
+ fs := android.MockFS{
+ "lint-baseline.xml": nil,
+ }
+
+ testCases := []struct {
+ testCaseName string
+ apexUpdatable bool
+ javaStrictUpdtabilityLint bool
+ lintFileExists bool
+ disallowedFlagExpected bool
+ }{
+ {
+ testCaseName: "lint-baseline.xml does not exist, no disallowed flag necessary in lint cmd",
+ apexUpdatable: true,
+ javaStrictUpdtabilityLint: true,
+ lintFileExists: false,
+ disallowedFlagExpected: false,
+ },
+ {
+ testCaseName: "non-updatable apex respects strict_updatability of javalib",
+ apexUpdatable: false,
+ javaStrictUpdtabilityLint: false,
+ lintFileExists: true,
+ disallowedFlagExpected: false,
+ },
+ {
+ testCaseName: "non-updatable apex respects strict updatability of javalib",
+ apexUpdatable: false,
+ javaStrictUpdtabilityLint: true,
+ lintFileExists: true,
+ disallowedFlagExpected: true,
+ },
+ {
+ testCaseName: "updatable apex sets strict updatability of javalib to true",
+ apexUpdatable: true,
+ javaStrictUpdtabilityLint: false, // will be set to true by mutator
+ lintFileExists: true,
+ disallowedFlagExpected: true,
+ },
+ }
+
+ for _, testCase := range testCases {
+ fixtures := []android.FixturePreparer{}
+ baselineProperty := ""
+ if testCase.lintFileExists {
+ fixtures = append(fixtures, fs.AddToFixture())
+ baselineProperty = "baseline_filename: \"lint-baseline.xml\""
+ }
+ bp := fmt.Sprintf(bpTemplate, testCase.apexUpdatable, testCase.javaStrictUpdtabilityLint, baselineProperty)
+
+ result := testApex(t, bp, fixtures...)
+ myjavalib := result.ModuleForTests("myjavalib", "android_common_apex29")
+ sboxProto := android.RuleBuilderSboxProtoForTests(t, result, myjavalib.Output("lint.sbox.textproto"))
+ disallowedFlagActual := strings.Contains(*sboxProto.Commands[0].Command, "--baseline lint-baseline.xml --disallowed_issues NewApi")
+
+ if disallowedFlagActual != testCase.disallowedFlagExpected {
+ t.Errorf("Failed testcase: %v \nActual lint cmd: %v", testCase.testCaseName, *sboxProto.Commands[0].Command)
+ }
+ }
+}
+
+func TestUpdatabilityLintSkipLibcore(t *testing.T) {
+ bp := `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ java_libs: ["myjavalib"],
+ updatable: true,
+ min_sdk_version: "29",
+ }
+ apex_key {
+ name: "myapex.key",
+ }
+ java_library {
+ name: "myjavalib",
+ srcs: ["MyClass.java"],
+ apex_available: [ "myapex" ],
+ sdk_version: "current",
+ min_sdk_version: "29",
+ lint: {
+ baseline_filename: "lint-baseline.xml",
+ }
+ }
+ `
+
+ testCases := []struct {
+ testCaseName string
+ moduleDirectory string
+ disallowedFlagExpected bool
+ }{
+ {
+ testCaseName: "lintable module defined outside libcore",
+ moduleDirectory: "",
+ disallowedFlagExpected: true,
+ },
+ {
+ testCaseName: "lintable module defined in libcore root directory",
+ moduleDirectory: "libcore/",
+ disallowedFlagExpected: false,
+ },
+ {
+ testCaseName: "lintable module defined in libcore child directory",
+ moduleDirectory: "libcore/childdir/",
+ disallowedFlagExpected: true,
+ },
+ }
+
+ for _, testCase := range testCases {
+ lintFileCreator := android.FixtureAddTextFile(testCase.moduleDirectory+"lint-baseline.xml", "")
+ bpFileCreator := android.FixtureAddTextFile(testCase.moduleDirectory+"Android.bp", bp)
+ result := testApex(t, "", lintFileCreator, bpFileCreator)
+ myjavalib := result.ModuleForTests("myjavalib", "android_common_apex29")
+ sboxProto := android.RuleBuilderSboxProtoForTests(t, result, myjavalib.Output("lint.sbox.textproto"))
+ cmdFlags := fmt.Sprintf("--baseline %vlint-baseline.xml --disallowed_issues NewApi", testCase.moduleDirectory)
+ disallowedFlagActual := strings.Contains(*sboxProto.Commands[0].Command, cmdFlags)
+
+ if disallowedFlagActual != testCase.disallowedFlagExpected {
+ t.Errorf("Failed testcase: %v \nActual lint cmd: %v", testCase.testCaseName, *sboxProto.Commands[0].Command)
+ }
+ }
+}
+
+// checks transtive deps of an apex coming from bootclasspath_fragment
+func TestApexStrictUpdtabilityLintBcpFragmentDeps(t *testing.T) {
+ bp := `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ bootclasspath_fragments: ["mybootclasspathfragment"],
+ updatable: true,
+ min_sdk_version: "29",
+ }
+ apex_key {
+ name: "myapex.key",
+ }
+ bootclasspath_fragment {
+ name: "mybootclasspathfragment",
+ contents: ["myjavalib"],
+ apex_available: ["myapex"],
+ hidden_api: {
+ split_packages: ["*"],
+ },
+ }
+ java_library {
+ name: "myjavalib",
+ srcs: ["MyClass.java"],
+ apex_available: [ "myapex" ],
+ sdk_version: "current",
+ min_sdk_version: "29",
+ compile_dex: true,
+ lint: {
+ baseline_filename: "lint-baseline.xml",
+ }
+ }
+ `
+ fs := android.MockFS{
+ "lint-baseline.xml": nil,
+ }
+
+ result := testApex(t, bp, dexpreopt.FixtureSetApexBootJars("myapex:myjavalib"), fs.AddToFixture())
+ myjavalib := result.ModuleForTests("myjavalib", "android_common_apex29")
+ sboxProto := android.RuleBuilderSboxProtoForTests(t, result, myjavalib.Output("lint.sbox.textproto"))
+ if !strings.Contains(*sboxProto.Commands[0].Command, "--baseline lint-baseline.xml --disallowed_issues NewApi") {
+ t.Errorf("Strict updabality lint missing in myjavalib coming from bootclasspath_fragment mybootclasspath-fragment\nActual lint cmd: %v", *sboxProto.Commands[0].Command)
+ }
+}
// updatable apexes should propagate updatable=true to its apps
func TestUpdatableApexEnforcesAppUpdatability(t *testing.T) {
@@ -10947,25 +11124,23 @@ 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) != 5 {
+ if len(copyCmds) != 8 {
t.Fatalf("Expected 5 commands, got %d in:\n%s", len(copyCmds), s)
}
- ensureMatches(t, copyCmds[4], "^cp -f .*/aconfig_flags.pb .*/image.apex$")
+ ensureMatches(t, copyCmds[4], "^cp -f .*/aconfig_flags.pb .*/image.apex/etc$")
+ ensureMatches(t, copyCmds[5], "^cp -f .*/package.map .*/image.apex/etc$")
+ ensureMatches(t, copyCmds[6], "^cp -f .*/flag.map .*/image.apex/etc$")
+ ensureMatches(t, copyCmds[7], "^cp -f .*/flag.val .*/image.apex/etc$")
- combineAconfigRule := mod.Rule("All_aconfig_declarations_dump")
- s = " " + combineAconfigRule.Args["cache_files"]
- aconfigArgs := regexp.MustCompile(" --cache ").Split(s, -1)[1:]
- if len(aconfigArgs) != 2 {
- t.Fatalf("Expected 2 commands, got %d in:\n%s", len(aconfigArgs), s)
+ inputs := []string{
+ "my_aconfig_declarations_foo/intermediate.pb",
+ "my_aconfig_declarations_bar/intermediate.pb",
}
- android.EnsureListContainsSuffix(t, aconfigArgs, "my_aconfig_declarations_foo/intermediate.pb")
- android.EnsureListContainsSuffix(t, aconfigArgs, "my_aconfig_declarations_bar/intermediate.pb")
-
- buildParams := combineAconfigRule.BuildParams
- android.EnsureListContainsSuffix(t, buildParams.Inputs.Strings(), "my_aconfig_declarations_foo/intermediate.pb")
- android.EnsureListContainsSuffix(t, buildParams.Inputs.Strings(), "my_aconfig_declarations_bar/intermediate.pb")
- ensureContains(t, buildParams.Output.String(), "android_common_myapex/aconfig_flags.pb")
+ VerifyAconfigRule(t, &mod, "combine_aconfig_declarations", inputs, "android_common_myapex/aconfig_flags.pb", "", "")
+ 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")
}
func TestAconfigFilesJavaAndCcDeps(t *testing.T) {
@@ -11073,30 +11248,24 @@ 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) != 9 {
- t.Fatalf("Expected 9 commands, got %d in:\n%s", len(copyCmds), s)
+ if len(copyCmds) != 12 {
+ t.Fatalf("Expected 12 commands, got %d in:\n%s", len(copyCmds), s)
}
- ensureMatches(t, copyCmds[8], "^cp -f .*/aconfig_flags.pb .*/image.apex$")
-
- combineAconfigRule := mod.Rule("All_aconfig_declarations_dump")
- s = " " + combineAconfigRule.Args["cache_files"]
- aconfigArgs := regexp.MustCompile(" --cache ").Split(s, -1)[1:]
- if len(aconfigArgs) != 3 {
- t.Fatalf("Expected 3 commands, got %d in:\n%s", len(aconfigArgs), s)
- }
- android.EnsureListContainsSuffix(t, aconfigArgs, "my_aconfig_declarations_foo/intermediate.pb")
- android.EnsureListContainsSuffix(t, aconfigArgs, "my_cc_library_bar/android_arm64_armv8-a_shared_apex10000/aconfig_merged.pb")
- android.EnsureListContainsSuffix(t, aconfigArgs, "my_aconfig_declarations_baz/intermediate.pb")
+ ensureMatches(t, copyCmds[8], "^cp -f .*/aconfig_flags.pb .*/image.apex/etc$")
+ ensureMatches(t, copyCmds[9], "^cp -f .*/package.map .*/image.apex/etc$")
+ ensureMatches(t, copyCmds[10], "^cp -f .*/flag.map .*/image.apex/etc$")
+ ensureMatches(t, copyCmds[11], "^cp -f .*/flag.val .*/image.apex/etc$")
- buildParams := combineAconfigRule.BuildParams
- if len(buildParams.Inputs) != 3 {
- t.Fatalf("Expected 3 input, got %d", len(buildParams.Inputs))
+ inputs := []string{
+ "my_aconfig_declarations_foo/intermediate.pb",
+ "my_cc_library_bar/android_arm64_armv8-a_shared_apex10000/myapex/aconfig_merged.pb",
+ "my_aconfig_declarations_baz/intermediate.pb",
}
- android.EnsureListContainsSuffix(t, buildParams.Inputs.Strings(), "my_aconfig_declarations_foo/intermediate.pb")
- android.EnsureListContainsSuffix(t, buildParams.Inputs.Strings(), "my_cc_library_bar/android_arm64_armv8-a_shared_apex10000/aconfig_merged.pb")
- android.EnsureListContainsSuffix(t, buildParams.Inputs.Strings(), "my_aconfig_declarations_baz/intermediate.pb")
- ensureContains(t, buildParams.Output.String(), "android_common_myapex/aconfig_flags.pb")
+ VerifyAconfigRule(t, &mod, "combine_aconfig_declarations", inputs, "android_common_myapex/aconfig_flags.pb", "", "")
+ 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")
}
func TestAconfigFilesRustDeps(t *testing.T) {
@@ -11220,28 +11389,45 @@ 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) != 23 {
- t.Fatalf("Expected 23 commands, got %d in:\n%s", len(copyCmds), s)
+ if len(copyCmds) != 26 {
+ t.Fatalf("Expected 26 commands, got %d in:\n%s", len(copyCmds), s)
}
- ensureMatches(t, copyCmds[22], "^cp -f .*/aconfig_flags.pb .*/image.apex$")
+ ensureMatches(t, copyCmds[22], "^cp -f .*/aconfig_flags.pb .*/image.apex/etc$")
+ ensureMatches(t, copyCmds[23], "^cp -f .*/package.map .*/image.apex/etc$")
+ ensureMatches(t, copyCmds[24], "^cp -f .*/flag.map .*/image.apex/etc$")
+ ensureMatches(t, copyCmds[25], "^cp -f .*/flag.val .*/image.apex/etc$")
- combineAconfigRule := mod.Rule("All_aconfig_declarations_dump")
- s = " " + combineAconfigRule.Args["cache_files"]
+ inputs := []string{
+ "my_aconfig_declarations_foo/intermediate.pb",
+ "my_aconfig_declarations_bar/intermediate.pb",
+ "my_aconfig_declarations_baz/intermediate.pb",
+ "my_rust_binary/android_arm64_armv8-a_apex10000/myapex/aconfig_merged.pb",
+ }
+ VerifyAconfigRule(t, &mod, "combine_aconfig_declarations", inputs, "android_common_myapex/aconfig_flags.pb", "", "")
+ 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")
+}
+
+func VerifyAconfigRule(t *testing.T, mod *android.TestingModule, desc string, inputs []string, output string, container string, file_type string) {
+ aconfigRule := mod.Description(desc)
+ s := " " + aconfigRule.Args["cache_files"]
aconfigArgs := regexp.MustCompile(" --cache ").Split(s, -1)[1:]
- if len(aconfigArgs) != 2 {
- t.Fatalf("Expected 2 commands, got %d in:\n%s", len(aconfigArgs), s)
+ if len(aconfigArgs) != len(inputs) {
+ t.Fatalf("Expected %d commands, got %d in:\n%s", len(inputs), len(aconfigArgs), s)
}
- android.EnsureListContainsSuffix(t, aconfigArgs, "my_aconfig_declarations_foo/intermediate.pb")
- android.EnsureListContainsSuffix(t, aconfigArgs, "my_rust_binary/android_arm64_armv8-a_apex10000/aconfig_merged.pb")
- buildParams := combineAconfigRule.BuildParams
- if len(buildParams.Inputs) != 2 {
- t.Fatalf("Expected 3 input, got %d", len(buildParams.Inputs))
+ ensureEquals(t, container, aconfigRule.Args["container"])
+ ensureEquals(t, file_type, aconfigRule.Args["file_type"])
+
+ buildParams := aconfigRule.BuildParams
+ for _, input := range inputs {
+ android.EnsureListContainsSuffix(t, aconfigArgs, input)
+ android.EnsureListContainsSuffix(t, buildParams.Inputs.Strings(), input)
}
- android.EnsureListContainsSuffix(t, buildParams.Inputs.Strings(), "my_aconfig_declarations_foo/intermediate.pb")
- android.EnsureListContainsSuffix(t, buildParams.Inputs.Strings(), "my_rust_binary/android_arm64_armv8-a_apex10000/aconfig_merged.pb")
- ensureContains(t, buildParams.Output.String(), "android_common_myapex/aconfig_flags.pb")
+
+ ensureContains(t, buildParams.Output.String(), output)
}
func TestAconfigFilesOnlyMatchCurrentApex(t *testing.T) {
@@ -11404,3 +11590,343 @@ func TestAconfigFilesRemoveDuplicates(t *testing.T) {
android.EnsureListContainsSuffix(t, buildParams.Inputs.Strings(), "my_aconfig_declarations_foo/intermediate.pb")
ensureContains(t, buildParams.Output.String(), "android_common_myapex/aconfig_flags.pb")
}
+
+// Test that the boot jars come from the _selected_ apex prebuilt
+// RELEASE_APEX_CONTIRBUTIONS_* build flags will be used to select the correct prebuilt for a specific release config
+func TestBootDexJarsMultipleApexPrebuilts(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()))
+ }
+ }
+
+ // Check that the boot jars of the selected apex are run through boot_jars_package_check
+ // This validates that the jars on the bootclasspath do not contain packages outside an allowlist
+ checkBootJarsPackageCheck := func(t *testing.T, ctx *android.TestContext, expectedBootJar string) {
+ platformBcp := ctx.ModuleForTests("platform-bootclasspath", "android_common")
+ bootJarsCheckRule := platformBcp.Rule("boot_jars_package_check")
+ android.AssertStringMatches(t, "Could not find the correct boot dex jar in package check rule", bootJarsCheckRule.RuleParams.Command, "build/soong/scripts/check_boot_jars/package_allowed_list.txt.*"+expectedBootJar)
+ }
+
+ // Check that the boot jars used to generate the monolithic hiddenapi flags come from the selected apex
+ checkBootJarsForMonolithicHiddenapi := func(t *testing.T, ctx *android.TestContext, expectedBootJar string) {
+ monolithicHiddenapiFlagsCmd := ctx.ModuleForTests("platform-bootclasspath", "android_common").Output("out/soong/hiddenapi/hiddenapi-stub-flags.txt").RuleParams.Command
+ android.AssertStringMatches(t, "Could not find the correct boot dex jar in monolithic hiddenapi flags generation command", monolithicHiddenapiFlagsCmd, "--boot-dex="+expectedBootJar)
+ }
+
+ bp := `
+ // Source APEX.
+
+ java_library {
+ name: "framework-foo",
+ srcs: ["foo.java"],
+ installable: true,
+ apex_available: [
+ "com.android.foo",
+ ],
+ }
+
+ bootclasspath_fragment {
+ name: "foo-bootclasspath-fragment",
+ contents: ["framework-foo"],
+ apex_available: [
+ "com.android.foo",
+ ],
+ hidden_api: {
+ split_packages: ["*"],
+ },
+ }
+
+ apex_key {
+ name: "com.android.foo.key",
+ public_key: "com.android.foo.avbpubkey",
+ private_key: "com.android.foo.pem",
+ }
+
+ apex {
+ name: "com.android.foo",
+ key: "com.android.foo.key",
+ bootclasspath_fragments: ["foo-bootclasspath-fragment"],
+ updatable: false,
+ }
+
+ // Prebuilt APEX.
+
+ java_sdk_library_import {
+ name: "framework-foo",
+ public: {
+ jars: ["foo.jar"],
+ },
+ apex_available: ["com.android.foo"],
+ shared_library: false,
+ }
+
+ prebuilt_bootclasspath_fragment {
+ name: "foo-bootclasspath-fragment",
+ contents: ["framework-foo"],
+ 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",
+ },
+ apex_available: [
+ "com.android.foo",
+ ],
+ }
+
+ prebuilt_apex {
+ name: "com.android.foo",
+ apex_name: "com.android.foo",
+ src: "com.android.foo-arm.apex",
+ exported_bootclasspath_fragments: ["foo-bootclasspath-fragment"],
+ }
+
+ // Another Prebuilt ART APEX
+ prebuilt_apex {
+ name: "com.android.foo.v2",
+ apex_name: "com.android.foo", // Used to determine the API domain
+ src: "com.android.foo-arm.apex",
+ exported_bootclasspath_fragments: ["foo-bootclasspath-fragment"],
+ }
+
+ // APEX contribution modules
+
+ apex_contributions {
+ name: "foo.source.contributions",
+ api_domain: "com.android.foo",
+ contents: ["com.android.foo"],
+ }
+
+ apex_contributions {
+ name: "foo.prebuilt.contributions",
+ api_domain: "com.android.foo",
+ contents: ["prebuilt_com.android.foo"],
+ }
+
+ apex_contributions {
+ name: "foo.prebuilt.v2.contributions",
+ api_domain: "com.android.foo",
+ contents: ["com.android.foo.v2"], // prebuilt_ prefix is missing because of prebuilt_rename mutator
+ }
+ `
+
+ testCases := []struct {
+ desc string
+ selectedApexContributions string
+ expectedBootJar string
+ }{
+ {
+ desc: "Source apex com.android.foo is selected, bootjar should come from source java library",
+ selectedApexContributions: "foo.source.contributions",
+ expectedBootJar: "out/soong/.intermediates/foo-bootclasspath-fragment/android_common_apex10000/hiddenapi-modular/encoded/framework-foo.jar",
+ },
+ {
+ 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",
+ },
+ {
+ 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",
+ },
+ }
+
+ fragment := java.ApexVariantReference{
+ Apex: proptools.StringPtr("com.android.foo"),
+ Module: proptools.StringPtr("foo-bootclasspath-fragment"),
+ }
+
+ for _, tc := range testCases {
+ preparer := android.GroupFixturePreparers(
+ java.FixtureConfigureApexBootJars("com.android.foo:framework-foo"),
+ android.FixtureMergeMockFs(map[string][]byte{
+ "system/sepolicy/apex/com.android.foo-file_contexts": nil,
+ }),
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.BuildFlags = map[string]string{
+ "RELEASE_APEX_CONTRIBUTIONS_ADSERVICES": tc.selectedApexContributions,
+ }
+ }),
+ )
+ ctx := testDexpreoptWithApexes(t, bp, "", preparer, fragment)
+ checkBootDexJarPath(t, ctx, "framework-foo", tc.expectedBootJar)
+ checkBootJarsPackageCheck(t, ctx, tc.expectedBootJar)
+ checkBootJarsForMonolithicHiddenapi(t, ctx, tc.expectedBootJar)
+ }
+}
+
+// Test that product packaging installs the selected mainline module (either source or a specific prebuilt)
+// RELEASE_APEX_CONTIRBUTIONS_* build flags will be used to select the correct prebuilt for a specific release config
+func TestInstallationRulesForMultipleApexPrebuilts(t *testing.T) {
+ // check that the LOCAL_MODULE in the generated mk file matches the name used in PRODUCT_PACKAGES
+ // Since the name used in PRODUCT_PACKAGES does not contain prebuilt_ prefix, LOCAL_MODULE should not contain any prefix either
+ checkLocalModuleName := func(t *testing.T, ctx *android.TestContext, soongApexModuleName string, expectedLocalModuleName string) {
+ // Variations are created based on apex_name
+ entries := android.AndroidMkEntriesForTest(t, ctx, ctx.ModuleForTests(soongApexModuleName, "android_common_com.android.foo").Module())
+ android.AssertStringEquals(t, "LOCAL_MODULE of the prebuilt apex must match the name listed in PRODUCT_PACKAGES", expectedLocalModuleName, entries[0].EntryMap["LOCAL_MODULE"][0])
+ }
+ // for a mainline module family, check that only the flagged soong module is visible to make
+ checkHideFromMake := func(t *testing.T, ctx *android.TestContext, visibleModuleName string, hiddenModuleNames []string) {
+ variation := func(moduleName string) string {
+ ret := "android_common_com.android.foo"
+ if moduleName == "com.google.android.foo" {
+ ret = "android_common_com.google.android.foo_com.android.foo"
+ }
+ return ret
+ }
+
+ visibleModule := ctx.ModuleForTests(visibleModuleName, variation(visibleModuleName)).Module()
+ android.AssertBoolEquals(t, "Apex "+visibleModuleName+" selected using apex_contributions should be visible to make", false, visibleModule.IsHideFromMake())
+
+ for _, hiddenModuleName := range hiddenModuleNames {
+ hiddenModule := ctx.ModuleForTests(hiddenModuleName, variation(hiddenModuleName)).Module()
+ android.AssertBoolEquals(t, "Apex "+hiddenModuleName+" not selected using apex_contributions should be hidden from make", true, hiddenModule.IsHideFromMake())
+
+ }
+ }
+
+ bp := `
+ apex_key {
+ name: "com.android.foo.key",
+ public_key: "com.android.foo.avbpubkey",
+ private_key: "com.android.foo.pem",
+ }
+
+ // AOSP source apex
+ apex {
+ name: "com.android.foo",
+ key: "com.android.foo.key",
+ updatable: false,
+ }
+
+ // Google source apex
+ override_apex {
+ name: "com.google.android.foo",
+ base: "com.android.foo",
+ key: "com.android.foo.key",
+ }
+
+ // Prebuilt Google APEX.
+
+ prebuilt_apex {
+ name: "com.google.android.foo",
+ apex_name: "com.android.foo",
+ src: "com.android.foo-arm.apex",
+ prefer: true, // prefer is set to true on both the prebuilts to induce an error if flagging is not present
+ }
+
+ // Another Prebuilt Google APEX
+ prebuilt_apex {
+ name: "com.google.android.foo.v2",
+ apex_name: "com.android.foo",
+ source_apex_name: "com.google.android.foo", // source_apex_name becomes LOCAL_MODULE in the generated mk file
+ src: "com.android.foo-arm.apex",
+ prefer: true, // prefer is set to true on both the prebuilts to induce an error if flagging is not present
+ }
+
+ // APEX contribution modules
+
+ apex_contributions {
+ name: "foo.source.contributions",
+ api_domain: "com.android.foo",
+ contents: ["com.google.android.foo"],
+ }
+
+ apex_contributions {
+ name: "foo.prebuilt.contributions",
+ api_domain: "com.android.foo",
+ contents: ["prebuilt_com.google.android.foo"],
+ }
+
+ apex_contributions {
+ name: "foo.prebuilt.v2.contributions",
+ api_domain: "com.android.foo",
+ contents: ["prebuilt_com.google.android.foo.v2"],
+ }
+
+ // This is an incompatible module because it selects multiple versions of the same mainline module
+ apex_contributions {
+ name: "foo.prebuilt.duplicate.contributions",
+ api_domain: "com.android.foo",
+ contents: [
+ "prebuilt_com.google.android.foo",
+ "prebuilt_com.google.android.foo.v2",
+ ],
+ }
+ `
+
+ testCases := []struct {
+ desc string
+ selectedApexContributions string
+ expectedVisibleModuleName string
+ expectedHiddenModuleNames []string
+ expectedError string
+ }{
+ {
+ desc: "Source apex is selected, prebuilts should be hidden from make",
+ selectedApexContributions: "foo.source.contributions",
+ expectedVisibleModuleName: "com.google.android.foo",
+ expectedHiddenModuleNames: []string{"prebuilt_com.google.android.foo", "prebuilt_com.google.android.foo.v2"},
+ },
+ {
+ desc: "Prebuilt apex prebuilt_com.android.foo is selected, source and the other prebuilt should be hidden from make",
+ selectedApexContributions: "foo.prebuilt.contributions",
+ expectedVisibleModuleName: "prebuilt_com.google.android.foo",
+ expectedHiddenModuleNames: []string{"com.google.android.foo", "prebuilt_com.google.android.foo.v2"},
+ },
+ {
+ desc: "Prebuilt apex prebuilt_com.android.fooi.v2 is selected, source and the other prebuilt should be hidden from make",
+ selectedApexContributions: "foo.prebuilt.v2.contributions",
+ expectedVisibleModuleName: "prebuilt_com.google.android.foo.v2",
+ expectedHiddenModuleNames: []string{"com.google.android.foo", "prebuilt_com.google.android.foo"},
+ },
+ {
+ desc: "Multiple versions of a prebuilt apex is selected in the same release config",
+ selectedApexContributions: "foo.prebuilt.duplicate.contributions",
+ expectedError: "Found duplicate variations of the same module in apex_contributions: prebuilt_com.google.android.foo and prebuilt_com.google.android.foo.v2",
+ },
+ }
+
+ for _, tc := range testCases {
+ preparer := android.GroupFixturePreparers(
+ android.FixtureMergeMockFs(map[string][]byte{
+ "system/sepolicy/apex/com.android.foo-file_contexts": nil,
+ }),
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.BuildFlags = map[string]string{
+ "RELEASE_APEX_CONTRIBUTIONS_ADSERVICES": tc.selectedApexContributions,
+ }
+ }),
+ )
+ if tc.expectedError != "" {
+ preparer = preparer.ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern(tc.expectedError))
+ testApex(t, bp, preparer)
+ return
+ }
+ ctx := testApex(t, bp, preparer)
+
+ // Check that the LOCAL_MODULE of the two prebuilts is com.android.foo
+ // This ensures that product packaging can pick them for installation if it has been flagged by apex_contributions
+ checkLocalModuleName(t, ctx, "prebuilt_com.google.android.foo", "com.google.android.foo")
+ checkLocalModuleName(t, ctx, "prebuilt_com.google.android.foo.v2", "com.google.android.foo")
+
+ // Check that
+ // 1. The contents of the selected apex_contributions are visible to make
+ // 2. The rest of the apexes in the mainline module family (source or other prebuilt) is hidden from make
+ checkHideFromMake(t, ctx, tc.expectedVisibleModuleName, tc.expectedHiddenModuleNames)
+ }
+}