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