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