• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright (C) 2021 The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package apex
16
17import (
18	"fmt"
19	"strings"
20	"testing"
21
22	"android/soong/android"
23	"android/soong/dexpreopt"
24	"android/soong/java"
25
26	"github.com/google/blueprint/proptools"
27)
28
29// Contains tests for platform_bootclasspath logic from java/platform_bootclasspath.go that requires
30// apexes.
31
32var prepareForTestWithPlatformBootclasspath = android.GroupFixturePreparers(
33	java.PrepareForTestWithJavaDefaultModules,
34	PrepareForTestWithApexBuildComponents,
35)
36
37func TestPlatformBootclasspath_Fragments(t *testing.T) {
38	t.Parallel()
39	result := android.GroupFixturePreparers(
40		prepareForTestWithPlatformBootclasspath,
41		prepareForTestWithMyapex,
42		java.PrepareForTestWithJavaSdkLibraryFiles,
43		java.FixtureWithLastReleaseApis("foo"),
44		java.FixtureConfigureApexBootJars("myapex:bar"),
45		android.FixtureWithRootAndroidBp(`
46			platform_bootclasspath {
47				name: "platform-bootclasspath",
48				fragments: [
49					{
50						apex: "myapex",
51						module:"bar-fragment",
52					},
53				],
54				hidden_api: {
55					unsupported: [
56							"unsupported.txt",
57					],
58					removed: [
59							"removed.txt",
60					],
61					max_target_r_low_priority: [
62							"max-target-r-low-priority.txt",
63					],
64					max_target_q: [
65							"max-target-q.txt",
66					],
67					max_target_p: [
68							"max-target-p.txt",
69					],
70					max_target_o_low_priority: [
71							"max-target-o-low-priority.txt",
72					],
73					blocked: [
74							"blocked.txt",
75					],
76					unsupported_packages: [
77							"unsupported-packages.txt",
78					],
79				},
80			}
81
82			apex {
83				name: "myapex",
84				key: "myapex.key",
85				bootclasspath_fragments: [
86					"bar-fragment",
87				],
88				updatable: false,
89				min_sdk_version: "30", // R
90			}
91
92			apex_key {
93				name: "myapex.key",
94				public_key: "testkey.avbpubkey",
95				private_key: "testkey.pem",
96			}
97
98			bootclasspath_fragment {
99				name: "bar-fragment",
100				contents: ["bar"],
101				apex_available: ["myapex"],
102				api: {
103					stub_libs: ["foo"],
104				},
105				hidden_api: {
106					unsupported: [
107							"bar-unsupported.txt",
108					],
109					removed: [
110							"bar-removed.txt",
111					],
112					max_target_r_low_priority: [
113							"bar-max-target-r-low-priority.txt",
114					],
115					max_target_q: [
116							"bar-max-target-q.txt",
117					],
118					max_target_p: [
119							"bar-max-target-p.txt",
120					],
121					max_target_o_low_priority: [
122							"bar-max-target-o-low-priority.txt",
123					],
124					blocked: [
125							"bar-blocked.txt",
126					],
127					unsupported_packages: [
128							"bar-unsupported-packages.txt",
129					],
130					split_packages: ["*"],
131				},
132			}
133
134			java_library {
135				name: "bar",
136				apex_available: ["myapex"],
137				srcs: ["a.java"],
138				system_modules: "none",
139				sdk_version: "none",
140				compile_dex: true,
141				permitted_packages: ["bar"],
142				min_sdk_version: "30", // R
143			}
144
145			java_sdk_library {
146				name: "foo",
147				srcs: ["a.java"],
148				public: {
149					enabled: true,
150				},
151				compile_dex: true,
152			}
153		`),
154	).RunTest(t)
155
156	pbcp := result.Module("platform-bootclasspath", "android_common")
157	info, _ := android.OtherModuleProvider(result, pbcp, java.MonolithicHiddenAPIInfoProvider)
158
159	for _, category := range java.HiddenAPIFlagFileCategories {
160		name := category.PropertyName()
161		message := fmt.Sprintf("category %s", name)
162		filename := strings.ReplaceAll(name, "_", "-")
163		expected := []string{fmt.Sprintf("%s.txt", filename), fmt.Sprintf("bar-%s.txt", filename)}
164		android.AssertPathsRelativeToTopEquals(t, message, expected, info.FlagsFilesByCategory[category])
165	}
166
167	android.AssertPathsRelativeToTopEquals(t, "annotation flags", []string{"out/soong/.intermediates/bar-fragment/android_common_myapex/modular-hiddenapi/annotation-flags.csv"}, info.AnnotationFlagsPaths)
168	android.AssertPathsRelativeToTopEquals(t, "metadata flags", []string{"out/soong/.intermediates/bar-fragment/android_common_myapex/modular-hiddenapi/metadata.csv"}, info.MetadataPaths)
169	android.AssertPathsRelativeToTopEquals(t, "index flags", []string{"out/soong/.intermediates/bar-fragment/android_common_myapex/modular-hiddenapi/index.csv"}, info.IndexPaths)
170
171	android.AssertArrayString(t, "stub flags", []string{"out/soong/.intermediates/bar-fragment/android_common_myapex/modular-hiddenapi/filtered-stub-flags.csv:out/soong/.intermediates/bar-fragment/android_common_myapex/modular-hiddenapi/signature-patterns.csv"}, info.StubFlagSubsets.RelativeToTop())
172	android.AssertArrayString(t, "all flags", []string{"out/soong/.intermediates/bar-fragment/android_common_myapex/modular-hiddenapi/filtered-flags.csv:out/soong/.intermediates/bar-fragment/android_common_myapex/modular-hiddenapi/signature-patterns.csv"}, info.FlagSubsets.RelativeToTop())
173}
174
175// TestPlatformBootclasspath_LegacyPrebuiltFragment verifies that the
176// prebuilt_bootclasspath_fragment falls back to using the complete stub-flags/all-flags if the
177// filtered files are not provided.
178//
179// TODO: Remove once all prebuilts use the filtered_... properties.
180func TestPlatformBootclasspath_LegacyPrebuiltFragment(t *testing.T) {
181	t.Parallel()
182	result := android.GroupFixturePreparers(
183		prepareForTestWithPlatformBootclasspath,
184		java.FixtureConfigureApexBootJars("myapex:foo"),
185		java.PrepareForTestWithJavaSdkLibraryFiles,
186	).RunTestWithBp(t, `
187		prebuilt_apex {
188			name: "myapex",
189			src: "myapex.apex",
190			exported_bootclasspath_fragments: ["mybootclasspath-fragment"],
191		}
192
193		// A prebuilt java_sdk_library_import that is not preferred by default but will be preferred
194		// because AlwaysUsePrebuiltSdks() is true.
195		java_sdk_library_import {
196			name: "foo",
197			prefer: false,
198			shared_library: false,
199			permitted_packages: ["foo"],
200			public: {
201				jars: ["sdk_library/public/foo-stubs.jar"],
202				stub_srcs: ["sdk_library/public/foo_stub_sources"],
203				current_api: "sdk_library/public/foo.txt",
204				removed_api: "sdk_library/public/foo-removed.txt",
205				sdk_version: "current",
206			},
207			apex_available: ["myapex"],
208		}
209
210		prebuilt_bootclasspath_fragment {
211			name: "mybootclasspath-fragment",
212			apex_available: [
213				"myapex",
214			],
215			contents: [
216				"foo",
217			],
218			hidden_api: {
219				stub_flags: "prebuilt-stub-flags.csv",
220				annotation_flags: "prebuilt-annotation-flags.csv",
221				metadata: "prebuilt-metadata.csv",
222				index: "prebuilt-index.csv",
223				all_flags: "prebuilt-all-flags.csv",
224			},
225		}
226
227		platform_bootclasspath {
228			name: "myplatform-bootclasspath",
229			fragments: [
230				{
231					apex: "myapex",
232					module:"mybootclasspath-fragment",
233				},
234			],
235		}
236`,
237	)
238
239	pbcp := result.Module("myplatform-bootclasspath", "android_common")
240	info, _ := android.OtherModuleProvider(result, pbcp, java.MonolithicHiddenAPIInfoProvider)
241
242	android.AssertArrayString(t, "stub flags", []string{"prebuilt-stub-flags.csv:out/soong/.intermediates/mybootclasspath-fragment/android_common_prebuilt_myapex/modular-hiddenapi/signature-patterns.csv"}, info.StubFlagSubsets.RelativeToTop())
243	android.AssertArrayString(t, "all flags", []string{"prebuilt-all-flags.csv:out/soong/.intermediates/mybootclasspath-fragment/android_common_prebuilt_myapex/modular-hiddenapi/signature-patterns.csv"}, info.FlagSubsets.RelativeToTop())
244}
245
246func TestPlatformBootclasspathDependencies(t *testing.T) {
247	t.Parallel()
248	result := android.GroupFixturePreparers(
249		prepareForTestWithPlatformBootclasspath,
250		prepareForTestWithArtApex,
251		prepareForTestWithMyapex,
252		// Configure some libraries in the art and framework boot images.
253		java.FixtureConfigureBootJars("com.android.art:baz", "com.android.art:quuz", "platform:foo"),
254		java.FixtureConfigureApexBootJars("myapex:bar"),
255		java.PrepareForTestWithJavaSdkLibraryFiles,
256		java.FixtureWithLastReleaseApis("foo"),
257		java.PrepareForTestWithDexpreopt,
258		dexpreopt.FixtureDisableDexpreoptBootImages(false),
259		android.PrepareForTestWithBuildFlag("RELEASE_HIDDEN_API_EXPORTABLE_STUBS", "true"),
260	).RunTestWithBp(t, `
261		apex {
262			name: "com.android.art",
263			key: "com.android.art.key",
264 			bootclasspath_fragments: [
265				"art-bootclasspath-fragment",
266			],
267			updatable: false,
268		}
269
270		apex_key {
271			name: "com.android.art.key",
272			public_key: "com.android.art.avbpubkey",
273			private_key: "com.android.art.pem",
274		}
275
276		bootclasspath_fragment {
277			name: "art-bootclasspath-fragment",
278			image_name: "art",
279			apex_available: [
280				"com.android.art",
281			],
282			contents: [
283				"baz",
284				"quuz",
285			],
286			hidden_api: {
287				split_packages: ["*"],
288			},
289		}
290
291		java_library {
292			name: "baz",
293			apex_available: [
294				"com.android.art",
295			],
296			srcs: ["b.java"],
297			installable: true,
298			sdk_version: "core_current",
299		}
300
301		// Add a java_import that is not preferred and so won't have an appropriate apex variant created
302		// for it to make sure that the platform_bootclasspath doesn't try and add a dependency onto it.
303		java_import {
304			name: "baz",
305			apex_available: [
306				"com.android.art",
307			],
308			jars: ["b.jar"],
309		}
310
311		java_library {
312			name: "quuz",
313			apex_available: [
314				"com.android.art",
315			],
316			srcs: ["b.java"],
317			installable: true,
318		}
319
320		apex {
321			name: "myapex",
322			key: "myapex.key",
323			bootclasspath_fragments: [
324				"my-bootclasspath-fragment",
325			],
326			updatable: false,
327		}
328
329		bootclasspath_fragment {
330			name: "my-bootclasspath-fragment",
331			contents: ["bar"],
332			apex_available: ["myapex"],
333			hidden_api: {
334				split_packages: ["*"],
335			},
336		}
337
338		apex_key {
339			name: "myapex.key",
340			public_key: "testkey.avbpubkey",
341			private_key: "testkey.pem",
342		}
343
344		java_sdk_library {
345			name: "foo",
346			srcs: ["b.java"],
347		}
348
349		java_library {
350			name: "bar",
351			srcs: ["b.java"],
352			installable: true,
353			apex_available: ["myapex"],
354			permitted_packages: ["bar"],
355		}
356
357		platform_bootclasspath {
358			name: "myplatform-bootclasspath",
359
360			fragments: [
361				{
362					apex: "com.android.art",
363					module: "art-bootclasspath-fragment",
364				},
365				{
366					apex: "myapex",
367					module: "my-bootclasspath-fragment",
368				},
369			],
370		}
371`,
372	)
373
374	java.CheckPlatformBootclasspathModules(t, result, "myplatform-bootclasspath", []string{
375		// The configured contents of BootJars.
376		"com.android.art:baz",
377		"com.android.art:quuz",
378		"platform:foo",
379
380		// The configured contents of ApexBootJars.
381		"myapex:bar",
382	})
383
384	java.CheckPlatformBootclasspathFragments(t, result, "myplatform-bootclasspath", []string{
385		"com.android.art:art-bootclasspath-fragment",
386		"myapex:my-bootclasspath-fragment",
387	})
388
389	// Make sure that the myplatform-bootclasspath has the correct dependencies.
390	java.CheckPlatformBootclasspathDependencies(t, result.TestContext, "myplatform-bootclasspath", "android_common", []string{
391		// source vs prebuilt selection metadata module
392		`platform:all_apex_contributions`,
393
394		// The following are stubs.
395		`platform:android_stubs_current_exportable`,
396		`platform:android_system_stubs_current_exportable`,
397		`platform:android_test_stubs_current_exportable`,
398		`platform:legacy.core.platform.api.stubs.exportable`,
399
400		// Needed for generating the boot image.
401		`platform:dex2oatd`,
402
403		// The configured contents of BootJars, via their apexes if necessary.
404		`platform:com.android.art`,
405		`platform:com.android.art`,
406		`platform:foo`,
407
408		// The configured contents of ApexBootJars, via their apex.
409		`platform:myapex`,
410
411		// The fragments via their apexes.
412		`platform:com.android.art`,
413		`platform:myapex`,
414
415		// Impl lib of sdk_library for transitive srcjar generation
416		`platform:foo.impl`,
417	})
418}
419
420// TestPlatformBootclasspath_AlwaysUsePrebuiltSdks verifies that the build does not fail when
421// AlwaysUsePrebuiltSdk() returns true.
422func TestPlatformBootclasspath_AlwaysUsePrebuiltSdks(t *testing.T) {
423	t.Parallel()
424	result := android.GroupFixturePreparers(
425		prepareForTestWithPlatformBootclasspath,
426		prepareForTestWithMyapex,
427		// Configure two libraries, the first is a java_sdk_library whose prebuilt will be used because
428		// of AlwaysUsePrebuiltsSdk(). The second is a normal library that is unaffected. The order
429		// matters, so that the dependencies resolved by the platform_bootclasspath matches the
430		// configured list.
431		java.FixtureConfigureApexBootJars("myapex:foo"),
432		java.PrepareForTestWithJavaSdkLibraryFiles,
433		android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
434			variables.Always_use_prebuilt_sdks = proptools.BoolPtr(true)
435		}),
436		android.PrepareForTestWithBuildFlag("RELEASE_HIDDEN_API_EXPORTABLE_STUBS", "true"),
437
438		java.FixtureWithPrebuiltApis(map[string][]string{
439			"current": {},
440			"30":      {"foo"},
441		}),
442	).RunTestWithBp(t, `
443		apex {
444			name: "myapex",
445			key: "myapex.key",
446			bootclasspath_fragments: [
447				"mybootclasspath-fragment",
448			],
449			updatable: false,
450		}
451
452		apex_key {
453			name: "myapex.key",
454			public_key: "testkey.avbpubkey",
455			private_key: "testkey.pem",
456		}
457
458		java_library {
459			name: "bar",
460			srcs: ["b.java"],
461			installable: true,
462			apex_available: ["myapex"],
463			permitted_packages: ["bar"],
464		}
465
466		java_sdk_library {
467			name: "foo",
468			srcs: ["b.java"],
469			shared_library: false,
470			public: {
471				enabled: true,
472			},
473			apex_available: ["myapex"],
474			permitted_packages: ["foo"],
475		}
476
477		prebuilt_apex {
478			name: "myapex",
479			src: "myapex.apex",
480			exported_bootclasspath_fragments: ["mybootclasspath-fragment"],
481			prefer: true,
482		}
483
484		// A prebuilt java_sdk_library_import that is not preferred by default but will be preferred
485		// because AlwaysUsePrebuiltSdks() is true.
486		java_sdk_library_import {
487			name: "foo",
488			prefer: false,
489			shared_library: false,
490			permitted_packages: ["foo"],
491			public: {
492				jars: ["sdk_library/public/foo-stubs.jar"],
493				stub_srcs: ["sdk_library/public/foo_stub_sources"],
494				current_api: "sdk_library/public/foo.txt",
495				removed_api: "sdk_library/public/foo-removed.txt",
496				sdk_version: "current",
497			},
498			apex_available: ["myapex"],
499		}
500
501		// This always depends on the source foo module, its dependencies are not affected by the
502		// AlwaysUsePrebuiltSdks().
503		bootclasspath_fragment {
504			name: "mybootclasspath-fragment",
505			apex_available: [
506				"myapex",
507			],
508			contents: [
509				"foo", "bar",
510			],
511			hidden_api: {
512				split_packages: ["*"],
513			},
514		}
515
516		prebuilt_bootclasspath_fragment {
517			name: "mybootclasspath-fragment",
518			apex_available: [
519				"myapex",
520			],
521			contents: [
522				"foo",
523			],
524			hidden_api: {
525				stub_flags: "",
526				annotation_flags: "",
527				metadata: "",
528				index: "",
529				all_flags: "",
530			},
531		}
532
533		platform_bootclasspath {
534			name: "myplatform-bootclasspath",
535			fragments: [
536				{
537					apex: "myapex",
538					module:"mybootclasspath-fragment",
539				},
540			],
541		}
542`,
543	)
544
545	java.CheckPlatformBootclasspathModules(t, result, "myplatform-bootclasspath", []string{
546		// The configured contents of BootJars.
547		"prebuilt_myapex:prebuilt_foo",
548	})
549
550	// Make sure that the myplatform-bootclasspath has the correct dependencies.
551	java.CheckPlatformBootclasspathDependencies(t, result.TestContext, "myplatform-bootclasspath", "android_common", []string{
552		// source vs prebuilt selection metadata module
553		`platform:all_apex_contributions`,
554
555		// The following are stubs.
556		"platform:prebuilt_sdk_public_current_android",
557		"platform:prebuilt_sdk_system_current_android",
558		"platform:prebuilt_sdk_test_current_android",
559
560		// Not a prebuilt as no prebuilt existed when it was added.
561		"platform:legacy.core.platform.api.stubs.exportable",
562
563		// The prebuilt library via the apex.
564		"platform:prebuilt_myapex",
565
566		// The fragments via the apex.
567		"platform:prebuilt_myapex",
568
569		// Impl lib of sdk_library for transitive srcjar generation
570		"platform:foo.impl",
571	})
572}
573
574// TestPlatformBootclasspath_IncludesRemainingApexJars verifies that any apex boot jar is present in
575// platform_bootclasspath's classpaths.proto config, if the apex does not generate its own config
576// by setting generate_classpaths_proto property to false.
577func TestPlatformBootclasspath_IncludesRemainingApexJars(t *testing.T) {
578	t.Parallel()
579	result := android.GroupFixturePreparers(
580		prepareForTestWithPlatformBootclasspath,
581		prepareForTestWithMyapex,
582		java.FixtureConfigureApexBootJars("myapex:foo"),
583		android.FixtureWithRootAndroidBp(`
584			platform_bootclasspath {
585				name: "platform-bootclasspath",
586				fragments: [
587					{
588						apex: "myapex",
589						module:"foo-fragment",
590					},
591				],
592			}
593
594			apex {
595				name: "myapex",
596				key: "myapex.key",
597				bootclasspath_fragments: ["foo-fragment"],
598				updatable: false,
599			}
600
601			apex_key {
602				name: "myapex.key",
603				public_key: "testkey.avbpubkey",
604				private_key: "testkey.pem",
605			}
606
607			bootclasspath_fragment {
608				name: "foo-fragment",
609				generate_classpaths_proto: false,
610				contents: ["foo"],
611				apex_available: ["myapex"],
612				hidden_api: {
613					split_packages: ["*"],
614				},
615			}
616
617			java_library {
618				name: "foo",
619				srcs: ["a.java"],
620				system_modules: "none",
621				sdk_version: "none",
622				compile_dex: true,
623				apex_available: ["myapex"],
624				permitted_packages: ["foo"],
625			}
626		`),
627	).RunTest(t)
628
629	java.CheckClasspathFragmentProtoContentInfoProvider(t, result,
630		true,         // proto should be generated
631		"myapex:foo", // apex doesn't generate its own config, so must be in platform_bootclasspath
632		"bootclasspath.pb",
633		"out/target/product/test_device/system/etc/classpaths",
634	)
635}
636
637func TestBootJarNotInApex(t *testing.T) {
638	t.Parallel()
639	android.GroupFixturePreparers(
640		prepareForTestWithPlatformBootclasspath,
641		PrepareForTestWithApexBuildComponents,
642		prepareForTestWithMyapex,
643		java.FixtureConfigureApexBootJars("myapex:foo"),
644	).ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(
645		`module "myplatform-bootclasspath" variant ".*": failed to find module "foo" in apex "myapex"`)).
646		RunTestWithBp(t, `
647			apex {
648				name: "myapex",
649				key: "myapex.key",
650				updatable: false,
651			}
652
653			apex_key {
654				name: "myapex.key",
655				public_key: "testkey.avbpubkey",
656				private_key: "testkey.pem",
657			}
658
659			java_library {
660				name: "foo",
661				srcs: ["b.java"],
662				installable: true,
663				apex_available: [
664					"myapex",
665				],
666			}
667
668			bootclasspath_fragment {
669				name: "not-in-apex-fragment",
670				contents: [
671					"foo",
672				],
673				hidden_api: {
674					split_packages: ["*"],
675				},
676			}
677
678			platform_bootclasspath {
679				name: "myplatform-bootclasspath",
680			}
681		`)
682}
683
684func TestBootFragmentNotInApex(t *testing.T) {
685	t.Parallel()
686	android.GroupFixturePreparers(
687		prepareForTestWithPlatformBootclasspath,
688		PrepareForTestWithApexBuildComponents,
689		prepareForTestWithMyapex,
690		java.FixtureConfigureApexBootJars("myapex:foo"),
691	).ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(
692		`library foo.*have no corresponding fragment.*`)).RunTestWithBp(t, `
693			apex {
694				name: "myapex",
695				key: "myapex.key",
696				java_libs: ["foo"],
697				updatable: false,
698			}
699
700			apex_key {
701				name: "myapex.key",
702				public_key: "testkey.avbpubkey",
703				private_key: "testkey.pem",
704			}
705
706			java_library {
707				name: "foo",
708				srcs: ["b.java"],
709				installable: true,
710				apex_available: ["myapex"],
711				permitted_packages: ["foo"],
712			}
713
714			bootclasspath_fragment {
715				name: "not-in-apex-fragment",
716				contents: ["foo"],
717				hidden_api: {
718					split_packages: ["*"],
719				},
720			}
721
722			platform_bootclasspath {
723				name: "myplatform-bootclasspath",
724			}
725		`)
726}
727
728func TestNonBootJarInFragment(t *testing.T) {
729	t.Parallel()
730	android.GroupFixturePreparers(
731		prepareForTestWithPlatformBootclasspath,
732		PrepareForTestWithApexBuildComponents,
733		prepareForTestWithMyapex,
734		java.FixtureConfigureApexBootJars("myapex:foo"),
735	).ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(
736		`in contents must also be declared in PRODUCT_APEX_BOOT_JARS`)).
737		RunTestWithBp(t, `
738			apex {
739				name: "myapex",
740				key: "myapex.key",
741				bootclasspath_fragments: ["apex-fragment"],
742				updatable: false,
743			}
744
745			apex_key {
746				name: "myapex.key",
747				public_key: "testkey.avbpubkey",
748				private_key: "testkey.pem",
749			}
750
751			java_library {
752				name: "foo",
753				srcs: ["b.java"],
754				installable: true,
755				apex_available: ["myapex"],
756				permitted_packages: ["foo"],
757			}
758
759			java_library {
760				name: "bar",
761				srcs: ["b.java"],
762				installable: true,
763				apex_available: ["myapex"],
764				permitted_packages: ["bar"],
765			}
766
767			bootclasspath_fragment {
768				name: "apex-fragment",
769				contents: ["foo", "bar"],
770				apex_available:[ "myapex" ],
771				hidden_api: {
772					split_packages: ["*"],
773				},
774			}
775
776			platform_bootclasspath {
777				name: "myplatform-bootclasspath",
778				fragments: [{
779						apex: "myapex",
780						module:"apex-fragment",
781				}],
782			}
783		`)
784}
785
786// Skip bcp_fragment content validation of source apexes if prebuilts are active.
787func TestNonBootJarInPrebuilts(t *testing.T) {
788	t.Parallel()
789	testCases := []struct {
790		description               string
791		selectedApexContributions string
792		expectedError             string
793	}{
794		{
795			description:               "source is active",
796			selectedApexContributions: "",
797			expectedError:             "in contents must also be declared in PRODUCT_APEX_BOOT_JARS",
798		},
799		{
800			description:               "prebuilts are active",
801			selectedApexContributions: "myapex.prebuilt.contributions",
802			expectedError:             "", // skip content validation of source bcp fragment
803		},
804	}
805	bp := `
806// Source
807apex {
808	name: "myapex",
809	key: "myapex.key",
810	bootclasspath_fragments: ["apex-fragment"],
811	updatable: false,
812	min_sdk_version: "29",
813}
814
815override_apex {
816	name: "myapex.override", // overrides the min_sdk_version, thereby creating different variants of its transitive deps
817	base: "myapex",
818	min_sdk_version: "34",
819}
820
821apex_key {
822	name: "myapex.key",
823	public_key: "testkey.avbpubkey",
824	private_key: "testkey.pem",
825}
826
827java_library {
828	name: "foo",
829	srcs: ["b.java"],
830	installable: true,
831	apex_available: ["myapex"],
832	permitted_packages: ["foo"],
833	min_sdk_version: "29",
834}
835
836java_library {
837	name: "bar",
838	srcs: ["b.java"],
839	installable: true,
840	apex_available: ["myapex"],
841	permitted_packages: ["bar"],
842	min_sdk_version: "29",
843}
844
845bootclasspath_fragment {
846	name: "apex-fragment",
847	contents: ["foo", "bar"],
848	apex_available:[ "myapex" ],
849	hidden_api: {
850		split_packages: ["*"],
851	},
852}
853
854platform_bootclasspath {
855	name: "myplatform-bootclasspath",
856	fragments: [{
857			apex: "myapex",
858			module:"apex-fragment",
859	}],
860}
861
862// prebuilts
863prebuilt_apex {
864	name: "myapex",
865		apex_name: "myapex",
866		src: "myapex.apex",
867		exported_bootclasspath_fragments: ["apex-fragment"],
868	}
869
870	prebuilt_bootclasspath_fragment {
871		name: "apex-fragment",
872		contents: ["foo"],
873		hidden_api: {
874			annotation_flags: "my-bootclasspath-fragment/annotation-flags.csv",
875			metadata: "my-bootclasspath-fragment/metadata.csv",
876			index: "my-bootclasspath-fragment/index.csv",
877			stub_flags: "my-bootclasspath-fragment/stub-flags.csv",
878			all_flags: "my-bootclasspath-fragment/all-flags.csv",
879		},
880	}
881	java_import {
882		name: "foo",
883		jars: ["foo.jar"],
884	}
885
886apex_contributions {
887	name: "myapex.prebuilt.contributions",
888	api_domain: "myapex",
889	contents: ["prebuilt_myapex"],
890}
891`
892
893	for _, tc := range testCases {
894		fixture := android.GroupFixturePreparers(
895			prepareForTestWithPlatformBootclasspath,
896			PrepareForTestWithApexBuildComponents,
897			prepareForTestWithMyapex,
898			java.FixtureConfigureApexBootJars("myapex:foo"),
899			android.PrepareForTestWithBuildFlag("RELEASE_APEX_CONTRIBUTIONS_ADSERVICES", tc.selectedApexContributions),
900		)
901		if tc.expectedError != "" {
902			fixture = fixture.ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(tc.expectedError))
903		}
904		fixture.RunTestWithBp(t, bp)
905	}
906
907}
908
909// Source and prebuilt apex provide different set of boot jars
910func TestNonBootJarMissingInPrebuiltFragment(t *testing.T) {
911	t.Parallel()
912	bp := `
913		apex {
914			name: "myapex",
915			key: "myapex.key",
916			bootclasspath_fragments: ["apex-fragment"],
917			updatable: false,
918		}
919
920		apex_key {
921			name: "myapex.key",
922			public_key: "testkey.avbpubkey",
923			private_key: "testkey.pem",
924		}
925
926		java_library {
927			name: "foo",
928			srcs: ["b.java"],
929			installable: true,
930			apex_available: ["myapex"],
931			permitted_packages: ["foo"],
932		}
933
934		java_library {
935			name: "bar",
936			srcs: ["b.java"],
937			installable: true,
938			apex_available: ["myapex"],
939			permitted_packages: ["bar"],
940		}
941
942		bootclasspath_fragment {
943			name: "apex-fragment",
944			contents: ["foo", "bar"],
945			apex_available:[ "myapex" ],
946			hidden_api: {
947				split_packages: ["*"],
948			},
949		}
950
951		prebuilt_apex {
952			name: "com.google.android.myapex", // mainline prebuilt selection logic in soong relies on the naming convention com.google.android
953			apex_name: "myapex",
954			source_apex_name: "myapex",
955			src: "myapex.apex",
956			exported_bootclasspath_fragments: ["apex-fragment"],
957		}
958
959		java_import {
960			name: "foo",
961			jars: ["foo.jar"],
962			apex_available: ["myapex"],
963			permitted_packages: ["foo"],
964		}
965
966		prebuilt_bootclasspath_fragment {
967			name: "apex-fragment",
968			contents: ["foo"], // Unlike the source fragment, this is missing bar
969			apex_available:[ "myapex" ],
970			hidden_api: {
971				annotation_flags: "my-bootclasspath-fragment/annotation-flags.csv",
972				metadata: "my-bootclasspath-fragment/metadata.csv",
973				index: "my-bootclasspath-fragment/index.csv",
974				stub_flags: "my-bootclasspath-fragment/stub-flags.csv",
975				all_flags: "my-bootclasspath-fragment/all-flags.csv",
976			},
977		}
978
979		// Another prebuilt apex, but this is not selected during the build.
980		prebuilt_apex {
981			name: "com.google.android.myapex.v2", // mainline prebuilt selection logic in soong relies on the naming convention com.google.android
982			apex_name: "myapex",
983			source_apex_name: "myapex",
984			src: "myapex.apex",
985			exported_bootclasspath_fragments: ["apex-fragment.v2"],
986		}
987
988		java_import {
989			name: "bar",
990			jars: ["bar.jar"],
991			apex_available: ["myapex"],
992			permitted_packages: ["bar"],
993		}
994
995		prebuilt_bootclasspath_fragment {
996			name: "apex-fragment.v2",
997			contents: ["bar"], // Unlike the source fragment, this is missing foo
998			apex_available:[ "myapex" ],
999			hidden_api: {
1000				annotation_flags: "my-bootclasspath-fragment/annotation-flags.csv",
1001				metadata: "my-bootclasspath-fragment/metadata.csv",
1002				index: "my-bootclasspath-fragment/index.csv",
1003				stub_flags: "my-bootclasspath-fragment/stub-flags.csv",
1004				all_flags: "my-bootclasspath-fragment/all-flags.csv",
1005			},
1006		}
1007
1008
1009		apex_contributions {
1010			name: "my_apex_contributions",
1011			api_domain: "myapex",
1012			contents: [%v],
1013		}
1014	`
1015	testCases := []struct {
1016		desc                     string
1017		configuredBootJars       []string
1018		apexContributionContents string
1019		errorExpected            bool
1020	}{
1021		{
1022			desc:               "Source apex is selected, and APEX_BOOT_JARS is correctly configured for source apex builds",
1023			configuredBootJars: []string{"myapex:foo", "myapex:bar"},
1024		},
1025		{
1026			desc:               "Source apex is selected, and APEX_BOOT_JARS is missing bar",
1027			configuredBootJars: []string{"myapex:foo"},
1028			errorExpected:      true,
1029		},
1030		{
1031			desc:                     "Prebuilt apex is selected, and APEX_BOOT_JARS is correctly configured for prebuilt apex build",
1032			configuredBootJars:       []string{"myapex:foo"},
1033			apexContributionContents: `"prebuilt_com.google.android.myapex"`,
1034		},
1035		{
1036			desc:                     "Prebuilt apex is selected, and APEX_BOOT_JARS is missing foo",
1037			configuredBootJars:       []string{"myapex:bar"},
1038			apexContributionContents: `"prebuilt_com.google.android.myapex"`,
1039			errorExpected:            true,
1040		},
1041	}
1042
1043	for _, tc := range testCases {
1044		fixture := android.GroupFixturePreparers(
1045			prepareForTestWithPlatformBootclasspath,
1046			PrepareForTestWithApexBuildComponents,
1047			prepareForTestWithMyapex,
1048			java.FixtureConfigureApexBootJars(tc.configuredBootJars...),
1049			android.PrepareForTestWithBuildFlag("RELEASE_APEX_CONTRIBUTIONS_ART", "my_apex_contributions"),
1050		)
1051		if tc.errorExpected {
1052			fixture = fixture.ExtendWithErrorHandler(
1053				android.FixtureExpectsAtLeastOneErrorMatchingPattern(`in contents.*must also be declared in PRODUCT_APEX_BOOT_JARS`),
1054			)
1055		}
1056		fixture.RunTestWithBp(t, fmt.Sprintf(bp, tc.apexContributionContents))
1057	}
1058}
1059