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