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