• 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	"path"
20	"sort"
21	"strings"
22	"testing"
23
24	"android/soong/android"
25	"android/soong/dexpreopt"
26	"android/soong/java"
27
28	"github.com/google/blueprint/proptools"
29)
30
31// Contains tests for bootclasspath_fragment logic from java/bootclasspath_fragment.go as the ART
32// bootclasspath_fragment requires modules from the ART apex.
33
34var prepareForTestWithBootclasspathFragment = android.GroupFixturePreparers(
35	java.PrepareForTestWithDexpreopt,
36	PrepareForTestWithApexBuildComponents,
37)
38
39// Some additional files needed for the art apex.
40var prepareForTestWithArtApex = android.GroupFixturePreparers(
41	android.FixtureMergeMockFs(android.MockFS{
42		"com.android.art.avbpubkey":                          nil,
43		"com.android.art.pem":                                nil,
44		"system/sepolicy/apex/com.android.art-file_contexts": nil,
45	}),
46	dexpreopt.FixtureSetBootImageProfiles("art/build/boot/boot-image-profile.txt"),
47)
48
49func TestBootclasspathFragments(t *testing.T) {
50	result := android.GroupFixturePreparers(
51		prepareForTestWithBootclasspathFragment,
52		// Configure some libraries in the art bootclasspath_fragment and platform_bootclasspath.
53		java.FixtureConfigureBootJars("com.android.art:baz", "com.android.art:quuz", "platform:foo", "platform:bar"),
54		prepareForTestWithArtApex,
55
56		java.PrepareForTestWithJavaSdkLibraryFiles,
57		java.FixtureWithLastReleaseApis("foo"),
58	).RunTestWithBp(t, `
59		java_sdk_library {
60			name: "foo",
61			srcs: ["b.java"],
62		}
63
64		java_library {
65			name: "bar",
66			srcs: ["b.java"],
67			installable: true,
68		}
69
70		apex {
71			name: "com.android.art",
72			key: "com.android.art.key",
73			bootclasspath_fragments: ["art-bootclasspath-fragment"],
74			updatable: false,
75		}
76
77		apex_key {
78			name: "com.android.art.key",
79			public_key: "com.android.art.avbpubkey",
80			private_key: "com.android.art.pem",
81		}
82
83		java_library {
84			name: "baz",
85			apex_available: [
86				"com.android.art",
87			],
88			srcs: ["b.java"],
89			compile_dex: true,
90		}
91
92		java_library {
93			name: "quuz",
94			apex_available: [
95				"com.android.art",
96			],
97			srcs: ["b.java"],
98			compile_dex: true,
99		}
100
101		bootclasspath_fragment {
102			name: "art-bootclasspath-fragment",
103			image_name: "art",
104			// Must match the "com.android.art:" entries passed to FixtureConfigureBootJars above.
105			contents: ["baz", "quuz"],
106			apex_available: [
107				"com.android.art",
108			],
109			hidden_api: {
110				split_packages: ["*"],
111			},
112		}
113`,
114	)
115
116	// Make sure that the art-bootclasspath-fragment is using the correct configuration.
117	checkBootclasspathFragment(t, result, "art-bootclasspath-fragment", "android_common_apex10000",
118		"com.android.art:baz,com.android.art:quuz")
119}
120
121func TestBootclasspathFragments_FragmentDependency(t *testing.T) {
122	result := android.GroupFixturePreparers(
123		prepareForTestWithBootclasspathFragment,
124		// Configure some libraries in the art bootclasspath_fragment and platform_bootclasspath.
125		java.FixtureConfigureBootJars("com.android.art:baz", "com.android.art:quuz"),
126		java.FixtureConfigureApexBootJars("someapex:foo", "someapex:bar"),
127		prepareForTestWithArtApex,
128
129		java.PrepareForTestWithJavaSdkLibraryFiles,
130		java.FixtureWithLastReleaseApis("foo", "baz"),
131	).RunTestWithBp(t, `
132		java_sdk_library {
133			name: "foo",
134			srcs: ["b.java"],
135			shared_library: false,
136			public: {
137				enabled: true,
138			},
139			system: {
140				enabled: true,
141			},
142		}
143
144		java_library {
145			name: "bar",
146			srcs: ["b.java"],
147			installable: true,
148		}
149
150		apex {
151			name: "com.android.art",
152			key: "com.android.art.key",
153			bootclasspath_fragments: ["art-bootclasspath-fragment"],
154			updatable: false,
155		}
156
157		apex_key {
158			name: "com.android.art.key",
159			public_key: "com.android.art.avbpubkey",
160			private_key: "com.android.art.pem",
161		}
162
163		java_sdk_library {
164			name: "baz",
165			apex_available: [
166				"com.android.art",
167			],
168			srcs: ["b.java"],
169			shared_library: false,
170			public: {
171				enabled: true,
172			},
173			system: {
174				enabled: true,
175			},
176			test: {
177				enabled: true,
178			},
179		}
180
181		java_library {
182			name: "quuz",
183			apex_available: [
184				"com.android.art",
185			],
186			srcs: ["b.java"],
187			compile_dex: true,
188		}
189
190		bootclasspath_fragment {
191			name: "art-bootclasspath-fragment",
192			image_name: "art",
193			// Must match the "com.android.art:" entries passed to FixtureConfigureBootJars above.
194			contents: ["baz", "quuz"],
195			apex_available: [
196				"com.android.art",
197			],
198			hidden_api: {
199				split_packages: ["*"],
200			},
201		}
202
203		bootclasspath_fragment {
204			name: "other-bootclasspath-fragment",
205			contents: ["foo", "bar"],
206			fragments: [
207					{
208							apex: "com.android.art",
209							module: "art-bootclasspath-fragment",
210					},
211			],
212			hidden_api: {
213				split_packages: ["*"],
214			},
215		}
216`,
217	)
218
219	checkAPIScopeStubs := func(message string, info java.HiddenAPIInfo, apiScope *java.HiddenAPIScope, expectedPaths ...string) {
220		t.Helper()
221		paths := info.TransitiveStubDexJarsByScope.StubDexJarsForScope(apiScope)
222		android.AssertPathsRelativeToTopEquals(t, fmt.Sprintf("%s %s", message, apiScope), expectedPaths, paths)
223	}
224
225	// Check stub dex paths exported by art.
226	artFragment := result.Module("art-bootclasspath-fragment", "android_common")
227	artInfo := result.ModuleProvider(artFragment, java.HiddenAPIInfoProvider).(java.HiddenAPIInfo)
228
229	bazPublicStubs := "out/soong/.intermediates/baz.stubs/android_common/dex/baz.stubs.jar"
230	bazSystemStubs := "out/soong/.intermediates/baz.stubs.system/android_common/dex/baz.stubs.system.jar"
231	bazTestStubs := "out/soong/.intermediates/baz.stubs.test/android_common/dex/baz.stubs.test.jar"
232
233	checkAPIScopeStubs("art", artInfo, java.PublicHiddenAPIScope, bazPublicStubs)
234	checkAPIScopeStubs("art", artInfo, java.SystemHiddenAPIScope, bazSystemStubs)
235	checkAPIScopeStubs("art", artInfo, java.TestHiddenAPIScope, bazTestStubs)
236	checkAPIScopeStubs("art", artInfo, java.CorePlatformHiddenAPIScope)
237
238	// Check stub dex paths exported by other.
239	otherFragment := result.Module("other-bootclasspath-fragment", "android_common")
240	otherInfo := result.ModuleProvider(otherFragment, java.HiddenAPIInfoProvider).(java.HiddenAPIInfo)
241
242	fooPublicStubs := "out/soong/.intermediates/foo.stubs/android_common/dex/foo.stubs.jar"
243	fooSystemStubs := "out/soong/.intermediates/foo.stubs.system/android_common/dex/foo.stubs.system.jar"
244
245	checkAPIScopeStubs("other", otherInfo, java.PublicHiddenAPIScope, bazPublicStubs, fooPublicStubs)
246	checkAPIScopeStubs("other", otherInfo, java.SystemHiddenAPIScope, bazSystemStubs, fooSystemStubs)
247	checkAPIScopeStubs("other", otherInfo, java.TestHiddenAPIScope, bazTestStubs, fooSystemStubs)
248	checkAPIScopeStubs("other", otherInfo, java.CorePlatformHiddenAPIScope)
249}
250
251func checkBootclasspathFragment(t *testing.T, result *android.TestResult, moduleName, variantName string, expectedConfiguredModules string) {
252	t.Helper()
253
254	bootclasspathFragment := result.ModuleForTests(moduleName, variantName).Module().(*java.BootclasspathFragmentModule)
255
256	bootclasspathFragmentInfo := result.ModuleProvider(bootclasspathFragment, java.BootclasspathFragmentApexContentInfoProvider).(java.BootclasspathFragmentApexContentInfo)
257	modules := bootclasspathFragmentInfo.Modules()
258	android.AssertStringEquals(t, "invalid modules for "+moduleName, expectedConfiguredModules, modules.String())
259}
260
261func TestBootclasspathFragmentInArtApex(t *testing.T) {
262	commonPreparer := android.GroupFixturePreparers(
263		prepareForTestWithBootclasspathFragment,
264		prepareForTestWithArtApex,
265
266		android.FixtureWithRootAndroidBp(`
267		apex {
268			name: "com.android.art",
269			key: "com.android.art.key",
270			bootclasspath_fragments: [
271				"mybootclasspathfragment",
272			],
273			// bar (like foo) should be transitively included in this apex because it is part of the
274			// mybootclasspathfragment bootclasspath_fragment.
275			updatable: false,
276		}
277
278		apex_key {
279			name: "com.android.art.key",
280			public_key: "testkey.avbpubkey",
281			private_key: "testkey.pem",
282		}
283
284		java_library {
285			name: "foo",
286			srcs: ["b.java"],
287			installable: true,
288			apex_available: [
289				"com.android.art",
290			],
291		}
292
293		java_library {
294			name: "bar",
295			srcs: ["b.java"],
296			installable: true,
297			apex_available: [
298				"com.android.art",
299			],
300		}
301
302		java_import {
303			name: "foo",
304			jars: ["foo.jar"],
305			apex_available: [
306				"com.android.art",
307			],
308			compile_dex: true,
309		}
310
311		java_import {
312			name: "bar",
313			jars: ["bar.jar"],
314			apex_available: [
315				"com.android.art",
316			],
317			compile_dex: true,
318		}
319	`),
320	)
321
322	contentsInsert := func(contents []string) string {
323		insert := ""
324		if contents != nil {
325			insert = fmt.Sprintf(`contents: ["%s"],`, strings.Join(contents, `", "`))
326		}
327		return insert
328	}
329
330	addSource := func(contents ...string) android.FixturePreparer {
331		text := fmt.Sprintf(`
332			bootclasspath_fragment {
333				name: "mybootclasspathfragment",
334				image_name: "art",
335				%s
336				apex_available: [
337					"com.android.art",
338				],
339				hidden_api: {
340					split_packages: ["*"],
341				},
342			}
343		`, contentsInsert(contents))
344
345		return android.FixtureAddTextFile("art/build/boot/Android.bp", text)
346	}
347
348	addPrebuilt := func(prefer bool, contents ...string) android.FixturePreparer {
349		text := fmt.Sprintf(`
350			prebuilt_apex {
351				name: "com.android.art",
352				arch: {
353					arm64: {
354						src: "com.android.art-arm64.apex",
355					},
356					arm: {
357						src: "com.android.art-arm.apex",
358					},
359				},
360				exported_bootclasspath_fragments: ["mybootclasspathfragment"],
361			}
362
363			prebuilt_bootclasspath_fragment {
364				name: "mybootclasspathfragment",
365				image_name: "art",
366				%s
367				prefer: %t,
368				apex_available: [
369					"com.android.art",
370				],
371				hidden_api: {
372					annotation_flags: "mybootclasspathfragment/annotation-flags.csv",
373					metadata: "mybootclasspathfragment/metadata.csv",
374					index: "mybootclasspathfragment/index.csv",
375					stub_flags: "mybootclasspathfragment/stub-flags.csv",
376					all_flags: "mybootclasspathfragment/all-flags.csv",
377				},
378			}
379		`, contentsInsert(contents), prefer)
380		return android.FixtureAddTextFile("prebuilts/module_sdk/art/Android.bp", text)
381	}
382
383	t.Run("boot image files from source", func(t *testing.T) {
384		result := android.GroupFixturePreparers(
385			commonPreparer,
386
387			// Configure some libraries in the art bootclasspath_fragment that match the source
388			// bootclasspath_fragment's contents property.
389			java.FixtureConfigureBootJars("com.android.art:foo", "com.android.art:bar"),
390			addSource("foo", "bar"),
391			java.FixtureSetBootImageInstallDirOnDevice("art", "apex/com.android.art/javalib"),
392		).RunTest(t)
393
394		ensureExactContents(t, result.TestContext, "com.android.art", "android_common_com.android.art_image", []string{
395			"etc/boot-image.prof",
396			"etc/classpaths/bootclasspath.pb",
397			"javalib/bar.jar",
398			"javalib/foo.jar",
399		})
400
401		java.CheckModuleDependencies(t, result.TestContext, "com.android.art", "android_common_com.android.art_image", []string{
402			`com.android.art.key`,
403			`mybootclasspathfragment`,
404		})
405
406		// Make sure that the source bootclasspath_fragment copies its dex files to the predefined
407		// locations for the art image.
408		module := result.ModuleForTests("mybootclasspathfragment", "android_common_apex10000")
409		checkCopiesToPredefinedLocationForArt(t, result.Config, module, "bar", "foo")
410	})
411
412	t.Run("generate boot image profile even if dexpreopt is disabled", func(t *testing.T) {
413		result := android.GroupFixturePreparers(
414			commonPreparer,
415
416			// Configure some libraries in the art bootclasspath_fragment that match the source
417			// bootclasspath_fragment's contents property.
418			java.FixtureConfigureBootJars("com.android.art:foo", "com.android.art:bar"),
419			addSource("foo", "bar"),
420			java.FixtureSetBootImageInstallDirOnDevice("art", "system/framework"),
421			dexpreopt.FixtureDisableDexpreoptBootImages(true),
422		).RunTest(t)
423
424		ensureExactContents(t, result.TestContext, "com.android.art", "android_common_com.android.art_image", []string{
425			"etc/boot-image.prof",
426			"etc/classpaths/bootclasspath.pb",
427			"javalib/bar.jar",
428			"javalib/foo.jar",
429		})
430	})
431
432	t.Run("boot image disable generate profile", func(t *testing.T) {
433		result := android.GroupFixturePreparers(
434			commonPreparer,
435
436			// Configure some libraries in the art bootclasspath_fragment that match the source
437			// bootclasspath_fragment's contents property.
438			java.FixtureConfigureBootJars("com.android.art:foo", "com.android.art:bar"),
439			addSource("foo", "bar"),
440			dexpreopt.FixtureDisableGenerateProfile(true),
441		).RunTest(t)
442
443		files := getFiles(t, result.TestContext, "com.android.art", "android_common_com.android.art_image")
444		for _, file := range files {
445			matched, _ := path.Match("etc/boot-image.prof", file.path)
446			android.AssertBoolEquals(t, "\"etc/boot-image.prof\" should not be in the APEX", matched, false)
447		}
448	})
449
450	t.Run("boot image files with preferred prebuilt", func(t *testing.T) {
451		result := android.GroupFixturePreparers(
452			commonPreparer,
453
454			// Configure some libraries in the art bootclasspath_fragment that match the source
455			// bootclasspath_fragment's contents property.
456			java.FixtureConfigureBootJars("com.android.art:foo", "com.android.art:bar"),
457			addSource("foo", "bar"),
458
459			// Make sure that a preferred prebuilt with consistent contents doesn't affect the apex.
460			addPrebuilt(true, "foo", "bar"),
461
462			java.FixtureSetBootImageInstallDirOnDevice("art", "apex/com.android.art/javalib"),
463		).RunTest(t)
464
465		ensureExactDeapexedContents(t, result.TestContext, "com.android.art", "android_common", []string{
466			"etc/boot-image.prof",
467			"javalib/bar.jar",
468			"javalib/foo.jar",
469		})
470
471		java.CheckModuleDependencies(t, result.TestContext, "com.android.art", "android_common_com.android.art_image", []string{
472			`com.android.art.key`,
473			`mybootclasspathfragment`,
474			`prebuilt_com.android.art`,
475		})
476
477		// Make sure that the prebuilt bootclasspath_fragment copies its dex files to the predefined
478		// locations for the art image.
479		module := result.ModuleForTests("prebuilt_mybootclasspathfragment", "android_common_com.android.art")
480		checkCopiesToPredefinedLocationForArt(t, result.Config, module, "bar", "foo")
481	})
482
483	t.Run("source with inconsistency between config and contents", func(t *testing.T) {
484		android.GroupFixturePreparers(
485			commonPreparer,
486
487			// Create an inconsistency between the ArtApexJars configuration and the art source
488			// bootclasspath_fragment module's contents property.
489			java.FixtureConfigureBootJars("com.android.art:foo"),
490			addSource("foo", "bar"),
491		).
492			ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`\QArtApexJars configuration specifies []string{"foo"}, contents property specifies []string{"foo", "bar"}\E`)).
493			RunTest(t)
494	})
495
496	t.Run("prebuilt with inconsistency between config and contents", func(t *testing.T) {
497		android.GroupFixturePreparers(
498			commonPreparer,
499
500			// Create an inconsistency between the ArtApexJars configuration and the art
501			// prebuilt_bootclasspath_fragment module's contents property.
502			java.FixtureConfigureBootJars("com.android.art:foo"),
503			addPrebuilt(false, "foo", "bar"),
504		).
505			ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`\QArtApexJars configuration specifies []string{"foo"}, contents property specifies []string{"foo", "bar"}\E`)).
506			RunTest(t)
507	})
508
509	t.Run("preferred prebuilt with inconsistency between config and contents", func(t *testing.T) {
510		android.GroupFixturePreparers(
511			commonPreparer,
512
513			// Create an inconsistency between the ArtApexJars configuration and the art
514			// prebuilt_bootclasspath_fragment module's contents property.
515			java.FixtureConfigureBootJars("com.android.art:foo"),
516			addPrebuilt(true, "foo", "bar"),
517
518			// Source contents property is consistent with the config.
519			addSource("foo"),
520		).
521			ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`\QArtApexJars configuration specifies []string{"foo"}, contents property specifies []string{"foo", "bar"}\E`)).
522			RunTest(t)
523	})
524
525	t.Run("source preferred and prebuilt with inconsistency between config and contents", func(t *testing.T) {
526		android.GroupFixturePreparers(
527			commonPreparer,
528
529			// Create an inconsistency between the ArtApexJars configuration and the art
530			// prebuilt_bootclasspath_fragment module's contents property.
531			java.FixtureConfigureBootJars("com.android.art:foo"),
532			addPrebuilt(false, "foo", "bar"),
533
534			// Source contents property is consistent with the config.
535			addSource("foo"),
536
537			// This should pass because while the prebuilt is inconsistent with the configuration it is
538			// not actually used.
539		).RunTest(t)
540	})
541}
542
543func TestBootclasspathFragmentInPrebuiltArtApex(t *testing.T) {
544	preparers := android.GroupFixturePreparers(
545		prepareForTestWithBootclasspathFragment,
546		prepareForTestWithArtApex,
547
548		android.FixtureMergeMockFs(android.MockFS{
549			"com.android.art-arm64.apex": nil,
550			"com.android.art-arm.apex":   nil,
551		}),
552
553		// Configure some libraries in the art bootclasspath_fragment.
554		java.FixtureConfigureBootJars("com.android.art:foo", "com.android.art:bar"),
555		java.FixtureSetBootImageInstallDirOnDevice("art", "apex/com.android.art/javalib"),
556	)
557
558	bp := `
559		prebuilt_apex {
560			name: "com.android.art",
561			arch: {
562				arm64: {
563					src: "com.android.art-arm64.apex",
564				},
565				arm: {
566					src: "com.android.art-arm.apex",
567				},
568			},
569			exported_bootclasspath_fragments: ["mybootclasspathfragment"],
570		}
571
572		java_import {
573			name: "foo",
574			jars: ["foo.jar"],
575			apex_available: [
576				"com.android.art",
577			],
578		}
579
580		java_import {
581			name: "bar",
582			jars: ["bar.jar"],
583			apex_available: [
584				"com.android.art",
585			],
586		}
587
588		prebuilt_bootclasspath_fragment {
589			name: "mybootclasspathfragment",
590			image_name: "art",
591			// Must match the "com.android.art:" entries passed to FixtureConfigureBootJars above.
592			contents: ["foo", "bar"],
593			apex_available: [
594				"com.android.art",
595			],
596			hidden_api: {
597				annotation_flags: "mybootclasspathfragment/annotation-flags.csv",
598				metadata: "mybootclasspathfragment/metadata.csv",
599				index: "mybootclasspathfragment/index.csv",
600				stub_flags: "mybootclasspathfragment/stub-flags.csv",
601				all_flags: "mybootclasspathfragment/all-flags.csv",
602			},
603		}
604
605		// A prebuilt apex with the same apex_name that shouldn't interfere when it isn't enabled.
606		prebuilt_apex {
607			name: "com.mycompany.android.art",
608			apex_name: "com.android.art",
609			%s
610			src: "com.mycompany.android.art.apex",
611			exported_bootclasspath_fragments: ["mybootclasspathfragment"],
612		}
613	`
614
615	t.Run("disabled alternative APEX", func(t *testing.T) {
616		result := preparers.RunTestWithBp(t, fmt.Sprintf(bp, "enabled: false,"))
617
618		java.CheckModuleDependencies(t, result.TestContext, "com.android.art", "android_common_com.android.art", []string{
619			`com.android.art.apex.selector`,
620			`prebuilt_mybootclasspathfragment`,
621		})
622
623		java.CheckModuleDependencies(t, result.TestContext, "mybootclasspathfragment", "android_common_com.android.art", []string{
624			`com.android.art.deapexer`,
625			`dex2oatd`,
626			`prebuilt_bar`,
627			`prebuilt_foo`,
628		})
629
630		module := result.ModuleForTests("mybootclasspathfragment", "android_common_com.android.art")
631		checkCopiesToPredefinedLocationForArt(t, result.Config, module, "bar", "foo")
632	})
633
634	t.Run("enabled alternative APEX", func(t *testing.T) {
635		preparers.ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(
636			"Multiple installable prebuilt APEXes provide ambiguous deapexers: com.android.art and com.mycompany.android.art")).
637			RunTestWithBp(t, fmt.Sprintf(bp, ""))
638	})
639}
640
641// checkCopiesToPredefinedLocationForArt checks that the supplied modules are copied to the
642// predefined locations of boot dex jars used as inputs for the ART boot image.
643func checkCopiesToPredefinedLocationForArt(t *testing.T, config android.Config, module android.TestingModule, modules ...string) {
644	t.Helper()
645	bootJarLocations := []string{}
646	for _, output := range module.AllOutputs() {
647		output = android.StringRelativeToTop(config, output)
648		if strings.HasPrefix(output, "out/soong/dexpreopt_arm64/dex_artjars_input/") {
649			bootJarLocations = append(bootJarLocations, output)
650		}
651	}
652
653	sort.Strings(bootJarLocations)
654	expected := []string{}
655	for _, m := range modules {
656		expected = append(expected, fmt.Sprintf("out/soong/dexpreopt_arm64/dex_artjars_input/%s.jar", m))
657	}
658	sort.Strings(expected)
659
660	android.AssertArrayString(t, "copies to predefined locations for art", expected, bootJarLocations)
661}
662
663func TestBootclasspathFragmentContentsNoName(t *testing.T) {
664	result := android.GroupFixturePreparers(
665		prepareForTestWithBootclasspathFragment,
666		prepareForTestWithMyapex,
667		// Configure bootclasspath jars to ensure that hidden API encoding is performed on them.
668		java.FixtureConfigureApexBootJars("myapex:foo", "myapex:bar"),
669		// Make sure that the frameworks/base/Android.bp file exists as otherwise hidden API encoding
670		// is disabled.
671		android.FixtureAddTextFile("frameworks/base/Android.bp", ""),
672
673		java.PrepareForTestWithJavaSdkLibraryFiles,
674		java.FixtureWithLastReleaseApis("foo"),
675	).RunTestWithBp(t, `
676		apex {
677			name: "myapex",
678			key: "myapex.key",
679			bootclasspath_fragments: [
680				"mybootclasspathfragment",
681			],
682			updatable: false,
683		}
684
685		apex_key {
686			name: "myapex.key",
687			public_key: "testkey.avbpubkey",
688			private_key: "testkey.pem",
689		}
690
691		java_sdk_library {
692			name: "foo",
693			srcs: ["b.java"],
694			shared_library: false,
695			public: {enabled: true},
696			apex_available: [
697				"myapex",
698			],
699		}
700
701		java_library {
702			name: "bar",
703			srcs: ["b.java"],
704			installable: true,
705			apex_available: [
706				"myapex",
707			],
708		}
709
710		bootclasspath_fragment {
711			name: "mybootclasspathfragment",
712			contents: [
713				"foo",
714				"bar",
715			],
716			apex_available: [
717				"myapex",
718			],
719			hidden_api: {
720				split_packages: ["*"],
721			},
722		}
723	`)
724
725	ensureExactContents(t, result.TestContext, "myapex", "android_common_myapex_image", []string{
726		// This does not include art, oat or vdex files as they are only included for the art boot
727		// image.
728		"etc/classpaths/bootclasspath.pb",
729		"javalib/bar.jar",
730		"javalib/foo.jar",
731	})
732
733	java.CheckModuleDependencies(t, result.TestContext, "myapex", "android_common_myapex_image", []string{
734		`myapex.key`,
735		`mybootclasspathfragment`,
736	})
737
738	apex := result.ModuleForTests("myapex", "android_common_myapex_image")
739	apexRule := apex.Rule("apexRule")
740	copyCommands := apexRule.Args["copy_commands"]
741
742	// Make sure that the fragment provides the hidden API encoded dex jars to the APEX.
743	fragment := result.Module("mybootclasspathfragment", "android_common_apex10000")
744
745	info := result.ModuleProvider(fragment, java.BootclasspathFragmentApexContentInfoProvider).(java.BootclasspathFragmentApexContentInfo)
746
747	checkFragmentExportedDexJar := func(name string, expectedDexJar string) {
748		module := result.Module(name, "android_common_apex10000")
749		dexJar, err := info.DexBootJarPathForContentModule(module)
750		if err != nil {
751			t.Error(err)
752		}
753		android.AssertPathRelativeToTopEquals(t, name+" dex", expectedDexJar, dexJar)
754
755		expectedCopyCommand := fmt.Sprintf("&& cp -f %s out/soong/.intermediates/myapex/android_common_myapex_image/image.apex/javalib/%s.jar", expectedDexJar, name)
756		android.AssertStringDoesContain(t, name+" apex copy command", copyCommands, expectedCopyCommand)
757	}
758
759	checkFragmentExportedDexJar("foo", "out/soong/.intermediates/mybootclasspathfragment/android_common_apex10000/hiddenapi-modular/encoded/foo.jar")
760	checkFragmentExportedDexJar("bar", "out/soong/.intermediates/mybootclasspathfragment/android_common_apex10000/hiddenapi-modular/encoded/bar.jar")
761}
762
763func getDexJarPath(result *android.TestResult, name string) string {
764	module := result.Module(name, "android_common")
765	return module.(java.UsesLibraryDependency).DexJarBuildPath().Path().RelativeToTop().String()
766}
767
768// TestBootclasspathFragment_HiddenAPIList checks to make sure that the correct parameters are
769// passed to the hiddenapi list tool.
770func TestBootclasspathFragment_HiddenAPIList(t *testing.T) {
771	result := android.GroupFixturePreparers(
772		prepareForTestWithBootclasspathFragment,
773		prepareForTestWithArtApex,
774		prepareForTestWithMyapex,
775		// Configure bootclasspath jars to ensure that hidden API encoding is performed on them.
776		java.FixtureConfigureBootJars("com.android.art:baz", "com.android.art:quuz"),
777		java.FixtureConfigureApexBootJars("myapex:foo", "myapex:bar"),
778		// Make sure that the frameworks/base/Android.bp file exists as otherwise hidden API encoding
779		// is disabled.
780		android.FixtureAddTextFile("frameworks/base/Android.bp", ""),
781
782		java.PrepareForTestWithJavaSdkLibraryFiles,
783		java.FixtureWithLastReleaseApis("foo", "quuz"),
784	).RunTestWithBp(t, `
785		apex {
786			name: "com.android.art",
787			key: "com.android.art.key",
788			bootclasspath_fragments: ["art-bootclasspath-fragment"],
789			updatable: false,
790		}
791
792		apex_key {
793			name: "com.android.art.key",
794			public_key: "com.android.art.avbpubkey",
795			private_key: "com.android.art.pem",
796		}
797
798		java_library {
799			name: "baz",
800			apex_available: [
801				"com.android.art",
802			],
803			srcs: ["b.java"],
804			compile_dex: true,
805		}
806
807		java_sdk_library {
808			name: "quuz",
809			apex_available: [
810				"com.android.art",
811			],
812			srcs: ["b.java"],
813			compile_dex: true,
814			public: {enabled: true},
815			system: {enabled: true},
816			test: {enabled: true},
817			module_lib: {enabled: true},
818		}
819
820		bootclasspath_fragment {
821			name: "art-bootclasspath-fragment",
822			image_name: "art",
823			// Must match the "com.android.art:" entries passed to FixtureConfigureBootJars above.
824			contents: ["baz", "quuz"],
825			apex_available: [
826				"com.android.art",
827			],
828			hidden_api: {
829				split_packages: ["*"],
830			},
831		}
832
833		apex {
834			name: "myapex",
835			key: "myapex.key",
836			bootclasspath_fragments: [
837				"mybootclasspathfragment",
838			],
839			updatable: false,
840		}
841
842		apex_key {
843			name: "myapex.key",
844			public_key: "testkey.avbpubkey",
845			private_key: "testkey.pem",
846		}
847
848		java_sdk_library {
849			name: "foo",
850			srcs: ["b.java"],
851			shared_library: false,
852			public: {enabled: true},
853			apex_available: [
854				"myapex",
855			],
856		}
857
858		java_library {
859			name: "bar",
860			srcs: ["b.java"],
861			installable: true,
862			apex_available: [
863				"myapex",
864			],
865		}
866
867		bootclasspath_fragment {
868			name: "mybootclasspathfragment",
869			contents: [
870				"foo",
871				"bar",
872			],
873			apex_available: [
874				"myapex",
875			],
876			fragments: [
877				{
878					apex: "com.android.art",
879					module: "art-bootclasspath-fragment",
880				},
881			],
882			hidden_api: {
883				split_packages: ["*"],
884			},
885		}
886	`)
887
888	java.CheckModuleDependencies(t, result.TestContext, "mybootclasspathfragment", "android_common_apex10000", []string{
889		"art-bootclasspath-fragment",
890		"bar",
891		"dex2oatd",
892		"foo",
893	})
894
895	fooStubs := getDexJarPath(result, "foo.stubs")
896	quuzPublicStubs := getDexJarPath(result, "quuz.stubs")
897	quuzSystemStubs := getDexJarPath(result, "quuz.stubs.system")
898	quuzTestStubs := getDexJarPath(result, "quuz.stubs.test")
899	quuzModuleLibStubs := getDexJarPath(result, "quuz.stubs.module_lib")
900
901	// Make sure that the fragment uses the quuz stub dex jars when generating the hidden API flags.
902	fragment := result.ModuleForTests("mybootclasspathfragment", "android_common_apex10000")
903
904	rule := fragment.Rule("modularHiddenAPIStubFlagsFile")
905	command := rule.RuleParams.Command
906	android.AssertStringDoesContain(t, "check correct rule", command, "hiddenapi list")
907
908	// Make sure that the quuz stubs are available for resolving references from the implementation
909	// boot dex jars provided by this module.
910	android.AssertStringDoesContain(t, "quuz widest", command, "--dependency-stub-dex="+quuzModuleLibStubs)
911
912	// Make sure that the quuz stubs are available for resolving references from the different API
913	// stubs provided by this module.
914	android.AssertStringDoesContain(t, "public", command, "--public-stub-classpath="+quuzPublicStubs+":"+fooStubs)
915	android.AssertStringDoesContain(t, "system", command, "--system-stub-classpath="+quuzSystemStubs+":"+fooStubs)
916	android.AssertStringDoesContain(t, "test", command, "--test-stub-classpath="+quuzTestStubs+":"+fooStubs)
917}
918
919// TestBootclasspathFragment_AndroidNonUpdatable checks to make sure that setting
920// additional_stubs: ["android-non-updatable"] causes the source android-non-updatable modules to be
921// added to the hiddenapi list tool.
922func TestBootclasspathFragment_AndroidNonUpdatable(t *testing.T) {
923	result := android.GroupFixturePreparers(
924		prepareForTestWithBootclasspathFragment,
925		prepareForTestWithArtApex,
926		prepareForTestWithMyapex,
927		// Configure bootclasspath jars to ensure that hidden API encoding is performed on them.
928		java.FixtureConfigureBootJars("com.android.art:baz", "com.android.art:quuz"),
929		java.FixtureConfigureApexBootJars("myapex:foo", "myapex:bar"),
930		// Make sure that the frameworks/base/Android.bp file exists as otherwise hidden API encoding
931		// is disabled.
932		android.FixtureAddTextFile("frameworks/base/Android.bp", ""),
933
934		java.PrepareForTestWithJavaSdkLibraryFiles,
935		java.FixtureWithLastReleaseApis("foo", "android-non-updatable"),
936	).RunTestWithBp(t, `
937		java_sdk_library {
938			name: "android-non-updatable",
939			srcs: ["b.java"],
940			compile_dex: true,
941			public: {
942				enabled: true,
943			},
944			system: {
945				enabled: true,
946			},
947			test: {
948				enabled: true,
949			},
950			module_lib: {
951				enabled: true,
952			},
953		}
954
955		apex {
956			name: "com.android.art",
957			key: "com.android.art.key",
958			bootclasspath_fragments: ["art-bootclasspath-fragment"],
959			updatable: false,
960		}
961
962		apex_key {
963			name: "com.android.art.key",
964			public_key: "com.android.art.avbpubkey",
965			private_key: "com.android.art.pem",
966		}
967
968		java_library {
969			name: "baz",
970			apex_available: [
971				"com.android.art",
972			],
973			srcs: ["b.java"],
974			compile_dex: true,
975		}
976
977		java_library {
978			name: "quuz",
979			apex_available: [
980				"com.android.art",
981			],
982			srcs: ["b.java"],
983			compile_dex: true,
984		}
985
986		bootclasspath_fragment {
987			name: "art-bootclasspath-fragment",
988			image_name: "art",
989			// Must match the "com.android.art:" entries passed to FixtureConfigureBootJars above.
990			contents: ["baz", "quuz"],
991			apex_available: [
992				"com.android.art",
993			],
994			hidden_api: {
995				split_packages: ["*"],
996			},
997		}
998
999		apex {
1000			name: "myapex",
1001			key: "myapex.key",
1002			bootclasspath_fragments: [
1003				"mybootclasspathfragment",
1004			],
1005			updatable: false,
1006		}
1007
1008		apex_key {
1009			name: "myapex.key",
1010			public_key: "testkey.avbpubkey",
1011			private_key: "testkey.pem",
1012		}
1013
1014		java_sdk_library {
1015			name: "foo",
1016			srcs: ["b.java"],
1017			shared_library: false,
1018			public: {enabled: true},
1019			apex_available: [
1020				"myapex",
1021			],
1022		}
1023
1024		java_library {
1025			name: "bar",
1026			srcs: ["b.java"],
1027			installable: true,
1028			apex_available: [
1029				"myapex",
1030			],
1031		}
1032
1033		bootclasspath_fragment {
1034			name: "mybootclasspathfragment",
1035			contents: [
1036				"foo",
1037				"bar",
1038			],
1039			apex_available: [
1040				"myapex",
1041			],
1042			additional_stubs: ["android-non-updatable"],
1043			fragments: [
1044				{
1045					apex: "com.android.art",
1046					module: "art-bootclasspath-fragment",
1047				},
1048			],
1049			hidden_api: {
1050				split_packages: ["*"],
1051			},
1052		}
1053	`)
1054
1055	java.CheckModuleDependencies(t, result.TestContext, "mybootclasspathfragment", "android_common_apex10000", []string{
1056		"android-non-updatable.stubs",
1057		"android-non-updatable.stubs.module_lib",
1058		"android-non-updatable.stubs.system",
1059		"android-non-updatable.stubs.test",
1060		"art-bootclasspath-fragment",
1061		"bar",
1062		"dex2oatd",
1063		"foo",
1064	})
1065
1066	nonUpdatablePublicStubs := getDexJarPath(result, "android-non-updatable.stubs")
1067	nonUpdatableSystemStubs := getDexJarPath(result, "android-non-updatable.stubs.system")
1068	nonUpdatableTestStubs := getDexJarPath(result, "android-non-updatable.stubs.test")
1069	nonUpdatableModuleLibStubs := getDexJarPath(result, "android-non-updatable.stubs.module_lib")
1070
1071	// Make sure that the fragment uses the android-non-updatable modules when generating the hidden
1072	// API flags.
1073	fragment := result.ModuleForTests("mybootclasspathfragment", "android_common_apex10000")
1074
1075	rule := fragment.Rule("modularHiddenAPIStubFlagsFile")
1076	command := rule.RuleParams.Command
1077	android.AssertStringDoesContain(t, "check correct rule", command, "hiddenapi list")
1078
1079	// Make sure that the module_lib non-updatable stubs are available for resolving references from
1080	// the implementation boot dex jars provided by this module.
1081	android.AssertStringDoesContain(t, "android-non-updatable widest", command, "--dependency-stub-dex="+nonUpdatableModuleLibStubs)
1082
1083	// Make sure that the appropriate non-updatable stubs are available for resolving references from
1084	// the different API stubs provided by this module.
1085	android.AssertStringDoesContain(t, "public", command, "--public-stub-classpath="+nonUpdatablePublicStubs)
1086	android.AssertStringDoesContain(t, "system", command, "--system-stub-classpath="+nonUpdatableSystemStubs)
1087	android.AssertStringDoesContain(t, "test", command, "--test-stub-classpath="+nonUpdatableTestStubs)
1088}
1089
1090// TestBootclasspathFragment_AndroidNonUpdatable_AlwaysUsePrebuiltSdks checks to make sure that
1091// setting additional_stubs: ["android-non-updatable"] causes the prebuilt android-non-updatable
1092// modules to be added to the hiddenapi list tool.
1093func TestBootclasspathFragment_AndroidNonUpdatable_AlwaysUsePrebuiltSdks(t *testing.T) {
1094	result := android.GroupFixturePreparers(
1095		prepareForTestWithBootclasspathFragment,
1096		java.PrepareForTestWithDexpreopt,
1097		prepareForTestWithArtApex,
1098		prepareForTestWithMyapex,
1099		// Configure bootclasspath jars to ensure that hidden API encoding is performed on them.
1100		java.FixtureConfigureBootJars("com.android.art:baz", "com.android.art:quuz"),
1101		java.FixtureConfigureApexBootJars("myapex:foo", "myapex:bar"),
1102		// Make sure that the frameworks/base/Android.bp file exists as otherwise hidden API encoding
1103		// is disabled.
1104		android.FixtureAddTextFile("frameworks/base/Android.bp", ""),
1105
1106		android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
1107			variables.Always_use_prebuilt_sdks = proptools.BoolPtr(true)
1108		}),
1109
1110		java.PrepareForTestWithJavaSdkLibraryFiles,
1111		java.FixtureWithPrebuiltApis(map[string][]string{
1112			"current": {"android-non-updatable"},
1113			"30":      {"foo"},
1114		}),
1115	).RunTestWithBp(t, `
1116		apex {
1117			name: "com.android.art",
1118			key: "com.android.art.key",
1119			bootclasspath_fragments: ["art-bootclasspath-fragment"],
1120			updatable: false,
1121		}
1122
1123		apex_key {
1124			name: "com.android.art.key",
1125			public_key: "com.android.art.avbpubkey",
1126			private_key: "com.android.art.pem",
1127		}
1128
1129		java_library {
1130			name: "baz",
1131			apex_available: [
1132				"com.android.art",
1133			],
1134			srcs: ["b.java"],
1135			compile_dex: true,
1136		}
1137
1138		java_library {
1139			name: "quuz",
1140			apex_available: [
1141				"com.android.art",
1142			],
1143			srcs: ["b.java"],
1144			compile_dex: true,
1145		}
1146
1147		bootclasspath_fragment {
1148			name: "art-bootclasspath-fragment",
1149			image_name: "art",
1150			// Must match the "com.android.art:" entries passed to FixtureConfigureBootJars above.
1151			contents: ["baz", "quuz"],
1152			apex_available: [
1153				"com.android.art",
1154			],
1155			hidden_api: {
1156				split_packages: ["*"],
1157			},
1158		}
1159
1160		apex {
1161			name: "myapex",
1162			key: "myapex.key",
1163			bootclasspath_fragments: [
1164				"mybootclasspathfragment",
1165			],
1166			updatable: false,
1167		}
1168
1169		apex_key {
1170			name: "myapex.key",
1171			public_key: "testkey.avbpubkey",
1172			private_key: "testkey.pem",
1173		}
1174
1175		java_sdk_library {
1176			name: "foo",
1177			srcs: ["b.java"],
1178			shared_library: false,
1179			public: {enabled: true},
1180			apex_available: [
1181				"myapex",
1182			],
1183		}
1184
1185		java_library {
1186			name: "bar",
1187			srcs: ["b.java"],
1188			installable: true,
1189			apex_available: [
1190				"myapex",
1191			],
1192		}
1193
1194		bootclasspath_fragment {
1195			name: "mybootclasspathfragment",
1196			contents: [
1197				"foo",
1198				"bar",
1199			],
1200			apex_available: [
1201				"myapex",
1202			],
1203			additional_stubs: ["android-non-updatable"],
1204			fragments: [
1205				{
1206					apex: "com.android.art",
1207					module: "art-bootclasspath-fragment",
1208				},
1209			],
1210			hidden_api: {
1211				split_packages: ["*"],
1212			},
1213		}
1214	`)
1215
1216	java.CheckModuleDependencies(t, result.TestContext, "mybootclasspathfragment", "android_common_apex10000", []string{
1217		"art-bootclasspath-fragment",
1218		"bar",
1219		"dex2oatd",
1220		"foo",
1221		"prebuilt_sdk_module-lib_current_android-non-updatable",
1222		"prebuilt_sdk_public_current_android-non-updatable",
1223		"prebuilt_sdk_system_current_android-non-updatable",
1224		"prebuilt_sdk_test_current_android-non-updatable",
1225	})
1226
1227	nonUpdatablePublicStubs := getDexJarPath(result, "sdk_public_current_android-non-updatable")
1228	nonUpdatableSystemStubs := getDexJarPath(result, "sdk_system_current_android-non-updatable")
1229	nonUpdatableTestStubs := getDexJarPath(result, "sdk_test_current_android-non-updatable")
1230	nonUpdatableModuleLibStubs := getDexJarPath(result, "sdk_module-lib_current_android-non-updatable")
1231
1232	// Make sure that the fragment uses the android-non-updatable modules when generating the hidden
1233	// API flags.
1234	fragment := result.ModuleForTests("mybootclasspathfragment", "android_common_apex10000")
1235
1236	rule := fragment.Rule("modularHiddenAPIStubFlagsFile")
1237	command := rule.RuleParams.Command
1238	android.AssertStringDoesContain(t, "check correct rule", command, "hiddenapi list")
1239
1240	// Make sure that the module_lib non-updatable stubs are available for resolving references from
1241	// the implementation boot dex jars provided by this module.
1242	android.AssertStringDoesContain(t, "android-non-updatable widest", command, "--dependency-stub-dex="+nonUpdatableModuleLibStubs)
1243
1244	// Make sure that the appropriate non-updatable stubs are available for resolving references from
1245	// the different API stubs provided by this module.
1246	android.AssertStringDoesContain(t, "public", command, "--public-stub-classpath="+nonUpdatablePublicStubs)
1247	android.AssertStringDoesContain(t, "system", command, "--system-stub-classpath="+nonUpdatableSystemStubs)
1248	android.AssertStringDoesContain(t, "test", command, "--test-stub-classpath="+nonUpdatableTestStubs)
1249}
1250
1251// TODO(b/177892522) - add test for host apex.
1252