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