• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2018 Google Inc. All rights reserved.
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	"path/filepath"
21	"reflect"
22	"regexp"
23	"sort"
24	"strconv"
25	"strings"
26	"testing"
27
28	"android/soong/aconfig/codegen"
29
30	"github.com/google/blueprint"
31	"github.com/google/blueprint/proptools"
32
33	"android/soong/android"
34	"android/soong/bpf"
35	"android/soong/cc"
36	"android/soong/dexpreopt"
37	prebuilt_etc "android/soong/etc"
38	"android/soong/filesystem"
39	"android/soong/java"
40	"android/soong/rust"
41	"android/soong/sh"
42)
43
44// names returns name list from white space separated string
45func names(s string) (ns []string) {
46	for _, n := range strings.Split(s, " ") {
47		if len(n) > 0 {
48			ns = append(ns, n)
49		}
50	}
51	return
52}
53
54func testApexError(t *testing.T, pattern, bp string, preparers ...android.FixturePreparer) {
55	t.Helper()
56	android.GroupFixturePreparers(
57		prepareForApexTest,
58		android.GroupFixturePreparers(preparers...),
59	).
60		ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(pattern)).
61		RunTestWithBp(t, bp)
62}
63
64func testApex(t *testing.T, bp string, preparers ...android.FixturePreparer) *android.TestContext {
65	t.Helper()
66
67	optionalBpPreparer := android.NullFixturePreparer
68	if bp != "" {
69		optionalBpPreparer = android.FixtureWithRootAndroidBp(bp)
70	}
71
72	result := android.GroupFixturePreparers(
73		prepareForApexTest,
74		android.GroupFixturePreparers(preparers...),
75		optionalBpPreparer,
76	).RunTest(t)
77
78	return result.TestContext
79}
80
81func withFiles(files android.MockFS) android.FixturePreparer {
82	return files.AddToFixture()
83}
84
85func withManifestPackageNameOverrides(specs []string) android.FixturePreparer {
86	return android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
87		variables.ManifestPackageNameOverrides = specs
88	})
89}
90
91func withApexGlobalMinSdkVersionOverride(minSdkOverride *string) android.FixturePreparer {
92	return android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
93		variables.ApexGlobalMinSdkVersionOverride = minSdkOverride
94	})
95}
96
97var withBinder32bit = android.FixtureModifyProductVariables(
98	func(variables android.FixtureProductVariables) {
99		variables.Binder32bit = proptools.BoolPtr(true)
100	},
101)
102
103var withUnbundledBuild = android.FixtureModifyProductVariables(
104	func(variables android.FixtureProductVariables) {
105		variables.Unbundled_build = proptools.BoolPtr(true)
106	},
107)
108
109// Legacy preparer used for running tests within the apex package.
110//
111// This includes everything that was needed to run any test in the apex package prior to the
112// introduction of the test fixtures. Tests that are being converted to use fixtures directly
113// rather than through the testApex...() methods should avoid using this and instead use the
114// various preparers directly, using android.GroupFixturePreparers(...) to group them when
115// necessary.
116//
117// deprecated
118var prepareForApexTest = android.GroupFixturePreparers(
119	// General preparers in alphabetical order as test infrastructure will enforce correct
120	// registration order.
121	android.PrepareForTestWithAndroidBuildComponents,
122	bpf.PrepareForTestWithBpf,
123	cc.PrepareForTestWithCcBuildComponents,
124	java.PrepareForTestWithDexpreopt,
125	prebuilt_etc.PrepareForTestWithPrebuiltEtc,
126	rust.PrepareForTestWithRustDefaultModules,
127	sh.PrepareForTestWithShBuildComponents,
128	codegen.PrepareForTestWithAconfigBuildComponents,
129
130	PrepareForTestWithApexBuildComponents,
131
132	// Additional apex test specific preparers.
133	android.FixtureAddTextFile("system/sepolicy/Android.bp", `
134		filegroup {
135			name: "myapex-file_contexts",
136			srcs: [
137				"apex/myapex-file_contexts",
138			],
139		}
140	`),
141	prepareForTestWithMyapex,
142	android.FixtureMergeMockFs(android.MockFS{
143		"a.java":                 nil,
144		"PrebuiltAppFoo.apk":     nil,
145		"PrebuiltAppFooPriv.apk": nil,
146		"apex_manifest.json":     nil,
147		"AndroidManifest.xml":    nil,
148		"system/sepolicy/apex/myapex.updatable-file_contexts":         nil,
149		"system/sepolicy/apex/myapex2-file_contexts":                  nil,
150		"system/sepolicy/apex/otherapex-file_contexts":                nil,
151		"system/sepolicy/apex/com.android.vndk-file_contexts":         nil,
152		"system/sepolicy/apex/com.android.vndk.current-file_contexts": nil,
153		"mylib.cpp":                            nil,
154		"mytest.cpp":                           nil,
155		"mytest1.cpp":                          nil,
156		"mytest2.cpp":                          nil,
157		"mytest3.cpp":                          nil,
158		"myprebuilt":                           nil,
159		"my_include":                           nil,
160		"foo/bar/MyClass.java":                 nil,
161		"prebuilt.jar":                         nil,
162		"prebuilt.so":                          nil,
163		"vendor/foo/devkeys/test.x509.pem":     nil,
164		"vendor/foo/devkeys/test.pk8":          nil,
165		"testkey.x509.pem":                     nil,
166		"testkey.pk8":                          nil,
167		"testkey.override.x509.pem":            nil,
168		"testkey.override.pk8":                 nil,
169		"vendor/foo/devkeys/testkey.avbpubkey": nil,
170		"vendor/foo/devkeys/testkey.pem":       nil,
171		"NOTICE":                               nil,
172		"custom_notice":                        nil,
173		"custom_notice_for_static_lib":         nil,
174		"testkey2.avbpubkey":                   nil,
175		"testkey2.pem":                         nil,
176		"myapex-arm64.apex":                    nil,
177		"myapex-arm.apex":                      nil,
178		"myapex.apks":                          nil,
179		"frameworks/base/api/current.txt":      nil,
180		"framework/aidl/a.aidl":                nil,
181		"dummy.txt":                            nil,
182		"baz":                                  nil,
183		"bar/baz":                              nil,
184		"testdata/baz":                         nil,
185		"AppSet.apks":                          nil,
186		"foo.rs":                               nil,
187		"libfoo.jar":                           nil,
188		"libbar.jar":                           nil,
189	},
190	),
191
192	android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
193		variables.DefaultAppCertificate = proptools.StringPtr("vendor/foo/devkeys/test")
194		variables.CertificateOverrides = []string{"myapex_keytest:myapex.certificate.override"}
195		variables.Platform_sdk_codename = proptools.StringPtr("Q")
196		variables.Platform_sdk_final = proptools.BoolPtr(false)
197		// "Tiramisu" needs to be in the next line for compatibility with soong code,
198		// not because of these tests specifically (it's not used by the tests)
199		variables.Platform_version_active_codenames = []string{"Q", "Tiramisu"}
200		variables.BuildId = proptools.StringPtr("TEST.BUILD_ID")
201	}),
202)
203
204var prepareForTestWithMyapex = android.FixtureMergeMockFs(android.MockFS{
205	"system/sepolicy/apex/myapex-file_contexts": nil,
206})
207
208var prepareForTestWithOtherapex = android.FixtureMergeMockFs(android.MockFS{
209	"system/sepolicy/apex/otherapex-file_contexts": nil,
210})
211
212// ensure that 'result' equals 'expected'
213func ensureEquals(t *testing.T, result string, expected string) {
214	t.Helper()
215	if result != expected {
216		t.Errorf("%q != %q", expected, result)
217	}
218}
219
220// ensure that 'result' contains 'expected'
221func ensureContains(t *testing.T, result string, expected string) {
222	t.Helper()
223	if !strings.Contains(result, expected) {
224		t.Errorf("%q is not found in %q", expected, result)
225	}
226}
227
228// ensure that 'result' contains 'expected' exactly one time
229func ensureContainsOnce(t *testing.T, result string, expected string) {
230	t.Helper()
231	count := strings.Count(result, expected)
232	if count != 1 {
233		t.Errorf("%q is found %d times (expected 1 time) in %q", expected, count, result)
234	}
235}
236
237// ensures that 'result' does not contain 'notExpected'
238func ensureNotContains(t *testing.T, result string, notExpected string) {
239	t.Helper()
240	if strings.Contains(result, notExpected) {
241		t.Errorf("%q is found in %q", notExpected, result)
242	}
243}
244
245func ensureMatches(t *testing.T, result string, expectedRex string) {
246	t.Helper()
247	ok, err := regexp.MatchString(expectedRex, result)
248	if err != nil {
249		t.Fatalf("regexp failure trying to match %s against `%s` expression: %s", result, expectedRex, err)
250		return
251	}
252	if !ok {
253		t.Errorf("%s does not match regular expession %s", result, expectedRex)
254	}
255}
256
257func ensureListContainsMatch(t *testing.T, result []string, expectedRex string) {
258	t.Helper()
259	p := regexp.MustCompile(expectedRex)
260	if android.IndexListPred(func(s string) bool { return p.MatchString(s) }, result) == -1 {
261		t.Errorf("%q is not found in %v", expectedRex, result)
262	}
263}
264
265func ensureListContains(t *testing.T, result []string, expected string) {
266	t.Helper()
267	if !android.InList(expected, result) {
268		t.Errorf("%q is not found in %v", expected, result)
269	}
270}
271
272func ensureListNotContains(t *testing.T, result []string, notExpected string) {
273	t.Helper()
274	if android.InList(notExpected, result) {
275		t.Errorf("%q is found in %v", notExpected, result)
276	}
277}
278
279func ensureListEmpty(t *testing.T, result []string) {
280	t.Helper()
281	if len(result) > 0 {
282		t.Errorf("%q is expected to be empty", result)
283	}
284}
285
286func ensureListNotEmpty(t *testing.T, result []string) {
287	t.Helper()
288	if len(result) == 0 {
289		t.Errorf("%q is expected to be not empty", result)
290	}
291}
292
293// Minimal test
294func TestBasicApex(t *testing.T) {
295	t.Parallel()
296	ctx := testApex(t, `
297		apex_defaults {
298			name: "myapex-defaults",
299			manifest: ":myapex.manifest",
300			androidManifest: ":myapex.androidmanifest",
301			key: "myapex.key",
302			binaries: ["foo.rust"],
303			native_shared_libs: [
304				"mylib",
305				"libfoo.ffi",
306			],
307			rust_dyn_libs: ["libfoo.dylib.rust"],
308			multilib: {
309				both: {
310					binaries: ["foo"],
311				}
312			},
313			java_libs: [
314				"myjar",
315				"myjar_dex",
316			],
317			updatable: false,
318		}
319
320		apex {
321			name: "myapex",
322			defaults: ["myapex-defaults"],
323		}
324
325		apex_key {
326			name: "myapex.key",
327			public_key: "testkey.avbpubkey",
328			private_key: "testkey.pem",
329		}
330
331		filegroup {
332			name: "myapex.manifest",
333			srcs: ["apex_manifest.json"],
334		}
335
336		filegroup {
337			name: "myapex.androidmanifest",
338			srcs: ["AndroidManifest.xml"],
339		}
340
341		cc_library {
342			name: "mylib",
343			srcs: ["mylib.cpp"],
344			shared_libs: [
345				"mylib2",
346				"libbar.ffi",
347			],
348			system_shared_libs: [],
349			stl: "none",
350			// TODO: remove //apex_available:platform
351			apex_available: [
352				"//apex_available:platform",
353				"myapex",
354			],
355		}
356
357		cc_binary {
358			name: "foo",
359			srcs: ["mylib.cpp"],
360			compile_multilib: "both",
361			multilib: {
362					lib32: {
363							suffix: "32",
364					},
365					lib64: {
366							suffix: "64",
367					},
368			},
369			symlinks: ["foo_link_"],
370			symlink_preferred_arch: true,
371			system_shared_libs: [],
372			stl: "none",
373			apex_available: [ "myapex" ],
374		}
375
376		rust_binary {
377			name: "foo.rust",
378			srcs: ["foo.rs"],
379			rlibs: ["libfoo.rlib.rust"],
380			rustlibs: ["libfoo.transitive.dylib.rust"],
381			apex_available: ["myapex"],
382		}
383
384		rust_library_rlib {
385			name: "libfoo.rlib.rust",
386			srcs: ["foo.rs"],
387			crate_name: "foo",
388			apex_available: ["myapex"],
389			shared_libs: ["libfoo.shared_from_rust"],
390		}
391
392		cc_library_shared {
393			name: "libfoo.shared_from_rust",
394			srcs: ["mylib.cpp"],
395			system_shared_libs: [],
396			stl: "none",
397			apex_available: ["myapex"],
398		}
399
400		rust_library_dylib {
401			name: "libfoo.dylib.rust",
402			srcs: ["foo.rs"],
403			crate_name: "foo",
404			apex_available: ["myapex"],
405		}
406
407		rust_library_dylib {
408			name: "libfoo.transitive.dylib.rust",
409			srcs: ["foo.rs"],
410			crate_name: "foo",
411			apex_available: ["myapex"],
412		}
413
414		rust_ffi_shared {
415			name: "libfoo.ffi",
416			srcs: ["foo.rs"],
417			crate_name: "foo",
418			apex_available: ["myapex"],
419		}
420
421		rust_ffi_shared {
422			name: "libbar.ffi",
423			srcs: ["foo.rs"],
424			crate_name: "bar",
425			apex_available: ["myapex"],
426		}
427
428		cc_library_shared {
429			name: "mylib2",
430			srcs: ["mylib.cpp"],
431			system_shared_libs: [],
432			stl: "none",
433			static_libs: ["libstatic"],
434			// TODO: remove //apex_available:platform
435			apex_available: [
436				"//apex_available:platform",
437				"myapex",
438			],
439		}
440
441		cc_prebuilt_library_shared {
442			name: "mylib2",
443			srcs: ["prebuilt.so"],
444			// TODO: remove //apex_available:platform
445			apex_available: [
446				"//apex_available:platform",
447				"myapex",
448			],
449		}
450
451		cc_library_static {
452			name: "libstatic",
453			srcs: ["mylib.cpp"],
454			system_shared_libs: [],
455			stl: "none",
456			// TODO: remove //apex_available:platform
457			apex_available: [
458				"//apex_available:platform",
459				"myapex",
460			],
461		}
462
463		java_library {
464			name: "myjar",
465			srcs: ["foo/bar/MyClass.java"],
466			stem: "myjar_stem",
467			sdk_version: "none",
468			system_modules: "none",
469			static_libs: ["myotherjar"],
470			libs: ["mysharedjar"],
471			// TODO: remove //apex_available:platform
472			apex_available: [
473				"//apex_available:platform",
474				"myapex",
475			],
476			compile_dex: true,
477		}
478
479		dex_import {
480			name: "myjar_dex",
481			jars: ["prebuilt.jar"],
482			apex_available: [
483				"//apex_available:platform",
484				"myapex",
485			],
486		}
487
488		java_library {
489			name: "myotherjar",
490			srcs: ["foo/bar/MyClass.java"],
491			sdk_version: "none",
492			system_modules: "none",
493			// TODO: remove //apex_available:platform
494			apex_available: [
495				"//apex_available:platform",
496				"myapex",
497			],
498		}
499
500		java_library {
501			name: "mysharedjar",
502			srcs: ["foo/bar/MyClass.java"],
503			sdk_version: "none",
504			system_modules: "none",
505		}
506	`)
507
508	apexRule := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Rule("apexRule")
509
510	// Make sure that Android.mk is created
511	ab := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Module().(*apexBundle)
512	data := android.AndroidMkDataForTest(t, ctx, ab)
513	var builder strings.Builder
514	data.Custom(&builder, ab.BaseModuleName(), "TARGET_", "", data)
515
516	androidMk := builder.String()
517	ensureContains(t, androidMk, "LOCAL_MODULE := mylib.myapex\n")
518	ensureNotContains(t, androidMk, "LOCAL_MODULE := mylib.com.android.myapex\n")
519
520	optFlags := apexRule.Args["opt_flags"]
521	ensureContains(t, optFlags, "--pubkey vendor/foo/devkeys/testkey.avbpubkey")
522	// Ensure that the NOTICE output is being packaged as an asset.
523	ensureContains(t, optFlags, "--assets_dir out/soong/.intermediates/myapex/android_common_myapex/NOTICE")
524
525	copyCmds := apexRule.Args["copy_commands"]
526
527	// Ensure that main rule creates an output
528	ensureContains(t, apexRule.Output.String(), "myapex.apex.unsigned")
529
530	// Ensure that apex variant is created for the direct dep
531	ensureListContains(t, ctx.ModuleVariantsForTests("mylib"), "android_arm64_armv8-a_shared_apex10000")
532	ensureListContains(t, ctx.ModuleVariantsForTests("myjar"), "android_common_apex10000")
533	ensureListContains(t, ctx.ModuleVariantsForTests("myjar_dex"), "android_common_apex10000")
534	ensureListContains(t, ctx.ModuleVariantsForTests("foo.rust"), "android_arm64_armv8-a_apex10000")
535	ensureListContains(t, ctx.ModuleVariantsForTests("libfoo.ffi"), "android_arm64_armv8-a_shared_apex10000")
536
537	// Ensure that apex variant is created for the indirect dep
538	ensureListContains(t, ctx.ModuleVariantsForTests("mylib2"), "android_arm64_armv8-a_shared_apex10000")
539	ensureListContains(t, ctx.ModuleVariantsForTests("myotherjar"), "android_common_apex10000")
540	ensureListContains(t, ctx.ModuleVariantsForTests("libfoo.rlib.rust"), "android_arm64_armv8-a_rlib_dylib-std_apex10000")
541	ensureListContains(t, ctx.ModuleVariantsForTests("libfoo.dylib.rust"), "android_arm64_armv8-a_dylib_apex10000")
542	ensureListContains(t, ctx.ModuleVariantsForTests("libfoo.transitive.dylib.rust"), "android_arm64_armv8-a_dylib_apex10000")
543	ensureListContains(t, ctx.ModuleVariantsForTests("libbar.ffi"), "android_arm64_armv8-a_shared_apex10000")
544	ensureListContains(t, ctx.ModuleVariantsForTests("libfoo.shared_from_rust"), "android_arm64_armv8-a_shared_apex10000")
545
546	// Ensure that both direct and indirect deps are copied into apex
547	ensureContains(t, copyCmds, "image.apex/lib64/mylib.so")
548	ensureContains(t, copyCmds, "image.apex/lib64/mylib2.so")
549	ensureContains(t, copyCmds, "image.apex/javalib/myjar_stem.jar")
550	ensureContains(t, copyCmds, "image.apex/javalib/myjar_dex.jar")
551	ensureContains(t, copyCmds, "image.apex/lib64/libfoo.dylib.rust.dylib.so")
552	ensureContains(t, copyCmds, "image.apex/lib64/libfoo.transitive.dylib.rust.dylib.so")
553	ensureContains(t, copyCmds, "image.apex/lib64/libfoo.ffi.so")
554	ensureContains(t, copyCmds, "image.apex/lib64/libbar.ffi.so")
555	ensureContains(t, copyCmds, "image.apex/lib64/libfoo.shared_from_rust.so")
556	// .. but not for java libs
557	ensureNotContains(t, copyCmds, "image.apex/javalib/myotherjar.jar")
558	ensureNotContains(t, copyCmds, "image.apex/javalib/msharedjar.jar")
559
560	// Ensure that the platform variant ends with _shared or _common
561	ensureListContains(t, ctx.ModuleVariantsForTests("mylib"), "android_arm64_armv8-a_shared")
562	ensureListContains(t, ctx.ModuleVariantsForTests("mylib2"), "android_arm64_armv8-a_shared")
563	ensureListContains(t, ctx.ModuleVariantsForTests("myjar"), "android_common")
564	ensureListContains(t, ctx.ModuleVariantsForTests("myotherjar"), "android_common")
565	ensureListContains(t, ctx.ModuleVariantsForTests("mysharedjar"), "android_common")
566
567	// Ensure that dynamic dependency to java libs are not included
568	ensureListNotContains(t, ctx.ModuleVariantsForTests("mysharedjar"), "android_common_myapex")
569
570	// Ensure that all symlinks are present.
571	found_foo_link_64 := false
572	found_foo := false
573	for _, cmd := range strings.Split(copyCmds, " && ") {
574		if strings.HasPrefix(cmd, "ln -sfn foo64") {
575			if strings.HasSuffix(cmd, "bin/foo") {
576				found_foo = true
577			} else if strings.HasSuffix(cmd, "bin/foo_link_64") {
578				found_foo_link_64 = true
579			}
580		}
581	}
582	good := found_foo && found_foo_link_64
583	if !good {
584		t.Errorf("Could not find all expected symlinks! foo: %t, foo_link_64: %t. Command was %s", found_foo, found_foo_link_64, copyCmds)
585	}
586
587	fullDepsInfo := strings.Split(android.ContentFromFileRuleForTests(t, ctx,
588		ctx.ModuleForTests(t, "myapex", "android_common_myapex").Output("depsinfo/fulllist.txt")), "\n")
589	ensureListContains(t, fullDepsInfo, "  myjar(minSdkVersion:(no version)) <- myapex")
590	ensureListContains(t, fullDepsInfo, "  mylib2(minSdkVersion:(no version)) <- mylib")
591	ensureListContains(t, fullDepsInfo, "  myotherjar(minSdkVersion:(no version)) <- myjar")
592	ensureListContains(t, fullDepsInfo, "  mysharedjar(minSdkVersion:(no version)) (external) <- myjar")
593
594	flatDepsInfo := strings.Split(android.ContentFromFileRuleForTests(t, ctx,
595		ctx.ModuleForTests(t, "myapex", "android_common_myapex").Output("depsinfo/flatlist.txt")), "\n")
596	ensureListContains(t, flatDepsInfo, "myjar(minSdkVersion:(no version))")
597	ensureListContains(t, flatDepsInfo, "mylib2(minSdkVersion:(no version))")
598	ensureListContains(t, flatDepsInfo, "myotherjar(minSdkVersion:(no version))")
599	ensureListContains(t, flatDepsInfo, "mysharedjar(minSdkVersion:(no version)) (external)")
600}
601
602func TestDefaults(t *testing.T) {
603	t.Parallel()
604	ctx := testApex(t, `
605		apex_defaults {
606			name: "myapex-defaults",
607			key: "myapex.key",
608			prebuilts: ["myetc"],
609			native_shared_libs: ["mylib"],
610			java_libs: ["myjar"],
611			apps: ["AppFoo"],
612			rros: ["rro"],
613			bpfs: ["bpf", "netdTest"],
614			updatable: false,
615		}
616
617		prebuilt_etc {
618			name: "myetc",
619			src: "myprebuilt",
620		}
621
622		apex {
623			name: "myapex",
624			defaults: ["myapex-defaults"],
625		}
626
627		apex_key {
628			name: "myapex.key",
629			public_key: "testkey.avbpubkey",
630			private_key: "testkey.pem",
631		}
632
633		cc_library {
634			name: "mylib",
635			system_shared_libs: [],
636			stl: "none",
637			apex_available: [ "myapex" ],
638		}
639
640		java_library {
641			name: "myjar",
642			srcs: ["foo/bar/MyClass.java"],
643			sdk_version: "none",
644			system_modules: "none",
645			apex_available: [ "myapex" ],
646			compile_dex: true,
647		}
648
649		android_app {
650			name: "AppFoo",
651			srcs: ["foo/bar/MyClass.java"],
652			sdk_version: "none",
653			system_modules: "none",
654			apex_available: [ "myapex" ],
655		}
656
657		runtime_resource_overlay {
658			name: "rro",
659			theme: "blue",
660		}
661
662		bpf {
663			name: "bpf",
664			srcs: ["bpf.c", "bpf2.c"],
665		}
666
667		bpf {
668			name: "netdTest",
669			srcs: ["netdTest.c"],
670			sub_dir: "netd",
671		}
672
673	`)
674	ensureExactContents(t, ctx, "myapex", "android_common_myapex", []string{
675		"etc/myetc",
676		"javalib/myjar.jar",
677		"lib64/mylib.so",
678		"app/AppFoo@TEST.BUILD_ID/AppFoo.apk",
679		"overlay/blue/rro.apk",
680		"etc/bpf/bpf.o",
681		"etc/bpf/bpf2.o",
682		"etc/bpf/netd/netdTest.o",
683	})
684}
685
686func TestApexManifest(t *testing.T) {
687	t.Parallel()
688	ctx := testApex(t, `
689		apex {
690			name: "myapex",
691			key: "myapex.key",
692			updatable: false,
693		}
694
695		apex_key {
696			name: "myapex.key",
697			public_key: "testkey.avbpubkey",
698			private_key: "testkey.pem",
699		}
700	`)
701
702	module := ctx.ModuleForTests(t, "myapex", "android_common_myapex")
703	args := module.Rule("apexRule").Args
704	if manifest := args["manifest"]; manifest != module.Output("apex_manifest.pb").Output.String() {
705		t.Error("manifest should be apex_manifest.pb, but " + manifest)
706	}
707}
708
709func TestApexManifestMinSdkVersion(t *testing.T) {
710	t.Parallel()
711	ctx := testApex(t, `
712		apex_defaults {
713			name: "my_defaults",
714			key: "myapex.key",
715			product_specific: true,
716			file_contexts: ":my-file-contexts",
717			updatable: false,
718		}
719		apex {
720			name: "myapex_30",
721			min_sdk_version: "30",
722			defaults: ["my_defaults"],
723		}
724
725		apex {
726			name: "myapex_current",
727			min_sdk_version: "current",
728			defaults: ["my_defaults"],
729		}
730
731		apex {
732			name: "myapex_none",
733			defaults: ["my_defaults"],
734		}
735
736		apex_key {
737			name: "myapex.key",
738			public_key: "testkey.avbpubkey",
739			private_key: "testkey.pem",
740		}
741
742		filegroup {
743			name: "my-file-contexts",
744			srcs: ["product_specific_file_contexts"],
745		}
746	`, withFiles(map[string][]byte{
747		"product_specific_file_contexts": nil,
748	}), android.FixtureModifyProductVariables(
749		func(variables android.FixtureProductVariables) {
750			variables.Unbundled_build = proptools.BoolPtr(true)
751			variables.Always_use_prebuilt_sdks = proptools.BoolPtr(false)
752		}), android.FixtureMergeEnv(map[string]string{
753		"UNBUNDLED_BUILD_TARGET_SDK_WITH_API_FINGERPRINT": "true",
754	}))
755
756	testCases := []struct {
757		module        string
758		minSdkVersion string
759	}{
760		{
761			module:        "myapex_30",
762			minSdkVersion: "30",
763		},
764		{
765			module:        "myapex_current",
766			minSdkVersion: "Q.$$(cat out/soong/api_fingerprint.txt)",
767		},
768		{
769			module:        "myapex_none",
770			minSdkVersion: "Q.$$(cat out/soong/api_fingerprint.txt)",
771		},
772	}
773	for _, tc := range testCases {
774		module := ctx.ModuleForTests(t, tc.module, "android_common_"+tc.module)
775		args := module.Rule("apexRule").Args
776		optFlags := args["opt_flags"]
777		if !strings.Contains(optFlags, "--min_sdk_version "+tc.minSdkVersion) {
778			t.Errorf("%s: Expected min_sdk_version=%s, got: %s", tc.module, tc.minSdkVersion, optFlags)
779		}
780	}
781}
782
783func TestApexWithDessertSha(t *testing.T) {
784	t.Parallel()
785	ctx := testApex(t, `
786		apex_defaults {
787			name: "my_defaults",
788			key: "myapex.key",
789			product_specific: true,
790			file_contexts: ":my-file-contexts",
791			updatable: false,
792		}
793		apex {
794			name: "myapex_30",
795			min_sdk_version: "30",
796			defaults: ["my_defaults"],
797		}
798
799		apex {
800			name: "myapex_current",
801			min_sdk_version: "current",
802			defaults: ["my_defaults"],
803		}
804
805		apex {
806			name: "myapex_none",
807			defaults: ["my_defaults"],
808		}
809
810		apex_key {
811			name: "myapex.key",
812			public_key: "testkey.avbpubkey",
813			private_key: "testkey.pem",
814		}
815
816		filegroup {
817			name: "my-file-contexts",
818			srcs: ["product_specific_file_contexts"],
819		}
820	`, withFiles(map[string][]byte{
821		"product_specific_file_contexts": nil,
822	}), android.FixtureModifyProductVariables(
823		func(variables android.FixtureProductVariables) {
824			variables.Unbundled_build = proptools.BoolPtr(true)
825			variables.Always_use_prebuilt_sdks = proptools.BoolPtr(false)
826		}), android.FixtureMergeEnv(map[string]string{
827		"UNBUNDLED_BUILD_TARGET_SDK_WITH_DESSERT_SHA": "UpsideDownCake.abcdefghijklmnopqrstuvwxyz123456",
828	}))
829
830	testCases := []struct {
831		module        string
832		minSdkVersion string
833	}{
834		{
835			module:        "myapex_30",
836			minSdkVersion: "30",
837		},
838		{
839			module:        "myapex_current",
840			minSdkVersion: "UpsideDownCake.abcdefghijklmnopqrstuvwxyz123456",
841		},
842		{
843			module:        "myapex_none",
844			minSdkVersion: "UpsideDownCake.abcdefghijklmnopqrstuvwxyz123456",
845		},
846	}
847	for _, tc := range testCases {
848		module := ctx.ModuleForTests(t, tc.module, "android_common_"+tc.module)
849		args := module.Rule("apexRule").Args
850		optFlags := args["opt_flags"]
851		if !strings.Contains(optFlags, "--min_sdk_version "+tc.minSdkVersion) {
852			t.Errorf("%s: Expected min_sdk_version=%s, got: %s", tc.module, tc.minSdkVersion, optFlags)
853		}
854	}
855}
856
857func TestFileContexts(t *testing.T) {
858	t.Parallel()
859	for _, vendor := range []bool{true, false} {
860		prop := ""
861		if vendor {
862			prop = "vendor: true,\n"
863		}
864		ctx := testApex(t, `
865			apex {
866				name: "myapex",
867				key: "myapex.key",
868				updatable: false,
869				`+prop+`
870			}
871
872			apex_key {
873				name: "myapex.key",
874				public_key: "testkey.avbpubkey",
875				private_key: "testkey.pem",
876			}
877		`)
878
879		rule := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Output("file_contexts")
880		if vendor {
881			android.AssertStringDoesContain(t, "should force-label as vendor_apex_metadata_file",
882				rule.RuleParams.Command,
883				"apex_manifest\\\\.pb u:object_r:vendor_apex_metadata_file:s0")
884		} else {
885			android.AssertStringDoesContain(t, "should force-label as system_file",
886				rule.RuleParams.Command,
887				"apex_manifest\\\\.pb u:object_r:system_file:s0")
888		}
889	}
890}
891
892func TestApexWithStubs(t *testing.T) {
893	t.Parallel()
894	ctx := testApex(t, `
895		apex {
896			name: "myapex",
897			key: "myapex.key",
898			native_shared_libs: [
899				"mylib",
900				"mylib3",
901				"libmylib3_rs",
902			],
903			binaries: ["foo.rust"],
904			updatable: false,
905		}
906
907		apex_key {
908			name: "myapex.key",
909			public_key: "testkey.avbpubkey",
910			private_key: "testkey.pem",
911		}
912
913		cc_library {
914			name: "mylib",
915			srcs: ["mylib.cpp"],
916			shared_libs: [
917				"mylib2",
918				"mylib3#impl",
919				"libmylib2_rs",
920				"libmylib3_rs#impl",
921				"my_prebuilt_platform_lib",
922				"my_prebuilt_platform_stub_only_lib",
923			],
924			system_shared_libs: [],
925			stl: "none",
926			apex_available: [ "myapex" ],
927		}
928
929		cc_library {
930			name: "mylib2",
931			srcs: ["mylib.cpp"],
932			cflags: ["-include mylib.h"],
933			system_shared_libs: [],
934			stl: "none",
935			stubs: {
936				symbol_file: "mylib2.map.txt",
937				versions: ["1", "2", "3"],
938			},
939		}
940
941		rust_ffi {
942			name: "libmylib2_rs",
943			crate_name: "mylib2",
944			srcs: ["mylib.rs"],
945			stubs: {
946				symbol_file: "mylib2.map.txt",
947				versions: ["1", "2", "3"],
948			},
949		}
950
951		cc_library {
952			name: "mylib3",
953			srcs: ["mylib.cpp"],
954			shared_libs: ["mylib4"],
955			system_shared_libs: [],
956			stl: "none",
957			stubs: {
958				symbol_file: "mylib3.map.txt",
959				versions: ["10", "11", "12"],
960			},
961			apex_available: [ "myapex" ],
962		}
963
964		rust_ffi {
965			name: "libmylib3_rs",
966			crate_name: "mylib3",
967			srcs: ["mylib.rs"],
968			shared_libs: ["mylib4.from_rust"],
969			stubs: {
970				symbol_file: "mylib3.map.txt",
971				versions: ["10", "11", "12"],
972			},
973			apex_available: [ "myapex" ],
974		}
975
976		cc_library {
977			name: "mylib4",
978			srcs: ["mylib.cpp"],
979			system_shared_libs: [],
980			stl: "none",
981			apex_available: [ "myapex" ],
982		}
983
984		cc_library {
985			name: "mylib4.from_rust",
986			srcs: ["mylib.cpp"],
987			system_shared_libs: [],
988			stl: "none",
989			apex_available: [ "myapex" ],
990		}
991
992		cc_prebuilt_library_shared {
993			name: "my_prebuilt_platform_lib",
994			stubs: {
995				symbol_file: "my_prebuilt_platform_lib.map.txt",
996				versions: ["1", "2", "3"],
997			},
998			srcs: ["foo.so"],
999		}
1000
1001		// Similar to my_prebuilt_platform_lib, but this library only provides stubs, i.e. srcs is empty
1002		cc_prebuilt_library_shared {
1003			name: "my_prebuilt_platform_stub_only_lib",
1004			stubs: {
1005				symbol_file: "my_prebuilt_platform_stub_only_lib.map.txt",
1006				versions: ["1", "2", "3"],
1007			}
1008		}
1009
1010		rust_binary {
1011			name: "foo.rust",
1012			srcs: ["foo.rs"],
1013			shared_libs: [
1014				"libfoo.shared_from_rust",
1015				"libfoo_rs.shared_from_rust",
1016			],
1017			prefer_rlib: true,
1018			apex_available: ["myapex"],
1019		}
1020
1021		cc_library_shared {
1022			name: "libfoo.shared_from_rust",
1023			srcs: ["mylib.cpp"],
1024			system_shared_libs: [],
1025			stl: "none",
1026			stubs: {
1027				versions: ["10", "11", "12"],
1028			},
1029		}
1030
1031		rust_ffi {
1032			name: "libfoo_rs.shared_from_rust",
1033			crate_name: "foo_rs",
1034			srcs: ["mylib.rs"],
1035			stubs: {
1036				versions: ["10", "11", "12"],
1037			},
1038		}
1039
1040	`)
1041
1042	apexRule := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Rule("apexRule")
1043	copyCmds := apexRule.Args["copy_commands"]
1044
1045	// Ensure that direct non-stubs dep is always included
1046	ensureContains(t, copyCmds, "image.apex/lib64/mylib.so")
1047
1048	// Ensure that indirect stubs dep is not included
1049	ensureNotContains(t, copyCmds, "image.apex/lib64/mylib2.so")
1050	ensureNotContains(t, copyCmds, "image.apex/lib64/libmylib2_rs.so")
1051
1052	// Ensure that direct stubs dep is included
1053	ensureContains(t, copyCmds, "image.apex/lib64/mylib3.so")
1054	ensureContains(t, copyCmds, "image.apex/lib64/libmylib3_rs.so")
1055
1056	mylibLdFlags := ctx.ModuleForTests(t, "mylib", "android_arm64_armv8-a_shared_apex10000").Rule("ld").Args["libFlags"]
1057
1058	// Ensure that mylib is linking with the latest version of stubs for mylib2
1059	ensureContains(t, mylibLdFlags, "mylib2/android_arm64_armv8-a_shared_current/mylib2.so")
1060	ensureContains(t, mylibLdFlags, "libmylib2_rs/android_arm64_armv8-a_shared_current/unstripped/libmylib2_rs.so")
1061	// ... and not linking to the non-stub (impl) variant of mylib2
1062	ensureNotContains(t, mylibLdFlags, "mylib2/android_arm64_armv8-a_shared/mylib2.so")
1063	ensureNotContains(t, mylibLdFlags, "libmylib2_rs/android_arm64_armv8-a_shared/unstripped/libmylib2_rs.so")
1064
1065	// Ensure that mylib is linking with the non-stub (impl) of mylib3 (because the dependency is added with mylib3#impl)
1066	ensureContains(t, mylibLdFlags, "mylib3/android_arm64_armv8-a_shared_apex10000/mylib3.so")
1067	ensureContains(t, mylibLdFlags, "libmylib3_rs/android_arm64_armv8-a_shared_apex10000/unstripped/libmylib3_rs.so")
1068	// .. and not linking to the stubs variant of mylib3
1069	ensureNotContains(t, mylibLdFlags, "mylib3/android_arm64_armv8-a_shared_12/mylib3.so")
1070	ensureNotContains(t, mylibLdFlags, "libmylib3_rs/android_arm64_armv8-a_shared_12/unstripped/mylib3.so")
1071
1072	// Comment out this test. Now it fails after the optimization of sharing "cflags" in cc/cc.go
1073	// is replaced by sharing of "cFlags" in cc/builder.go.
1074	// The "cflags" contains "-include mylib.h", but cFlags contained only a reference to the
1075	// module variable representing "cflags". So it was not detected by ensureNotContains.
1076	// Now "cFlags" is a reference to a module variable like $flags1, which includes all previous
1077	// content of "cflags". ModuleForTests...Args["cFlags"] returns the full string of $flags1,
1078	// including the original cflags's "-include mylib.h".
1079	//
1080	// Ensure that stubs libs are built without -include flags
1081	// mylib2Cflags := ctx.ModuleForTests(t, "mylib2", "android_arm64_armv8-a_static").Rule("cc").Args["cFlags"]
1082	// ensureNotContains(t, mylib2Cflags, "-include ")
1083
1084	// Ensure that genstub for platform-provided lib is invoked with --systemapi
1085	ensureContains(t, ctx.ModuleForTests(t, "mylib2", "android_arm64_armv8-a_shared_3").Rule("genStubSrc").Args["flags"], "--systemapi")
1086	ensureContains(t, ctx.ModuleForTests(t, "libmylib2_rs", "android_arm64_armv8-a_shared_3").Rule("genStubSrc").Args["flags"], "--systemapi")
1087	// Ensure that genstub for apex-provided lib is invoked with --apex
1088	ensureContains(t, ctx.ModuleForTests(t, "mylib3", "android_arm64_armv8-a_shared_12").Rule("genStubSrc").Args["flags"], "--apex")
1089	ensureContains(t, ctx.ModuleForTests(t, "libmylib3_rs", "android_arm64_armv8-a_shared_12").Rule("genStubSrc").Args["flags"], "--apex")
1090
1091	ensureExactContents(t, ctx, "myapex", "android_common_myapex", []string{
1092		"lib64/mylib.so",
1093		"lib64/mylib3.so",
1094		"lib64/libmylib3_rs.so",
1095		"lib64/mylib4.so",
1096		"lib64/mylib4.from_rust.so",
1097		"bin/foo.rust",
1098
1099		"lib64/libstd.dylib.so", // implicit rust ffi dep
1100	})
1101
1102	// Ensure that stub dependency from a rust module is not included
1103	ensureNotContains(t, copyCmds, "image.apex/lib64/libfoo.shared_from_rust.so")
1104	ensureNotContains(t, copyCmds, "image.apex/lib64/libfoo_rs.shared_from_rust.so")
1105	// The rust module is linked to the stub cc library
1106	rustDeps := ctx.ModuleForTests(t, "foo.rust", "android_arm64_armv8-a_apex10000").Rule("rustc").Args["linkFlags"]
1107	ensureContains(t, rustDeps, "libfoo.shared_from_rust/android_arm64_armv8-a_shared_current/libfoo.shared_from_rust.so")
1108	ensureContains(t, rustDeps, "libfoo_rs.shared_from_rust/android_arm64_armv8-a_shared_current/unstripped/libfoo_rs.shared_from_rust.so")
1109	ensureNotContains(t, rustDeps, "libfoo.shared_from_rust/android_arm64_armv8-a_shared/libfoo.shared_from_rust.so")
1110	ensureNotContains(t, rustDeps, "libfoo_rs.shared_from_rust/android_arm64_armv8-a_shared/unstripped/libfoo_rs.shared_from_rust.so")
1111
1112	apexManifestRule := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Rule("apexManifestRule")
1113	ensureListContains(t, names(apexManifestRule.Args["requireNativeLibs"]), "libfoo.shared_from_rust.so")
1114	ensureListContains(t, names(apexManifestRule.Args["requireNativeLibs"]), "libfoo_rs.shared_from_rust.so")
1115
1116	// Ensure that mylib is linking with the latest version of stubs for my_prebuilt_platform_lib
1117	ensureContains(t, mylibLdFlags, "my_prebuilt_platform_lib/android_arm64_armv8-a_shared_current/my_prebuilt_platform_lib.so")
1118	// ... and not linking to the non-stub (impl) variant of my_prebuilt_platform_lib
1119	ensureNotContains(t, mylibLdFlags, "my_prebuilt_platform_lib/android_arm64_armv8-a_shared/my_prebuilt_platform_lib.so")
1120	// Ensure that genstub for platform-provided lib is invoked with --systemapi
1121	ensureContains(t, ctx.ModuleForTests(t, "my_prebuilt_platform_lib", "android_arm64_armv8-a_shared_3").Rule("genStubSrc").Args["flags"], "--systemapi")
1122
1123	// Ensure that mylib is linking with the latest version of stubs for my_prebuilt_platform_lib
1124	ensureContains(t, mylibLdFlags, "my_prebuilt_platform_stub_only_lib/android_arm64_armv8-a_shared_current/my_prebuilt_platform_stub_only_lib.so")
1125	// ... and not linking to the non-stub (impl) variant of my_prebuilt_platform_lib
1126	ensureNotContains(t, mylibLdFlags, "my_prebuilt_platform_stub_only_lib/android_arm64_armv8-a_shared/my_prebuilt_platform_stub_only_lib.so")
1127	// Ensure that genstub for platform-provided lib is invoked with --systemapi
1128	ensureContains(t, ctx.ModuleForTests(t, "my_prebuilt_platform_stub_only_lib", "android_arm64_armv8-a_shared_3").Rule("genStubSrc").Args["flags"], "--systemapi")
1129}
1130
1131func TestApexShouldNotEmbedStubVariant(t *testing.T) {
1132	t.Parallel()
1133	testApexError(t, `module "myapex" .*: native_shared_libs: "libbar" is a stub`, `
1134		apex {
1135			name: "myapex",
1136			key: "myapex.key",
1137			vendor: true,
1138			updatable: false,
1139			native_shared_libs: ["libbar"], // should not add an LLNDK stub in a vendor apex
1140		}
1141
1142		apex_key {
1143			name: "myapex.key",
1144			public_key: "testkey.avbpubkey",
1145			private_key: "testkey.pem",
1146		}
1147
1148		cc_library {
1149			name: "libbar",
1150			srcs: ["mylib.cpp"],
1151			llndk: {
1152				symbol_file: "libbar.map.txt",
1153			}
1154		}
1155	`)
1156}
1157
1158func TestApexCanUsePrivateApis(t *testing.T) {
1159	t.Parallel()
1160	ctx := testApex(t, `
1161		apex {
1162			name: "myapex",
1163			key: "myapex.key",
1164			native_shared_libs: ["mylib"],
1165			binaries: ["foo.rust"],
1166			updatable: false,
1167			platform_apis: true,
1168		}
1169
1170		apex_key {
1171			name: "myapex.key",
1172			public_key: "testkey.avbpubkey",
1173			private_key: "testkey.pem",
1174		}
1175
1176		cc_library {
1177			name: "mylib",
1178			srcs: ["mylib.cpp"],
1179			shared_libs: [
1180				"mylib2",
1181				"libmylib2_rust"
1182			],
1183			system_shared_libs: [],
1184			stl: "none",
1185			apex_available: [ "myapex" ],
1186		}
1187
1188		cc_library {
1189			name: "mylib2",
1190			srcs: ["mylib.cpp"],
1191			cflags: ["-include mylib.h"],
1192			system_shared_libs: [],
1193			stl: "none",
1194			stubs: {
1195				versions: ["1", "2", "3"],
1196			},
1197		}
1198
1199		rust_ffi {
1200			name: "libmylib2_rust",
1201			crate_name: "mylib2_rust",
1202			srcs: ["mylib.rs"],
1203			stubs: {
1204				versions: ["1", "2", "3"],
1205			},
1206		}
1207
1208		rust_binary {
1209			name: "foo.rust",
1210			srcs: ["foo.rs"],
1211			shared_libs: [
1212				"libfoo.shared_from_rust",
1213				"libmylib_rust.shared_from_rust"
1214			],
1215			prefer_rlib: true,
1216			apex_available: ["myapex"],
1217		}
1218
1219		cc_library_shared {
1220			name: "libfoo.shared_from_rust",
1221			srcs: ["mylib.cpp"],
1222			system_shared_libs: [],
1223			stl: "none",
1224			stubs: {
1225				versions: ["10", "11", "12"],
1226			},
1227		}
1228		rust_ffi {
1229			name: "libmylib_rust.shared_from_rust",
1230			crate_name: "mylib_rust",
1231			srcs: ["mylib.rs"],
1232			stubs: {
1233				versions: ["1", "2", "3"],
1234			},
1235		}
1236
1237	`)
1238
1239	apexRule := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Rule("apexRule")
1240	copyCmds := apexRule.Args["copy_commands"]
1241
1242	// Ensure that indirect stubs dep is not included
1243	ensureNotContains(t, copyCmds, "image.apex/lib64/mylib2.so")
1244	ensureNotContains(t, copyCmds, "image.apex/lib64/libmylib_rust.so")
1245	ensureNotContains(t, copyCmds, "image.apex/lib64/libmylib_rust.shared_from_rust.so")
1246	ensureNotContains(t, copyCmds, "image.apex/lib64/libfoo.shared_from_rust.so")
1247
1248	// Ensure that we are using non-stub variants of mylib2 and libfoo.shared_from_rust (because
1249	// of the platform_apis: true)
1250	mylibLdFlags := ctx.ModuleForTests(t, "mylib", "android_arm64_armv8-a_shared_apex10000_p").Rule("ld").Args["libFlags"]
1251	ensureNotContains(t, mylibLdFlags, "mylib2/android_arm64_armv8-a_shared_current/mylib2.so")
1252	ensureContains(t, mylibLdFlags, "mylib2/android_arm64_armv8-a_shared/mylib2.so")
1253	ensureNotContains(t, mylibLdFlags, "libmylib2_rust/android_arm64_armv8-a_shared_current/unstripped/libmylib2_rust.so")
1254	ensureContains(t, mylibLdFlags, "libmylib2_rust/android_arm64_armv8-a_shared/unstripped/libmylib2_rust.so")
1255	rustDeps := ctx.ModuleForTests(t, "foo.rust", "android_arm64_armv8-a_apex10000_p").Rule("rustc").Args["linkFlags"]
1256	ensureNotContains(t, rustDeps, "libfoo.shared_from_rust/android_arm64_armv8-a_shared_current/libfoo.shared_from_rust.so")
1257	ensureContains(t, rustDeps, "libfoo.shared_from_rust/android_arm64_armv8-a_shared/libfoo.shared_from_rust.so")
1258	ensureNotContains(t, rustDeps, "libmylib_rust.shared_from_rust/android_arm64_armv8-a_shared_current/unstripped/libmylib_rust.shared_from_rust.so")
1259	ensureContains(t, rustDeps, "libmylib_rust.shared_from_rust/android_arm64_armv8-a_shared/unstripped/libmylib_rust.shared_from_rust.so")
1260}
1261
1262func TestApexWithStubsWithMinSdkVersion(t *testing.T) {
1263	t.Parallel()
1264	ctx := testApex(t, `
1265		apex {
1266			name: "myapex",
1267			key: "myapex.key",
1268			native_shared_libs: [
1269				"mylib",
1270				"mylib3",
1271				"libmylib3_rust",
1272			],
1273			min_sdk_version: "29",
1274		}
1275
1276		apex_key {
1277			name: "myapex.key",
1278			public_key: "testkey.avbpubkey",
1279			private_key: "testkey.pem",
1280		}
1281
1282		cc_library {
1283			name: "mylib",
1284			srcs: ["mylib.cpp"],
1285			shared_libs: [
1286				"mylib2",
1287				"mylib3#impl",
1288				"libmylib2_rust",
1289				"libmylib3_rust#impl",
1290			],
1291			system_shared_libs: [],
1292			stl: "none",
1293			apex_available: [ "myapex" ],
1294			min_sdk_version: "28",
1295		}
1296
1297		cc_library {
1298			name: "mylib2",
1299			srcs: ["mylib.cpp"],
1300			cflags: ["-include mylib.h"],
1301			system_shared_libs: [],
1302			stl: "none",
1303			stubs: {
1304				symbol_file: "mylib2.map.txt",
1305				versions: ["28", "29", "30", "current"],
1306			},
1307			min_sdk_version: "28",
1308		}
1309
1310		rust_ffi {
1311			name: "libmylib2_rust",
1312			crate_name: "mylib2_rust",
1313			srcs: ["mylib.rs"],
1314			stubs: {
1315				symbol_file: "mylib2.map.txt",
1316				versions: ["28", "29", "30", "current"],
1317			},
1318			min_sdk_version: "28",
1319		}
1320
1321		cc_library {
1322			name: "mylib3",
1323			srcs: ["mylib.cpp"],
1324			shared_libs: ["mylib4"],
1325			system_shared_libs: [],
1326			stl: "none",
1327			stubs: {
1328				symbol_file: "mylib3.map.txt",
1329				versions: ["28", "29", "30", "current"],
1330			},
1331			apex_available: [ "myapex" ],
1332			min_sdk_version: "28",
1333		}
1334
1335		rust_ffi {
1336			name: "libmylib3_rust",
1337			crate_name: "mylib3_rust",
1338			srcs: ["mylib.rs"],
1339			shared_libs: ["libmylib4.from_rust"],
1340			stubs: {
1341				symbol_file: "mylib3.map.txt",
1342				versions: ["28", "29", "30", "current"],
1343			},
1344			apex_available: [ "myapex" ],
1345			min_sdk_version: "28",
1346		}
1347
1348		cc_library {
1349			name: "mylib4",
1350			srcs: ["mylib.cpp"],
1351			system_shared_libs: [],
1352			stl: "none",
1353			apex_available: [ "myapex" ],
1354			min_sdk_version: "28",
1355		}
1356
1357		rust_ffi {
1358			name: "libmylib4.from_rust",
1359			crate_name: "mylib4",
1360			srcs: ["mylib.rs"],
1361			apex_available: [ "myapex" ],
1362			min_sdk_version: "28",
1363		}
1364	`)
1365
1366	apexRule := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Rule("apexRule")
1367	copyCmds := apexRule.Args["copy_commands"]
1368
1369	// Ensure that direct non-stubs dep is always included
1370	ensureContains(t, copyCmds, "image.apex/lib64/mylib.so")
1371	ensureContains(t, copyCmds, "image.apex/lib64/mylib3.so")
1372	ensureContains(t, copyCmds, "image.apex/lib64/libmylib3_rust.so")
1373
1374	// Ensure that indirect stubs dep is not included
1375	ensureNotContains(t, copyCmds, "image.apex/lib64/mylib2.so")
1376	ensureNotContains(t, copyCmds, "image.apex/lib64/libmylib2_rust.so")
1377
1378	// Ensure that direct stubs dep is included
1379	ensureContains(t, copyCmds, "image.apex/lib64/mylib3.so")
1380
1381	mylibLdFlags := ctx.ModuleForTests(t, "mylib", "android_arm64_armv8-a_shared_apex29").Rule("ld").Args["libFlags"]
1382
1383	// Ensure that mylib is linking with the latest version of stub for mylib2
1384	ensureContains(t, mylibLdFlags, "mylib2/android_arm64_armv8-a_shared_current/mylib2.so")
1385	ensureContains(t, mylibLdFlags, "libmylib2_rust/android_arm64_armv8-a_shared_current/unstripped/libmylib2_rust.so")
1386	// ... and not linking to the non-stub (impl) variant of mylib2
1387	ensureNotContains(t, mylibLdFlags, "mylib2/android_arm64_armv8-a_shared/mylib2.so")
1388	ensureNotContains(t, mylibLdFlags, "libmylib2_rust/android_arm64_armv8-a_shared/unstripped/libmylib2_rust.so")
1389
1390	// Ensure that mylib is linking with the non-stub (impl) of mylib3 (because the dependency is added with mylib3#impl)
1391	ensureContains(t, mylibLdFlags, "mylib3/android_arm64_armv8-a_shared_apex29/mylib3.so")
1392	ensureContains(t, mylibLdFlags, "libmylib3_rust/android_arm64_armv8-a_shared_apex29/unstripped/libmylib3_rust.so")
1393	// .. and not linking to the stubs variant of mylib3
1394	ensureNotContains(t, mylibLdFlags, "mylib3/android_arm64_armv8-a_shared_29/mylib3.so")
1395	ensureNotContains(t, mylibLdFlags, "libmylib3_rust/android_arm64_armv8-a_shared_29/unstripped/libmylib3_rust.so")
1396
1397	// Ensure that stubs libs are built without -include flags
1398	mylib2Cflags := ctx.ModuleForTests(t, "mylib2", "android_arm64_armv8-a_shared_29").Rule("cc").Args["cFlags"]
1399	ensureNotContains(t, mylib2Cflags, "-include ")
1400
1401	// Ensure that genstub is invoked with --systemapi
1402	ensureContains(t, ctx.ModuleForTests(t, "mylib2", "android_arm64_armv8-a_shared_29").Rule("genStubSrc").Args["flags"], "--systemapi")
1403	ensureContains(t, ctx.ModuleForTests(t, "libmylib2_rust", "android_arm64_armv8-a_shared_29").Rule("cc.genStubSrc").Args["flags"], "--systemapi")
1404
1405	ensureExactContents(t, ctx, "myapex", "android_common_myapex", []string{
1406		"lib64/mylib.so",
1407		"lib64/mylib3.so",
1408		"lib64/libmylib3_rust.so",
1409		"lib64/mylib4.so",
1410		"lib64/libmylib4.from_rust.so",
1411
1412		"lib64/libstd.dylib.so", // by the implicit dependency from foo.rust
1413	})
1414}
1415
1416func TestApex_PlatformUsesLatestStubFromApex(t *testing.T) {
1417	t.Parallel()
1418	//   myapex (Z)
1419	//      mylib -----------------.
1420	//                             |
1421	//   otherapex (29)            |
1422	//      libstub's versions: 29 Z current
1423	//                                  |
1424	//   <platform>                     |
1425	//      libplatform ----------------'
1426	ctx := testApex(t, `
1427		apex {
1428			name: "myapex",
1429			key: "myapex.key",
1430			native_shared_libs: ["mylib"],
1431			min_sdk_version: "Z", // non-final
1432		}
1433
1434		cc_library {
1435			name: "mylib",
1436			srcs: ["mylib.cpp"],
1437			shared_libs: [
1438				"libstub",
1439				"libstub_rust",
1440			],
1441			apex_available: ["myapex"],
1442			min_sdk_version: "Z",
1443		}
1444
1445		apex_key {
1446			name: "myapex.key",
1447			public_key: "testkey.avbpubkey",
1448			private_key: "testkey.pem",
1449		}
1450
1451		apex {
1452			name: "otherapex",
1453			key: "myapex.key",
1454			native_shared_libs: [
1455				"libstub",
1456				"libstub_rust",
1457			],
1458			min_sdk_version: "29",
1459		}
1460
1461		cc_library {
1462			name: "libstub",
1463			srcs: ["mylib.cpp"],
1464			stubs: {
1465				versions: ["29", "Z", "current"],
1466			},
1467			apex_available: ["otherapex"],
1468			min_sdk_version: "29",
1469		}
1470
1471		rust_ffi {
1472			name: "libstub_rust",
1473			crate_name: "stub_rust",
1474			srcs: ["mylib.rs"],
1475			stubs: {
1476				versions: ["29", "Z", "current"],
1477			},
1478			apex_available: ["otherapex"],
1479			min_sdk_version: "29",
1480		}
1481
1482		// platform module depending on libstub from otherapex should use the latest stub("current")
1483		cc_library {
1484			name: "libplatform",
1485			srcs: ["mylib.cpp"],
1486			shared_libs: [
1487				"libstub",
1488				"libstub_rust",
1489			],
1490		}
1491	`,
1492		android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
1493			variables.Platform_sdk_codename = proptools.StringPtr("Z")
1494			variables.Platform_sdk_final = proptools.BoolPtr(false)
1495			variables.Platform_version_active_codenames = []string{"Z"}
1496		}),
1497	)
1498
1499	// Ensure that mylib from myapex is built against the latest stub (current)
1500	mylibCflags := ctx.ModuleForTests(t, "mylib", "android_arm64_armv8-a_static_apex10000").Rule("cc").Args["cFlags"]
1501	ensureContains(t, mylibCflags, "-D__LIBSTUB_API__=10000 ")
1502	// rust stubs do not emit -D__LIBFOO_API__ flags as this is deprecated behavior for cc stubs
1503
1504	mylibLdflags := ctx.ModuleForTests(t, "mylib", "android_arm64_armv8-a_shared_apex10000").Rule("ld").Args["libFlags"]
1505	ensureContains(t, mylibLdflags, "libstub/android_arm64_armv8-a_shared_current/libstub.so ")
1506	ensureContains(t, mylibLdflags, "libstub_rust/android_arm64_armv8-a_shared_current/unstripped/libstub_rust.so ")
1507
1508	// Ensure that libplatform is built against latest stub ("current") of mylib3 from the apex
1509	libplatformCflags := ctx.ModuleForTests(t, "libplatform", "android_arm64_armv8-a_static").Rule("cc").Args["cFlags"]
1510	ensureContains(t, libplatformCflags, "-D__LIBSTUB_API__=10000 ") // "current" maps to 10000
1511	// rust stubs do not emit -D__LIBFOO_API__ flags as this is deprecated behavior for cc stubs
1512
1513	libplatformLdflags := ctx.ModuleForTests(t, "libplatform", "android_arm64_armv8-a_shared").Rule("ld").Args["libFlags"]
1514	ensureContains(t, libplatformLdflags, "libstub/android_arm64_armv8-a_shared_current/libstub.so ")
1515	ensureContains(t, libplatformLdflags, "libstub_rust/android_arm64_armv8-a_shared_current/unstripped/libstub_rust.so ")
1516}
1517
1518func TestApexWithExplicitStubsDependency(t *testing.T) {
1519	t.Parallel()
1520	ctx := testApex(t, `
1521		apex {
1522			name: "myapex2",
1523			key: "myapex2.key",
1524			native_shared_libs: ["mylib"],
1525			updatable: false,
1526		}
1527
1528		apex_key {
1529			name: "myapex2.key",
1530			public_key: "testkey.avbpubkey",
1531			private_key: "testkey.pem",
1532		}
1533
1534		cc_library {
1535			name: "mylib",
1536			srcs: ["mylib.cpp"],
1537			shared_libs: [
1538				"libfoo#10",
1539				"libfoo_rust#10"
1540			],
1541			static_libs: ["libbaz"],
1542			system_shared_libs: [],
1543			stl: "none",
1544			apex_available: [ "myapex2" ],
1545		}
1546
1547		cc_library {
1548			name: "libfoo",
1549			srcs: ["mylib.cpp"],
1550			shared_libs: ["libbar"],
1551			system_shared_libs: [],
1552			stl: "none",
1553			stubs: {
1554				versions: ["10", "20", "30"],
1555			},
1556		}
1557
1558		rust_ffi {
1559			name: "libfoo_rust",
1560			crate_name: "foo_rust",
1561			srcs: ["mylib.cpp"],
1562			shared_libs: ["libbar.from_rust"],
1563			stubs: {
1564				versions: ["10", "20", "30"],
1565			},
1566		}
1567
1568		cc_library {
1569			name: "libbar",
1570			srcs: ["mylib.cpp"],
1571			system_shared_libs: [],
1572			stl: "none",
1573		}
1574
1575		cc_library {
1576			name: "libbar.from_rust",
1577			srcs: ["mylib.cpp"],
1578			system_shared_libs: [],
1579			stl: "none",
1580		}
1581
1582		cc_library_static {
1583			name: "libbaz",
1584			srcs: ["mylib.cpp"],
1585			system_shared_libs: [],
1586			stl: "none",
1587			apex_available: [ "myapex2" ],
1588		}
1589
1590	`)
1591
1592	apexRule := ctx.ModuleForTests(t, "myapex2", "android_common_myapex2").Rule("apexRule")
1593	copyCmds := apexRule.Args["copy_commands"]
1594
1595	// Ensure that direct non-stubs dep is always included
1596	ensureContains(t, copyCmds, "image.apex/lib64/mylib.so")
1597
1598	// Ensure that indirect stubs dep is not included
1599	ensureNotContains(t, copyCmds, "image.apex/lib64/libfoo.so")
1600	ensureNotContains(t, copyCmds, "image.apex/lib64/libfoo_rust.so")
1601
1602	// Ensure that dependency of stubs is not included
1603	ensureNotContains(t, copyCmds, "image.apex/lib64/libbar.so")
1604	ensureNotContains(t, copyCmds, "image.apex/lib64/libbar.from_rust.so")
1605
1606	mylibLdFlags := ctx.ModuleForTests(t, "mylib", "android_arm64_armv8-a_shared_apex10000").Rule("ld").Args["libFlags"]
1607
1608	// Ensure that mylib is linking with version 10 of libfoo
1609	ensureContains(t, mylibLdFlags, "libfoo/android_arm64_armv8-a_shared_10/libfoo.so")
1610	ensureContains(t, mylibLdFlags, "libfoo_rust/android_arm64_armv8-a_shared_10/unstripped/libfoo_rust.so")
1611	// ... and not linking to the non-stub (impl) variant of libfoo
1612	ensureNotContains(t, mylibLdFlags, "libfoo/android_arm64_armv8-a_shared/libfoo.so")
1613	ensureNotContains(t, mylibLdFlags, "libfoo_rust/android_arm64_armv8-a_shared/unstripped/libfoo_rust.so")
1614
1615	libFooStubsLdFlags := ctx.ModuleForTests(t, "libfoo", "android_arm64_armv8-a_shared_10").Rule("ld").Args["libFlags"]
1616	libFooRustStubsLdFlags := ctx.ModuleForTests(t, "libfoo_rust", "android_arm64_armv8-a_shared_10").Rule("ld").Args["libFlags"]
1617
1618	// Ensure that libfoo stubs is not linking to libbar (since it is a stubs)
1619	ensureNotContains(t, libFooStubsLdFlags, "libbar.so")
1620	ensureNotContains(t, libFooRustStubsLdFlags, "libbar.from_rust.so")
1621
1622	fullDepsInfo := strings.Split(android.ContentFromFileRuleForTests(t, ctx,
1623		ctx.ModuleForTests(t, "myapex2", "android_common_myapex2").Output("depsinfo/fulllist.txt")), "\n")
1624	ensureListContains(t, fullDepsInfo, "  libfoo(minSdkVersion:(no version)) (external) <- mylib")
1625
1626	flatDepsInfo := strings.Split(android.ContentFromFileRuleForTests(t, ctx,
1627		ctx.ModuleForTests(t, "myapex2", "android_common_myapex2").Output("depsinfo/flatlist.txt")), "\n")
1628	ensureListContains(t, flatDepsInfo, "libfoo(minSdkVersion:(no version)) (external)")
1629}
1630
1631func TestApexWithRuntimeLibsDependency(t *testing.T) {
1632	t.Parallel()
1633	/*
1634		myapex
1635		  |
1636		  v   (runtime_libs)
1637		mylib ------+------> libfoo [provides stub]
1638			    |
1639			    `------> libbar
1640	*/
1641	ctx := testApex(t, `
1642		apex {
1643			name: "myapex",
1644			key: "myapex.key",
1645			native_shared_libs: ["mylib"],
1646			updatable: false,
1647		}
1648
1649		apex_key {
1650			name: "myapex.key",
1651			public_key: "testkey.avbpubkey",
1652			private_key: "testkey.pem",
1653		}
1654
1655		cc_library {
1656			name: "mylib",
1657			srcs: ["mylib.cpp"],
1658			static_libs: ["libstatic"],
1659			shared_libs: ["libshared"],
1660			runtime_libs: [
1661				"libfoo",
1662				"libbar",
1663				"libfoo_rs",
1664			],
1665			system_shared_libs: [],
1666			stl: "none",
1667			apex_available: [ "myapex" ],
1668		}
1669
1670		cc_library {
1671			name: "libfoo",
1672			srcs: ["mylib.cpp"],
1673			system_shared_libs: [],
1674			stl: "none",
1675			stubs: {
1676				versions: ["10", "20", "30"],
1677			},
1678		}
1679
1680		rust_ffi {
1681			name: "libfoo_rs",
1682			crate_name: "foo_rs",
1683			srcs: ["mylib.rs"],
1684			stubs: {
1685				versions: ["10", "20", "30"],
1686			},
1687		}
1688
1689		cc_library {
1690			name: "libbar",
1691			srcs: ["mylib.cpp"],
1692			system_shared_libs: [],
1693			stl: "none",
1694			apex_available: [ "myapex" ],
1695		}
1696
1697		cc_library {
1698			name: "libstatic",
1699			srcs: ["mylib.cpp"],
1700			system_shared_libs: [],
1701			stl: "none",
1702			apex_available: [ "myapex" ],
1703			runtime_libs: ["libstatic_to_runtime"],
1704		}
1705
1706		cc_library {
1707			name: "libshared",
1708			srcs: ["mylib.cpp"],
1709			system_shared_libs: [],
1710			stl: "none",
1711			apex_available: [ "myapex" ],
1712			runtime_libs: ["libshared_to_runtime"],
1713		}
1714
1715		cc_library {
1716			name: "libstatic_to_runtime",
1717			srcs: ["mylib.cpp"],
1718			system_shared_libs: [],
1719			stl: "none",
1720			apex_available: [ "myapex" ],
1721		}
1722
1723		cc_library {
1724			name: "libshared_to_runtime",
1725			srcs: ["mylib.cpp"],
1726			system_shared_libs: [],
1727			stl: "none",
1728			apex_available: [ "myapex" ],
1729		}
1730	`)
1731
1732	apexRule := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Rule("apexRule")
1733	copyCmds := apexRule.Args["copy_commands"]
1734
1735	// Ensure that direct non-stubs dep is always included
1736	ensureContains(t, copyCmds, "image.apex/lib64/mylib.so")
1737
1738	// Ensure that indirect stubs dep is not included
1739	ensureNotContains(t, copyCmds, "image.apex/lib64/libfoo.so")
1740	ensureNotContains(t, copyCmds, "image.apex/lib64/libfoo_rs.so")
1741
1742	// Ensure that runtime_libs dep in included
1743	ensureContains(t, copyCmds, "image.apex/lib64/libbar.so")
1744	ensureContains(t, copyCmds, "image.apex/lib64/libshared.so")
1745	ensureContains(t, copyCmds, "image.apex/lib64/libshared_to_runtime.so")
1746
1747	ensureNotContains(t, copyCmds, "image.apex/lib64/libstatic_to_runtime.so")
1748
1749	apexManifestRule := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Rule("apexManifestRule")
1750	ensureListEmpty(t, names(apexManifestRule.Args["provideNativeLibs"]))
1751	ensureListContains(t, names(apexManifestRule.Args["requireNativeLibs"]), "libfoo.so")
1752	ensureListContains(t, names(apexManifestRule.Args["requireNativeLibs"]), "libfoo_rs.so")
1753}
1754
1755var prepareForTestOfRuntimeApexWithHwasan = android.GroupFixturePreparers(
1756	cc.PrepareForTestWithCcBuildComponents,
1757	PrepareForTestWithApexBuildComponents,
1758	android.FixtureAddTextFile("bionic/apex/Android.bp", `
1759		apex {
1760			name: "com.android.runtime",
1761			key: "com.android.runtime.key",
1762			native_shared_libs: ["libc"],
1763			updatable: false,
1764		}
1765
1766		apex_key {
1767			name: "com.android.runtime.key",
1768			public_key: "testkey.avbpubkey",
1769			private_key: "testkey.pem",
1770		}
1771	`),
1772	android.FixtureAddFile("system/sepolicy/apex/com.android.runtime-file_contexts", nil),
1773)
1774
1775func TestRuntimeApexShouldInstallHwasanIfLibcDependsOnIt(t *testing.T) {
1776	t.Parallel()
1777	result := android.GroupFixturePreparers(prepareForTestOfRuntimeApexWithHwasan).RunTestWithBp(t, `
1778		cc_library {
1779			name: "libc",
1780			no_libcrt: true,
1781			nocrt: true,
1782			no_crt_pad_segment: true,
1783			stl: "none",
1784			system_shared_libs: [],
1785			stubs: { versions: ["1"] },
1786			apex_available: ["com.android.runtime"],
1787
1788			sanitize: {
1789				hwaddress: true,
1790			}
1791		}
1792
1793		cc_prebuilt_library_shared {
1794			name: "libclang_rt.hwasan",
1795			no_libcrt: true,
1796			nocrt: true,
1797			no_crt_pad_segment: true,
1798			stl: "none",
1799			system_shared_libs: [],
1800			srcs: [""],
1801			stubs: { versions: ["1"] },
1802			stem: "libclang_rt.hwasan-aarch64-android",
1803
1804			sanitize: {
1805				never: true,
1806			},
1807			apex_available: [
1808				"//apex_available:anyapex",
1809				"//apex_available:platform",
1810			],
1811		}	`)
1812	ctx := result.TestContext
1813
1814	ensureExactContents(t, ctx, "com.android.runtime", "android_common_hwasan_com.android.runtime", []string{
1815		"lib64/bionic/libc.so",
1816		"lib64/bionic/libclang_rt.hwasan-aarch64-android.so",
1817	})
1818
1819	hwasan := ctx.ModuleForTests(t, "libclang_rt.hwasan", "android_arm64_armv8-a_shared")
1820
1821	installed := hwasan.Description("install libclang_rt.hwasan")
1822	ensureContains(t, installed.Output.String(), "/system/lib64/bootstrap/libclang_rt.hwasan-aarch64-android.so")
1823
1824	symlink := hwasan.Description("install symlink libclang_rt.hwasan")
1825	ensureEquals(t, symlink.Args["fromPath"], "/apex/com.android.runtime/lib64/bionic/libclang_rt.hwasan-aarch64-android.so")
1826	ensureContains(t, symlink.Output.String(), "/system/lib64/libclang_rt.hwasan-aarch64-android.so")
1827}
1828
1829func TestRuntimeApexShouldInstallHwasanIfHwaddressSanitized(t *testing.T) {
1830	t.Parallel()
1831	result := android.GroupFixturePreparers(
1832		prepareForTestOfRuntimeApexWithHwasan,
1833		android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
1834			variables.SanitizeDevice = []string{"hwaddress"}
1835		}),
1836	).RunTestWithBp(t, `
1837		cc_library {
1838			name: "libc",
1839			no_libcrt: true,
1840			nocrt: true,
1841			no_crt_pad_segment: true,
1842			stl: "none",
1843			system_shared_libs: [],
1844			stubs: { versions: ["1"] },
1845			apex_available: ["com.android.runtime"],
1846		}
1847
1848		cc_prebuilt_library_shared {
1849			name: "libclang_rt.hwasan",
1850			no_libcrt: true,
1851			nocrt: true,
1852			no_crt_pad_segment: true,
1853			stl: "none",
1854			system_shared_libs: [],
1855			srcs: [""],
1856			stubs: { versions: ["1"] },
1857			stem: "libclang_rt.hwasan-aarch64-android",
1858
1859			sanitize: {
1860				never: true,
1861			},
1862			apex_available: [
1863				"//apex_available:anyapex",
1864				"//apex_available:platform",
1865			],
1866		}
1867		`)
1868	ctx := result.TestContext
1869
1870	ensureExactContents(t, ctx, "com.android.runtime", "android_common_hwasan_com.android.runtime", []string{
1871		"lib64/bionic/libc.so",
1872		"lib64/bionic/libclang_rt.hwasan-aarch64-android.so",
1873	})
1874
1875	hwasan := ctx.ModuleForTests(t, "libclang_rt.hwasan", "android_arm64_armv8-a_shared")
1876
1877	installed := hwasan.Description("install libclang_rt.hwasan")
1878	ensureContains(t, installed.Output.String(), "/system/lib64/bootstrap/libclang_rt.hwasan-aarch64-android.so")
1879
1880	symlink := hwasan.Description("install symlink libclang_rt.hwasan")
1881	ensureEquals(t, symlink.Args["fromPath"], "/apex/com.android.runtime/lib64/bionic/libclang_rt.hwasan-aarch64-android.so")
1882	ensureContains(t, symlink.Output.String(), "/system/lib64/libclang_rt.hwasan-aarch64-android.so")
1883}
1884
1885func TestApexDependsOnLLNDKTransitively(t *testing.T) {
1886	t.Parallel()
1887	testcases := []struct {
1888		name          string
1889		minSdkVersion string
1890		apexVariant   string
1891		shouldLink    string
1892		shouldNotLink []string
1893	}{
1894		{
1895			name:          "unspecified version links to the latest",
1896			minSdkVersion: "",
1897			apexVariant:   "apex10000",
1898			shouldLink:    "current",
1899			shouldNotLink: []string{"29", "30"},
1900		},
1901		{
1902			name:          "always use the latest",
1903			minSdkVersion: "min_sdk_version: \"29\",",
1904			apexVariant:   "apex29",
1905			shouldLink:    "current",
1906			shouldNotLink: []string{"29", "30"},
1907		},
1908	}
1909	for _, tc := range testcases {
1910		t.Run(tc.name, func(t *testing.T) {
1911			t.Parallel()
1912			ctx := testApex(t, `
1913			apex {
1914				name: "myapex",
1915				key: "myapex.key",
1916				native_shared_libs: ["mylib"],
1917				updatable: false,
1918				`+tc.minSdkVersion+`
1919			}
1920
1921			apex_key {
1922				name: "myapex.key",
1923				public_key: "testkey.avbpubkey",
1924				private_key: "testkey.pem",
1925			}
1926
1927			cc_library {
1928				name: "mylib",
1929				srcs: ["mylib.cpp"],
1930				vendor_available: true,
1931				shared_libs: ["libbar"],
1932				system_shared_libs: [],
1933				stl: "none",
1934				apex_available: [ "myapex" ],
1935				min_sdk_version: "29",
1936			}
1937
1938			cc_library {
1939				name: "libbar",
1940				srcs: ["mylib.cpp"],
1941				system_shared_libs: [],
1942				stl: "none",
1943				stubs: { versions: ["29","30"] },
1944				llndk: {
1945					symbol_file: "libbar.map.txt",
1946				}
1947			}
1948			`,
1949				withUnbundledBuild,
1950			)
1951
1952			// Ensure that LLNDK dep is not included
1953			ensureExactContents(t, ctx, "myapex", "android_common_myapex", []string{
1954				"lib64/mylib.so",
1955			})
1956
1957			// Ensure that LLNDK dep is required
1958			apexManifestRule := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Rule("apexManifestRule")
1959			ensureListEmpty(t, names(apexManifestRule.Args["provideNativeLibs"]))
1960			ensureListContains(t, names(apexManifestRule.Args["requireNativeLibs"]), "libbar.so")
1961
1962			mylibLdFlags := ctx.ModuleForTests(t, "mylib", "android_arm64_armv8-a_shared_"+tc.apexVariant).Rule("ld").Args["libFlags"]
1963			ensureContains(t, mylibLdFlags, "libbar/android_arm64_armv8-a_shared_"+tc.shouldLink+"/libbar.so")
1964			for _, ver := range tc.shouldNotLink {
1965				ensureNotContains(t, mylibLdFlags, "libbar/android_arm64_armv8-a_shared_"+ver+"/libbar.so")
1966			}
1967
1968			mylibCFlags := ctx.ModuleForTests(t, "mylib", "android_arm64_armv8-a_static_"+tc.apexVariant).Rule("cc").Args["cFlags"]
1969			ver := tc.shouldLink
1970			if tc.shouldLink == "current" {
1971				ver = strconv.Itoa(android.FutureApiLevelInt)
1972			}
1973			ensureContains(t, mylibCFlags, "__LIBBAR_API__="+ver)
1974		})
1975	}
1976}
1977
1978func TestApexWithSystemLibsStubs(t *testing.T) {
1979	t.Parallel()
1980	ctx := testApex(t, `
1981		apex {
1982			name: "myapex",
1983			key: "myapex.key",
1984			native_shared_libs: ["mylib", "mylib_shared", "libdl", "libm", "libmylib_rs"],
1985			updatable: false,
1986		}
1987
1988		apex_key {
1989			name: "myapex.key",
1990			public_key: "testkey.avbpubkey",
1991			private_key: "testkey.pem",
1992		}
1993
1994		cc_library {
1995			name: "mylib",
1996			srcs: ["mylib.cpp"],
1997			system_shared_libs: ["libc"],
1998			shared_libs: ["libdl#27", "libm#impl"],
1999			stl: "none",
2000			apex_available: [ "myapex" ],
2001		}
2002
2003		rust_ffi {
2004			name: "libmylib_rs",
2005			crate_name: "mylib_rs",
2006			shared_libs: ["libvers#27", "libm#impl"],
2007			srcs: ["mylib.rs"],
2008			apex_available: [ "myapex" ],
2009		}
2010
2011		cc_library_shared {
2012			name: "mylib_shared",
2013			srcs: ["mylib.cpp"],
2014			shared_libs: ["libdl#27"],
2015			stl: "none",
2016			apex_available: [ "myapex" ],
2017		}
2018
2019		cc_library {
2020			name: "libBootstrap",
2021			srcs: ["mylib.cpp"],
2022			stl: "none",
2023			bootstrap: true,
2024		}
2025
2026		rust_ffi {
2027			name: "libbootstrap_rs",
2028			srcs: ["mylib.cpp"],
2029			crate_name: "bootstrap_rs",
2030			bootstrap: true,
2031		}
2032
2033		cc_library {
2034			name: "libvers",
2035			srcs: ["mylib.cpp"],
2036			stl: "none",
2037			stubs: { versions: ["27","30"] },
2038		}
2039	`)
2040
2041	apexRule := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Rule("apexRule")
2042	copyCmds := apexRule.Args["copy_commands"]
2043
2044	// Ensure that mylib, libmylib_rs, libm, libdl, libstd.dylib.so (from Rust) are included.
2045	ensureContains(t, copyCmds, "image.apex/lib64/mylib.so")
2046	ensureContains(t, copyCmds, "image.apex/lib64/libmylib_rs.so")
2047	ensureContains(t, copyCmds, "image.apex/lib64/bionic/libm.so")
2048	ensureContains(t, copyCmds, "image.apex/lib64/bionic/libdl.so")
2049	ensureContains(t, copyCmds, "image.apex/lib64/libstd.dylib.so")
2050
2051	// Ensure that libc and liblog (from Rust) is not included (since it has stubs and not listed in native_shared_libs)
2052	ensureNotContains(t, copyCmds, "image.apex/lib64/bionic/libc.so")
2053	ensureNotContains(t, copyCmds, "image.apex/lib64/liblog.so")
2054
2055	mylibLdFlags := ctx.ModuleForTests(t, "mylib", "android_arm64_armv8-a_shared_apex10000").Rule("ld").Args["libFlags"]
2056	mylibRsFlags := ctx.ModuleForTests(t, "libmylib_rs", "android_arm64_armv8-a_shared_apex10000").Rule("rustc").Args["linkFlags"]
2057	mylibCFlags := ctx.ModuleForTests(t, "mylib", "android_arm64_armv8-a_static_apex10000").Rule("cc").Args["cFlags"]
2058	mylibSharedCFlags := ctx.ModuleForTests(t, "mylib_shared", "android_arm64_armv8-a_shared_apex10000").Rule("cc").Args["cFlags"]
2059
2060	// For dependency to libc
2061	// Ensure that mylib is linking with the latest version of stubs
2062	ensureContains(t, mylibLdFlags, "libc/android_arm64_armv8-a_shared_current/libc.so")
2063	// ... and not linking to the non-stub (impl) variant
2064	ensureNotContains(t, mylibLdFlags, "libc/android_arm64_armv8-a_shared/libc.so")
2065	// ... Cflags from stub is correctly exported to mylib
2066	ensureContains(t, mylibCFlags, "__LIBC_API__=10000")
2067	ensureContains(t, mylibSharedCFlags, "__LIBC_API__=10000")
2068
2069	// For dependency to libm
2070	// Ensure that mylib is linking with the non-stub (impl) variant
2071	ensureContains(t, mylibLdFlags, "libm/android_arm64_armv8-a_shared_apex10000/libm.so")
2072	// ... and not linking to the stub variant
2073	ensureNotContains(t, mylibLdFlags, "libm/android_arm64_armv8-a_shared_29/libm.so")
2074	// ... and is not compiling with the stub
2075	ensureNotContains(t, mylibCFlags, "__LIBM_API__=29")
2076	ensureNotContains(t, mylibSharedCFlags, "__LIBM_API__=29")
2077
2078	// For dependency to libdl
2079	// Ensure that mylib is linking with the specified version of stubs
2080	ensureContains(t, mylibLdFlags, "libdl/android_arm64_armv8-a_shared_27/libdl.so")
2081	// ... and not linking to the other versions of stubs
2082	ensureNotContains(t, mylibLdFlags, "libdl/android_arm64_armv8-a_shared_28/libdl.so")
2083	ensureNotContains(t, mylibLdFlags, "libdl/android_arm64_armv8-a_shared_29/libdl.so")
2084	// ... and not linking to the non-stub (impl) variant
2085	ensureNotContains(t, mylibLdFlags, "libdl/android_arm64_armv8-a_shared_apex10000/libdl.so")
2086	// ... Cflags from stub is correctly exported to mylib
2087	ensureContains(t, mylibCFlags, "__LIBDL_API__=27")
2088	ensureContains(t, mylibSharedCFlags, "__LIBDL_API__=27")
2089
2090	// Rust checks
2091	// For dependency to libc, liblog
2092	// Ensure that libmylib_rs is linking with the latest versions of stubs
2093	ensureContains(t, mylibRsFlags, "libc/android_arm64_armv8-a_shared_current/libc.so")
2094	ensureContains(t, mylibRsFlags, "liblog/android_arm64_armv8-a_shared_current/liblog.so")
2095	// ... and not linking to the non-stub (impl) variants
2096	ensureNotContains(t, mylibRsFlags, "libc/android_arm64_armv8-a_shared/libc.so")
2097	ensureNotContains(t, mylibRsFlags, "liblog/android_arm64_armv8-a_shared/liblog.so")
2098
2099	// For libm dependency (explicit)
2100	// Ensure that mylib is linking with the non-stub (impl) variant
2101	ensureContains(t, mylibRsFlags, "libm/android_arm64_armv8-a_shared_apex10000/libm.so")
2102	// ... and not linking to the stub variant
2103	ensureNotContains(t, mylibRsFlags, "libm/android_arm64_armv8-a_shared_29/libm.so")
2104
2105	// For dependency to libvers
2106	// (We do not use libdl#27 as Rust links the system libs implicitly and does
2107	// not currently have a system_shared_libs equivalent to prevent this)
2108	// Ensure that mylib is linking with the specified version of stubs
2109	ensureContains(t, mylibRsFlags, "libvers/android_arm64_armv8-a_shared_27/libvers.so")
2110	// ... and not linking to the other versions of stubs
2111	ensureNotContains(t, mylibRsFlags, "libvers/android_arm64_armv8-a_shared_30/libvers.so")
2112	// ... and not linking to the non-stub (impl) variant
2113	ensureNotContains(t, mylibRsFlags, "libvers/android_arm64_armv8-a_shared_apex10000/libvers.so")
2114
2115	// Ensure that libBootstrap is depending on the platform variant of bionic libs
2116	libFlags := ctx.ModuleForTests(t, "libBootstrap", "android_arm64_armv8-a_shared").Rule("ld").Args["libFlags"]
2117	ensureContains(t, libFlags, "libc/android_arm64_armv8-a_shared/libc.so")
2118	ensureContains(t, libFlags, "libm/android_arm64_armv8-a_shared/libm.so")
2119	ensureContains(t, libFlags, "libdl/android_arm64_armv8-a_shared/libdl.so")
2120
2121	// Ensure that libbootstrap_rs is depending on the platform variant of bionic libs
2122	libRsFlags := ctx.ModuleForTests(t, "libbootstrap_rs", "android_arm64_armv8-a_shared").Rule("rustc").Args["linkFlags"]
2123	ensureContains(t, libRsFlags, "libc/android_arm64_armv8-a_shared/libc.so")
2124	ensureContains(t, libRsFlags, "libm/android_arm64_armv8-a_shared/libm.so")
2125	ensureContains(t, libRsFlags, "libdl/android_arm64_armv8-a_shared/libdl.so")
2126}
2127
2128func TestApexMinSdkVersion_NativeModulesShouldBeBuiltAgainstStubs(t *testing.T) {
2129	t.Parallel()
2130	// there are three links between liba --> libz.
2131	// 1) myapex -> libx -> liba -> libz    : this should be #30 link
2132	// 2) otherapex -> liby -> liba -> libz : this should be #30 link
2133	// 3) (platform) -> liba -> libz        : this should be non-stub link
2134	ctx := testApex(t, `
2135		apex {
2136			name: "myapex",
2137			key: "myapex.key",
2138			native_shared_libs: ["libx"],
2139			min_sdk_version: "29",
2140		}
2141
2142		apex {
2143			name: "otherapex",
2144			key: "myapex.key",
2145			native_shared_libs: ["liby"],
2146			min_sdk_version: "30",
2147		}
2148
2149		apex_key {
2150			name: "myapex.key",
2151			public_key: "testkey.avbpubkey",
2152			private_key: "testkey.pem",
2153		}
2154
2155		cc_library {
2156			name: "libx",
2157			shared_libs: ["liba"],
2158			system_shared_libs: [],
2159			stl: "none",
2160			apex_available: [ "myapex" ],
2161			min_sdk_version: "29",
2162		}
2163
2164		cc_library {
2165			name: "liby",
2166			shared_libs: ["liba"],
2167			system_shared_libs: [],
2168			stl: "none",
2169			apex_available: [ "otherapex" ],
2170			min_sdk_version: "29",
2171		}
2172
2173		cc_library {
2174			name: "liba",
2175			shared_libs: ["libz", "libz_rs"],
2176			system_shared_libs: [],
2177			stl: "none",
2178			apex_available: [
2179				"//apex_available:anyapex",
2180				"//apex_available:platform",
2181			],
2182			min_sdk_version: "29",
2183		}
2184
2185		cc_library {
2186			name: "libz",
2187			system_shared_libs: [],
2188			stl: "none",
2189			stubs: {
2190				versions: ["28", "30"],
2191			},
2192		}
2193
2194		rust_ffi {
2195			name: "libz_rs",
2196			crate_name: "z_rs",
2197			srcs: ["foo.rs"],
2198			stubs: {
2199				versions: ["28", "30"],
2200			},
2201		}
2202	`)
2203
2204	expectLink := func(from, from_variant, to, to_variant string) {
2205		ldArgs := ctx.ModuleForTests(t, from, "android_arm64_armv8-a_"+from_variant).Rule("ld").Args["libFlags"]
2206		ensureContains(t, ldArgs, "android_arm64_armv8-a_"+to_variant+"/"+to+".so")
2207	}
2208	expectNoLink := func(from, from_variant, to, to_variant string) {
2209		ldArgs := ctx.ModuleForTests(t, from, "android_arm64_armv8-a_"+from_variant).Rule("ld").Args["libFlags"]
2210		ensureNotContains(t, ldArgs, "android_arm64_armv8-a_"+to_variant+"/"+to+".so")
2211	}
2212	// platform liba is linked to non-stub version
2213	expectLink("liba", "shared", "libz", "shared")
2214	expectLink("liba", "shared", "unstripped/libz_rs", "shared")
2215	// liba in myapex is linked to current
2216	expectLink("liba", "shared_apex29", "libz", "shared_current")
2217	expectNoLink("liba", "shared_apex29", "libz", "shared_30")
2218	expectNoLink("liba", "shared_apex29", "libz", "shared_28")
2219	expectNoLink("liba", "shared_apex29", "libz", "shared")
2220	expectLink("liba", "shared_apex29", "unstripped/libz_rs", "shared_current")
2221	expectNoLink("liba", "shared_apex29", "unstripped/libz_rs", "shared_30")
2222	expectNoLink("liba", "shared_apex29", "unstripped/libz_rs", "shared_28")
2223	expectNoLink("liba", "shared_apex29", "unstripped/libz_rs", "shared")
2224	// liba in otherapex is linked to current
2225	expectLink("liba", "shared_apex30", "libz", "shared_current")
2226	expectNoLink("liba", "shared_apex30", "libz", "shared_30")
2227	expectNoLink("liba", "shared_apex30", "libz", "shared_28")
2228	expectNoLink("liba", "shared_apex30", "libz", "shared")
2229	expectLink("liba", "shared_apex30", "unstripped/libz_rs", "shared_current")
2230	expectNoLink("liba", "shared_apex30", "unstripped/libz_rs", "shared_30")
2231	expectNoLink("liba", "shared_apex30", "unstripped/libz_rs", "shared_28")
2232	expectNoLink("liba", "shared_apex30", "unstripped/libz_rs", "shared")
2233}
2234
2235func TestApexMinSdkVersion_SupportsCodeNames(t *testing.T) {
2236	t.Parallel()
2237	ctx := testApex(t, `
2238		apex {
2239			name: "myapex",
2240			key: "myapex.key",
2241			native_shared_libs: ["libx"],
2242			min_sdk_version: "R",
2243		}
2244
2245		apex_key {
2246			name: "myapex.key",
2247			public_key: "testkey.avbpubkey",
2248			private_key: "testkey.pem",
2249		}
2250
2251		cc_library {
2252			name: "libx",
2253			shared_libs: ["libz"],
2254			system_shared_libs: [],
2255			stl: "none",
2256			apex_available: [ "myapex" ],
2257			min_sdk_version: "R",
2258		}
2259
2260		cc_library {
2261			name: "libz",
2262			system_shared_libs: [],
2263			stl: "none",
2264			stubs: {
2265				versions: ["29", "R"],
2266			},
2267		}
2268	`,
2269		android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
2270			variables.Platform_version_active_codenames = []string{"R"}
2271		}),
2272	)
2273
2274	expectLink := func(from, from_variant, to, to_variant string) {
2275		ldArgs := ctx.ModuleForTests(t, from, "android_arm64_armv8-a_"+from_variant).Rule("ld").Args["libFlags"]
2276		ensureContains(t, ldArgs, "android_arm64_armv8-a_"+to_variant+"/"+to+".so")
2277	}
2278	expectNoLink := func(from, from_variant, to, to_variant string) {
2279		ldArgs := ctx.ModuleForTests(t, from, "android_arm64_armv8-a_"+from_variant).Rule("ld").Args["libFlags"]
2280		ensureNotContains(t, ldArgs, "android_arm64_armv8-a_"+to_variant+"/"+to+".so")
2281	}
2282	expectLink("libx", "shared_apex10000", "libz", "shared_current")
2283	expectNoLink("libx", "shared_apex10000", "libz", "shared_R")
2284	expectNoLink("libx", "shared_apex10000", "libz", "shared_29")
2285	expectNoLink("libx", "shared_apex10000", "libz", "shared")
2286}
2287
2288func TestApexMinSdkVersion_SupportsCodeNames_JavaLibs(t *testing.T) {
2289	t.Parallel()
2290	testApex(t, `
2291		apex {
2292			name: "myapex",
2293			key: "myapex.key",
2294			java_libs: ["libx"],
2295			min_sdk_version: "S",
2296		}
2297
2298		apex_key {
2299			name: "myapex.key",
2300			public_key: "testkey.avbpubkey",
2301			private_key: "testkey.pem",
2302		}
2303
2304		java_library {
2305			name: "libx",
2306			srcs: ["a.java"],
2307			apex_available: [ "myapex" ],
2308			sdk_version: "current",
2309			min_sdk_version: "S", // should be okay
2310			compile_dex: true,
2311		}
2312	`,
2313		android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
2314			variables.Platform_version_active_codenames = []string{"S"}
2315			variables.Platform_sdk_codename = proptools.StringPtr("S")
2316		}),
2317	)
2318}
2319
2320func TestApexMinSdkVersion_DefaultsToLatest(t *testing.T) {
2321	t.Parallel()
2322	ctx := testApex(t, `
2323		apex {
2324			name: "myapex",
2325			key: "myapex.key",
2326			native_shared_libs: ["libx"],
2327			updatable: false,
2328		}
2329
2330		apex_key {
2331			name: "myapex.key",
2332			public_key: "testkey.avbpubkey",
2333			private_key: "testkey.pem",
2334		}
2335
2336		cc_library {
2337			name: "libx",
2338			shared_libs: ["libz"],
2339			system_shared_libs: [],
2340			stl: "none",
2341			apex_available: [ "myapex" ],
2342		}
2343
2344		cc_library {
2345			name: "libz",
2346			system_shared_libs: [],
2347			stl: "none",
2348			stubs: {
2349				versions: ["1", "2"],
2350			},
2351		}
2352	`)
2353
2354	expectLink := func(from, from_variant, to, to_variant string) {
2355		ldArgs := ctx.ModuleForTests(t, from, "android_arm64_armv8-a_"+from_variant).Rule("ld").Args["libFlags"]
2356		ensureContains(t, ldArgs, "android_arm64_armv8-a_"+to_variant+"/"+to+".so")
2357	}
2358	expectNoLink := func(from, from_variant, to, to_variant string) {
2359		ldArgs := ctx.ModuleForTests(t, from, "android_arm64_armv8-a_"+from_variant).Rule("ld").Args["libFlags"]
2360		ensureNotContains(t, ldArgs, "android_arm64_armv8-a_"+to_variant+"/"+to+".so")
2361	}
2362	expectLink("libx", "shared_apex10000", "libz", "shared_current")
2363	expectNoLink("libx", "shared_apex10000", "libz", "shared_1")
2364	expectNoLink("libx", "shared_apex10000", "libz", "shared_2")
2365	expectNoLink("libx", "shared_apex10000", "libz", "shared")
2366}
2367
2368func TestApexMinSdkVersion_InVendorApex(t *testing.T) {
2369	t.Parallel()
2370	ctx := testApex(t, `
2371		apex {
2372			name: "myapex",
2373			key: "myapex.key",
2374			native_shared_libs: ["mylib"],
2375			updatable: true,
2376			vendor: true,
2377			min_sdk_version: "29",
2378		}
2379
2380		apex_key {
2381			name: "myapex.key",
2382			public_key: "testkey.avbpubkey",
2383			private_key: "testkey.pem",
2384		}
2385
2386		cc_library {
2387			name: "mylib",
2388			srcs: ["mylib.cpp"],
2389			vendor_available: true,
2390			min_sdk_version: "29",
2391			shared_libs: ["libbar"],
2392		}
2393
2394		cc_library {
2395			name: "libbar",
2396			stubs: { versions: ["29", "30"] },
2397			llndk: { symbol_file: "libbar.map.txt" },
2398		}
2399	`)
2400
2401	vendorVariant := "android_vendor_arm64_armv8-a"
2402
2403	mylib := ctx.ModuleForTests(t, "mylib", vendorVariant+"_shared_apex29")
2404
2405	// Ensure that mylib links with "current" LLNDK
2406	libFlags := names(mylib.Rule("ld").Args["libFlags"])
2407	ensureListContains(t, libFlags, "out/soong/.intermediates/libbar/"+vendorVariant+"_shared/libbar.so")
2408
2409	// Ensure that mylib is targeting 29
2410	ccRule := ctx.ModuleForTests(t, "mylib", vendorVariant+"_static_apex29").Output("obj/mylib.o")
2411	ensureContains(t, ccRule.Args["cFlags"], "-target aarch64-linux-android29")
2412
2413	// Ensure that the correct variant of crtbegin_so is used.
2414	crtBegin := mylib.Rule("ld").Args["crtBegin"]
2415	ensureContains(t, crtBegin, "out/soong/.intermediates/"+cc.DefaultCcCommonTestModulesDir+"crtbegin_so/"+vendorVariant+"_apex29/crtbegin_so.o")
2416
2417	// Ensure that the crtbegin_so used by the APEX is targeting 29
2418	cflags := ctx.ModuleForTests(t, "crtbegin_so", vendorVariant+"_apex29").Rule("cc").Args["cFlags"]
2419	android.AssertStringDoesContain(t, "cflags", cflags, "-target aarch64-linux-android29")
2420}
2421
2422func TestTrackAllowedDepsForAndroidApex(t *testing.T) {
2423	t.Parallel()
2424	ctx := testApex(t, `
2425		apex {
2426			name: "com.android.myapex",
2427			key: "myapex.key",
2428			updatable: true,
2429			native_shared_libs: [
2430				"mylib",
2431				"yourlib",
2432			],
2433			min_sdk_version: "29",
2434		}
2435
2436		apex {
2437			name: "myapex2",
2438			key: "myapex.key",
2439			updatable: false,
2440			native_shared_libs: ["yourlib"],
2441		}
2442
2443		apex_key {
2444			name: "myapex.key",
2445			public_key: "testkey.avbpubkey",
2446			private_key: "testkey.pem",
2447		}
2448
2449		cc_library {
2450			name: "mylib",
2451			srcs: ["mylib.cpp"],
2452			shared_libs: ["libbar", "libbar_rs"],
2453			min_sdk_version: "29",
2454			apex_available: ["com.android.myapex"],
2455		}
2456
2457		cc_library {
2458			name: "libbar",
2459			stubs: { versions: ["29", "30"] },
2460		}
2461
2462		rust_ffi {
2463			name: "libbar_rs",
2464			crate_name: "bar_rs",
2465			srcs: ["bar.rs"],
2466			stubs: { versions: ["29", "30"] },
2467		}
2468
2469		cc_library {
2470			name: "yourlib",
2471			srcs: ["mylib.cpp"],
2472			min_sdk_version: "29",
2473			apex_available: ["com.android.myapex", "myapex2", "//apex_available:platform"],
2474		}
2475	`, withFiles(android.MockFS{
2476		"packages/modules/common/build/allowed_deps.txt": nil,
2477	}),
2478		android.FixtureMergeMockFs(android.MockFS{
2479			"system/sepolicy/apex/com.android.myapex-file_contexts": nil,
2480		}))
2481
2482	depsinfo := ctx.SingletonForTests(t, "apex_depsinfo_singleton")
2483	inputs := depsinfo.Rule("generateApexDepsInfoFilesRule").BuildParams.Inputs.Strings()
2484	android.AssertStringListContains(t, "updatable com.android.myapex should generate depsinfo file", inputs,
2485		"out/soong/.intermediates/com.android.myapex/android_common_com.android.myapex/depsinfo/flatlist.txt")
2486	android.AssertStringListDoesNotContain(t, "non-updatable myapex2 should not generate depsinfo file", inputs,
2487		"out/soong/.intermediates/myapex2/android_common_myapex2/depsinfo/flatlist.txt")
2488
2489	myapex := ctx.ModuleForTests(t, "com.android.myapex", "android_common_com.android.myapex")
2490	flatlist := strings.Split(android.ContentFromFileRuleForTests(t, ctx,
2491		myapex.Output("depsinfo/flatlist.txt")), "\n")
2492	android.AssertStringListContains(t, "deps with stubs should be tracked in depsinfo as external dep",
2493		flatlist, "libbar(minSdkVersion:(no version)) (external)")
2494	android.AssertStringListContains(t, "deps with stubs should be tracked in depsinfo as external dep",
2495		flatlist, "libbar_rs(minSdkVersion:(no version)) (external)")
2496	android.AssertStringListDoesNotContain(t, "do not track if not available for platform",
2497		flatlist, "mylib:(minSdkVersion:29)")
2498	android.AssertStringListContains(t, "track platform-available lib",
2499		flatlist, "yourlib(minSdkVersion:29)")
2500}
2501
2502func TestNotTrackAllowedDepsForNonAndroidApex(t *testing.T) {
2503	t.Parallel()
2504	ctx := testApex(t, `
2505		apex {
2506			name: "myapex",
2507			key: "myapex.key",
2508			updatable: true,
2509			native_shared_libs: [
2510				"mylib",
2511				"yourlib",
2512			],
2513			min_sdk_version: "29",
2514		}
2515
2516		apex {
2517			name: "myapex2",
2518			key: "myapex.key",
2519			updatable: false,
2520			native_shared_libs: ["yourlib"],
2521		}
2522
2523		apex_key {
2524			name: "myapex.key",
2525			public_key: "testkey.avbpubkey",
2526			private_key: "testkey.pem",
2527		}
2528
2529		cc_library {
2530			name: "mylib",
2531			srcs: ["mylib.cpp"],
2532			shared_libs: ["libbar"],
2533			min_sdk_version: "29",
2534			apex_available: ["myapex"],
2535		}
2536
2537		cc_library {
2538			name: "libbar",
2539			stubs: { versions: ["29", "30"] },
2540		}
2541
2542		cc_library {
2543			name: "yourlib",
2544			srcs: ["mylib.cpp"],
2545			min_sdk_version: "29",
2546			apex_available: ["myapex", "myapex2", "//apex_available:platform"],
2547		}
2548	`, withFiles(android.MockFS{
2549		"packages/modules/common/build/allowed_deps.txt": nil,
2550	}))
2551
2552	depsinfo := ctx.SingletonForTests(t, "apex_depsinfo_singleton")
2553	inputs := depsinfo.Rule("generateApexDepsInfoFilesRule").BuildParams.Inputs.Strings()
2554	android.AssertStringListDoesNotContain(t, "updatable myapex should generate depsinfo file", inputs,
2555		"out/soong/.intermediates/myapex/android_common_myapex/depsinfo/flatlist.txt")
2556	android.AssertStringListDoesNotContain(t, "non-updatable myapex2 should not generate depsinfo file", inputs,
2557		"out/soong/.intermediates/myapex2/android_common_myapex2/depsinfo/flatlist.txt")
2558}
2559
2560func TestTrackAllowedDeps_SkipWithoutAllowedDepsTxt(t *testing.T) {
2561	t.Parallel()
2562	ctx := testApex(t, `
2563		apex {
2564			name: "com.android.myapex",
2565			key: "myapex.key",
2566			updatable: true,
2567			min_sdk_version: "29",
2568		}
2569
2570		apex_key {
2571			name: "myapex.key",
2572			public_key: "testkey.avbpubkey",
2573			private_key: "testkey.pem",
2574		}
2575	`,
2576		android.FixtureMergeMockFs(android.MockFS{
2577			"system/sepolicy/apex/com.android.myapex-file_contexts": nil,
2578		}))
2579	depsinfo := ctx.SingletonForTests(t, "apex_depsinfo_singleton")
2580	if nil != depsinfo.MaybeRule("generateApexDepsInfoFilesRule").Output {
2581		t.Error("apex_depsinfo_singleton shouldn't run when allowed_deps.txt doesn't exist")
2582	}
2583}
2584
2585func TestPlatformUsesLatestStubsFromApexes(t *testing.T) {
2586	t.Parallel()
2587	ctx := testApex(t, `
2588		apex {
2589			name: "myapex",
2590			key: "myapex.key",
2591			native_shared_libs: ["libx", "libx_rs"],
2592			updatable: false,
2593		}
2594
2595		apex_key {
2596			name: "myapex.key",
2597			public_key: "testkey.avbpubkey",
2598			private_key: "testkey.pem",
2599		}
2600
2601		cc_library {
2602			name: "libx",
2603			system_shared_libs: [],
2604			stl: "none",
2605			apex_available: [ "myapex" ],
2606			stubs: {
2607				versions: ["1", "2"],
2608			},
2609		}
2610
2611		rust_ffi {
2612			name: "libx_rs",
2613			crate_name: "x_rs",
2614			srcs: ["x.rs"],
2615			apex_available: [ "myapex" ],
2616			stubs: {
2617				versions: ["1", "2"],
2618			},
2619		}
2620
2621		cc_library {
2622			name: "libz",
2623			shared_libs: ["libx", "libx_rs",],
2624			system_shared_libs: [],
2625			stl: "none",
2626		}
2627	`)
2628
2629	expectLink := func(from, from_variant, to, to_variant string) {
2630		t.Helper()
2631		ldArgs := ctx.ModuleForTests(t, from, "android_arm64_armv8-a_"+from_variant).Rule("ld").Args["libFlags"]
2632		ensureContains(t, ldArgs, "android_arm64_armv8-a_"+to_variant+"/"+to+".so")
2633	}
2634	expectNoLink := func(from, from_variant, to, to_variant string) {
2635		t.Helper()
2636		ldArgs := ctx.ModuleForTests(t, from, "android_arm64_armv8-a_"+from_variant).Rule("ld").Args["libFlags"]
2637		ensureNotContains(t, ldArgs, "android_arm64_armv8-a_"+to_variant+"/"+to+".so")
2638	}
2639	expectLink("libz", "shared", "libx", "shared_current")
2640	expectNoLink("libz", "shared", "libx", "shared_2")
2641	expectLink("libz", "shared", "unstripped/libx_rs", "shared_current")
2642	expectNoLink("libz", "shared", "unstripped/libx_rs", "shared_2")
2643	expectNoLink("libz", "shared", "libz", "shared_1")
2644	expectNoLink("libz", "shared", "libz", "shared")
2645}
2646
2647var prepareForTestWithSantitizeHwaddress = android.FixtureModifyProductVariables(
2648	func(variables android.FixtureProductVariables) {
2649		variables.SanitizeDevice = []string{"hwaddress"}
2650	},
2651)
2652
2653func TestQApexesUseLatestStubsInBundledBuildsAndHWASAN(t *testing.T) {
2654	t.Parallel()
2655	ctx := testApex(t, `
2656		apex {
2657			name: "myapex",
2658			key: "myapex.key",
2659			native_shared_libs: ["libx"],
2660			min_sdk_version: "29",
2661		}
2662
2663		apex_key {
2664			name: "myapex.key",
2665			public_key: "testkey.avbpubkey",
2666			private_key: "testkey.pem",
2667		}
2668
2669		cc_library {
2670			name: "libx",
2671			shared_libs: ["libbar", "libbar_rs"],
2672			apex_available: [ "myapex" ],
2673			min_sdk_version: "29",
2674		}
2675
2676		rust_ffi {
2677			name: "libbar_rs",
2678			crate_name: "bar_rs",
2679			srcs: ["bar.rs"],
2680			stubs: { versions: ["29", "30"] },
2681		}
2682
2683		cc_library {
2684			name: "libbar",
2685			stubs: {
2686				versions: ["29", "30"],
2687			},
2688		}
2689	`,
2690		prepareForTestWithSantitizeHwaddress,
2691	)
2692	expectLink := func(from, from_variant, to, to_variant string) {
2693		ld := ctx.ModuleForTests(t, from, "android_arm64_armv8-a_"+from_variant).Rule("ld")
2694		libFlags := ld.Args["libFlags"]
2695		ensureContains(t, libFlags, "android_arm64_armv8-a_"+to_variant+"/"+to+".so")
2696	}
2697	expectLink("libx", "shared_hwasan_apex29", "libbar", "shared_current")
2698	expectLink("libx", "shared_hwasan_apex29", "unstripped/libbar_rs", "shared_current")
2699}
2700
2701func TestQTargetApexUsesStaticUnwinder(t *testing.T) {
2702	t.Parallel()
2703	ctx := testApex(t, `
2704		apex {
2705			name: "myapex",
2706			key: "myapex.key",
2707			native_shared_libs: ["libx"],
2708			min_sdk_version: "29",
2709		}
2710
2711		apex_key {
2712			name: "myapex.key",
2713			public_key: "testkey.avbpubkey",
2714			private_key: "testkey.pem",
2715		}
2716
2717		cc_library {
2718			name: "libx",
2719			apex_available: [ "myapex" ],
2720			min_sdk_version: "29",
2721		}
2722	`)
2723
2724	// ensure apex variant of c++ is linked with static unwinder
2725	cm := ctx.ModuleForTests(t, "libc++", "android_arm64_armv8-a_shared_apex29").Module().(*cc.Module)
2726	ensureListContains(t, cm.Properties.AndroidMkStaticLibs, "libunwind")
2727	// note that platform variant is not.
2728	cm = ctx.ModuleForTests(t, "libc++", "android_arm64_armv8-a_shared").Module().(*cc.Module)
2729	ensureListNotContains(t, cm.Properties.AndroidMkStaticLibs, "libunwind")
2730}
2731
2732func TestApexMinSdkVersion_ErrorIfIncompatibleVersion(t *testing.T) {
2733	t.Parallel()
2734	testApexError(t, `module "mylib".*: should support min_sdk_version\(29\)`, `
2735		apex {
2736			name: "myapex",
2737			key: "myapex.key",
2738			native_shared_libs: ["mylib"],
2739			min_sdk_version: "29",
2740		}
2741
2742		apex_key {
2743			name: "myapex.key",
2744			public_key: "testkey.avbpubkey",
2745			private_key: "testkey.pem",
2746		}
2747
2748		cc_library {
2749			name: "mylib",
2750			srcs: ["mylib.cpp"],
2751			system_shared_libs: [],
2752			stl: "none",
2753			apex_available: [
2754				"myapex",
2755			],
2756			min_sdk_version: "30",
2757		}
2758	`)
2759
2760	testApexError(t, `module "libfoo.ffi".*: should support min_sdk_version\(29\)`, `
2761		apex {
2762			name: "myapex",
2763			key: "myapex.key",
2764			native_shared_libs: ["libfoo.ffi"],
2765			min_sdk_version: "29",
2766		}
2767
2768		apex_key {
2769			name: "myapex.key",
2770			public_key: "testkey.avbpubkey",
2771			private_key: "testkey.pem",
2772		}
2773
2774		rust_ffi_shared {
2775			name: "libfoo.ffi",
2776			srcs: ["foo.rs"],
2777			crate_name: "foo",
2778			apex_available: [
2779				"myapex",
2780			],
2781			min_sdk_version: "30",
2782		}
2783	`)
2784
2785	testApexError(t, `module "libfoo".*: should support min_sdk_version\(29\)`, `
2786		apex {
2787			name: "myapex",
2788			key: "myapex.key",
2789			java_libs: ["libfoo"],
2790			min_sdk_version: "29",
2791		}
2792
2793		apex_key {
2794			name: "myapex.key",
2795			public_key: "testkey.avbpubkey",
2796			private_key: "testkey.pem",
2797		}
2798
2799		java_import {
2800			name: "libfoo",
2801			jars: ["libfoo.jar"],
2802			apex_available: [
2803				"myapex",
2804			],
2805			min_sdk_version: "30",
2806			compile_dex: true,
2807		}
2808	`)
2809
2810	// Skip check for modules compiling against core API surface
2811	testApex(t, `
2812		apex {
2813			name: "myapex",
2814			key: "myapex.key",
2815			java_libs: ["libfoo"],
2816			min_sdk_version: "29",
2817		}
2818
2819		apex_key {
2820			name: "myapex.key",
2821			public_key: "testkey.avbpubkey",
2822			private_key: "testkey.pem",
2823		}
2824
2825		java_library {
2826			name: "libfoo",
2827			srcs: ["Foo.java"],
2828			apex_available: [
2829				"myapex",
2830			],
2831			// Compile against core API surface
2832			sdk_version: "core_current",
2833			min_sdk_version: "30",
2834			compile_dex: true,
2835		}
2836	`)
2837
2838}
2839
2840func TestApexMinSdkVersion_Okay(t *testing.T) {
2841	t.Parallel()
2842	testApex(t, `
2843		apex {
2844			name: "myapex",
2845			key: "myapex.key",
2846			native_shared_libs: ["libfoo"],
2847			java_libs: ["libbar"],
2848			min_sdk_version: "29",
2849		}
2850
2851		apex_key {
2852			name: "myapex.key",
2853			public_key: "testkey.avbpubkey",
2854			private_key: "testkey.pem",
2855		}
2856
2857		cc_library {
2858			name: "libfoo",
2859			srcs: ["mylib.cpp"],
2860			shared_libs: ["libfoo_dep"],
2861			apex_available: ["myapex"],
2862			min_sdk_version: "29",
2863		}
2864
2865		cc_library {
2866			name: "libfoo_dep",
2867			srcs: ["mylib.cpp"],
2868			apex_available: ["myapex"],
2869			min_sdk_version: "29",
2870		}
2871
2872		java_library {
2873			name: "libbar",
2874			sdk_version: "current",
2875			srcs: ["a.java"],
2876			static_libs: [
2877				"libbar_dep",
2878				"libbar_import_dep",
2879			],
2880			apex_available: ["myapex"],
2881			min_sdk_version: "29",
2882			compile_dex: true,
2883		}
2884
2885		java_library {
2886			name: "libbar_dep",
2887			sdk_version: "current",
2888			srcs: ["a.java"],
2889			apex_available: ["myapex"],
2890			min_sdk_version: "29",
2891		}
2892
2893		java_import {
2894			name: "libbar_import_dep",
2895			jars: ["libbar.jar"],
2896			apex_available: ["myapex"],
2897			min_sdk_version: "29",
2898		}
2899	`)
2900}
2901
2902func TestApexMinSdkVersion_MinApiForArch(t *testing.T) {
2903	t.Parallel()
2904	// Tests that an apex dependency with min_sdk_version higher than the
2905	// min_sdk_version of the apex is allowed as long as the dependency's
2906	// min_sdk_version is less than or equal to the api level that the
2907	// architecture was introduced in.  In this case, arm64 didn't exist
2908	// until api level 21, so the arm64 code will never need to run on
2909	// an api level 20 device, even if other architectures of the apex
2910	// will.
2911	testApex(t, `
2912		apex {
2913			name: "myapex",
2914			key: "myapex.key",
2915			native_shared_libs: ["libfoo"],
2916			min_sdk_version: "20",
2917		}
2918
2919		apex_key {
2920			name: "myapex.key",
2921			public_key: "testkey.avbpubkey",
2922			private_key: "testkey.pem",
2923		}
2924
2925		cc_library {
2926			name: "libfoo",
2927			srcs: ["mylib.cpp"],
2928			apex_available: ["myapex"],
2929			min_sdk_version: "21",
2930			stl: "none",
2931		}
2932	`)
2933}
2934
2935func TestJavaStableSdkVersion(t *testing.T) {
2936	t.Parallel()
2937	testCases := []struct {
2938		name          string
2939		expectedError string
2940		bp            string
2941		preparer      android.FixturePreparer
2942	}{
2943		{
2944			name: "Non-updatable apex with non-stable dep",
2945			bp: `
2946				apex {
2947					name: "myapex",
2948					java_libs: ["myjar"],
2949					key: "myapex.key",
2950					updatable: false,
2951				}
2952				apex_key {
2953					name: "myapex.key",
2954					public_key: "testkey.avbpubkey",
2955					private_key: "testkey.pem",
2956				}
2957				java_library {
2958					name: "myjar",
2959					srcs: ["foo/bar/MyClass.java"],
2960					sdk_version: "test_current",
2961					apex_available: ["myapex"],
2962					compile_dex: true,
2963				}
2964			`,
2965		},
2966		{
2967			name: "Updatable apex with stable dep",
2968			bp: `
2969				apex {
2970					name: "myapex",
2971					java_libs: ["myjar"],
2972					key: "myapex.key",
2973					updatable: true,
2974					min_sdk_version: "29",
2975				}
2976				apex_key {
2977					name: "myapex.key",
2978					public_key: "testkey.avbpubkey",
2979					private_key: "testkey.pem",
2980				}
2981				java_library {
2982					name: "myjar",
2983					srcs: ["foo/bar/MyClass.java"],
2984					sdk_version: "current",
2985					apex_available: ["myapex"],
2986					min_sdk_version: "29",
2987					compile_dex: true,
2988				}
2989			`,
2990		},
2991		{
2992			name:          "Updatable apex with non-stable dep",
2993			expectedError: "cannot depend on \"myjar\"",
2994			bp: `
2995				apex {
2996					name: "myapex",
2997					java_libs: ["myjar"],
2998					key: "myapex.key",
2999					updatable: true,
3000				}
3001				apex_key {
3002					name: "myapex.key",
3003					public_key: "testkey.avbpubkey",
3004					private_key: "testkey.pem",
3005				}
3006				java_library {
3007					name: "myjar",
3008					srcs: ["foo/bar/MyClass.java"],
3009					sdk_version: "test_current",
3010					apex_available: ["myapex"],
3011					compile_dex: true,
3012				}
3013			`,
3014		},
3015		{
3016			name:          "Updatable apex with non-stable legacy core platform dep",
3017			expectedError: `\Qcannot depend on "myjar-uses-legacy": non stable SDK core_platform_current - uses legacy core platform\E`,
3018			bp: `
3019				apex {
3020					name: "myapex",
3021					java_libs: ["myjar-uses-legacy"],
3022					key: "myapex.key",
3023					updatable: true,
3024				}
3025				apex_key {
3026					name: "myapex.key",
3027					public_key: "testkey.avbpubkey",
3028					private_key: "testkey.pem",
3029				}
3030				java_library {
3031					name: "myjar-uses-legacy",
3032					srcs: ["foo/bar/MyClass.java"],
3033					sdk_version: "core_platform",
3034					apex_available: ["myapex"],
3035					compile_dex: true,
3036				}
3037			`,
3038			preparer: java.FixtureUseLegacyCorePlatformApi("myjar-uses-legacy"),
3039		},
3040		{
3041			name: "Updatable apex with non-stable transitive dep",
3042			// This is not actually detecting that the transitive dependency is unstable, rather it is
3043			// detecting that the transitive dependency is building against a wider API surface than the
3044			// module that depends on it is using.
3045			expectedError: "compiles against Android API, but dependency \"transitive-jar\" is compiling against private API.",
3046			bp: `
3047				apex {
3048					name: "myapex",
3049					java_libs: ["myjar"],
3050					key: "myapex.key",
3051					updatable: true,
3052				}
3053				apex_key {
3054					name: "myapex.key",
3055					public_key: "testkey.avbpubkey",
3056					private_key: "testkey.pem",
3057				}
3058				java_library {
3059					name: "myjar",
3060					srcs: ["foo/bar/MyClass.java"],
3061					sdk_version: "current",
3062					apex_available: ["myapex"],
3063					static_libs: ["transitive-jar"],
3064					compile_dex: true,
3065				}
3066				java_library {
3067					name: "transitive-jar",
3068					srcs: ["foo/bar/MyClass.java"],
3069					sdk_version: "core_platform",
3070					apex_available: ["myapex"],
3071				}
3072			`,
3073		},
3074	}
3075
3076	for _, test := range testCases {
3077		if test.name != "Updatable apex with non-stable legacy core platform dep" {
3078			continue
3079		}
3080		t.Run(test.name, func(t *testing.T) {
3081			t.Parallel()
3082			errorHandler := android.FixtureExpectsNoErrors
3083			if test.expectedError != "" {
3084				errorHandler = android.FixtureExpectsAtLeastOneErrorMatchingPattern(test.expectedError)
3085			}
3086			android.GroupFixturePreparers(
3087				java.PrepareForTestWithJavaDefaultModules,
3088				PrepareForTestWithApexBuildComponents,
3089				prepareForTestWithMyapex,
3090				android.OptionalFixturePreparer(test.preparer),
3091			).
3092				ExtendWithErrorHandler(errorHandler).
3093				RunTestWithBp(t, test.bp)
3094		})
3095	}
3096}
3097
3098func TestApexMinSdkVersion_ErrorIfDepIsNewer(t *testing.T) {
3099	testApexError(t, `module "mylib2".*: should support min_sdk_version\(29\) for "myapex"`, `
3100		apex {
3101			name: "myapex",
3102			key: "myapex.key",
3103			native_shared_libs: ["mylib"],
3104			min_sdk_version: "29",
3105		}
3106
3107		apex_key {
3108			name: "myapex.key",
3109			public_key: "testkey.avbpubkey",
3110			private_key: "testkey.pem",
3111		}
3112
3113		cc_library {
3114			name: "mylib",
3115			srcs: ["mylib.cpp"],
3116			shared_libs: ["mylib2"],
3117			system_shared_libs: [],
3118			stl: "none",
3119			apex_available: [
3120				"myapex",
3121			],
3122			min_sdk_version: "29",
3123		}
3124
3125		// indirect part of the apex
3126		cc_library {
3127			name: "mylib2",
3128			srcs: ["mylib.cpp"],
3129			system_shared_libs: [],
3130			stl: "none",
3131			apex_available: [
3132				"myapex",
3133			],
3134			min_sdk_version: "30",
3135		}
3136	`)
3137}
3138
3139func TestApexMinSdkVersion_ErrorIfDepIsNewer_Java(t *testing.T) {
3140	t.Parallel()
3141	testApexError(t, `module "bar".*: should support min_sdk_version\(29\) for "myapex"`, `
3142		apex {
3143			name: "myapex",
3144			key: "myapex.key",
3145			apps: ["AppFoo"],
3146			min_sdk_version: "29",
3147			updatable: false,
3148		}
3149
3150		apex_key {
3151			name: "myapex.key",
3152			public_key: "testkey.avbpubkey",
3153			private_key: "testkey.pem",
3154		}
3155
3156		android_app {
3157			name: "AppFoo",
3158			srcs: ["foo/bar/MyClass.java"],
3159			sdk_version: "current",
3160			min_sdk_version: "29",
3161			system_modules: "none",
3162			stl: "none",
3163			static_libs: ["bar"],
3164			apex_available: [ "myapex" ],
3165		}
3166
3167		java_library {
3168			name: "bar",
3169			sdk_version: "current",
3170			srcs: ["a.java"],
3171			apex_available: [ "myapex" ],
3172		}
3173	`)
3174}
3175
3176func TestApexMinSdkVersion_OkayEvenWhenDepIsNewer_IfItSatisfiesApexMinSdkVersion(t *testing.T) {
3177	t.Parallel()
3178	ctx := testApex(t, `
3179		apex {
3180			name: "myapex",
3181			key: "myapex.key",
3182			native_shared_libs: ["mylib"],
3183			min_sdk_version: "29",
3184		}
3185
3186		apex_key {
3187			name: "myapex.key",
3188			public_key: "testkey.avbpubkey",
3189			private_key: "testkey.pem",
3190		}
3191
3192		// mylib will link to mylib2#current
3193		cc_library {
3194			name: "mylib",
3195			srcs: ["mylib.cpp"],
3196			shared_libs: ["mylib2"],
3197			system_shared_libs: [],
3198			stl: "none",
3199			apex_available: ["myapex", "otherapex"],
3200			min_sdk_version: "29",
3201		}
3202
3203		cc_library {
3204			name: "mylib2",
3205			srcs: ["mylib.cpp"],
3206			system_shared_libs: [],
3207			stl: "none",
3208			apex_available: ["otherapex"],
3209			stubs: { versions: ["29", "30"] },
3210			min_sdk_version: "30",
3211		}
3212
3213		apex {
3214			name: "otherapex",
3215			key: "myapex.key",
3216			native_shared_libs: ["mylib", "mylib2"],
3217			min_sdk_version: "30",
3218		}
3219	`)
3220	expectLink := func(from, from_variant, to, to_variant string) {
3221		ld := ctx.ModuleForTests(t, from, "android_arm64_armv8-a_"+from_variant).Rule("ld")
3222		libFlags := ld.Args["libFlags"]
3223		ensureContains(t, libFlags, "android_arm64_armv8-a_"+to_variant+"/"+to+".so")
3224	}
3225	expectLink("mylib", "shared_apex29", "mylib2", "shared_current")
3226	expectLink("mylib", "shared_apex30", "mylib2", "shared_current")
3227}
3228
3229func TestApexMinSdkVersion_WorksWithSdkCodename(t *testing.T) {
3230	t.Parallel()
3231	withSAsActiveCodeNames := android.FixtureModifyProductVariables(
3232		func(variables android.FixtureProductVariables) {
3233			variables.Platform_sdk_codename = proptools.StringPtr("S")
3234			variables.Platform_version_active_codenames = []string{"S"}
3235		},
3236	)
3237	testApexError(t, `libbar.*: should support min_sdk_version\(S\)`, `
3238		apex {
3239			name: "myapex",
3240			key: "myapex.key",
3241			native_shared_libs: ["libfoo"],
3242			min_sdk_version: "S",
3243		}
3244		apex_key {
3245			name: "myapex.key",
3246			public_key: "testkey.avbpubkey",
3247			private_key: "testkey.pem",
3248		}
3249		cc_library {
3250			name: "libfoo",
3251			shared_libs: ["libbar"],
3252			apex_available: ["myapex"],
3253			min_sdk_version: "29",
3254		}
3255		cc_library {
3256			name: "libbar",
3257			apex_available: ["myapex"],
3258		}
3259	`, withSAsActiveCodeNames)
3260}
3261
3262func TestApexMinSdkVersion_WorksWithActiveCodenames(t *testing.T) {
3263	t.Parallel()
3264	withSAsActiveCodeNames := android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
3265		variables.Platform_sdk_codename = proptools.StringPtr("S")
3266		variables.Platform_version_active_codenames = []string{"S", "T"}
3267	})
3268	ctx := testApex(t, `
3269		apex {
3270			name: "myapex",
3271			key: "myapex.key",
3272			native_shared_libs: ["libfoo"],
3273			min_sdk_version: "S",
3274		}
3275		apex_key {
3276			name: "myapex.key",
3277			public_key: "testkey.avbpubkey",
3278			private_key: "testkey.pem",
3279		}
3280		cc_library {
3281			name: "libfoo",
3282			shared_libs: ["libbar"],
3283			apex_available: ["myapex"],
3284			min_sdk_version: "S",
3285		}
3286		cc_library {
3287			name: "libbar",
3288			stubs: {
3289				symbol_file: "libbar.map.txt",
3290				versions: ["30", "S", "T"],
3291			},
3292		}
3293	`, withSAsActiveCodeNames)
3294
3295	// ensure libfoo is linked with current version of libbar stub
3296	libfoo := ctx.ModuleForTests(t, "libfoo", "android_arm64_armv8-a_shared_apex10000")
3297	libFlags := libfoo.Rule("ld").Args["libFlags"]
3298	ensureContains(t, libFlags, "android_arm64_armv8-a_shared_current/libbar.so")
3299}
3300
3301func TestFilesInSubDir(t *testing.T) {
3302	t.Parallel()
3303	ctx := testApex(t, `
3304		apex {
3305			name: "myapex",
3306			key: "myapex.key",
3307			native_shared_libs: ["mylib"],
3308			binaries: ["mybin", "mybin.rust"],
3309			prebuilts: ["myetc"],
3310			compile_multilib: "both",
3311			updatable: false,
3312		}
3313
3314		apex_key {
3315			name: "myapex.key",
3316			public_key: "testkey.avbpubkey",
3317			private_key: "testkey.pem",
3318		}
3319
3320		prebuilt_etc {
3321			name: "myetc",
3322			src: "myprebuilt",
3323			sub_dir: "foo/bar",
3324		}
3325
3326		cc_library {
3327			name: "mylib",
3328			srcs: ["mylib.cpp"],
3329			relative_install_path: "foo/bar",
3330			system_shared_libs: [],
3331			stl: "none",
3332			apex_available: [ "myapex" ],
3333		}
3334
3335		cc_binary {
3336			name: "mybin",
3337			srcs: ["mylib.cpp"],
3338			relative_install_path: "foo/bar",
3339			system_shared_libs: [],
3340			stl: "none",
3341			apex_available: [ "myapex" ],
3342		}
3343
3344		rust_binary {
3345			name: "mybin.rust",
3346			srcs: ["foo.rs"],
3347			relative_install_path: "rust_subdir",
3348			apex_available: [ "myapex" ],
3349		}
3350	`)
3351
3352	generateFsRule := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Rule("generateFsConfig")
3353	cmd := generateFsRule.RuleParams.Command
3354
3355	// Ensure that the subdirectories are all listed
3356	ensureContains(t, cmd, "/etc ")
3357	ensureContains(t, cmd, "/etc/foo ")
3358	ensureContains(t, cmd, "/etc/foo/bar ")
3359	ensureContains(t, cmd, "/lib64 ")
3360	ensureContains(t, cmd, "/lib64/foo ")
3361	ensureContains(t, cmd, "/lib64/foo/bar ")
3362	ensureContains(t, cmd, "/lib ")
3363	ensureContains(t, cmd, "/lib/foo ")
3364	ensureContains(t, cmd, "/lib/foo/bar ")
3365	ensureContains(t, cmd, "/bin ")
3366	ensureContains(t, cmd, "/bin/foo ")
3367	ensureContains(t, cmd, "/bin/foo/bar ")
3368	ensureContains(t, cmd, "/bin/rust_subdir ")
3369}
3370
3371func TestFilesInSubDirWhenNativeBridgeEnabled(t *testing.T) {
3372	t.Parallel()
3373	ctx := testApex(t, `
3374		apex {
3375			name: "myapex",
3376			key: "myapex.key",
3377			multilib: {
3378				both: {
3379					native_shared_libs: ["mylib"],
3380					binaries: ["mybin"],
3381				},
3382			},
3383			compile_multilib: "both",
3384			native_bridge_supported: true,
3385			updatable: false,
3386		}
3387
3388		apex_key {
3389			name: "myapex.key",
3390			public_key: "testkey.avbpubkey",
3391			private_key: "testkey.pem",
3392		}
3393
3394		cc_library {
3395			name: "mylib",
3396			relative_install_path: "foo/bar",
3397			system_shared_libs: [],
3398			stl: "none",
3399			apex_available: [ "myapex" ],
3400			native_bridge_supported: true,
3401		}
3402
3403		cc_binary {
3404			name: "mybin",
3405			relative_install_path: "foo/bar",
3406			system_shared_libs: [],
3407			stl: "none",
3408			apex_available: [ "myapex" ],
3409			native_bridge_supported: true,
3410			compile_multilib: "both", // default is "first" for binary
3411			multilib: {
3412				lib64: {
3413					suffix: "64",
3414				},
3415			},
3416		}
3417	`, android.PrepareForNativeBridgeEnabled)
3418	ensureExactContents(t, ctx, "myapex", "android_common_myapex", []string{
3419		"bin/foo/bar/mybin",
3420		"bin/foo/bar/mybin64",
3421		"bin/arm/foo/bar/mybin",
3422		"bin/arm64/foo/bar/mybin64",
3423		"lib/foo/bar/mylib.so",
3424		"lib/arm/foo/bar/mylib.so",
3425		"lib64/foo/bar/mylib.so",
3426		"lib64/arm64/foo/bar/mylib.so",
3427	})
3428}
3429
3430func TestVendorApex(t *testing.T) {
3431	t.Parallel()
3432	result := android.GroupFixturePreparers(
3433		prepareForApexTest,
3434		android.FixtureModifyConfig(android.SetKatiEnabledForTests),
3435	).RunTestWithBp(t, `
3436		apex {
3437			name: "myapex",
3438			key: "myapex.key",
3439			binaries: ["mybin"],
3440			vendor: true,
3441			updatable: false,
3442		}
3443		apex_key {
3444			name: "myapex.key",
3445			public_key: "testkey.avbpubkey",
3446			private_key: "testkey.pem",
3447		}
3448		cc_binary {
3449			name: "mybin",
3450			vendor: true,
3451			shared_libs: ["libfoo"],
3452		}
3453		cc_library {
3454			name: "libfoo",
3455			proprietary: true,
3456		}
3457	`)
3458
3459	ensureExactContents(t, result.TestContext, "myapex", "android_common_myapex", []string{
3460		"bin/mybin",
3461		"lib64/libfoo.so",
3462		// TODO(b/159195575): Add an option to use VNDK libs from VNDK APEX
3463		"lib64/libc++.so",
3464	})
3465
3466	apexBundle := result.ModuleForTests(t, "myapex", "android_common_myapex").Module().(*apexBundle)
3467	data := android.AndroidMkDataForTest(t, result.TestContext, apexBundle)
3468	name := apexBundle.BaseModuleName()
3469	prefix := "TARGET_"
3470	var builder strings.Builder
3471	data.Custom(&builder, name, prefix, "", data)
3472	androidMk := android.StringRelativeToTop(result.Config, builder.String())
3473	installPath := "out/target/product/test_device/vendor/apex"
3474	ensureContains(t, androidMk, "LOCAL_MODULE_PATH := "+installPath)
3475
3476	apexManifestRule := result.ModuleForTests(t, "myapex", "android_common_myapex").Rule("apexManifestRule")
3477	requireNativeLibs := names(apexManifestRule.Args["requireNativeLibs"])
3478	ensureListNotContains(t, requireNativeLibs, ":vndk")
3479}
3480
3481func TestProductVariant(t *testing.T) {
3482	t.Parallel()
3483	ctx := testApex(t, `
3484		apex {
3485			name: "myapex",
3486			key: "myapex.key",
3487			updatable: false,
3488			product_specific: true,
3489			binaries: ["foo"],
3490		}
3491
3492		apex_key {
3493			name: "myapex.key",
3494			public_key: "testkey.avbpubkey",
3495			private_key: "testkey.pem",
3496		}
3497
3498		cc_binary {
3499			name: "foo",
3500			product_available: true,
3501			apex_available: ["myapex"],
3502			srcs: ["foo.cpp"],
3503		}
3504	`)
3505
3506	cflags := strings.Fields(
3507		ctx.ModuleForTests(t, "foo", "android_product_arm64_armv8-a_apex10000").Rule("cc").Args["cFlags"])
3508	ensureListContains(t, cflags, "-D__ANDROID_VNDK__")
3509	ensureListContains(t, cflags, "-D__ANDROID_APEX__")
3510	ensureListContains(t, cflags, "-D__ANDROID_PRODUCT__")
3511	ensureListNotContains(t, cflags, "-D__ANDROID_VENDOR__")
3512}
3513
3514func TestApex_withPrebuiltFirmware(t *testing.T) {
3515	t.Parallel()
3516	testCases := []struct {
3517		name           string
3518		additionalProp string
3519	}{
3520		{"system apex with prebuilt_firmware", ""},
3521		{"vendor apex with prebuilt_firmware", "vendor: true,"},
3522	}
3523	for _, tc := range testCases {
3524		t.Run(tc.name, func(t *testing.T) {
3525			t.Parallel()
3526			ctx := testApex(t, `
3527				apex {
3528					name: "myapex",
3529					key: "myapex.key",
3530					prebuilts: ["myfirmware"],
3531					updatable: false,
3532					`+tc.additionalProp+`
3533				}
3534				apex_key {
3535					name: "myapex.key",
3536					public_key: "testkey.avbpubkey",
3537					private_key: "testkey.pem",
3538				}
3539				prebuilt_firmware {
3540					name: "myfirmware",
3541					src: "myfirmware.bin",
3542					filename_from_src: true,
3543					`+tc.additionalProp+`
3544				}
3545			`)
3546			ensureExactContents(t, ctx, "myapex", "android_common_myapex", []string{
3547				"etc/firmware/myfirmware.bin",
3548			})
3549		})
3550	}
3551}
3552
3553func TestAndroidMk_VendorApexRequired(t *testing.T) {
3554	t.Parallel()
3555	ctx := testApex(t, `
3556		apex {
3557			name: "myapex",
3558			key: "myapex.key",
3559			vendor: true,
3560			native_shared_libs: ["mylib"],
3561			updatable: false,
3562		}
3563
3564		apex_key {
3565			name: "myapex.key",
3566			public_key: "testkey.avbpubkey",
3567			private_key: "testkey.pem",
3568		}
3569
3570		cc_library {
3571			name: "mylib",
3572			vendor_available: true,
3573		}
3574	`)
3575
3576	apexBundle := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Module().(*apexBundle)
3577	data := android.AndroidMkDataForTest(t, ctx, apexBundle)
3578	name := apexBundle.BaseModuleName()
3579	prefix := "TARGET_"
3580	var builder strings.Builder
3581	data.Custom(&builder, name, prefix, "", data)
3582	androidMk := builder.String()
3583	ensureContains(t, androidMk, "LOCAL_REQUIRED_MODULES := libc++.vendor.myapex:64 mylib.vendor.myapex:64 libc.vendor libm.vendor libdl.vendor\n")
3584}
3585
3586func TestAndroidMkWritesCommonProperties(t *testing.T) {
3587	ctx := testApex(t, `
3588		apex {
3589			name: "myapex",
3590			key: "myapex.key",
3591			vintf_fragments: ["fragment.xml"],
3592			init_rc: ["init.rc"],
3593			updatable: false,
3594		}
3595		apex_key {
3596			name: "myapex.key",
3597			public_key: "testkey.avbpubkey",
3598			private_key: "testkey.pem",
3599		}
3600		cc_binary {
3601			name: "mybin",
3602		}
3603	`)
3604
3605	apexBundle := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Module().(*apexBundle)
3606	data := android.AndroidMkDataForTest(t, ctx, apexBundle)
3607	name := apexBundle.BaseModuleName()
3608	prefix := "TARGET_"
3609	var builder strings.Builder
3610	data.Custom(&builder, name, prefix, "", data)
3611	androidMk := builder.String()
3612	ensureContains(t, androidMk, "LOCAL_FULL_VINTF_FRAGMENTS := fragment.xml\n")
3613	ensureContains(t, androidMk, "LOCAL_FULL_INIT_RC := init.rc\n")
3614}
3615
3616func TestStaticLinking(t *testing.T) {
3617	t.Parallel()
3618	ctx := testApex(t, `
3619		apex {
3620			name: "myapex",
3621			key: "myapex.key",
3622			native_shared_libs: ["mylib"],
3623			updatable: false,
3624		}
3625
3626		apex_key {
3627			name: "myapex.key",
3628			public_key: "testkey.avbpubkey",
3629			private_key: "testkey.pem",
3630		}
3631
3632		cc_library {
3633			name: "mylib",
3634			srcs: ["mylib.cpp"],
3635			system_shared_libs: [],
3636			stl: "none",
3637			stubs: {
3638				versions: ["1", "2", "3"],
3639			},
3640			apex_available: ["myapex"],
3641		}
3642
3643		rust_ffi {
3644			name: "libmylib_rs",
3645			crate_name: "mylib_rs",
3646			srcs: ["mylib.rs"],
3647			stubs: {
3648				versions: ["1", "2", "3"],
3649			},
3650			apex_available: ["myapex"],
3651		}
3652
3653		cc_binary {
3654			name: "not_in_apex",
3655			srcs: ["mylib.cpp"],
3656			static_libs: ["mylib", "libmylib_rs"],
3657			static_executable: true,
3658			system_shared_libs: [],
3659			stl: "none",
3660		}
3661	`)
3662
3663	ldFlags := ctx.ModuleForTests(t, "not_in_apex", "android_arm64_armv8-a").Rule("ld").Args["libFlags"]
3664
3665	// Ensure that not_in_apex is linking with the static variant of mylib
3666	ensureContains(t, ldFlags, "mylib/android_arm64_armv8-a_static/mylib.a")
3667	ensureContains(t, ldFlags, "generated_rust_staticlib/librustlibs.a")
3668}
3669
3670func TestKeys(t *testing.T) {
3671	t.Parallel()
3672	ctx := testApex(t, `
3673		apex {
3674			name: "myapex_keytest",
3675			key: "myapex.key",
3676			certificate: ":myapex.certificate",
3677			native_shared_libs: ["mylib"],
3678			file_contexts: ":myapex-file_contexts",
3679			updatable: false,
3680		}
3681
3682		cc_library {
3683			name: "mylib",
3684			srcs: ["mylib.cpp"],
3685			system_shared_libs: [],
3686			stl: "none",
3687			apex_available: [ "myapex_keytest" ],
3688		}
3689
3690		apex_key {
3691			name: "myapex.key",
3692			public_key: "testkey.avbpubkey",
3693			private_key: "testkey.pem",
3694		}
3695
3696		android_app_certificate {
3697			name: "myapex.certificate",
3698			certificate: "testkey",
3699		}
3700
3701		android_app_certificate {
3702			name: "myapex.certificate.override",
3703			certificate: "testkey.override",
3704		}
3705
3706	`)
3707
3708	// check the APEX keys
3709	keys := ctx.ModuleForTests(t, "myapex.key", "android_common").Module().(*apexKey)
3710
3711	if keys.publicKeyFile.String() != "vendor/foo/devkeys/testkey.avbpubkey" {
3712		t.Errorf("public key %q is not %q", keys.publicKeyFile.String(),
3713			"vendor/foo/devkeys/testkey.avbpubkey")
3714	}
3715	if keys.privateKeyFile.String() != "vendor/foo/devkeys/testkey.pem" {
3716		t.Errorf("private key %q is not %q", keys.privateKeyFile.String(),
3717			"vendor/foo/devkeys/testkey.pem")
3718	}
3719
3720	// check the APK certs. It should be overridden to myapex.certificate.override
3721	certs := ctx.ModuleForTests(t, "myapex_keytest", "android_common_myapex_keytest").Rule("signapk").Args["certificates"]
3722	if certs != "testkey.override.x509.pem testkey.override.pk8" {
3723		t.Errorf("cert and private key %q are not %q", certs,
3724			"testkey.override.509.pem testkey.override.pk8")
3725	}
3726}
3727
3728func TestCertificate(t *testing.T) {
3729	t.Parallel()
3730	t.Run("if unspecified, it defaults to DefaultAppCertificate", func(t *testing.T) {
3731		t.Parallel()
3732		ctx := testApex(t, `
3733			apex {
3734				name: "myapex",
3735				key: "myapex.key",
3736				updatable: false,
3737			}
3738			apex_key {
3739				name: "myapex.key",
3740				public_key: "testkey.avbpubkey",
3741				private_key: "testkey.pem",
3742			}`)
3743		rule := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Rule("signapk")
3744		expected := "vendor/foo/devkeys/test.x509.pem vendor/foo/devkeys/test.pk8"
3745		if actual := rule.Args["certificates"]; actual != expected {
3746			t.Errorf("certificates should be %q, not %q", expected, actual)
3747		}
3748	})
3749	t.Run("override when unspecified", func(t *testing.T) {
3750		t.Parallel()
3751		ctx := testApex(t, `
3752			apex {
3753				name: "myapex_keytest",
3754				key: "myapex.key",
3755				file_contexts: ":myapex-file_contexts",
3756				updatable: false,
3757			}
3758			apex_key {
3759				name: "myapex.key",
3760				public_key: "testkey.avbpubkey",
3761				private_key: "testkey.pem",
3762			}
3763			android_app_certificate {
3764				name: "myapex.certificate.override",
3765				certificate: "testkey.override",
3766			}`)
3767		rule := ctx.ModuleForTests(t, "myapex_keytest", "android_common_myapex_keytest").Rule("signapk")
3768		expected := "testkey.override.x509.pem testkey.override.pk8"
3769		if actual := rule.Args["certificates"]; actual != expected {
3770			t.Errorf("certificates should be %q, not %q", expected, actual)
3771		}
3772	})
3773	t.Run("if specified as :module, it respects the prop", func(t *testing.T) {
3774		t.Parallel()
3775		ctx := testApex(t, `
3776			apex {
3777				name: "myapex",
3778				key: "myapex.key",
3779				certificate: ":myapex.certificate",
3780				updatable: false,
3781			}
3782			apex_key {
3783				name: "myapex.key",
3784				public_key: "testkey.avbpubkey",
3785				private_key: "testkey.pem",
3786			}
3787			android_app_certificate {
3788				name: "myapex.certificate",
3789				certificate: "testkey",
3790			}`)
3791		rule := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Rule("signapk")
3792		expected := "testkey.x509.pem testkey.pk8"
3793		if actual := rule.Args["certificates"]; actual != expected {
3794			t.Errorf("certificates should be %q, not %q", expected, actual)
3795		}
3796	})
3797	t.Run("override when specifiec as <:module>", func(t *testing.T) {
3798		t.Parallel()
3799		ctx := testApex(t, `
3800			apex {
3801				name: "myapex_keytest",
3802				key: "myapex.key",
3803				file_contexts: ":myapex-file_contexts",
3804				certificate: ":myapex.certificate",
3805				updatable: false,
3806			}
3807			apex_key {
3808				name: "myapex.key",
3809				public_key: "testkey.avbpubkey",
3810				private_key: "testkey.pem",
3811			}
3812			android_app_certificate {
3813				name: "myapex.certificate.override",
3814				certificate: "testkey.override",
3815			}`)
3816		rule := ctx.ModuleForTests(t, "myapex_keytest", "android_common_myapex_keytest").Rule("signapk")
3817		expected := "testkey.override.x509.pem testkey.override.pk8"
3818		if actual := rule.Args["certificates"]; actual != expected {
3819			t.Errorf("certificates should be %q, not %q", expected, actual)
3820		}
3821	})
3822	t.Run("if specified as name, finds it from DefaultDevKeyDir", func(t *testing.T) {
3823		t.Parallel()
3824		ctx := testApex(t, `
3825			apex {
3826				name: "myapex",
3827				key: "myapex.key",
3828				certificate: "testkey",
3829				updatable: false,
3830			}
3831			apex_key {
3832				name: "myapex.key",
3833				public_key: "testkey.avbpubkey",
3834				private_key: "testkey.pem",
3835			}`,
3836			android.MockFS{
3837				"vendor/foo/devkeys/testkey.x509.pem": nil,
3838			}.AddToFixture(),
3839		)
3840		rule := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Rule("signapk")
3841		expected := "vendor/foo/devkeys/testkey.x509.pem vendor/foo/devkeys/testkey.pk8"
3842		if actual := rule.Args["certificates"]; actual != expected {
3843			t.Errorf("certificates should be %q, not %q", expected, actual)
3844		}
3845	})
3846	t.Run("override when specified as <name>", func(t *testing.T) {
3847		t.Parallel()
3848		ctx := testApex(t, `
3849			apex {
3850				name: "myapex_keytest",
3851				key: "myapex.key",
3852				file_contexts: ":myapex-file_contexts",
3853				certificate: "testkey",
3854				updatable: false,
3855			}
3856			apex_key {
3857				name: "myapex.key",
3858				public_key: "testkey.avbpubkey",
3859				private_key: "testkey.pem",
3860			}
3861			android_app_certificate {
3862				name: "myapex.certificate.override",
3863				certificate: "testkey.override",
3864			}`)
3865		rule := ctx.ModuleForTests(t, "myapex_keytest", "android_common_myapex_keytest").Rule("signapk")
3866		expected := "testkey.override.x509.pem testkey.override.pk8"
3867		if actual := rule.Args["certificates"]; actual != expected {
3868			t.Errorf("certificates should be %q, not %q", expected, actual)
3869		}
3870	})
3871}
3872
3873func TestMacro(t *testing.T) {
3874	t.Parallel()
3875	ctx := testApex(t, `
3876		apex {
3877			name: "myapex",
3878			key: "myapex.key",
3879			native_shared_libs: ["mylib", "mylib2"],
3880			updatable: false,
3881		}
3882
3883		apex {
3884			name: "otherapex",
3885			key: "myapex.key",
3886			native_shared_libs: ["mylib", "mylib2"],
3887			min_sdk_version: "29",
3888		}
3889
3890		apex_key {
3891			name: "myapex.key",
3892			public_key: "testkey.avbpubkey",
3893			private_key: "testkey.pem",
3894		}
3895
3896		cc_library {
3897			name: "mylib",
3898			srcs: ["mylib.cpp"],
3899			system_shared_libs: [],
3900			stl: "none",
3901			apex_available: [
3902				"myapex",
3903				"otherapex",
3904			],
3905			recovery_available: true,
3906			min_sdk_version: "29",
3907		}
3908		cc_library {
3909			name: "mylib2",
3910			srcs: ["mylib.cpp"],
3911			system_shared_libs: [],
3912			stl: "none",
3913			apex_available: [
3914				"myapex",
3915				"otherapex",
3916			],
3917			static_libs: ["mylib3"],
3918			recovery_available: true,
3919			min_sdk_version: "29",
3920		}
3921		cc_library {
3922			name: "mylib3",
3923			srcs: ["mylib.cpp"],
3924			system_shared_libs: [],
3925			stl: "none",
3926			apex_available: [
3927				"myapex",
3928				"otherapex",
3929			],
3930			recovery_available: true,
3931			min_sdk_version: "29",
3932		}
3933	`)
3934
3935	// non-APEX variant does not have __ANDROID_APEX__ defined
3936	mylibCFlags := ctx.ModuleForTests(t, "mylib", "android_arm64_armv8-a_static").Rule("cc").Args["cFlags"]
3937	ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX__")
3938
3939	// APEX variant has __ANDROID_APEX__ and __ANDROID_APEX__ defined
3940	mylibCFlags = ctx.ModuleForTests(t, "mylib", "android_arm64_armv8-a_static_apex10000").Rule("cc").Args["cFlags"]
3941	ensureContains(t, mylibCFlags, "-D__ANDROID_APEX__")
3942
3943	// APEX variant has __ANDROID_APEX__ and __ANDROID_APEX__ defined
3944	mylibCFlags = ctx.ModuleForTests(t, "mylib", "android_arm64_armv8-a_static_apex29").Rule("cc").Args["cFlags"]
3945	ensureContains(t, mylibCFlags, "-D__ANDROID_APEX__")
3946
3947	// When a cc_library sets use_apex_name_macro: true each apex gets a unique variant and
3948	// each variant defines additional macros to distinguish which apex variant it is built for
3949
3950	// non-APEX variant does not have __ANDROID_APEX__ defined
3951	mylibCFlags = ctx.ModuleForTests(t, "mylib3", "android_arm64_armv8-a_static").Rule("cc").Args["cFlags"]
3952	ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX__")
3953
3954	// recovery variant does not set __ANDROID_APEX__
3955	mylibCFlags = ctx.ModuleForTests(t, "mylib3", "android_recovery_arm64_armv8-a_static").Rule("cc").Args["cFlags"]
3956	ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX__")
3957
3958	// non-APEX variant does not have __ANDROID_APEX__ defined
3959	mylibCFlags = ctx.ModuleForTests(t, "mylib2", "android_arm64_armv8-a_static").Rule("cc").Args["cFlags"]
3960	ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX__")
3961
3962	// recovery variant does not set __ANDROID_APEX__
3963	mylibCFlags = ctx.ModuleForTests(t, "mylib2", "android_recovery_arm64_armv8-a_static").Rule("cc").Args["cFlags"]
3964	ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX__")
3965}
3966
3967func TestHeaderLibsDependency(t *testing.T) {
3968	t.Parallel()
3969	ctx := testApex(t, `
3970		apex {
3971			name: "myapex",
3972			key: "myapex.key",
3973			native_shared_libs: ["mylib"],
3974			updatable: false,
3975		}
3976
3977		apex_key {
3978			name: "myapex.key",
3979			public_key: "testkey.avbpubkey",
3980			private_key: "testkey.pem",
3981		}
3982
3983		cc_library_headers {
3984			name: "mylib_headers",
3985			export_include_dirs: ["my_include"],
3986			system_shared_libs: [],
3987			stl: "none",
3988			apex_available: [ "myapex" ],
3989		}
3990
3991		cc_library {
3992			name: "mylib",
3993			srcs: ["mylib.cpp"],
3994			system_shared_libs: [],
3995			stl: "none",
3996			header_libs: ["mylib_headers"],
3997			export_header_lib_headers: ["mylib_headers"],
3998			stubs: {
3999				versions: ["1", "2", "3"],
4000			},
4001			apex_available: [ "myapex" ],
4002		}
4003
4004		cc_library {
4005			name: "otherlib",
4006			srcs: ["mylib.cpp"],
4007			system_shared_libs: [],
4008			stl: "none",
4009			shared_libs: ["mylib"],
4010		}
4011	`)
4012
4013	cFlags := ctx.ModuleForTests(t, "otherlib", "android_arm64_armv8-a_static").Rule("cc").Args["cFlags"]
4014
4015	// Ensure that the include path of the header lib is exported to 'otherlib'
4016	ensureContains(t, cFlags, "-Imy_include")
4017}
4018
4019type fileInApex struct {
4020	path   string // path in apex
4021	src    string // src path
4022	isLink bool
4023}
4024
4025func (f fileInApex) String() string {
4026	return f.src + ":" + f.path
4027}
4028
4029func (f fileInApex) match(expectation string) bool {
4030	parts := strings.Split(expectation, ":")
4031	if len(parts) == 1 {
4032		match, _ := path.Match(parts[0], f.path)
4033		return match
4034	}
4035	if len(parts) == 2 {
4036		matchSrc, _ := path.Match(parts[0], f.src)
4037		matchDst, _ := path.Match(parts[1], f.path)
4038		return matchSrc && matchDst
4039	}
4040	panic("invalid expected file specification: " + expectation)
4041}
4042
4043func getFiles(t *testing.T, ctx *android.TestContext, moduleName, variant string) []fileInApex {
4044	t.Helper()
4045	module := ctx.ModuleForTests(t, moduleName, variant)
4046	apexRule := module.MaybeRule("apexRule")
4047	apexDir := "/image.apex/"
4048	copyCmds := apexRule.Args["copy_commands"]
4049	var ret []fileInApex
4050	for _, cmd := range strings.Split(copyCmds, "&&") {
4051		cmd = strings.TrimSpace(cmd)
4052		if cmd == "" {
4053			continue
4054		}
4055		terms := strings.Split(cmd, " ")
4056		var dst, src string
4057		var isLink bool
4058		switch terms[0] {
4059		case "mkdir":
4060		case "cp":
4061			if len(terms) != 3 && len(terms) != 4 {
4062				t.Fatal("copyCmds contains invalid cp command", cmd)
4063			}
4064			dst = terms[len(terms)-1]
4065			src = terms[len(terms)-2]
4066			isLink = false
4067		case "ln":
4068			if len(terms) != 3 && len(terms) != 4 {
4069				// ln LINK TARGET or ln -s LINK TARGET
4070				t.Fatal("copyCmds contains invalid ln command", cmd)
4071			}
4072			dst = terms[len(terms)-1]
4073			src = terms[len(terms)-2]
4074			isLink = true
4075		default:
4076			t.Fatalf("copyCmds should contain mkdir/cp commands only: %q", cmd)
4077		}
4078		if dst != "" {
4079			index := strings.Index(dst, apexDir)
4080			if index == -1 {
4081				t.Fatal("copyCmds should copy a file to "+apexDir, cmd)
4082			}
4083			dstFile := dst[index+len(apexDir):]
4084			ret = append(ret, fileInApex{path: dstFile, src: src, isLink: isLink})
4085		}
4086	}
4087	return ret
4088}
4089
4090func assertFileListEquals(t *testing.T, expectedFiles []string, actualFiles []fileInApex) {
4091	t.Helper()
4092	var failed bool
4093	var surplus []string
4094	filesMatched := make(map[string]bool)
4095	for _, file := range actualFiles {
4096		matchFound := false
4097		for _, expected := range expectedFiles {
4098			if file.match(expected) {
4099				matchFound = true
4100				filesMatched[expected] = true
4101				break
4102			}
4103		}
4104		if !matchFound {
4105			surplus = append(surplus, file.String())
4106		}
4107	}
4108
4109	if len(surplus) > 0 {
4110		sort.Strings(surplus)
4111		t.Log("surplus files", surplus)
4112		failed = true
4113	}
4114
4115	if len(expectedFiles) > len(filesMatched) {
4116		var missing []string
4117		for _, expected := range expectedFiles {
4118			if !filesMatched[expected] {
4119				missing = append(missing, expected)
4120			}
4121		}
4122		sort.Strings(missing)
4123		t.Log("missing files", missing)
4124		failed = true
4125	}
4126	if failed {
4127		t.Fail()
4128	}
4129}
4130
4131func ensureExactContents(t *testing.T, ctx *android.TestContext, moduleName, variant string, files []string) {
4132	assertFileListEquals(t, files, getFiles(t, ctx, moduleName, variant))
4133}
4134
4135func ensureExactDeapexedContents(t *testing.T, ctx *android.TestContext, moduleName string, variant string, files []string) {
4136	deapexer := ctx.ModuleForTests(t, moduleName, variant).Description("deapex")
4137	outputs := make([]string, 0, len(deapexer.ImplicitOutputs)+1)
4138	if deapexer.Output != nil {
4139		outputs = append(outputs, deapexer.Output.String())
4140	}
4141	for _, output := range deapexer.ImplicitOutputs {
4142		outputs = append(outputs, output.String())
4143	}
4144	actualFiles := make([]fileInApex, 0, len(outputs))
4145	for _, output := range outputs {
4146		dir := "/deapexer/"
4147		pos := strings.LastIndex(output, dir)
4148		if pos == -1 {
4149			t.Fatal("Unknown deapexer output ", output)
4150		}
4151		path := output[pos+len(dir):]
4152		actualFiles = append(actualFiles, fileInApex{path: path, src: "", isLink: false})
4153	}
4154	assertFileListEquals(t, files, actualFiles)
4155}
4156
4157func vndkLibrariesTxtFiles(vers ...string) (result string) {
4158	for _, v := range vers {
4159		for _, txt := range []string{"llndk", "vndkcore", "vndksp", "vndkprivate", "vndkproduct"} {
4160			result += `
4161					prebuilt_etc {
4162						name: "` + txt + `.libraries.` + v + `.txt",
4163						src: "dummy.txt",
4164					}
4165				`
4166		}
4167	}
4168	return
4169}
4170
4171func TestVndkApexVersion(t *testing.T) {
4172	t.Parallel()
4173	ctx := testApex(t, `
4174		apex_vndk {
4175			name: "com.android.vndk.v27",
4176			key: "myapex.key",
4177			file_contexts: ":myapex-file_contexts",
4178			vndk_version: "27",
4179			updatable: false,
4180		}
4181
4182		apex_key {
4183			name: "myapex.key",
4184			public_key: "testkey.avbpubkey",
4185			private_key: "testkey.pem",
4186		}
4187
4188		vndk_prebuilt_shared {
4189			name: "libvndk27",
4190			version: "27",
4191			vendor_available: true,
4192			product_available: true,
4193			vndk: {
4194				enabled: true,
4195			},
4196			target_arch: "arm64",
4197			arch: {
4198				arm: {
4199					srcs: ["libvndk27_arm.so"],
4200				},
4201				arm64: {
4202					srcs: ["libvndk27_arm64.so"],
4203				},
4204			},
4205			apex_available: [ "com.android.vndk.v27" ],
4206		}
4207
4208		vndk_prebuilt_shared {
4209			name: "libvndk27",
4210			version: "27",
4211			vendor_available: true,
4212			product_available: true,
4213			vndk: {
4214				enabled: true,
4215			},
4216			target_arch: "x86_64",
4217			arch: {
4218				x86: {
4219					srcs: ["libvndk27_x86.so"],
4220				},
4221				x86_64: {
4222					srcs: ["libvndk27_x86_64.so"],
4223				},
4224			},
4225		}
4226		`+vndkLibrariesTxtFiles("27"),
4227		withFiles(map[string][]byte{
4228			"libvndk27_arm.so":    nil,
4229			"libvndk27_arm64.so":  nil,
4230			"libvndk27_x86.so":    nil,
4231			"libvndk27_x86_64.so": nil,
4232		}))
4233
4234	ensureExactContents(t, ctx, "com.android.vndk.v27", "android_common", []string{
4235		"lib/libvndk27_arm.so",
4236		"lib64/libvndk27_arm64.so",
4237		"etc/*",
4238	})
4239}
4240
4241func TestVndkApexNameRule(t *testing.T) {
4242	t.Parallel()
4243	ctx := testApex(t, `
4244		apex_vndk {
4245			name: "com.android.vndk.v29",
4246			key: "myapex.key",
4247			file_contexts: ":myapex-file_contexts",
4248			vndk_version: "29",
4249			updatable: false,
4250		}
4251		apex_vndk {
4252			name: "com.android.vndk.v28",
4253			key: "myapex.key",
4254			file_contexts: ":myapex-file_contexts",
4255			vndk_version: "28",
4256			updatable: false,
4257		}
4258		apex_key {
4259			name: "myapex.key",
4260			public_key: "testkey.avbpubkey",
4261			private_key: "testkey.pem",
4262		}`+vndkLibrariesTxtFiles("28", "29"))
4263
4264	assertApexName := func(expected, moduleName string) {
4265		module := ctx.ModuleForTests(t, moduleName, "android_common")
4266		apexManifestRule := module.Rule("apexManifestRule")
4267		ensureContains(t, apexManifestRule.Args["opt"], "-v name "+expected)
4268	}
4269
4270	assertApexName("com.android.vndk.v29", "com.android.vndk.v29")
4271	assertApexName("com.android.vndk.v28", "com.android.vndk.v28")
4272}
4273
4274func TestVndkApexDoesntSupportNativeBridgeSupported(t *testing.T) {
4275	t.Parallel()
4276	testApexError(t, `module "com.android.vndk.v30" .*: native_bridge_supported: .* doesn't support native bridge binary`, `
4277		apex_vndk {
4278			name: "com.android.vndk.v30",
4279			key: "com.android.vndk.v30.key",
4280			file_contexts: ":myapex-file_contexts",
4281			native_bridge_supported: true,
4282		}
4283
4284		apex_key {
4285			name: "com.android.vndk.v30.key",
4286			public_key: "testkey.avbpubkey",
4287			private_key: "testkey.pem",
4288		}
4289
4290		vndk_prebuilt_shared {
4291			name: "libvndk",
4292			version: "30",
4293			target_arch: "arm",
4294			srcs: ["mylib.cpp"],
4295			vendor_available: true,
4296			product_available: true,
4297			native_bridge_supported: true,
4298			vndk: {
4299				enabled: true,
4300			},
4301		}
4302	`)
4303}
4304
4305func TestVndkApexWithBinder32(t *testing.T) {
4306	t.Parallel()
4307	ctx := testApex(t, `
4308		apex_vndk {
4309			name: "com.android.vndk.v27",
4310			key: "myapex.key",
4311			file_contexts: ":myapex-file_contexts",
4312			vndk_version: "27",
4313			updatable: false,
4314		}
4315
4316		apex_key {
4317			name: "myapex.key",
4318			public_key: "testkey.avbpubkey",
4319			private_key: "testkey.pem",
4320		}
4321
4322		vndk_prebuilt_shared {
4323			name: "libvndk27",
4324			version: "27",
4325			target_arch: "arm",
4326			vendor_available: true,
4327			product_available: true,
4328			vndk: {
4329				enabled: true,
4330			},
4331			arch: {
4332				arm: {
4333					srcs: ["libvndk27.so"],
4334				}
4335			},
4336		}
4337
4338		vndk_prebuilt_shared {
4339			name: "libvndk27",
4340			version: "27",
4341			target_arch: "arm",
4342			binder32bit: true,
4343			vendor_available: true,
4344			product_available: true,
4345			vndk: {
4346				enabled: true,
4347			},
4348			arch: {
4349				arm: {
4350					srcs: ["libvndk27binder32.so"],
4351				}
4352			},
4353			apex_available: [ "com.android.vndk.v27" ],
4354		}
4355		`+vndkLibrariesTxtFiles("27"),
4356		withFiles(map[string][]byte{
4357			"libvndk27.so":         nil,
4358			"libvndk27binder32.so": nil,
4359		}),
4360		withBinder32bit,
4361		android.FixtureModifyConfig(func(config android.Config) {
4362			target := android.Target{
4363				Os: android.Android,
4364				Arch: android.Arch{
4365					ArchType:    android.Arm,
4366					ArchVariant: "armv7-a-neon",
4367					Abi:         []string{"armeabi-v7a"},
4368				},
4369				NativeBridge:             android.NativeBridgeDisabled,
4370				NativeBridgeHostArchName: "",
4371				NativeBridgeRelativePath: "",
4372			}
4373			config.Targets[android.Android] = []android.Target{target}
4374			config.AndroidFirstDeviceTarget = target
4375		}),
4376	)
4377
4378	ensureExactContents(t, ctx, "com.android.vndk.v27", "android_common", []string{
4379		"lib/libvndk27binder32.so",
4380		"etc/*",
4381	})
4382}
4383
4384func TestDependenciesInApexManifest(t *testing.T) {
4385	t.Parallel()
4386	ctx := testApex(t, `
4387		apex {
4388			name: "myapex_nodep",
4389			key: "myapex.key",
4390			native_shared_libs: ["lib_nodep"],
4391			compile_multilib: "both",
4392			file_contexts: ":myapex-file_contexts",
4393			updatable: false,
4394		}
4395
4396		apex {
4397			name: "myapex_dep",
4398			key: "myapex.key",
4399			native_shared_libs: ["lib_dep"],
4400			compile_multilib: "both",
4401			file_contexts: ":myapex-file_contexts",
4402			updatable: false,
4403		}
4404
4405		apex {
4406			name: "myapex_provider",
4407			key: "myapex.key",
4408			native_shared_libs: ["libfoo"],
4409			compile_multilib: "both",
4410			file_contexts: ":myapex-file_contexts",
4411			updatable: false,
4412		}
4413
4414		apex {
4415			name: "myapex_selfcontained",
4416			key: "myapex.key",
4417			native_shared_libs: ["lib_dep_on_bar", "libbar"],
4418			compile_multilib: "both",
4419			file_contexts: ":myapex-file_contexts",
4420			updatable: false,
4421		}
4422
4423		apex_key {
4424			name: "myapex.key",
4425			public_key: "testkey.avbpubkey",
4426			private_key: "testkey.pem",
4427		}
4428
4429		cc_library {
4430			name: "lib_nodep",
4431			srcs: ["mylib.cpp"],
4432			system_shared_libs: [],
4433			stl: "none",
4434			apex_available: [ "myapex_nodep" ],
4435		}
4436
4437		cc_library {
4438			name: "lib_dep",
4439			srcs: ["mylib.cpp"],
4440			shared_libs: ["libfoo"],
4441			system_shared_libs: [],
4442			stl: "none",
4443			apex_available: [
4444				"myapex_dep",
4445				"myapex_provider",
4446				"myapex_selfcontained",
4447			],
4448		}
4449
4450		cc_library {
4451			name: "lib_dep_on_bar",
4452			srcs: ["mylib.cpp"],
4453			shared_libs: ["libbar"],
4454			system_shared_libs: [],
4455			stl: "none",
4456			apex_available: [
4457				"myapex_selfcontained",
4458			],
4459		}
4460
4461
4462		cc_library {
4463			name: "libfoo",
4464			srcs: ["mytest.cpp"],
4465			stubs: {
4466				versions: ["1"],
4467			},
4468			system_shared_libs: [],
4469			stl: "none",
4470			apex_available: [
4471				"myapex_provider",
4472			],
4473		}
4474
4475		cc_library {
4476			name: "libbar",
4477			srcs: ["mytest.cpp"],
4478			stubs: {
4479				versions: ["1"],
4480			},
4481			system_shared_libs: [],
4482			stl: "none",
4483			apex_available: [
4484				"myapex_selfcontained",
4485			],
4486		}
4487
4488	`)
4489
4490	var apexManifestRule android.TestingBuildParams
4491	var provideNativeLibs, requireNativeLibs []string
4492
4493	apexManifestRule = ctx.ModuleForTests(t, "myapex_nodep", "android_common_myapex_nodep").Rule("apexManifestRule")
4494	provideNativeLibs = names(apexManifestRule.Args["provideNativeLibs"])
4495	requireNativeLibs = names(apexManifestRule.Args["requireNativeLibs"])
4496	ensureListEmpty(t, provideNativeLibs)
4497	ensureListEmpty(t, requireNativeLibs)
4498
4499	apexManifestRule = ctx.ModuleForTests(t, "myapex_dep", "android_common_myapex_dep").Rule("apexManifestRule")
4500	provideNativeLibs = names(apexManifestRule.Args["provideNativeLibs"])
4501	requireNativeLibs = names(apexManifestRule.Args["requireNativeLibs"])
4502	ensureListEmpty(t, provideNativeLibs)
4503	ensureListContains(t, requireNativeLibs, "libfoo.so")
4504
4505	apexManifestRule = ctx.ModuleForTests(t, "myapex_provider", "android_common_myapex_provider").Rule("apexManifestRule")
4506	provideNativeLibs = names(apexManifestRule.Args["provideNativeLibs"])
4507	requireNativeLibs = names(apexManifestRule.Args["requireNativeLibs"])
4508	ensureListContains(t, provideNativeLibs, "libfoo.so")
4509	ensureListEmpty(t, requireNativeLibs)
4510
4511	apexManifestRule = ctx.ModuleForTests(t, "myapex_selfcontained", "android_common_myapex_selfcontained").Rule("apexManifestRule")
4512	provideNativeLibs = names(apexManifestRule.Args["provideNativeLibs"])
4513	requireNativeLibs = names(apexManifestRule.Args["requireNativeLibs"])
4514	ensureListContains(t, provideNativeLibs, "libbar.so")
4515	ensureListEmpty(t, requireNativeLibs)
4516}
4517
4518func TestOverrideApexManifestDefaultVersion(t *testing.T) {
4519	t.Parallel()
4520	ctx := testApex(t, `
4521		apex {
4522			name: "myapex",
4523			key: "myapex.key",
4524			native_shared_libs: ["mylib"],
4525			updatable: false,
4526		}
4527
4528		apex_key {
4529			name: "myapex.key",
4530			public_key: "testkey.avbpubkey",
4531			private_key: "testkey.pem",
4532		}
4533
4534		cc_library {
4535			name: "mylib",
4536			srcs: ["mylib.cpp"],
4537			system_shared_libs: [],
4538			stl: "none",
4539			apex_available: [
4540				"//apex_available:platform",
4541				"myapex",
4542			],
4543		}
4544	`, android.FixtureMergeEnv(map[string]string{
4545		"OVERRIDE_APEX_MANIFEST_DEFAULT_VERSION": "1234",
4546	}))
4547
4548	module := ctx.ModuleForTests(t, "myapex", "android_common_myapex")
4549	apexManifestRule := module.Rule("apexManifestRule")
4550	ensureContains(t, apexManifestRule.Args["default_version"], "1234")
4551}
4552
4553func TestCompileMultilibProp(t *testing.T) {
4554	t.Parallel()
4555	testCases := []struct {
4556		compileMultiLibProp string
4557		containedLibs       []string
4558		notContainedLibs    []string
4559	}{
4560		{
4561			containedLibs: []string{
4562				"image.apex/lib64/mylib.so",
4563				"image.apex/lib/mylib.so",
4564			},
4565			compileMultiLibProp: `compile_multilib: "both",`,
4566		},
4567		{
4568			containedLibs:       []string{"image.apex/lib64/mylib.so"},
4569			notContainedLibs:    []string{"image.apex/lib/mylib.so"},
4570			compileMultiLibProp: `compile_multilib: "first",`,
4571		},
4572		{
4573			containedLibs:    []string{"image.apex/lib64/mylib.so"},
4574			notContainedLibs: []string{"image.apex/lib/mylib.so"},
4575			// compile_multilib, when unset, should result to the same output as when compile_multilib is "first"
4576		},
4577		{
4578			containedLibs:       []string{"image.apex/lib64/mylib.so"},
4579			notContainedLibs:    []string{"image.apex/lib/mylib.so"},
4580			compileMultiLibProp: `compile_multilib: "64",`,
4581		},
4582		{
4583			containedLibs:       []string{"image.apex/lib/mylib.so"},
4584			notContainedLibs:    []string{"image.apex/lib64/mylib.so"},
4585			compileMultiLibProp: `compile_multilib: "32",`,
4586		},
4587	}
4588	for _, testCase := range testCases {
4589		ctx := testApex(t, fmt.Sprintf(`
4590			apex {
4591				name: "myapex",
4592				key: "myapex.key",
4593				%s
4594				native_shared_libs: ["mylib"],
4595				updatable: false,
4596			}
4597			apex_key {
4598				name: "myapex.key",
4599				public_key: "testkey.avbpubkey",
4600				private_key: "testkey.pem",
4601			}
4602			cc_library {
4603				name: "mylib",
4604				srcs: ["mylib.cpp"],
4605				apex_available: [
4606					"//apex_available:platform",
4607					"myapex",
4608			],
4609			}
4610		`, testCase.compileMultiLibProp),
4611		)
4612		module := ctx.ModuleForTests(t, "myapex", "android_common_myapex")
4613		apexRule := module.Rule("apexRule")
4614		copyCmds := apexRule.Args["copy_commands"]
4615		for _, containedLib := range testCase.containedLibs {
4616			ensureContains(t, copyCmds, containedLib)
4617		}
4618		for _, notContainedLib := range testCase.notContainedLibs {
4619			ensureNotContains(t, copyCmds, notContainedLib)
4620		}
4621	}
4622}
4623
4624func TestNonTestApex(t *testing.T) {
4625	t.Parallel()
4626	ctx := testApex(t, `
4627		apex {
4628			name: "myapex",
4629			key: "myapex.key",
4630			native_shared_libs: ["mylib_common"],
4631			updatable: false,
4632		}
4633
4634		apex_key {
4635			name: "myapex.key",
4636			public_key: "testkey.avbpubkey",
4637			private_key: "testkey.pem",
4638		}
4639
4640		cc_library {
4641			name: "mylib_common",
4642			srcs: ["mylib.cpp"],
4643			system_shared_libs: [],
4644			stl: "none",
4645			apex_available: [
4646					"//apex_available:platform",
4647				  "myapex",
4648		  ],
4649		}
4650	`)
4651
4652	module := ctx.ModuleForTests(t, "myapex", "android_common_myapex")
4653	apexRule := module.Rule("apexRule")
4654	copyCmds := apexRule.Args["copy_commands"]
4655
4656	if apex, ok := module.Module().(*apexBundle); !ok || apex.testApex {
4657		t.Log("Apex was a test apex!")
4658		t.Fail()
4659	}
4660	// Ensure that main rule creates an output
4661	ensureContains(t, apexRule.Output.String(), "myapex.apex.unsigned")
4662
4663	// Ensure that apex variant is created for the direct dep
4664	ensureListContains(t, ctx.ModuleVariantsForTests("mylib_common"), "android_arm64_armv8-a_shared_apex10000")
4665
4666	// Ensure that both direct and indirect deps are copied into apex
4667	ensureContains(t, copyCmds, "image.apex/lib64/mylib_common.so")
4668
4669	// Ensure that the platform variant ends with _shared
4670	ensureListContains(t, ctx.ModuleVariantsForTests("mylib_common"), "android_arm64_armv8-a_shared")
4671
4672	if !ctx.ModuleForTests(t, "mylib_common", "android_arm64_armv8-a_shared_apex10000").Module().(*cc.Module).InAnyApex() {
4673		t.Log("Found mylib_common not in any apex!")
4674		t.Fail()
4675	}
4676}
4677
4678func TestTestApex(t *testing.T) {
4679	t.Parallel()
4680	ctx := testApex(t, `
4681		apex_test {
4682			name: "myapex",
4683			key: "myapex.key",
4684			native_shared_libs: ["mylib_common_test"],
4685			updatable: false,
4686		}
4687
4688		apex_key {
4689			name: "myapex.key",
4690			public_key: "testkey.avbpubkey",
4691			private_key: "testkey.pem",
4692		}
4693
4694		cc_library {
4695			name: "mylib_common_test",
4696			srcs: ["mylib.cpp"],
4697			system_shared_libs: [],
4698			stl: "none",
4699			// TODO: remove //apex_available:platform
4700			apex_available: [
4701				"//apex_available:platform",
4702				"myapex",
4703			],
4704		}
4705	`)
4706
4707	module := ctx.ModuleForTests(t, "myapex", "android_common_myapex")
4708	apexRule := module.Rule("apexRule")
4709	copyCmds := apexRule.Args["copy_commands"]
4710
4711	if apex, ok := module.Module().(*apexBundle); !ok || !apex.testApex {
4712		t.Log("Apex was not a test apex!")
4713		t.Fail()
4714	}
4715	// Ensure that main rule creates an output
4716	ensureContains(t, apexRule.Output.String(), "myapex.apex.unsigned")
4717
4718	// Ensure that apex variant is created for the direct dep
4719	ensureListContains(t, ctx.ModuleVariantsForTests("mylib_common_test"), "android_arm64_armv8-a_shared_apex10000")
4720
4721	// Ensure that both direct and indirect deps are copied into apex
4722	ensureContains(t, copyCmds, "image.apex/lib64/mylib_common_test.so")
4723
4724	// Ensure that the platform variant ends with _shared
4725	ensureListContains(t, ctx.ModuleVariantsForTests("mylib_common_test"), "android_arm64_armv8-a_shared")
4726}
4727
4728func TestLibzVendorIsntStable(t *testing.T) {
4729	t.Parallel()
4730	ctx := testApex(t, `
4731	apex {
4732		name: "myapex",
4733		key: "myapex.key",
4734		updatable: false,
4735		binaries: ["mybin"],
4736	}
4737	apex {
4738		name: "myvendorapex",
4739		key: "myapex.key",
4740		file_contexts: "myvendorapex_file_contexts",
4741		vendor: true,
4742		updatable: false,
4743		binaries: ["mybin"],
4744	}
4745	apex_key {
4746		name: "myapex.key",
4747		public_key: "testkey.avbpubkey",
4748		private_key: "testkey.pem",
4749	}
4750	cc_binary {
4751		name: "mybin",
4752		vendor_available: true,
4753		system_shared_libs: [],
4754		stl: "none",
4755		shared_libs: ["libz"],
4756		apex_available: ["//apex_available:anyapex"],
4757	}
4758	cc_library {
4759		name: "libz",
4760		vendor_available: true,
4761		system_shared_libs: [],
4762		stl: "none",
4763		stubs: {
4764			versions: ["28", "30"],
4765		},
4766		target: {
4767			vendor: {
4768				no_stubs: true,
4769			},
4770		},
4771	}
4772	`, withFiles(map[string][]byte{
4773		"myvendorapex_file_contexts": nil,
4774	}))
4775
4776	// libz provides stubs for core variant.
4777	{
4778		ensureExactContents(t, ctx, "myapex", "android_common_myapex", []string{
4779			"bin/mybin",
4780		})
4781		apexManifestRule := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Rule("apexManifestRule")
4782		android.AssertStringEquals(t, "should require libz", apexManifestRule.Args["requireNativeLibs"], "libz.so")
4783	}
4784	// libz doesn't provide stubs for vendor variant.
4785	{
4786		ensureExactContents(t, ctx, "myvendorapex", "android_common_myvendorapex", []string{
4787			"bin/mybin",
4788			"lib64/libz.so",
4789		})
4790		apexManifestRule := ctx.ModuleForTests(t, "myvendorapex", "android_common_myvendorapex").Rule("apexManifestRule")
4791		android.AssertStringEquals(t, "should not require libz", apexManifestRule.Args["requireNativeLibs"], "")
4792	}
4793}
4794
4795func TestApexWithTarget(t *testing.T) {
4796	t.Parallel()
4797	ctx := testApex(t, `
4798		apex {
4799			name: "myapex",
4800			key: "myapex.key",
4801			updatable: false,
4802			multilib: {
4803				first: {
4804					native_shared_libs: ["mylib_common"],
4805				}
4806			},
4807			target: {
4808				android: {
4809					multilib: {
4810						first: {
4811							native_shared_libs: ["mylib"],
4812						}
4813					}
4814				},
4815				host: {
4816					multilib: {
4817						first: {
4818							native_shared_libs: ["mylib2"],
4819						}
4820					}
4821				}
4822			}
4823		}
4824
4825		apex_key {
4826			name: "myapex.key",
4827			public_key: "testkey.avbpubkey",
4828			private_key: "testkey.pem",
4829		}
4830
4831		cc_library {
4832			name: "mylib",
4833			srcs: ["mylib.cpp"],
4834			system_shared_libs: [],
4835			stl: "none",
4836			// TODO: remove //apex_available:platform
4837			apex_available: [
4838				"//apex_available:platform",
4839				"myapex",
4840			],
4841		}
4842
4843		cc_library {
4844			name: "mylib_common",
4845			srcs: ["mylib.cpp"],
4846			system_shared_libs: [],
4847			stl: "none",
4848			compile_multilib: "first",
4849			// TODO: remove //apex_available:platform
4850			apex_available: [
4851				"//apex_available:platform",
4852				"myapex",
4853			],
4854		}
4855
4856		cc_library {
4857			name: "mylib2",
4858			srcs: ["mylib.cpp"],
4859			system_shared_libs: [],
4860			stl: "none",
4861			compile_multilib: "first",
4862		}
4863	`)
4864
4865	apexRule := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Rule("apexRule")
4866	copyCmds := apexRule.Args["copy_commands"]
4867
4868	// Ensure that main rule creates an output
4869	ensureContains(t, apexRule.Output.String(), "myapex.apex.unsigned")
4870
4871	// Ensure that apex variant is created for the direct dep
4872	ensureListContains(t, ctx.ModuleVariantsForTests("mylib"), "android_arm64_armv8-a_shared_apex10000")
4873	ensureListContains(t, ctx.ModuleVariantsForTests("mylib_common"), "android_arm64_armv8-a_shared_apex10000")
4874	ensureListNotContains(t, ctx.ModuleVariantsForTests("mylib2"), "android_arm64_armv8-a_shared_apex10000")
4875
4876	// Ensure that both direct and indirect deps are copied into apex
4877	ensureContains(t, copyCmds, "image.apex/lib64/mylib.so")
4878	ensureContains(t, copyCmds, "image.apex/lib64/mylib_common.so")
4879	ensureNotContains(t, copyCmds, "image.apex/lib64/mylib2.so")
4880
4881	// Ensure that the platform variant ends with _shared
4882	ensureListContains(t, ctx.ModuleVariantsForTests("mylib"), "android_arm64_armv8-a_shared")
4883	ensureListContains(t, ctx.ModuleVariantsForTests("mylib_common"), "android_arm64_armv8-a_shared")
4884	ensureListContains(t, ctx.ModuleVariantsForTests("mylib2"), "android_arm64_armv8-a_shared")
4885}
4886
4887func TestApexWithArch(t *testing.T) {
4888	t.Parallel()
4889	ctx := testApex(t, `
4890		apex {
4891			name: "myapex",
4892			key: "myapex.key",
4893			updatable: false,
4894			native_shared_libs: ["mylib.generic"],
4895			arch: {
4896				arm64: {
4897					native_shared_libs: ["mylib.arm64"],
4898					exclude_native_shared_libs: ["mylib.generic"],
4899				},
4900				x86_64: {
4901					native_shared_libs: ["mylib.x64"],
4902					exclude_native_shared_libs: ["mylib.generic"],
4903				},
4904			}
4905		}
4906
4907		apex_key {
4908			name: "myapex.key",
4909			public_key: "testkey.avbpubkey",
4910			private_key: "testkey.pem",
4911		}
4912
4913		cc_library {
4914			name: "mylib.generic",
4915			srcs: ["mylib.cpp"],
4916			system_shared_libs: [],
4917			stl: "none",
4918			// TODO: remove //apex_available:platform
4919			apex_available: [
4920				"//apex_available:platform",
4921				"myapex",
4922			],
4923		}
4924
4925		cc_library {
4926			name: "mylib.arm64",
4927			srcs: ["mylib.cpp"],
4928			system_shared_libs: [],
4929			stl: "none",
4930			// TODO: remove //apex_available:platform
4931			apex_available: [
4932				"//apex_available:platform",
4933				"myapex",
4934			],
4935		}
4936
4937		cc_library {
4938			name: "mylib.x64",
4939			srcs: ["mylib.cpp"],
4940			system_shared_libs: [],
4941			stl: "none",
4942			// TODO: remove //apex_available:platform
4943			apex_available: [
4944				"//apex_available:platform",
4945				"myapex",
4946			],
4947		}
4948	`)
4949
4950	apexRule := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Rule("apexRule")
4951	copyCmds := apexRule.Args["copy_commands"]
4952
4953	// Ensure that apex variant is created for the direct dep
4954	ensureListContains(t, ctx.ModuleVariantsForTests("mylib.arm64"), "android_arm64_armv8-a_shared_apex10000")
4955	ensureListNotContains(t, ctx.ModuleVariantsForTests("mylib.generic"), "android_arm64_armv8-a_shared_apex10000")
4956	ensureListNotContains(t, ctx.ModuleVariantsForTests("mylib.x64"), "android_arm64_armv8-a_shared_apex10000")
4957
4958	// Ensure that both direct and indirect deps are copied into apex
4959	ensureContains(t, copyCmds, "image.apex/lib64/mylib.arm64.so")
4960	ensureNotContains(t, copyCmds, "image.apex/lib64/mylib.x64.so")
4961}
4962
4963func TestApexWithShBinary(t *testing.T) {
4964	t.Parallel()
4965	ctx := testApex(t, `
4966		apex {
4967			name: "myapex",
4968			key: "myapex.key",
4969			sh_binaries: ["myscript"],
4970			updatable: false,
4971			compile_multilib: "both",
4972		}
4973
4974		apex_key {
4975			name: "myapex.key",
4976			public_key: "testkey.avbpubkey",
4977			private_key: "testkey.pem",
4978		}
4979
4980		sh_binary {
4981			name: "myscript",
4982			src: "mylib.cpp",
4983			filename: "myscript.sh",
4984			sub_dir: "script",
4985		}
4986	`)
4987
4988	apexRule := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Rule("apexRule")
4989	copyCmds := apexRule.Args["copy_commands"]
4990
4991	ensureContains(t, copyCmds, "image.apex/bin/script/myscript.sh")
4992}
4993
4994func TestApexInVariousPartition(t *testing.T) {
4995	t.Parallel()
4996	testcases := []struct {
4997		propName, partition string
4998	}{
4999		{"", "system"},
5000		{"product_specific: true", "product"},
5001		{"soc_specific: true", "vendor"},
5002		{"proprietary: true", "vendor"},
5003		{"vendor: true", "vendor"},
5004		{"system_ext_specific: true", "system_ext"},
5005	}
5006	for _, tc := range testcases {
5007		t.Run(tc.propName+":"+tc.partition, func(t *testing.T) {
5008			t.Parallel()
5009			ctx := testApex(t, `
5010				apex {
5011					name: "myapex",
5012					key: "myapex.key",
5013					updatable: false,
5014					`+tc.propName+`
5015				}
5016
5017				apex_key {
5018					name: "myapex.key",
5019					public_key: "testkey.avbpubkey",
5020					private_key: "testkey.pem",
5021				}
5022			`)
5023
5024			apex := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Module().(*apexBundle)
5025			expected := "out/target/product/test_device/" + tc.partition + "/apex"
5026			actual := apex.installDir.RelativeToTop().String()
5027			if actual != expected {
5028				t.Errorf("wrong install path. expected %q. actual %q", expected, actual)
5029			}
5030		})
5031	}
5032}
5033
5034func TestFileContexts_FindInDefaultLocationIfNotSet(t *testing.T) {
5035	t.Parallel()
5036	ctx := testApex(t, `
5037		apex {
5038			name: "myapex",
5039			key: "myapex.key",
5040			updatable: false,
5041		}
5042
5043		apex_key {
5044			name: "myapex.key",
5045			public_key: "testkey.avbpubkey",
5046			private_key: "testkey.pem",
5047		}
5048	`)
5049	module := ctx.ModuleForTests(t, "myapex", "android_common_myapex")
5050	rule := module.Output("file_contexts")
5051	ensureContains(t, rule.RuleParams.Command, "cat system/sepolicy/apex/myapex-file_contexts")
5052}
5053
5054func TestFileContexts_ShouldBeUnderSystemSepolicyForSystemApexes(t *testing.T) {
5055	t.Parallel()
5056	testApexError(t, `"myapex" .*: file_contexts: should be under system/sepolicy`, `
5057		apex {
5058			name: "myapex",
5059			key: "myapex.key",
5060			file_contexts: "my_own_file_contexts",
5061			updatable: false,
5062		}
5063
5064		apex_key {
5065			name: "myapex.key",
5066			public_key: "testkey.avbpubkey",
5067			private_key: "testkey.pem",
5068		}
5069	`, withFiles(map[string][]byte{
5070		"my_own_file_contexts": nil,
5071	}))
5072}
5073
5074func TestFileContexts_ProductSpecificApexes(t *testing.T) {
5075	t.Parallel()
5076	testApexError(t, `"myapex" .*: file_contexts: cannot find`, `
5077		apex {
5078			name: "myapex",
5079			key: "myapex.key",
5080			product_specific: true,
5081			file_contexts: "product_specific_file_contexts",
5082			updatable: false,
5083		}
5084
5085		apex_key {
5086			name: "myapex.key",
5087			public_key: "testkey.avbpubkey",
5088			private_key: "testkey.pem",
5089		}
5090	`)
5091
5092	ctx := testApex(t, `
5093		apex {
5094			name: "myapex",
5095			key: "myapex.key",
5096			product_specific: true,
5097			file_contexts: "product_specific_file_contexts",
5098			updatable: false,
5099		}
5100
5101		apex_key {
5102			name: "myapex.key",
5103			public_key: "testkey.avbpubkey",
5104			private_key: "testkey.pem",
5105		}
5106	`, withFiles(map[string][]byte{
5107		"product_specific_file_contexts": nil,
5108	}))
5109	module := ctx.ModuleForTests(t, "myapex", "android_common_myapex")
5110	rule := module.Output("file_contexts")
5111	ensureContains(t, rule.RuleParams.Command, "cat product_specific_file_contexts")
5112}
5113
5114func TestFileContexts_SetViaFileGroup(t *testing.T) {
5115	t.Parallel()
5116	ctx := testApex(t, `
5117		apex {
5118			name: "myapex",
5119			key: "myapex.key",
5120			product_specific: true,
5121			file_contexts: ":my-file-contexts",
5122			updatable: false,
5123		}
5124
5125		apex_key {
5126			name: "myapex.key",
5127			public_key: "testkey.avbpubkey",
5128			private_key: "testkey.pem",
5129		}
5130
5131		filegroup {
5132			name: "my-file-contexts",
5133			srcs: ["product_specific_file_contexts"],
5134		}
5135	`, withFiles(map[string][]byte{
5136		"product_specific_file_contexts": nil,
5137	}))
5138	module := ctx.ModuleForTests(t, "myapex", "android_common_myapex")
5139	rule := module.Output("file_contexts")
5140	ensureContains(t, rule.RuleParams.Command, "cat product_specific_file_contexts")
5141}
5142
5143func TestApexKeyFromOtherModule(t *testing.T) {
5144	t.Parallel()
5145	ctx := testApex(t, `
5146		apex_key {
5147			name: "myapex.key",
5148			public_key: ":my.avbpubkey",
5149			private_key: ":my.pem",
5150			product_specific: true,
5151		}
5152
5153		filegroup {
5154			name: "my.avbpubkey",
5155			srcs: ["testkey2.avbpubkey"],
5156		}
5157
5158		filegroup {
5159			name: "my.pem",
5160			srcs: ["testkey2.pem"],
5161		}
5162	`)
5163
5164	apex_key := ctx.ModuleForTests(t, "myapex.key", "android_common").Module().(*apexKey)
5165	expected_pubkey := "testkey2.avbpubkey"
5166	actual_pubkey := apex_key.publicKeyFile.String()
5167	if actual_pubkey != expected_pubkey {
5168		t.Errorf("wrong public key path. expected %q. actual %q", expected_pubkey, actual_pubkey)
5169	}
5170	expected_privkey := "testkey2.pem"
5171	actual_privkey := apex_key.privateKeyFile.String()
5172	if actual_privkey != expected_privkey {
5173		t.Errorf("wrong private key path. expected %q. actual %q", expected_privkey, actual_privkey)
5174	}
5175}
5176
5177func TestPrebuilt(t *testing.T) {
5178	t.Parallel()
5179	ctx := testApex(t, `
5180		prebuilt_apex {
5181			name: "myapex",
5182			arch: {
5183				arm64: {
5184					src: "myapex-arm64.apex",
5185				},
5186				arm: {
5187					src: "myapex-arm.apex",
5188				},
5189			},
5190		}
5191	`)
5192
5193	testingModule := ctx.ModuleForTests(t, "myapex", "android_common_prebuilt_myapex")
5194	prebuilt := testingModule.Module().(*Prebuilt)
5195
5196	expectedInput := "myapex-arm64.apex"
5197	if prebuilt.inputApex.String() != expectedInput {
5198		t.Errorf("inputApex invalid. expected: %q, actual: %q", expectedInput, prebuilt.inputApex.String())
5199	}
5200	android.AssertStringDoesContain(t, "Invalid provenance metadata file",
5201		prebuilt.ProvenanceMetaDataFile().String(), "soong/.intermediates/provenance_metadata/myapex/provenance_metadata.textproto")
5202	rule := testingModule.Rule("genProvenanceMetaData")
5203	android.AssertStringEquals(t, "Invalid input", "myapex-arm64.apex", rule.Inputs[0].String())
5204	android.AssertStringEquals(t, "Invalid output", "out/soong/.intermediates/provenance_metadata/myapex/provenance_metadata.textproto", rule.Output.String())
5205	android.AssertStringEquals(t, "Invalid args", "myapex", rule.Args["module_name"])
5206	android.AssertStringEquals(t, "Invalid args", "/system/apex/myapex.apex", rule.Args["install_path"])
5207
5208	entries := android.AndroidMkEntriesForTest(t, ctx, testingModule.Module())[0]
5209	android.AssertStringEquals(t, "unexpected LOCAL_SOONG_MODULE_TYPE", "prebuilt_apex", entries.EntryMap["LOCAL_SOONG_MODULE_TYPE"][0])
5210}
5211
5212func TestPrebuiltMissingSrc(t *testing.T) {
5213	t.Parallel()
5214	testApexError(t, `module "myapex" variant "android_common_prebuilt_myapex".*: prebuilt_apex does not support "arm64_armv8-a"`, `
5215		prebuilt_apex {
5216			name: "myapex",
5217		}
5218	`)
5219}
5220
5221func TestPrebuiltFilenameOverride(t *testing.T) {
5222	t.Parallel()
5223	ctx := testApex(t, `
5224		prebuilt_apex {
5225			name: "myapex",
5226			src: "myapex-arm.apex",
5227			filename: "notmyapex.apex",
5228		}
5229	`)
5230
5231	testingModule := ctx.ModuleForTests(t, "myapex", "android_common_prebuilt_myapex")
5232	p := testingModule.Module().(*Prebuilt)
5233
5234	expected := "notmyapex.apex"
5235	if p.installFilename != expected {
5236		t.Errorf("installFilename invalid. expected: %q, actual: %q", expected, p.installFilename)
5237	}
5238	rule := testingModule.Rule("genProvenanceMetaData")
5239	android.AssertStringEquals(t, "Invalid input", "myapex-arm.apex", rule.Inputs[0].String())
5240	android.AssertStringEquals(t, "Invalid output", "out/soong/.intermediates/provenance_metadata/myapex/provenance_metadata.textproto", rule.Output.String())
5241	android.AssertStringEquals(t, "Invalid args", "myapex", rule.Args["module_name"])
5242	android.AssertStringEquals(t, "Invalid args", "/system/apex/notmyapex.apex", rule.Args["install_path"])
5243}
5244
5245func TestApexSetFilenameOverride(t *testing.T) {
5246	t.Parallel()
5247	testApex(t, `
5248		apex_set {
5249 			name: "com.company.android.myapex",
5250			apex_name: "com.android.myapex",
5251			set: "company-myapex.apks",
5252      filename: "com.company.android.myapex.apex"
5253		}
5254	`).ModuleForTests(t, "com.company.android.myapex", "android_common_prebuilt_com.android.myapex")
5255
5256	testApex(t, `
5257		apex_set {
5258 			name: "com.company.android.myapex",
5259			apex_name: "com.android.myapex",
5260			set: "company-myapex.apks",
5261      filename: "com.company.android.myapex.capex"
5262		}
5263	`).ModuleForTests(t, "com.company.android.myapex", "android_common_prebuilt_com.android.myapex")
5264
5265	testApexError(t, `filename should end in .apex or .capex for apex_set`, `
5266		apex_set {
5267 			name: "com.company.android.myapex",
5268			apex_name: "com.android.myapex",
5269			set: "company-myapex.apks",
5270      filename: "some-random-suffix"
5271		}
5272	`)
5273}
5274
5275func TestPrebuiltOverrides(t *testing.T) {
5276	t.Parallel()
5277	ctx := testApex(t, `
5278		prebuilt_apex {
5279			name: "myapex.prebuilt",
5280			src: "myapex-arm.apex",
5281			overrides: [
5282				"myapex",
5283			],
5284		}
5285	`)
5286
5287	testingModule := ctx.ModuleForTests(t, "myapex.prebuilt", "android_common_prebuilt_myapex.prebuilt")
5288	p := testingModule.Module().(*Prebuilt)
5289
5290	expected := []string{"myapex"}
5291	actual := android.AndroidMkEntriesForTest(t, ctx, p)[0].EntryMap["LOCAL_OVERRIDES_MODULES"]
5292	if !reflect.DeepEqual(actual, expected) {
5293		t.Errorf("Incorrect LOCAL_OVERRIDES_MODULES value '%s', expected '%s'", actual, expected)
5294	}
5295	rule := testingModule.Rule("genProvenanceMetaData")
5296	android.AssertStringEquals(t, "Invalid input", "myapex-arm.apex", rule.Inputs[0].String())
5297	android.AssertStringEquals(t, "Invalid output", "out/soong/.intermediates/provenance_metadata/myapex.prebuilt/provenance_metadata.textproto", rule.Output.String())
5298	android.AssertStringEquals(t, "Invalid args", "myapex.prebuilt", rule.Args["module_name"])
5299	android.AssertStringEquals(t, "Invalid args", "/system/apex/myapex.prebuilt.apex", rule.Args["install_path"])
5300}
5301
5302func TestPrebuiltApexName(t *testing.T) {
5303	t.Parallel()
5304	testApex(t, `
5305		prebuilt_apex {
5306			name: "com.company.android.myapex",
5307			apex_name: "com.android.myapex",
5308			src: "company-myapex-arm.apex",
5309		}
5310	`).ModuleForTests(t, "com.company.android.myapex", "android_common_prebuilt_com.android.myapex")
5311
5312	testApex(t, `
5313		apex_set {
5314			name: "com.company.android.myapex",
5315			apex_name: "com.android.myapex",
5316			set: "company-myapex.apks",
5317		}
5318	`).ModuleForTests(t, "com.company.android.myapex", "android_common_prebuilt_com.android.myapex")
5319}
5320
5321func TestPrebuiltApexNameWithPlatformBootclasspath(t *testing.T) {
5322	t.Parallel()
5323	_ = android.GroupFixturePreparers(
5324		java.PrepareForTestWithJavaDefaultModules,
5325		PrepareForTestWithApexBuildComponents,
5326		android.FixtureWithRootAndroidBp(`
5327			platform_bootclasspath {
5328				name: "platform-bootclasspath",
5329				fragments: [
5330					{
5331						apex: "com.android.art",
5332						module: "art-bootclasspath-fragment",
5333					},
5334				],
5335			}
5336
5337			prebuilt_apex {
5338				name: "com.company.android.art",
5339				apex_name: "com.android.art",
5340				src: "com.company.android.art-arm.apex",
5341				exported_bootclasspath_fragments: ["art-bootclasspath-fragment"],
5342			}
5343
5344			prebuilt_apex {
5345				name: "com.android.art",
5346				src: "com.android.art-arm.apex",
5347				exported_bootclasspath_fragments: ["art-bootclasspath-fragment"],
5348			}
5349
5350			prebuilt_bootclasspath_fragment {
5351				name: "art-bootclasspath-fragment",
5352				image_name: "art",
5353				contents: ["core-oj"],
5354				hidden_api: {
5355					annotation_flags: "my-bootclasspath-fragment/annotation-flags.csv",
5356					metadata: "my-bootclasspath-fragment/metadata.csv",
5357					index: "my-bootclasspath-fragment/index.csv",
5358					stub_flags: "my-bootclasspath-fragment/stub-flags.csv",
5359					all_flags: "my-bootclasspath-fragment/all-flags.csv",
5360				},
5361			}
5362
5363			java_import {
5364				name: "core-oj",
5365				jars: ["prebuilt.jar"],
5366			}
5367		`),
5368	).RunTest(t)
5369}
5370
5371// A minimal context object for use with DexJarBuildPath
5372type moduleErrorfTestCtx struct {
5373}
5374
5375func (ctx moduleErrorfTestCtx) ModuleErrorf(format string, args ...interface{}) {
5376}
5377
5378func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) {
5379	t.Parallel()
5380	preparer := android.GroupFixturePreparers(
5381		java.FixtureConfigureApexBootJars("myapex:libfoo", "myapex:libbar"),
5382		// Make sure that the frameworks/base/Android.bp file exists as otherwise hidden API encoding
5383		// is disabled.
5384		android.FixtureAddTextFile("frameworks/base/Android.bp", ""),
5385
5386		// Make sure that we have atleast one platform library so that we can check the monolithic hiddenapi
5387		// file creation.
5388		java.FixtureConfigureBootJars("platform:foo"),
5389		android.FixtureModifyMockFS(func(fs android.MockFS) {
5390			fs["platform/Android.bp"] = []byte(`
5391		java_library {
5392			name: "foo",
5393			srcs: ["Test.java"],
5394			compile_dex: true,
5395		}
5396		`)
5397			fs["platform/Test.java"] = nil
5398		}),
5399	)
5400
5401	checkHiddenAPIIndexFromClassesInputs := func(t *testing.T, ctx *android.TestContext, expectedIntermediateInputs string) {
5402		t.Helper()
5403		platformBootclasspath := ctx.ModuleForTests(t, "platform-bootclasspath", "android_common")
5404		var rule android.TestingBuildParams
5405
5406		rule = platformBootclasspath.Output("hiddenapi-monolithic/index-from-classes.csv")
5407		java.CheckHiddenAPIRuleInputs(t, "intermediate index", expectedIntermediateInputs, rule)
5408	}
5409
5410	checkHiddenAPIIndexFromFlagsInputs := func(t *testing.T, ctx *android.TestContext, expectedIntermediateInputs string) {
5411		t.Helper()
5412		platformBootclasspath := ctx.ModuleForTests(t, "platform-bootclasspath", "android_common")
5413		var rule android.TestingBuildParams
5414
5415		rule = platformBootclasspath.Output("hiddenapi-index.csv")
5416		java.CheckHiddenAPIRuleInputs(t, "monolithic index", expectedIntermediateInputs, rule)
5417	}
5418
5419	fragment := java.ApexVariantReference{
5420		Apex:   proptools.StringPtr("myapex"),
5421		Module: proptools.StringPtr("my-bootclasspath-fragment"),
5422	}
5423
5424	t.Run("prebuilt only", func(t *testing.T) {
5425		t.Parallel()
5426		bp := `
5427		prebuilt_apex {
5428			name: "myapex",
5429			arch: {
5430				arm64: {
5431					src: "myapex-arm64.apex",
5432				},
5433				arm: {
5434					src: "myapex-arm.apex",
5435				},
5436			},
5437			exported_bootclasspath_fragments: ["my-bootclasspath-fragment"],
5438		}
5439
5440		prebuilt_bootclasspath_fragment {
5441			name: "my-bootclasspath-fragment",
5442			contents: ["libfoo", "libbar"],
5443			apex_available: ["myapex"],
5444			hidden_api: {
5445				annotation_flags: "my-bootclasspath-fragment/annotation-flags.csv",
5446				metadata: "my-bootclasspath-fragment/metadata.csv",
5447				index: "my-bootclasspath-fragment/index.csv",
5448				signature_patterns: "my-bootclasspath-fragment/signature-patterns.csv",
5449				filtered_stub_flags: "my-bootclasspath-fragment/filtered-stub-flags.csv",
5450				filtered_flags: "my-bootclasspath-fragment/filtered-flags.csv",
5451			},
5452		}
5453
5454		java_sdk_library_import {
5455			name: "libfoo",
5456			public: {
5457				jars: ["libfoo.jar"],
5458			},
5459			apex_available: ["myapex"],
5460			shared_library: false,
5461			permitted_packages: ["foo"],
5462		}
5463
5464		java_sdk_library_import {
5465			name: "libbar",
5466			public: {
5467				jars: ["libbar.jar"],
5468			},
5469			apex_available: ["myapex"],
5470			shared_library: false,
5471			permitted_packages: ["bar"],
5472		}
5473	`
5474
5475		ctx := testDexpreoptWithApexes(t, bp, "", preparer, fragment)
5476
5477		// Verify the correct module jars contribute to the hiddenapi index file.
5478		checkHiddenAPIIndexFromClassesInputs(t, ctx, `out/soong/.intermediates/platform/foo/android_common/javac/foo.jar`)
5479		checkHiddenAPIIndexFromFlagsInputs(t, ctx, `
5480			my-bootclasspath-fragment/index.csv
5481			out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/hiddenapi-monolithic/index-from-classes.csv
5482			out/soong/.intermediates/packages/modules/com.android.art/art-bootclasspath-fragment/android_common_com.android.art/modular-hiddenapi/index.csv
5483		`)
5484	})
5485
5486	t.Run("apex_set only", func(t *testing.T) {
5487		t.Parallel()
5488		bp := `
5489		apex_set {
5490			name: "myapex",
5491			set: "myapex.apks",
5492			exported_bootclasspath_fragments: ["my-bootclasspath-fragment"],
5493			exported_systemserverclasspath_fragments: ["my-systemserverclasspath-fragment"],
5494		}
5495
5496		prebuilt_bootclasspath_fragment {
5497			name: "my-bootclasspath-fragment",
5498			contents: ["libfoo", "libbar"],
5499			apex_available: ["myapex"],
5500			hidden_api: {
5501				annotation_flags: "my-bootclasspath-fragment/annotation-flags.csv",
5502				metadata: "my-bootclasspath-fragment/metadata.csv",
5503				index: "my-bootclasspath-fragment/index.csv",
5504				signature_patterns: "my-bootclasspath-fragment/signature-patterns.csv",
5505				filtered_stub_flags: "my-bootclasspath-fragment/filtered-stub-flags.csv",
5506				filtered_flags: "my-bootclasspath-fragment/filtered-flags.csv",
5507			},
5508		}
5509
5510		prebuilt_systemserverclasspath_fragment {
5511			name: "my-systemserverclasspath-fragment",
5512			contents: ["libbaz"],
5513			apex_available: ["myapex"],
5514		}
5515
5516		java_sdk_library_import {
5517			name: "libfoo",
5518			public: {
5519				jars: ["libfoo.jar"],
5520			},
5521			apex_available: ["myapex"],
5522			shared_library: false,
5523			permitted_packages: ["libfoo"],
5524		}
5525
5526
5527		java_sdk_library_import {
5528			name: "libbar",
5529			public: {
5530				jars: ["libbar.jar"],
5531			},
5532			apex_available: ["myapex"],
5533			shared_library: false,
5534			permitted_packages: ["bar"],
5535		}
5536
5537		java_sdk_library_import {
5538			name: "libbaz",
5539			public: {
5540				jars: ["libbaz.jar"],
5541			},
5542			apex_available: ["myapex"],
5543			shared_library: false,
5544			permitted_packages: ["baz"],
5545		}
5546	`
5547
5548		ctx := testDexpreoptWithApexes(t, bp, "", preparer, fragment)
5549
5550		// Verify the correct module jars contribute to the hiddenapi index file.
5551		checkHiddenAPIIndexFromClassesInputs(t, ctx, `out/soong/.intermediates/platform/foo/android_common/javac/foo.jar`)
5552		checkHiddenAPIIndexFromFlagsInputs(t, ctx, `
5553			my-bootclasspath-fragment/index.csv
5554			out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/hiddenapi-monolithic/index-from-classes.csv
5555			out/soong/.intermediates/packages/modules/com.android.art/art-bootclasspath-fragment/android_common_com.android.art/modular-hiddenapi/index.csv
5556		`)
5557
5558		myApex := ctx.ModuleForTests(t, "myapex", "android_common_prebuilt_myapex").Module()
5559
5560		overrideNames := []string{
5561			"",
5562			"myjavalib.myapex",
5563			"libfoo.myapex",
5564			"libbar.myapex",
5565			"libbaz.myapex",
5566		}
5567		mkEntries := android.AndroidMkEntriesForTest(t, ctx, myApex)
5568		for i, e := range mkEntries {
5569			g := e.OverrideName
5570			if w := overrideNames[i]; w != g {
5571				t.Errorf("Expected override name %q, got %q", w, g)
5572			}
5573		}
5574
5575	})
5576
5577	t.Run("prebuilt with source library preferred", func(t *testing.T) {
5578		t.Parallel()
5579		bp := `
5580		prebuilt_apex {
5581			name: "myapex",
5582			arch: {
5583				arm64: {
5584					src: "myapex-arm64.apex",
5585				},
5586				arm: {
5587					src: "myapex-arm.apex",
5588				},
5589			},
5590			exported_bootclasspath_fragments: ["my-bootclasspath-fragment"],
5591		}
5592
5593		prebuilt_bootclasspath_fragment {
5594			name: "my-bootclasspath-fragment",
5595			contents: ["libfoo", "libbar"],
5596			apex_available: ["myapex"],
5597			hidden_api: {
5598				annotation_flags: "my-bootclasspath-fragment/annotation-flags.csv",
5599				metadata: "my-bootclasspath-fragment/metadata.csv",
5600				index: "my-bootclasspath-fragment/index.csv",
5601				stub_flags: "my-bootclasspath-fragment/stub-flags.csv",
5602				all_flags: "my-bootclasspath-fragment/all-flags.csv",
5603			},
5604		}
5605
5606		java_import {
5607			name: "libfoo",
5608			jars: ["libfoo.jar"],
5609			apex_available: ["myapex"],
5610			sdk_version: "core_current",
5611		}
5612
5613		java_library {
5614			name: "libfoo",
5615			srcs: ["foo/bar/MyClass.java"],
5616			apex_available: ["myapex"],
5617			sdk_version: "core_current",
5618		}
5619
5620		java_sdk_library_import {
5621			name: "libbar",
5622			public: {
5623				jars: ["libbar.jar"],
5624			},
5625			apex_available: ["myapex"],
5626			shared_library: false,
5627		}
5628
5629		java_sdk_library {
5630			name: "libbar",
5631			srcs: ["foo/bar/MyClass.java"],
5632			unsafe_ignore_missing_latest_api: true,
5633			apex_available: ["myapex"],
5634		}
5635	`
5636
5637		// In this test the source (java_library) libfoo is active since the
5638		// prebuilt (java_import) defaults to prefer:false. However the
5639		// prebuilt_apex module always depends on the prebuilt, and so it doesn't
5640		// find the dex boot jar in it. We either need to disable the source libfoo
5641		// or make the prebuilt libfoo preferred.
5642		testDexpreoptWithApexes(t, bp, `module "platform-bootclasspath" variant ".*": module libfoo{.*} does not provide a dex jar`, preparer, fragment)
5643		// dexbootjar check is skipped if AllowMissingDependencies is true
5644		preparerAllowMissingDeps := android.GroupFixturePreparers(
5645			preparer,
5646			android.PrepareForTestWithAllowMissingDependencies,
5647		)
5648		testDexpreoptWithApexes(t, bp, "", preparerAllowMissingDeps, fragment)
5649	})
5650
5651	t.Run("prebuilt library preferred with source", func(t *testing.T) {
5652		t.Parallel()
5653		bp := `
5654		apex {
5655			name: "myapex",
5656			key: "myapex.key",
5657			updatable: false,
5658			bootclasspath_fragments: ["my-bootclasspath-fragment"],
5659		}
5660
5661		apex_key {
5662			name: "myapex.key",
5663			public_key: "testkey.avbpubkey",
5664			private_key: "testkey.pem",
5665		}
5666
5667		bootclasspath_fragment {
5668			name: "my-bootclasspath-fragment",
5669			contents: ["libfoo", "libbar"],
5670			apex_available: ["myapex"],
5671			hidden_api: {
5672				split_packages: ["*"],
5673			},
5674		}
5675
5676		prebuilt_apex {
5677			name: "myapex",
5678			prefer: true,
5679			arch: {
5680				arm64: {
5681					src: "myapex-arm64.apex",
5682				},
5683				arm: {
5684					src: "myapex-arm.apex",
5685				},
5686			},
5687			exported_bootclasspath_fragments: ["my-bootclasspath-fragment"],
5688		}
5689
5690		prebuilt_bootclasspath_fragment {
5691			name: "my-bootclasspath-fragment",
5692			prefer: true,
5693			contents: ["libfoo", "libbar"],
5694			apex_available: ["myapex"],
5695			hidden_api: {
5696				annotation_flags: "my-bootclasspath-fragment/annotation-flags.csv",
5697				metadata: "my-bootclasspath-fragment/metadata.csv",
5698				index: "my-bootclasspath-fragment/index.csv",
5699				signature_patterns: "my-bootclasspath-fragment/signature-patterns.csv",
5700				filtered_stub_flags: "my-bootclasspath-fragment/filtered-stub-flags.csv",
5701				filtered_flags: "my-bootclasspath-fragment/filtered-flags.csv",
5702			},
5703		}
5704
5705		java_sdk_library_import {
5706			name: "libfoo",
5707			prefer: true,
5708			public: {
5709				jars: ["libfoo.jar"],
5710			},
5711			apex_available: ["myapex"],
5712			shared_library: false,
5713			permitted_packages: ["libfoo"],
5714		}
5715
5716		java_library {
5717			name: "libfoo",
5718			srcs: ["foo/bar/MyClass.java"],
5719			apex_available: ["myapex"],
5720			installable: true,
5721			sdk_version: "core_current",
5722		}
5723
5724		java_sdk_library_import {
5725			name: "libbar",
5726			prefer: true,
5727			public: {
5728				jars: ["libbar.jar"],
5729			},
5730			apex_available: ["myapex"],
5731			shared_library: false,
5732			permitted_packages: ["bar"],
5733		}
5734
5735		java_sdk_library {
5736			name: "libbar",
5737			srcs: ["foo/bar/MyClass.java"],
5738			unsafe_ignore_missing_latest_api: true,
5739			apex_available: ["myapex"],
5740			compile_dex: true,
5741		}
5742	`
5743
5744		ctx := testDexpreoptWithApexes(t, bp, "", preparer, fragment)
5745
5746		// Verify the correct module jars contribute to the hiddenapi index file.
5747		checkHiddenAPIIndexFromClassesInputs(t, ctx, `out/soong/.intermediates/platform/foo/android_common/javac/foo.jar`)
5748		checkHiddenAPIIndexFromFlagsInputs(t, ctx, `
5749			my-bootclasspath-fragment/index.csv
5750			out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/hiddenapi-monolithic/index-from-classes.csv
5751			out/soong/.intermediates/packages/modules/com.android.art/art-bootclasspath-fragment/android_common_com.android.art/modular-hiddenapi/index.csv
5752		`)
5753	})
5754
5755	t.Run("prebuilt with source apex preferred", func(t *testing.T) {
5756		t.Parallel()
5757		bp := `
5758		apex {
5759			name: "myapex",
5760			key: "myapex.key",
5761			updatable: false,
5762			bootclasspath_fragments: ["my-bootclasspath-fragment"],
5763		}
5764
5765		apex_key {
5766			name: "myapex.key",
5767			public_key: "testkey.avbpubkey",
5768			private_key: "testkey.pem",
5769		}
5770
5771		bootclasspath_fragment {
5772			name: "my-bootclasspath-fragment",
5773			contents: ["libfoo", "libbar"],
5774			apex_available: ["myapex"],
5775			hidden_api: {
5776				split_packages: ["*"],
5777			},
5778		}
5779
5780		prebuilt_apex {
5781			name: "myapex",
5782			arch: {
5783				arm64: {
5784					src: "myapex-arm64.apex",
5785				},
5786				arm: {
5787					src: "myapex-arm.apex",
5788				},
5789			},
5790			exported_bootclasspath_fragments: ["my-bootclasspath-fragment"],
5791		}
5792
5793		prebuilt_bootclasspath_fragment {
5794			name: "my-bootclasspath-fragment",
5795			contents: ["libfoo", "libbar"],
5796			apex_available: ["myapex"],
5797			hidden_api: {
5798				annotation_flags: "my-bootclasspath-fragment/annotation-flags.csv",
5799				metadata: "my-bootclasspath-fragment/metadata.csv",
5800				index: "my-bootclasspath-fragment/index.csv",
5801				signature_patterns: "my-bootclasspath-fragment/signature-patterns.csv",
5802				filtered_stub_flags: "my-bootclasspath-fragment/filtered-stub-flags.csv",
5803				filtered_flags: "my-bootclasspath-fragment/filtered-flags.csv",
5804			},
5805		}
5806
5807		java_import {
5808			name: "libfoo",
5809			jars: ["libfoo.jar"],
5810			apex_available: ["myapex"],
5811			sdk_version: "core_current",
5812		}
5813
5814		java_library {
5815			name: "libfoo",
5816			srcs: ["foo/bar/MyClass.java"],
5817			apex_available: ["myapex"],
5818			permitted_packages: ["foo"],
5819			installable: true,
5820			sdk_version: "core_current",
5821		}
5822
5823		java_sdk_library_import {
5824			name: "libbar",
5825			public: {
5826				jars: ["libbar.jar"],
5827			},
5828			apex_available: ["myapex"],
5829			shared_library: false,
5830		}
5831
5832		java_sdk_library {
5833			name: "libbar",
5834			srcs: ["foo/bar/MyClass.java"],
5835			unsafe_ignore_missing_latest_api: true,
5836			apex_available: ["myapex"],
5837			permitted_packages: ["bar"],
5838			compile_dex: true,
5839			sdk_version: "core_current",
5840		}
5841	`
5842
5843		ctx := testDexpreoptWithApexes(t, bp, "", preparer, fragment)
5844
5845		// Verify the correct module jars contribute to the hiddenapi index file.
5846		checkHiddenAPIIndexFromClassesInputs(t, ctx, `out/soong/.intermediates/platform/foo/android_common/javac/foo.jar`)
5847		checkHiddenAPIIndexFromFlagsInputs(t, ctx, `
5848			out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/hiddenapi-monolithic/index-from-classes.csv
5849			out/soong/.intermediates/my-bootclasspath-fragment/android_common_myapex/modular-hiddenapi/index.csv
5850			out/soong/.intermediates/packages/modules/com.android.art/art-bootclasspath-fragment/android_common_com.android.art/modular-hiddenapi/index.csv
5851		`)
5852	})
5853
5854	t.Run("prebuilt preferred with source apex disabled", func(t *testing.T) {
5855		t.Parallel()
5856		bp := `
5857		apex {
5858			name: "myapex",
5859			enabled: false,
5860			key: "myapex.key",
5861			bootclasspath_fragments: ["my-bootclasspath-fragment"],
5862		}
5863
5864		apex_key {
5865			name: "myapex.key",
5866			public_key: "testkey.avbpubkey",
5867			private_key: "testkey.pem",
5868		}
5869
5870		bootclasspath_fragment {
5871			name: "my-bootclasspath-fragment",
5872			enabled: false,
5873			contents: ["libfoo", "libbar"],
5874			apex_available: ["myapex"],
5875			hidden_api: {
5876				split_packages: ["*"],
5877			},
5878		}
5879
5880		prebuilt_apex {
5881			name: "myapex",
5882			arch: {
5883				arm64: {
5884					src: "myapex-arm64.apex",
5885				},
5886				arm: {
5887					src: "myapex-arm.apex",
5888				},
5889			},
5890			exported_bootclasspath_fragments: ["my-bootclasspath-fragment"],
5891		}
5892
5893		prebuilt_bootclasspath_fragment {
5894			name: "my-bootclasspath-fragment",
5895			contents: ["libfoo", "libbar"],
5896			apex_available: ["myapex"],
5897			hidden_api: {
5898				annotation_flags: "my-bootclasspath-fragment/annotation-flags.csv",
5899				metadata: "my-bootclasspath-fragment/metadata.csv",
5900				index: "my-bootclasspath-fragment/index.csv",
5901				signature_patterns: "my-bootclasspath-fragment/signature-patterns.csv",
5902				filtered_stub_flags: "my-bootclasspath-fragment/filtered-stub-flags.csv",
5903				filtered_flags: "my-bootclasspath-fragment/filtered-flags.csv",
5904			},
5905		}
5906
5907		java_import {
5908			name: "libfoo",
5909			jars: ["libfoo.jar"],
5910			apex_available: ["myapex"],
5911			permitted_packages: ["foo"],
5912		}
5913
5914		java_library {
5915			name: "libfoo",
5916			enabled: false,
5917			srcs: ["foo/bar/MyClass.java"],
5918			apex_available: ["myapex"],
5919			installable: true,
5920		}
5921
5922		java_sdk_library_import {
5923			name: "libbar",
5924			public: {
5925				jars: ["libbar.jar"],
5926			},
5927			apex_available: ["myapex"],
5928			shared_library: false,
5929			permitted_packages: ["bar"],
5930			prefer: true,
5931		}
5932
5933		java_sdk_library {
5934			name: "libbar",
5935			srcs: ["foo/bar/MyClass.java"],
5936			unsafe_ignore_missing_latest_api: true,
5937			apex_available: ["myapex"],
5938			compile_dex: true,
5939		}
5940	`
5941		// This test disables libbar, which causes the ComponentDepsMutator to add
5942		// deps on libbar.stubs and other sub-modules that don't exist. We can
5943		// enable AllowMissingDependencies to work around that, but enabling that
5944		// causes extra checks for missing source files to dex_bootjars, so add those
5945		// to the mock fs as well.
5946		preparer2 := android.GroupFixturePreparers(
5947			preparer,
5948			android.PrepareForTestWithAllowMissingDependencies,
5949			android.FixtureMergeMockFs(map[string][]byte{
5950				"build/soong/scripts/check_boot_jars/package_allowed_list.txt": nil,
5951				"frameworks/base/boot/boot-profile.txt":                        nil,
5952			}),
5953		)
5954
5955		ctx := testDexpreoptWithApexes(t, bp, "", preparer2, fragment)
5956
5957		// Verify the correct module jars contribute to the hiddenapi index file.
5958		checkHiddenAPIIndexFromClassesInputs(t, ctx, `out/soong/.intermediates/platform/foo/android_common/javac/foo.jar`)
5959		checkHiddenAPIIndexFromFlagsInputs(t, ctx, `
5960			my-bootclasspath-fragment/index.csv
5961			out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/hiddenapi-monolithic/index-from-classes.csv
5962			out/soong/.intermediates/packages/modules/com.android.art/art-bootclasspath-fragment/android_common_com.android.art/modular-hiddenapi/index.csv
5963		`)
5964	})
5965
5966	t.Run("Co-existing unflagged apexes should create a duplicate module error", func(t *testing.T) {
5967		t.Parallel()
5968		bp := `
5969		// Source
5970		apex {
5971			name: "myapex",
5972			enabled: false,
5973			key: "myapex.key",
5974			bootclasspath_fragments: ["my-bootclasspath-fragment"],
5975		}
5976
5977		apex_key {
5978			name: "myapex.key",
5979			public_key: "testkey.avbpubkey",
5980			private_key: "testkey.pem",
5981		}
5982
5983		// Prebuilt
5984		prebuilt_apex {
5985			name: "myapex.v1",
5986			source_apex_name: "myapex",
5987			arch: {
5988				arm64: {
5989					src: "myapex-arm64.apex",
5990				},
5991				arm: {
5992					src: "myapex-arm.apex",
5993				},
5994			},
5995			exported_bootclasspath_fragments: ["my-bootclasspath-fragment"],
5996			prefer: true,
5997		}
5998		prebuilt_apex {
5999			name: "myapex.v2",
6000			source_apex_name: "myapex",
6001			arch: {
6002				arm64: {
6003					src: "myapex-arm64.apex",
6004				},
6005				arm: {
6006					src: "myapex-arm.apex",
6007				},
6008			},
6009			exported_bootclasspath_fragments: ["my-bootclasspath-fragment"],
6010			prefer: true,
6011		}
6012
6013		prebuilt_bootclasspath_fragment {
6014			name: "my-bootclasspath-fragment",
6015			contents: ["libfoo", "libbar"],
6016			apex_available: ["myapex"],
6017			hidden_api: {
6018				annotation_flags: "my-bootclasspath-fragment/annotation-flags.csv",
6019				metadata: "my-bootclasspath-fragment/metadata.csv",
6020				index: "my-bootclasspath-fragment/index.csv",
6021				stub_flags: "my-bootclasspath-fragment/stub-flags.csv",
6022				all_flags: "my-bootclasspath-fragment/all-flags.csv",
6023			},
6024			prefer: true,
6025		}
6026
6027		java_import {
6028			name: "libfoo",
6029			jars: ["libfoo.jar"],
6030			apex_available: ["myapex"],
6031			prefer: true,
6032		}
6033		java_import {
6034			name: "libbar",
6035			jars: ["libbar.jar"],
6036			apex_available: ["myapex"],
6037			prefer: true,
6038		}
6039	`
6040
6041		testDexpreoptWithApexes(t, bp, "Multiple prebuilt modules prebuilt_myapex.v1 and prebuilt_myapex.v2 have been marked as preferred for this source module", preparer, fragment)
6042	})
6043
6044}
6045
6046func TestApexWithTests(t *testing.T) {
6047	t.Parallel()
6048	ctx := testApex(t, `
6049		apex_test {
6050			name: "myapex",
6051			key: "myapex.key",
6052			updatable: false,
6053			tests: [
6054				"mytest",
6055			],
6056		}
6057
6058		apex_key {
6059			name: "myapex.key",
6060			public_key: "testkey.avbpubkey",
6061			private_key: "testkey.pem",
6062		}
6063
6064		filegroup {
6065			name: "fg",
6066			srcs: [
6067				"baz",
6068				"bar/baz"
6069			],
6070		}
6071
6072		cc_test {
6073			name: "mytest",
6074			gtest: false,
6075			srcs: ["mytest.cpp"],
6076			relative_install_path: "test",
6077			shared_libs: ["mylib"],
6078			system_shared_libs: [],
6079			stl: "none",
6080			data: [":fg"],
6081		}
6082
6083		cc_library {
6084			name: "mylib",
6085			srcs: ["mylib.cpp"],
6086			system_shared_libs: [],
6087			stl: "none",
6088		}
6089
6090		filegroup {
6091			name: "fg2",
6092			srcs: [
6093				"testdata/baz"
6094			],
6095		}
6096	`)
6097
6098	apexRule := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Rule("apexRule")
6099	copyCmds := apexRule.Args["copy_commands"]
6100
6101	// Ensure that test dep (and their transitive dependencies) are copied into apex.
6102	ensureContains(t, copyCmds, "image.apex/bin/test/mytest")
6103	ensureContains(t, copyCmds, "image.apex/lib64/mylib.so")
6104
6105	//Ensure that test data are copied into apex.
6106	ensureContains(t, copyCmds, "image.apex/bin/test/baz")
6107	ensureContains(t, copyCmds, "image.apex/bin/test/bar/baz")
6108
6109	// Ensure the module is correctly translated.
6110	bundle := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Module().(*apexBundle)
6111	data := android.AndroidMkDataForTest(t, ctx, bundle)
6112	name := bundle.BaseModuleName()
6113	prefix := "TARGET_"
6114	var builder strings.Builder
6115	data.Custom(&builder, name, prefix, "", data)
6116	androidMk := builder.String()
6117	ensureContains(t, androidMk, "LOCAL_MODULE := mytest.myapex\n")
6118	ensureContains(t, androidMk, "LOCAL_MODULE := myapex\n")
6119}
6120
6121func TestErrorsIfDepsAreNotEnabled(t *testing.T) {
6122	t.Parallel()
6123	testApexError(t, `module "myapex" .* depends on disabled module "libfoo"`, `
6124		apex {
6125			name: "myapex",
6126			key: "myapex.key",
6127			native_shared_libs: ["libfoo"],
6128		}
6129
6130		apex_key {
6131			name: "myapex.key",
6132			public_key: "testkey.avbpubkey",
6133			private_key: "testkey.pem",
6134		}
6135
6136		cc_library {
6137			name: "libfoo",
6138			stl: "none",
6139			system_shared_libs: [],
6140			enabled: false,
6141			apex_available: ["myapex"],
6142		}
6143	`)
6144	testApexError(t, `module "myapex" .* depends on disabled module "myjar"`, `
6145		apex {
6146			name: "myapex",
6147			key: "myapex.key",
6148			java_libs: ["myjar"],
6149		}
6150
6151		apex_key {
6152			name: "myapex.key",
6153			public_key: "testkey.avbpubkey",
6154			private_key: "testkey.pem",
6155		}
6156
6157		java_library {
6158			name: "myjar",
6159			srcs: ["foo/bar/MyClass.java"],
6160			sdk_version: "none",
6161			system_modules: "none",
6162			enabled: false,
6163			apex_available: ["myapex"],
6164			compile_dex: true,
6165		}
6166	`)
6167}
6168
6169func TestApexWithJavaImport(t *testing.T) {
6170	ctx := testApex(t, `
6171		apex {
6172			name: "myapex",
6173			key: "myapex.key",
6174			java_libs: ["myjavaimport"],
6175			updatable: false,
6176		}
6177
6178		apex_key {
6179			name: "myapex.key",
6180			public_key: "testkey.avbpubkey",
6181			private_key: "testkey.pem",
6182		}
6183
6184		java_import {
6185			name: "myjavaimport",
6186			apex_available: ["myapex"],
6187			jars: ["my.jar"],
6188			compile_dex: true,
6189		}
6190	`)
6191
6192	module := ctx.ModuleForTests(t, "myapex", "android_common_myapex")
6193	apexRule := module.Rule("apexRule")
6194	copyCmds := apexRule.Args["copy_commands"]
6195	ensureContains(t, copyCmds, "image.apex/javalib/myjavaimport.jar")
6196}
6197
6198func TestApexWithApps(t *testing.T) {
6199	t.Parallel()
6200	ctx := testApex(t, `
6201		apex {
6202			name: "myapex",
6203			key: "myapex.key",
6204			apps: [
6205				"AppFoo",
6206				"AppFooPriv",
6207			],
6208			updatable: false,
6209		}
6210
6211		apex_key {
6212			name: "myapex.key",
6213			public_key: "testkey.avbpubkey",
6214			private_key: "testkey.pem",
6215		}
6216
6217		android_app {
6218			name: "AppFoo",
6219			srcs: ["foo/bar/MyClass.java"],
6220			sdk_version: "current",
6221			system_modules: "none",
6222			use_embedded_native_libs: true,
6223			jni_libs: ["libjni"],
6224			stl: "none",
6225			apex_available: [ "myapex" ],
6226		}
6227
6228		android_app {
6229			name: "AppFooPriv",
6230			srcs: ["foo/bar/MyClass.java"],
6231			sdk_version: "current",
6232			system_modules: "none",
6233			privileged: true,
6234			privapp_allowlist: "privapp_allowlist_com.android.AppFooPriv.xml",
6235			stl: "none",
6236			apex_available: [ "myapex" ],
6237		}
6238
6239		cc_library_shared {
6240			name: "libjni",
6241			srcs: ["mylib.cpp"],
6242			shared_libs: ["libfoo"],
6243			stl: "none",
6244			system_shared_libs: [],
6245			apex_available: [ "myapex" ],
6246			sdk_version: "current",
6247		}
6248
6249		cc_library_shared {
6250			name: "libfoo",
6251			stl: "none",
6252			system_shared_libs: [],
6253			apex_available: [ "myapex" ],
6254			sdk_version: "current",
6255		}
6256	`)
6257
6258	module := ctx.ModuleForTests(t, "myapex", "android_common_myapex")
6259	apexRule := module.Rule("apexRule")
6260	copyCmds := apexRule.Args["copy_commands"]
6261
6262	ensureContains(t, copyCmds, "image.apex/app/AppFoo@TEST.BUILD_ID/AppFoo.apk")
6263	ensureContains(t, copyCmds, "image.apex/priv-app/AppFooPriv@TEST.BUILD_ID/AppFooPriv.apk")
6264	ensureContains(t, copyCmds, "image.apex/etc/permissions/privapp_allowlist_com.android.AppFooPriv.xml")
6265
6266	appZipRule := ctx.ModuleForTests(t, "AppFoo", "android_common_apex10000").Description("zip jni libs")
6267	// JNI libraries are uncompressed
6268	if args := appZipRule.Args["jarArgs"]; !strings.Contains(args, "-L 0") {
6269		t.Errorf("jni libs are not uncompressed for AppFoo")
6270	}
6271	// JNI libraries including transitive deps are
6272	for _, jni := range []string{"libjni", "libfoo"} {
6273		jniOutput := ctx.ModuleForTests(t, jni, "android_arm64_armv8-a_sdk_shared_apex10000").Module().(*cc.Module).OutputFile().RelativeToTop()
6274		// ... embedded inside APK (jnilibs.zip)
6275		ensureListContains(t, appZipRule.Implicits.Strings(), jniOutput.String())
6276		// ... and not directly inside the APEX
6277		ensureNotContains(t, copyCmds, "image.apex/lib64/"+jni+".so")
6278	}
6279
6280	apexBundle := module.Module().(*apexBundle)
6281	data := android.AndroidMkDataForTest(t, ctx, apexBundle)
6282	var builder strings.Builder
6283	data.Custom(&builder, apexBundle.Name(), "TARGET_", "", data)
6284	androidMk := builder.String()
6285	ensureContains(t, androidMk, "LOCAL_MODULE := AppFooPriv.myapex")
6286	ensureContains(t, androidMk, "LOCAL_MODULE := AppFoo.myapex")
6287	ensureMatches(t, androidMk, "LOCAL_SOONG_INSTALLED_MODULE := \\S+AppFooPriv.apk")
6288	ensureMatches(t, androidMk, "LOCAL_SOONG_INSTALLED_MODULE := \\S+AppFoo.apk")
6289	ensureMatches(t, androidMk, "LOCAL_SOONG_INSTALL_PAIRS := \\S+AppFooPriv.apk")
6290	ensureContains(t, androidMk, "LOCAL_SOONG_INSTALL_PAIRS := privapp_allowlist_com.android.AppFooPriv.xml:$(PRODUCT_OUT)/apex/myapex/etc/permissions/privapp_allowlist_com.android.AppFooPriv.xml")
6291}
6292
6293func TestApexWithAppImportBuildId(t *testing.T) {
6294	t.Parallel()
6295	invalidBuildIds := []string{"../", "a b", "a/b", "a/b/../c", "/a"}
6296	for _, id := range invalidBuildIds {
6297		message := fmt.Sprintf("Unable to use build id %s as filename suffix", id)
6298		fixture := android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
6299			variables.BuildId = proptools.StringPtr(id)
6300		})
6301		testApexError(t, message, `apex {
6302			name: "myapex",
6303			key: "myapex.key",
6304			apps: ["AppFooPrebuilt"],
6305			updatable: false,
6306		}
6307
6308		apex_key {
6309			name: "myapex.key",
6310			public_key: "testkey.avbpubkey",
6311			private_key: "testkey.pem",
6312		}
6313
6314		android_app_import {
6315			name: "AppFooPrebuilt",
6316			apk: "PrebuiltAppFoo.apk",
6317			presigned: true,
6318			apex_available: ["myapex"],
6319		}
6320	`, fixture)
6321	}
6322}
6323
6324func TestApexWithAppImports(t *testing.T) {
6325	t.Parallel()
6326	ctx := testApex(t, `
6327		apex {
6328			name: "myapex",
6329			key: "myapex.key",
6330			apps: [
6331				"AppFooPrebuilt",
6332				"AppFooPrivPrebuilt",
6333			],
6334			updatable: false,
6335		}
6336
6337		apex_key {
6338			name: "myapex.key",
6339			public_key: "testkey.avbpubkey",
6340			private_key: "testkey.pem",
6341		}
6342
6343		android_app_import {
6344			name: "AppFooPrebuilt",
6345			apk: "PrebuiltAppFoo.apk",
6346			presigned: true,
6347			dex_preopt: {
6348				enabled: false,
6349			},
6350			apex_available: ["myapex"],
6351		}
6352
6353		android_app_import {
6354			name: "AppFooPrivPrebuilt",
6355			apk: "PrebuiltAppFooPriv.apk",
6356			privileged: true,
6357			presigned: true,
6358			dex_preopt: {
6359				enabled: false,
6360			},
6361			filename: "AwesomePrebuiltAppFooPriv.apk",
6362			apex_available: ["myapex"],
6363		}
6364	`)
6365
6366	module := ctx.ModuleForTests(t, "myapex", "android_common_myapex")
6367	apexRule := module.Rule("apexRule")
6368	copyCmds := apexRule.Args["copy_commands"]
6369
6370	ensureContains(t, copyCmds, "image.apex/app/AppFooPrebuilt@TEST.BUILD_ID/AppFooPrebuilt.apk")
6371	ensureContains(t, copyCmds, "image.apex/priv-app/AppFooPrivPrebuilt@TEST.BUILD_ID/AwesomePrebuiltAppFooPriv.apk")
6372}
6373
6374func TestApexWithAppImportsPrefer(t *testing.T) {
6375	t.Parallel()
6376	ctx := testApex(t, `
6377		apex {
6378			name: "myapex",
6379			key: "myapex.key",
6380			apps: [
6381				"AppFoo",
6382			],
6383			updatable: false,
6384		}
6385
6386		apex_key {
6387			name: "myapex.key",
6388			public_key: "testkey.avbpubkey",
6389			private_key: "testkey.pem",
6390		}
6391
6392		android_app {
6393			name: "AppFoo",
6394			srcs: ["foo/bar/MyClass.java"],
6395			sdk_version: "none",
6396			system_modules: "none",
6397			apex_available: [ "myapex" ],
6398		}
6399
6400		android_app_import {
6401			name: "AppFoo",
6402			apk: "AppFooPrebuilt.apk",
6403			filename: "AppFooPrebuilt.apk",
6404			presigned: true,
6405			prefer: true,
6406			apex_available: ["myapex"],
6407		}
6408	`, withFiles(map[string][]byte{
6409		"AppFooPrebuilt.apk": nil,
6410	}))
6411
6412	ensureExactContents(t, ctx, "myapex", "android_common_myapex", []string{
6413		"app/AppFoo@TEST.BUILD_ID/AppFooPrebuilt.apk",
6414	})
6415}
6416
6417func TestApexWithTestHelperApp(t *testing.T) {
6418	t.Parallel()
6419	ctx := testApex(t, `
6420		apex {
6421			name: "myapex",
6422			key: "myapex.key",
6423			apps: [
6424				"TesterHelpAppFoo",
6425			],
6426			updatable: false,
6427		}
6428
6429		apex_key {
6430			name: "myapex.key",
6431			public_key: "testkey.avbpubkey",
6432			private_key: "testkey.pem",
6433		}
6434
6435		android_test_helper_app {
6436			name: "TesterHelpAppFoo",
6437			srcs: ["foo/bar/MyClass.java"],
6438			apex_available: [ "myapex" ],
6439			sdk_version: "test_current",
6440		}
6441
6442	`)
6443
6444	module := ctx.ModuleForTests(t, "myapex", "android_common_myapex")
6445	apexRule := module.Rule("apexRule")
6446	copyCmds := apexRule.Args["copy_commands"]
6447
6448	ensureContains(t, copyCmds, "image.apex/app/TesterHelpAppFoo@TEST.BUILD_ID/TesterHelpAppFoo.apk")
6449}
6450
6451func TestApexPropertiesShouldBeDefaultable(t *testing.T) {
6452	t.Parallel()
6453	// libfoo's apex_available comes from cc_defaults
6454	testApexError(t, `requires "libfoo" that doesn't list the APEX under 'apex_available'.`, `
6455	apex {
6456		name: "myapex",
6457		key: "myapex.key",
6458		native_shared_libs: ["libfoo"],
6459		updatable: false,
6460	}
6461
6462	apex_key {
6463		name: "myapex.key",
6464		public_key: "testkey.avbpubkey",
6465		private_key: "testkey.pem",
6466	}
6467
6468	apex {
6469		name: "otherapex",
6470		key: "myapex.key",
6471		native_shared_libs: ["libfoo"],
6472		updatable: false,
6473	}
6474
6475	cc_defaults {
6476		name: "libfoo-defaults",
6477		apex_available: ["otherapex"],
6478	}
6479
6480	cc_library {
6481		name: "libfoo",
6482		defaults: ["libfoo-defaults"],
6483		stl: "none",
6484		system_shared_libs: [],
6485	}`)
6486}
6487
6488func TestApexAvailable_DirectDep(t *testing.T) {
6489	t.Parallel()
6490	// libfoo is not available to myapex, but only to otherapex
6491	testApexError(t, "requires \"libfoo\" that doesn't list the APEX under 'apex_available'.", `
6492	apex {
6493		name: "myapex",
6494		key: "myapex.key",
6495		native_shared_libs: ["libfoo"],
6496		updatable: false,
6497	}
6498
6499	apex_key {
6500		name: "myapex.key",
6501		public_key: "testkey.avbpubkey",
6502		private_key: "testkey.pem",
6503	}
6504
6505	apex {
6506		name: "otherapex",
6507		key: "otherapex.key",
6508		native_shared_libs: ["libfoo"],
6509		updatable: false,
6510	}
6511
6512	apex_key {
6513		name: "otherapex.key",
6514		public_key: "testkey.avbpubkey",
6515		private_key: "testkey.pem",
6516	}
6517
6518	cc_library {
6519		name: "libfoo",
6520		stl: "none",
6521		system_shared_libs: [],
6522		apex_available: ["otherapex"],
6523	}`)
6524
6525	// 'apex_available' check is bypassed for /product apex with a specific prefix.
6526	// TODO: b/352818241 - Remove below two cases after APEX availability is enforced for /product APEXes.
6527	testApex(t, `
6528	apex {
6529		name: "com.sdv.myapex",
6530		key: "myapex.key",
6531		native_shared_libs: ["libfoo"],
6532		updatable: false,
6533		product_specific: true,
6534	}
6535
6536	apex_key {
6537		name: "myapex.key",
6538		public_key: "testkey.avbpubkey",
6539		private_key: "testkey.pem",
6540	}
6541
6542	apex {
6543		name: "com.any.otherapex",
6544		key: "otherapex.key",
6545		native_shared_libs: ["libfoo"],
6546		updatable: false,
6547	}
6548
6549	apex_key {
6550		name: "otherapex.key",
6551		public_key: "testkey.avbpubkey",
6552		private_key: "testkey.pem",
6553	}
6554
6555	cc_library {
6556		name: "libfoo",
6557		stl: "none",
6558		system_shared_libs: [],
6559		apex_available: ["com.any.otherapex"],
6560		product_specific: true,
6561	}`,
6562		android.FixtureMergeMockFs(android.MockFS{
6563			"system/sepolicy/apex/com.sdv.myapex-file_contexts":    nil,
6564			"system/sepolicy/apex/com.any.otherapex-file_contexts": nil,
6565		}))
6566
6567	// 'apex_available' check is not bypassed for non-product apex with a specific prefix.
6568	testApexError(t, "requires \"libfoo\" that doesn't list the APEX under 'apex_available'.", `
6569	apex {
6570		name: "com.sdv.myapex",
6571		key: "myapex.key",
6572		native_shared_libs: ["libfoo"],
6573		updatable: false,
6574	}
6575
6576	apex_key {
6577		name: "myapex.key",
6578		public_key: "testkey.avbpubkey",
6579		private_key: "testkey.pem",
6580	}
6581
6582	apex {
6583		name: "com.any.otherapex",
6584		key: "otherapex.key",
6585		native_shared_libs: ["libfoo"],
6586		updatable: false,
6587	}
6588
6589	apex_key {
6590		name: "otherapex.key",
6591		public_key: "testkey.avbpubkey",
6592		private_key: "testkey.pem",
6593	}
6594
6595	cc_library {
6596		name: "libfoo",
6597		stl: "none",
6598		system_shared_libs: [],
6599		apex_available: ["com.any.otherapex"],
6600	}`,
6601		android.FixtureMergeMockFs(android.MockFS{
6602			"system/sepolicy/apex/com.sdv.myapex-file_contexts":    nil,
6603			"system/sepolicy/apex/com.any.otherapex-file_contexts": nil,
6604		}))
6605}
6606
6607func TestApexAvailable_IndirectDep(t *testing.T) {
6608	t.Parallel()
6609	// libbbaz is an indirect dep
6610	testApexError(t, `requires "libbaz" that doesn't list the APEX under 'apex_available'.\n\nDependency path:
6611.*via tag apex\.dependencyTag\{"sharedLib"\}
6612.*-> libfoo.*link:shared.*
6613.*via tag cc\.libraryDependencyTag.*Kind:sharedLibraryDependency.*
6614.*-> libbar.*link:shared.*
6615.*via tag cc\.libraryDependencyTag.*Kind:sharedLibraryDependency.*
6616.*-> libbaz.*link:shared.*`, `
6617	apex {
6618		name: "myapex",
6619		key: "myapex.key",
6620		native_shared_libs: ["libfoo"],
6621		updatable: false,
6622	}
6623
6624	apex_key {
6625		name: "myapex.key",
6626		public_key: "testkey.avbpubkey",
6627		private_key: "testkey.pem",
6628	}
6629
6630	cc_library {
6631		name: "libfoo",
6632		stl: "none",
6633		shared_libs: ["libbar"],
6634		system_shared_libs: [],
6635		apex_available: ["myapex"],
6636	}
6637
6638	cc_library {
6639		name: "libbar",
6640		stl: "none",
6641		shared_libs: ["libbaz"],
6642		system_shared_libs: [],
6643		apex_available: ["myapex"],
6644	}
6645
6646	cc_library {
6647		name: "libbaz",
6648		stl: "none",
6649		system_shared_libs: [],
6650	}`)
6651
6652	// 'apex_available' check is bypassed for /product apex with a specific prefix.
6653	// TODO: b/352818241 - Remove below two cases after APEX availability is enforced for /product APEXes.
6654	testApex(t, `
6655		apex {
6656			name: "com.sdv.myapex",
6657			key: "myapex.key",
6658			native_shared_libs: ["libfoo"],
6659			updatable: false,
6660			product_specific: true,
6661		}
6662
6663		apex_key {
6664			name: "myapex.key",
6665			public_key: "testkey.avbpubkey",
6666			private_key: "testkey.pem",
6667		}
6668
6669		cc_library {
6670			name: "libfoo",
6671			stl: "none",
6672			shared_libs: ["libbar"],
6673			system_shared_libs: [],
6674			apex_available: ["com.sdv.myapex"],
6675			product_specific: true,
6676		}
6677
6678		cc_library {
6679			name: "libbar",
6680			stl: "none",
6681			shared_libs: ["libbaz"],
6682			system_shared_libs: [],
6683			apex_available: ["com.sdv.myapex"],
6684			product_specific: true,
6685		}
6686
6687		cc_library {
6688			name: "libbaz",
6689			stl: "none",
6690			system_shared_libs: [],
6691			product_specific: true,
6692		}`,
6693		android.FixtureMergeMockFs(android.MockFS{
6694			"system/sepolicy/apex/com.sdv.myapex-file_contexts": nil,
6695		}))
6696
6697	// 'apex_available' check is not bypassed for non-product apex with a specific prefix.
6698	testApexError(t, `requires "libbaz" that doesn't list the APEX under 'apex_available'.`, `
6699		apex {
6700			name: "com.sdv.myapex",
6701			key: "myapex.key",
6702			native_shared_libs: ["libfoo"],
6703			updatable: false,
6704		}
6705
6706		apex_key {
6707			name: "myapex.key",
6708			public_key: "testkey.avbpubkey",
6709			private_key: "testkey.pem",
6710		}
6711
6712		cc_library {
6713			name: "libfoo",
6714			stl: "none",
6715			shared_libs: ["libbar"],
6716			system_shared_libs: [],
6717			apex_available: ["com.sdv.myapex"],
6718		}
6719
6720		cc_library {
6721			name: "libbar",
6722			stl: "none",
6723			shared_libs: ["libbaz"],
6724			system_shared_libs: [],
6725			apex_available: ["com.sdv.myapex"],
6726		}
6727
6728		cc_library {
6729			name: "libbaz",
6730			stl: "none",
6731			system_shared_libs: [],
6732		}`,
6733		android.FixtureMergeMockFs(android.MockFS{
6734			"system/sepolicy/apex/com.sdv.myapex-file_contexts": nil,
6735		}))
6736}
6737
6738func TestApexAvailable_IndirectStaticDep(t *testing.T) {
6739	t.Parallel()
6740	testApex(t, `
6741	apex {
6742		name: "myapex",
6743		key: "myapex.key",
6744		native_shared_libs: ["libfoo"],
6745		updatable: false,
6746	}
6747
6748	apex_key {
6749		name: "myapex.key",
6750		public_key: "testkey.avbpubkey",
6751		private_key: "testkey.pem",
6752	}
6753
6754	cc_library {
6755		name: "libfoo",
6756		stl: "none",
6757		static_libs: ["libbar"],
6758		system_shared_libs: [],
6759		apex_available: ["myapex"],
6760	}
6761
6762	cc_library {
6763		name: "libbar",
6764		stl: "none",
6765		shared_libs: ["libbaz"],
6766		system_shared_libs: [],
6767		apex_available: ["myapex"],
6768	}
6769
6770	cc_library {
6771		name: "libbaz",
6772		stl: "none",
6773		system_shared_libs: [],
6774	}`)
6775
6776	testApexError(t, `requires "libbar" that doesn't list the APEX under 'apex_available'.`, `
6777	apex {
6778		name: "myapex",
6779		key: "myapex.key",
6780		native_shared_libs: ["libfoo"],
6781		updatable: false,
6782	}
6783
6784	apex_key {
6785		name: "myapex.key",
6786		public_key: "testkey.avbpubkey",
6787		private_key: "testkey.pem",
6788	}
6789
6790	cc_library {
6791		name: "libfoo",
6792		stl: "none",
6793		static_libs: ["libbar"],
6794		system_shared_libs: [],
6795		apex_available: ["myapex"],
6796	}
6797
6798	cc_library {
6799		name: "libbar",
6800		stl: "none",
6801		system_shared_libs: [],
6802	}`)
6803}
6804
6805func TestApexAvailable_InvalidApexName(t *testing.T) {
6806	t.Parallel()
6807	testApexError(t, "\"otherapex\" is not a valid module name", `
6808	apex {
6809		name: "myapex",
6810		key: "myapex.key",
6811		native_shared_libs: ["libfoo"],
6812		updatable: false,
6813	}
6814
6815	apex_key {
6816		name: "myapex.key",
6817		public_key: "testkey.avbpubkey",
6818		private_key: "testkey.pem",
6819	}
6820
6821	cc_library {
6822		name: "libfoo",
6823		stl: "none",
6824		system_shared_libs: [],
6825		apex_available: ["otherapex"],
6826	}`)
6827
6828	testApex(t, `
6829	apex {
6830		name: "myapex",
6831		key: "myapex.key",
6832		native_shared_libs: ["libfoo", "libbar"],
6833		updatable: false,
6834	}
6835
6836	apex_key {
6837		name: "myapex.key",
6838		public_key: "testkey.avbpubkey",
6839		private_key: "testkey.pem",
6840	}
6841
6842	cc_library {
6843		name: "libfoo",
6844		stl: "none",
6845		system_shared_libs: [],
6846		runtime_libs: ["libbaz"],
6847		apex_available: ["myapex"],
6848	}
6849
6850	cc_library {
6851		name: "libbar",
6852		stl: "none",
6853		system_shared_libs: [],
6854		apex_available: ["//apex_available:anyapex"],
6855	}
6856
6857	cc_library {
6858		name: "libbaz",
6859		stl: "none",
6860		system_shared_libs: [],
6861		stubs: {
6862			versions: ["10", "20", "30"],
6863		},
6864	}`)
6865}
6866
6867func TestApexAvailable_ApexAvailableNameWithVersionCodeError(t *testing.T) {
6868	t.Parallel()
6869	t.Run("negative variant_version produces error", func(t *testing.T) {
6870		t.Parallel()
6871		testApexError(t, "expected an integer between 0-9; got -1", `
6872			apex {
6873				name: "myapex",
6874				key: "myapex.key",
6875				apex_available_name: "com.android.foo",
6876				variant_version: "-1",
6877				updatable: false,
6878			}
6879			apex_key {
6880				name: "myapex.key",
6881				public_key: "testkey.avbpubkey",
6882				private_key: "testkey.pem",
6883			}
6884		`)
6885	})
6886
6887	t.Run("variant_version greater than 9 produces error", func(t *testing.T) {
6888		t.Parallel()
6889		testApexError(t, "expected an integer between 0-9; got 10", `
6890			apex {
6891				name: "myapex",
6892				key: "myapex.key",
6893				apex_available_name: "com.android.foo",
6894				variant_version: "10",
6895				updatable: false,
6896			}
6897			apex_key {
6898				name: "myapex.key",
6899				public_key: "testkey.avbpubkey",
6900				private_key: "testkey.pem",
6901			}
6902		`)
6903	})
6904}
6905
6906func TestApexAvailable_ApexAvailableNameWithVersionCode(t *testing.T) {
6907	t.Parallel()
6908	context := android.GroupFixturePreparers(
6909		android.PrepareForIntegrationTestWithAndroid,
6910		PrepareForTestWithApexBuildComponents,
6911		android.FixtureMergeMockFs(android.MockFS{
6912			"system/sepolicy/apex/foo-file_contexts": nil,
6913			"system/sepolicy/apex/bar-file_contexts": nil,
6914		}),
6915	)
6916	result := context.RunTestWithBp(t, `
6917		apex {
6918			name: "foo",
6919			key: "myapex.key",
6920			apex_available_name: "com.android.foo",
6921			variant_version: "0",
6922			updatable: false,
6923		}
6924		apex {
6925			name: "bar",
6926			key: "myapex.key",
6927			apex_available_name: "com.android.foo",
6928			variant_version: "3",
6929			updatable: false,
6930		}
6931		apex_key {
6932			name: "myapex.key",
6933			public_key: "testkey.avbpubkey",
6934			private_key: "testkey.pem",
6935		}
6936		override_apex {
6937			name: "myoverrideapex",
6938			base: "bar",
6939		}
6940	`)
6941
6942	fooManifestRule := result.ModuleForTests(t, "foo", "android_common_foo").Rule("apexManifestRule")
6943	fooExpectedDefaultVersion := testDefaultUpdatableModuleVersion
6944	fooActualDefaultVersion := fooManifestRule.Args["default_version"]
6945	if fooActualDefaultVersion != fooExpectedDefaultVersion {
6946		t.Errorf("expected to find defaultVersion %q; got %q", fooExpectedDefaultVersion, fooActualDefaultVersion)
6947	}
6948
6949	barManifestRule := result.ModuleForTests(t, "bar", "android_common_bar").Rule("apexManifestRule")
6950	defaultVersionInt, _ := strconv.Atoi(testDefaultUpdatableModuleVersion)
6951	barExpectedDefaultVersion := fmt.Sprint(defaultVersionInt + 3)
6952	barActualDefaultVersion := barManifestRule.Args["default_version"]
6953	if barActualDefaultVersion != barExpectedDefaultVersion {
6954		t.Errorf("expected to find defaultVersion %q; got %q", barExpectedDefaultVersion, barActualDefaultVersion)
6955	}
6956
6957	overrideBarManifestRule := result.ModuleForTests(t, "bar", "android_common_myoverrideapex_myoverrideapex").Rule("apexManifestRule")
6958	overrideBarActualDefaultVersion := overrideBarManifestRule.Args["default_version"]
6959	if overrideBarActualDefaultVersion != barExpectedDefaultVersion {
6960		t.Errorf("expected to find defaultVersion %q; got %q", barExpectedDefaultVersion, barActualDefaultVersion)
6961	}
6962}
6963
6964func TestApexAvailable_ApexAvailableName(t *testing.T) {
6965	t.Parallel()
6966	t.Run("using name of apex that sets apex_available_name is not allowed", func(t *testing.T) {
6967		t.Parallel()
6968		testApexError(t, "Consider adding \"myapex\" to 'apex_available' property of \"AppFoo\"", `
6969			apex {
6970				name: "myapex_sminus",
6971				key: "myapex.key",
6972				apps: ["AppFoo"],
6973				apex_available_name: "myapex",
6974				updatable: false,
6975			}
6976			apex {
6977				name: "myapex",
6978				key: "myapex.key",
6979				apps: ["AppFoo"],
6980				updatable: false,
6981			}
6982			apex_key {
6983				name: "myapex.key",
6984				public_key: "testkey.avbpubkey",
6985				private_key: "testkey.pem",
6986			}
6987			android_app {
6988				name: "AppFoo",
6989				srcs: ["foo/bar/MyClass.java"],
6990				sdk_version: "none",
6991				system_modules: "none",
6992				apex_available: [ "myapex_sminus" ],
6993			}`,
6994			android.FixtureMergeMockFs(android.MockFS{
6995				"system/sepolicy/apex/myapex_sminus-file_contexts": nil,
6996			}),
6997		)
6998	})
6999
7000	t.Run("apex_available_name allows module to be used in two different apexes", func(t *testing.T) {
7001		t.Parallel()
7002		testApex(t, `
7003			apex {
7004				name: "myapex_sminus",
7005				key: "myapex.key",
7006				apps: ["AppFoo"],
7007				apex_available_name: "myapex",
7008				updatable: false,
7009			}
7010			apex {
7011				name: "myapex",
7012				key: "myapex.key",
7013				apps: ["AppFoo"],
7014				updatable: false,
7015			}
7016			apex_key {
7017				name: "myapex.key",
7018				public_key: "testkey.avbpubkey",
7019				private_key: "testkey.pem",
7020			}
7021			android_app {
7022				name: "AppFoo",
7023				srcs: ["foo/bar/MyClass.java"],
7024				sdk_version: "none",
7025				system_modules: "none",
7026				apex_available: [ "myapex" ],
7027			}`,
7028			android.FixtureMergeMockFs(android.MockFS{
7029				"system/sepolicy/apex/myapex_sminus-file_contexts": nil,
7030			}),
7031		)
7032	})
7033
7034	t.Run("override_apexes work with apex_available_name", func(t *testing.T) {
7035		t.Parallel()
7036		testApex(t, `
7037			override_apex {
7038				name: "myoverrideapex_sminus",
7039				base: "myapex_sminus",
7040				key: "myapex.key",
7041				apps: ["AppFooOverride"],
7042			}
7043			override_apex {
7044				name: "myoverrideapex",
7045				base: "myapex",
7046				key: "myapex.key",
7047				apps: ["AppFooOverride"],
7048			}
7049			apex {
7050				name: "myapex_sminus",
7051				key: "myapex.key",
7052				apps: ["AppFoo"],
7053				apex_available_name: "myapex",
7054				updatable: false,
7055			}
7056			apex {
7057				name: "myapex",
7058				key: "myapex.key",
7059				apps: ["AppFoo"],
7060				updatable: false,
7061			}
7062			apex_key {
7063				name: "myapex.key",
7064				public_key: "testkey.avbpubkey",
7065				private_key: "testkey.pem",
7066			}
7067			android_app {
7068				name: "AppFooOverride",
7069				srcs: ["foo/bar/MyClass.java"],
7070				sdk_version: "none",
7071				system_modules: "none",
7072				apex_available: [ "myapex" ],
7073			}
7074			android_app {
7075				name: "AppFoo",
7076				srcs: ["foo/bar/MyClass.java"],
7077				sdk_version: "none",
7078				system_modules: "none",
7079				apex_available: [ "myapex" ],
7080			}`,
7081			android.FixtureMergeMockFs(android.MockFS{
7082				"system/sepolicy/apex/myapex_sminus-file_contexts": nil,
7083			}),
7084		)
7085	})
7086}
7087
7088func TestApexAvailable_ApexAvailableNameWithOverrides(t *testing.T) {
7089	t.Parallel()
7090	context := android.GroupFixturePreparers(
7091		android.PrepareForIntegrationTestWithAndroid,
7092		PrepareForTestWithApexBuildComponents,
7093		java.PrepareForTestWithDexpreopt,
7094		android.FixtureMergeMockFs(android.MockFS{
7095			"system/sepolicy/apex/myapex-file_contexts":        nil,
7096			"system/sepolicy/apex/myapex_sminus-file_contexts": nil,
7097		}),
7098		android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
7099			variables.BuildId = proptools.StringPtr("buildid")
7100		}),
7101	)
7102	context.RunTestWithBp(t, `
7103	override_apex {
7104		name: "myoverrideapex_sminus",
7105		base: "myapex_sminus",
7106	}
7107	override_apex {
7108		name: "myoverrideapex",
7109		base: "myapex",
7110	}
7111	apex {
7112		name: "myapex",
7113		key: "myapex.key",
7114		apps: ["AppFoo"],
7115		updatable: false,
7116	}
7117	apex {
7118		name: "myapex_sminus",
7119		apex_available_name: "myapex",
7120		key: "myapex.key",
7121		apps: ["AppFoo_sminus"],
7122		updatable: false,
7123	}
7124	apex_key {
7125		name: "myapex.key",
7126		public_key: "testkey.avbpubkey",
7127		private_key: "testkey.pem",
7128	}
7129	android_app {
7130		name: "AppFoo",
7131		srcs: ["foo/bar/MyClass.java"],
7132		sdk_version: "none",
7133		system_modules: "none",
7134		apex_available: [ "myapex" ],
7135	}
7136	android_app {
7137		name: "AppFoo_sminus",
7138		srcs: ["foo/bar/MyClass.java"],
7139		sdk_version: "none",
7140		min_sdk_version: "29",
7141		system_modules: "none",
7142		apex_available: [ "myapex" ],
7143	}`)
7144}
7145
7146func TestApexAvailable_CheckForPlatform(t *testing.T) {
7147	t.Parallel()
7148	ctx := testApex(t, `
7149	apex {
7150		name: "myapex",
7151		key: "myapex.key",
7152		native_shared_libs: ["libbar", "libbaz"],
7153		updatable: false,
7154	}
7155
7156	apex_key {
7157		name: "myapex.key",
7158		public_key: "testkey.avbpubkey",
7159		private_key: "testkey.pem",
7160	}
7161
7162	cc_library {
7163		name: "libfoo",
7164		stl: "none",
7165		system_shared_libs: [],
7166		shared_libs: ["libbar"],
7167		apex_available: ["//apex_available:platform"],
7168	}
7169
7170	cc_library {
7171		name: "libfoo2",
7172		stl: "none",
7173		system_shared_libs: [],
7174		shared_libs: ["libbaz"],
7175		apex_available: ["//apex_available:platform"],
7176	}
7177
7178	cc_library {
7179		name: "libbar",
7180		stl: "none",
7181		system_shared_libs: [],
7182		apex_available: ["myapex"],
7183	}
7184
7185	cc_library {
7186		name: "libbaz",
7187		stl: "none",
7188		system_shared_libs: [],
7189		apex_available: ["myapex"],
7190		stubs: {
7191			versions: ["1"],
7192		},
7193	}`)
7194
7195	// libfoo shouldn't be available to platform even though it has "//apex_available:platform",
7196	// because it depends on libbar which isn't available to platform
7197	libfoo := ctx.ModuleForTests(t, "libfoo", "android_arm64_armv8-a_shared").Module().(*cc.Module)
7198	if libfoo.NotAvailableForPlatform() != true {
7199		t.Errorf("%q shouldn't be available to platform", libfoo.String())
7200	}
7201
7202	// libfoo2 however can be available to platform because it depends on libbaz which provides
7203	// stubs
7204	libfoo2 := ctx.ModuleForTests(t, "libfoo2", "android_arm64_armv8-a_shared").Module().(*cc.Module)
7205	if libfoo2.NotAvailableForPlatform() == true {
7206		t.Errorf("%q should be available to platform", libfoo2.String())
7207	}
7208}
7209
7210func TestApexAvailable_CreatedForApex(t *testing.T) {
7211	t.Parallel()
7212	ctx := testApex(t, `
7213	apex {
7214		name: "myapex",
7215		key: "myapex.key",
7216		native_shared_libs: ["libfoo"],
7217		updatable: false,
7218	}
7219
7220	apex_key {
7221		name: "myapex.key",
7222		public_key: "testkey.avbpubkey",
7223		private_key: "testkey.pem",
7224	}
7225
7226	cc_library {
7227		name: "libfoo",
7228		stl: "none",
7229		system_shared_libs: [],
7230		apex_available: ["myapex"],
7231		static: {
7232			apex_available: ["//apex_available:platform"],
7233		},
7234	}`)
7235
7236	libfooShared := ctx.ModuleForTests(t, "libfoo", "android_arm64_armv8-a_shared").Module().(*cc.Module)
7237	if libfooShared.NotAvailableForPlatform() != true {
7238		t.Errorf("%q shouldn't be available to platform", libfooShared.String())
7239	}
7240	libfooStatic := ctx.ModuleForTests(t, "libfoo", "android_arm64_armv8-a_static").Module().(*cc.Module)
7241	if libfooStatic.NotAvailableForPlatform() != false {
7242		t.Errorf("%q should be available to platform", libfooStatic.String())
7243	}
7244}
7245
7246func TestApexAvailable_PrefixMatch(t *testing.T) {
7247	t.Parallel()
7248
7249	for _, tc := range []struct {
7250		name          string
7251		apexAvailable string
7252		expectedError string
7253	}{
7254		{
7255			name:          "prefix matches correctly",
7256			apexAvailable: "com.foo.*",
7257		},
7258		{
7259			name:          "prefix doesn't match",
7260			apexAvailable: "com.bar.*",
7261			expectedError: `Consider .* "com.foo\.\*"`,
7262		},
7263		{
7264			name:          "short prefix",
7265			apexAvailable: "com.*",
7266			expectedError: "requires two or more components",
7267		},
7268		{
7269			name:          "wildcard not in the end",
7270			apexAvailable: "com.*.foo",
7271			expectedError: "should end with .*",
7272		},
7273		{
7274			name:          "wildcard in the middle",
7275			apexAvailable: "com.foo*.*",
7276			expectedError: "not allowed in the middle",
7277		},
7278		{
7279			name:          "hint with prefix pattern",
7280			apexAvailable: "//apex_available:platform",
7281			expectedError: "Consider adding \"com.foo.bar\" or \"com.foo.*\"",
7282		},
7283	} {
7284		t.Run(tc.name, func(t *testing.T) {
7285			t.Parallel()
7286			errorHandler := android.FixtureExpectsNoErrors
7287			if tc.expectedError != "" {
7288				errorHandler = android.FixtureExpectsAtLeastOneErrorMatchingPattern(tc.expectedError)
7289			}
7290			context := android.GroupFixturePreparers(
7291				prepareForApexTest,
7292				android.FixtureMergeMockFs(android.MockFS{
7293					"system/sepolicy/apex/com.foo.bar-file_contexts": nil,
7294				}),
7295			).ExtendWithErrorHandler(errorHandler)
7296
7297			context.RunTestWithBp(t, `
7298				apex {
7299					name: "com.foo.bar",
7300					key: "myapex.key",
7301					native_shared_libs: ["libfoo"],
7302					updatable: false,
7303				}
7304
7305				apex_key {
7306					name: "myapex.key",
7307					public_key: "testkey.avbpubkey",
7308					private_key: "testkey.pem",
7309				}
7310
7311				cc_library {
7312					name: "libfoo",
7313					stl: "none",
7314					system_shared_libs: [],
7315					apex_available: ["`+tc.apexAvailable+`"],
7316				}`)
7317		})
7318	}
7319	testApexError(t, `Consider adding "com.foo" to`, `
7320		apex {
7321			name: "com.foo", // too short for a partner apex
7322			key: "myapex.key",
7323			native_shared_libs: ["libfoo"],
7324			updatable: false,
7325		}
7326
7327		apex_key {
7328			name: "myapex.key",
7329			public_key: "testkey.avbpubkey",
7330			private_key: "testkey.pem",
7331		}
7332
7333		cc_library {
7334			name: "libfoo",
7335			stl: "none",
7336			system_shared_libs: [],
7337		}
7338	`)
7339}
7340
7341func TestApexValidation_UsesProperPartitionTag(t *testing.T) {
7342	t.Parallel()
7343	ctx := testApex(t, `
7344		apex {
7345			name: "myapex",
7346			key: "myapex.key",
7347			updatable: false,
7348			vendor: true,
7349		}
7350		apex_key {
7351			name: "myapex.key",
7352			public_key: "testkey.avbpubkey",
7353			private_key: "testkey.pem",
7354		}
7355	`, android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
7356		// vendor path should not affect "partition tag"
7357		variables.VendorPath = proptools.StringPtr("system/vendor")
7358	}))
7359
7360	module := ctx.ModuleForTests(t, "myapex", "android_common_myapex")
7361	android.AssertStringEquals(t, "partition tag for host_apex_verifier",
7362		"vendor",
7363		module.Output("host_apex_verifier.timestamp").Args["partition_tag"])
7364	android.AssertStringEquals(t, "partition tag for apex_sepolicy_tests",
7365		"vendor",
7366		module.Output("apex_sepolicy_tests.timestamp").Args["partition_tag"])
7367}
7368
7369func TestApexValidation_TestApexCanSkipInitRcCheck(t *testing.T) {
7370	t.Parallel()
7371	ctx := testApex(t, `
7372		apex_test {
7373			name: "myapex",
7374			key: "myapex.key",
7375			skip_validations: {
7376				host_apex_verifier: true,
7377			},
7378			updatable: false,
7379		}
7380		apex_key {
7381			name: "myapex.key",
7382			public_key: "testkey.avbpubkey",
7383			private_key: "testkey.pem",
7384		}
7385	`)
7386
7387	validations := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Rule("signapk").Validations.Strings()
7388	if android.SuffixInList(validations, "host_apex_verifier.timestamp") {
7389		t.Error("should not run host_apex_verifier")
7390	}
7391}
7392
7393func TestApexValidation_TestApexCheckInitRc(t *testing.T) {
7394	t.Parallel()
7395	ctx := testApex(t, `
7396		apex_test {
7397			name: "myapex",
7398			key: "myapex.key",
7399			updatable: false,
7400		}
7401		apex_key {
7402			name: "myapex.key",
7403			public_key: "testkey.avbpubkey",
7404			private_key: "testkey.pem",
7405		}
7406	`)
7407
7408	validations := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Rule("signapk").Validations.Strings()
7409	if !android.SuffixInList(validations, "host_apex_verifier.timestamp") {
7410		t.Error("should run host_apex_verifier")
7411	}
7412}
7413
7414func TestOverrideApex(t *testing.T) {
7415	t.Parallel()
7416	ctx := testApex(t, `
7417		apex {
7418			name: "myapex",
7419			key: "myapex.key",
7420			apps: ["app"],
7421			bpfs: ["bpf"],
7422			prebuilts: ["myetc"],
7423			overrides: ["oldapex"],
7424			updatable: false,
7425		}
7426
7427		override_apex {
7428			name: "override_myapex",
7429			base: "myapex",
7430			apps: ["override_app"],
7431			bpfs: ["overrideBpf"],
7432			prebuilts: ["override_myetc"],
7433			overrides: ["unknownapex"],
7434			compile_multilib: "first",
7435			multilib: {
7436				lib32: {
7437					native_shared_libs: ["mylib32"],
7438				},
7439				lib64: {
7440					native_shared_libs: ["mylib64"],
7441				},
7442			},
7443			logging_parent: "com.foo.bar",
7444			package_name: "test.overridden.package",
7445			key: "mynewapex.key",
7446			certificate: ":myapex.certificate",
7447		}
7448
7449		apex_key {
7450			name: "myapex.key",
7451			public_key: "testkey.avbpubkey",
7452			private_key: "testkey.pem",
7453		}
7454
7455		apex_key {
7456			name: "mynewapex.key",
7457			public_key: "testkey2.avbpubkey",
7458			private_key: "testkey2.pem",
7459		}
7460
7461		android_app_certificate {
7462			name: "myapex.certificate",
7463			certificate: "testkey",
7464		}
7465
7466		android_app {
7467			name: "app",
7468			srcs: ["foo/bar/MyClass.java"],
7469			package_name: "foo",
7470			sdk_version: "none",
7471			system_modules: "none",
7472			apex_available: [ "myapex" ],
7473		}
7474
7475		override_android_app {
7476			name: "override_app",
7477			base: "app",
7478			package_name: "bar",
7479		}
7480
7481		bpf {
7482			name: "bpf",
7483			srcs: ["bpf.c"],
7484		}
7485
7486		bpf {
7487			name: "overrideBpf",
7488			srcs: ["overrideBpf.c"],
7489		}
7490
7491		prebuilt_etc {
7492			name: "myetc",
7493			src: "myprebuilt",
7494		}
7495
7496		prebuilt_etc {
7497			name: "override_myetc",
7498			src: "override_myprebuilt",
7499		}
7500
7501		cc_library {
7502			name: "mylib32",
7503			apex_available: [ "myapex" ],
7504		}
7505
7506		cc_library {
7507			name: "mylib64",
7508			apex_available: [ "myapex" ],
7509		}
7510	`, withManifestPackageNameOverrides([]string{"myapex:com.android.myapex"}))
7511
7512	originalVariant := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Module().(android.OverridableModule)
7513	overriddenVariant := ctx.ModuleForTests(t, "myapex", "android_common_override_myapex_override_myapex").Module().(android.OverridableModule)
7514	if originalVariant.GetOverriddenBy() != "" {
7515		t.Errorf("GetOverriddenBy should be empty, but was %q", originalVariant.GetOverriddenBy())
7516	}
7517	if overriddenVariant.GetOverriddenBy() != "override_myapex" {
7518		t.Errorf("GetOverriddenBy should be \"override_myapex\", but was %q", overriddenVariant.GetOverriddenBy())
7519	}
7520
7521	module := ctx.ModuleForTests(t, "myapex", "android_common_override_myapex_override_myapex")
7522	apexRule := module.Rule("apexRule")
7523	copyCmds := apexRule.Args["copy_commands"]
7524
7525	ensureNotContains(t, copyCmds, "image.apex/app/app@TEST.BUILD_ID/app.apk")
7526	ensureContains(t, copyCmds, "image.apex/app/override_app@TEST.BUILD_ID/override_app.apk")
7527
7528	ensureNotContains(t, copyCmds, "image.apex/etc/bpf/bpf.o")
7529	ensureContains(t, copyCmds, "image.apex/etc/bpf/overrideBpf.o")
7530
7531	ensureNotContains(t, copyCmds, "image.apex/etc/myetc")
7532	ensureContains(t, copyCmds, "image.apex/etc/override_myetc")
7533
7534	apexBundle := module.Module().(*apexBundle)
7535	name := apexBundle.Name()
7536	if name != "override_myapex" {
7537		t.Errorf("name should be \"override_myapex\", but was %q", name)
7538	}
7539
7540	if apexBundle.overridableProperties.Logging_parent != "com.foo.bar" {
7541		t.Errorf("override_myapex should have logging parent (com.foo.bar), but was %q.", apexBundle.overridableProperties.Logging_parent)
7542	}
7543
7544	optFlags := apexRule.Args["opt_flags"]
7545	ensureContains(t, optFlags, "--override_apk_package_name test.overridden.package")
7546	ensureContains(t, optFlags, "--pubkey testkey2.avbpubkey")
7547
7548	signApkRule := module.Rule("signapk")
7549	ensureEquals(t, signApkRule.Args["certificates"], "testkey.x509.pem testkey.pk8")
7550
7551	data := android.AndroidMkDataForTest(t, ctx, apexBundle)
7552	var builder strings.Builder
7553	data.Custom(&builder, name, "TARGET_", "", data)
7554	androidMk := builder.String()
7555	ensureContains(t, androidMk, "LOCAL_MODULE := override_app.override_myapex")
7556	ensureContains(t, androidMk, "LOCAL_MODULE := overrideBpf.o.override_myapex")
7557	ensureContains(t, androidMk, "LOCAL_MODULE_STEM := override_myapex.apex")
7558	ensureContains(t, androidMk, "LOCAL_OVERRIDES_MODULES := unknownapex myapex")
7559	ensureNotContains(t, androidMk, "LOCAL_MODULE := app.myapex")
7560	ensureNotContains(t, androidMk, "LOCAL_MODULE := bpf.myapex")
7561	ensureNotContains(t, androidMk, "LOCAL_MODULE := override_app.myapex")
7562	ensureNotContains(t, androidMk, "LOCAL_MODULE_STEM := myapex.apex")
7563}
7564
7565func TestMinSdkVersionOverride(t *testing.T) {
7566	t.Parallel()
7567	// Override from 29 to 31
7568	minSdkOverride31 := "31"
7569	ctx := testApex(t, `
7570			apex {
7571					name: "myapex",
7572					key: "myapex.key",
7573					native_shared_libs: ["mylib"],
7574					updatable: true,
7575					min_sdk_version: "29"
7576			}
7577
7578			override_apex {
7579					name: "override_myapex",
7580					base: "myapex",
7581					logging_parent: "com.foo.bar",
7582					package_name: "test.overridden.package"
7583			}
7584
7585			apex_key {
7586					name: "myapex.key",
7587					public_key: "testkey.avbpubkey",
7588					private_key: "testkey.pem",
7589			}
7590
7591			cc_library {
7592					name: "mylib",
7593					srcs: ["mylib.cpp"],
7594					runtime_libs: ["libbar"],
7595					system_shared_libs: [],
7596					stl: "none",
7597					apex_available: [ "myapex" ],
7598					min_sdk_version: "apex_inherit"
7599			}
7600
7601			cc_library {
7602					name: "libbar",
7603					srcs: ["mylib.cpp"],
7604					system_shared_libs: [],
7605					stl: "none",
7606					apex_available: [ "myapex" ],
7607					min_sdk_version: "apex_inherit"
7608			}
7609
7610	`, withApexGlobalMinSdkVersionOverride(&minSdkOverride31))
7611
7612	apexRule := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Rule("apexRule")
7613	copyCmds := apexRule.Args["copy_commands"]
7614
7615	// Ensure that direct non-stubs dep is always included
7616	ensureContains(t, copyCmds, "image.apex/lib64/mylib.so")
7617
7618	// Ensure that runtime_libs dep in included
7619	ensureContains(t, copyCmds, "image.apex/lib64/libbar.so")
7620
7621	// Ensure libraries target overridden min_sdk_version value
7622	ensureListContains(t, ctx.ModuleVariantsForTests("libbar"), "android_arm64_armv8-a_shared_apex31")
7623}
7624
7625func TestMinSdkVersionOverrideToLowerVersionNoOp(t *testing.T) {
7626	t.Parallel()
7627	// Attempt to override from 31 to 29, should be a NOOP
7628	minSdkOverride29 := "29"
7629	ctx := testApex(t, `
7630			apex {
7631					name: "myapex",
7632					key: "myapex.key",
7633					native_shared_libs: ["mylib"],
7634					updatable: true,
7635					min_sdk_version: "31"
7636			}
7637
7638			override_apex {
7639					name: "override_myapex",
7640					base: "myapex",
7641					logging_parent: "com.foo.bar",
7642					package_name: "test.overridden.package"
7643			}
7644
7645			apex_key {
7646					name: "myapex.key",
7647					public_key: "testkey.avbpubkey",
7648					private_key: "testkey.pem",
7649			}
7650
7651			cc_library {
7652					name: "mylib",
7653					srcs: ["mylib.cpp"],
7654					runtime_libs: ["libbar"],
7655					system_shared_libs: [],
7656					stl: "none",
7657					apex_available: [ "myapex" ],
7658					min_sdk_version: "apex_inherit"
7659			}
7660
7661			cc_library {
7662					name: "libbar",
7663					srcs: ["mylib.cpp"],
7664					system_shared_libs: [],
7665					stl: "none",
7666					apex_available: [ "myapex" ],
7667					min_sdk_version: "apex_inherit"
7668			}
7669
7670	`, withApexGlobalMinSdkVersionOverride(&minSdkOverride29))
7671
7672	apexRule := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Rule("apexRule")
7673	copyCmds := apexRule.Args["copy_commands"]
7674
7675	// Ensure that direct non-stubs dep is always included
7676	ensureContains(t, copyCmds, "image.apex/lib64/mylib.so")
7677
7678	// Ensure that runtime_libs dep in included
7679	ensureContains(t, copyCmds, "image.apex/lib64/libbar.so")
7680
7681	// Ensure libraries target the original min_sdk_version value rather than the overridden
7682	ensureListContains(t, ctx.ModuleVariantsForTests("libbar"), "android_arm64_armv8-a_shared_apex31")
7683}
7684
7685func TestLegacyAndroid10Support(t *testing.T) {
7686	t.Parallel()
7687	ctx := testApex(t, `
7688		apex {
7689			name: "myapex",
7690			key: "myapex.key",
7691			native_shared_libs: ["mylib"],
7692			min_sdk_version: "29",
7693		}
7694
7695		apex_key {
7696			name: "myapex.key",
7697			public_key: "testkey.avbpubkey",
7698			private_key: "testkey.pem",
7699		}
7700
7701		cc_library {
7702			name: "mylib",
7703			srcs: ["mylib.cpp"],
7704			stl: "libc++",
7705			system_shared_libs: [],
7706			apex_available: [ "myapex" ],
7707			min_sdk_version: "29",
7708		}
7709	`, withUnbundledBuild)
7710
7711	module := ctx.ModuleForTests(t, "myapex", "android_common_myapex")
7712	args := module.Rule("apexRule").Args
7713	ensureContains(t, args["opt_flags"], "--manifest_json "+module.Output("apex_manifest.json").Output.String())
7714
7715	// The copies of the libraries in the apex should have one more dependency than
7716	// the ones outside the apex, namely the unwinder. Ideally we should check
7717	// the dependency names directly here but for some reason the names are blank in
7718	// this test.
7719	for _, lib := range []string{"libc++", "mylib"} {
7720		apexImplicits := ctx.ModuleForTests(t, lib, "android_arm64_armv8-a_shared_apex29").Rule("ld").Implicits
7721		nonApexImplicits := ctx.ModuleForTests(t, lib, "android_arm64_armv8-a_shared").Rule("ld").Implicits
7722		if len(apexImplicits) != len(nonApexImplicits)+1 {
7723			t.Errorf("%q missing unwinder dep", lib)
7724		}
7725	}
7726}
7727
7728var filesForSdkLibrary = android.MockFS{
7729	"api/current.txt":        nil,
7730	"api/removed.txt":        nil,
7731	"api/system-current.txt": nil,
7732	"api/system-removed.txt": nil,
7733	"api/test-current.txt":   nil,
7734	"api/test-removed.txt":   nil,
7735
7736	"100/public/api/foo.txt":         nil,
7737	"100/public/api/foo-removed.txt": nil,
7738	"100/system/api/foo.txt":         nil,
7739	"100/system/api/foo-removed.txt": nil,
7740
7741	// For java_sdk_library_import
7742	"a.jar": nil,
7743}
7744
7745func TestJavaSDKLibrary(t *testing.T) {
7746	t.Parallel()
7747	ctx := testApex(t, `
7748		apex {
7749			name: "myapex",
7750			key: "myapex.key",
7751			java_libs: ["foo"],
7752			updatable: false,
7753		}
7754
7755		apex_key {
7756			name: "myapex.key",
7757			public_key: "testkey.avbpubkey",
7758			private_key: "testkey.pem",
7759		}
7760
7761		java_sdk_library {
7762			name: "foo",
7763			srcs: ["a.java"],
7764			api_packages: ["foo"],
7765			apex_available: [ "myapex" ],
7766		}
7767
7768		prebuilt_apis {
7769			name: "sdk",
7770			api_dirs: ["100"],
7771		}
7772	`, withFiles(filesForSdkLibrary))
7773
7774	// java_sdk_library installs both impl jar and permission XML
7775	ensureExactContents(t, ctx, "myapex", "android_common_myapex", []string{
7776		"javalib/foo.jar",
7777		"etc/permissions/foo.xml",
7778	})
7779	// Permission XML should point to the activated path of impl jar of java_sdk_library
7780	sdkLibrary := ctx.ModuleForTests(t, "foo.xml", "android_common_myapex").Output("foo.xml")
7781	contents := android.ContentFromFileRuleForTests(t, ctx, sdkLibrary)
7782	ensureMatches(t, contents, "<library\\n\\s+name=\\\"foo\\\"\\n\\s+file=\\\"/apex/myapex/javalib/foo.jar\\\"")
7783}
7784
7785func TestJavaSDKLibraryOverrideApexes(t *testing.T) {
7786	t.Parallel()
7787	ctx := testApex(t, `
7788		override_apex {
7789			name: "mycompanyapex",
7790			base: "myapex",
7791		}
7792		apex {
7793			name: "myapex",
7794			key: "myapex.key",
7795			java_libs: ["foo"],
7796			updatable: false,
7797		}
7798
7799		apex_key {
7800			name: "myapex.key",
7801			public_key: "testkey.avbpubkey",
7802			private_key: "testkey.pem",
7803		}
7804
7805		java_sdk_library {
7806			name: "foo",
7807			srcs: ["a.java"],
7808			api_packages: ["foo"],
7809			apex_available: [ "myapex" ],
7810		}
7811
7812		prebuilt_apis {
7813			name: "sdk",
7814			api_dirs: ["100"],
7815		}
7816	`, withFiles(filesForSdkLibrary))
7817
7818	// Permission XML should point to the activated path of impl jar of java_sdk_library.
7819	// Since override variants (com.mycompany.android.foo) are installed in the same package as the overridden variant
7820	// (com.android.foo), the filepath should not contain override apex name.
7821	sdkLibrary := ctx.ModuleForTests(t, "foo.xml", "android_common_mycompanyapex").Output("foo.xml")
7822	contents := android.ContentFromFileRuleForTests(t, ctx, sdkLibrary)
7823	ensureMatches(t, contents, "<library\\n\\s+name=\\\"foo\\\"\\n\\s+file=\\\"/apex/myapex/javalib/foo.jar\\\"")
7824}
7825
7826func TestJavaSDKLibrary_WithinApex(t *testing.T) {
7827	t.Parallel()
7828	ctx := testApex(t, `
7829		apex {
7830			name: "myapex",
7831			key: "myapex.key",
7832			java_libs: ["foo", "bar"],
7833			updatable: false,
7834		}
7835
7836		apex_key {
7837			name: "myapex.key",
7838			public_key: "testkey.avbpubkey",
7839			private_key: "testkey.pem",
7840		}
7841
7842		java_sdk_library {
7843			name: "foo",
7844			srcs: ["a.java"],
7845			api_packages: ["foo"],
7846			apex_available: ["myapex"],
7847			sdk_version: "none",
7848			system_modules: "none",
7849			compile_dex: true,
7850		}
7851
7852		java_library {
7853			name: "bar",
7854			srcs: ["a.java"],
7855			libs: ["foo.impl"],
7856			apex_available: ["myapex"],
7857			sdk_version: "none",
7858			system_modules: "none",
7859			compile_dex: true,
7860		}
7861
7862		prebuilt_apis {
7863			name: "sdk",
7864			api_dirs: ["100"],
7865		}
7866	`, withFiles(filesForSdkLibrary))
7867
7868	// java_sdk_library installs both impl jar and permission XML
7869	ensureExactContents(t, ctx, "myapex", "android_common_myapex", []string{
7870		"javalib/bar.jar",
7871		"javalib/foo.jar",
7872		"etc/permissions/foo.xml",
7873	})
7874
7875	// The bar library should depend on the implementation jar.
7876	barLibrary := ctx.ModuleForTests(t, "bar", "android_common_apex10000").Rule("javac")
7877	if expected, actual := `^-classpath [^:]*/turbine/foo\.jar$`, barLibrary.Args["classpath"]; !regexp.MustCompile(expected).MatchString(actual) {
7878		t.Errorf("expected %q, found %#q", expected, actual)
7879	}
7880}
7881
7882func TestJavaSDKLibrary_CrossBoundary(t *testing.T) {
7883	t.Parallel()
7884	ctx := testApex(t, `
7885		apex {
7886			name: "myapex",
7887			key: "myapex.key",
7888			java_libs: ["foo"],
7889			updatable: false,
7890		}
7891
7892		apex_key {
7893			name: "myapex.key",
7894			public_key: "testkey.avbpubkey",
7895			private_key: "testkey.pem",
7896		}
7897
7898		java_sdk_library {
7899			name: "foo",
7900			srcs: ["a.java"],
7901			api_packages: ["foo"],
7902			apex_available: ["myapex"],
7903			sdk_version: "none",
7904			system_modules: "none",
7905		}
7906
7907		java_library {
7908			name: "bar",
7909			srcs: ["a.java"],
7910			libs: ["foo.stubs"],
7911			sdk_version: "none",
7912			system_modules: "none",
7913		}
7914
7915		prebuilt_apis {
7916			name: "sdk",
7917			api_dirs: ["100"],
7918		}
7919	`, withFiles(filesForSdkLibrary))
7920
7921	// java_sdk_library installs both impl jar and permission XML
7922	ensureExactContents(t, ctx, "myapex", "android_common_myapex", []string{
7923		"javalib/foo.jar",
7924		"etc/permissions/foo.xml",
7925	})
7926
7927	// The bar library should depend on the stubs jar.
7928	barLibrary := ctx.ModuleForTests(t, "bar", "android_common").Rule("javac")
7929	if expected, actual := `^-classpath [^:]*/foo\.stubs\.from-text/foo\.stubs\.from-text\.jar$`, barLibrary.Args["classpath"]; !regexp.MustCompile(expected).MatchString(actual) {
7930		t.Errorf("expected %q, found %#q", expected, actual)
7931	}
7932}
7933
7934func TestJavaSDKLibrary_ImportPreferred(t *testing.T) {
7935	t.Parallel()
7936	ctx := testApex(t, `
7937		prebuilt_apis {
7938			name: "sdk",
7939			api_dirs: ["100"],
7940		}`,
7941		withFiles(map[string][]byte{
7942			"apex/a.java":             nil,
7943			"apex/apex_manifest.json": nil,
7944			"apex/Android.bp": []byte(`
7945		package {
7946			default_visibility: ["//visibility:private"],
7947		}
7948
7949		apex {
7950			name: "myapex",
7951			key: "myapex.key",
7952			java_libs: ["foo", "bar"],
7953			updatable: false,
7954		}
7955
7956		apex_key {
7957			name: "myapex.key",
7958			public_key: "testkey.avbpubkey",
7959			private_key: "testkey.pem",
7960		}
7961
7962		java_library {
7963			name: "bar",
7964			srcs: ["a.java"],
7965			libs: ["foo.impl"],
7966			apex_available: ["myapex"],
7967			sdk_version: "none",
7968			system_modules: "none",
7969			compile_dex: true,
7970		}
7971`),
7972			"source/a.java":          nil,
7973			"source/api/current.txt": nil,
7974			"source/api/removed.txt": nil,
7975			"source/Android.bp": []byte(`
7976		package {
7977			default_visibility: ["//visibility:private"],
7978		}
7979
7980		java_sdk_library {
7981			name: "foo",
7982			visibility: ["//apex"],
7983			srcs: ["a.java"],
7984			api_packages: ["foo"],
7985			apex_available: ["myapex"],
7986			sdk_version: "none",
7987			system_modules: "none",
7988			public: {
7989				enabled: true,
7990			},
7991			compile_dex: true,
7992		}
7993`),
7994			"prebuilt/a.jar": nil,
7995			"prebuilt/Android.bp": []byte(`
7996		package {
7997			default_visibility: ["//visibility:private"],
7998		}
7999
8000		java_sdk_library_import {
8001			name: "foo",
8002			visibility: ["//apex", "//source"],
8003			apex_available: ["myapex"],
8004			prefer: true,
8005			public: {
8006				jars: ["a.jar"],
8007			},
8008			compile_dex: true,
8009		}
8010`),
8011		}), withFiles(filesForSdkLibrary),
8012	)
8013
8014	// java_sdk_library installs both impl jar and permission XML
8015	ensureExactContents(t, ctx, "myapex", "android_common_myapex", []string{
8016		"javalib/bar.jar",
8017		"javalib/foo.jar",
8018		"etc/permissions/foo.xml",
8019	})
8020
8021	// The bar library should depend on the implementation jar.
8022	barLibrary := ctx.ModuleForTests(t, "bar", "android_common_apex10000").Rule("javac")
8023	if expected, actual := `^-classpath [^:]*/turbine/foo\.jar$`, barLibrary.Args["classpath"]; !regexp.MustCompile(expected).MatchString(actual) {
8024		t.Errorf("expected %q, found %#q", expected, actual)
8025	}
8026}
8027
8028func TestJavaSDKLibrary_ImportOnly(t *testing.T) {
8029	t.Parallel()
8030	testApexError(t, `java_libs: "foo" is not configured to be compiled into dex`, `
8031		apex {
8032			name: "myapex",
8033			key: "myapex.key",
8034			java_libs: ["foo"],
8035			updatable: false,
8036		}
8037
8038		apex_key {
8039			name: "myapex.key",
8040			public_key: "testkey.avbpubkey",
8041			private_key: "testkey.pem",
8042		}
8043
8044		java_sdk_library_import {
8045			name: "foo",
8046			apex_available: ["myapex"],
8047			prefer: true,
8048			public: {
8049				jars: ["a.jar"],
8050			},
8051		}
8052
8053	`, withFiles(filesForSdkLibrary))
8054}
8055
8056func TestCompatConfig(t *testing.T) {
8057	t.Parallel()
8058	result := android.GroupFixturePreparers(
8059		prepareForApexTest,
8060		java.PrepareForTestWithPlatformCompatConfig,
8061	).RunTestWithBp(t, `
8062		apex {
8063			name: "myapex",
8064			key: "myapex.key",
8065			compat_configs: ["myjar-platform-compat-config"],
8066			java_libs: ["myjar"],
8067			updatable: false,
8068		}
8069
8070		apex_key {
8071			name: "myapex.key",
8072			public_key: "testkey.avbpubkey",
8073			private_key: "testkey.pem",
8074		}
8075
8076		platform_compat_config {
8077		    name: "myjar-platform-compat-config",
8078		    src: ":myjar",
8079		}
8080
8081		java_library {
8082			name: "myjar",
8083			srcs: ["foo/bar/MyClass.java"],
8084			sdk_version: "none",
8085			system_modules: "none",
8086			apex_available: [ "myapex" ],
8087			compile_dex: true,
8088		}
8089
8090		// Make sure that a preferred prebuilt does not affect the apex contents.
8091		prebuilt_platform_compat_config {
8092			name: "myjar-platform-compat-config",
8093			metadata: "compat-config/metadata.xml",
8094			prefer: true,
8095		}
8096	`)
8097	ctx := result.TestContext
8098	ensureExactContents(t, ctx, "myapex", "android_common_myapex", []string{
8099		"etc/compatconfig/myjar-platform-compat-config.xml",
8100		"javalib/myjar.jar",
8101	})
8102}
8103
8104func TestNoDupeApexFiles(t *testing.T) {
8105	t.Parallel()
8106	android.GroupFixturePreparers(
8107		android.PrepareForTestWithAndroidBuildComponents,
8108		PrepareForTestWithApexBuildComponents,
8109		prepareForTestWithMyapex,
8110		prebuilt_etc.PrepareForTestWithPrebuiltEtc,
8111	).
8112		ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern("is provided by two different files")).
8113		RunTestWithBp(t, `
8114			apex {
8115				name: "myapex",
8116				key: "myapex.key",
8117				prebuilts: ["foo", "bar"],
8118				updatable: false,
8119			}
8120
8121			apex_key {
8122				name: "myapex.key",
8123				public_key: "testkey.avbpubkey",
8124				private_key: "testkey.pem",
8125			}
8126
8127			prebuilt_etc {
8128				name: "foo",
8129				src: "myprebuilt",
8130				filename_from_src: true,
8131			}
8132
8133			prebuilt_etc {
8134				name: "bar",
8135				src: "myprebuilt",
8136				filename_from_src: true,
8137			}
8138		`)
8139}
8140
8141func TestApexUnwantedTransitiveDeps(t *testing.T) {
8142	t.Parallel()
8143	bp := `
8144	apex {
8145		name: "myapex",
8146		key: "myapex.key",
8147		native_shared_libs: ["libfoo"],
8148		updatable: false,
8149		unwanted_transitive_deps: ["libbar"],
8150	}
8151
8152	apex_key {
8153		name: "myapex.key",
8154		public_key: "testkey.avbpubkey",
8155		private_key: "testkey.pem",
8156	}
8157
8158	cc_library {
8159		name: "libfoo",
8160		srcs: ["foo.cpp"],
8161		shared_libs: ["libbar"],
8162		apex_available: ["myapex"],
8163	}
8164
8165	cc_library {
8166		name: "libbar",
8167		srcs: ["bar.cpp"],
8168		apex_available: ["myapex"],
8169	}`
8170	ctx := testApex(t, bp)
8171	ensureExactContents(t, ctx, "myapex", "android_common_myapex", []string{
8172		"*/libc++.so",
8173		"*/libfoo.so",
8174		// not libbar.so
8175	})
8176}
8177
8178func TestRejectNonInstallableJavaLibrary(t *testing.T) {
8179	t.Parallel()
8180	testApexError(t, `"myjar" is not configured to be compiled into dex`, `
8181		apex {
8182			name: "myapex",
8183			key: "myapex.key",
8184			java_libs: ["myjar"],
8185			updatable: false,
8186		}
8187
8188		apex_key {
8189			name: "myapex.key",
8190			public_key: "testkey.avbpubkey",
8191			private_key: "testkey.pem",
8192		}
8193
8194		java_library {
8195			name: "myjar",
8196			srcs: ["foo/bar/MyClass.java"],
8197			sdk_version: "none",
8198			system_modules: "none",
8199			compile_dex: false,
8200			apex_available: ["myapex"],
8201		}
8202	`)
8203}
8204
8205func TestSymlinksFromApexToSystem(t *testing.T) {
8206	t.Parallel()
8207	bp := `
8208		apex {
8209			name: "myapex",
8210			key: "myapex.key",
8211			native_shared_libs: ["mylib"],
8212			java_libs: ["myjar"],
8213			updatable: false,
8214		}
8215
8216		apex {
8217			name: "myapex.updatable",
8218			key: "myapex.key",
8219			native_shared_libs: ["mylib"],
8220			java_libs: ["myjar"],
8221			updatable: true,
8222			min_sdk_version: "33",
8223		}
8224
8225		apex_key {
8226			name: "myapex.key",
8227			public_key: "testkey.avbpubkey",
8228			private_key: "testkey.pem",
8229		}
8230
8231		cc_library {
8232			name: "mylib",
8233			srcs: ["mylib.cpp"],
8234			shared_libs: [
8235				"myotherlib",
8236				"myotherlib_ext",
8237			],
8238			system_shared_libs: [],
8239			stl: "none",
8240			apex_available: [
8241				"myapex",
8242				"myapex.updatable",
8243				"//apex_available:platform",
8244			],
8245			min_sdk_version: "33",
8246		}
8247
8248		cc_library {
8249			name: "myotherlib",
8250			srcs: ["mylib.cpp"],
8251			system_shared_libs: [],
8252			stl: "none",
8253			apex_available: [
8254				"myapex",
8255				"myapex.updatable",
8256				"//apex_available:platform",
8257			],
8258			min_sdk_version: "33",
8259		}
8260
8261		cc_library {
8262			name: "myotherlib_ext",
8263			srcs: ["mylib.cpp"],
8264			system_shared_libs: [],
8265			system_ext_specific: true,
8266			stl: "none",
8267			apex_available: [
8268				"myapex",
8269				"myapex.updatable",
8270				"//apex_available:platform",
8271			],
8272			min_sdk_version: "33",
8273		}
8274
8275		java_library {
8276			name: "myjar",
8277			srcs: ["foo/bar/MyClass.java"],
8278			sdk_version: "none",
8279			system_modules: "none",
8280			static_libs: ["myotherjar"],
8281			apex_available: [
8282				"myapex",
8283				"myapex.updatable",
8284				"//apex_available:platform",
8285			],
8286			min_sdk_version: "33",
8287			compile_dex: true,
8288		}
8289
8290		java_library {
8291			name: "myotherjar",
8292			srcs: ["foo/bar/MyClass.java"],
8293			sdk_version: "none",
8294			system_modules: "none",
8295			apex_available: [
8296				"myapex",
8297				"myapex.updatable",
8298				"//apex_available:platform",
8299			],
8300			min_sdk_version: "33",
8301		}
8302	`
8303
8304	ensureRealfileExists := func(t *testing.T, files []fileInApex, file string) {
8305		for _, f := range files {
8306			if f.path == file {
8307				if f.isLink {
8308					t.Errorf("%q is not a real file", file)
8309				}
8310				return
8311			}
8312		}
8313		t.Errorf("%q is not found", file)
8314	}
8315
8316	ensureSymlinkExists := func(t *testing.T, files []fileInApex, file string, target string) {
8317		for _, f := range files {
8318			if f.path == file {
8319				if !f.isLink {
8320					t.Errorf("%q is not a symlink", file)
8321				}
8322				if f.src != target {
8323					t.Errorf("expected symlink target to be %q, got %q", target, f.src)
8324				}
8325				return
8326			}
8327		}
8328		t.Errorf("%q is not found", file)
8329	}
8330
8331	// For unbundled build, symlink shouldn't exist regardless of whether an APEX
8332	// is updatable or not
8333	ctx := testApex(t, bp, withUnbundledBuild)
8334	files := getFiles(t, ctx, "myapex", "android_common_myapex")
8335	ensureRealfileExists(t, files, "javalib/myjar.jar")
8336	ensureRealfileExists(t, files, "lib64/mylib.so")
8337	ensureRealfileExists(t, files, "lib64/myotherlib.so")
8338	ensureRealfileExists(t, files, "lib64/myotherlib_ext.so")
8339
8340	files = getFiles(t, ctx, "myapex.updatable", "android_common_myapex.updatable")
8341	ensureRealfileExists(t, files, "javalib/myjar.jar")
8342	ensureRealfileExists(t, files, "lib64/mylib.so")
8343	ensureRealfileExists(t, files, "lib64/myotherlib.so")
8344	ensureRealfileExists(t, files, "lib64/myotherlib_ext.so")
8345
8346	// For bundled build, symlink to the system for the non-updatable APEXes only
8347	ctx = testApex(t, bp)
8348	files = getFiles(t, ctx, "myapex", "android_common_myapex")
8349	ensureRealfileExists(t, files, "javalib/myjar.jar")
8350	ensureRealfileExists(t, files, "lib64/mylib.so")
8351	ensureSymlinkExists(t, files, "lib64/myotherlib.so", "/system/lib64/myotherlib.so")             // this is symlink
8352	ensureSymlinkExists(t, files, "lib64/myotherlib_ext.so", "/system_ext/lib64/myotherlib_ext.so") // this is symlink
8353
8354	files = getFiles(t, ctx, "myapex.updatable", "android_common_myapex.updatable")
8355	ensureRealfileExists(t, files, "javalib/myjar.jar")
8356	ensureRealfileExists(t, files, "lib64/mylib.so")
8357	ensureRealfileExists(t, files, "lib64/myotherlib.so")     // this is a real file
8358	ensureRealfileExists(t, files, "lib64/myotherlib_ext.so") // this is a real file
8359}
8360
8361func TestSymlinksFromApexToSystemRequiredModuleNames(t *testing.T) {
8362	t.Parallel()
8363	ctx := testApex(t, `
8364		apex {
8365			name: "myapex",
8366			key: "myapex.key",
8367			native_shared_libs: ["mylib"],
8368			updatable: false,
8369		}
8370
8371		apex_key {
8372			name: "myapex.key",
8373			public_key: "testkey.avbpubkey",
8374			private_key: "testkey.pem",
8375		}
8376
8377		cc_library_shared {
8378			name: "mylib",
8379			srcs: ["mylib.cpp"],
8380			shared_libs: ["myotherlib"],
8381			system_shared_libs: [],
8382			stl: "none",
8383			apex_available: [
8384				"myapex",
8385				"//apex_available:platform",
8386			],
8387		}
8388
8389		cc_prebuilt_library_shared {
8390			name: "myotherlib",
8391			srcs: ["prebuilt.so"],
8392			system_shared_libs: [],
8393			stl: "none",
8394			apex_available: [
8395				"myapex",
8396				"//apex_available:platform",
8397			],
8398		}
8399	`)
8400
8401	apexBundle := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Module().(*apexBundle)
8402	data := android.AndroidMkDataForTest(t, ctx, apexBundle)
8403	var builder strings.Builder
8404	data.Custom(&builder, apexBundle.BaseModuleName(), "TARGET_", "", data)
8405	androidMk := builder.String()
8406	// `myotherlib` is added to `myapex` as symlink
8407	ensureContains(t, androidMk, "LOCAL_MODULE := mylib.myapex\n")
8408	ensureNotContains(t, androidMk, "LOCAL_MODULE := prebuilt_myotherlib.myapex\n")
8409	ensureNotContains(t, androidMk, "LOCAL_MODULE := myotherlib.myapex\n")
8410	// `myapex` should have `myotherlib` in its required line, not `prebuilt_myotherlib`
8411	ensureContains(t, androidMk, "LOCAL_REQUIRED_MODULES := mylib.myapex:64 myotherlib:64\n")
8412}
8413
8414func TestApexWithJniLibs(t *testing.T) {
8415	t.Parallel()
8416	ctx := testApex(t, `
8417		apex {
8418			name: "myapex",
8419			key: "myapex.key",
8420			binaries: ["mybin"],
8421			jni_libs: ["mylib", "mylib3", "libfoo.rust"],
8422			updatable: false,
8423		}
8424
8425		apex_key {
8426			name: "myapex.key",
8427			public_key: "testkey.avbpubkey",
8428			private_key: "testkey.pem",
8429		}
8430
8431		cc_library {
8432			name: "mylib",
8433			srcs: ["mylib.cpp"],
8434			shared_libs: ["mylib2"],
8435			system_shared_libs: [],
8436			stl: "none",
8437			apex_available: [ "myapex" ],
8438		}
8439
8440		cc_library {
8441			name: "mylib2",
8442			srcs: ["mylib.cpp"],
8443			system_shared_libs: [],
8444			stl: "none",
8445			apex_available: [ "myapex" ],
8446		}
8447
8448		// Used as both a JNI library and a regular shared library.
8449		cc_library {
8450			name: "mylib3",
8451			srcs: ["mylib.cpp"],
8452			system_shared_libs: [],
8453			stl: "none",
8454			apex_available: [ "myapex" ],
8455		}
8456
8457		cc_binary {
8458			name: "mybin",
8459			srcs: ["mybin.cpp"],
8460			shared_libs: ["mylib3"],
8461			system_shared_libs: [],
8462			stl: "none",
8463			apex_available: [ "myapex" ],
8464		}
8465
8466		rust_ffi_shared {
8467			name: "libfoo.rust",
8468			crate_name: "foo",
8469			srcs: ["foo.rs"],
8470			shared_libs: ["libfoo.shared_from_rust"],
8471			prefer_rlib: true,
8472			apex_available: ["myapex"],
8473		}
8474
8475		cc_library_shared {
8476			name: "libfoo.shared_from_rust",
8477			srcs: ["mylib.cpp"],
8478			system_shared_libs: [],
8479			stl: "none",
8480			stubs: {
8481				versions: ["10", "11", "12"],
8482			},
8483		}
8484
8485	`)
8486
8487	rule := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Rule("apexManifestRule")
8488	// Notice mylib2.so (transitive dep) is not added as a jni_lib
8489	ensureEquals(t, rule.Args["opt"], "-a jniLibs libfoo.rust.so mylib.so mylib3.so")
8490	ensureExactContents(t, ctx, "myapex", "android_common_myapex", []string{
8491		"bin/mybin",
8492		"lib64/mylib.so",
8493		"lib64/mylib2.so",
8494		"lib64/mylib3.so",
8495		"lib64/libfoo.rust.so",
8496	})
8497
8498	// b/220397949
8499	ensureListContains(t, names(rule.Args["requireNativeLibs"]), "libfoo.shared_from_rust.so")
8500}
8501
8502func TestAppBundle(t *testing.T) {
8503	t.Parallel()
8504	ctx := testApex(t, `
8505		apex {
8506			name: "myapex",
8507			key: "myapex.key",
8508			apps: ["AppFoo"],
8509			updatable: false,
8510		}
8511
8512		apex_key {
8513			name: "myapex.key",
8514			public_key: "testkey.avbpubkey",
8515			private_key: "testkey.pem",
8516		}
8517
8518		android_app {
8519			name: "AppFoo",
8520			srcs: ["foo/bar/MyClass.java"],
8521			sdk_version: "none",
8522			system_modules: "none",
8523			apex_available: [ "myapex" ],
8524		}
8525		`, withManifestPackageNameOverrides([]string{"AppFoo:com.android.foo"}))
8526
8527	bundleConfigRule := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Output("bundle_config.json")
8528	content := android.ContentFromFileRuleForTests(t, ctx, bundleConfigRule)
8529
8530	ensureContains(t, content, `"compression":{"uncompressed_glob":["apex_payload.img","apex_manifest.*"]}`)
8531	ensureContains(t, content, `"apex_config":{"apex_embedded_apk_config":[{"package_name":"com.android.foo","path":"app/AppFoo@TEST.BUILD_ID/AppFoo.apk"}]}`)
8532}
8533
8534func TestAppSetBundle(t *testing.T) {
8535	t.Parallel()
8536	ctx := testApex(t, `
8537		apex {
8538			name: "myapex",
8539			key: "myapex.key",
8540			apps: ["AppSet"],
8541			updatable: false,
8542		}
8543
8544		apex_key {
8545			name: "myapex.key",
8546			public_key: "testkey.avbpubkey",
8547			private_key: "testkey.pem",
8548		}
8549
8550		android_app_set {
8551			name: "AppSet",
8552			set: "AppSet.apks",
8553		}`)
8554	mod := ctx.ModuleForTests(t, "myapex", "android_common_myapex")
8555	bundleConfigRule := mod.Output("bundle_config.json")
8556	content := android.ContentFromFileRuleForTests(t, ctx, bundleConfigRule)
8557	ensureContains(t, content, `"compression":{"uncompressed_glob":["apex_payload.img","apex_manifest.*"]}`)
8558	s := mod.Rule("apexRule").Args["copy_commands"]
8559	copyCmds := regexp.MustCompile(" *&& *").Split(s, -1)
8560	if len(copyCmds) != 4 {
8561		t.Fatalf("Expected 4 commands, got %d in:\n%s", len(copyCmds), s)
8562	}
8563	ensureMatches(t, copyCmds[0], "^rm -rf .*/app/AppSet@TEST.BUILD_ID$")
8564	ensureMatches(t, copyCmds[1], "^mkdir -p .*/app/AppSet@TEST.BUILD_ID$")
8565	ensureMatches(t, copyCmds[2], "^cp -f .*/app/AppSet@TEST.BUILD_ID/AppSet.apk$")
8566	ensureMatches(t, copyCmds[3], "^unzip .*-d .*/app/AppSet@TEST.BUILD_ID .*/AppSet.zip$")
8567
8568	// Ensure that canned_fs_config has an entry for the app set zip file
8569	generateFsRule := mod.Rule("generateFsConfig")
8570	cmd := generateFsRule.RuleParams.Command
8571	ensureContains(t, cmd, "AppSet.zip")
8572}
8573
8574func TestAppSetBundlePrebuilt(t *testing.T) {
8575	bp := `
8576		apex_set {
8577			name: "myapex",
8578			filename: "foo_v2.apex",
8579			sanitized: {
8580				none: { set: "myapex.apks", },
8581				hwaddress: { set: "myapex.hwasan.apks", },
8582			},
8583		}
8584	`
8585	ctx := testApex(t, bp, prepareForTestWithSantitizeHwaddress)
8586
8587	// Check that the extractor produces the correct output file from the correct input file.
8588	extractorOutput := "out/soong/.intermediates/myapex/android_common_prebuilt_myapex/extracted/myapex.hwasan.apks"
8589
8590	m := ctx.ModuleForTests(t, "myapex", "android_common_prebuilt_myapex")
8591	extractedApex := m.Output(extractorOutput)
8592
8593	android.AssertArrayString(t, "extractor input", []string{"myapex.hwasan.apks"}, extractedApex.Inputs.Strings())
8594
8595	// Ditto for the apex.
8596	m = ctx.ModuleForTests(t, "myapex", "android_common_prebuilt_myapex")
8597	copiedApex := m.Output("out/soong/.intermediates/myapex/android_common_prebuilt_myapex/foo_v2.apex")
8598
8599	android.AssertStringEquals(t, "myapex input", extractorOutput, copiedApex.Input.String())
8600}
8601
8602func TestApexSetApksModuleAssignment(t *testing.T) {
8603	t.Parallel()
8604	ctx := testApex(t, `
8605		apex_set {
8606			name: "myapex",
8607			set: ":myapex_apks_file",
8608		}
8609
8610		filegroup {
8611			name: "myapex_apks_file",
8612			srcs: ["myapex.apks"],
8613		}
8614	`)
8615
8616	m := ctx.ModuleForTests(t, "myapex", "android_common_prebuilt_myapex")
8617
8618	// Check that the extractor produces the correct apks file from the input module
8619	extractorOutput := "out/soong/.intermediates/myapex/android_common_prebuilt_myapex/extracted/myapex.apks"
8620	extractedApex := m.Output(extractorOutput)
8621
8622	android.AssertArrayString(t, "extractor input", []string{"myapex.apks"}, extractedApex.Inputs.Strings())
8623}
8624
8625func testDexpreoptWithApexes(t *testing.T, bp, errmsg string, preparer android.FixturePreparer, fragments ...java.ApexVariantReference) *android.TestContext {
8626	t.Helper()
8627
8628	fs := android.MockFS{
8629		"a.java":              nil,
8630		"a.jar":               nil,
8631		"apex_manifest.json":  nil,
8632		"AndroidManifest.xml": nil,
8633		"system/sepolicy/apex/myapex-file_contexts":                  nil,
8634		"system/sepolicy/apex/some-updatable-apex-file_contexts":     nil,
8635		"system/sepolicy/apex/some-non-updatable-apex-file_contexts": nil,
8636		"system/sepolicy/apex/com.android.art.debug-file_contexts":   nil,
8637		"framework/aidl/a.aidl":                                      nil,
8638	}
8639
8640	errorHandler := android.FixtureExpectsNoErrors
8641	if errmsg != "" {
8642		errorHandler = android.FixtureExpectsAtLeastOneErrorMatchingPattern(errmsg)
8643	}
8644
8645	result := android.GroupFixturePreparers(
8646		cc.PrepareForTestWithCcDefaultModules,
8647		java.PrepareForTestWithHiddenApiBuildComponents,
8648		java.PrepareForTestWithDexpreopt,
8649		java.PrepareForTestWithJavaSdkLibraryFiles,
8650		PrepareForTestWithApexBuildComponents,
8651		preparer,
8652		fs.AddToFixture(),
8653		android.FixtureModifyMockFS(func(fs android.MockFS) {
8654			if _, ok := fs["frameworks/base/boot/Android.bp"]; !ok {
8655				insert := ""
8656				for _, fragment := range fragments {
8657					insert += fmt.Sprintf("{apex: %q, module: %q},\n", *fragment.Apex, *fragment.Module)
8658				}
8659				fs["frameworks/base/boot/Android.bp"] = []byte(fmt.Sprintf(`
8660					platform_bootclasspath {
8661						name: "platform-bootclasspath",
8662						fragments: [
8663							{apex: "com.android.art", module: "art-bootclasspath-fragment"},
8664  						%s
8665						],
8666					}
8667				`, insert))
8668			}
8669		}),
8670		// Dexpreopt for boot jars requires the ART boot image profile.
8671		java.PrepareApexBootJarModule("com.android.art", "core-oj"),
8672		dexpreopt.FixtureSetArtBootJars("com.android.art:core-oj"),
8673		dexpreopt.FixtureSetBootImageProfiles("art/build/boot/boot-image-profile.txt"),
8674	).
8675		ExtendWithErrorHandler(errorHandler).
8676		RunTestWithBp(t, bp)
8677
8678	return result.TestContext
8679}
8680
8681func TestUpdatable_should_set_min_sdk_version(t *testing.T) {
8682	t.Parallel()
8683	testApexError(t, `"myapex" .*: updatable: updatable APEXes should set min_sdk_version`, `
8684		apex {
8685			name: "myapex",
8686			key: "myapex.key",
8687			updatable: true,
8688		}
8689
8690		apex_key {
8691			name: "myapex.key",
8692			public_key: "testkey.avbpubkey",
8693			private_key: "testkey.pem",
8694		}
8695	`)
8696}
8697
8698func TestUpdatableDefault_should_set_min_sdk_version(t *testing.T) {
8699	t.Parallel()
8700	testApexError(t, `"myapex" .*: updatable: updatable APEXes should set min_sdk_version`, `
8701		apex {
8702			name: "myapex",
8703			key: "myapex.key",
8704		}
8705
8706		apex_key {
8707			name: "myapex.key",
8708			public_key: "testkey.avbpubkey",
8709			private_key: "testkey.pem",
8710		}
8711	`)
8712}
8713
8714func TestUpdatable_should_not_set_generate_classpaths_proto(t *testing.T) {
8715	t.Parallel()
8716	testApexError(t, `"mysystemserverclasspathfragment" .* it must not set generate_classpaths_proto to false`, `
8717		apex {
8718			name: "myapex",
8719			key: "myapex.key",
8720			systemserverclasspath_fragments: [
8721				"mysystemserverclasspathfragment",
8722			],
8723			min_sdk_version: "29",
8724			updatable: true,
8725		}
8726
8727		apex_key {
8728			name: "myapex.key",
8729			public_key: "testkey.avbpubkey",
8730			private_key: "testkey.pem",
8731		}
8732
8733		java_library {
8734			name: "foo",
8735			srcs: ["b.java"],
8736			min_sdk_version: "29",
8737			installable: true,
8738			apex_available: [
8739				"myapex",
8740			],
8741			sdk_version: "current",
8742		}
8743
8744		systemserverclasspath_fragment {
8745			name: "mysystemserverclasspathfragment",
8746			generate_classpaths_proto: false,
8747			contents: [
8748				"foo",
8749			],
8750			apex_available: [
8751				"myapex",
8752			],
8753		}
8754	`,
8755		dexpreopt.FixtureSetApexSystemServerJars("myapex:foo"),
8756	)
8757}
8758
8759func TestDexpreoptAccessDexFilesFromPrebuiltApex(t *testing.T) {
8760	t.Parallel()
8761	preparer := java.FixtureConfigureApexBootJars("myapex:libfoo")
8762	t.Run("prebuilt no source", func(t *testing.T) {
8763		t.Parallel()
8764		fragment := java.ApexVariantReference{
8765			Apex:   proptools.StringPtr("myapex"),
8766			Module: proptools.StringPtr("my-bootclasspath-fragment"),
8767		}
8768
8769		testDexpreoptWithApexes(t, `
8770			prebuilt_apex {
8771				name: "myapex" ,
8772				arch: {
8773					arm64: {
8774						src: "myapex-arm64.apex",
8775					},
8776					arm: {
8777						src: "myapex-arm.apex",
8778					},
8779				},
8780				exported_bootclasspath_fragments: ["my-bootclasspath-fragment"],
8781			}
8782
8783			prebuilt_bootclasspath_fragment {
8784				name: "my-bootclasspath-fragment",
8785				contents: ["libfoo"],
8786				apex_available: ["myapex"],
8787				hidden_api: {
8788					annotation_flags: "my-bootclasspath-fragment/annotation-flags.csv",
8789					metadata: "my-bootclasspath-fragment/metadata.csv",
8790					index: "my-bootclasspath-fragment/index.csv",
8791					signature_patterns: "my-bootclasspath-fragment/signature-patterns.csv",
8792					filtered_stub_flags: "my-bootclasspath-fragment/filtered-stub-flags.csv",
8793					filtered_flags: "my-bootclasspath-fragment/filtered-flags.csv",
8794				},
8795			}
8796
8797		java_sdk_library_import {
8798			name: "libfoo",
8799			prefer: true,
8800			public: {
8801				jars: ["libfoo.jar"],
8802			},
8803			apex_available: ["myapex"],
8804			shared_library: false,
8805			permitted_packages: ["libfoo"],
8806		}
8807		`, "", preparer, fragment)
8808	})
8809}
8810
8811func testBootJarPermittedPackagesRules(t *testing.T, errmsg, bp string, bootJars []string, rules []android.Rule) {
8812	t.Helper()
8813	bp += `
8814	apex_key {
8815		name: "myapex.key",
8816		public_key: "testkey.avbpubkey",
8817		private_key: "testkey.pem",
8818	}`
8819	fs := android.MockFS{
8820		"lib1/src/A.java": nil,
8821		"lib2/src/B.java": nil,
8822		"system/sepolicy/apex/myapex-file_contexts": nil,
8823	}
8824
8825	errorHandler := android.FixtureExpectsNoErrors
8826	if errmsg != "" {
8827		errorHandler = android.FixtureExpectsAtLeastOneErrorMatchingPattern(errmsg)
8828	}
8829
8830	android.GroupFixturePreparers(
8831		android.PrepareForTestWithAndroidBuildComponents,
8832		java.PrepareForTestWithJavaBuildComponents,
8833		PrepareForTestWithApexBuildComponents,
8834		android.PrepareForTestWithNeverallowRules(rules),
8835		android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
8836			apexBootJars := make([]string, 0, len(bootJars))
8837			for _, apexBootJar := range bootJars {
8838				apexBootJars = append(apexBootJars, "myapex:"+apexBootJar)
8839			}
8840			variables.ApexBootJars = android.CreateTestConfiguredJarList(apexBootJars)
8841		}),
8842		fs.AddToFixture(),
8843	).
8844		ExtendWithErrorHandler(errorHandler).
8845		RunTestWithBp(t, bp)
8846}
8847
8848func TestApexPermittedPackagesRules(t *testing.T) {
8849	t.Parallel()
8850	testcases := []struct {
8851		name                 string
8852		expectedError        string
8853		bp                   string
8854		bootJars             []string
8855		bcpPermittedPackages map[string][]string
8856	}{
8857
8858		{
8859			name:          "Non-Bootclasspath apex jar not satisfying allowed module packages.",
8860			expectedError: "",
8861			bp: `
8862				java_library {
8863					name: "bcp_lib1",
8864					srcs: ["lib1/src/*.java"],
8865					permitted_packages: ["foo.bar"],
8866					apex_available: ["myapex"],
8867					sdk_version: "none",
8868					system_modules: "none",
8869					compile_dex: true,
8870				}
8871				java_library {
8872					name: "nonbcp_lib2",
8873					srcs: ["lib2/src/*.java"],
8874					apex_available: ["myapex"],
8875					permitted_packages: ["a.b"],
8876					sdk_version: "none",
8877					system_modules: "none",
8878					compile_dex: true,
8879				}
8880				apex {
8881					name: "myapex",
8882					key: "myapex.key",
8883					java_libs: ["bcp_lib1", "nonbcp_lib2"],
8884					updatable: false,
8885				}`,
8886			bootJars: []string{"bcp_lib1"},
8887			bcpPermittedPackages: map[string][]string{
8888				"bcp_lib1": []string{
8889					"foo.bar",
8890				},
8891			},
8892		},
8893		{
8894			name:          "Bootclasspath apex jar not satisfying allowed module packages.",
8895			expectedError: `(?s)module "bcp_lib2" .* which is restricted because bcp_lib2 bootjar may only use these package prefixes: foo.bar. Please consider the following alternatives:\n    1. If the offending code is from a statically linked library, consider removing that dependency and using an alternative already in the bootclasspath, or perhaps a shared library.    2. Move the offending code into an allowed package.\n    3. Jarjar the offending code. Please be mindful of the potential system health implications of bundling that code, particularly if the offending jar is part of the bootclasspath.`,
8896			bp: `
8897				java_library {
8898					name: "bcp_lib1",
8899					srcs: ["lib1/src/*.java"],
8900					apex_available: ["myapex"],
8901					permitted_packages: ["foo.bar"],
8902					sdk_version: "none",
8903					system_modules: "none",
8904					compile_dex: true,
8905				}
8906				java_library {
8907					name: "bcp_lib2",
8908					srcs: ["lib2/src/*.java"],
8909					apex_available: ["myapex"],
8910					permitted_packages: ["foo.bar", "bar.baz"],
8911					sdk_version: "none",
8912					system_modules: "none",
8913					compile_dex: true,
8914				}
8915				apex {
8916					name: "myapex",
8917					key: "myapex.key",
8918					java_libs: ["bcp_lib1", "bcp_lib2"],
8919					updatable: false,
8920				}
8921			`,
8922			bootJars: []string{"bcp_lib1", "bcp_lib2"},
8923			bcpPermittedPackages: map[string][]string{
8924				"bcp_lib1": []string{
8925					"foo.bar",
8926				},
8927				"bcp_lib2": []string{
8928					"foo.bar",
8929				},
8930			},
8931		},
8932		{
8933			name:          "Updateable Bootclasspath apex jar not satisfying allowed module packages.",
8934			expectedError: "",
8935			bp: `
8936				java_library {
8937					name: "bcp_lib_restricted",
8938					srcs: ["lib1/src/*.java"],
8939					apex_available: ["myapex"],
8940					permitted_packages: ["foo.bar"],
8941					sdk_version: "none",
8942					min_sdk_version: "29",
8943					system_modules: "none",
8944					compile_dex: true,
8945				}
8946				java_library {
8947					name: "bcp_lib_unrestricted",
8948					srcs: ["lib2/src/*.java"],
8949					apex_available: ["myapex"],
8950					permitted_packages: ["foo.bar", "bar.baz"],
8951					sdk_version: "none",
8952					min_sdk_version: "29",
8953					system_modules: "none",
8954					compile_dex: true,
8955				}
8956				apex {
8957					name: "myapex",
8958					key: "myapex.key",
8959					java_libs: ["bcp_lib_restricted", "bcp_lib_unrestricted"],
8960					updatable: true,
8961					min_sdk_version: "29",
8962				}
8963			`,
8964			bootJars: []string{"bcp_lib1", "bcp_lib2"},
8965			bcpPermittedPackages: map[string][]string{
8966				"bcp_lib1_non_updateable": []string{
8967					"foo.bar",
8968				},
8969				// bcp_lib2_updateable has no entry here since updateable bcp can contain new packages - tracking via an allowlist is not necessary
8970			},
8971		},
8972	}
8973	for _, tc := range testcases {
8974		t.Run(tc.name, func(t *testing.T) {
8975			t.Parallel()
8976			rules := createBcpPermittedPackagesRules(tc.bcpPermittedPackages)
8977			testBootJarPermittedPackagesRules(t, tc.expectedError, tc.bp, tc.bootJars, rules)
8978		})
8979	}
8980}
8981
8982// TODO(jungjw): Move this to proptools
8983func intPtr(i int) *int {
8984	return &i
8985}
8986
8987func TestApexSet(t *testing.T) {
8988	t.Parallel()
8989	ctx := testApex(t, `
8990		apex_set {
8991			name: "myapex",
8992			set: "myapex.apks",
8993			filename: "foo_v2.apex",
8994			overrides: ["foo"],
8995		}
8996	`,
8997		android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
8998			variables.Platform_sdk_version = intPtr(30)
8999		}),
9000		android.FixtureModifyConfig(func(config android.Config) {
9001			config.Targets[android.Android] = []android.Target{
9002				{Os: android.Android, Arch: android.Arch{ArchType: android.Arm, ArchVariant: "armv7-a-neon", Abi: []string{"armeabi-v7a"}}},
9003				{Os: android.Android, Arch: android.Arch{ArchType: android.Arm64, ArchVariant: "armv8-a", Abi: []string{"arm64-v8a"}}},
9004			}
9005		}),
9006	)
9007
9008	m := ctx.ModuleForTests(t, "myapex", "android_common_prebuilt_myapex")
9009
9010	// Check extract_apks tool parameters.
9011	extractedApex := m.Output("extracted/myapex.apks")
9012	actual := extractedApex.Args["abis"]
9013	expected := "ARMEABI_V7A,ARM64_V8A"
9014	if actual != expected {
9015		t.Errorf("Unexpected abis parameter - expected %q vs actual %q", expected, actual)
9016	}
9017	actual = extractedApex.Args["sdk-version"]
9018	expected = "30"
9019	if actual != expected {
9020		t.Errorf("Unexpected abis parameter - expected %q vs actual %q", expected, actual)
9021	}
9022
9023	m = ctx.ModuleForTests(t, "myapex", "android_common_prebuilt_myapex")
9024	a := m.Module().(*ApexSet)
9025	expectedOverrides := []string{"foo"}
9026	actualOverrides := android.AndroidMkEntriesForTest(t, ctx, a)[0].EntryMap["LOCAL_OVERRIDES_MODULES"]
9027	if !reflect.DeepEqual(actualOverrides, expectedOverrides) {
9028		t.Errorf("Incorrect LOCAL_OVERRIDES_MODULES - expected %q vs actual %q", expectedOverrides, actualOverrides)
9029	}
9030}
9031
9032func TestApexSet_NativeBridge(t *testing.T) {
9033	t.Parallel()
9034	ctx := testApex(t, `
9035		apex_set {
9036			name: "myapex",
9037			set: "myapex.apks",
9038			filename: "foo_v2.apex",
9039			overrides: ["foo"],
9040		}
9041	`,
9042		android.FixtureModifyConfig(func(config android.Config) {
9043			config.Targets[android.Android] = []android.Target{
9044				{Os: android.Android, Arch: android.Arch{ArchType: android.X86_64, ArchVariant: "", Abi: []string{"x86_64"}}},
9045				{Os: android.Android, Arch: android.Arch{ArchType: android.Arm64, ArchVariant: "armv8-a", Abi: []string{"arm64-v8a"}}, NativeBridge: android.NativeBridgeEnabled},
9046			}
9047		}),
9048	)
9049
9050	m := ctx.ModuleForTests(t, "myapex", "android_common_prebuilt_myapex")
9051
9052	// Check extract_apks tool parameters. No native bridge arch expected
9053	extractedApex := m.Output("extracted/myapex.apks")
9054	android.AssertStringEquals(t, "abis", "X86_64", extractedApex.Args["abis"])
9055}
9056
9057func TestNoStaticLinkingToStubsLib(t *testing.T) {
9058	t.Parallel()
9059	testApexError(t, `.*required by "mylib" is a native library providing stub.*`, `
9060		apex {
9061			name: "myapex",
9062			key: "myapex.key",
9063			native_shared_libs: ["mylib"],
9064			updatable: false,
9065		}
9066
9067		apex_key {
9068			name: "myapex.key",
9069			public_key: "testkey.avbpubkey",
9070			private_key: "testkey.pem",
9071		}
9072
9073		cc_library {
9074			name: "mylib",
9075			srcs: ["mylib.cpp"],
9076			static_libs: ["otherlib"],
9077			system_shared_libs: [],
9078			stl: "none",
9079			apex_available: [ "myapex" ],
9080		}
9081
9082		cc_library {
9083			name: "otherlib",
9084			srcs: ["mylib.cpp"],
9085			system_shared_libs: [],
9086			stl: "none",
9087			stubs: {
9088				versions: ["1", "2", "3"],
9089			},
9090			apex_available: [ "myapex" ],
9091		}
9092	`)
9093}
9094
9095func TestApexKeysTxt(t *testing.T) {
9096	t.Parallel()
9097	ctx := testApex(t, `
9098		apex {
9099			name: "myapex",
9100			key: "myapex.key",
9101			updatable: false,
9102			custom_sign_tool: "sign_myapex",
9103		}
9104
9105		apex_key {
9106			name: "myapex.key",
9107			public_key: "testkey.avbpubkey",
9108			private_key: "testkey.pem",
9109		}
9110	`)
9111
9112	myapex := ctx.ModuleForTests(t, "myapex", "android_common_myapex")
9113	content := android.ContentFromFileRuleForTests(t, ctx, myapex.Output("apexkeys.txt"))
9114	ensureContains(t, content, `name="myapex.apex" public_key="vendor/foo/devkeys/testkey.avbpubkey" private_key="vendor/foo/devkeys/testkey.pem" container_certificate="vendor/foo/devkeys/test.x509.pem" container_private_key="vendor/foo/devkeys/test.pk8" partition="system" sign_tool="sign_myapex"`)
9115}
9116
9117func TestApexKeysTxtOverrides(t *testing.T) {
9118	t.Parallel()
9119	ctx := testApex(t, `
9120		apex {
9121			name: "myapex",
9122			key: "myapex.key",
9123			updatable: false,
9124			custom_sign_tool: "sign_myapex",
9125		}
9126
9127		apex_key {
9128			name: "myapex.key",
9129			public_key: "testkey.avbpubkey",
9130			private_key: "testkey.pem",
9131		}
9132
9133		prebuilt_apex {
9134			name: "myapex",
9135			prefer: true,
9136			arch: {
9137				arm64: {
9138					src: "myapex-arm64.apex",
9139				},
9140				arm: {
9141					src: "myapex-arm.apex",
9142				},
9143			},
9144		}
9145
9146		apex_set {
9147			name: "myapex_set",
9148			set: "myapex.apks",
9149			filename: "myapex_set.apex",
9150			overrides: ["myapex"],
9151		}
9152	`)
9153
9154	content := android.ContentFromFileRuleForTests(t, ctx,
9155		ctx.ModuleForTests(t, "myapex", "android_common_myapex").Output("apexkeys.txt"))
9156	ensureContains(t, content, `name="myapex.apex" public_key="vendor/foo/devkeys/testkey.avbpubkey" private_key="vendor/foo/devkeys/testkey.pem" container_certificate="vendor/foo/devkeys/test.x509.pem" container_private_key="vendor/foo/devkeys/test.pk8" partition="system" sign_tool="sign_myapex"`)
9157	content = android.ContentFromFileRuleForTests(t, ctx,
9158		ctx.ModuleForTests(t, "myapex_set", "android_common_prebuilt_myapex_set").Output("apexkeys.txt"))
9159	ensureContains(t, content, `name="myapex_set.apex" public_key="PRESIGNED" private_key="PRESIGNED" container_certificate="PRESIGNED" container_private_key="PRESIGNED" partition="system"`)
9160}
9161
9162func TestAllowedFiles(t *testing.T) {
9163	t.Parallel()
9164	ctx := testApex(t, `
9165		apex {
9166			name: "myapex",
9167			key: "myapex.key",
9168			apps: ["app"],
9169			allowed_files: "allowed.txt",
9170			updatable: false,
9171		}
9172
9173		apex_key {
9174			name: "myapex.key",
9175			public_key: "testkey.avbpubkey",
9176			private_key: "testkey.pem",
9177		}
9178
9179		android_app {
9180			name: "app",
9181			srcs: ["foo/bar/MyClass.java"],
9182			package_name: "foo",
9183			sdk_version: "none",
9184			system_modules: "none",
9185			apex_available: [ "myapex" ],
9186		}
9187	`, withFiles(map[string][]byte{
9188		"sub/Android.bp": []byte(`
9189			override_apex {
9190				name: "override_myapex",
9191				base: "myapex",
9192				apps: ["override_app"],
9193				allowed_files: ":allowed",
9194			}
9195			// Overridable "path" property should be referenced indirectly
9196			filegroup {
9197				name: "allowed",
9198				srcs: ["allowed.txt"],
9199			}
9200			override_android_app {
9201				name: "override_app",
9202				base: "app",
9203				package_name: "bar",
9204			}
9205			`),
9206	}))
9207
9208	rule := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Rule("diffApexContentRule")
9209	if expected, actual := "allowed.txt", rule.Args["allowed_files_file"]; expected != actual {
9210		t.Errorf("allowed_files_file: expected %q but got %q", expected, actual)
9211	}
9212
9213	rule2 := ctx.ModuleForTests(t, "myapex", "android_common_override_myapex_override_myapex").Rule("diffApexContentRule")
9214	if expected, actual := "sub/allowed.txt", rule2.Args["allowed_files_file"]; expected != actual {
9215		t.Errorf("allowed_files_file: expected %q but got %q", expected, actual)
9216	}
9217}
9218
9219func TestNonPreferredPrebuiltDependency(t *testing.T) {
9220	t.Parallel()
9221	testApex(t, `
9222		apex {
9223			name: "myapex",
9224			key: "myapex.key",
9225			native_shared_libs: ["mylib"],
9226			updatable: false,
9227		}
9228
9229		apex_key {
9230			name: "myapex.key",
9231			public_key: "testkey.avbpubkey",
9232			private_key: "testkey.pem",
9233		}
9234
9235		cc_library {
9236			name: "mylib",
9237			srcs: ["mylib.cpp"],
9238			stubs: {
9239				versions: ["current"],
9240			},
9241			apex_available: ["myapex"],
9242		}
9243
9244		cc_prebuilt_library_shared {
9245			name: "mylib",
9246			prefer: false,
9247			srcs: ["prebuilt.so"],
9248			stubs: {
9249				versions: ["current"],
9250			},
9251			apex_available: ["myapex"],
9252		}
9253	`)
9254}
9255
9256func TestCompressedApex(t *testing.T) {
9257	t.Parallel()
9258	ctx := testApex(t, `
9259		apex {
9260			name: "myapex",
9261			key: "myapex.key",
9262			compressible: true,
9263			updatable: false,
9264		}
9265		apex_key {
9266			name: "myapex.key",
9267			public_key: "testkey.avbpubkey",
9268			private_key: "testkey.pem",
9269		}
9270	`,
9271		android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
9272			variables.CompressedApex = proptools.BoolPtr(true)
9273		}),
9274	)
9275
9276	compressRule := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Rule("compressRule")
9277	ensureContains(t, compressRule.Output.String(), "myapex.capex.unsigned")
9278
9279	signApkRule := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Description("sign compressedApex")
9280	ensureEquals(t, signApkRule.Input.String(), compressRule.Output.String())
9281
9282	// Make sure output of bundle is .capex
9283	ab := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Module().(*apexBundle)
9284	ensureContains(t, ab.outputFile.String(), "myapex.capex")
9285
9286	// Verify android.mk rules
9287	data := android.AndroidMkDataForTest(t, ctx, ab)
9288	var builder strings.Builder
9289	data.Custom(&builder, ab.BaseModuleName(), "TARGET_", "", data)
9290	androidMk := builder.String()
9291	ensureContains(t, androidMk, "LOCAL_MODULE_STEM := myapex.capex\n")
9292}
9293
9294func TestCompressedApexIsDisabledWhenUsingErofs(t *testing.T) {
9295	t.Parallel()
9296	ctx := testApex(t, `
9297		apex {
9298			name: "myapex",
9299			key: "myapex.key",
9300			compressible: true,
9301			updatable: false,
9302			payload_fs_type: "erofs",
9303		}
9304		apex_key {
9305			name: "myapex.key",
9306			public_key: "testkey.avbpubkey",
9307			private_key: "testkey.pem",
9308		}
9309	`,
9310		android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
9311			variables.CompressedApex = proptools.BoolPtr(true)
9312		}),
9313	)
9314
9315	compressRule := ctx.ModuleForTests(t, "myapex", "android_common_myapex").MaybeRule("compressRule")
9316	if compressRule.Rule != nil {
9317		t.Error("erofs apex should not be compressed")
9318	}
9319}
9320
9321func TestApexSet_ShouldRespectCompressedApexFlag(t *testing.T) {
9322	t.Parallel()
9323	for _, compressionEnabled := range []bool{true, false} {
9324		t.Run(fmt.Sprintf("compressionEnabled=%v", compressionEnabled), func(t *testing.T) {
9325			t.Parallel()
9326			ctx := testApex(t, `
9327				apex_set {
9328					name: "com.company.android.myapex",
9329					apex_name: "com.android.myapex",
9330					set: "company-myapex.apks",
9331				}
9332			`, android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
9333				variables.CompressedApex = proptools.BoolPtr(compressionEnabled)
9334			}),
9335			)
9336
9337			build := ctx.ModuleForTests(t, "com.company.android.myapex", "android_common_prebuilt_com.android.myapex").Output("com.company.android.myapex.apex")
9338			if compressionEnabled {
9339				ensureEquals(t, build.Rule.String(), "android/soong/android.Cp")
9340			} else {
9341				ensureEquals(t, build.Rule.String(), "android/apex.decompressApex")
9342			}
9343		})
9344	}
9345}
9346
9347func TestPreferredPrebuiltSharedLibDep(t *testing.T) {
9348	t.Parallel()
9349	ctx := testApex(t, `
9350		apex {
9351			name: "myapex",
9352			key: "myapex.key",
9353			native_shared_libs: ["mylib"],
9354			updatable: false,
9355		}
9356
9357		apex_key {
9358			name: "myapex.key",
9359			public_key: "testkey.avbpubkey",
9360			private_key: "testkey.pem",
9361		}
9362
9363		cc_library {
9364			name: "mylib",
9365			srcs: ["mylib.cpp"],
9366			apex_available: ["myapex"],
9367			shared_libs: ["otherlib"],
9368			system_shared_libs: [],
9369		}
9370
9371		cc_library {
9372			name: "otherlib",
9373			srcs: ["mylib.cpp"],
9374			stubs: {
9375				versions: ["current"],
9376			},
9377		}
9378
9379		cc_prebuilt_library_shared {
9380			name: "otherlib",
9381			prefer: true,
9382			srcs: ["prebuilt.so"],
9383			stubs: {
9384				versions: ["current"],
9385			},
9386		}
9387	`)
9388
9389	ab := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Module().(*apexBundle)
9390	data := android.AndroidMkDataForTest(t, ctx, ab)
9391	var builder strings.Builder
9392	data.Custom(&builder, ab.BaseModuleName(), "TARGET_", "", data)
9393	androidMk := builder.String()
9394
9395	// The make level dependency needs to be on otherlib - prebuilt_otherlib isn't
9396	// a thing there.
9397	ensureContains(t, androidMk, "LOCAL_REQUIRED_MODULES := libc++:64 mylib.myapex:64 otherlib\n")
9398}
9399
9400func TestExcludeDependency(t *testing.T) {
9401	t.Parallel()
9402	ctx := testApex(t, `
9403		apex {
9404			name: "myapex",
9405			key: "myapex.key",
9406			native_shared_libs: ["mylib"],
9407			updatable: false,
9408		}
9409
9410		apex_key {
9411			name: "myapex.key",
9412			public_key: "testkey.avbpubkey",
9413			private_key: "testkey.pem",
9414		}
9415
9416		cc_library {
9417			name: "mylib",
9418			srcs: ["mylib.cpp"],
9419			system_shared_libs: [],
9420			stl: "none",
9421			apex_available: ["myapex"],
9422			shared_libs: ["mylib2"],
9423			target: {
9424				apex: {
9425					exclude_shared_libs: ["mylib2"],
9426				},
9427			},
9428		}
9429
9430		cc_library {
9431			name: "mylib2",
9432			srcs: ["mylib.cpp"],
9433			system_shared_libs: [],
9434			stl: "none",
9435		}
9436	`)
9437
9438	// Check if mylib is linked to mylib2 for the non-apex target
9439	ldFlags := ctx.ModuleForTests(t, "mylib", "android_arm64_armv8-a_shared").Rule("ld").Args["libFlags"]
9440	ensureContains(t, ldFlags, "mylib2/android_arm64_armv8-a_shared/mylib2.so")
9441
9442	// Make sure that the link doesn't occur for the apex target
9443	ldFlags = ctx.ModuleForTests(t, "mylib", "android_arm64_armv8-a_shared_apex10000").Rule("ld").Args["libFlags"]
9444	ensureNotContains(t, ldFlags, "mylib2/android_arm64_armv8-a_shared_apex10000/mylib2.so")
9445
9446	// It shouldn't appear in the copy cmd as well.
9447	copyCmds := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Rule("apexRule").Args["copy_commands"]
9448	ensureNotContains(t, copyCmds, "image.apex/lib64/mylib2.so")
9449}
9450
9451func TestPrebuiltStubLibDep(t *testing.T) {
9452	t.Parallel()
9453	bpBase := `
9454		apex {
9455			name: "myapex",
9456			key: "myapex.key",
9457			native_shared_libs: ["mylib"],
9458			updatable: false,
9459		}
9460		apex_key {
9461			name: "myapex.key",
9462			public_key: "testkey.avbpubkey",
9463			private_key: "testkey.pem",
9464		}
9465		cc_library {
9466			name: "mylib",
9467			srcs: ["mylib.cpp"],
9468			apex_available: ["myapex"],
9469			shared_libs: ["stublib"],
9470			system_shared_libs: [],
9471		}
9472		apex {
9473			name: "otherapex",
9474			enabled: %s,
9475			key: "myapex.key",
9476			native_shared_libs: ["stublib"],
9477			updatable: false,
9478		}
9479	`
9480
9481	stublibSourceBp := `
9482		cc_library {
9483			name: "stublib",
9484			srcs: ["mylib.cpp"],
9485			apex_available: ["otherapex"],
9486			system_shared_libs: [],
9487			stl: "none",
9488			stubs: {
9489				versions: ["1"],
9490			},
9491		}
9492	`
9493
9494	stublibPrebuiltBp := `
9495		cc_prebuilt_library_shared {
9496			name: "stublib",
9497			srcs: ["prebuilt.so"],
9498			apex_available: ["otherapex"],
9499			stubs: {
9500				versions: ["1"],
9501			},
9502			%s
9503		}
9504	`
9505
9506	tests := []struct {
9507		name             string
9508		stublibBp        string
9509		usePrebuilt      bool
9510		modNames         []string // Modules to collect AndroidMkEntries for
9511		otherApexEnabled []string
9512	}{
9513		{
9514			name:             "only_source",
9515			stublibBp:        stublibSourceBp,
9516			usePrebuilt:      false,
9517			modNames:         []string{"stublib"},
9518			otherApexEnabled: []string{"true", "false"},
9519		},
9520		{
9521			name:             "source_preferred",
9522			stublibBp:        stublibSourceBp + fmt.Sprintf(stublibPrebuiltBp, ""),
9523			usePrebuilt:      false,
9524			modNames:         []string{"stublib", "prebuilt_stublib"},
9525			otherApexEnabled: []string{"true", "false"},
9526		},
9527		{
9528			name:             "prebuilt_preferred",
9529			stublibBp:        stublibSourceBp + fmt.Sprintf(stublibPrebuiltBp, "prefer: true,"),
9530			usePrebuilt:      true,
9531			modNames:         []string{"stublib", "prebuilt_stublib"},
9532			otherApexEnabled: []string{"false"}, // No "true" since APEX cannot depend on prebuilt.
9533		},
9534		{
9535			name:             "only_prebuilt",
9536			stublibBp:        fmt.Sprintf(stublibPrebuiltBp, ""),
9537			usePrebuilt:      true,
9538			modNames:         []string{"stublib"},
9539			otherApexEnabled: []string{"false"}, // No "true" since APEX cannot depend on prebuilt.
9540		},
9541	}
9542
9543	for _, test := range tests {
9544		t.Run(test.name, func(t *testing.T) {
9545			t.Parallel()
9546			for _, otherApexEnabled := range test.otherApexEnabled {
9547				t.Run("otherapex_enabled_"+otherApexEnabled, func(t *testing.T) {
9548					t.Parallel()
9549					ctx := testApex(t, fmt.Sprintf(bpBase, otherApexEnabled)+test.stublibBp)
9550
9551					type modAndMkEntries struct {
9552						mod       *cc.Module
9553						mkEntries android.AndroidMkInfo
9554					}
9555					entries := []*modAndMkEntries{}
9556
9557					// Gather shared lib modules that are installable
9558					for _, modName := range test.modNames {
9559						for _, variant := range ctx.ModuleVariantsForTests(modName) {
9560							if !strings.HasPrefix(variant, "android_arm64_armv8-a_shared") {
9561								continue
9562							}
9563							mod := ctx.ModuleForTests(t, modName, variant).Module().(*cc.Module)
9564							if !mod.Enabled(android.PanickingConfigAndErrorContext(ctx)) || mod.IsHideFromMake() {
9565								continue
9566							}
9567							info := android.AndroidMkInfoForTest(t, ctx, mod)
9568							ents := []android.AndroidMkInfo{info.PrimaryInfo}
9569							ents = append(ents, info.ExtraInfo...)
9570							for _, ent := range ents {
9571								if ent.Disabled {
9572									continue
9573								}
9574								entries = append(entries, &modAndMkEntries{
9575									mod:       mod,
9576									mkEntries: ent,
9577								})
9578							}
9579						}
9580					}
9581
9582					var entry *modAndMkEntries = nil
9583					for _, ent := range entries {
9584						if strings.Join(ent.mkEntries.EntryMap["LOCAL_MODULE"], ",") == "stublib" {
9585							if entry != nil {
9586								t.Errorf("More than one AndroidMk entry for \"stublib\": %s and %s", entry.mod, ent.mod)
9587							} else {
9588								entry = ent
9589							}
9590						}
9591					}
9592
9593					if entry == nil {
9594						t.Errorf("AndroidMk entry for \"stublib\" missing")
9595					} else {
9596						isPrebuilt := entry.mod.Prebuilt() != nil
9597						if isPrebuilt != test.usePrebuilt {
9598							t.Errorf("Wrong module for \"stublib\" AndroidMk entry: got prebuilt %t, want prebuilt %t", isPrebuilt, test.usePrebuilt)
9599						}
9600						if !entry.mod.IsStubs() {
9601							t.Errorf("Module for \"stublib\" AndroidMk entry isn't a stub: %s", entry.mod)
9602						}
9603						if entry.mkEntries.EntryMap["LOCAL_NOT_AVAILABLE_FOR_PLATFORM"] != nil {
9604							t.Errorf("AndroidMk entry for \"stublib\" has LOCAL_NOT_AVAILABLE_FOR_PLATFORM set: %+v", entry.mkEntries)
9605						}
9606						cflags := entry.mkEntries.EntryMap["LOCAL_EXPORT_CFLAGS"]
9607						expected := "-D__STUBLIB_API__=10000"
9608						if !android.InList(expected, cflags) {
9609							t.Errorf("LOCAL_EXPORT_CFLAGS expected to have %q, but got %q", expected, cflags)
9610						}
9611					}
9612				})
9613			}
9614		})
9615	}
9616}
9617
9618func TestApexJavaCoverage(t *testing.T) {
9619	t.Parallel()
9620	bp := `
9621		apex {
9622			name: "myapex",
9623			key: "myapex.key",
9624			java_libs: ["mylib"],
9625			bootclasspath_fragments: ["mybootclasspathfragment"],
9626			systemserverclasspath_fragments: ["mysystemserverclasspathfragment"],
9627			updatable: false,
9628		}
9629
9630		apex_key {
9631			name: "myapex.key",
9632			public_key: "testkey.avbpubkey",
9633			private_key: "testkey.pem",
9634		}
9635
9636		java_library {
9637			name: "mylib",
9638			srcs: ["mylib.java"],
9639			apex_available: ["myapex"],
9640			compile_dex: true,
9641		}
9642
9643		bootclasspath_fragment {
9644			name: "mybootclasspathfragment",
9645			contents: ["mybootclasspathlib"],
9646			apex_available: ["myapex"],
9647			hidden_api: {
9648				split_packages: ["*"],
9649			},
9650		}
9651
9652		java_library {
9653			name: "mybootclasspathlib",
9654			srcs: ["mybootclasspathlib.java"],
9655			apex_available: ["myapex"],
9656			compile_dex: true,
9657			sdk_version: "current",
9658		}
9659
9660		systemserverclasspath_fragment {
9661			name: "mysystemserverclasspathfragment",
9662			contents: ["mysystemserverclasspathlib"],
9663			apex_available: ["myapex"],
9664		}
9665
9666		java_library {
9667			name: "mysystemserverclasspathlib",
9668			srcs: ["mysystemserverclasspathlib.java"],
9669			apex_available: ["myapex"],
9670			compile_dex: true,
9671		}
9672	`
9673
9674	result := android.GroupFixturePreparers(
9675		PrepareForTestWithApexBuildComponents,
9676		prepareForTestWithMyapex,
9677		java.PrepareForTestWithJavaDefaultModules,
9678		android.PrepareForTestWithAndroidBuildComponents,
9679		android.FixtureWithRootAndroidBp(bp),
9680		dexpreopt.FixtureSetApexBootJars("myapex:mybootclasspathlib"),
9681		dexpreopt.FixtureSetApexSystemServerJars("myapex:mysystemserverclasspathlib"),
9682		java.PrepareForTestWithJacocoInstrumentation,
9683	).RunTest(t)
9684
9685	// Make sure jacoco ran on both mylib and mybootclasspathlib
9686	if result.ModuleForTests(t, "mylib", "android_common_apex10000").MaybeRule("jacoco").Rule == nil {
9687		t.Errorf("Failed to find jacoco rule for mylib")
9688	}
9689	if result.ModuleForTests(t, "mybootclasspathlib", "android_common_apex10000").MaybeRule("jacoco").Rule == nil {
9690		t.Errorf("Failed to find jacoco rule for mybootclasspathlib")
9691	}
9692	if result.ModuleForTests(t, "mysystemserverclasspathlib", "android_common_apex10000").MaybeRule("jacoco").Rule == nil {
9693		t.Errorf("Failed to find jacoco rule for mysystemserverclasspathlib")
9694	}
9695}
9696
9697func TestProhibitStaticExecutable(t *testing.T) {
9698	t.Parallel()
9699	testApexError(t, `executable mybin is static`, `
9700		apex {
9701			name: "myapex",
9702			key: "myapex.key",
9703			binaries: ["mybin"],
9704			min_sdk_version: "29",
9705		}
9706
9707		apex_key {
9708			name: "myapex.key",
9709			public_key: "testkey.avbpubkey",
9710			private_key: "testkey.pem",
9711		}
9712
9713		cc_binary {
9714			name: "mybin",
9715			srcs: ["mylib.cpp"],
9716			relative_install_path: "foo/bar",
9717			static_executable: true,
9718			system_shared_libs: [],
9719			stl: "none",
9720			apex_available: [ "myapex" ],
9721			min_sdk_version: "29",
9722		}
9723	`)
9724
9725	testApexError(t, `executable mybin.rust is static`, `
9726		apex {
9727			name: "myapex",
9728			key: "myapex.key",
9729			binaries: ["mybin.rust"],
9730			min_sdk_version: "29",
9731		}
9732
9733		apex_key {
9734			name: "myapex.key",
9735			public_key: "testkey.avbpubkey",
9736			private_key: "testkey.pem",
9737		}
9738
9739		rust_binary {
9740			name: "mybin.rust",
9741			srcs: ["foo.rs"],
9742			static_executable: true,
9743			apex_available: ["myapex"],
9744			min_sdk_version: "29",
9745		}
9746	`)
9747}
9748
9749func TestAndroidMk_DexpreoptBuiltInstalledForApex(t *testing.T) {
9750	t.Parallel()
9751	ctx := testApex(t, `
9752		apex {
9753			name: "myapex",
9754			key: "myapex.key",
9755			updatable: false,
9756			java_libs: ["foo"],
9757		}
9758
9759		apex_key {
9760			name: "myapex.key",
9761			public_key: "testkey.avbpubkey",
9762			private_key: "testkey.pem",
9763		}
9764
9765		java_library {
9766			name: "foo",
9767			srcs: ["foo.java"],
9768			apex_available: ["myapex"],
9769			installable: true,
9770		}
9771	`,
9772		dexpreopt.FixtureSetApexSystemServerJars("myapex:foo"),
9773	)
9774
9775	apexBundle := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Module().(*apexBundle)
9776	data := android.AndroidMkDataForTest(t, ctx, apexBundle)
9777	var builder strings.Builder
9778	data.Custom(&builder, apexBundle.BaseModuleName(), "TARGET_", "", data)
9779	androidMk := builder.String()
9780	out := ctx.Config().OutDir()
9781	ensureContains(t, androidMk, "LOCAL_SOONG_INSTALL_PAIRS += "+
9782		filepath.Join(out, "soong/.intermediates/foo/android_common_apex10000/dexpreopt/foo/oat/arm64/javalib.odex")+
9783		":"+
9784		filepath.Join(out, "target/product/test_device/system/framework/oat/arm64/apex@myapex@javalib@foo.jar@classes.odex")+
9785		" "+
9786		filepath.Join(out, "soong/.intermediates/foo/android_common_apex10000/dexpreopt/foo/oat/arm64/javalib.vdex")+
9787		":"+
9788		filepath.Join(out, "target/product/test_device/system/framework/oat/arm64/apex@myapex@javalib@foo.jar@classes.vdex")+
9789		"\n")
9790}
9791
9792func TestAndroidMk_RequiredModules(t *testing.T) {
9793	t.Parallel()
9794	ctx := testApex(t, `
9795		apex {
9796			name: "myapex",
9797			key: "myapex.key",
9798			updatable: false,
9799			java_libs: ["foo"],
9800			required: ["otherapex"],
9801		}
9802
9803		apex {
9804			name: "otherapex",
9805			key: "myapex.key",
9806			updatable: false,
9807			java_libs: ["foo"],
9808		}
9809
9810		apex_key {
9811			name: "myapex.key",
9812			public_key: "testkey.avbpubkey",
9813			private_key: "testkey.pem",
9814		}
9815
9816		java_library {
9817			name: "foo",
9818			srcs: ["foo.java"],
9819			apex_available: ["myapex", "otherapex"],
9820			installable: true,
9821		}
9822	`)
9823
9824	apexBundle := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Module().(*apexBundle)
9825	data := android.AndroidMkDataForTest(t, ctx, apexBundle)
9826	var builder strings.Builder
9827	data.Custom(&builder, apexBundle.BaseModuleName(), "TARGET_", "", data)
9828	androidMk := builder.String()
9829	ensureContains(t, androidMk, "LOCAL_REQUIRED_MODULES := foo.myapex otherapex")
9830}
9831
9832func TestAndroidMk_RequiredDeps(t *testing.T) {
9833	t.Parallel()
9834	ctx := testApex(t, `
9835		apex {
9836			name: "myapex",
9837			key: "myapex.key",
9838			updatable: false,
9839		}
9840
9841		apex_key {
9842			name: "myapex.key",
9843			public_key: "testkey.avbpubkey",
9844			private_key: "testkey.pem",
9845		}
9846	`)
9847
9848	bundle := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Module().(*apexBundle)
9849	bundle.makeModulesToInstall = append(bundle.makeModulesToInstall, "foo")
9850	data := android.AndroidMkDataForTest(t, ctx, bundle)
9851	var builder strings.Builder
9852	data.Custom(&builder, bundle.BaseModuleName(), "TARGET_", "", data)
9853	androidMk := builder.String()
9854	ensureContains(t, androidMk, "LOCAL_REQUIRED_MODULES := foo\n")
9855}
9856
9857func TestApexOutputFileProducer(t *testing.T) {
9858	t.Parallel()
9859	for _, tc := range []struct {
9860		name          string
9861		ref           string
9862		expected_data []string
9863	}{
9864		{
9865			name:          "test_using_output",
9866			ref:           ":myapex",
9867			expected_data: []string{"out/soong/.intermediates/myapex/android_common_myapex/myapex.capex:myapex.capex"},
9868		},
9869		{
9870			name:          "test_using_apex",
9871			ref:           ":myapex{.apex}",
9872			expected_data: []string{"out/soong/.intermediates/myapex/android_common_myapex/myapex.apex:myapex.apex"},
9873		},
9874	} {
9875		t.Run(tc.name, func(t *testing.T) {
9876			t.Parallel()
9877			ctx := testApex(t, `
9878					apex {
9879						name: "myapex",
9880						key: "myapex.key",
9881						compressible: true,
9882						updatable: false,
9883					}
9884
9885					apex_key {
9886						name: "myapex.key",
9887						public_key: "testkey.avbpubkey",
9888						private_key: "testkey.pem",
9889					}
9890
9891					java_test {
9892						name: "`+tc.name+`",
9893						srcs: ["a.java"],
9894						data: ["`+tc.ref+`"],
9895					}
9896				`,
9897				android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
9898					variables.CompressedApex = proptools.BoolPtr(true)
9899				}))
9900			javaTest := ctx.ModuleForTests(t, tc.name, "android_common").Module().(*java.Test)
9901			data := android.AndroidMkEntriesForTest(t, ctx, javaTest)[0].EntryMap["LOCAL_COMPATIBILITY_SUPPORT_FILES"]
9902			android.AssertStringPathsRelativeToTopEquals(t, "data", ctx.Config(), tc.expected_data, data)
9903		})
9904	}
9905}
9906
9907func TestSdkLibraryCanHaveHigherMinSdkVersion(t *testing.T) {
9908	t.Parallel()
9909	preparer := android.GroupFixturePreparers(
9910		PrepareForTestWithApexBuildComponents,
9911		prepareForTestWithMyapex,
9912		java.PrepareForTestWithJavaSdkLibraryFiles,
9913		java.PrepareForTestWithJavaDefaultModules,
9914		android.PrepareForTestWithAndroidBuildComponents,
9915		dexpreopt.FixtureSetApexBootJars("myapex:mybootclasspathlib"),
9916		dexpreopt.FixtureSetApexSystemServerJars("myapex:mysystemserverclasspathlib"),
9917	)
9918
9919	// Test java_sdk_library in bootclasspath_fragment may define higher min_sdk_version than the apex
9920	t.Run("bootclasspath_fragment jar has higher min_sdk_version than apex", func(t *testing.T) {
9921		t.Parallel()
9922		preparer.RunTestWithBp(t, `
9923			apex {
9924				name: "myapex",
9925				key: "myapex.key",
9926				bootclasspath_fragments: ["mybootclasspathfragment"],
9927				min_sdk_version: "30",
9928				updatable: false,
9929			}
9930
9931			apex_key {
9932				name: "myapex.key",
9933				public_key: "testkey.avbpubkey",
9934				private_key: "testkey.pem",
9935			}
9936
9937			bootclasspath_fragment {
9938				name: "mybootclasspathfragment",
9939				contents: ["mybootclasspathlib"],
9940				apex_available: ["myapex"],
9941				hidden_api: {
9942					split_packages: ["*"],
9943				},
9944			}
9945
9946			java_sdk_library {
9947				name: "mybootclasspathlib",
9948				srcs: ["mybootclasspathlib.java"],
9949				apex_available: ["myapex"],
9950				compile_dex: true,
9951				unsafe_ignore_missing_latest_api: true,
9952				min_sdk_version: "31",
9953				static_libs: ["util"],
9954				sdk_version: "core_current",
9955			}
9956
9957			java_library {
9958				name: "util",
9959                srcs: ["a.java"],
9960				apex_available: ["myapex"],
9961				min_sdk_version: "31",
9962				static_libs: ["another_util"],
9963				sdk_version: "core_current",
9964			}
9965
9966			java_library {
9967				name: "another_util",
9968                srcs: ["a.java"],
9969				min_sdk_version: "31",
9970				apex_available: ["myapex"],
9971				sdk_version: "core_current",
9972			}
9973		`)
9974	})
9975
9976	// Test java_sdk_library in systemserverclasspath_fragment may define higher min_sdk_version than the apex
9977	t.Run("systemserverclasspath_fragment jar has higher min_sdk_version than apex", func(t *testing.T) {
9978		t.Parallel()
9979		preparer.RunTestWithBp(t, `
9980			apex {
9981				name: "myapex",
9982				key: "myapex.key",
9983				systemserverclasspath_fragments: ["mysystemserverclasspathfragment"],
9984				min_sdk_version: "30",
9985				updatable: false,
9986			}
9987
9988			apex_key {
9989				name: "myapex.key",
9990				public_key: "testkey.avbpubkey",
9991				private_key: "testkey.pem",
9992			}
9993
9994			systemserverclasspath_fragment {
9995				name: "mysystemserverclasspathfragment",
9996				contents: ["mysystemserverclasspathlib"],
9997				apex_available: ["myapex"],
9998			}
9999
10000			java_sdk_library {
10001				name: "mysystemserverclasspathlib",
10002				srcs: ["mysystemserverclasspathlib.java"],
10003				apex_available: ["myapex"],
10004				compile_dex: true,
10005				min_sdk_version: "32",
10006				unsafe_ignore_missing_latest_api: true,
10007				static_libs: ["util"],
10008			}
10009
10010			java_library {
10011				name: "util",
10012                srcs: ["a.java"],
10013				apex_available: ["myapex"],
10014				min_sdk_version: "31",
10015				static_libs: ["another_util"],
10016			}
10017
10018			java_library {
10019				name: "another_util",
10020                srcs: ["a.java"],
10021				min_sdk_version: "31",
10022				apex_available: ["myapex"],
10023			}
10024		`)
10025	})
10026
10027	t.Run("bootclasspath_fragment jar must set min_sdk_version", func(t *testing.T) {
10028		t.Parallel()
10029		preparer.
10030			RunTestWithBp(t, `
10031				apex {
10032					name: "myapex",
10033					key: "myapex.key",
10034					bootclasspath_fragments: ["mybootclasspathfragment"],
10035					min_sdk_version: "30",
10036					updatable: false,
10037				}
10038
10039				apex_key {
10040					name: "myapex.key",
10041					public_key: "testkey.avbpubkey",
10042					private_key: "testkey.pem",
10043				}
10044
10045				bootclasspath_fragment {
10046					name: "mybootclasspathfragment",
10047					contents: ["mybootclasspathlib"],
10048					apex_available: ["myapex"],
10049					hidden_api: {
10050						split_packages: ["*"],
10051					},
10052				}
10053
10054				java_sdk_library {
10055					name: "mybootclasspathlib",
10056					srcs: ["mybootclasspathlib.java"],
10057					apex_available: ["myapex"],
10058					compile_dex: true,
10059					unsafe_ignore_missing_latest_api: true,
10060					sdk_version: "current",
10061					min_sdk_version: "30",
10062				}
10063		`)
10064	})
10065
10066	t.Run("systemserverclasspath_fragment jar must set min_sdk_version", func(t *testing.T) {
10067		t.Parallel()
10068		preparer.ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`module "mysystemserverclasspathlib".*must set min_sdk_version`)).
10069			RunTestWithBp(t, `
10070				apex {
10071					name: "myapex",
10072					key: "myapex.key",
10073					systemserverclasspath_fragments: ["mysystemserverclasspathfragment"],
10074					min_sdk_version: "30",
10075					updatable: false,
10076				}
10077
10078				apex_key {
10079					name: "myapex.key",
10080					public_key: "testkey.avbpubkey",
10081					private_key: "testkey.pem",
10082				}
10083
10084				systemserverclasspath_fragment {
10085					name: "mysystemserverclasspathfragment",
10086					contents: ["mysystemserverclasspathlib"],
10087					apex_available: ["myapex"],
10088				}
10089
10090				java_sdk_library {
10091					name: "mysystemserverclasspathlib",
10092					srcs: ["mysystemserverclasspathlib.java"],
10093					apex_available: ["myapex"],
10094					compile_dex: true,
10095					unsafe_ignore_missing_latest_api: true,
10096				}
10097		`)
10098	})
10099}
10100
10101// Verifies that the APEX depends on all the Make modules in the list.
10102func ensureContainsRequiredDeps(t *testing.T, ctx *android.TestContext, moduleName, variant string, deps []string) {
10103	a := ctx.ModuleForTests(t, moduleName, variant).Module().(*apexBundle)
10104	for _, dep := range deps {
10105		android.AssertStringListContains(t, "", a.makeModulesToInstall, dep)
10106	}
10107}
10108
10109// Verifies that the APEX does not depend on any of the Make modules in the list.
10110func ensureDoesNotContainRequiredDeps(t *testing.T, ctx *android.TestContext, moduleName, variant string, deps []string) {
10111	a := ctx.ModuleForTests(t, moduleName, variant).Module().(*apexBundle)
10112	for _, dep := range deps {
10113		android.AssertStringListDoesNotContain(t, "", a.makeModulesToInstall, dep)
10114	}
10115}
10116
10117func TestApexStrictUpdtabilityLint(t *testing.T) {
10118	t.Parallel()
10119	bpTemplate := `
10120		apex {
10121			name: "myapex",
10122			key: "myapex.key",
10123			java_libs: ["myjavalib"],
10124			updatable: %v,
10125			min_sdk_version: "29",
10126		}
10127		apex_key {
10128			name: "myapex.key",
10129		}
10130		java_library {
10131			name: "myjavalib",
10132			srcs: ["MyClass.java"],
10133			apex_available: [ "myapex" ],
10134			lint: {
10135				strict_updatability_linting: %v,
10136				%s
10137			},
10138			sdk_version: "current",
10139			min_sdk_version: "29",
10140			compile_dex: true,
10141		}
10142		`
10143	fs := android.MockFS{
10144		"lint-baseline.xml": nil,
10145	}
10146
10147	testCases := []struct {
10148		testCaseName                    string
10149		apexUpdatable                   bool
10150		javaStrictUpdtabilityLint       bool
10151		lintFileExists                  bool
10152		disallowedFlagExpectedOnApex    bool
10153		disallowedFlagExpectedOnJavalib bool
10154	}{
10155		{
10156			testCaseName:                    "lint-baseline.xml does not exist, no disallowed flag necessary in lint cmd",
10157			apexUpdatable:                   true,
10158			javaStrictUpdtabilityLint:       true,
10159			lintFileExists:                  false,
10160			disallowedFlagExpectedOnApex:    false,
10161			disallowedFlagExpectedOnJavalib: false,
10162		},
10163		{
10164			testCaseName:                    "non-updatable apex respects strict_updatability of javalib",
10165			apexUpdatable:                   false,
10166			javaStrictUpdtabilityLint:       false,
10167			lintFileExists:                  true,
10168			disallowedFlagExpectedOnApex:    false,
10169			disallowedFlagExpectedOnJavalib: false,
10170		},
10171		{
10172			testCaseName:                    "non-updatable apex respects strict updatability of javalib",
10173			apexUpdatable:                   false,
10174			javaStrictUpdtabilityLint:       true,
10175			lintFileExists:                  true,
10176			disallowedFlagExpectedOnApex:    false,
10177			disallowedFlagExpectedOnJavalib: true,
10178		},
10179		{
10180			testCaseName:                    "updatable apex checks strict updatability of javalib",
10181			apexUpdatable:                   true,
10182			javaStrictUpdtabilityLint:       false,
10183			lintFileExists:                  true,
10184			disallowedFlagExpectedOnApex:    true,
10185			disallowedFlagExpectedOnJavalib: false,
10186		},
10187	}
10188
10189	for _, testCase := range testCases {
10190		t.Run(testCase.testCaseName, func(t *testing.T) {
10191			t.Parallel()
10192			fixtures := []android.FixturePreparer{}
10193			baselineProperty := ""
10194			if testCase.lintFileExists {
10195				fixtures = append(fixtures, fs.AddToFixture())
10196				baselineProperty = "baseline_filename: \"lint-baseline.xml\""
10197			}
10198			bp := fmt.Sprintf(bpTemplate, testCase.apexUpdatable, testCase.javaStrictUpdtabilityLint, baselineProperty)
10199
10200			result := testApex(t, bp, fixtures...)
10201
10202			checkModule := func(m android.TestingBuildParams, name string, expectStrictUpdatability bool) {
10203				if expectStrictUpdatability {
10204					if m.Rule == nil {
10205						t.Errorf("expected strict updatability check rule on %s", name)
10206					} else {
10207						android.AssertStringDoesContain(t, fmt.Sprintf("strict updatability check rule for %s", name),
10208							m.RuleParams.Command, "--disallowed_issues NewApi")
10209						android.AssertStringListContains(t, fmt.Sprintf("strict updatability check baselines for %s", name),
10210							m.Inputs.Strings(), "lint-baseline.xml")
10211					}
10212				} else {
10213					if m.Rule != nil {
10214						t.Errorf("expected no strict updatability check rule on %s", name)
10215					}
10216				}
10217			}
10218
10219			myjavalib := result.ModuleForTests(t, "myjavalib", "android_common_apex29")
10220			apex := result.ModuleForTests(t, "myapex", "android_common_myapex")
10221			apexStrictUpdatabilityCheck := apex.MaybeOutput("lint_strict_updatability_check.stamp")
10222			javalibStrictUpdatabilityCheck := myjavalib.MaybeOutput("lint_strict_updatability_check.stamp")
10223
10224			checkModule(apexStrictUpdatabilityCheck, "myapex", testCase.disallowedFlagExpectedOnApex)
10225			checkModule(javalibStrictUpdatabilityCheck, "myjavalib", testCase.disallowedFlagExpectedOnJavalib)
10226		})
10227	}
10228}
10229
10230// checks transtive deps of an apex coming from bootclasspath_fragment
10231func TestApexStrictUpdtabilityLintBcpFragmentDeps(t *testing.T) {
10232	t.Parallel()
10233	bp := `
10234		apex {
10235			name: "myapex",
10236			key: "myapex.key",
10237			bootclasspath_fragments: ["mybootclasspathfragment"],
10238			updatable: true,
10239			min_sdk_version: "29",
10240		}
10241		apex_key {
10242			name: "myapex.key",
10243		}
10244		bootclasspath_fragment {
10245			name: "mybootclasspathfragment",
10246			contents: ["myjavalib"],
10247			apex_available: ["myapex"],
10248			hidden_api: {
10249				split_packages: ["*"],
10250			},
10251		}
10252		java_library {
10253			name: "myjavalib",
10254			srcs: ["MyClass.java"],
10255			apex_available: [ "myapex" ],
10256			sdk_version: "current",
10257			min_sdk_version: "29",
10258			compile_dex: true,
10259			lint: {
10260				baseline_filename: "lint-baseline.xml",
10261			}
10262		}
10263		`
10264	fs := android.MockFS{
10265		"lint-baseline.xml": nil,
10266	}
10267
10268	result := testApex(t, bp, dexpreopt.FixtureSetApexBootJars("myapex:myjavalib"), fs.AddToFixture())
10269	apex := result.ModuleForTests(t, "myapex", "android_common_myapex")
10270	apexStrictUpdatabilityCheck := apex.Output("lint_strict_updatability_check.stamp")
10271	android.AssertStringDoesContain(t, "strict updatability check rule for myapex",
10272		apexStrictUpdatabilityCheck.RuleParams.Command, "--disallowed_issues NewApi")
10273	android.AssertStringListContains(t, "strict updatability check baselines for myapex",
10274		apexStrictUpdatabilityCheck.Inputs.Strings(), "lint-baseline.xml")
10275}
10276
10277func TestApexLintBcpFragmentSdkLibDeps(t *testing.T) {
10278	t.Parallel()
10279	bp := `
10280		apex {
10281			name: "myapex",
10282			key: "myapex.key",
10283			bootclasspath_fragments: ["mybootclasspathfragment"],
10284			min_sdk_version: "29",
10285			java_libs: [
10286				"jacocoagent",
10287			],
10288		}
10289		apex_key {
10290			name: "myapex.key",
10291		}
10292		bootclasspath_fragment {
10293			name: "mybootclasspathfragment",
10294			contents: ["foo"],
10295			apex_available: ["myapex"],
10296			hidden_api: {
10297				split_packages: ["*"],
10298			},
10299		}
10300		java_sdk_library {
10301			name: "foo",
10302			srcs: ["MyClass.java"],
10303			apex_available: [ "myapex" ],
10304			sdk_version: "current",
10305			min_sdk_version: "29",
10306			compile_dex: true,
10307		}
10308		`
10309	fs := android.MockFS{
10310		"lint-baseline.xml": nil,
10311	}
10312
10313	result := android.GroupFixturePreparers(
10314		prepareForApexTest,
10315		java.PrepareForTestWithJavaSdkLibraryFiles,
10316		java.PrepareForTestWithJacocoInstrumentation,
10317		java.FixtureWithLastReleaseApis("foo"),
10318		android.FixtureMergeMockFs(fs),
10319	).RunTestWithBp(t, bp)
10320
10321	myapex := result.ModuleForTests(t, "myapex", "android_common_myapex")
10322	lintReportInputs := strings.Join(myapex.Output("lint-report-xml.zip").Inputs.Strings(), " ")
10323	android.AssertStringDoesContain(t,
10324		"myapex lint report expected to contain that of the sdk library impl lib as an input",
10325		lintReportInputs, "foo.impl")
10326}
10327
10328// updatable apexes should propagate updatable=true to its apps
10329func TestUpdatableApexEnforcesAppUpdatability(t *testing.T) {
10330	t.Parallel()
10331	bp := `
10332		apex {
10333			name: "myapex",
10334			key: "myapex.key",
10335			updatable: true,
10336			apps: [
10337				"myapp",
10338			],
10339			min_sdk_version: "30",
10340		}
10341		apex_key {
10342			name: "myapex.key",
10343		}
10344		android_app {
10345			name: "myapp",
10346			apex_available: [
10347				"myapex",
10348			],
10349			sdk_version: "current",
10350			min_sdk_version: "30",
10351		}
10352		`
10353	_ = android.GroupFixturePreparers(
10354		prepareForApexTest,
10355	).ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern("app dependency myapp must have updatable: true")).
10356		RunTestWithBp(t, bp)
10357}
10358
10359func TestCannedFsConfig(t *testing.T) {
10360	t.Parallel()
10361	ctx := testApex(t, `
10362		apex {
10363			name: "myapex",
10364			key: "myapex.key",
10365			updatable: false,
10366		}
10367
10368		apex_key {
10369			name: "myapex.key",
10370			public_key: "testkey.avbpubkey",
10371			private_key: "testkey.pem",
10372		}`)
10373	mod := ctx.ModuleForTests(t, "myapex", "android_common_myapex")
10374	generateFsRule := mod.Rule("generateFsConfig")
10375	cmd := generateFsRule.RuleParams.Command
10376
10377	ensureContains(t, cmd, `( echo '/ 1000 1000 0755'; echo '/apex_manifest.json 1000 1000 0644'; echo '/apex_manifest.pb 1000 1000 0644'; ) >`)
10378}
10379
10380func TestCannedFsConfig_HasCustomConfig(t *testing.T) {
10381	t.Parallel()
10382	ctx := testApex(t, `
10383		apex {
10384			name: "myapex",
10385			key: "myapex.key",
10386			canned_fs_config: "my_config",
10387			updatable: false,
10388		}
10389
10390		apex_key {
10391			name: "myapex.key",
10392			public_key: "testkey.avbpubkey",
10393			private_key: "testkey.pem",
10394		}`)
10395	mod := ctx.ModuleForTests(t, "myapex", "android_common_myapex")
10396	generateFsRule := mod.Rule("generateFsConfig")
10397	cmd := generateFsRule.RuleParams.Command
10398
10399	// Ensure that canned_fs_config has "cat my_config" at the end
10400	ensureContains(t, cmd, `( echo '/ 1000 1000 0755'; echo '/apex_manifest.json 1000 1000 0644'; echo '/apex_manifest.pb 1000 1000 0644'; cat my_config ) >`)
10401}
10402
10403func TestStubLibrariesMultipleApexViolation(t *testing.T) {
10404	t.Parallel()
10405	testCases := []struct {
10406		desc          string
10407		hasStubs      bool
10408		apexAvailable string
10409		expectedError string
10410	}{
10411		{
10412			desc:          "non-stub library can have multiple apex_available",
10413			hasStubs:      false,
10414			apexAvailable: `["myapex", "otherapex"]`,
10415		},
10416		{
10417			desc:          "stub library should not be available to anyapex",
10418			hasStubs:      true,
10419			apexAvailable: `["//apex_available:anyapex"]`,
10420			expectedError: "Stub libraries should have a single apex_available.*anyapex",
10421		},
10422		{
10423			desc:          "stub library should not be available to multiple apexes",
10424			hasStubs:      true,
10425			apexAvailable: `["myapex", "otherapex"]`,
10426			expectedError: "Stub libraries should have a single apex_available.*myapex.*otherapex",
10427		},
10428		{
10429			desc:          "stub library can be available to a core apex and a test apex using apex_available_name",
10430			hasStubs:      true,
10431			apexAvailable: `["myapex"]`,
10432		},
10433	}
10434	bpTemplate := `
10435		cc_library {
10436			name: "libfoo",
10437			%v
10438			apex_available: %v,
10439		}
10440		apex {
10441			name: "myapex",
10442			key: "apex.key",
10443			updatable: false,
10444			native_shared_libs: ["libfoo"],
10445		}
10446		apex {
10447			name: "otherapex",
10448			key: "apex.key",
10449			updatable: false,
10450		}
10451		apex_test {
10452			name: "test_myapex",
10453			key: "apex.key",
10454			updatable: false,
10455			native_shared_libs: ["libfoo"],
10456			apex_available_name: "myapex",
10457		}
10458		apex_key {
10459			name: "apex.key",
10460		}
10461	`
10462	for _, tc := range testCases {
10463		t.Run(tc.desc, func(t *testing.T) {
10464			stubs := ""
10465			if tc.hasStubs {
10466				stubs = `stubs: {symbol_file: "libfoo.map.txt"},`
10467			}
10468			bp := fmt.Sprintf(bpTemplate, stubs, tc.apexAvailable)
10469			mockFsFixturePreparer := android.FixtureModifyMockFS(func(fs android.MockFS) {
10470				fs["system/sepolicy/apex/test_myapex-file_contexts"] = nil
10471			})
10472			if tc.expectedError == "" {
10473				testApex(t, bp, mockFsFixturePreparer)
10474			} else {
10475				testApexError(t, tc.expectedError, bp, mockFsFixturePreparer)
10476			}
10477		})
10478	}
10479}
10480
10481func TestFileSystemShouldSkipApexLibraries(t *testing.T) {
10482	t.Parallel()
10483	context := android.GroupFixturePreparers(
10484		android.PrepareForIntegrationTestWithAndroid,
10485		cc.PrepareForIntegrationTestWithCc,
10486		PrepareForTestWithApexBuildComponents,
10487		prepareForTestWithMyapex,
10488		filesystem.PrepareForTestWithFilesystemBuildComponents,
10489	)
10490	result := context.RunTestWithBp(t, `
10491		android_system_image {
10492			name: "myfilesystem",
10493			deps: [
10494				"libfoo",
10495			],
10496			linker_config: {
10497				gen_linker_config: true,
10498				linker_config_srcs: ["linker.config.json"],
10499			},
10500		}
10501
10502		cc_library {
10503			name: "libfoo",
10504			shared_libs: [
10505				"libbar",
10506			],
10507			stl: "none",
10508		}
10509
10510		cc_library {
10511			name: "libbar",
10512			stl: "none",
10513			apex_available: ["myapex"],
10514		}
10515
10516		apex {
10517			name: "myapex",
10518			native_shared_libs: ["libbar"],
10519			key: "myapex.key",
10520			updatable: false,
10521		}
10522
10523		apex_key {
10524			name: "myapex.key",
10525			public_key: "testkey.avbpubkey",
10526			private_key: "testkey.pem",
10527		}
10528	`)
10529
10530	inputs := result.ModuleForTests(t, "myfilesystem", "android_common").Output("myfilesystem.img").Implicits
10531	android.AssertStringListDoesNotContain(t, "filesystem should not have libbar",
10532		inputs.Strings(),
10533		"out/soong/.intermediates/libbar/android_arm64_armv8-a_shared/libbar.so")
10534}
10535
10536var apex_default_bp = `
10537		apex_key {
10538			name: "myapex.key",
10539			public_key: "testkey.avbpubkey",
10540			private_key: "testkey.pem",
10541		}
10542
10543		filegroup {
10544			name: "myapex.manifest",
10545			srcs: ["apex_manifest.json"],
10546		}
10547
10548		filegroup {
10549			name: "myapex.androidmanifest",
10550			srcs: ["AndroidManifest.xml"],
10551		}
10552`
10553
10554func TestAconfigFilesJavaDeps(t *testing.T) {
10555	t.Parallel()
10556	ctx := testApex(t, apex_default_bp+`
10557		apex {
10558			name: "myapex",
10559			manifest: ":myapex.manifest",
10560			androidManifest: ":myapex.androidmanifest",
10561			key: "myapex.key",
10562			java_libs: [
10563				"my_java_library_foo",
10564				"my_java_library_bar",
10565			],
10566			updatable: false,
10567		}
10568
10569		java_library {
10570			name: "my_java_library_foo",
10571			srcs: ["foo/bar/MyClass.java"],
10572			sdk_version: "none",
10573			system_modules: "none",
10574			static_libs: ["my_java_aconfig_library_foo"],
10575			apex_available: [
10576				"myapex",
10577			],
10578			compile_dex: true,
10579		}
10580
10581		java_library {
10582			name: "my_java_library_bar",
10583			srcs: ["foo/bar/MyClass.java"],
10584			sdk_version: "none",
10585			system_modules: "none",
10586			static_libs: ["my_java_aconfig_library_bar"],
10587			apex_available: [
10588				"myapex",
10589			],
10590			compile_dex: true,
10591		}
10592
10593		aconfig_declarations {
10594			name: "my_aconfig_declarations_foo",
10595			package: "com.example.package",
10596			container: "myapex",
10597			srcs: ["foo.aconfig"],
10598		}
10599
10600		java_aconfig_library {
10601			name: "my_java_aconfig_library_foo",
10602			aconfig_declarations: "my_aconfig_declarations_foo",
10603			apex_available: [
10604				"myapex",
10605			],
10606		}
10607
10608		aconfig_declarations {
10609			name: "my_aconfig_declarations_bar",
10610			package: "com.example.package",
10611			container: "myapex",
10612			srcs: ["bar.aconfig"],
10613		}
10614
10615		java_aconfig_library {
10616			name: "my_java_aconfig_library_bar",
10617			aconfig_declarations: "my_aconfig_declarations_bar",
10618			apex_available: [
10619				"myapex",
10620			],
10621		}
10622	`)
10623
10624	mod := ctx.ModuleForTests(t, "myapex", "android_common_myapex")
10625	s := mod.Rule("apexRule").Args["copy_commands"]
10626	copyCmds := regexp.MustCompile(" *&& *").Split(s, -1)
10627	if len(copyCmds) != 14 {
10628		t.Fatalf("Expected 14 commands, got %d in:\n%s", len(copyCmds), s)
10629	}
10630
10631	ensureListContainsMatch(t, copyCmds, "^cp -f .*/aconfig_flags.pb .*/image.apex/etc/aconfig_flags.pb")
10632	ensureListContainsMatch(t, copyCmds, "^cp -f .*/package.map .*/image.apex/etc/package.map")
10633	ensureListContainsMatch(t, copyCmds, "^cp -f .*/flag.map .*/image.apex/etc/flag.map")
10634	ensureListContainsMatch(t, copyCmds, "^cp -f .*/flag.val .*/image.apex/etc/flag.val")
10635	ensureListContainsMatch(t, copyCmds, "^cp -f .*/flag.info.*/image.apex/etc/flag.info")
10636
10637	inputs := []string{
10638		"my_aconfig_declarations_foo/intermediate.pb",
10639		"my_aconfig_declarations_bar/intermediate.pb",
10640	}
10641	VerifyAconfigRule(t, &mod, "combine_aconfig_declarations", inputs, "android_common_myapex/aconfig_flags.pb", "", "")
10642	VerifyAconfigRule(t, &mod, "create_aconfig_package_map_file", inputs, "android_common_myapex/package.map", "myapex", "package_map")
10643	VerifyAconfigRule(t, &mod, "create_aconfig_flag_map_file", inputs, "android_common_myapex/flag.map", "myapex", "flag_map")
10644	VerifyAconfigRule(t, &mod, "create_aconfig_flag_val_file", inputs, "android_common_myapex/flag.val", "myapex", "flag_val")
10645	VerifyAconfigRule(t, &mod, "create_aconfig_flag_info_file", inputs, "android_common_myapex/flag.info", "myapex", "flag_info")
10646}
10647
10648func TestAconfigFilesJavaAndCcDeps(t *testing.T) {
10649	t.Parallel()
10650	ctx := testApex(t, apex_default_bp+`
10651		apex {
10652			name: "myapex",
10653			manifest: ":myapex.manifest",
10654			androidManifest: ":myapex.androidmanifest",
10655			key: "myapex.key",
10656			java_libs: [
10657				"my_java_library_foo",
10658			],
10659			native_shared_libs: [
10660				"my_cc_library_bar",
10661			],
10662			binaries: [
10663				"my_cc_binary_baz",
10664			],
10665			updatable: false,
10666		}
10667
10668		java_library {
10669			name: "my_java_library_foo",
10670			srcs: ["foo/bar/MyClass.java"],
10671			sdk_version: "none",
10672			system_modules: "none",
10673			static_libs: ["my_java_aconfig_library_foo"],
10674			apex_available: [
10675				"myapex",
10676			],
10677			compile_dex: true,
10678		}
10679
10680		cc_library {
10681			name: "my_cc_library_bar",
10682			srcs: ["foo/bar/MyClass.cc"],
10683			static_libs: [
10684				"my_cc_aconfig_library_bar",
10685				"my_cc_aconfig_library_baz",
10686			],
10687			apex_available: [
10688				"myapex",
10689			],
10690		}
10691
10692		cc_binary {
10693			name: "my_cc_binary_baz",
10694			srcs: ["foo/bar/MyClass.cc"],
10695			static_libs: ["my_cc_aconfig_library_baz"],
10696			apex_available: [
10697				"myapex",
10698			],
10699		}
10700
10701		aconfig_declarations {
10702			name: "my_aconfig_declarations_foo",
10703			package: "com.example.package",
10704			container: "myapex",
10705			srcs: ["foo.aconfig"],
10706		}
10707
10708		java_aconfig_library {
10709			name: "my_java_aconfig_library_foo",
10710			aconfig_declarations: "my_aconfig_declarations_foo",
10711			apex_available: [
10712				"myapex",
10713			],
10714		}
10715
10716		aconfig_declarations {
10717			name: "my_aconfig_declarations_bar",
10718			package: "com.example.package",
10719			container: "myapex",
10720			srcs: ["bar.aconfig"],
10721		}
10722
10723		cc_aconfig_library {
10724			name: "my_cc_aconfig_library_bar",
10725			aconfig_declarations: "my_aconfig_declarations_bar",
10726			apex_available: [
10727				"myapex",
10728			],
10729		}
10730
10731		aconfig_declarations {
10732			name: "my_aconfig_declarations_baz",
10733			package: "com.example.package",
10734			container: "myapex",
10735			srcs: ["baz.aconfig"],
10736		}
10737
10738		cc_aconfig_library {
10739			name: "my_cc_aconfig_library_baz",
10740			aconfig_declarations: "my_aconfig_declarations_baz",
10741			apex_available: [
10742				"myapex",
10743			],
10744		}
10745
10746		cc_library {
10747			name: "server_configurable_flags",
10748			srcs: ["server_configurable_flags.cc"],
10749		}
10750		cc_library {
10751			name: "libbase",
10752			srcs: ["libbase.cc"],
10753			apex_available: [
10754				"myapex",
10755			],
10756		}
10757		cc_library {
10758			name: "libaconfig_storage_read_api_cc",
10759			srcs: ["libaconfig_storage_read_api_cc.cc"],
10760		}
10761	`)
10762
10763	mod := ctx.ModuleForTests(t, "myapex", "android_common_myapex")
10764	s := mod.Rule("apexRule").Args["copy_commands"]
10765	copyCmds := regexp.MustCompile(" *&& *").Split(s, -1)
10766	if len(copyCmds) != 18 {
10767		t.Fatalf("Expected 18 commands, got %d in:\n%s", len(copyCmds), s)
10768	}
10769
10770	ensureListContainsMatch(t, copyCmds, "^cp -f .*/aconfig_flags.pb .*/image.apex/etc/aconfig_flags.pb")
10771	ensureListContainsMatch(t, copyCmds, "^cp -f .*/package.map .*/image.apex/etc/package.map")
10772	ensureListContainsMatch(t, copyCmds, "^cp -f .*/flag.map .*/image.apex/etc/flag.map")
10773	ensureListContainsMatch(t, copyCmds, "^cp -f .*/flag.val .*/image.apex/etc/flag.val")
10774	ensureListContainsMatch(t, copyCmds, "^cp -f .*/flag.info .*/image.apex/etc/flag.info")
10775
10776	inputs := []string{
10777		"my_aconfig_declarations_foo/intermediate.pb",
10778		"my_cc_library_bar/android_arm64_armv8-a_shared_apex10000/myapex/aconfig_merged.pb",
10779		"my_aconfig_declarations_baz/intermediate.pb",
10780	}
10781	VerifyAconfigRule(t, &mod, "combine_aconfig_declarations", inputs, "android_common_myapex/aconfig_flags.pb", "", "")
10782	VerifyAconfigRule(t, &mod, "create_aconfig_package_map_file", inputs, "android_common_myapex/package.map", "myapex", "package_map")
10783	VerifyAconfigRule(t, &mod, "create_aconfig_flag_map_file", inputs, "android_common_myapex/flag.map", "myapex", "flag_map")
10784	VerifyAconfigRule(t, &mod, "create_aconfig_flag_val_file", inputs, "android_common_myapex/flag.val", "myapex", "flag_val")
10785	VerifyAconfigRule(t, &mod, "create_aconfig_flag_info_file", inputs, "android_common_myapex/flag.info", "myapex", "flag_info")
10786}
10787
10788func TestAconfigFilesRustDeps(t *testing.T) {
10789	t.Parallel()
10790	ctx := testApex(t, apex_default_bp+`
10791		apex {
10792			name: "myapex",
10793			manifest: ":myapex.manifest",
10794			androidManifest: ":myapex.androidmanifest",
10795			key: "myapex.key",
10796			native_shared_libs: [
10797				"libmy_rust_library",
10798			],
10799			binaries: [
10800				"my_rust_binary",
10801			],
10802			rust_dyn_libs: [
10803				"libmy_rust_dylib",
10804			],
10805			updatable: false,
10806		}
10807
10808		rust_library {
10809			name: "liblazy_static", // test mock
10810			crate_name: "lazy_static",
10811			srcs: ["src/lib.rs"],
10812			apex_available: [
10813				"myapex",
10814			],
10815		}
10816
10817		rust_library {
10818			name: "libaconfig_storage_read_api", // test mock
10819			crate_name: "aconfig_storage_read_api",
10820			srcs: ["src/lib.rs"],
10821			apex_available: [
10822				"myapex",
10823			],
10824		}
10825
10826		rust_library {
10827			name: "liblogger", // test mock
10828			crate_name: "logger",
10829			srcs: ["src/lib.rs"],
10830			apex_available: [
10831				"myapex",
10832			],
10833		}
10834
10835		rust_library {
10836			name: "liblog_rust", // test mock
10837			crate_name: "log_rust",
10838			srcs: ["src/lib.rs"],
10839			apex_available: [
10840				"myapex",
10841			],
10842		}
10843
10844		rust_ffi_shared {
10845			name: "libmy_rust_library",
10846			srcs: ["src/lib.rs"],
10847			rustlibs: ["libmy_rust_aconfig_library_foo"],
10848			crate_name: "my_rust_library",
10849			apex_available: [
10850				"myapex",
10851			],
10852		}
10853
10854		rust_library_dylib {
10855			name: "libmy_rust_dylib",
10856			srcs: ["foo/bar/MyClass.rs"],
10857			rustlibs: ["libmy_rust_aconfig_library_bar"],
10858			crate_name: "my_rust_dylib",
10859			apex_available: [
10860				"myapex",
10861			],
10862		}
10863
10864		rust_binary {
10865			name: "my_rust_binary",
10866			srcs: ["foo/bar/MyClass.rs"],
10867			rustlibs: [
10868				"libmy_rust_aconfig_library_baz",
10869				"libmy_rust_dylib",
10870			],
10871			apex_available: [
10872				"myapex",
10873			],
10874		}
10875
10876		aconfig_declarations {
10877			name: "my_aconfig_declarations_foo",
10878			package: "com.example.package",
10879			container: "myapex",
10880			srcs: ["foo.aconfig"],
10881		}
10882
10883		aconfig_declarations {
10884			name: "my_aconfig_declarations_bar",
10885			package: "com.example.package",
10886			container: "myapex",
10887			srcs: ["bar.aconfig"],
10888		}
10889
10890		aconfig_declarations {
10891			name: "my_aconfig_declarations_baz",
10892			package: "com.example.package",
10893			container: "myapex",
10894			srcs: ["baz.aconfig"],
10895		}
10896
10897		rust_aconfig_library {
10898			name: "libmy_rust_aconfig_library_foo",
10899			aconfig_declarations: "my_aconfig_declarations_foo",
10900			crate_name: "my_rust_aconfig_library_foo",
10901			apex_available: [
10902				"myapex",
10903			],
10904		}
10905
10906		rust_aconfig_library {
10907			name: "libmy_rust_aconfig_library_bar",
10908			aconfig_declarations: "my_aconfig_declarations_bar",
10909			crate_name: "my_rust_aconfig_library_bar",
10910			apex_available: [
10911				"myapex",
10912			],
10913		}
10914
10915		rust_aconfig_library {
10916			name: "libmy_rust_aconfig_library_baz",
10917			aconfig_declarations: "my_aconfig_declarations_baz",
10918			crate_name: "my_rust_aconfig_library_baz",
10919			apex_available: [
10920				"myapex",
10921			],
10922		}
10923	`)
10924
10925	mod := ctx.ModuleForTests(t, "myapex", "android_common_myapex")
10926	s := mod.Rule("apexRule").Args["copy_commands"]
10927	copyCmds := regexp.MustCompile(" *&& *").Split(s, -1)
10928	if len(copyCmds) != 32 {
10929		t.Fatalf("Expected 32 commands, got %d in:\n%s", len(copyCmds), s)
10930	}
10931
10932	ensureListContainsMatch(t, copyCmds, "^cp -f .*/aconfig_flags.pb .*/image.apex/etc/aconfig_flags.pb")
10933	ensureListContainsMatch(t, copyCmds, "^cp -f .*/package.map .*/image.apex/etc/package.map")
10934	ensureListContainsMatch(t, copyCmds, "^cp -f .*/flag.map .*/image.apex/etc/flag.map")
10935	ensureListContainsMatch(t, copyCmds, "^cp -f .*/flag.val .*/image.apex/etc/flag.val")
10936	ensureListContainsMatch(t, copyCmds, "^cp -f .*/flag.info .*/image.apex/etc/flag.info")
10937
10938	inputs := []string{
10939		"my_aconfig_declarations_foo/intermediate.pb",
10940		"my_aconfig_declarations_bar/intermediate.pb",
10941		"my_aconfig_declarations_baz/intermediate.pb",
10942		"my_rust_binary/android_arm64_armv8-a_apex10000/myapex/aconfig_merged.pb",
10943	}
10944	VerifyAconfigRule(t, &mod, "combine_aconfig_declarations", inputs, "android_common_myapex/aconfig_flags.pb", "", "")
10945	VerifyAconfigRule(t, &mod, "create_aconfig_package_map_file", inputs, "android_common_myapex/package.map", "myapex", "package_map")
10946	VerifyAconfigRule(t, &mod, "create_aconfig_flag_map_file", inputs, "android_common_myapex/flag.map", "myapex", "flag_map")
10947	VerifyAconfigRule(t, &mod, "create_aconfig_flag_val_file", inputs, "android_common_myapex/flag.val", "myapex", "flag_val")
10948	VerifyAconfigRule(t, &mod, "create_aconfig_flag_info_file", inputs, "android_common_myapex/flag.info", "myapex", "flag_info")
10949}
10950
10951func VerifyAconfigRule(t *testing.T, mod *android.TestingModule, desc string, inputs []string, output string, container string, file_type string) {
10952	aconfigRule := mod.Description(desc)
10953	s := " " + aconfigRule.Args["cache_files"]
10954	aconfigArgs := regexp.MustCompile(" --cache ").Split(s, -1)[1:]
10955	if len(aconfigArgs) != len(inputs) {
10956		t.Fatalf("Expected %d commands, got %d in:\n%s", len(inputs), len(aconfigArgs), s)
10957	}
10958
10959	ensureEquals(t, container, aconfigRule.Args["container"])
10960	ensureEquals(t, file_type, aconfigRule.Args["file_type"])
10961
10962	buildParams := aconfigRule.BuildParams
10963	for _, input := range inputs {
10964		android.EnsureListContainsSuffix(t, aconfigArgs, input)
10965		android.EnsureListContainsSuffix(t, buildParams.Inputs.Strings(), input)
10966	}
10967
10968	ensureContains(t, buildParams.Output.String(), output)
10969}
10970
10971func TestAconfigFilesOnlyMatchCurrentApex(t *testing.T) {
10972	t.Parallel()
10973	ctx := testApex(t, apex_default_bp+`
10974		apex {
10975			name: "myapex",
10976			manifest: ":myapex.manifest",
10977			androidManifest: ":myapex.androidmanifest",
10978			key: "myapex.key",
10979			java_libs: [
10980				"my_java_library_foo",
10981				"other_java_library_bar",
10982			],
10983			updatable: false,
10984		}
10985
10986		java_library {
10987			name: "my_java_library_foo",
10988			srcs: ["foo/bar/MyClass.java"],
10989			sdk_version: "none",
10990			system_modules: "none",
10991			static_libs: ["my_java_aconfig_library_foo"],
10992			apex_available: [
10993				"myapex",
10994			],
10995			compile_dex: true,
10996		}
10997
10998		java_library {
10999			name: "other_java_library_bar",
11000			srcs: ["foo/bar/MyClass.java"],
11001			sdk_version: "none",
11002			system_modules: "none",
11003			static_libs: ["other_java_aconfig_library_bar"],
11004			apex_available: [
11005				"myapex",
11006			],
11007			compile_dex: true,
11008		}
11009
11010		aconfig_declarations {
11011			name: "my_aconfig_declarations_foo",
11012			package: "com.example.package",
11013			container: "myapex",
11014			srcs: ["foo.aconfig"],
11015		}
11016
11017		java_aconfig_library {
11018			name: "my_java_aconfig_library_foo",
11019			aconfig_declarations: "my_aconfig_declarations_foo",
11020			apex_available: [
11021				"myapex",
11022			],
11023		}
11024
11025		aconfig_declarations {
11026			name: "other_aconfig_declarations_bar",
11027			package: "com.example.package",
11028			container: "otherapex",
11029			srcs: ["bar.aconfig"],
11030		}
11031
11032		java_aconfig_library {
11033			name: "other_java_aconfig_library_bar",
11034			aconfig_declarations: "other_aconfig_declarations_bar",
11035			apex_available: [
11036				"myapex",
11037			],
11038		}
11039	`)
11040
11041	mod := ctx.ModuleForTests(t, "myapex", "android_common_myapex")
11042	combineAconfigRule := mod.Rule("All_aconfig_declarations_dump")
11043	s := " " + combineAconfigRule.Args["cache_files"]
11044	aconfigArgs := regexp.MustCompile(" --cache ").Split(s, -1)[1:]
11045	if len(aconfigArgs) != 1 {
11046		t.Fatalf("Expected 1 commands, got %d in:\n%s", len(aconfigArgs), s)
11047	}
11048	android.EnsureListContainsSuffix(t, aconfigArgs, "my_aconfig_declarations_foo/intermediate.pb")
11049
11050	buildParams := combineAconfigRule.BuildParams
11051	if len(buildParams.Inputs) != 1 {
11052		t.Fatalf("Expected 1 input, got %d", len(buildParams.Inputs))
11053	}
11054	android.EnsureListContainsSuffix(t, buildParams.Inputs.Strings(), "my_aconfig_declarations_foo/intermediate.pb")
11055	ensureContains(t, buildParams.Output.String(), "android_common_myapex/aconfig_flags.pb")
11056}
11057
11058func TestAconfigFilesRemoveDuplicates(t *testing.T) {
11059	t.Parallel()
11060	ctx := testApex(t, apex_default_bp+`
11061		apex {
11062			name: "myapex",
11063			manifest: ":myapex.manifest",
11064			androidManifest: ":myapex.androidmanifest",
11065			key: "myapex.key",
11066			java_libs: [
11067				"my_java_library_foo",
11068				"my_java_library_bar",
11069			],
11070			updatable: false,
11071		}
11072
11073		java_library {
11074			name: "my_java_library_foo",
11075			srcs: ["foo/bar/MyClass.java"],
11076			sdk_version: "none",
11077			system_modules: "none",
11078			static_libs: ["my_java_aconfig_library_foo"],
11079			apex_available: [
11080				"myapex",
11081			],
11082			compile_dex: true,
11083		}
11084
11085		java_library {
11086			name: "my_java_library_bar",
11087			srcs: ["foo/bar/MyClass.java"],
11088			sdk_version: "none",
11089			system_modules: "none",
11090			static_libs: ["my_java_aconfig_library_bar"],
11091			apex_available: [
11092				"myapex",
11093			],
11094			compile_dex: true,
11095		}
11096
11097		aconfig_declarations {
11098			name: "my_aconfig_declarations_foo",
11099			package: "com.example.package",
11100			container: "myapex",
11101			srcs: ["foo.aconfig"],
11102		}
11103
11104		java_aconfig_library {
11105			name: "my_java_aconfig_library_foo",
11106			aconfig_declarations: "my_aconfig_declarations_foo",
11107			apex_available: [
11108				"myapex",
11109			],
11110		}
11111
11112		java_aconfig_library {
11113			name: "my_java_aconfig_library_bar",
11114			aconfig_declarations: "my_aconfig_declarations_foo",
11115			apex_available: [
11116				"myapex",
11117			],
11118		}
11119	`)
11120
11121	mod := ctx.ModuleForTests(t, "myapex", "android_common_myapex")
11122	combineAconfigRule := mod.Rule("All_aconfig_declarations_dump")
11123	s := " " + combineAconfigRule.Args["cache_files"]
11124	aconfigArgs := regexp.MustCompile(" --cache ").Split(s, -1)[1:]
11125	if len(aconfigArgs) != 1 {
11126		t.Fatalf("Expected 1 commands, got %d in:\n%s", len(aconfigArgs), s)
11127	}
11128	android.EnsureListContainsSuffix(t, aconfigArgs, "my_aconfig_declarations_foo/intermediate.pb")
11129
11130	buildParams := combineAconfigRule.BuildParams
11131	if len(buildParams.Inputs) != 1 {
11132		t.Fatalf("Expected 1 input, got %d", len(buildParams.Inputs))
11133	}
11134	android.EnsureListContainsSuffix(t, buildParams.Inputs.Strings(), "my_aconfig_declarations_foo/intermediate.pb")
11135	ensureContains(t, buildParams.Output.String(), "android_common_myapex/aconfig_flags.pb")
11136}
11137
11138// Test that the boot jars come from the _selected_ apex prebuilt
11139// RELEASE_APEX_CONTIRBUTIONS_* build flags will be used to select the correct prebuilt for a specific release config
11140func TestBootDexJarsMultipleApexPrebuilts(t *testing.T) {
11141	t.Parallel()
11142	checkBootDexJarPath := func(t *testing.T, ctx *android.TestContext, stem string, bootDexJarPath string) {
11143		t.Helper()
11144		s := ctx.ModuleForTests(t, "dex_bootjars", "android_common")
11145		foundLibfooJar := false
11146		base := stem + ".jar"
11147		for _, output := range s.AllOutputs() {
11148			if filepath.Base(output) == base {
11149				foundLibfooJar = true
11150				buildRule := s.Output(output)
11151				android.AssertStringEquals(t, "boot dex jar path", bootDexJarPath, buildRule.Input.String())
11152			}
11153		}
11154		if !foundLibfooJar {
11155			t.Errorf("Rule for libfoo.jar missing in dex_bootjars singleton outputs %q", android.StringPathsRelativeToTop(ctx.Config().SoongOutDir(), s.AllOutputs()))
11156		}
11157	}
11158
11159	// Check that the boot jars of the selected apex are run through boot_jars_package_check
11160	// This validates that the jars on the bootclasspath do not contain packages outside an allowlist
11161	checkBootJarsPackageCheck := func(t *testing.T, ctx *android.TestContext, expectedBootJar string) {
11162		platformBcp := ctx.ModuleForTests(t, "platform-bootclasspath", "android_common")
11163		bootJarsCheckRule := platformBcp.Rule("boot_jars_package_check")
11164		android.AssertStringMatches(t, "Could not find the correct boot dex jar in package check rule", bootJarsCheckRule.RuleParams.Command, "build/soong/scripts/check_boot_jars/package_allowed_list.txt.*"+expectedBootJar)
11165	}
11166
11167	// Check that the boot jars used to generate the monolithic hiddenapi flags come from the selected apex
11168	checkBootJarsForMonolithicHiddenapi := func(t *testing.T, ctx *android.TestContext, expectedBootJar string) {
11169		monolithicHiddenapiFlagsCmd := ctx.ModuleForTests(t, "platform-bootclasspath", "android_common").Output("out/soong/hiddenapi/hiddenapi-stub-flags.txt").RuleParams.Command
11170		android.AssertStringMatches(t, "Could not find the correct boot dex jar in monolithic hiddenapi flags generation command", monolithicHiddenapiFlagsCmd, "--boot-dex="+expectedBootJar)
11171	}
11172
11173	bp := `
11174		// Source APEX.
11175
11176		java_library {
11177			name: "framework-foo",
11178			srcs: ["foo.java"],
11179			installable: true,
11180			apex_available: [
11181				"com.android.foo",
11182			],
11183		}
11184
11185		bootclasspath_fragment {
11186			name: "foo-bootclasspath-fragment",
11187			contents: ["framework-foo"],
11188			apex_available: [
11189				"com.android.foo",
11190			],
11191			hidden_api: {
11192				split_packages: ["*"],
11193			},
11194		}
11195
11196		apex_key {
11197			name: "com.android.foo.key",
11198			public_key: "com.android.foo.avbpubkey",
11199			private_key: "com.android.foo.pem",
11200		}
11201
11202		apex {
11203			name: "com.android.foo",
11204			key: "com.android.foo.key",
11205			bootclasspath_fragments: ["foo-bootclasspath-fragment"],
11206			updatable: false,
11207		}
11208
11209		// Prebuilt APEX.
11210
11211		java_sdk_library_import {
11212			name: "framework-foo",
11213			public: {
11214				jars: ["foo.jar"],
11215			},
11216			apex_available: ["com.android.foo"],
11217			shared_library: false,
11218		}
11219
11220		prebuilt_bootclasspath_fragment {
11221			name: "foo-bootclasspath-fragment",
11222			contents: ["framework-foo"],
11223			hidden_api: {
11224				annotation_flags: "my-bootclasspath-fragment/annotation-flags.csv",
11225				metadata: "my-bootclasspath-fragment/metadata.csv",
11226				index: "my-bootclasspath-fragment/index.csv",
11227				stub_flags: "my-bootclasspath-fragment/stub-flags.csv",
11228				all_flags: "my-bootclasspath-fragment/all-flags.csv",
11229			},
11230			apex_available: [
11231				"com.android.foo",
11232			],
11233		}
11234
11235		prebuilt_apex {
11236			name: "com.android.foo",
11237			apex_name: "com.android.foo",
11238			src: "com.android.foo-arm.apex",
11239			exported_bootclasspath_fragments: ["foo-bootclasspath-fragment"],
11240		}
11241
11242		// Another Prebuilt ART APEX
11243		prebuilt_apex {
11244			name: "com.android.foo.v2",
11245			apex_name: "com.android.foo", // Used to determine the API domain
11246			src: "com.android.foo-arm.apex",
11247			exported_bootclasspath_fragments: ["foo-bootclasspath-fragment"],
11248		}
11249
11250		// APEX contribution modules
11251
11252		apex_contributions {
11253			name: "foo.source.contributions",
11254			api_domain: "com.android.foo",
11255			contents: ["com.android.foo"],
11256		}
11257
11258		apex_contributions {
11259			name: "foo.prebuilt.contributions",
11260			api_domain: "com.android.foo",
11261			contents: ["prebuilt_com.android.foo"],
11262		}
11263
11264		apex_contributions {
11265			name: "foo.prebuilt.v2.contributions",
11266			api_domain: "com.android.foo",
11267			contents: ["com.android.foo.v2"], // prebuilt_ prefix is missing because of prebuilt_rename mutator
11268		}
11269	`
11270
11271	testCases := []struct {
11272		desc                      string
11273		selectedApexContributions string
11274		expectedBootJar           string
11275	}{
11276		{
11277			desc:                      "Source apex com.android.foo is selected, bootjar should come from source java library",
11278			selectedApexContributions: "foo.source.contributions",
11279			expectedBootJar:           "out/soong/.intermediates/foo-bootclasspath-fragment/android_common_com.android.foo/hiddenapi-modular/encoded/framework-foo.jar",
11280		},
11281		{
11282			desc:                      "Prebuilt apex prebuilt_com.android.foo is selected, profile should come from .prof deapexed from the prebuilt",
11283			selectedApexContributions: "foo.prebuilt.contributions",
11284			expectedBootJar:           "out/soong/.intermediates/prebuilt_com.android.foo/android_common_prebuilt_com.android.foo/deapexer/javalib/framework-foo.jar",
11285		},
11286		{
11287			desc:                      "Prebuilt apex prebuilt_com.android.foo.v2 is selected, profile should come from .prof deapexed from the prebuilt",
11288			selectedApexContributions: "foo.prebuilt.v2.contributions",
11289			expectedBootJar:           "out/soong/.intermediates/com.android.foo.v2/android_common_prebuilt_com.android.foo/deapexer/javalib/framework-foo.jar",
11290		},
11291	}
11292
11293	fragment := java.ApexVariantReference{
11294		Apex:   proptools.StringPtr("com.android.foo"),
11295		Module: proptools.StringPtr("foo-bootclasspath-fragment"),
11296	}
11297
11298	for _, tc := range testCases {
11299		preparer := android.GroupFixturePreparers(
11300			java.FixtureConfigureApexBootJars("com.android.foo:framework-foo"),
11301			android.FixtureMergeMockFs(map[string][]byte{
11302				"system/sepolicy/apex/com.android.foo-file_contexts": nil,
11303			}),
11304			// Make sure that we have atleast one platform library so that we can check the monolithic hiddenapi
11305			// file creation.
11306			java.FixtureConfigureBootJars("platform:foo"),
11307			android.FixtureModifyMockFS(func(fs android.MockFS) {
11308				fs["platform/Android.bp"] = []byte(`
11309		java_library {
11310			name: "foo",
11311			srcs: ["Test.java"],
11312			compile_dex: true,
11313		}
11314		`)
11315				fs["platform/Test.java"] = nil
11316			}),
11317
11318			android.PrepareForTestWithBuildFlag("RELEASE_APEX_CONTRIBUTIONS_ADSERVICES", tc.selectedApexContributions),
11319		)
11320		ctx := testDexpreoptWithApexes(t, bp, "", preparer, fragment)
11321		checkBootDexJarPath(t, ctx, "framework-foo", tc.expectedBootJar)
11322		checkBootJarsPackageCheck(t, ctx, tc.expectedBootJar)
11323		checkBootJarsForMonolithicHiddenapi(t, ctx, tc.expectedBootJar)
11324	}
11325}
11326
11327// Test that product packaging installs the selected mainline module (either source or a specific prebuilt)
11328// RELEASE_APEX_CONTIRBUTIONS_* build flags will be used to select the correct prebuilt for a specific release config
11329func TestInstallationRulesForMultipleApexPrebuilts(t *testing.T) {
11330	t.Parallel()
11331	// for a mainline module family, check that only the flagged soong module is visible to make
11332	checkHideFromMake := func(t *testing.T, ctx *android.TestContext, visibleModuleName string, hiddenModuleNames []string) {
11333		variation := func(moduleName string) string {
11334			ret := "android_common_prebuilt_com.android.foo"
11335			if moduleName == "com.google.android.foo" {
11336				ret = "android_common_com.google.android.foo"
11337			}
11338			return ret
11339		}
11340
11341		visibleModule := ctx.ModuleForTests(t, visibleModuleName, variation(visibleModuleName)).Module()
11342		android.AssertBoolEquals(t, "Apex "+visibleModuleName+" selected using apex_contributions should be visible to make", false, visibleModule.IsHideFromMake())
11343
11344		for _, hiddenModuleName := range hiddenModuleNames {
11345			hiddenModule := ctx.ModuleForTests(t, hiddenModuleName, variation(hiddenModuleName)).Module()
11346			android.AssertBoolEquals(t, "Apex "+hiddenModuleName+" not selected using apex_contributions should be hidden from make", true, hiddenModule.IsHideFromMake())
11347
11348		}
11349	}
11350
11351	bp := `
11352		apex_key {
11353			name: "com.android.foo.key",
11354			public_key: "com.android.foo.avbpubkey",
11355			private_key: "com.android.foo.pem",
11356		}
11357
11358		// AOSP source apex
11359		apex {
11360			name: "com.android.foo",
11361			key: "com.android.foo.key",
11362			updatable: false,
11363		}
11364
11365		// Google source apex
11366		override_apex {
11367			name: "com.google.android.foo",
11368			base: "com.android.foo",
11369			key: "com.android.foo.key",
11370		}
11371
11372		// Prebuilt Google APEX.
11373
11374		prebuilt_apex {
11375			name: "com.google.android.foo",
11376			apex_name: "com.android.foo",
11377			src: "com.android.foo-arm.apex",
11378			prefer: true, // prefer is set to true on both the prebuilts to induce an error if flagging is not present
11379		}
11380
11381		// Another Prebuilt Google APEX
11382		prebuilt_apex {
11383			name: "com.google.android.foo.v2",
11384			apex_name: "com.android.foo",
11385			source_apex_name: "com.google.android.foo",
11386			src: "com.android.foo-arm.apex",
11387			prefer: true, // prefer is set to true on both the prebuilts to induce an error if flagging is not present
11388		}
11389
11390		// APEX contribution modules
11391
11392		apex_contributions {
11393			name: "foo.source.contributions",
11394			api_domain: "com.android.foo",
11395			contents: ["com.google.android.foo"],
11396		}
11397
11398		apex_contributions {
11399			name: "foo.prebuilt.contributions",
11400			api_domain: "com.android.foo",
11401			contents: ["prebuilt_com.google.android.foo"],
11402		}
11403
11404		apex_contributions {
11405			name: "foo.prebuilt.v2.contributions",
11406			api_domain: "com.android.foo",
11407			contents: ["prebuilt_com.google.android.foo.v2"],
11408		}
11409
11410		// This is an incompatible module because it selects multiple versions of the same mainline module
11411		apex_contributions {
11412			name: "foo.prebuilt.duplicate.contributions",
11413			api_domain: "com.android.foo",
11414			contents: [
11415			    "prebuilt_com.google.android.foo",
11416			    "prebuilt_com.google.android.foo.v2",
11417			],
11418		}
11419	`
11420
11421	testCases := []struct {
11422		desc                      string
11423		selectedApexContributions string
11424		expectedVisibleModuleName string
11425		expectedHiddenModuleNames []string
11426		expectedError             string
11427	}{
11428		{
11429			desc:                      "Source apex is selected, prebuilts should be hidden from make",
11430			selectedApexContributions: "foo.source.contributions",
11431			expectedVisibleModuleName: "com.google.android.foo",
11432			expectedHiddenModuleNames: []string{"prebuilt_com.google.android.foo", "prebuilt_com.google.android.foo.v2"},
11433		},
11434		{
11435			desc:                      "Prebuilt apex prebuilt_com.android.foo is selected, source and the other prebuilt should be hidden from make",
11436			selectedApexContributions: "foo.prebuilt.contributions",
11437			expectedVisibleModuleName: "prebuilt_com.google.android.foo",
11438			expectedHiddenModuleNames: []string{"com.google.android.foo", "prebuilt_com.google.android.foo.v2"},
11439		},
11440		{
11441			desc:                      "Prebuilt apex prebuilt_com.android.fooi.v2 is selected, source and the other prebuilt should be hidden from make",
11442			selectedApexContributions: "foo.prebuilt.v2.contributions",
11443			expectedVisibleModuleName: "prebuilt_com.google.android.foo.v2",
11444			expectedHiddenModuleNames: []string{"com.google.android.foo", "prebuilt_com.google.android.foo"},
11445		},
11446		{
11447			desc:                      "Multiple versions of a prebuilt apex is selected in the same release config",
11448			selectedApexContributions: "foo.prebuilt.duplicate.contributions",
11449			expectedError:             "Found duplicate variations of the same module in apex_contributions: prebuilt_com.google.android.foo and prebuilt_com.google.android.foo.v2",
11450		},
11451	}
11452
11453	for _, tc := range testCases {
11454		preparer := android.GroupFixturePreparers(
11455			android.FixtureMergeMockFs(map[string][]byte{
11456				"system/sepolicy/apex/com.android.foo-file_contexts": nil,
11457			}),
11458			android.PrepareForTestWithBuildFlag("RELEASE_APEX_CONTRIBUTIONS_ADSERVICES", tc.selectedApexContributions),
11459		)
11460		if tc.expectedError != "" {
11461			preparer = preparer.ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern(tc.expectedError))
11462			testApex(t, bp, preparer)
11463			return
11464		}
11465		ctx := testApex(t, bp, preparer)
11466
11467		// Check that
11468		// 1. The contents of the selected apex_contributions are visible to make
11469		// 2. The rest of the apexes in the mainline module family (source or other prebuilt) is hidden from make
11470		checkHideFromMake(t, ctx, tc.expectedVisibleModuleName, tc.expectedHiddenModuleNames)
11471
11472		// Check that source_apex_name is written as LOCAL_MODULE for make packaging
11473		if tc.expectedVisibleModuleName == "prebuilt_com.google.android.foo.v2" {
11474			apex := ctx.ModuleForTests(t, "prebuilt_com.google.android.foo.v2", "android_common_prebuilt_com.android.foo").Module()
11475			entries := android.AndroidMkEntriesForTest(t, ctx, apex)[0]
11476
11477			expected := "com.google.android.foo"
11478			actual := entries.EntryMap["LOCAL_MODULE"][0]
11479			android.AssertStringEquals(t, "LOCAL_MODULE", expected, actual)
11480		}
11481	}
11482}
11483
11484// Test that product packaging installs the selected mainline module in workspaces withtout source mainline module
11485func TestInstallationRulesForMultipleApexPrebuiltsWithoutSource(t *testing.T) {
11486	t.Parallel()
11487	// for a mainline module family, check that only the flagged soong module is visible to make
11488	checkHideFromMake := func(t *testing.T, ctx *android.TestContext, visibleModuleNames []string, hiddenModuleNames []string) {
11489		variation := func(moduleName string) string {
11490			ret := "android_common_com.android.adservices"
11491			if moduleName == "com.google.android.adservices" || moduleName == "com.google.android.adservices.v2" {
11492				ret = "android_common_prebuilt_com.android.adservices"
11493			}
11494			return ret
11495		}
11496
11497		for _, visibleModuleName := range visibleModuleNames {
11498			visibleModule := ctx.ModuleForTests(t, visibleModuleName, variation(visibleModuleName)).Module()
11499			android.AssertBoolEquals(t, "Apex "+visibleModuleName+" selected using apex_contributions should be visible to make", false, visibleModule.IsHideFromMake())
11500		}
11501
11502		for _, hiddenModuleName := range hiddenModuleNames {
11503			hiddenModule := ctx.ModuleForTests(t, hiddenModuleName, variation(hiddenModuleName)).Module()
11504			android.AssertBoolEquals(t, "Apex "+hiddenModuleName+" not selected using apex_contributions should be hidden from make", true, hiddenModule.IsHideFromMake())
11505
11506		}
11507	}
11508
11509	bp := `
11510		apex_key {
11511			name: "com.android.adservices.key",
11512			public_key: "com.android.adservices.avbpubkey",
11513			private_key: "com.android.adservices.pem",
11514		}
11515
11516		// AOSP source apex
11517		apex {
11518			name: "com.android.adservices",
11519			key: "com.android.adservices.key",
11520			updatable: false,
11521		}
11522
11523		// Prebuilt Google APEX.
11524
11525		prebuilt_apex {
11526			name: "com.google.android.adservices",
11527			apex_name: "com.android.adservices",
11528			src: "com.android.foo-arm.apex",
11529		}
11530
11531		// Another Prebuilt Google APEX
11532		prebuilt_apex {
11533			name: "com.google.android.adservices.v2",
11534			apex_name: "com.android.adservices",
11535			src: "com.android.foo-arm.apex",
11536		}
11537
11538		// APEX contribution modules
11539
11540
11541		apex_contributions {
11542			name: "adservices.prebuilt.contributions",
11543			api_domain: "com.android.adservices",
11544			contents: ["prebuilt_com.google.android.adservices"],
11545		}
11546
11547		apex_contributions {
11548			name: "adservices.prebuilt.v2.contributions",
11549			api_domain: "com.android.adservices",
11550			contents: ["prebuilt_com.google.android.adservices.v2"],
11551		}
11552	`
11553
11554	testCases := []struct {
11555		desc                       string
11556		selectedApexContributions  string
11557		expectedVisibleModuleNames []string
11558		expectedHiddenModuleNames  []string
11559	}{
11560		{
11561			desc:                       "No apex contributions selected, source aosp apex should be visible, and mainline prebuilts should be hidden",
11562			selectedApexContributions:  "",
11563			expectedVisibleModuleNames: []string{"com.android.adservices"},
11564			expectedHiddenModuleNames:  []string{"com.google.android.adservices", "com.google.android.adservices.v2"},
11565		},
11566		{
11567			desc:                       "Prebuilt apex prebuilt_com.android.adservices is selected",
11568			selectedApexContributions:  "adservices.prebuilt.contributions",
11569			expectedVisibleModuleNames: []string{"com.android.adservices", "com.google.android.adservices"},
11570			expectedHiddenModuleNames:  []string{"com.google.android.adservices.v2"},
11571		},
11572		{
11573			desc:                       "Prebuilt apex prebuilt_com.android.adservices.v2 is selected",
11574			selectedApexContributions:  "adservices.prebuilt.v2.contributions",
11575			expectedVisibleModuleNames: []string{"com.android.adservices", "com.google.android.adservices.v2"},
11576			expectedHiddenModuleNames:  []string{"com.google.android.adservices"},
11577		},
11578	}
11579
11580	for _, tc := range testCases {
11581		preparer := android.GroupFixturePreparers(
11582			android.FixtureMergeMockFs(map[string][]byte{
11583				"system/sepolicy/apex/com.android.adservices-file_contexts": nil,
11584			}),
11585			android.PrepareForTestWithBuildFlag("RELEASE_APEX_CONTRIBUTIONS_ADSERVICES", tc.selectedApexContributions),
11586		)
11587		ctx := testApex(t, bp, preparer)
11588
11589		checkHideFromMake(t, ctx, tc.expectedVisibleModuleNames, tc.expectedHiddenModuleNames)
11590	}
11591}
11592
11593func TestAconfifDeclarationsValidation(t *testing.T) {
11594	t.Parallel()
11595	aconfigDeclarationLibraryString := func(moduleNames []string) (ret string) {
11596		for _, moduleName := range moduleNames {
11597			ret += fmt.Sprintf(`
11598			aconfig_declarations {
11599				name: "%[1]s",
11600				package: "com.example.package",
11601				container: "system",
11602				srcs: [
11603					"%[1]s.aconfig",
11604				],
11605			}
11606			java_aconfig_library {
11607				name: "%[1]s-lib",
11608				aconfig_declarations: "%[1]s",
11609			}
11610			`, moduleName)
11611		}
11612		return ret
11613	}
11614
11615	result := android.GroupFixturePreparers(
11616		prepareForApexTest,
11617		java.PrepareForTestWithJavaSdkLibraryFiles,
11618		java.FixtureWithLastReleaseApis("foo"),
11619	).RunTestWithBp(t, `
11620		java_library {
11621			name: "baz-java-lib",
11622			static_libs: [
11623				"baz-lib",
11624			],
11625		}
11626		filegroup {
11627			name: "qux-filegroup",
11628			device_common_srcs: [
11629				":qux-lib{.generated_srcjars}",
11630			],
11631		}
11632		filegroup {
11633			name: "qux-another-filegroup",
11634			srcs: [
11635				":qux-filegroup",
11636			],
11637		}
11638		java_library {
11639			name: "quux-java-lib",
11640			srcs: [
11641				"a.java",
11642			],
11643			libs: [
11644				"quux-lib",
11645			],
11646		}
11647		java_sdk_library {
11648			name: "foo",
11649			srcs: [
11650				":qux-another-filegroup",
11651			],
11652			api_packages: ["foo"],
11653			system: {
11654				enabled: true,
11655			},
11656			module_lib: {
11657				enabled: true,
11658			},
11659			test: {
11660				enabled: true,
11661			},
11662			static_libs: [
11663				"bar-lib",
11664			],
11665			libs: [
11666				"baz-java-lib",
11667				"quux-java-lib",
11668			],
11669			aconfig_declarations: [
11670				"bar",
11671			],
11672		}
11673	`+aconfigDeclarationLibraryString([]string{"bar", "baz", "qux", "quux"}))
11674
11675	m := result.ModuleForTests(t, "foo.stubs.source", "android_common")
11676	outDir := "out/soong/.intermediates"
11677
11678	// Arguments passed to aconfig to retrieve the state of the flags defined in the
11679	// textproto files
11680	aconfigFlagArgs := m.Output("released-flags-exportable.pb").Args["flags_path"]
11681
11682	// "bar-lib" is a static_lib of "foo" and is passed to metalava as classpath. Thus the
11683	// cache file provided by the associated aconfig_declarations module "bar" should be passed
11684	// to aconfig.
11685	android.AssertStringDoesContain(t, "cache file of a java_aconfig_library static_lib "+
11686		"passed as an input",
11687		aconfigFlagArgs, fmt.Sprintf("%s/%s/intermediate.pb", outDir, "bar"))
11688
11689	// "baz-java-lib", which statically depends on "baz-lib", is a lib of "foo" and is passed
11690	// to metalava as classpath. Thus the cache file provided by the associated
11691	// aconfig_declarations module "baz" should be passed to aconfig.
11692	android.AssertStringDoesContain(t, "cache file of a lib that statically depends on "+
11693		"java_aconfig_library passed as an input",
11694		aconfigFlagArgs, fmt.Sprintf("%s/%s/intermediate.pb", outDir, "baz"))
11695
11696	// "qux-lib" is passed to metalava as src via the filegroup, thus the cache file provided by
11697	// the associated aconfig_declarations module "qux" should be passed to aconfig.
11698	android.AssertStringDoesContain(t, "cache file of srcs java_aconfig_library passed as an "+
11699		"input",
11700		aconfigFlagArgs, fmt.Sprintf("%s/%s/intermediate.pb", outDir, "qux"))
11701
11702	// "quux-java-lib" is a lib of "foo" and is passed to metalava as classpath, but does not
11703	// statically depend on "quux-lib". Therefore, the cache file provided by the associated
11704	// aconfig_declarations module "quux" should not be passed to aconfig.
11705	android.AssertStringDoesNotContain(t, "cache file of a lib that does not statically "+
11706		"depend on java_aconfig_library not passed as an input",
11707		aconfigFlagArgs, fmt.Sprintf("%s/%s/intermediate.pb", outDir, "quux"))
11708}
11709
11710func TestMultiplePrebuiltsWithSameBase(t *testing.T) {
11711	t.Parallel()
11712	ctx := testApex(t, `
11713		apex {
11714			name: "myapex",
11715			key: "myapex.key",
11716			prebuilts: ["myetc", "myetc2"],
11717			min_sdk_version: "29",
11718		}
11719		apex_key {
11720			name: "myapex.key",
11721			public_key: "testkey.avbpubkey",
11722			private_key: "testkey.pem",
11723		}
11724
11725		prebuilt_etc {
11726			name: "myetc",
11727			src: "myprebuilt",
11728			filename: "myfilename",
11729		}
11730		prebuilt_etc {
11731			name: "myetc2",
11732			sub_dir: "mysubdir",
11733			src: "myprebuilt",
11734			filename: "myfilename",
11735		}
11736	`, withFiles(android.MockFS{
11737		"packages/modules/common/build/allowed_deps.txt": nil,
11738	}))
11739
11740	ab := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Module().(*apexBundle)
11741	data := android.AndroidMkDataForTest(t, ctx, ab)
11742	var builder strings.Builder
11743	data.Custom(&builder, ab.BaseModuleName(), "TARGET_", "", data)
11744	androidMk := builder.String()
11745
11746	android.AssertStringDoesContain(t, "not found", androidMk, "LOCAL_MODULE := etc_myfilename.myapex")
11747	android.AssertStringDoesContain(t, "not found", androidMk, "LOCAL_MODULE := etc_mysubdir_myfilename.myapex")
11748}
11749
11750func TestApexMinSdkVersionOverride(t *testing.T) {
11751	t.Parallel()
11752	checkMinSdkVersion := func(t *testing.T, module android.TestingModule, expectedMinSdkVersion string) {
11753		args := module.Rule("apexRule").Args
11754		optFlags := args["opt_flags"]
11755		if !strings.Contains(optFlags, "--min_sdk_version "+expectedMinSdkVersion) {
11756			t.Errorf("%s: Expected min_sdk_version=%s, got: %s", module.Module(), expectedMinSdkVersion, optFlags)
11757		}
11758	}
11759
11760	checkHasDep := func(t *testing.T, ctx *android.TestContext, m android.Module, wantDep android.Module) {
11761		t.Helper()
11762		found := false
11763		ctx.VisitDirectDeps(m, func(dep blueprint.Module) {
11764			if dep == wantDep {
11765				found = true
11766			}
11767		})
11768		if !found {
11769			t.Errorf("Could not find a dependency from %v to %v\n", m, wantDep)
11770		}
11771	}
11772
11773	ctx := testApex(t, `
11774		apex {
11775			name: "com.android.apex30",
11776			min_sdk_version: "30",
11777			key: "apex30.key",
11778			java_libs: ["javalib"],
11779		}
11780
11781		java_library {
11782			name: "javalib",
11783			srcs: ["A.java"],
11784			apex_available: ["com.android.apex30"],
11785			min_sdk_version: "30",
11786			sdk_version: "current",
11787			compile_dex: true,
11788		}
11789
11790		override_apex {
11791			name: "com.mycompany.android.apex30",
11792			base: "com.android.apex30",
11793		}
11794
11795		override_apex {
11796			name: "com.mycompany.android.apex31",
11797			base: "com.android.apex30",
11798			min_sdk_version: "31",
11799		}
11800
11801		apex_key {
11802			name: "apex30.key",
11803			public_key: "testkey.avbpubkey",
11804			private_key: "testkey.pem",
11805		}
11806
11807	`, android.FixtureMergeMockFs(android.MockFS{
11808		"system/sepolicy/apex/com.android.apex30-file_contexts": nil,
11809	}),
11810	)
11811
11812	baseModule := ctx.ModuleForTests(t, "com.android.apex30", "android_common_com.android.apex30")
11813	checkMinSdkVersion(t, baseModule, "30")
11814
11815	// Override module, but uses same min_sdk_version
11816	overridingModuleSameMinSdkVersion := ctx.ModuleForTests(t, "com.android.apex30", "android_common_com.mycompany.android.apex30_com.mycompany.android.apex30")
11817	javalibApex30Variant := ctx.ModuleForTests(t, "javalib", "android_common_apex30")
11818	checkMinSdkVersion(t, overridingModuleSameMinSdkVersion, "30")
11819	checkHasDep(t, ctx, overridingModuleSameMinSdkVersion.Module(), javalibApex30Variant.Module())
11820
11821	// Override module, uses different min_sdk_version
11822	overridingModuleDifferentMinSdkVersion := ctx.ModuleForTests(t, "com.android.apex30", "android_common_com.mycompany.android.apex31_com.mycompany.android.apex31")
11823	javalibApex31Variant := ctx.ModuleForTests(t, "javalib", "android_common_apex31")
11824	checkMinSdkVersion(t, overridingModuleDifferentMinSdkVersion, "31")
11825	checkHasDep(t, ctx, overridingModuleDifferentMinSdkVersion.Module(), javalibApex31Variant.Module())
11826}
11827
11828func TestOverrideApexWithPrebuiltApexPreferred(t *testing.T) {
11829	t.Parallel()
11830	context := android.GroupFixturePreparers(
11831		android.PrepareForIntegrationTestWithAndroid,
11832		PrepareForTestWithApexBuildComponents,
11833		android.FixtureMergeMockFs(android.MockFS{
11834			"system/sepolicy/apex/foo-file_contexts": nil,
11835		}),
11836	)
11837	res := context.RunTestWithBp(t, `
11838		apex {
11839			name: "foo",
11840			key: "myapex.key",
11841			apex_available_name: "com.android.foo",
11842			variant_version: "0",
11843			updatable: false,
11844		}
11845		apex_key {
11846			name: "myapex.key",
11847			public_key: "testkey.avbpubkey",
11848			private_key: "testkey.pem",
11849		}
11850		prebuilt_apex {
11851			name: "foo",
11852			src: "foo.apex",
11853			prefer: true,
11854		}
11855		override_apex {
11856			name: "myoverrideapex",
11857			base: "foo",
11858		}
11859	`)
11860
11861	java.CheckModuleHasDependency(t, res.TestContext, "myoverrideapex", "android_common_myoverrideapex", "foo")
11862}
11863
11864func TestUpdatableApexMinSdkVersionCurrent(t *testing.T) {
11865	t.Parallel()
11866	testApexError(t, `"myapex" .*: updatable: updatable APEXes should not set min_sdk_version to current. Please use a finalized API level or a recognized in-development codename`, `
11867		apex {
11868			name: "myapex",
11869			key: "myapex.key",
11870			updatable: true,
11871			min_sdk_version: "current",
11872		}
11873
11874		apex_key {
11875			name: "myapex.key",
11876			public_key: "testkey.avbpubkey",
11877			private_key: "testkey.pem",
11878		}
11879	`)
11880}
11881
11882func TestPrebuiltStubNoinstall(t *testing.T) {
11883	t.Parallel()
11884	testFunc := func(t *testing.T, expectLibfooOnSystemLib bool, fs android.MockFS) {
11885		result := android.GroupFixturePreparers(
11886			prepareForApexTest,
11887			android.PrepareForTestWithAndroidMk,
11888			android.PrepareForTestWithMakevars,
11889			android.FixtureMergeMockFs(fs),
11890		).RunTest(t)
11891
11892		ldRule := result.ModuleForTests(t, "installedlib", "android_arm64_armv8-a_shared").Rule("ld")
11893		android.AssertStringDoesContain(t, "", ldRule.Args["libFlags"], "android_arm64_armv8-a_shared_current/libfoo.so")
11894
11895		installRules := result.InstallMakeRulesForTesting(t)
11896
11897		var installedlibRule *android.InstallMakeRule
11898		for i, rule := range installRules {
11899			if rule.Target == "out/target/product/test_device/system/lib/installedlib.so" {
11900				if installedlibRule != nil {
11901					t.Errorf("Duplicate install rules for %s", rule.Target)
11902				}
11903				installedlibRule = &installRules[i]
11904			}
11905		}
11906		if installedlibRule == nil {
11907			t.Errorf("No install rule found for installedlib")
11908			return
11909		}
11910
11911		if expectLibfooOnSystemLib {
11912			android.AssertStringListContains(t,
11913				"installedlib doesn't have install dependency on libfoo impl",
11914				installedlibRule.OrderOnlyDeps,
11915				"out/target/product/test_device/system/lib/libfoo.so")
11916		} else {
11917			android.AssertStringListDoesNotContain(t,
11918				"installedlib has install dependency on libfoo stub",
11919				installedlibRule.Deps,
11920				"out/target/product/test_device/system/lib/libfoo.so")
11921			android.AssertStringListDoesNotContain(t,
11922				"installedlib has order-only install dependency on libfoo stub",
11923				installedlibRule.OrderOnlyDeps,
11924				"out/target/product/test_device/system/lib/libfoo.so")
11925		}
11926	}
11927
11928	prebuiltLibfooBp := []byte(`
11929		cc_prebuilt_library {
11930			name: "libfoo",
11931			prefer: true,
11932			srcs: ["libfoo.so"],
11933			stubs: {
11934				versions: ["1"],
11935			},
11936			apex_available: ["apexfoo"],
11937		}
11938	`)
11939
11940	apexfooBp := []byte(`
11941		apex {
11942			name: "apexfoo",
11943			key: "apexfoo.key",
11944			native_shared_libs: ["libfoo"],
11945			updatable: false,
11946			compile_multilib: "both",
11947		}
11948		apex_key {
11949			name: "apexfoo.key",
11950			public_key: "testkey.avbpubkey",
11951			private_key: "testkey.pem",
11952		}
11953	`)
11954
11955	installedlibBp := []byte(`
11956		cc_library {
11957			name: "installedlib",
11958			shared_libs: ["libfoo"],
11959		}
11960	`)
11961
11962	t.Run("prebuilt stub (without source): no install", func(t *testing.T) {
11963		t.Parallel()
11964		testFunc(
11965			t,
11966			/*expectLibfooOnSystemLib=*/ false,
11967			android.MockFS{
11968				"prebuilts/module_sdk/art/current/Android.bp": prebuiltLibfooBp,
11969				"apexfoo/Android.bp":                          apexfooBp,
11970				"system/sepolicy/apex/apexfoo-file_contexts":  nil,
11971				"Android.bp": installedlibBp,
11972			},
11973		)
11974	})
11975
11976	disabledSourceLibfooBp := []byte(`
11977		cc_library {
11978			name: "libfoo",
11979			enabled: false,
11980			stubs: {
11981				versions: ["1"],
11982			},
11983			apex_available: ["apexfoo"],
11984		}
11985	`)
11986
11987	t.Run("prebuilt stub (with disabled source): no install", func(t *testing.T) {
11988		t.Parallel()
11989		testFunc(
11990			t,
11991			/*expectLibfooOnSystemLib=*/ false,
11992			android.MockFS{
11993				"prebuilts/module_sdk/art/current/Android.bp": prebuiltLibfooBp,
11994				"impl/Android.bp":                            disabledSourceLibfooBp,
11995				"apexfoo/Android.bp":                         apexfooBp,
11996				"system/sepolicy/apex/apexfoo-file_contexts": nil,
11997				"Android.bp":                                 installedlibBp,
11998			},
11999		)
12000	})
12001}
12002
12003func TestSdkLibraryTransitiveClassLoaderContext(t *testing.T) {
12004	t.Parallel()
12005	// This test case tests that listing the impl lib instead of the top level java_sdk_library
12006	// in libs of android_app and java_library does not lead to class loader context device/host
12007	// path mismatch errors.
12008	android.GroupFixturePreparers(
12009		prepareForApexTest,
12010		android.PrepareForIntegrationTestWithAndroid,
12011		PrepareForTestWithApexBuildComponents,
12012		android.FixtureModifyEnv(func(env map[string]string) {
12013			env["DISABLE_CONTAINER_CHECK"] = "true"
12014		}),
12015		withFiles(filesForSdkLibrary),
12016		android.FixtureMergeMockFs(android.MockFS{
12017			"system/sepolicy/apex/com.android.foo30-file_contexts": nil,
12018		}),
12019	).RunTestWithBp(t, `
12020		apex {
12021		name: "com.android.foo30",
12022		key: "myapex.key",
12023		updatable: true,
12024		bootclasspath_fragments: [
12025			"foo-bootclasspath-fragment",
12026		],
12027		java_libs: [
12028			"bar",
12029		],
12030		apps: [
12031			"bar-app",
12032		],
12033		min_sdk_version: "30",
12034		}
12035		apex_key {
12036			name: "myapex.key",
12037			public_key: "testkey.avbpubkey",
12038			private_key: "testkey.pem",
12039		}
12040		bootclasspath_fragment {
12041			name: "foo-bootclasspath-fragment",
12042			contents: [
12043				"framework-foo",
12044			],
12045			apex_available: [
12046				"com.android.foo30",
12047			],
12048			hidden_api: {
12049				split_packages: ["*"]
12050			},
12051		}
12052
12053		java_sdk_library {
12054			name: "framework-foo",
12055			srcs: [
12056				"A.java"
12057			],
12058			unsafe_ignore_missing_latest_api: true,
12059			apex_available: [
12060				"com.android.foo30",
12061			],
12062			compile_dex: true,
12063			sdk_version: "core_current",
12064			shared_library: false,
12065		}
12066
12067		java_library {
12068			name: "bar",
12069			srcs: [
12070				"A.java"
12071			],
12072			libs: [
12073				"framework-foo.impl",
12074			],
12075			apex_available: [
12076				"com.android.foo30",
12077			],
12078			sdk_version: "core_current",
12079			compile_dex: true,
12080		}
12081
12082		java_library {
12083			name: "baz",
12084			srcs: [
12085				"A.java"
12086			],
12087			libs: [
12088				"bar",
12089			],
12090			sdk_version: "core_current",
12091		}
12092
12093		android_app {
12094			name: "bar-app",
12095			srcs: [
12096				"A.java"
12097			],
12098			libs: [
12099				"baz",
12100				"framework-foo.impl",
12101			],
12102			apex_available: [
12103				"com.android.foo30",
12104			],
12105			sdk_version: "core_current",
12106			min_sdk_version: "30",
12107			manifest: "AndroidManifest.xml",
12108			updatable: true,
12109		}
12110       `)
12111}
12112
12113// If an apex sets system_ext_specific: true, its systemserverclasspath libraries must set this property as well.
12114func TestApexSSCPJarMustBeInSamePartitionAsApex(t *testing.T) {
12115	t.Parallel()
12116	testApexError(t, `foo is an apex systemserver jar, but its partition does not match the partition of its containing apex`, `
12117		apex {
12118			name: "myapex",
12119			key: "myapex.key",
12120			systemserverclasspath_fragments: [
12121				"mysystemserverclasspathfragment",
12122			],
12123			min_sdk_version: "29",
12124			updatable: true,
12125			system_ext_specific: true,
12126		}
12127
12128		apex_key {
12129			name: "myapex.key",
12130			public_key: "testkey.avbpubkey",
12131			private_key: "testkey.pem",
12132		}
12133
12134		java_library {
12135			name: "foo",
12136			srcs: ["b.java"],
12137			min_sdk_version: "29",
12138			installable: true,
12139			apex_available: [
12140				"myapex",
12141			],
12142			sdk_version: "current",
12143		}
12144
12145		systemserverclasspath_fragment {
12146			name: "mysystemserverclasspathfragment",
12147			contents: [
12148				"foo",
12149			],
12150			apex_available: [
12151				"myapex",
12152			],
12153		}
12154	`,
12155		dexpreopt.FixtureSetApexSystemServerJars("myapex:foo"),
12156	)
12157}
12158
12159// partitions should not package the artifacts that are included inside the apex.
12160func TestFilesystemWithApexDeps(t *testing.T) {
12161	t.Parallel()
12162	result := testApex(t, `
12163		android_filesystem {
12164			name: "myfilesystem",
12165			deps: ["myapex"],
12166		}
12167		apex {
12168			name: "myapex",
12169			key: "myapex.key",
12170			binaries: ["binfoo"],
12171			native_shared_libs: ["libfoo"],
12172			apps: ["appfoo"],
12173			updatable: false,
12174		}
12175		apex_key {
12176			name: "myapex.key",
12177		}
12178		cc_binary {
12179			name: "binfoo",
12180			apex_available: ["myapex"],
12181		}
12182		cc_library {
12183			name: "libfoo",
12184			apex_available: ["myapex"],
12185		}
12186		android_app {
12187			name: "appfoo",
12188			sdk_version: "current",
12189			apex_available: ["myapex"],
12190		}
12191	`, filesystem.PrepareForTestWithFilesystemBuildComponents)
12192
12193	partition := result.ModuleForTests(t, "myfilesystem", "android_common")
12194	fileList := android.ContentFromFileRuleForTests(t, result, partition.Output("fileList"))
12195	android.AssertDeepEquals(t, "filesystem with apex", "apex/myapex.apex\n", fileList)
12196}
12197
12198func TestVintfFragmentInApex(t *testing.T) {
12199	t.Parallel()
12200	ctx := testApex(t, apex_default_bp+`
12201		apex {
12202			name: "myapex",
12203			manifest: ":myapex.manifest",
12204			androidManifest: ":myapex.androidmanifest",
12205			key: "myapex.key",
12206			binaries: [ "mybin" ],
12207			updatable: false,
12208		}
12209
12210		cc_binary {
12211			name: "mybin",
12212			srcs: ["mybin.cpp"],
12213			vintf_fragment_modules: ["my_vintf_fragment.xml"],
12214			apex_available: [ "myapex" ],
12215		}
12216
12217		vintf_fragment {
12218			name: "my_vintf_fragment.xml",
12219			src: "my_vintf_fragment.xml",
12220		}
12221	`)
12222
12223	generateFsRule := ctx.ModuleForTests(t, "myapex", "android_common_myapex").Rule("generateFsConfig")
12224	cmd := generateFsRule.RuleParams.Command
12225
12226	// Ensure that vintf fragment file is being installed
12227	ensureContains(t, cmd, "/etc/vintf/my_vintf_fragment.xml ")
12228}
12229
12230func TestNoVintfFragmentInUpdatableApex(t *testing.T) {
12231	t.Parallel()
12232	testApexError(t, `VINTF fragment .* is not supported in updatable APEX`, apex_default_bp+`
12233		apex {
12234			name: "myapex",
12235			manifest: ":myapex.manifest",
12236			key: "myapex.key",
12237			binaries: [ "mybin" ],
12238			updatable: true,
12239			min_sdk_version: "29",
12240		}
12241
12242		cc_binary {
12243			name: "mybin",
12244			srcs: ["mybin.cpp"],
12245			vintf_fragment_modules: ["my_vintf_fragment.xml"],
12246			apex_available: [ "myapex" ],
12247			min_sdk_version: "29",
12248		}
12249
12250		vintf_fragment {
12251			name: "my_vintf_fragment.xml",
12252			src: "my_vintf_fragment.xml",
12253		}
12254	`)
12255}
12256