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