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	"os"
20	"path"
21	"path/filepath"
22	"reflect"
23	"regexp"
24	"sort"
25	"strconv"
26	"strings"
27	"testing"
28
29	"github.com/google/blueprint/proptools"
30
31	"android/soong/android"
32	"android/soong/bpf"
33	"android/soong/cc"
34	"android/soong/dexpreopt"
35	prebuilt_etc "android/soong/etc"
36	"android/soong/java"
37	"android/soong/rust"
38	"android/soong/sh"
39)
40
41// names returns name list from white space separated string
42func names(s string) (ns []string) {
43	for _, n := range strings.Split(s, " ") {
44		if len(n) > 0 {
45			ns = append(ns, n)
46		}
47	}
48	return
49}
50
51func testApexError(t *testing.T, pattern, bp string, preparers ...android.FixturePreparer) {
52	t.Helper()
53	android.GroupFixturePreparers(
54		prepareForApexTest,
55		android.GroupFixturePreparers(preparers...),
56	).
57		ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(pattern)).
58		RunTestWithBp(t, bp)
59}
60
61func testApex(t *testing.T, bp string, preparers ...android.FixturePreparer) *android.TestContext {
62	t.Helper()
63
64	optionalBpPreparer := android.NullFixturePreparer
65	if bp != "" {
66		optionalBpPreparer = android.FixtureWithRootAndroidBp(bp)
67	}
68
69	result := android.GroupFixturePreparers(
70		prepareForApexTest,
71		android.GroupFixturePreparers(preparers...),
72		optionalBpPreparer,
73	).RunTest(t)
74
75	return result.TestContext
76}
77
78func withFiles(files android.MockFS) android.FixturePreparer {
79	return files.AddToFixture()
80}
81
82func withTargets(targets map[android.OsType][]android.Target) android.FixturePreparer {
83	return android.FixtureModifyConfig(func(config android.Config) {
84		for k, v := range targets {
85			config.Targets[k] = v
86		}
87	})
88}
89
90// withNativeBridgeTargets sets configuration with targets including:
91// - X86_64 (primary)
92// - X86 (secondary)
93// - Arm64 on X86_64 (native bridge)
94// - Arm on X86 (native bridge)
95var withNativeBridgeEnabled = android.FixtureModifyConfig(
96	func(config android.Config) {
97		config.Targets[android.Android] = []android.Target{
98			{Os: android.Android, Arch: android.Arch{ArchType: android.X86_64, ArchVariant: "silvermont", Abi: []string{"arm64-v8a"}},
99				NativeBridge: android.NativeBridgeDisabled, NativeBridgeHostArchName: "", NativeBridgeRelativePath: ""},
100			{Os: android.Android, Arch: android.Arch{ArchType: android.X86, ArchVariant: "silvermont", Abi: []string{"armeabi-v7a"}},
101				NativeBridge: android.NativeBridgeDisabled, NativeBridgeHostArchName: "", NativeBridgeRelativePath: ""},
102			{Os: android.Android, Arch: android.Arch{ArchType: android.Arm64, ArchVariant: "armv8-a", Abi: []string{"arm64-v8a"}},
103				NativeBridge: android.NativeBridgeEnabled, NativeBridgeHostArchName: "x86_64", NativeBridgeRelativePath: "arm64"},
104			{Os: android.Android, Arch: android.Arch{ArchType: android.Arm, ArchVariant: "armv7-a-neon", Abi: []string{"armeabi-v7a"}},
105				NativeBridge: android.NativeBridgeEnabled, NativeBridgeHostArchName: "x86", NativeBridgeRelativePath: "arm"},
106		}
107	},
108)
109
110func withManifestPackageNameOverrides(specs []string) android.FixturePreparer {
111	return android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
112		variables.ManifestPackageNameOverrides = specs
113	})
114}
115
116var withBinder32bit = android.FixtureModifyProductVariables(
117	func(variables android.FixtureProductVariables) {
118		variables.Binder32bit = proptools.BoolPtr(true)
119	},
120)
121
122var withUnbundledBuild = android.FixtureModifyProductVariables(
123	func(variables android.FixtureProductVariables) {
124		variables.Unbundled_build = proptools.BoolPtr(true)
125	},
126)
127
128// Legacy preparer used for running tests within the apex package.
129//
130// This includes everything that was needed to run any test in the apex package prior to the
131// introduction of the test fixtures. Tests that are being converted to use fixtures directly
132// rather than through the testApex...() methods should avoid using this and instead use the
133// various preparers directly, using android.GroupFixturePreparers(...) to group them when
134// necessary.
135//
136// deprecated
137var prepareForApexTest = android.GroupFixturePreparers(
138	// General preparers in alphabetical order as test infrastructure will enforce correct
139	// registration order.
140	android.PrepareForTestWithAndroidBuildComponents,
141	bpf.PrepareForTestWithBpf,
142	cc.PrepareForTestWithCcBuildComponents,
143	java.PrepareForTestWithJavaDefaultModules,
144	prebuilt_etc.PrepareForTestWithPrebuiltEtc,
145	rust.PrepareForTestWithRustDefaultModules,
146	sh.PrepareForTestWithShBuildComponents,
147
148	PrepareForTestWithApexBuildComponents,
149
150	// Additional apex test specific preparers.
151	android.FixtureAddTextFile("system/sepolicy/Android.bp", `
152		filegroup {
153			name: "myapex-file_contexts",
154			srcs: [
155				"apex/myapex-file_contexts",
156			],
157		}
158	`),
159	prepareForTestWithMyapex,
160	android.FixtureMergeMockFs(android.MockFS{
161		"a.java":                 nil,
162		"PrebuiltAppFoo.apk":     nil,
163		"PrebuiltAppFooPriv.apk": nil,
164		"apex_manifest.json":     nil,
165		"AndroidManifest.xml":    nil,
166		"system/sepolicy/apex/myapex.updatable-file_contexts":         nil,
167		"system/sepolicy/apex/myapex2-file_contexts":                  nil,
168		"system/sepolicy/apex/otherapex-file_contexts":                nil,
169		"system/sepolicy/apex/com.android.vndk-file_contexts":         nil,
170		"system/sepolicy/apex/com.android.vndk.current-file_contexts": nil,
171		"mylib.cpp":                                  nil,
172		"mytest.cpp":                                 nil,
173		"mytest1.cpp":                                nil,
174		"mytest2.cpp":                                nil,
175		"mytest3.cpp":                                nil,
176		"myprebuilt":                                 nil,
177		"my_include":                                 nil,
178		"foo/bar/MyClass.java":                       nil,
179		"prebuilt.jar":                               nil,
180		"prebuilt.so":                                nil,
181		"vendor/foo/devkeys/test.x509.pem":           nil,
182		"vendor/foo/devkeys/test.pk8":                nil,
183		"testkey.x509.pem":                           nil,
184		"testkey.pk8":                                nil,
185		"testkey.override.x509.pem":                  nil,
186		"testkey.override.pk8":                       nil,
187		"vendor/foo/devkeys/testkey.avbpubkey":       nil,
188		"vendor/foo/devkeys/testkey.pem":             nil,
189		"NOTICE":                                     nil,
190		"custom_notice":                              nil,
191		"custom_notice_for_static_lib":               nil,
192		"testkey2.avbpubkey":                         nil,
193		"testkey2.pem":                               nil,
194		"myapex-arm64.apex":                          nil,
195		"myapex-arm.apex":                            nil,
196		"myapex.apks":                                nil,
197		"frameworks/base/api/current.txt":            nil,
198		"framework/aidl/a.aidl":                      nil,
199		"build/make/core/proguard.flags":             nil,
200		"build/make/core/proguard_basic_keeps.flags": nil,
201		"dummy.txt":                                  nil,
202		"baz":                                        nil,
203		"bar/baz":                                    nil,
204		"testdata/baz":                               nil,
205		"AppSet.apks":                                nil,
206		"foo.rs":                                     nil,
207		"libfoo.jar":                                 nil,
208		"libbar.jar":                                 nil,
209	},
210	),
211
212	android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
213		variables.DeviceVndkVersion = proptools.StringPtr("current")
214		variables.DefaultAppCertificate = proptools.StringPtr("vendor/foo/devkeys/test")
215		variables.CertificateOverrides = []string{"myapex_keytest:myapex.certificate.override"}
216		variables.Platform_sdk_codename = proptools.StringPtr("Q")
217		variables.Platform_sdk_final = proptools.BoolPtr(false)
218		variables.Platform_version_active_codenames = []string{"Q"}
219		variables.Platform_vndk_version = proptools.StringPtr("29")
220	}),
221)
222
223var prepareForTestWithMyapex = android.FixtureMergeMockFs(android.MockFS{
224	"system/sepolicy/apex/myapex-file_contexts": nil,
225})
226
227// ensure that 'result' equals 'expected'
228func ensureEquals(t *testing.T, result string, expected string) {
229	t.Helper()
230	if result != expected {
231		t.Errorf("%q != %q", expected, result)
232	}
233}
234
235// ensure that 'result' contains 'expected'
236func ensureContains(t *testing.T, result string, expected string) {
237	t.Helper()
238	if !strings.Contains(result, expected) {
239		t.Errorf("%q is not found in %q", expected, result)
240	}
241}
242
243// ensure that 'result' contains 'expected' exactly one time
244func ensureContainsOnce(t *testing.T, result string, expected string) {
245	t.Helper()
246	count := strings.Count(result, expected)
247	if count != 1 {
248		t.Errorf("%q is found %d times (expected 1 time) in %q", expected, count, result)
249	}
250}
251
252// ensures that 'result' does not contain 'notExpected'
253func ensureNotContains(t *testing.T, result string, notExpected string) {
254	t.Helper()
255	if strings.Contains(result, notExpected) {
256		t.Errorf("%q is found in %q", notExpected, result)
257	}
258}
259
260func ensureMatches(t *testing.T, result string, expectedRex string) {
261	ok, err := regexp.MatchString(expectedRex, result)
262	if err != nil {
263		t.Fatalf("regexp failure trying to match %s against `%s` expression: %s", result, expectedRex, err)
264		return
265	}
266	if !ok {
267		t.Errorf("%s does not match regular expession %s", result, expectedRex)
268	}
269}
270
271func ensureListContains(t *testing.T, result []string, expected string) {
272	t.Helper()
273	if !android.InList(expected, result) {
274		t.Errorf("%q is not found in %v", expected, result)
275	}
276}
277
278func ensureListNotContains(t *testing.T, result []string, notExpected string) {
279	t.Helper()
280	if android.InList(notExpected, result) {
281		t.Errorf("%q is found in %v", notExpected, result)
282	}
283}
284
285func ensureListEmpty(t *testing.T, result []string) {
286	t.Helper()
287	if len(result) > 0 {
288		t.Errorf("%q is expected to be empty", result)
289	}
290}
291
292func ensureListNotEmpty(t *testing.T, result []string) {
293	t.Helper()
294	if len(result) == 0 {
295		t.Errorf("%q is expected to be not empty", result)
296	}
297}
298
299// Minimal test
300func TestBasicApex(t *testing.T) {
301	ctx := testApex(t, `
302		apex_defaults {
303			name: "myapex-defaults",
304			manifest: ":myapex.manifest",
305			androidManifest: ":myapex.androidmanifest",
306			key: "myapex.key",
307			binaries: ["foo.rust"],
308			native_shared_libs: [
309				"mylib",
310				"libfoo.ffi",
311			],
312			rust_dyn_libs: ["libfoo.dylib.rust"],
313			multilib: {
314				both: {
315					binaries: ["foo"],
316				}
317			},
318			java_libs: [
319				"myjar",
320				"myjar_dex",
321			],
322			updatable: false,
323		}
324
325		apex {
326			name: "myapex",
327			defaults: ["myapex-defaults"],
328		}
329
330		apex_key {
331			name: "myapex.key",
332			public_key: "testkey.avbpubkey",
333			private_key: "testkey.pem",
334		}
335
336		filegroup {
337			name: "myapex.manifest",
338			srcs: ["apex_manifest.json"],
339		}
340
341		filegroup {
342			name: "myapex.androidmanifest",
343			srcs: ["AndroidManifest.xml"],
344		}
345
346		cc_library {
347			name: "mylib",
348			srcs: ["mylib.cpp"],
349			shared_libs: [
350				"mylib2",
351				"libbar.ffi",
352			],
353			system_shared_libs: [],
354			stl: "none",
355			// TODO: remove //apex_available:platform
356			apex_available: [
357				"//apex_available:platform",
358				"myapex",
359			],
360		}
361
362		cc_binary {
363			name: "foo",
364			srcs: ["mylib.cpp"],
365			compile_multilib: "both",
366			multilib: {
367					lib32: {
368							suffix: "32",
369					},
370					lib64: {
371							suffix: "64",
372					},
373			},
374			symlinks: ["foo_link_"],
375			symlink_preferred_arch: true,
376			system_shared_libs: [],
377			static_executable: true,
378			stl: "none",
379			apex_available: [ "myapex", "com.android.gki.*" ],
380		}
381
382		rust_binary {
383			name: "foo.rust",
384			srcs: ["foo.rs"],
385			rlibs: ["libfoo.rlib.rust"],
386			dylibs: ["libfoo.dylib.rust"],
387			apex_available: ["myapex"],
388		}
389
390		rust_library_rlib {
391			name: "libfoo.rlib.rust",
392			srcs: ["foo.rs"],
393			crate_name: "foo",
394			apex_available: ["myapex"],
395			shared_libs: ["libfoo.shared_from_rust"],
396		}
397
398		cc_library_shared {
399			name: "libfoo.shared_from_rust",
400			srcs: ["mylib.cpp"],
401			system_shared_libs: [],
402			stl: "none",
403			apex_available: ["myapex"],
404		}
405
406		rust_library_dylib {
407			name: "libfoo.dylib.rust",
408			srcs: ["foo.rs"],
409			crate_name: "foo",
410			apex_available: ["myapex"],
411		}
412
413		rust_ffi_shared {
414			name: "libfoo.ffi",
415			srcs: ["foo.rs"],
416			crate_name: "foo",
417			apex_available: ["myapex"],
418		}
419
420		rust_ffi_shared {
421			name: "libbar.ffi",
422			srcs: ["foo.rs"],
423			crate_name: "bar",
424			apex_available: ["myapex"],
425		}
426
427		apex {
428			name: "com.android.gki.fake",
429			binaries: ["foo"],
430			key: "myapex.key",
431			file_contexts: ":myapex-file_contexts",
432			updatable: false,
433		}
434
435		cc_library_shared {
436			name: "mylib2",
437			srcs: ["mylib.cpp"],
438			system_shared_libs: [],
439			stl: "none",
440			notice: "custom_notice",
441			static_libs: ["libstatic"],
442			// TODO: remove //apex_available:platform
443			apex_available: [
444				"//apex_available:platform",
445				"myapex",
446			],
447		}
448
449		cc_prebuilt_library_shared {
450			name: "mylib2",
451			srcs: ["prebuilt.so"],
452			// TODO: remove //apex_available:platform
453			apex_available: [
454				"//apex_available:platform",
455				"myapex",
456			],
457    }
458
459		cc_library_static {
460			name: "libstatic",
461			srcs: ["mylib.cpp"],
462			system_shared_libs: [],
463			stl: "none",
464			notice: "custom_notice_for_static_lib",
465			// TODO: remove //apex_available:platform
466			apex_available: [
467				"//apex_available:platform",
468				"myapex",
469			],
470		}
471
472		java_library {
473			name: "myjar",
474			srcs: ["foo/bar/MyClass.java"],
475			stem: "myjar_stem",
476			sdk_version: "none",
477			system_modules: "none",
478			static_libs: ["myotherjar"],
479			libs: ["mysharedjar"],
480			// TODO: remove //apex_available:platform
481			apex_available: [
482				"//apex_available:platform",
483				"myapex",
484			],
485		}
486
487		dex_import {
488			name: "myjar_dex",
489			jars: ["prebuilt.jar"],
490			apex_available: [
491				"//apex_available:platform",
492				"myapex",
493			],
494		}
495
496		java_library {
497			name: "myotherjar",
498			srcs: ["foo/bar/MyClass.java"],
499			sdk_version: "none",
500			system_modules: "none",
501			// TODO: remove //apex_available:platform
502			apex_available: [
503				"//apex_available:platform",
504				"myapex",
505			],
506		}
507
508		java_library {
509			name: "mysharedjar",
510			srcs: ["foo/bar/MyClass.java"],
511			sdk_version: "none",
512			system_modules: "none",
513		}
514	`)
515
516	apexRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("apexRule")
517
518	// Make sure that Android.mk is created
519	ab := ctx.ModuleForTests("myapex", "android_common_myapex_image").Module().(*apexBundle)
520	data := android.AndroidMkDataForTest(t, ctx, ab)
521	var builder strings.Builder
522	data.Custom(&builder, ab.BaseModuleName(), "TARGET_", "", data)
523
524	androidMk := builder.String()
525	ensureContains(t, androidMk, "LOCAL_MODULE := mylib.myapex\n")
526	ensureNotContains(t, androidMk, "LOCAL_MODULE := mylib.com.android.myapex\n")
527
528	optFlags := apexRule.Args["opt_flags"]
529	ensureContains(t, optFlags, "--pubkey vendor/foo/devkeys/testkey.avbpubkey")
530	// Ensure that the NOTICE output is being packaged as an asset.
531	ensureContains(t, optFlags, "--assets_dir out/soong/.intermediates/myapex/android_common_myapex_image/NOTICE")
532
533	copyCmds := apexRule.Args["copy_commands"]
534
535	// Ensure that main rule creates an output
536	ensureContains(t, apexRule.Output.String(), "myapex.apex.unsigned")
537
538	// Ensure that apex variant is created for the direct dep
539	ensureListContains(t, ctx.ModuleVariantsForTests("mylib"), "android_arm64_armv8-a_shared_apex10000")
540	ensureListContains(t, ctx.ModuleVariantsForTests("myjar"), "android_common_apex10000")
541	ensureListContains(t, ctx.ModuleVariantsForTests("myjar_dex"), "android_common_apex10000")
542	ensureListContains(t, ctx.ModuleVariantsForTests("foo.rust"), "android_arm64_armv8-a_apex10000")
543	ensureListContains(t, ctx.ModuleVariantsForTests("libfoo.ffi"), "android_arm64_armv8-a_shared_apex10000")
544
545	// Ensure that apex variant is created for the indirect dep
546	ensureListContains(t, ctx.ModuleVariantsForTests("mylib2"), "android_arm64_armv8-a_shared_apex10000")
547	ensureListContains(t, ctx.ModuleVariantsForTests("myotherjar"), "android_common_apex10000")
548	ensureListContains(t, ctx.ModuleVariantsForTests("libfoo.rlib.rust"), "android_arm64_armv8-a_rlib_dylib-std_apex10000")
549	ensureListContains(t, ctx.ModuleVariantsForTests("libfoo.dylib.rust"), "android_arm64_armv8-a_dylib_apex10000")
550	ensureListContains(t, ctx.ModuleVariantsForTests("libbar.ffi"), "android_arm64_armv8-a_shared_apex10000")
551	ensureListContains(t, ctx.ModuleVariantsForTests("libfoo.shared_from_rust"), "android_arm64_armv8-a_shared_apex10000")
552
553	// Ensure that both direct and indirect deps are copied into apex
554	ensureContains(t, copyCmds, "image.apex/lib64/mylib.so")
555	ensureContains(t, copyCmds, "image.apex/lib64/mylib2.so")
556	ensureContains(t, copyCmds, "image.apex/javalib/myjar_stem.jar")
557	ensureContains(t, copyCmds, "image.apex/javalib/myjar_dex.jar")
558	ensureContains(t, copyCmds, "image.apex/lib64/libfoo.dylib.rust.dylib.so")
559	ensureContains(t, copyCmds, "image.apex/lib64/libfoo.ffi.so")
560	ensureContains(t, copyCmds, "image.apex/lib64/libbar.ffi.so")
561	ensureContains(t, copyCmds, "image.apex/lib64/libfoo.shared_from_rust.so")
562	// .. but not for java libs
563	ensureNotContains(t, copyCmds, "image.apex/javalib/myotherjar.jar")
564	ensureNotContains(t, copyCmds, "image.apex/javalib/msharedjar.jar")
565
566	// Ensure that the platform variant ends with _shared or _common
567	ensureListContains(t, ctx.ModuleVariantsForTests("mylib"), "android_arm64_armv8-a_shared")
568	ensureListContains(t, ctx.ModuleVariantsForTests("mylib2"), "android_arm64_armv8-a_shared")
569	ensureListContains(t, ctx.ModuleVariantsForTests("myjar"), "android_common")
570	ensureListContains(t, ctx.ModuleVariantsForTests("myotherjar"), "android_common")
571	ensureListContains(t, ctx.ModuleVariantsForTests("mysharedjar"), "android_common")
572
573	// Ensure that dynamic dependency to java libs are not included
574	ensureListNotContains(t, ctx.ModuleVariantsForTests("mysharedjar"), "android_common_myapex")
575
576	// Ensure that all symlinks are present.
577	found_foo_link_64 := false
578	found_foo := false
579	for _, cmd := range strings.Split(copyCmds, " && ") {
580		if strings.HasPrefix(cmd, "ln -sfn foo64") {
581			if strings.HasSuffix(cmd, "bin/foo") {
582				found_foo = true
583			} else if strings.HasSuffix(cmd, "bin/foo_link_64") {
584				found_foo_link_64 = true
585			}
586		}
587	}
588	good := found_foo && found_foo_link_64
589	if !good {
590		t.Errorf("Could not find all expected symlinks! foo: %t, foo_link_64: %t. Command was %s", found_foo, found_foo_link_64, copyCmds)
591	}
592
593	mergeNoticesRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("mergeNoticesRule")
594	noticeInputs := mergeNoticesRule.Inputs.Strings()
595	if len(noticeInputs) != 3 {
596		t.Errorf("number of input notice files: expected = 3, actual = %q", len(noticeInputs))
597	}
598	ensureListContains(t, noticeInputs, "NOTICE")
599	ensureListContains(t, noticeInputs, "custom_notice")
600	ensureListContains(t, noticeInputs, "custom_notice_for_static_lib")
601
602	fullDepsInfo := strings.Split(ctx.ModuleForTests("myapex", "android_common_myapex_image").Output("depsinfo/fulllist.txt").Args["content"], "\\n")
603	ensureListContains(t, fullDepsInfo, "  myjar(minSdkVersion:(no version)) <- myapex")
604	ensureListContains(t, fullDepsInfo, "  mylib2(minSdkVersion:(no version)) <- mylib")
605	ensureListContains(t, fullDepsInfo, "  myotherjar(minSdkVersion:(no version)) <- myjar")
606	ensureListContains(t, fullDepsInfo, "  mysharedjar(minSdkVersion:(no version)) (external) <- myjar")
607
608	flatDepsInfo := strings.Split(ctx.ModuleForTests("myapex", "android_common_myapex_image").Output("depsinfo/flatlist.txt").Args["content"], "\\n")
609	ensureListContains(t, flatDepsInfo, "myjar(minSdkVersion:(no version))")
610	ensureListContains(t, flatDepsInfo, "mylib2(minSdkVersion:(no version))")
611	ensureListContains(t, flatDepsInfo, "myotherjar(minSdkVersion:(no version))")
612	ensureListContains(t, flatDepsInfo, "mysharedjar(minSdkVersion:(no version)) (external)")
613}
614
615func TestDefaults(t *testing.T) {
616	ctx := testApex(t, `
617		apex_defaults {
618			name: "myapex-defaults",
619			key: "myapex.key",
620			prebuilts: ["myetc"],
621			native_shared_libs: ["mylib"],
622			java_libs: ["myjar"],
623			apps: ["AppFoo"],
624			rros: ["rro"],
625			bpfs: ["bpf"],
626			updatable: false,
627		}
628
629		prebuilt_etc {
630			name: "myetc",
631			src: "myprebuilt",
632		}
633
634		apex {
635			name: "myapex",
636			defaults: ["myapex-defaults"],
637		}
638
639		apex_key {
640			name: "myapex.key",
641			public_key: "testkey.avbpubkey",
642			private_key: "testkey.pem",
643		}
644
645		cc_library {
646			name: "mylib",
647			system_shared_libs: [],
648			stl: "none",
649			apex_available: [ "myapex" ],
650		}
651
652		java_library {
653			name: "myjar",
654			srcs: ["foo/bar/MyClass.java"],
655			sdk_version: "none",
656			system_modules: "none",
657			apex_available: [ "myapex" ],
658		}
659
660		android_app {
661			name: "AppFoo",
662			srcs: ["foo/bar/MyClass.java"],
663			sdk_version: "none",
664			system_modules: "none",
665			apex_available: [ "myapex" ],
666		}
667
668		runtime_resource_overlay {
669			name: "rro",
670			theme: "blue",
671		}
672
673		bpf {
674			name: "bpf",
675			srcs: ["bpf.c", "bpf2.c"],
676		}
677
678	`)
679	ensureExactContents(t, ctx, "myapex", "android_common_myapex_image", []string{
680		"etc/myetc",
681		"javalib/myjar.jar",
682		"lib64/mylib.so",
683		"app/AppFoo/AppFoo.apk",
684		"overlay/blue/rro.apk",
685		"etc/bpf/bpf.o",
686		"etc/bpf/bpf2.o",
687	})
688}
689
690func TestApexManifest(t *testing.T) {
691	ctx := testApex(t, `
692		apex {
693			name: "myapex",
694			key: "myapex.key",
695			updatable: false,
696		}
697
698		apex_key {
699			name: "myapex.key",
700			public_key: "testkey.avbpubkey",
701			private_key: "testkey.pem",
702		}
703	`)
704
705	module := ctx.ModuleForTests("myapex", "android_common_myapex_image")
706	args := module.Rule("apexRule").Args
707	if manifest := args["manifest"]; manifest != module.Output("apex_manifest.pb").Output.String() {
708		t.Error("manifest should be apex_manifest.pb, but " + manifest)
709	}
710}
711
712func TestBasicZipApex(t *testing.T) {
713	ctx := testApex(t, `
714		apex {
715			name: "myapex",
716			key: "myapex.key",
717			payload_type: "zip",
718			native_shared_libs: ["mylib"],
719			updatable: false,
720		}
721
722		apex_key {
723			name: "myapex.key",
724			public_key: "testkey.avbpubkey",
725			private_key: "testkey.pem",
726		}
727
728		cc_library {
729			name: "mylib",
730			srcs: ["mylib.cpp"],
731			shared_libs: ["mylib2"],
732			system_shared_libs: [],
733			stl: "none",
734			apex_available: [ "myapex" ],
735		}
736
737		cc_library {
738			name: "mylib2",
739			srcs: ["mylib.cpp"],
740			system_shared_libs: [],
741			stl: "none",
742			apex_available: [ "myapex" ],
743		}
744	`)
745
746	zipApexRule := ctx.ModuleForTests("myapex", "android_common_myapex_zip").Rule("zipApexRule")
747	copyCmds := zipApexRule.Args["copy_commands"]
748
749	// Ensure that main rule creates an output
750	ensureContains(t, zipApexRule.Output.String(), "myapex.zipapex.unsigned")
751
752	// Ensure that APEX variant is created for the direct dep
753	ensureListContains(t, ctx.ModuleVariantsForTests("mylib"), "android_arm64_armv8-a_shared_apex10000")
754
755	// Ensure that APEX variant is created for the indirect dep
756	ensureListContains(t, ctx.ModuleVariantsForTests("mylib2"), "android_arm64_armv8-a_shared_apex10000")
757
758	// Ensure that both direct and indirect deps are copied into apex
759	ensureContains(t, copyCmds, "image.zipapex/lib64/mylib.so")
760	ensureContains(t, copyCmds, "image.zipapex/lib64/mylib2.so")
761}
762
763func TestApexWithStubs(t *testing.T) {
764	ctx := testApex(t, `
765		apex {
766			name: "myapex",
767			key: "myapex.key",
768			native_shared_libs: ["mylib", "mylib3"],
769			updatable: false,
770		}
771
772		apex_key {
773			name: "myapex.key",
774			public_key: "testkey.avbpubkey",
775			private_key: "testkey.pem",
776		}
777
778		cc_library {
779			name: "mylib",
780			srcs: ["mylib.cpp"],
781			shared_libs: ["mylib2", "mylib3"],
782			system_shared_libs: [],
783			stl: "none",
784			apex_available: [ "myapex" ],
785		}
786
787		cc_library {
788			name: "mylib2",
789			srcs: ["mylib.cpp"],
790			cflags: ["-include mylib.h"],
791			system_shared_libs: [],
792			stl: "none",
793			stubs: {
794				versions: ["1", "2", "3"],
795			},
796		}
797
798		cc_library {
799			name: "mylib3",
800			srcs: ["mylib.cpp"],
801			shared_libs: ["mylib4"],
802			system_shared_libs: [],
803			stl: "none",
804			stubs: {
805				versions: ["10", "11", "12"],
806			},
807			apex_available: [ "myapex" ],
808		}
809
810		cc_library {
811			name: "mylib4",
812			srcs: ["mylib.cpp"],
813			system_shared_libs: [],
814			stl: "none",
815			apex_available: [ "myapex" ],
816		}
817	`)
818
819	apexRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("apexRule")
820	copyCmds := apexRule.Args["copy_commands"]
821
822	// Ensure that direct non-stubs dep is always included
823	ensureContains(t, copyCmds, "image.apex/lib64/mylib.so")
824
825	// Ensure that indirect stubs dep is not included
826	ensureNotContains(t, copyCmds, "image.apex/lib64/mylib2.so")
827
828	// Ensure that direct stubs dep is included
829	ensureContains(t, copyCmds, "image.apex/lib64/mylib3.so")
830
831	mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_apex10000").Rule("ld").Args["libFlags"]
832
833	// Ensure that mylib is linking with the latest version of stubs for mylib2
834	ensureContains(t, mylibLdFlags, "mylib2/android_arm64_armv8-a_shared_current/mylib2.so")
835	// ... and not linking to the non-stub (impl) variant of mylib2
836	ensureNotContains(t, mylibLdFlags, "mylib2/android_arm64_armv8-a_shared/mylib2.so")
837
838	// Ensure that mylib is linking with the non-stub (impl) of mylib3 (because mylib3 is in the same apex)
839	ensureContains(t, mylibLdFlags, "mylib3/android_arm64_armv8-a_shared_apex10000/mylib3.so")
840	// .. and not linking to the stubs variant of mylib3
841	ensureNotContains(t, mylibLdFlags, "mylib3/android_arm64_armv8-a_shared_12/mylib3.so")
842
843	// Ensure that stubs libs are built without -include flags
844	mylib2Cflags := ctx.ModuleForTests("mylib2", "android_arm64_armv8-a_static").Rule("cc").Args["cFlags"]
845	ensureNotContains(t, mylib2Cflags, "-include ")
846
847	// Ensure that genstub is invoked with --apex
848	ensureContains(t, "--apex", ctx.ModuleForTests("mylib2", "android_arm64_armv8-a_shared_3").Rule("genStubSrc").Args["flags"])
849
850	ensureExactContents(t, ctx, "myapex", "android_common_myapex_image", []string{
851		"lib64/mylib.so",
852		"lib64/mylib3.so",
853		"lib64/mylib4.so",
854	})
855}
856
857func TestApexWithStubsWithMinSdkVersion(t *testing.T) {
858	t.Parallel()
859	ctx := testApex(t, `
860		apex {
861			name: "myapex",
862			key: "myapex.key",
863			native_shared_libs: ["mylib", "mylib3"],
864			min_sdk_version: "29",
865		}
866
867		apex_key {
868			name: "myapex.key",
869			public_key: "testkey.avbpubkey",
870			private_key: "testkey.pem",
871		}
872
873		cc_library {
874			name: "mylib",
875			srcs: ["mylib.cpp"],
876			shared_libs: ["mylib2", "mylib3"],
877			system_shared_libs: [],
878			stl: "none",
879			apex_available: [ "myapex" ],
880			min_sdk_version: "28",
881		}
882
883		cc_library {
884			name: "mylib2",
885			srcs: ["mylib.cpp"],
886			cflags: ["-include mylib.h"],
887			system_shared_libs: [],
888			stl: "none",
889			stubs: {
890				versions: ["28", "29", "30", "current"],
891			},
892			min_sdk_version: "28",
893		}
894
895		cc_library {
896			name: "mylib3",
897			srcs: ["mylib.cpp"],
898			shared_libs: ["mylib4"],
899			system_shared_libs: [],
900			stl: "none",
901			stubs: {
902				versions: ["28", "29", "30", "current"],
903			},
904			apex_available: [ "myapex" ],
905			min_sdk_version: "28",
906		}
907
908		cc_library {
909			name: "mylib4",
910			srcs: ["mylib.cpp"],
911			system_shared_libs: [],
912			stl: "none",
913			apex_available: [ "myapex" ],
914			min_sdk_version: "28",
915		}
916	`)
917
918	apexRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("apexRule")
919	copyCmds := apexRule.Args["copy_commands"]
920
921	// Ensure that direct non-stubs dep is always included
922	ensureContains(t, copyCmds, "image.apex/lib64/mylib.so")
923
924	// Ensure that indirect stubs dep is not included
925	ensureNotContains(t, copyCmds, "image.apex/lib64/mylib2.so")
926
927	// Ensure that direct stubs dep is included
928	ensureContains(t, copyCmds, "image.apex/lib64/mylib3.so")
929
930	mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_apex29").Rule("ld").Args["libFlags"]
931
932	// Ensure that mylib is linking with the latest version of stub for mylib2
933	ensureContains(t, mylibLdFlags, "mylib2/android_arm64_armv8-a_shared_current/mylib2.so")
934	// ... and not linking to the non-stub (impl) variant of mylib2
935	ensureNotContains(t, mylibLdFlags, "mylib2/android_arm64_armv8-a_shared/mylib2.so")
936
937	// Ensure that mylib is linking with the non-stub (impl) of mylib3 (because mylib3 is in the same apex)
938	ensureContains(t, mylibLdFlags, "mylib3/android_arm64_armv8-a_shared_apex29/mylib3.so")
939	// .. and not linking to the stubs variant of mylib3
940	ensureNotContains(t, mylibLdFlags, "mylib3/android_arm64_armv8-a_shared_29/mylib3.so")
941
942	// Ensure that stubs libs are built without -include flags
943	mylib2Cflags := ctx.ModuleForTests("mylib2", "android_arm64_armv8-a_shared_29").Rule("cc").Args["cFlags"]
944	ensureNotContains(t, mylib2Cflags, "-include ")
945
946	// Ensure that genstub is invoked with --apex
947	ensureContains(t, "--apex", ctx.ModuleForTests("mylib2", "android_arm64_armv8-a_shared_29").Rule("genStubSrc").Args["flags"])
948
949	ensureExactContents(t, ctx, "myapex", "android_common_myapex_image", []string{
950		"lib64/mylib.so",
951		"lib64/mylib3.so",
952		"lib64/mylib4.so",
953	})
954}
955
956func TestApex_PlatformUsesLatestStubFromApex(t *testing.T) {
957	t.Parallel()
958	//   myapex (Z)
959	//      mylib -----------------.
960	//                             |
961	//   otherapex (29)            |
962	//      libstub's versions: 29 Z current
963	//                                  |
964	//   <platform>                     |
965	//      libplatform ----------------'
966	ctx := testApex(t, `
967		apex {
968			name: "myapex",
969			key: "myapex.key",
970			native_shared_libs: ["mylib"],
971			min_sdk_version: "Z", // non-final
972		}
973
974		cc_library {
975			name: "mylib",
976			srcs: ["mylib.cpp"],
977			shared_libs: ["libstub"],
978			apex_available: ["myapex"],
979			min_sdk_version: "Z",
980		}
981
982		apex_key {
983			name: "myapex.key",
984			public_key: "testkey.avbpubkey",
985			private_key: "testkey.pem",
986		}
987
988		apex {
989			name: "otherapex",
990			key: "myapex.key",
991			native_shared_libs: ["libstub"],
992			min_sdk_version: "29",
993		}
994
995		cc_library {
996			name: "libstub",
997			srcs: ["mylib.cpp"],
998			stubs: {
999				versions: ["29", "Z", "current"],
1000			},
1001			apex_available: ["otherapex"],
1002			min_sdk_version: "29",
1003		}
1004
1005		// platform module depending on libstub from otherapex should use the latest stub("current")
1006		cc_library {
1007			name: "libplatform",
1008			srcs: ["mylib.cpp"],
1009			shared_libs: ["libstub"],
1010		}
1011	`,
1012		android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
1013			variables.Platform_sdk_codename = proptools.StringPtr("Z")
1014			variables.Platform_sdk_final = proptools.BoolPtr(false)
1015			variables.Platform_version_active_codenames = []string{"Z"}
1016		}),
1017	)
1018
1019	// Ensure that mylib from myapex is built against the latest stub (current)
1020	mylibCflags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_static_apex10000").Rule("cc").Args["cFlags"]
1021	ensureContains(t, mylibCflags, "-D__LIBSTUB_API__=10000 ")
1022	mylibLdflags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_apex10000").Rule("ld").Args["libFlags"]
1023	ensureContains(t, mylibLdflags, "libstub/android_arm64_armv8-a_shared_current/libstub.so ")
1024
1025	// Ensure that libplatform is built against latest stub ("current") of mylib3 from the apex
1026	libplatformCflags := ctx.ModuleForTests("libplatform", "android_arm64_armv8-a_static").Rule("cc").Args["cFlags"]
1027	ensureContains(t, libplatformCflags, "-D__LIBSTUB_API__=10000 ") // "current" maps to 10000
1028	libplatformLdflags := ctx.ModuleForTests("libplatform", "android_arm64_armv8-a_shared").Rule("ld").Args["libFlags"]
1029	ensureContains(t, libplatformLdflags, "libstub/android_arm64_armv8-a_shared_current/libstub.so ")
1030}
1031
1032func TestApexWithExplicitStubsDependency(t *testing.T) {
1033	ctx := testApex(t, `
1034		apex {
1035			name: "myapex2",
1036			key: "myapex2.key",
1037			native_shared_libs: ["mylib"],
1038			updatable: false,
1039		}
1040
1041		apex_key {
1042			name: "myapex2.key",
1043			public_key: "testkey.avbpubkey",
1044			private_key: "testkey.pem",
1045		}
1046
1047		cc_library {
1048			name: "mylib",
1049			srcs: ["mylib.cpp"],
1050			shared_libs: ["libfoo#10"],
1051			static_libs: ["libbaz"],
1052			system_shared_libs: [],
1053			stl: "none",
1054			apex_available: [ "myapex2" ],
1055		}
1056
1057		cc_library {
1058			name: "libfoo",
1059			srcs: ["mylib.cpp"],
1060			shared_libs: ["libbar"],
1061			system_shared_libs: [],
1062			stl: "none",
1063			stubs: {
1064				versions: ["10", "20", "30"],
1065			},
1066		}
1067
1068		cc_library {
1069			name: "libbar",
1070			srcs: ["mylib.cpp"],
1071			system_shared_libs: [],
1072			stl: "none",
1073		}
1074
1075		cc_library_static {
1076			name: "libbaz",
1077			srcs: ["mylib.cpp"],
1078			system_shared_libs: [],
1079			stl: "none",
1080			apex_available: [ "myapex2" ],
1081		}
1082
1083	`)
1084
1085	apexRule := ctx.ModuleForTests("myapex2", "android_common_myapex2_image").Rule("apexRule")
1086	copyCmds := apexRule.Args["copy_commands"]
1087
1088	// Ensure that direct non-stubs dep is always included
1089	ensureContains(t, copyCmds, "image.apex/lib64/mylib.so")
1090
1091	// Ensure that indirect stubs dep is not included
1092	ensureNotContains(t, copyCmds, "image.apex/lib64/libfoo.so")
1093
1094	// Ensure that dependency of stubs is not included
1095	ensureNotContains(t, copyCmds, "image.apex/lib64/libbar.so")
1096
1097	mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_apex10000").Rule("ld").Args["libFlags"]
1098
1099	// Ensure that mylib is linking with version 10 of libfoo
1100	ensureContains(t, mylibLdFlags, "libfoo/android_arm64_armv8-a_shared_10/libfoo.so")
1101	// ... and not linking to the non-stub (impl) variant of libfoo
1102	ensureNotContains(t, mylibLdFlags, "libfoo/android_arm64_armv8-a_shared/libfoo.so")
1103
1104	libFooStubsLdFlags := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared_10").Rule("ld").Args["libFlags"]
1105
1106	// Ensure that libfoo stubs is not linking to libbar (since it is a stubs)
1107	ensureNotContains(t, libFooStubsLdFlags, "libbar.so")
1108
1109	fullDepsInfo := strings.Split(ctx.ModuleForTests("myapex2", "android_common_myapex2_image").Output("depsinfo/fulllist.txt").Args["content"], "\\n")
1110	ensureListContains(t, fullDepsInfo, "  libfoo(minSdkVersion:(no version)) (external) <- mylib")
1111
1112	flatDepsInfo := strings.Split(ctx.ModuleForTests("myapex2", "android_common_myapex2_image").Output("depsinfo/flatlist.txt").Args["content"], "\\n")
1113	ensureListContains(t, flatDepsInfo, "libfoo(minSdkVersion:(no version)) (external)")
1114}
1115
1116func TestApexWithRuntimeLibsDependency(t *testing.T) {
1117	/*
1118		myapex
1119		  |
1120		  v   (runtime_libs)
1121		mylib ------+------> libfoo [provides stub]
1122			    |
1123			    `------> libbar
1124	*/
1125	ctx := testApex(t, `
1126		apex {
1127			name: "myapex",
1128			key: "myapex.key",
1129			native_shared_libs: ["mylib"],
1130			updatable: false,
1131		}
1132
1133		apex_key {
1134			name: "myapex.key",
1135			public_key: "testkey.avbpubkey",
1136			private_key: "testkey.pem",
1137		}
1138
1139		cc_library {
1140			name: "mylib",
1141			srcs: ["mylib.cpp"],
1142			runtime_libs: ["libfoo", "libbar"],
1143			system_shared_libs: [],
1144			stl: "none",
1145			apex_available: [ "myapex" ],
1146		}
1147
1148		cc_library {
1149			name: "libfoo",
1150			srcs: ["mylib.cpp"],
1151			system_shared_libs: [],
1152			stl: "none",
1153			stubs: {
1154				versions: ["10", "20", "30"],
1155			},
1156		}
1157
1158		cc_library {
1159			name: "libbar",
1160			srcs: ["mylib.cpp"],
1161			system_shared_libs: [],
1162			stl: "none",
1163			apex_available: [ "myapex" ],
1164		}
1165
1166	`)
1167
1168	apexRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("apexRule")
1169	copyCmds := apexRule.Args["copy_commands"]
1170
1171	// Ensure that direct non-stubs dep is always included
1172	ensureContains(t, copyCmds, "image.apex/lib64/mylib.so")
1173
1174	// Ensure that indirect stubs dep is not included
1175	ensureNotContains(t, copyCmds, "image.apex/lib64/libfoo.so")
1176
1177	// Ensure that runtime_libs dep in included
1178	ensureContains(t, copyCmds, "image.apex/lib64/libbar.so")
1179
1180	apexManifestRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("apexManifestRule")
1181	ensureListEmpty(t, names(apexManifestRule.Args["provideNativeLibs"]))
1182	ensureListContains(t, names(apexManifestRule.Args["requireNativeLibs"]), "libfoo.so")
1183
1184}
1185
1186var prepareForTestOfRuntimeApexWithHwasan = android.GroupFixturePreparers(
1187	cc.PrepareForTestWithCcBuildComponents,
1188	PrepareForTestWithApexBuildComponents,
1189	android.FixtureAddTextFile("bionic/apex/Android.bp", `
1190		apex {
1191			name: "com.android.runtime",
1192			key: "com.android.runtime.key",
1193			native_shared_libs: ["libc"],
1194			updatable: false,
1195		}
1196
1197		apex_key {
1198			name: "com.android.runtime.key",
1199			public_key: "testkey.avbpubkey",
1200			private_key: "testkey.pem",
1201		}
1202	`),
1203	android.FixtureAddFile("system/sepolicy/apex/com.android.runtime-file_contexts", nil),
1204)
1205
1206func TestRuntimeApexShouldInstallHwasanIfLibcDependsOnIt(t *testing.T) {
1207	result := android.GroupFixturePreparers(prepareForTestOfRuntimeApexWithHwasan).RunTestWithBp(t, `
1208		cc_library {
1209			name: "libc",
1210			no_libcrt: true,
1211			nocrt: true,
1212			stl: "none",
1213			system_shared_libs: [],
1214			stubs: { versions: ["1"] },
1215			apex_available: ["com.android.runtime"],
1216
1217			sanitize: {
1218				hwaddress: true,
1219			}
1220		}
1221
1222		cc_prebuilt_library_shared {
1223			name: "libclang_rt.hwasan-aarch64-android",
1224			no_libcrt: true,
1225			nocrt: true,
1226			stl: "none",
1227			system_shared_libs: [],
1228			srcs: [""],
1229			stubs: { versions: ["1"] },
1230
1231			sanitize: {
1232				never: true,
1233			},
1234		}	`)
1235	ctx := result.TestContext
1236
1237	ensureExactContents(t, ctx, "com.android.runtime", "android_common_hwasan_com.android.runtime_image", []string{
1238		"lib64/bionic/libc.so",
1239		"lib64/bionic/libclang_rt.hwasan-aarch64-android.so",
1240	})
1241
1242	hwasan := ctx.ModuleForTests("libclang_rt.hwasan-aarch64-android", "android_arm64_armv8-a_shared")
1243
1244	installed := hwasan.Description("install libclang_rt.hwasan")
1245	ensureContains(t, installed.Output.String(), "/system/lib64/bootstrap/libclang_rt.hwasan-aarch64-android.so")
1246
1247	symlink := hwasan.Description("install symlink libclang_rt.hwasan")
1248	ensureEquals(t, symlink.Args["fromPath"], "/apex/com.android.runtime/lib64/bionic/libclang_rt.hwasan-aarch64-android.so")
1249	ensureContains(t, symlink.Output.String(), "/system/lib64/libclang_rt.hwasan-aarch64-android.so")
1250}
1251
1252func TestRuntimeApexShouldInstallHwasanIfHwaddressSanitized(t *testing.T) {
1253	result := android.GroupFixturePreparers(
1254		prepareForTestOfRuntimeApexWithHwasan,
1255		android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
1256			variables.SanitizeDevice = []string{"hwaddress"}
1257		}),
1258	).RunTestWithBp(t, `
1259		cc_library {
1260			name: "libc",
1261			no_libcrt: true,
1262			nocrt: true,
1263			stl: "none",
1264			system_shared_libs: [],
1265			stubs: { versions: ["1"] },
1266			apex_available: ["com.android.runtime"],
1267		}
1268
1269		cc_prebuilt_library_shared {
1270			name: "libclang_rt.hwasan-aarch64-android",
1271			no_libcrt: true,
1272			nocrt: true,
1273			stl: "none",
1274			system_shared_libs: [],
1275			srcs: [""],
1276			stubs: { versions: ["1"] },
1277
1278			sanitize: {
1279				never: true,
1280			},
1281		}
1282		`)
1283	ctx := result.TestContext
1284
1285	ensureExactContents(t, ctx, "com.android.runtime", "android_common_hwasan_com.android.runtime_image", []string{
1286		"lib64/bionic/libc.so",
1287		"lib64/bionic/libclang_rt.hwasan-aarch64-android.so",
1288	})
1289
1290	hwasan := ctx.ModuleForTests("libclang_rt.hwasan-aarch64-android", "android_arm64_armv8-a_shared")
1291
1292	installed := hwasan.Description("install libclang_rt.hwasan")
1293	ensureContains(t, installed.Output.String(), "/system/lib64/bootstrap/libclang_rt.hwasan-aarch64-android.so")
1294
1295	symlink := hwasan.Description("install symlink libclang_rt.hwasan")
1296	ensureEquals(t, symlink.Args["fromPath"], "/apex/com.android.runtime/lib64/bionic/libclang_rt.hwasan-aarch64-android.so")
1297	ensureContains(t, symlink.Output.String(), "/system/lib64/libclang_rt.hwasan-aarch64-android.so")
1298}
1299
1300func TestApexDependsOnLLNDKTransitively(t *testing.T) {
1301	testcases := []struct {
1302		name          string
1303		minSdkVersion string
1304		apexVariant   string
1305		shouldLink    string
1306		shouldNotLink []string
1307	}{
1308		{
1309			name:          "unspecified version links to the latest",
1310			minSdkVersion: "",
1311			apexVariant:   "apex10000",
1312			shouldLink:    "current",
1313			shouldNotLink: []string{"29", "30"},
1314		},
1315		{
1316			name:          "always use the latest",
1317			minSdkVersion: "min_sdk_version: \"29\",",
1318			apexVariant:   "apex29",
1319			shouldLink:    "current",
1320			shouldNotLink: []string{"29", "30"},
1321		},
1322	}
1323	for _, tc := range testcases {
1324		t.Run(tc.name, func(t *testing.T) {
1325			ctx := testApex(t, `
1326			apex {
1327				name: "myapex",
1328				key: "myapex.key",
1329				native_shared_libs: ["mylib"],
1330				updatable: false,
1331				`+tc.minSdkVersion+`
1332			}
1333
1334			apex_key {
1335				name: "myapex.key",
1336				public_key: "testkey.avbpubkey",
1337				private_key: "testkey.pem",
1338			}
1339
1340			cc_library {
1341				name: "mylib",
1342				srcs: ["mylib.cpp"],
1343				vendor_available: true,
1344				shared_libs: ["libbar"],
1345				system_shared_libs: [],
1346				stl: "none",
1347				apex_available: [ "myapex" ],
1348				min_sdk_version: "29",
1349			}
1350
1351			cc_library {
1352				name: "libbar",
1353				srcs: ["mylib.cpp"],
1354				system_shared_libs: [],
1355				stl: "none",
1356				stubs: { versions: ["29","30"] },
1357				llndk: {
1358					symbol_file: "libbar.map.txt",
1359				}
1360			}
1361			`,
1362				withUnbundledBuild,
1363			)
1364
1365			// Ensure that LLNDK dep is not included
1366			ensureExactContents(t, ctx, "myapex", "android_common_myapex_image", []string{
1367				"lib64/mylib.so",
1368			})
1369
1370			// Ensure that LLNDK dep is required
1371			apexManifestRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("apexManifestRule")
1372			ensureListEmpty(t, names(apexManifestRule.Args["provideNativeLibs"]))
1373			ensureListContains(t, names(apexManifestRule.Args["requireNativeLibs"]), "libbar.so")
1374
1375			mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_"+tc.apexVariant).Rule("ld").Args["libFlags"]
1376			ensureContains(t, mylibLdFlags, "libbar/android_arm64_armv8-a_shared_"+tc.shouldLink+"/libbar.so")
1377			for _, ver := range tc.shouldNotLink {
1378				ensureNotContains(t, mylibLdFlags, "libbar/android_arm64_armv8-a_shared_"+ver+"/libbar.so")
1379			}
1380
1381			mylibCFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_static_"+tc.apexVariant).Rule("cc").Args["cFlags"]
1382			ver := tc.shouldLink
1383			if tc.shouldLink == "current" {
1384				ver = strconv.Itoa(android.FutureApiLevelInt)
1385			}
1386			ensureContains(t, mylibCFlags, "__LIBBAR_API__="+ver)
1387		})
1388	}
1389}
1390
1391func TestApexWithSystemLibsStubs(t *testing.T) {
1392	ctx := testApex(t, `
1393		apex {
1394			name: "myapex",
1395			key: "myapex.key",
1396			native_shared_libs: ["mylib", "mylib_shared", "libdl", "libm"],
1397			updatable: false,
1398		}
1399
1400		apex_key {
1401			name: "myapex.key",
1402			public_key: "testkey.avbpubkey",
1403			private_key: "testkey.pem",
1404		}
1405
1406		cc_library {
1407			name: "mylib",
1408			srcs: ["mylib.cpp"],
1409			system_shared_libs: ["libc", "libm"],
1410			shared_libs: ["libdl#27"],
1411			stl: "none",
1412			apex_available: [ "myapex" ],
1413		}
1414
1415		cc_library_shared {
1416			name: "mylib_shared",
1417			srcs: ["mylib.cpp"],
1418			shared_libs: ["libdl#27"],
1419			stl: "none",
1420			apex_available: [ "myapex" ],
1421		}
1422
1423		cc_library {
1424			name: "libBootstrap",
1425			srcs: ["mylib.cpp"],
1426			stl: "none",
1427			bootstrap: true,
1428		}
1429	`)
1430
1431	apexRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("apexRule")
1432	copyCmds := apexRule.Args["copy_commands"]
1433
1434	// Ensure that mylib, libm, libdl are included.
1435	ensureContains(t, copyCmds, "image.apex/lib64/mylib.so")
1436	ensureContains(t, copyCmds, "image.apex/lib64/bionic/libm.so")
1437	ensureContains(t, copyCmds, "image.apex/lib64/bionic/libdl.so")
1438
1439	// Ensure that libc is not included (since it has stubs and not listed in native_shared_libs)
1440	ensureNotContains(t, copyCmds, "image.apex/lib64/bionic/libc.so")
1441
1442	mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_apex10000").Rule("ld").Args["libFlags"]
1443	mylibCFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_static_apex10000").Rule("cc").Args["cFlags"]
1444	mylibSharedCFlags := ctx.ModuleForTests("mylib_shared", "android_arm64_armv8-a_shared_apex10000").Rule("cc").Args["cFlags"]
1445
1446	// For dependency to libc
1447	// Ensure that mylib is linking with the latest version of stubs
1448	ensureContains(t, mylibLdFlags, "libc/android_arm64_armv8-a_shared_current/libc.so")
1449	// ... and not linking to the non-stub (impl) variant
1450	ensureNotContains(t, mylibLdFlags, "libc/android_arm64_armv8-a_shared/libc.so")
1451	// ... Cflags from stub is correctly exported to mylib
1452	ensureContains(t, mylibCFlags, "__LIBC_API__=10000")
1453	ensureContains(t, mylibSharedCFlags, "__LIBC_API__=10000")
1454
1455	// For dependency to libm
1456	// Ensure that mylib is linking with the non-stub (impl) variant
1457	ensureContains(t, mylibLdFlags, "libm/android_arm64_armv8-a_shared_apex10000/libm.so")
1458	// ... and not linking to the stub variant
1459	ensureNotContains(t, mylibLdFlags, "libm/android_arm64_armv8-a_shared_29/libm.so")
1460	// ... and is not compiling with the stub
1461	ensureNotContains(t, mylibCFlags, "__LIBM_API__=29")
1462	ensureNotContains(t, mylibSharedCFlags, "__LIBM_API__=29")
1463
1464	// For dependency to libdl
1465	// Ensure that mylib is linking with the specified version of stubs
1466	ensureContains(t, mylibLdFlags, "libdl/android_arm64_armv8-a_shared_27/libdl.so")
1467	// ... and not linking to the other versions of stubs
1468	ensureNotContains(t, mylibLdFlags, "libdl/android_arm64_armv8-a_shared_28/libdl.so")
1469	ensureNotContains(t, mylibLdFlags, "libdl/android_arm64_armv8-a_shared_29/libdl.so")
1470	// ... and not linking to the non-stub (impl) variant
1471	ensureNotContains(t, mylibLdFlags, "libdl/android_arm64_armv8-a_shared_apex10000/libdl.so")
1472	// ... Cflags from stub is correctly exported to mylib
1473	ensureContains(t, mylibCFlags, "__LIBDL_API__=27")
1474	ensureContains(t, mylibSharedCFlags, "__LIBDL_API__=27")
1475
1476	// Ensure that libBootstrap is depending on the platform variant of bionic libs
1477	libFlags := ctx.ModuleForTests("libBootstrap", "android_arm64_armv8-a_shared").Rule("ld").Args["libFlags"]
1478	ensureContains(t, libFlags, "libc/android_arm64_armv8-a_shared/libc.so")
1479	ensureContains(t, libFlags, "libm/android_arm64_armv8-a_shared/libm.so")
1480	ensureContains(t, libFlags, "libdl/android_arm64_armv8-a_shared/libdl.so")
1481}
1482
1483func TestApexMinSdkVersion_NativeModulesShouldBeBuiltAgainstStubs(t *testing.T) {
1484	// there are three links between liba --> libz.
1485	// 1) myapex -> libx -> liba -> libz    : this should be #30 link
1486	// 2) otherapex -> liby -> liba -> libz : this should be #30 link
1487	// 3) (platform) -> liba -> libz        : this should be non-stub link
1488	ctx := testApex(t, `
1489		apex {
1490			name: "myapex",
1491			key: "myapex.key",
1492			native_shared_libs: ["libx"],
1493			min_sdk_version: "29",
1494		}
1495
1496		apex {
1497			name: "otherapex",
1498			key: "myapex.key",
1499			native_shared_libs: ["liby"],
1500			min_sdk_version: "30",
1501		}
1502
1503		apex_key {
1504			name: "myapex.key",
1505			public_key: "testkey.avbpubkey",
1506			private_key: "testkey.pem",
1507		}
1508
1509		cc_library {
1510			name: "libx",
1511			shared_libs: ["liba"],
1512			system_shared_libs: [],
1513			stl: "none",
1514			apex_available: [ "myapex" ],
1515			min_sdk_version: "29",
1516		}
1517
1518		cc_library {
1519			name: "liby",
1520			shared_libs: ["liba"],
1521			system_shared_libs: [],
1522			stl: "none",
1523			apex_available: [ "otherapex" ],
1524			min_sdk_version: "29",
1525		}
1526
1527		cc_library {
1528			name: "liba",
1529			shared_libs: ["libz"],
1530			system_shared_libs: [],
1531			stl: "none",
1532			apex_available: [
1533				"//apex_available:anyapex",
1534				"//apex_available:platform",
1535			],
1536			min_sdk_version: "29",
1537		}
1538
1539		cc_library {
1540			name: "libz",
1541			system_shared_libs: [],
1542			stl: "none",
1543			stubs: {
1544				versions: ["28", "30"],
1545			},
1546		}
1547	`)
1548
1549	expectLink := func(from, from_variant, to, to_variant string) {
1550		ldArgs := ctx.ModuleForTests(from, "android_arm64_armv8-a_"+from_variant).Rule("ld").Args["libFlags"]
1551		ensureContains(t, ldArgs, "android_arm64_armv8-a_"+to_variant+"/"+to+".so")
1552	}
1553	expectNoLink := func(from, from_variant, to, to_variant string) {
1554		ldArgs := ctx.ModuleForTests(from, "android_arm64_armv8-a_"+from_variant).Rule("ld").Args["libFlags"]
1555		ensureNotContains(t, ldArgs, "android_arm64_armv8-a_"+to_variant+"/"+to+".so")
1556	}
1557	// platform liba is linked to non-stub version
1558	expectLink("liba", "shared", "libz", "shared")
1559	// liba in myapex is linked to current
1560	expectLink("liba", "shared_apex29", "libz", "shared_current")
1561	expectNoLink("liba", "shared_apex29", "libz", "shared_30")
1562	expectNoLink("liba", "shared_apex29", "libz", "shared_28")
1563	expectNoLink("liba", "shared_apex29", "libz", "shared")
1564	// liba in otherapex is linked to current
1565	expectLink("liba", "shared_apex30", "libz", "shared_current")
1566	expectNoLink("liba", "shared_apex30", "libz", "shared_30")
1567	expectNoLink("liba", "shared_apex30", "libz", "shared_28")
1568	expectNoLink("liba", "shared_apex30", "libz", "shared")
1569}
1570
1571func TestApexMinSdkVersion_SupportsCodeNames(t *testing.T) {
1572	ctx := testApex(t, `
1573		apex {
1574			name: "myapex",
1575			key: "myapex.key",
1576			native_shared_libs: ["libx"],
1577			min_sdk_version: "R",
1578		}
1579
1580		apex_key {
1581			name: "myapex.key",
1582			public_key: "testkey.avbpubkey",
1583			private_key: "testkey.pem",
1584		}
1585
1586		cc_library {
1587			name: "libx",
1588			shared_libs: ["libz"],
1589			system_shared_libs: [],
1590			stl: "none",
1591			apex_available: [ "myapex" ],
1592			min_sdk_version: "R",
1593		}
1594
1595		cc_library {
1596			name: "libz",
1597			system_shared_libs: [],
1598			stl: "none",
1599			stubs: {
1600				versions: ["29", "R"],
1601			},
1602		}
1603	`,
1604		android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
1605			variables.Platform_version_active_codenames = []string{"R"}
1606		}),
1607	)
1608
1609	expectLink := func(from, from_variant, to, to_variant string) {
1610		ldArgs := ctx.ModuleForTests(from, "android_arm64_armv8-a_"+from_variant).Rule("ld").Args["libFlags"]
1611		ensureContains(t, ldArgs, "android_arm64_armv8-a_"+to_variant+"/"+to+".so")
1612	}
1613	expectNoLink := func(from, from_variant, to, to_variant string) {
1614		ldArgs := ctx.ModuleForTests(from, "android_arm64_armv8-a_"+from_variant).Rule("ld").Args["libFlags"]
1615		ensureNotContains(t, ldArgs, "android_arm64_armv8-a_"+to_variant+"/"+to+".so")
1616	}
1617	expectLink("libx", "shared_apex10000", "libz", "shared_current")
1618	expectNoLink("libx", "shared_apex10000", "libz", "shared_R")
1619	expectNoLink("libx", "shared_apex10000", "libz", "shared_29")
1620	expectNoLink("libx", "shared_apex10000", "libz", "shared")
1621}
1622
1623func TestApexMinSdkVersion_DefaultsToLatest(t *testing.T) {
1624	ctx := testApex(t, `
1625		apex {
1626			name: "myapex",
1627			key: "myapex.key",
1628			native_shared_libs: ["libx"],
1629			updatable: false,
1630		}
1631
1632		apex_key {
1633			name: "myapex.key",
1634			public_key: "testkey.avbpubkey",
1635			private_key: "testkey.pem",
1636		}
1637
1638		cc_library {
1639			name: "libx",
1640			shared_libs: ["libz"],
1641			system_shared_libs: [],
1642			stl: "none",
1643			apex_available: [ "myapex" ],
1644		}
1645
1646		cc_library {
1647			name: "libz",
1648			system_shared_libs: [],
1649			stl: "none",
1650			stubs: {
1651				versions: ["1", "2"],
1652			},
1653		}
1654	`)
1655
1656	expectLink := func(from, from_variant, to, to_variant string) {
1657		ldArgs := ctx.ModuleForTests(from, "android_arm64_armv8-a_"+from_variant).Rule("ld").Args["libFlags"]
1658		ensureContains(t, ldArgs, "android_arm64_armv8-a_"+to_variant+"/"+to+".so")
1659	}
1660	expectNoLink := func(from, from_variant, to, to_variant string) {
1661		ldArgs := ctx.ModuleForTests(from, "android_arm64_armv8-a_"+from_variant).Rule("ld").Args["libFlags"]
1662		ensureNotContains(t, ldArgs, "android_arm64_armv8-a_"+to_variant+"/"+to+".so")
1663	}
1664	expectLink("libx", "shared_apex10000", "libz", "shared_current")
1665	expectNoLink("libx", "shared_apex10000", "libz", "shared_1")
1666	expectNoLink("libx", "shared_apex10000", "libz", "shared_2")
1667	expectNoLink("libx", "shared_apex10000", "libz", "shared")
1668}
1669
1670func TestPlatformUsesLatestStubsFromApexes(t *testing.T) {
1671	ctx := testApex(t, `
1672		apex {
1673			name: "myapex",
1674			key: "myapex.key",
1675			native_shared_libs: ["libx"],
1676			updatable: false,
1677		}
1678
1679		apex_key {
1680			name: "myapex.key",
1681			public_key: "testkey.avbpubkey",
1682			private_key: "testkey.pem",
1683		}
1684
1685		cc_library {
1686			name: "libx",
1687			system_shared_libs: [],
1688			stl: "none",
1689			apex_available: [ "myapex" ],
1690			stubs: {
1691				versions: ["1", "2"],
1692			},
1693		}
1694
1695		cc_library {
1696			name: "libz",
1697			shared_libs: ["libx"],
1698			system_shared_libs: [],
1699			stl: "none",
1700		}
1701	`)
1702
1703	expectLink := func(from, from_variant, to, to_variant string) {
1704		t.Helper()
1705		ldArgs := ctx.ModuleForTests(from, "android_arm64_armv8-a_"+from_variant).Rule("ld").Args["libFlags"]
1706		ensureContains(t, ldArgs, "android_arm64_armv8-a_"+to_variant+"/"+to+".so")
1707	}
1708	expectNoLink := func(from, from_variant, to, to_variant string) {
1709		t.Helper()
1710		ldArgs := ctx.ModuleForTests(from, "android_arm64_armv8-a_"+from_variant).Rule("ld").Args["libFlags"]
1711		ensureNotContains(t, ldArgs, "android_arm64_armv8-a_"+to_variant+"/"+to+".so")
1712	}
1713	expectLink("libz", "shared", "libx", "shared_current")
1714	expectNoLink("libz", "shared", "libx", "shared_2")
1715	expectNoLink("libz", "shared", "libz", "shared_1")
1716	expectNoLink("libz", "shared", "libz", "shared")
1717}
1718
1719var prepareForTestWithSantitizeHwaddress = android.FixtureModifyProductVariables(
1720	func(variables android.FixtureProductVariables) {
1721		variables.SanitizeDevice = []string{"hwaddress"}
1722	},
1723)
1724
1725func TestQApexesUseLatestStubsInBundledBuildsAndHWASAN(t *testing.T) {
1726	ctx := testApex(t, `
1727		apex {
1728			name: "myapex",
1729			key: "myapex.key",
1730			native_shared_libs: ["libx"],
1731			min_sdk_version: "29",
1732		}
1733
1734		apex_key {
1735			name: "myapex.key",
1736			public_key: "testkey.avbpubkey",
1737			private_key: "testkey.pem",
1738		}
1739
1740		cc_library {
1741			name: "libx",
1742			shared_libs: ["libbar"],
1743			apex_available: [ "myapex" ],
1744			min_sdk_version: "29",
1745		}
1746
1747		cc_library {
1748			name: "libbar",
1749			stubs: {
1750				versions: ["29", "30"],
1751			},
1752		}
1753	`,
1754		prepareForTestWithSantitizeHwaddress,
1755	)
1756	expectLink := func(from, from_variant, to, to_variant string) {
1757		ld := ctx.ModuleForTests(from, "android_arm64_armv8-a_"+from_variant).Rule("ld")
1758		libFlags := ld.Args["libFlags"]
1759		ensureContains(t, libFlags, "android_arm64_armv8-a_"+to_variant+"/"+to+".so")
1760	}
1761	expectLink("libx", "shared_hwasan_apex29", "libbar", "shared_current")
1762}
1763
1764func TestQTargetApexUsesStaticUnwinder(t *testing.T) {
1765	ctx := testApex(t, `
1766		apex {
1767			name: "myapex",
1768			key: "myapex.key",
1769			native_shared_libs: ["libx"],
1770			min_sdk_version: "29",
1771		}
1772
1773		apex_key {
1774			name: "myapex.key",
1775			public_key: "testkey.avbpubkey",
1776			private_key: "testkey.pem",
1777		}
1778
1779		cc_library {
1780			name: "libx",
1781			apex_available: [ "myapex" ],
1782			min_sdk_version: "29",
1783		}
1784	`)
1785
1786	// ensure apex variant of c++ is linked with static unwinder
1787	cm := ctx.ModuleForTests("libc++", "android_arm64_armv8-a_shared_apex29").Module().(*cc.Module)
1788	ensureListContains(t, cm.Properties.AndroidMkStaticLibs, "libunwind")
1789	// note that platform variant is not.
1790	cm = ctx.ModuleForTests("libc++", "android_arm64_armv8-a_shared").Module().(*cc.Module)
1791	ensureListNotContains(t, cm.Properties.AndroidMkStaticLibs, "libunwind")
1792}
1793
1794func TestApexMinSdkVersion_ErrorIfIncompatibleVersion(t *testing.T) {
1795	testApexError(t, `module "mylib".*: should support min_sdk_version\(29\)`, `
1796		apex {
1797			name: "myapex",
1798			key: "myapex.key",
1799			native_shared_libs: ["mylib"],
1800			min_sdk_version: "29",
1801		}
1802
1803		apex_key {
1804			name: "myapex.key",
1805			public_key: "testkey.avbpubkey",
1806			private_key: "testkey.pem",
1807		}
1808
1809		cc_library {
1810			name: "mylib",
1811			srcs: ["mylib.cpp"],
1812			system_shared_libs: [],
1813			stl: "none",
1814			apex_available: [
1815				"myapex",
1816			],
1817			min_sdk_version: "30",
1818		}
1819	`)
1820
1821	testApexError(t, `module "libfoo.ffi".*: should support min_sdk_version\(29\)`, `
1822		apex {
1823			name: "myapex",
1824			key: "myapex.key",
1825			native_shared_libs: ["libfoo.ffi"],
1826			min_sdk_version: "29",
1827		}
1828
1829		apex_key {
1830			name: "myapex.key",
1831			public_key: "testkey.avbpubkey",
1832			private_key: "testkey.pem",
1833		}
1834
1835		rust_ffi_shared {
1836			name: "libfoo.ffi",
1837			srcs: ["foo.rs"],
1838			crate_name: "foo",
1839			apex_available: [
1840				"myapex",
1841			],
1842			min_sdk_version: "30",
1843		}
1844	`)
1845
1846	testApexError(t, `module "libfoo".*: should support min_sdk_version\(29\)`, `
1847		apex {
1848			name: "myapex",
1849			key: "myapex.key",
1850			java_libs: ["libfoo"],
1851			min_sdk_version: "29",
1852		}
1853
1854		apex_key {
1855			name: "myapex.key",
1856			public_key: "testkey.avbpubkey",
1857			private_key: "testkey.pem",
1858		}
1859
1860		java_import {
1861			name: "libfoo",
1862			jars: ["libfoo.jar"],
1863			apex_available: [
1864				"myapex",
1865			],
1866			min_sdk_version: "30",
1867		}
1868	`)
1869}
1870
1871func TestApexMinSdkVersion_Okay(t *testing.T) {
1872	testApex(t, `
1873		apex {
1874			name: "myapex",
1875			key: "myapex.key",
1876			native_shared_libs: ["libfoo"],
1877			java_libs: ["libbar"],
1878			min_sdk_version: "29",
1879		}
1880
1881		apex_key {
1882			name: "myapex.key",
1883			public_key: "testkey.avbpubkey",
1884			private_key: "testkey.pem",
1885		}
1886
1887		cc_library {
1888			name: "libfoo",
1889			srcs: ["mylib.cpp"],
1890			shared_libs: ["libfoo_dep"],
1891			apex_available: ["myapex"],
1892			min_sdk_version: "29",
1893		}
1894
1895		cc_library {
1896			name: "libfoo_dep",
1897			srcs: ["mylib.cpp"],
1898			apex_available: ["myapex"],
1899			min_sdk_version: "29",
1900		}
1901
1902		java_library {
1903			name: "libbar",
1904			sdk_version: "current",
1905			srcs: ["a.java"],
1906			static_libs: [
1907				"libbar_dep",
1908				"libbar_import_dep",
1909			],
1910			apex_available: ["myapex"],
1911			min_sdk_version: "29",
1912		}
1913
1914		java_library {
1915			name: "libbar_dep",
1916			sdk_version: "current",
1917			srcs: ["a.java"],
1918			apex_available: ["myapex"],
1919			min_sdk_version: "29",
1920		}
1921
1922		java_import {
1923			name: "libbar_import_dep",
1924			jars: ["libbar.jar"],
1925			apex_available: ["myapex"],
1926			min_sdk_version: "29",
1927		}
1928	`)
1929}
1930
1931func TestJavaStableSdkVersion(t *testing.T) {
1932	testCases := []struct {
1933		name          string
1934		expectedError string
1935		bp            string
1936	}{
1937		{
1938			name: "Non-updatable apex with non-stable dep",
1939			bp: `
1940				apex {
1941					name: "myapex",
1942					java_libs: ["myjar"],
1943					key: "myapex.key",
1944					updatable: false,
1945				}
1946				apex_key {
1947					name: "myapex.key",
1948					public_key: "testkey.avbpubkey",
1949					private_key: "testkey.pem",
1950				}
1951				java_library {
1952					name: "myjar",
1953					srcs: ["foo/bar/MyClass.java"],
1954					sdk_version: "test_current",
1955					apex_available: ["myapex"],
1956				}
1957			`,
1958		},
1959		{
1960			name: "Updatable apex with stable dep",
1961			bp: `
1962				apex {
1963					name: "myapex",
1964					java_libs: ["myjar"],
1965					key: "myapex.key",
1966					updatable: true,
1967					min_sdk_version: "29",
1968				}
1969				apex_key {
1970					name: "myapex.key",
1971					public_key: "testkey.avbpubkey",
1972					private_key: "testkey.pem",
1973				}
1974				java_library {
1975					name: "myjar",
1976					srcs: ["foo/bar/MyClass.java"],
1977					sdk_version: "current",
1978					apex_available: ["myapex"],
1979					min_sdk_version: "29",
1980				}
1981			`,
1982		},
1983		{
1984			name:          "Updatable apex with non-stable dep",
1985			expectedError: "cannot depend on \"myjar\"",
1986			bp: `
1987				apex {
1988					name: "myapex",
1989					java_libs: ["myjar"],
1990					key: "myapex.key",
1991					updatable: true,
1992				}
1993				apex_key {
1994					name: "myapex.key",
1995					public_key: "testkey.avbpubkey",
1996					private_key: "testkey.pem",
1997				}
1998				java_library {
1999					name: "myjar",
2000					srcs: ["foo/bar/MyClass.java"],
2001					sdk_version: "test_current",
2002					apex_available: ["myapex"],
2003				}
2004			`,
2005		},
2006		{
2007			name: "Updatable apex with non-stable transitive dep",
2008			// This is not actually detecting that the transitive dependency is unstable, rather it is
2009			// detecting that the transitive dependency is building against a wider API surface than the
2010			// module that depends on it is using.
2011			expectedError: "compiles against Android API, but dependency \"transitive-jar\" is compiling against private API.",
2012			bp: `
2013				apex {
2014					name: "myapex",
2015					java_libs: ["myjar"],
2016					key: "myapex.key",
2017					updatable: true,
2018				}
2019				apex_key {
2020					name: "myapex.key",
2021					public_key: "testkey.avbpubkey",
2022					private_key: "testkey.pem",
2023				}
2024				java_library {
2025					name: "myjar",
2026					srcs: ["foo/bar/MyClass.java"],
2027					sdk_version: "current",
2028					apex_available: ["myapex"],
2029					static_libs: ["transitive-jar"],
2030				}
2031				java_library {
2032					name: "transitive-jar",
2033					srcs: ["foo/bar/MyClass.java"],
2034					sdk_version: "core_platform",
2035					apex_available: ["myapex"],
2036				}
2037			`,
2038		},
2039	}
2040
2041	for _, test := range testCases {
2042		t.Run(test.name, func(t *testing.T) {
2043			if test.expectedError == "" {
2044				testApex(t, test.bp)
2045			} else {
2046				testApexError(t, test.expectedError, test.bp)
2047			}
2048		})
2049	}
2050}
2051
2052func TestApexMinSdkVersion_ErrorIfDepIsNewer(t *testing.T) {
2053	testApexError(t, `module "mylib2".*: should support min_sdk_version\(29\) for "myapex"`, `
2054		apex {
2055			name: "myapex",
2056			key: "myapex.key",
2057			native_shared_libs: ["mylib"],
2058			min_sdk_version: "29",
2059		}
2060
2061		apex_key {
2062			name: "myapex.key",
2063			public_key: "testkey.avbpubkey",
2064			private_key: "testkey.pem",
2065		}
2066
2067		cc_library {
2068			name: "mylib",
2069			srcs: ["mylib.cpp"],
2070			shared_libs: ["mylib2"],
2071			system_shared_libs: [],
2072			stl: "none",
2073			apex_available: [
2074				"myapex",
2075			],
2076			min_sdk_version: "29",
2077		}
2078
2079		// indirect part of the apex
2080		cc_library {
2081			name: "mylib2",
2082			srcs: ["mylib.cpp"],
2083			system_shared_libs: [],
2084			stl: "none",
2085			apex_available: [
2086				"myapex",
2087			],
2088			min_sdk_version: "30",
2089		}
2090	`)
2091}
2092
2093func TestApexMinSdkVersion_ErrorIfDepIsNewer_Java(t *testing.T) {
2094	testApexError(t, `module "bar".*: should support min_sdk_version\(29\) for "myapex"`, `
2095		apex {
2096			name: "myapex",
2097			key: "myapex.key",
2098			apps: ["AppFoo"],
2099			min_sdk_version: "29",
2100		}
2101
2102		apex_key {
2103			name: "myapex.key",
2104			public_key: "testkey.avbpubkey",
2105			private_key: "testkey.pem",
2106		}
2107
2108		android_app {
2109			name: "AppFoo",
2110			srcs: ["foo/bar/MyClass.java"],
2111			sdk_version: "current",
2112			min_sdk_version: "29",
2113			system_modules: "none",
2114			stl: "none",
2115			static_libs: ["bar"],
2116			apex_available: [ "myapex" ],
2117		}
2118
2119		java_library {
2120			name: "bar",
2121			sdk_version: "current",
2122			srcs: ["a.java"],
2123			apex_available: [ "myapex" ],
2124		}
2125	`)
2126}
2127
2128func TestApexMinSdkVersion_OkayEvenWhenDepIsNewer_IfItSatisfiesApexMinSdkVersion(t *testing.T) {
2129	ctx := testApex(t, `
2130		apex {
2131			name: "myapex",
2132			key: "myapex.key",
2133			native_shared_libs: ["mylib"],
2134			min_sdk_version: "29",
2135		}
2136
2137		apex_key {
2138			name: "myapex.key",
2139			public_key: "testkey.avbpubkey",
2140			private_key: "testkey.pem",
2141		}
2142
2143		// mylib in myapex will link to mylib2#current
2144		// mylib in otherapex will link to mylib2(non-stub) in otherapex as well
2145		cc_library {
2146			name: "mylib",
2147			srcs: ["mylib.cpp"],
2148			shared_libs: ["mylib2"],
2149			system_shared_libs: [],
2150			stl: "none",
2151			apex_available: ["myapex", "otherapex"],
2152			min_sdk_version: "29",
2153		}
2154
2155		cc_library {
2156			name: "mylib2",
2157			srcs: ["mylib.cpp"],
2158			system_shared_libs: [],
2159			stl: "none",
2160			apex_available: ["otherapex"],
2161			stubs: { versions: ["29", "30"] },
2162			min_sdk_version: "30",
2163		}
2164
2165		apex {
2166			name: "otherapex",
2167			key: "myapex.key",
2168			native_shared_libs: ["mylib", "mylib2"],
2169			min_sdk_version: "30",
2170		}
2171	`)
2172	expectLink := func(from, from_variant, to, to_variant string) {
2173		ld := ctx.ModuleForTests(from, "android_arm64_armv8-a_"+from_variant).Rule("ld")
2174		libFlags := ld.Args["libFlags"]
2175		ensureContains(t, libFlags, "android_arm64_armv8-a_"+to_variant+"/"+to+".so")
2176	}
2177	expectLink("mylib", "shared_apex29", "mylib2", "shared_current")
2178	expectLink("mylib", "shared_apex30", "mylib2", "shared_apex30")
2179}
2180
2181func TestApexMinSdkVersion_WorksWithSdkCodename(t *testing.T) {
2182	withSAsActiveCodeNames := android.FixtureModifyProductVariables(
2183		func(variables android.FixtureProductVariables) {
2184			variables.Platform_sdk_codename = proptools.StringPtr("S")
2185			variables.Platform_version_active_codenames = []string{"S"}
2186		},
2187	)
2188	testApexError(t, `libbar.*: should support min_sdk_version\(S\)`, `
2189		apex {
2190			name: "myapex",
2191			key: "myapex.key",
2192			native_shared_libs: ["libfoo"],
2193			min_sdk_version: "S",
2194		}
2195		apex_key {
2196			name: "myapex.key",
2197			public_key: "testkey.avbpubkey",
2198			private_key: "testkey.pem",
2199		}
2200		cc_library {
2201			name: "libfoo",
2202			shared_libs: ["libbar"],
2203			apex_available: ["myapex"],
2204			min_sdk_version: "29",
2205		}
2206		cc_library {
2207			name: "libbar",
2208			apex_available: ["myapex"],
2209		}
2210	`, withSAsActiveCodeNames)
2211}
2212
2213func TestApexMinSdkVersion_WorksWithActiveCodenames(t *testing.T) {
2214	withSAsActiveCodeNames := android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
2215		variables.Platform_sdk_codename = proptools.StringPtr("S")
2216		variables.Platform_version_active_codenames = []string{"S", "T"}
2217	})
2218	ctx := testApex(t, `
2219		apex {
2220			name: "myapex",
2221			key: "myapex.key",
2222			native_shared_libs: ["libfoo"],
2223			min_sdk_version: "S",
2224		}
2225		apex_key {
2226			name: "myapex.key",
2227			public_key: "testkey.avbpubkey",
2228			private_key: "testkey.pem",
2229		}
2230		cc_library {
2231			name: "libfoo",
2232			shared_libs: ["libbar"],
2233			apex_available: ["myapex"],
2234			min_sdk_version: "S",
2235		}
2236		cc_library {
2237			name: "libbar",
2238			stubs: {
2239				symbol_file: "libbar.map.txt",
2240				versions: ["30", "S", "T"],
2241			},
2242		}
2243	`, withSAsActiveCodeNames)
2244
2245	// ensure libfoo is linked with current version of libbar stub
2246	libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared_apex10000")
2247	libFlags := libfoo.Rule("ld").Args["libFlags"]
2248	ensureContains(t, libFlags, "android_arm64_armv8-a_shared_current/libbar.so")
2249}
2250
2251func TestFilesInSubDir(t *testing.T) {
2252	ctx := testApex(t, `
2253		apex {
2254			name: "myapex",
2255			key: "myapex.key",
2256			native_shared_libs: ["mylib"],
2257			binaries: ["mybin"],
2258			prebuilts: ["myetc"],
2259			compile_multilib: "both",
2260			updatable: false,
2261		}
2262
2263		apex_key {
2264			name: "myapex.key",
2265			public_key: "testkey.avbpubkey",
2266			private_key: "testkey.pem",
2267		}
2268
2269		prebuilt_etc {
2270			name: "myetc",
2271			src: "myprebuilt",
2272			sub_dir: "foo/bar",
2273		}
2274
2275		cc_library {
2276			name: "mylib",
2277			srcs: ["mylib.cpp"],
2278			relative_install_path: "foo/bar",
2279			system_shared_libs: [],
2280			stl: "none",
2281			apex_available: [ "myapex" ],
2282		}
2283
2284		cc_binary {
2285			name: "mybin",
2286			srcs: ["mylib.cpp"],
2287			relative_install_path: "foo/bar",
2288			system_shared_libs: [],
2289			static_executable: true,
2290			stl: "none",
2291			apex_available: [ "myapex" ],
2292		}
2293	`)
2294
2295	generateFsRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("generateFsConfig")
2296	dirs := strings.Split(generateFsRule.Args["exec_paths"], " ")
2297
2298	// Ensure that the subdirectories are all listed
2299	ensureListContains(t, dirs, "etc")
2300	ensureListContains(t, dirs, "etc/foo")
2301	ensureListContains(t, dirs, "etc/foo/bar")
2302	ensureListContains(t, dirs, "lib64")
2303	ensureListContains(t, dirs, "lib64/foo")
2304	ensureListContains(t, dirs, "lib64/foo/bar")
2305	ensureListContains(t, dirs, "lib")
2306	ensureListContains(t, dirs, "lib/foo")
2307	ensureListContains(t, dirs, "lib/foo/bar")
2308
2309	ensureListContains(t, dirs, "bin")
2310	ensureListContains(t, dirs, "bin/foo")
2311	ensureListContains(t, dirs, "bin/foo/bar")
2312}
2313
2314func TestFilesInSubDirWhenNativeBridgeEnabled(t *testing.T) {
2315	ctx := testApex(t, `
2316		apex {
2317			name: "myapex",
2318			key: "myapex.key",
2319			multilib: {
2320				both: {
2321					native_shared_libs: ["mylib"],
2322					binaries: ["mybin"],
2323				},
2324			},
2325			compile_multilib: "both",
2326			native_bridge_supported: true,
2327			updatable: false,
2328		}
2329
2330		apex_key {
2331			name: "myapex.key",
2332			public_key: "testkey.avbpubkey",
2333			private_key: "testkey.pem",
2334		}
2335
2336		cc_library {
2337			name: "mylib",
2338			relative_install_path: "foo/bar",
2339			system_shared_libs: [],
2340			stl: "none",
2341			apex_available: [ "myapex" ],
2342			native_bridge_supported: true,
2343		}
2344
2345		cc_binary {
2346			name: "mybin",
2347			relative_install_path: "foo/bar",
2348			system_shared_libs: [],
2349			static_executable: true,
2350			stl: "none",
2351			apex_available: [ "myapex" ],
2352			native_bridge_supported: true,
2353			compile_multilib: "both", // default is "first" for binary
2354			multilib: {
2355				lib64: {
2356					suffix: "64",
2357				},
2358			},
2359		}
2360	`, withNativeBridgeEnabled)
2361	ensureExactContents(t, ctx, "myapex", "android_common_myapex_image", []string{
2362		"bin/foo/bar/mybin",
2363		"bin/foo/bar/mybin64",
2364		"bin/arm/foo/bar/mybin",
2365		"bin/arm64/foo/bar/mybin64",
2366		"lib/foo/bar/mylib.so",
2367		"lib/arm/foo/bar/mylib.so",
2368		"lib64/foo/bar/mylib.so",
2369		"lib64/arm64/foo/bar/mylib.so",
2370	})
2371}
2372
2373func TestVendorApex(t *testing.T) {
2374	ctx := testApex(t, `
2375		apex {
2376			name: "myapex",
2377			key: "myapex.key",
2378			binaries: ["mybin"],
2379			vendor: true,
2380			updatable: false,
2381		}
2382		apex_key {
2383			name: "myapex.key",
2384			public_key: "testkey.avbpubkey",
2385			private_key: "testkey.pem",
2386		}
2387		cc_binary {
2388			name: "mybin",
2389			vendor: true,
2390			shared_libs: ["libfoo"],
2391		}
2392		cc_library {
2393			name: "libfoo",
2394			proprietary: true,
2395		}
2396	`)
2397
2398	ensureExactContents(t, ctx, "myapex", "android_common_myapex_image", []string{
2399		"bin/mybin",
2400		"lib64/libfoo.so",
2401		// TODO(b/159195575): Add an option to use VNDK libs from VNDK APEX
2402		"lib64/libc++.so",
2403	})
2404
2405	apexBundle := ctx.ModuleForTests("myapex", "android_common_myapex_image").Module().(*apexBundle)
2406	data := android.AndroidMkDataForTest(t, ctx, apexBundle)
2407	name := apexBundle.BaseModuleName()
2408	prefix := "TARGET_"
2409	var builder strings.Builder
2410	data.Custom(&builder, name, prefix, "", data)
2411	androidMk := android.StringRelativeToTop(ctx.Config(), builder.String())
2412	installPath := "out/target/product/test_device/vendor/apex"
2413	ensureContains(t, androidMk, "LOCAL_MODULE_PATH := "+installPath)
2414
2415	apexManifestRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("apexManifestRule")
2416	requireNativeLibs := names(apexManifestRule.Args["requireNativeLibs"])
2417	ensureListNotContains(t, requireNativeLibs, ":vndk")
2418}
2419
2420func TestVendorApex_use_vndk_as_stable(t *testing.T) {
2421	ctx := testApex(t, `
2422		apex {
2423			name: "myapex",
2424			key: "myapex.key",
2425			binaries: ["mybin"],
2426			vendor: true,
2427			use_vndk_as_stable: true,
2428			updatable: false,
2429		}
2430		apex_key {
2431			name: "myapex.key",
2432			public_key: "testkey.avbpubkey",
2433			private_key: "testkey.pem",
2434		}
2435		cc_binary {
2436			name: "mybin",
2437			vendor: true,
2438			shared_libs: ["libvndk", "libvendor"],
2439		}
2440		cc_library {
2441			name: "libvndk",
2442			vndk: {
2443				enabled: true,
2444			},
2445			vendor_available: true,
2446			product_available: true,
2447		}
2448		cc_library {
2449			name: "libvendor",
2450			vendor: true,
2451		}
2452	`)
2453
2454	vendorVariant := "android_vendor.29_arm64_armv8-a"
2455
2456	ldRule := ctx.ModuleForTests("mybin", vendorVariant+"_apex10000").Rule("ld")
2457	libs := names(ldRule.Args["libFlags"])
2458	// VNDK libs(libvndk/libc++) as they are
2459	ensureListContains(t, libs, "out/soong/.intermediates/libvndk/"+vendorVariant+"_shared/libvndk.so")
2460	ensureListContains(t, libs, "out/soong/.intermediates/"+cc.DefaultCcCommonTestModulesDir+"libc++/"+vendorVariant+"_shared/libc++.so")
2461	// non-stable Vendor libs as APEX variants
2462	ensureListContains(t, libs, "out/soong/.intermediates/libvendor/"+vendorVariant+"_shared_apex10000/libvendor.so")
2463
2464	// VNDK libs are not included when use_vndk_as_stable: true
2465	ensureExactContents(t, ctx, "myapex", "android_common_myapex_image", []string{
2466		"bin/mybin",
2467		"lib64/libvendor.so",
2468	})
2469
2470	apexManifestRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("apexManifestRule")
2471	requireNativeLibs := names(apexManifestRule.Args["requireNativeLibs"])
2472	ensureListContains(t, requireNativeLibs, ":vndk")
2473}
2474
2475func TestProductVariant(t *testing.T) {
2476	ctx := testApex(t, `
2477		apex {
2478			name: "myapex",
2479			key: "myapex.key",
2480			updatable: false,
2481			product_specific: true,
2482			binaries: ["foo"],
2483		}
2484
2485		apex_key {
2486			name: "myapex.key",
2487			public_key: "testkey.avbpubkey",
2488			private_key: "testkey.pem",
2489		}
2490
2491		cc_binary {
2492			name: "foo",
2493			product_available: true,
2494			apex_available: ["myapex"],
2495			srcs: ["foo.cpp"],
2496		}
2497	`, android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
2498		variables.ProductVndkVersion = proptools.StringPtr("current")
2499	}),
2500	)
2501
2502	cflags := strings.Fields(
2503		ctx.ModuleForTests("foo", "android_product.29_arm64_armv8-a_apex10000").Rule("cc").Args["cFlags"])
2504	ensureListContains(t, cflags, "-D__ANDROID_VNDK__")
2505	ensureListContains(t, cflags, "-D__ANDROID_APEX__")
2506	ensureListContains(t, cflags, "-D__ANDROID_PRODUCT__")
2507	ensureListNotContains(t, cflags, "-D__ANDROID_VENDOR__")
2508}
2509
2510func TestApex_withPrebuiltFirmware(t *testing.T) {
2511	testCases := []struct {
2512		name           string
2513		additionalProp string
2514	}{
2515		{"system apex with prebuilt_firmware", ""},
2516		{"vendor apex with prebuilt_firmware", "vendor: true,"},
2517	}
2518	for _, tc := range testCases {
2519		t.Run(tc.name, func(t *testing.T) {
2520			ctx := testApex(t, `
2521				apex {
2522					name: "myapex",
2523					key: "myapex.key",
2524					prebuilts: ["myfirmware"],
2525					updatable: false,
2526					`+tc.additionalProp+`
2527				}
2528				apex_key {
2529					name: "myapex.key",
2530					public_key: "testkey.avbpubkey",
2531					private_key: "testkey.pem",
2532				}
2533				prebuilt_firmware {
2534					name: "myfirmware",
2535					src: "myfirmware.bin",
2536					filename_from_src: true,
2537					`+tc.additionalProp+`
2538				}
2539			`)
2540			ensureExactContents(t, ctx, "myapex", "android_common_myapex_image", []string{
2541				"etc/firmware/myfirmware.bin",
2542			})
2543		})
2544	}
2545}
2546
2547func TestAndroidMk_VendorApexRequired(t *testing.T) {
2548	ctx := testApex(t, `
2549		apex {
2550			name: "myapex",
2551			key: "myapex.key",
2552			vendor: true,
2553			native_shared_libs: ["mylib"],
2554			updatable: false,
2555		}
2556
2557		apex_key {
2558			name: "myapex.key",
2559			public_key: "testkey.avbpubkey",
2560			private_key: "testkey.pem",
2561		}
2562
2563		cc_library {
2564			name: "mylib",
2565			vendor_available: true,
2566		}
2567	`)
2568
2569	apexBundle := ctx.ModuleForTests("myapex", "android_common_myapex_image").Module().(*apexBundle)
2570	data := android.AndroidMkDataForTest(t, ctx, apexBundle)
2571	name := apexBundle.BaseModuleName()
2572	prefix := "TARGET_"
2573	var builder strings.Builder
2574	data.Custom(&builder, name, prefix, "", data)
2575	androidMk := builder.String()
2576	ensureContains(t, androidMk, "LOCAL_REQUIRED_MODULES += libc.vendor libm.vendor libdl.vendor\n")
2577}
2578
2579func TestAndroidMkWritesCommonProperties(t *testing.T) {
2580	ctx := testApex(t, `
2581		apex {
2582			name: "myapex",
2583			key: "myapex.key",
2584			vintf_fragments: ["fragment.xml"],
2585			init_rc: ["init.rc"],
2586			updatable: false,
2587		}
2588		apex_key {
2589			name: "myapex.key",
2590			public_key: "testkey.avbpubkey",
2591			private_key: "testkey.pem",
2592		}
2593		cc_binary {
2594			name: "mybin",
2595		}
2596	`)
2597
2598	apexBundle := ctx.ModuleForTests("myapex", "android_common_myapex_image").Module().(*apexBundle)
2599	data := android.AndroidMkDataForTest(t, ctx, apexBundle)
2600	name := apexBundle.BaseModuleName()
2601	prefix := "TARGET_"
2602	var builder strings.Builder
2603	data.Custom(&builder, name, prefix, "", data)
2604	androidMk := builder.String()
2605	ensureContains(t, androidMk, "LOCAL_FULL_VINTF_FRAGMENTS := fragment.xml\n")
2606	ensureContains(t, androidMk, "LOCAL_FULL_INIT_RC := init.rc\n")
2607}
2608
2609func TestStaticLinking(t *testing.T) {
2610	ctx := testApex(t, `
2611		apex {
2612			name: "myapex",
2613			key: "myapex.key",
2614			native_shared_libs: ["mylib"],
2615			updatable: false,
2616		}
2617
2618		apex_key {
2619			name: "myapex.key",
2620			public_key: "testkey.avbpubkey",
2621			private_key: "testkey.pem",
2622		}
2623
2624		cc_library {
2625			name: "mylib",
2626			srcs: ["mylib.cpp"],
2627			system_shared_libs: [],
2628			stl: "none",
2629			stubs: {
2630				versions: ["1", "2", "3"],
2631			},
2632			apex_available: [
2633				"//apex_available:platform",
2634				"myapex",
2635			],
2636		}
2637
2638		cc_binary {
2639			name: "not_in_apex",
2640			srcs: ["mylib.cpp"],
2641			static_libs: ["mylib"],
2642			static_executable: true,
2643			system_shared_libs: [],
2644			stl: "none",
2645		}
2646	`)
2647
2648	ldFlags := ctx.ModuleForTests("not_in_apex", "android_arm64_armv8-a").Rule("ld").Args["libFlags"]
2649
2650	// Ensure that not_in_apex is linking with the static variant of mylib
2651	ensureContains(t, ldFlags, "mylib/android_arm64_armv8-a_static/mylib.a")
2652}
2653
2654func TestKeys(t *testing.T) {
2655	ctx := testApex(t, `
2656		apex {
2657			name: "myapex_keytest",
2658			key: "myapex.key",
2659			certificate: ":myapex.certificate",
2660			native_shared_libs: ["mylib"],
2661			file_contexts: ":myapex-file_contexts",
2662			updatable: false,
2663		}
2664
2665		cc_library {
2666			name: "mylib",
2667			srcs: ["mylib.cpp"],
2668			system_shared_libs: [],
2669			stl: "none",
2670			apex_available: [ "myapex_keytest" ],
2671		}
2672
2673		apex_key {
2674			name: "myapex.key",
2675			public_key: "testkey.avbpubkey",
2676			private_key: "testkey.pem",
2677		}
2678
2679		android_app_certificate {
2680			name: "myapex.certificate",
2681			certificate: "testkey",
2682		}
2683
2684		android_app_certificate {
2685			name: "myapex.certificate.override",
2686			certificate: "testkey.override",
2687		}
2688
2689	`)
2690
2691	// check the APEX keys
2692	keys := ctx.ModuleForTests("myapex.key", "android_common").Module().(*apexKey)
2693
2694	if keys.publicKeyFile.String() != "vendor/foo/devkeys/testkey.avbpubkey" {
2695		t.Errorf("public key %q is not %q", keys.publicKeyFile.String(),
2696			"vendor/foo/devkeys/testkey.avbpubkey")
2697	}
2698	if keys.privateKeyFile.String() != "vendor/foo/devkeys/testkey.pem" {
2699		t.Errorf("private key %q is not %q", keys.privateKeyFile.String(),
2700			"vendor/foo/devkeys/testkey.pem")
2701	}
2702
2703	// check the APK certs. It should be overridden to myapex.certificate.override
2704	certs := ctx.ModuleForTests("myapex_keytest", "android_common_myapex_keytest_image").Rule("signapk").Args["certificates"]
2705	if certs != "testkey.override.x509.pem testkey.override.pk8" {
2706		t.Errorf("cert and private key %q are not %q", certs,
2707			"testkey.override.509.pem testkey.override.pk8")
2708	}
2709}
2710
2711func TestCertificate(t *testing.T) {
2712	t.Run("if unspecified, it defaults to DefaultAppCertificate", func(t *testing.T) {
2713		ctx := testApex(t, `
2714			apex {
2715				name: "myapex",
2716				key: "myapex.key",
2717				updatable: false,
2718			}
2719			apex_key {
2720				name: "myapex.key",
2721				public_key: "testkey.avbpubkey",
2722				private_key: "testkey.pem",
2723			}`)
2724		rule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("signapk")
2725		expected := "vendor/foo/devkeys/test.x509.pem vendor/foo/devkeys/test.pk8"
2726		if actual := rule.Args["certificates"]; actual != expected {
2727			t.Errorf("certificates should be %q, not %q", expected, actual)
2728		}
2729	})
2730	t.Run("override when unspecified", func(t *testing.T) {
2731		ctx := testApex(t, `
2732			apex {
2733				name: "myapex_keytest",
2734				key: "myapex.key",
2735				file_contexts: ":myapex-file_contexts",
2736				updatable: false,
2737			}
2738			apex_key {
2739				name: "myapex.key",
2740				public_key: "testkey.avbpubkey",
2741				private_key: "testkey.pem",
2742			}
2743			android_app_certificate {
2744				name: "myapex.certificate.override",
2745				certificate: "testkey.override",
2746			}`)
2747		rule := ctx.ModuleForTests("myapex_keytest", "android_common_myapex_keytest_image").Rule("signapk")
2748		expected := "testkey.override.x509.pem testkey.override.pk8"
2749		if actual := rule.Args["certificates"]; actual != expected {
2750			t.Errorf("certificates should be %q, not %q", expected, actual)
2751		}
2752	})
2753	t.Run("if specified as :module, it respects the prop", func(t *testing.T) {
2754		ctx := testApex(t, `
2755			apex {
2756				name: "myapex",
2757				key: "myapex.key",
2758				certificate: ":myapex.certificate",
2759				updatable: false,
2760			}
2761			apex_key {
2762				name: "myapex.key",
2763				public_key: "testkey.avbpubkey",
2764				private_key: "testkey.pem",
2765			}
2766			android_app_certificate {
2767				name: "myapex.certificate",
2768				certificate: "testkey",
2769			}`)
2770		rule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("signapk")
2771		expected := "testkey.x509.pem testkey.pk8"
2772		if actual := rule.Args["certificates"]; actual != expected {
2773			t.Errorf("certificates should be %q, not %q", expected, actual)
2774		}
2775	})
2776	t.Run("override when specifiec as <:module>", func(t *testing.T) {
2777		ctx := testApex(t, `
2778			apex {
2779				name: "myapex_keytest",
2780				key: "myapex.key",
2781				file_contexts: ":myapex-file_contexts",
2782				certificate: ":myapex.certificate",
2783				updatable: false,
2784			}
2785			apex_key {
2786				name: "myapex.key",
2787				public_key: "testkey.avbpubkey",
2788				private_key: "testkey.pem",
2789			}
2790			android_app_certificate {
2791				name: "myapex.certificate.override",
2792				certificate: "testkey.override",
2793			}`)
2794		rule := ctx.ModuleForTests("myapex_keytest", "android_common_myapex_keytest_image").Rule("signapk")
2795		expected := "testkey.override.x509.pem testkey.override.pk8"
2796		if actual := rule.Args["certificates"]; actual != expected {
2797			t.Errorf("certificates should be %q, not %q", expected, actual)
2798		}
2799	})
2800	t.Run("if specified as name, finds it from DefaultDevKeyDir", func(t *testing.T) {
2801		ctx := testApex(t, `
2802			apex {
2803				name: "myapex",
2804				key: "myapex.key",
2805				certificate: "testkey",
2806				updatable: false,
2807			}
2808			apex_key {
2809				name: "myapex.key",
2810				public_key: "testkey.avbpubkey",
2811				private_key: "testkey.pem",
2812			}`)
2813		rule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("signapk")
2814		expected := "vendor/foo/devkeys/testkey.x509.pem vendor/foo/devkeys/testkey.pk8"
2815		if actual := rule.Args["certificates"]; actual != expected {
2816			t.Errorf("certificates should be %q, not %q", expected, actual)
2817		}
2818	})
2819	t.Run("override when specified as <name>", func(t *testing.T) {
2820		ctx := testApex(t, `
2821			apex {
2822				name: "myapex_keytest",
2823				key: "myapex.key",
2824				file_contexts: ":myapex-file_contexts",
2825				certificate: "testkey",
2826				updatable: false,
2827			}
2828			apex_key {
2829				name: "myapex.key",
2830				public_key: "testkey.avbpubkey",
2831				private_key: "testkey.pem",
2832			}
2833			android_app_certificate {
2834				name: "myapex.certificate.override",
2835				certificate: "testkey.override",
2836			}`)
2837		rule := ctx.ModuleForTests("myapex_keytest", "android_common_myapex_keytest_image").Rule("signapk")
2838		expected := "testkey.override.x509.pem testkey.override.pk8"
2839		if actual := rule.Args["certificates"]; actual != expected {
2840			t.Errorf("certificates should be %q, not %q", expected, actual)
2841		}
2842	})
2843}
2844
2845func TestMacro(t *testing.T) {
2846	ctx := testApex(t, `
2847		apex {
2848			name: "myapex",
2849			key: "myapex.key",
2850			native_shared_libs: ["mylib", "mylib2"],
2851			updatable: false,
2852		}
2853
2854		apex {
2855			name: "otherapex",
2856			key: "myapex.key",
2857			native_shared_libs: ["mylib", "mylib2"],
2858			min_sdk_version: "29",
2859		}
2860
2861		apex_key {
2862			name: "myapex.key",
2863			public_key: "testkey.avbpubkey",
2864			private_key: "testkey.pem",
2865		}
2866
2867		cc_library {
2868			name: "mylib",
2869			srcs: ["mylib.cpp"],
2870			system_shared_libs: [],
2871			stl: "none",
2872			apex_available: [
2873				"myapex",
2874				"otherapex",
2875			],
2876			recovery_available: true,
2877			min_sdk_version: "29",
2878		}
2879		cc_library {
2880			name: "mylib2",
2881			srcs: ["mylib.cpp"],
2882			system_shared_libs: [],
2883			stl: "none",
2884			apex_available: [
2885				"myapex",
2886				"otherapex",
2887			],
2888			static_libs: ["mylib3"],
2889			recovery_available: true,
2890			min_sdk_version: "29",
2891		}
2892		cc_library {
2893			name: "mylib3",
2894			srcs: ["mylib.cpp"],
2895			system_shared_libs: [],
2896			stl: "none",
2897			apex_available: [
2898				"myapex",
2899				"otherapex",
2900			],
2901			use_apex_name_macro: true,
2902			recovery_available: true,
2903			min_sdk_version: "29",
2904		}
2905	`)
2906
2907	// non-APEX variant does not have __ANDROID_APEX__ defined
2908	mylibCFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_static").Rule("cc").Args["cFlags"]
2909	ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX__")
2910	ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX_MIN_SDK_VERSION__")
2911
2912	// APEX variant has __ANDROID_APEX__ and __ANDROID_APEX_SDK__ defined
2913	mylibCFlags = ctx.ModuleForTests("mylib", "android_arm64_armv8-a_static_apex10000").Rule("cc").Args["cFlags"]
2914	ensureContains(t, mylibCFlags, "-D__ANDROID_APEX__")
2915	ensureContains(t, mylibCFlags, "-D__ANDROID_APEX_MIN_SDK_VERSION__=10000")
2916	ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX_MYAPEX__")
2917
2918	// APEX variant has __ANDROID_APEX__ and __ANDROID_APEX_SDK__ defined
2919	mylibCFlags = ctx.ModuleForTests("mylib", "android_arm64_armv8-a_static_apex29").Rule("cc").Args["cFlags"]
2920	ensureContains(t, mylibCFlags, "-D__ANDROID_APEX__")
2921	ensureContains(t, mylibCFlags, "-D__ANDROID_APEX_MIN_SDK_VERSION__=29")
2922	ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX_OTHERAPEX__")
2923
2924	// When a cc_library sets use_apex_name_macro: true each apex gets a unique variant and
2925	// each variant defines additional macros to distinguish which apex variant it is built for
2926
2927	// non-APEX variant does not have __ANDROID_APEX__ defined
2928	mylibCFlags = ctx.ModuleForTests("mylib3", "android_arm64_armv8-a_static").Rule("cc").Args["cFlags"]
2929	ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX__")
2930
2931	// APEX variant has __ANDROID_APEX__ defined
2932	mylibCFlags = ctx.ModuleForTests("mylib3", "android_arm64_armv8-a_static_myapex").Rule("cc").Args["cFlags"]
2933	ensureContains(t, mylibCFlags, "-D__ANDROID_APEX__")
2934	ensureContains(t, mylibCFlags, "-D__ANDROID_APEX_MYAPEX__")
2935	ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX_OTHERAPEX__")
2936
2937	// APEX variant has __ANDROID_APEX__ defined
2938	mylibCFlags = ctx.ModuleForTests("mylib3", "android_arm64_armv8-a_static_otherapex").Rule("cc").Args["cFlags"]
2939	ensureContains(t, mylibCFlags, "-D__ANDROID_APEX__")
2940	ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX_MYAPEX__")
2941	ensureContains(t, mylibCFlags, "-D__ANDROID_APEX_OTHERAPEX__")
2942
2943	// recovery variant does not set __ANDROID_APEX_MIN_SDK_VERSION__
2944	mylibCFlags = ctx.ModuleForTests("mylib3", "android_recovery_arm64_armv8-a_static").Rule("cc").Args["cFlags"]
2945	ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX__")
2946	ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX_MIN_SDK_VERSION__")
2947
2948	// When a dependency of a cc_library sets use_apex_name_macro: true each apex gets a unique
2949	// variant.
2950
2951	// non-APEX variant does not have __ANDROID_APEX__ defined
2952	mylibCFlags = ctx.ModuleForTests("mylib2", "android_arm64_armv8-a_static").Rule("cc").Args["cFlags"]
2953	ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX__")
2954
2955	// APEX variant has __ANDROID_APEX__ defined
2956	mylibCFlags = ctx.ModuleForTests("mylib2", "android_arm64_armv8-a_static_myapex").Rule("cc").Args["cFlags"]
2957	ensureContains(t, mylibCFlags, "-D__ANDROID_APEX__")
2958	ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX_MYAPEX__")
2959	ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX_OTHERAPEX__")
2960
2961	// APEX variant has __ANDROID_APEX__ defined
2962	mylibCFlags = ctx.ModuleForTests("mylib2", "android_arm64_armv8-a_static_otherapex").Rule("cc").Args["cFlags"]
2963	ensureContains(t, mylibCFlags, "-D__ANDROID_APEX__")
2964	ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX_MYAPEX__")
2965	ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX_OTHERAPEX__")
2966
2967	// recovery variant does not set __ANDROID_APEX_MIN_SDK_VERSION__
2968	mylibCFlags = ctx.ModuleForTests("mylib2", "android_recovery_arm64_armv8-a_static").Rule("cc").Args["cFlags"]
2969	ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX__")
2970	ensureNotContains(t, mylibCFlags, "-D__ANDROID_APEX_MIN_SDK_VERSION__")
2971}
2972
2973func TestHeaderLibsDependency(t *testing.T) {
2974	ctx := testApex(t, `
2975		apex {
2976			name: "myapex",
2977			key: "myapex.key",
2978			native_shared_libs: ["mylib"],
2979			updatable: false,
2980		}
2981
2982		apex_key {
2983			name: "myapex.key",
2984			public_key: "testkey.avbpubkey",
2985			private_key: "testkey.pem",
2986		}
2987
2988		cc_library_headers {
2989			name: "mylib_headers",
2990			export_include_dirs: ["my_include"],
2991			system_shared_libs: [],
2992			stl: "none",
2993			apex_available: [ "myapex" ],
2994		}
2995
2996		cc_library {
2997			name: "mylib",
2998			srcs: ["mylib.cpp"],
2999			system_shared_libs: [],
3000			stl: "none",
3001			header_libs: ["mylib_headers"],
3002			export_header_lib_headers: ["mylib_headers"],
3003			stubs: {
3004				versions: ["1", "2", "3"],
3005			},
3006			apex_available: [ "myapex" ],
3007		}
3008
3009		cc_library {
3010			name: "otherlib",
3011			srcs: ["mylib.cpp"],
3012			system_shared_libs: [],
3013			stl: "none",
3014			shared_libs: ["mylib"],
3015		}
3016	`)
3017
3018	cFlags := ctx.ModuleForTests("otherlib", "android_arm64_armv8-a_static").Rule("cc").Args["cFlags"]
3019
3020	// Ensure that the include path of the header lib is exported to 'otherlib'
3021	ensureContains(t, cFlags, "-Imy_include")
3022}
3023
3024type fileInApex struct {
3025	path   string // path in apex
3026	src    string // src path
3027	isLink bool
3028}
3029
3030func getFiles(t *testing.T, ctx *android.TestContext, moduleName, variant string) []fileInApex {
3031	t.Helper()
3032	apexRule := ctx.ModuleForTests(moduleName, variant).Rule("apexRule")
3033	copyCmds := apexRule.Args["copy_commands"]
3034	imageApexDir := "/image.apex/"
3035	var ret []fileInApex
3036	for _, cmd := range strings.Split(copyCmds, "&&") {
3037		cmd = strings.TrimSpace(cmd)
3038		if cmd == "" {
3039			continue
3040		}
3041		terms := strings.Split(cmd, " ")
3042		var dst, src string
3043		var isLink bool
3044		switch terms[0] {
3045		case "mkdir":
3046		case "cp":
3047			if len(terms) != 3 && len(terms) != 4 {
3048				t.Fatal("copyCmds contains invalid cp command", cmd)
3049			}
3050			dst = terms[len(terms)-1]
3051			src = terms[len(terms)-2]
3052			isLink = false
3053		case "ln":
3054			if len(terms) != 3 && len(terms) != 4 {
3055				// ln LINK TARGET or ln -s LINK TARGET
3056				t.Fatal("copyCmds contains invalid ln command", cmd)
3057			}
3058			dst = terms[len(terms)-1]
3059			src = terms[len(terms)-2]
3060			isLink = true
3061		default:
3062			t.Fatalf("copyCmds should contain mkdir/cp commands only: %q", cmd)
3063		}
3064		if dst != "" {
3065			index := strings.Index(dst, imageApexDir)
3066			if index == -1 {
3067				t.Fatal("copyCmds should copy a file to image.apex/", cmd)
3068			}
3069			dstFile := dst[index+len(imageApexDir):]
3070			ret = append(ret, fileInApex{path: dstFile, src: src, isLink: isLink})
3071		}
3072	}
3073	return ret
3074}
3075
3076func ensureExactContents(t *testing.T, ctx *android.TestContext, moduleName, variant string, files []string) {
3077	t.Helper()
3078	var failed bool
3079	var surplus []string
3080	filesMatched := make(map[string]bool)
3081	for _, file := range getFiles(t, ctx, moduleName, variant) {
3082		mactchFound := false
3083		for _, expected := range files {
3084			if matched, _ := path.Match(expected, file.path); matched {
3085				filesMatched[expected] = true
3086				mactchFound = true
3087				break
3088			}
3089		}
3090		if !mactchFound {
3091			surplus = append(surplus, file.path)
3092		}
3093	}
3094
3095	if len(surplus) > 0 {
3096		sort.Strings(surplus)
3097		t.Log("surplus files", surplus)
3098		failed = true
3099	}
3100
3101	if len(files) > len(filesMatched) {
3102		var missing []string
3103		for _, expected := range files {
3104			if !filesMatched[expected] {
3105				missing = append(missing, expected)
3106			}
3107		}
3108		sort.Strings(missing)
3109		t.Log("missing files", missing)
3110		failed = true
3111	}
3112	if failed {
3113		t.Fail()
3114	}
3115}
3116
3117func TestVndkApexCurrent(t *testing.T) {
3118	ctx := testApex(t, `
3119		apex_vndk {
3120			name: "com.android.vndk.current",
3121			key: "com.android.vndk.current.key",
3122			updatable: false,
3123		}
3124
3125		apex_key {
3126			name: "com.android.vndk.current.key",
3127			public_key: "testkey.avbpubkey",
3128			private_key: "testkey.pem",
3129		}
3130
3131		cc_library {
3132			name: "libvndk",
3133			srcs: ["mylib.cpp"],
3134			vendor_available: true,
3135			product_available: true,
3136			vndk: {
3137				enabled: true,
3138			},
3139			system_shared_libs: [],
3140			stl: "none",
3141			apex_available: [ "com.android.vndk.current" ],
3142		}
3143
3144		cc_library {
3145			name: "libvndksp",
3146			srcs: ["mylib.cpp"],
3147			vendor_available: true,
3148			product_available: true,
3149			vndk: {
3150				enabled: true,
3151				support_system_process: true,
3152			},
3153			system_shared_libs: [],
3154			stl: "none",
3155			apex_available: [ "com.android.vndk.current" ],
3156		}
3157	`+vndkLibrariesTxtFiles("current"))
3158
3159	ensureExactContents(t, ctx, "com.android.vndk.current", "android_common_image", []string{
3160		"lib/libvndk.so",
3161		"lib/libvndksp.so",
3162		"lib/libc++.so",
3163		"lib64/libvndk.so",
3164		"lib64/libvndksp.so",
3165		"lib64/libc++.so",
3166		"etc/llndk.libraries.29.txt",
3167		"etc/vndkcore.libraries.29.txt",
3168		"etc/vndksp.libraries.29.txt",
3169		"etc/vndkprivate.libraries.29.txt",
3170		"etc/vndkproduct.libraries.29.txt",
3171	})
3172}
3173
3174func TestVndkApexWithPrebuilt(t *testing.T) {
3175	ctx := testApex(t, `
3176		apex_vndk {
3177			name: "com.android.vndk.current",
3178			key: "com.android.vndk.current.key",
3179			updatable: false,
3180		}
3181
3182		apex_key {
3183			name: "com.android.vndk.current.key",
3184			public_key: "testkey.avbpubkey",
3185			private_key: "testkey.pem",
3186		}
3187
3188		cc_prebuilt_library_shared {
3189			name: "libvndk",
3190			srcs: ["libvndk.so"],
3191			vendor_available: true,
3192			product_available: true,
3193			vndk: {
3194				enabled: true,
3195			},
3196			system_shared_libs: [],
3197			stl: "none",
3198			apex_available: [ "com.android.vndk.current" ],
3199		}
3200
3201		cc_prebuilt_library_shared {
3202			name: "libvndk.arm",
3203			srcs: ["libvndk.arm.so"],
3204			vendor_available: true,
3205			product_available: true,
3206			vndk: {
3207				enabled: true,
3208			},
3209			enabled: false,
3210			arch: {
3211				arm: {
3212					enabled: true,
3213				},
3214			},
3215			system_shared_libs: [],
3216			stl: "none",
3217			apex_available: [ "com.android.vndk.current" ],
3218		}
3219		`+vndkLibrariesTxtFiles("current"),
3220		withFiles(map[string][]byte{
3221			"libvndk.so":     nil,
3222			"libvndk.arm.so": nil,
3223		}))
3224	ensureExactContents(t, ctx, "com.android.vndk.current", "android_common_image", []string{
3225		"lib/libvndk.so",
3226		"lib/libvndk.arm.so",
3227		"lib64/libvndk.so",
3228		"lib/libc++.so",
3229		"lib64/libc++.so",
3230		"etc/*",
3231	})
3232}
3233
3234func vndkLibrariesTxtFiles(vers ...string) (result string) {
3235	for _, v := range vers {
3236		if v == "current" {
3237			for _, txt := range []string{"llndk", "vndkcore", "vndksp", "vndkprivate", "vndkproduct"} {
3238				result += `
3239					` + txt + `_libraries_txt {
3240						name: "` + txt + `.libraries.txt",
3241					}
3242				`
3243			}
3244		} else {
3245			for _, txt := range []string{"llndk", "vndkcore", "vndksp", "vndkprivate", "vndkproduct"} {
3246				result += `
3247					prebuilt_etc {
3248						name: "` + txt + `.libraries.` + v + `.txt",
3249						src: "dummy.txt",
3250					}
3251				`
3252			}
3253		}
3254	}
3255	return
3256}
3257
3258func TestVndkApexVersion(t *testing.T) {
3259	ctx := testApex(t, `
3260		apex_vndk {
3261			name: "com.android.vndk.v27",
3262			key: "myapex.key",
3263			file_contexts: ":myapex-file_contexts",
3264			vndk_version: "27",
3265			updatable: false,
3266		}
3267
3268		apex_key {
3269			name: "myapex.key",
3270			public_key: "testkey.avbpubkey",
3271			private_key: "testkey.pem",
3272		}
3273
3274		vndk_prebuilt_shared {
3275			name: "libvndk27",
3276			version: "27",
3277			vendor_available: true,
3278			product_available: true,
3279			vndk: {
3280				enabled: true,
3281			},
3282			target_arch: "arm64",
3283			arch: {
3284				arm: {
3285					srcs: ["libvndk27_arm.so"],
3286				},
3287				arm64: {
3288					srcs: ["libvndk27_arm64.so"],
3289				},
3290			},
3291			apex_available: [ "com.android.vndk.v27" ],
3292		}
3293
3294		vndk_prebuilt_shared {
3295			name: "libvndk27",
3296			version: "27",
3297			vendor_available: true,
3298			product_available: true,
3299			vndk: {
3300				enabled: true,
3301			},
3302			target_arch: "x86_64",
3303			arch: {
3304				x86: {
3305					srcs: ["libvndk27_x86.so"],
3306				},
3307				x86_64: {
3308					srcs: ["libvndk27_x86_64.so"],
3309				},
3310			},
3311		}
3312		`+vndkLibrariesTxtFiles("27"),
3313		withFiles(map[string][]byte{
3314			"libvndk27_arm.so":    nil,
3315			"libvndk27_arm64.so":  nil,
3316			"libvndk27_x86.so":    nil,
3317			"libvndk27_x86_64.so": nil,
3318		}))
3319
3320	ensureExactContents(t, ctx, "com.android.vndk.v27", "android_common_image", []string{
3321		"lib/libvndk27_arm.so",
3322		"lib64/libvndk27_arm64.so",
3323		"etc/*",
3324	})
3325}
3326
3327func TestVndkApexNameRule(t *testing.T) {
3328	ctx := testApex(t, `
3329		apex_vndk {
3330			name: "com.android.vndk.current",
3331			key: "myapex.key",
3332			file_contexts: ":myapex-file_contexts",
3333			updatable: false,
3334		}
3335		apex_vndk {
3336			name: "com.android.vndk.v28",
3337			key: "myapex.key",
3338			file_contexts: ":myapex-file_contexts",
3339			vndk_version: "28",
3340			updatable: false,
3341		}
3342		apex_key {
3343			name: "myapex.key",
3344			public_key: "testkey.avbpubkey",
3345			private_key: "testkey.pem",
3346		}`+vndkLibrariesTxtFiles("28", "current"))
3347
3348	assertApexName := func(expected, moduleName string) {
3349		bundle := ctx.ModuleForTests(moduleName, "android_common_image").Module().(*apexBundle)
3350		actual := proptools.String(bundle.properties.Apex_name)
3351		if !reflect.DeepEqual(actual, expected) {
3352			t.Errorf("Got '%v', expected '%v'", actual, expected)
3353		}
3354	}
3355
3356	assertApexName("com.android.vndk.v29", "com.android.vndk.current")
3357	assertApexName("com.android.vndk.v28", "com.android.vndk.v28")
3358}
3359
3360func TestVndkApexSkipsNativeBridgeSupportedModules(t *testing.T) {
3361	ctx := testApex(t, `
3362		apex_vndk {
3363			name: "com.android.vndk.current",
3364			key: "com.android.vndk.current.key",
3365			file_contexts: ":myapex-file_contexts",
3366			updatable: false,
3367		}
3368
3369		apex_key {
3370			name: "com.android.vndk.current.key",
3371			public_key: "testkey.avbpubkey",
3372			private_key: "testkey.pem",
3373		}
3374
3375		cc_library {
3376			name: "libvndk",
3377			srcs: ["mylib.cpp"],
3378			vendor_available: true,
3379			product_available: true,
3380			native_bridge_supported: true,
3381			host_supported: true,
3382			vndk: {
3383				enabled: true,
3384			},
3385			system_shared_libs: [],
3386			stl: "none",
3387			apex_available: [ "com.android.vndk.current" ],
3388		}
3389		`+vndkLibrariesTxtFiles("current"),
3390		withNativeBridgeEnabled)
3391
3392	ensureExactContents(t, ctx, "com.android.vndk.current", "android_common_image", []string{
3393		"lib/libvndk.so",
3394		"lib64/libvndk.so",
3395		"lib/libc++.so",
3396		"lib64/libc++.so",
3397		"etc/*",
3398	})
3399}
3400
3401func TestVndkApexDoesntSupportNativeBridgeSupported(t *testing.T) {
3402	testApexError(t, `module "com.android.vndk.current" .*: native_bridge_supported: .* doesn't support native bridge binary`, `
3403		apex_vndk {
3404			name: "com.android.vndk.current",
3405			key: "com.android.vndk.current.key",
3406			file_contexts: ":myapex-file_contexts",
3407			native_bridge_supported: true,
3408		}
3409
3410		apex_key {
3411			name: "com.android.vndk.current.key",
3412			public_key: "testkey.avbpubkey",
3413			private_key: "testkey.pem",
3414		}
3415
3416		cc_library {
3417			name: "libvndk",
3418			srcs: ["mylib.cpp"],
3419			vendor_available: true,
3420			product_available: true,
3421			native_bridge_supported: true,
3422			host_supported: true,
3423			vndk: {
3424				enabled: true,
3425			},
3426			system_shared_libs: [],
3427			stl: "none",
3428		}
3429	`)
3430}
3431
3432func TestVndkApexWithBinder32(t *testing.T) {
3433	ctx := testApex(t, `
3434		apex_vndk {
3435			name: "com.android.vndk.v27",
3436			key: "myapex.key",
3437			file_contexts: ":myapex-file_contexts",
3438			vndk_version: "27",
3439			updatable: false,
3440		}
3441
3442		apex_key {
3443			name: "myapex.key",
3444			public_key: "testkey.avbpubkey",
3445			private_key: "testkey.pem",
3446		}
3447
3448		vndk_prebuilt_shared {
3449			name: "libvndk27",
3450			version: "27",
3451			target_arch: "arm",
3452			vendor_available: true,
3453			product_available: true,
3454			vndk: {
3455				enabled: true,
3456			},
3457			arch: {
3458				arm: {
3459					srcs: ["libvndk27.so"],
3460				}
3461			},
3462		}
3463
3464		vndk_prebuilt_shared {
3465			name: "libvndk27",
3466			version: "27",
3467			target_arch: "arm",
3468			binder32bit: true,
3469			vendor_available: true,
3470			product_available: true,
3471			vndk: {
3472				enabled: true,
3473			},
3474			arch: {
3475				arm: {
3476					srcs: ["libvndk27binder32.so"],
3477				}
3478			},
3479			apex_available: [ "com.android.vndk.v27" ],
3480		}
3481		`+vndkLibrariesTxtFiles("27"),
3482		withFiles(map[string][]byte{
3483			"libvndk27.so":         nil,
3484			"libvndk27binder32.so": nil,
3485		}),
3486		withBinder32bit,
3487		withTargets(map[android.OsType][]android.Target{
3488			android.Android: []android.Target{
3489				{Os: android.Android, Arch: android.Arch{ArchType: android.Arm, ArchVariant: "armv7-a-neon", Abi: []string{"armeabi-v7a"}},
3490					NativeBridge: android.NativeBridgeDisabled, NativeBridgeHostArchName: "", NativeBridgeRelativePath: ""},
3491			},
3492		}),
3493	)
3494
3495	ensureExactContents(t, ctx, "com.android.vndk.v27", "android_common_image", []string{
3496		"lib/libvndk27binder32.so",
3497		"etc/*",
3498	})
3499}
3500
3501func TestVndkApexShouldNotProvideNativeLibs(t *testing.T) {
3502	ctx := testApex(t, `
3503		apex_vndk {
3504			name: "com.android.vndk.current",
3505			key: "com.android.vndk.current.key",
3506			file_contexts: ":myapex-file_contexts",
3507			updatable: false,
3508		}
3509
3510		apex_key {
3511			name: "com.android.vndk.current.key",
3512			public_key: "testkey.avbpubkey",
3513			private_key: "testkey.pem",
3514		}
3515
3516		cc_library {
3517			name: "libz",
3518			vendor_available: true,
3519			product_available: true,
3520			vndk: {
3521				enabled: true,
3522			},
3523			stubs: {
3524				symbol_file: "libz.map.txt",
3525				versions: ["30"],
3526			}
3527		}
3528	`+vndkLibrariesTxtFiles("current"), withFiles(map[string][]byte{
3529		"libz.map.txt": nil,
3530	}))
3531
3532	apexManifestRule := ctx.ModuleForTests("com.android.vndk.current", "android_common_image").Rule("apexManifestRule")
3533	provideNativeLibs := names(apexManifestRule.Args["provideNativeLibs"])
3534	ensureListEmpty(t, provideNativeLibs)
3535}
3536
3537func TestDependenciesInApexManifest(t *testing.T) {
3538	ctx := testApex(t, `
3539		apex {
3540			name: "myapex_nodep",
3541			key: "myapex.key",
3542			native_shared_libs: ["lib_nodep"],
3543			compile_multilib: "both",
3544			file_contexts: ":myapex-file_contexts",
3545			updatable: false,
3546		}
3547
3548		apex {
3549			name: "myapex_dep",
3550			key: "myapex.key",
3551			native_shared_libs: ["lib_dep"],
3552			compile_multilib: "both",
3553			file_contexts: ":myapex-file_contexts",
3554			updatable: false,
3555		}
3556
3557		apex {
3558			name: "myapex_provider",
3559			key: "myapex.key",
3560			native_shared_libs: ["libfoo"],
3561			compile_multilib: "both",
3562			file_contexts: ":myapex-file_contexts",
3563			updatable: false,
3564		}
3565
3566		apex {
3567			name: "myapex_selfcontained",
3568			key: "myapex.key",
3569			native_shared_libs: ["lib_dep", "libfoo"],
3570			compile_multilib: "both",
3571			file_contexts: ":myapex-file_contexts",
3572			updatable: false,
3573		}
3574
3575		apex_key {
3576			name: "myapex.key",
3577			public_key: "testkey.avbpubkey",
3578			private_key: "testkey.pem",
3579		}
3580
3581		cc_library {
3582			name: "lib_nodep",
3583			srcs: ["mylib.cpp"],
3584			system_shared_libs: [],
3585			stl: "none",
3586			apex_available: [ "myapex_nodep" ],
3587		}
3588
3589		cc_library {
3590			name: "lib_dep",
3591			srcs: ["mylib.cpp"],
3592			shared_libs: ["libfoo"],
3593			system_shared_libs: [],
3594			stl: "none",
3595			apex_available: [
3596				"myapex_dep",
3597				"myapex_provider",
3598				"myapex_selfcontained",
3599			],
3600		}
3601
3602		cc_library {
3603			name: "libfoo",
3604			srcs: ["mytest.cpp"],
3605			stubs: {
3606				versions: ["1"],
3607			},
3608			system_shared_libs: [],
3609			stl: "none",
3610			apex_available: [
3611				"myapex_provider",
3612				"myapex_selfcontained",
3613			],
3614		}
3615	`)
3616
3617	var apexManifestRule android.TestingBuildParams
3618	var provideNativeLibs, requireNativeLibs []string
3619
3620	apexManifestRule = ctx.ModuleForTests("myapex_nodep", "android_common_myapex_nodep_image").Rule("apexManifestRule")
3621	provideNativeLibs = names(apexManifestRule.Args["provideNativeLibs"])
3622	requireNativeLibs = names(apexManifestRule.Args["requireNativeLibs"])
3623	ensureListEmpty(t, provideNativeLibs)
3624	ensureListEmpty(t, requireNativeLibs)
3625
3626	apexManifestRule = ctx.ModuleForTests("myapex_dep", "android_common_myapex_dep_image").Rule("apexManifestRule")
3627	provideNativeLibs = names(apexManifestRule.Args["provideNativeLibs"])
3628	requireNativeLibs = names(apexManifestRule.Args["requireNativeLibs"])
3629	ensureListEmpty(t, provideNativeLibs)
3630	ensureListContains(t, requireNativeLibs, "libfoo.so")
3631
3632	apexManifestRule = ctx.ModuleForTests("myapex_provider", "android_common_myapex_provider_image").Rule("apexManifestRule")
3633	provideNativeLibs = names(apexManifestRule.Args["provideNativeLibs"])
3634	requireNativeLibs = names(apexManifestRule.Args["requireNativeLibs"])
3635	ensureListContains(t, provideNativeLibs, "libfoo.so")
3636	ensureListEmpty(t, requireNativeLibs)
3637
3638	apexManifestRule = ctx.ModuleForTests("myapex_selfcontained", "android_common_myapex_selfcontained_image").Rule("apexManifestRule")
3639	provideNativeLibs = names(apexManifestRule.Args["provideNativeLibs"])
3640	requireNativeLibs = names(apexManifestRule.Args["requireNativeLibs"])
3641	ensureListContains(t, provideNativeLibs, "libfoo.so")
3642	ensureListEmpty(t, requireNativeLibs)
3643}
3644
3645func TestApexName(t *testing.T) {
3646	ctx := testApex(t, `
3647		apex {
3648			name: "myapex",
3649			key: "myapex.key",
3650			apex_name: "com.android.myapex",
3651			native_shared_libs: ["mylib"],
3652			updatable: false,
3653		}
3654
3655		apex_key {
3656			name: "myapex.key",
3657			public_key: "testkey.avbpubkey",
3658			private_key: "testkey.pem",
3659		}
3660
3661		cc_library {
3662			name: "mylib",
3663			srcs: ["mylib.cpp"],
3664			system_shared_libs: [],
3665			stl: "none",
3666			apex_available: [
3667				"//apex_available:platform",
3668				"myapex",
3669			],
3670		}
3671	`)
3672
3673	module := ctx.ModuleForTests("myapex", "android_common_com.android.myapex_image")
3674	apexManifestRule := module.Rule("apexManifestRule")
3675	ensureContains(t, apexManifestRule.Args["opt"], "-v name com.android.myapex")
3676	apexRule := module.Rule("apexRule")
3677	ensureContains(t, apexRule.Args["opt_flags"], "--do_not_check_keyname")
3678
3679	apexBundle := module.Module().(*apexBundle)
3680	data := android.AndroidMkDataForTest(t, ctx, apexBundle)
3681	name := apexBundle.BaseModuleName()
3682	prefix := "TARGET_"
3683	var builder strings.Builder
3684	data.Custom(&builder, name, prefix, "", data)
3685	androidMk := builder.String()
3686	ensureContains(t, androidMk, "LOCAL_MODULE := mylib.myapex\n")
3687	ensureNotContains(t, androidMk, "LOCAL_MODULE := mylib.com.android.myapex\n")
3688}
3689
3690func TestNonTestApex(t *testing.T) {
3691	ctx := testApex(t, `
3692		apex {
3693			name: "myapex",
3694			key: "myapex.key",
3695			native_shared_libs: ["mylib_common"],
3696			updatable: false,
3697		}
3698
3699		apex_key {
3700			name: "myapex.key",
3701			public_key: "testkey.avbpubkey",
3702			private_key: "testkey.pem",
3703		}
3704
3705		cc_library {
3706			name: "mylib_common",
3707			srcs: ["mylib.cpp"],
3708			system_shared_libs: [],
3709			stl: "none",
3710			apex_available: [
3711					"//apex_available:platform",
3712				  "myapex",
3713		  ],
3714		}
3715	`)
3716
3717	module := ctx.ModuleForTests("myapex", "android_common_myapex_image")
3718	apexRule := module.Rule("apexRule")
3719	copyCmds := apexRule.Args["copy_commands"]
3720
3721	if apex, ok := module.Module().(*apexBundle); !ok || apex.testApex {
3722		t.Log("Apex was a test apex!")
3723		t.Fail()
3724	}
3725	// Ensure that main rule creates an output
3726	ensureContains(t, apexRule.Output.String(), "myapex.apex.unsigned")
3727
3728	// Ensure that apex variant is created for the direct dep
3729	ensureListContains(t, ctx.ModuleVariantsForTests("mylib_common"), "android_arm64_armv8-a_shared_apex10000")
3730
3731	// Ensure that both direct and indirect deps are copied into apex
3732	ensureContains(t, copyCmds, "image.apex/lib64/mylib_common.so")
3733
3734	// Ensure that the platform variant ends with _shared
3735	ensureListContains(t, ctx.ModuleVariantsForTests("mylib_common"), "android_arm64_armv8-a_shared")
3736
3737	if !ctx.ModuleForTests("mylib_common", "android_arm64_armv8-a_shared_apex10000").Module().(*cc.Module).InAnyApex() {
3738		t.Log("Found mylib_common not in any apex!")
3739		t.Fail()
3740	}
3741}
3742
3743func TestTestApex(t *testing.T) {
3744	ctx := testApex(t, `
3745		apex_test {
3746			name: "myapex",
3747			key: "myapex.key",
3748			native_shared_libs: ["mylib_common_test"],
3749			updatable: false,
3750		}
3751
3752		apex_key {
3753			name: "myapex.key",
3754			public_key: "testkey.avbpubkey",
3755			private_key: "testkey.pem",
3756		}
3757
3758		cc_library {
3759			name: "mylib_common_test",
3760			srcs: ["mylib.cpp"],
3761			system_shared_libs: [],
3762			stl: "none",
3763			// TODO: remove //apex_available:platform
3764			apex_available: [
3765				"//apex_available:platform",
3766				"myapex",
3767			],
3768		}
3769	`)
3770
3771	module := ctx.ModuleForTests("myapex", "android_common_myapex_image")
3772	apexRule := module.Rule("apexRule")
3773	copyCmds := apexRule.Args["copy_commands"]
3774
3775	if apex, ok := module.Module().(*apexBundle); !ok || !apex.testApex {
3776		t.Log("Apex was not a test apex!")
3777		t.Fail()
3778	}
3779	// Ensure that main rule creates an output
3780	ensureContains(t, apexRule.Output.String(), "myapex.apex.unsigned")
3781
3782	// Ensure that apex variant is created for the direct dep
3783	ensureListContains(t, ctx.ModuleVariantsForTests("mylib_common_test"), "android_arm64_armv8-a_shared_apex10000")
3784
3785	// Ensure that both direct and indirect deps are copied into apex
3786	ensureContains(t, copyCmds, "image.apex/lib64/mylib_common_test.so")
3787
3788	// Ensure that the platform variant ends with _shared
3789	ensureListContains(t, ctx.ModuleVariantsForTests("mylib_common_test"), "android_arm64_armv8-a_shared")
3790}
3791
3792func TestApexWithTarget(t *testing.T) {
3793	ctx := testApex(t, `
3794		apex {
3795			name: "myapex",
3796			key: "myapex.key",
3797			updatable: false,
3798			multilib: {
3799				first: {
3800					native_shared_libs: ["mylib_common"],
3801				}
3802			},
3803			target: {
3804				android: {
3805					multilib: {
3806						first: {
3807							native_shared_libs: ["mylib"],
3808						}
3809					}
3810				},
3811				host: {
3812					multilib: {
3813						first: {
3814							native_shared_libs: ["mylib2"],
3815						}
3816					}
3817				}
3818			}
3819		}
3820
3821		apex_key {
3822			name: "myapex.key",
3823			public_key: "testkey.avbpubkey",
3824			private_key: "testkey.pem",
3825		}
3826
3827		cc_library {
3828			name: "mylib",
3829			srcs: ["mylib.cpp"],
3830			system_shared_libs: [],
3831			stl: "none",
3832			// TODO: remove //apex_available:platform
3833			apex_available: [
3834				"//apex_available:platform",
3835				"myapex",
3836			],
3837		}
3838
3839		cc_library {
3840			name: "mylib_common",
3841			srcs: ["mylib.cpp"],
3842			system_shared_libs: [],
3843			stl: "none",
3844			compile_multilib: "first",
3845			// TODO: remove //apex_available:platform
3846			apex_available: [
3847				"//apex_available:platform",
3848				"myapex",
3849			],
3850		}
3851
3852		cc_library {
3853			name: "mylib2",
3854			srcs: ["mylib.cpp"],
3855			system_shared_libs: [],
3856			stl: "none",
3857			compile_multilib: "first",
3858		}
3859	`)
3860
3861	apexRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("apexRule")
3862	copyCmds := apexRule.Args["copy_commands"]
3863
3864	// Ensure that main rule creates an output
3865	ensureContains(t, apexRule.Output.String(), "myapex.apex.unsigned")
3866
3867	// Ensure that apex variant is created for the direct dep
3868	ensureListContains(t, ctx.ModuleVariantsForTests("mylib"), "android_arm64_armv8-a_shared_apex10000")
3869	ensureListContains(t, ctx.ModuleVariantsForTests("mylib_common"), "android_arm64_armv8-a_shared_apex10000")
3870	ensureListNotContains(t, ctx.ModuleVariantsForTests("mylib2"), "android_arm64_armv8-a_shared_apex10000")
3871
3872	// Ensure that both direct and indirect deps are copied into apex
3873	ensureContains(t, copyCmds, "image.apex/lib64/mylib.so")
3874	ensureContains(t, copyCmds, "image.apex/lib64/mylib_common.so")
3875	ensureNotContains(t, copyCmds, "image.apex/lib64/mylib2.so")
3876
3877	// Ensure that the platform variant ends with _shared
3878	ensureListContains(t, ctx.ModuleVariantsForTests("mylib"), "android_arm64_armv8-a_shared")
3879	ensureListContains(t, ctx.ModuleVariantsForTests("mylib_common"), "android_arm64_armv8-a_shared")
3880	ensureListContains(t, ctx.ModuleVariantsForTests("mylib2"), "android_arm64_armv8-a_shared")
3881}
3882
3883func TestApexWithArch(t *testing.T) {
3884	ctx := testApex(t, `
3885		apex {
3886			name: "myapex",
3887			key: "myapex.key",
3888			updatable: false,
3889			arch: {
3890				arm64: {
3891					native_shared_libs: ["mylib.arm64"],
3892				},
3893				x86_64: {
3894					native_shared_libs: ["mylib.x64"],
3895				},
3896			}
3897		}
3898
3899		apex_key {
3900			name: "myapex.key",
3901			public_key: "testkey.avbpubkey",
3902			private_key: "testkey.pem",
3903		}
3904
3905		cc_library {
3906			name: "mylib.arm64",
3907			srcs: ["mylib.cpp"],
3908			system_shared_libs: [],
3909			stl: "none",
3910			// TODO: remove //apex_available:platform
3911			apex_available: [
3912				"//apex_available:platform",
3913				"myapex",
3914			],
3915		}
3916
3917		cc_library {
3918			name: "mylib.x64",
3919			srcs: ["mylib.cpp"],
3920			system_shared_libs: [],
3921			stl: "none",
3922			// TODO: remove //apex_available:platform
3923			apex_available: [
3924				"//apex_available:platform",
3925				"myapex",
3926			],
3927		}
3928	`)
3929
3930	apexRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("apexRule")
3931	copyCmds := apexRule.Args["copy_commands"]
3932
3933	// Ensure that apex variant is created for the direct dep
3934	ensureListContains(t, ctx.ModuleVariantsForTests("mylib.arm64"), "android_arm64_armv8-a_shared_apex10000")
3935	ensureListNotContains(t, ctx.ModuleVariantsForTests("mylib.x64"), "android_arm64_armv8-a_shared_apex10000")
3936
3937	// Ensure that both direct and indirect deps are copied into apex
3938	ensureContains(t, copyCmds, "image.apex/lib64/mylib.arm64.so")
3939	ensureNotContains(t, copyCmds, "image.apex/lib64/mylib.x64.so")
3940}
3941
3942func TestApexWithShBinary(t *testing.T) {
3943	ctx := testApex(t, `
3944		apex {
3945			name: "myapex",
3946			key: "myapex.key",
3947			binaries: ["myscript"],
3948			updatable: false,
3949		}
3950
3951		apex_key {
3952			name: "myapex.key",
3953			public_key: "testkey.avbpubkey",
3954			private_key: "testkey.pem",
3955		}
3956
3957		sh_binary {
3958			name: "myscript",
3959			src: "mylib.cpp",
3960			filename: "myscript.sh",
3961			sub_dir: "script",
3962		}
3963	`)
3964
3965	apexRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("apexRule")
3966	copyCmds := apexRule.Args["copy_commands"]
3967
3968	ensureContains(t, copyCmds, "image.apex/bin/script/myscript.sh")
3969}
3970
3971func TestApexInVariousPartition(t *testing.T) {
3972	testcases := []struct {
3973		propName, parition, flattenedPartition string
3974	}{
3975		{"", "system", "system_ext"},
3976		{"product_specific: true", "product", "product"},
3977		{"soc_specific: true", "vendor", "vendor"},
3978		{"proprietary: true", "vendor", "vendor"},
3979		{"vendor: true", "vendor", "vendor"},
3980		{"system_ext_specific: true", "system_ext", "system_ext"},
3981	}
3982	for _, tc := range testcases {
3983		t.Run(tc.propName+":"+tc.parition, func(t *testing.T) {
3984			ctx := testApex(t, `
3985				apex {
3986					name: "myapex",
3987					key: "myapex.key",
3988					updatable: false,
3989					`+tc.propName+`
3990				}
3991
3992				apex_key {
3993					name: "myapex.key",
3994					public_key: "testkey.avbpubkey",
3995					private_key: "testkey.pem",
3996				}
3997			`)
3998
3999			apex := ctx.ModuleForTests("myapex", "android_common_myapex_image").Module().(*apexBundle)
4000			expected := "out/soong/target/product/test_device/" + tc.parition + "/apex"
4001			actual := apex.installDir.RelativeToTop().String()
4002			if actual != expected {
4003				t.Errorf("wrong install path. expected %q. actual %q", expected, actual)
4004			}
4005
4006			flattened := ctx.ModuleForTests("myapex", "android_common_myapex_flattened").Module().(*apexBundle)
4007			expected = "out/soong/target/product/test_device/" + tc.flattenedPartition + "/apex"
4008			actual = flattened.installDir.RelativeToTop().String()
4009			if actual != expected {
4010				t.Errorf("wrong install path. expected %q. actual %q", expected, actual)
4011			}
4012		})
4013	}
4014}
4015
4016func TestFileContexts_FindInDefaultLocationIfNotSet(t *testing.T) {
4017	ctx := testApex(t, `
4018		apex {
4019			name: "myapex",
4020			key: "myapex.key",
4021			updatable: false,
4022		}
4023
4024		apex_key {
4025			name: "myapex.key",
4026			public_key: "testkey.avbpubkey",
4027			private_key: "testkey.pem",
4028		}
4029	`)
4030	module := ctx.ModuleForTests("myapex", "android_common_myapex_image")
4031	rule := module.Output("file_contexts")
4032	ensureContains(t, rule.RuleParams.Command, "cat system/sepolicy/apex/myapex-file_contexts")
4033}
4034
4035func TestFileContexts_ShouldBeUnderSystemSepolicyForSystemApexes(t *testing.T) {
4036	testApexError(t, `"myapex" .*: file_contexts: should be under system/sepolicy`, `
4037		apex {
4038			name: "myapex",
4039			key: "myapex.key",
4040			file_contexts: "my_own_file_contexts",
4041			updatable: false,
4042		}
4043
4044		apex_key {
4045			name: "myapex.key",
4046			public_key: "testkey.avbpubkey",
4047			private_key: "testkey.pem",
4048		}
4049	`, withFiles(map[string][]byte{
4050		"my_own_file_contexts": nil,
4051	}))
4052}
4053
4054func TestFileContexts_ProductSpecificApexes(t *testing.T) {
4055	testApexError(t, `"myapex" .*: file_contexts: cannot find`, `
4056		apex {
4057			name: "myapex",
4058			key: "myapex.key",
4059			product_specific: true,
4060			file_contexts: "product_specific_file_contexts",
4061			updatable: false,
4062		}
4063
4064		apex_key {
4065			name: "myapex.key",
4066			public_key: "testkey.avbpubkey",
4067			private_key: "testkey.pem",
4068		}
4069	`)
4070
4071	ctx := testApex(t, `
4072		apex {
4073			name: "myapex",
4074			key: "myapex.key",
4075			product_specific: true,
4076			file_contexts: "product_specific_file_contexts",
4077			updatable: false,
4078		}
4079
4080		apex_key {
4081			name: "myapex.key",
4082			public_key: "testkey.avbpubkey",
4083			private_key: "testkey.pem",
4084		}
4085	`, withFiles(map[string][]byte{
4086		"product_specific_file_contexts": nil,
4087	}))
4088	module := ctx.ModuleForTests("myapex", "android_common_myapex_image")
4089	rule := module.Output("file_contexts")
4090	ensureContains(t, rule.RuleParams.Command, "cat product_specific_file_contexts")
4091}
4092
4093func TestFileContexts_SetViaFileGroup(t *testing.T) {
4094	ctx := testApex(t, `
4095		apex {
4096			name: "myapex",
4097			key: "myapex.key",
4098			product_specific: true,
4099			file_contexts: ":my-file-contexts",
4100			updatable: false,
4101		}
4102
4103		apex_key {
4104			name: "myapex.key",
4105			public_key: "testkey.avbpubkey",
4106			private_key: "testkey.pem",
4107		}
4108
4109		filegroup {
4110			name: "my-file-contexts",
4111			srcs: ["product_specific_file_contexts"],
4112		}
4113	`, withFiles(map[string][]byte{
4114		"product_specific_file_contexts": nil,
4115	}))
4116	module := ctx.ModuleForTests("myapex", "android_common_myapex_image")
4117	rule := module.Output("file_contexts")
4118	ensureContains(t, rule.RuleParams.Command, "cat product_specific_file_contexts")
4119}
4120
4121func TestApexKeyFromOtherModule(t *testing.T) {
4122	ctx := testApex(t, `
4123		apex_key {
4124			name: "myapex.key",
4125			public_key: ":my.avbpubkey",
4126			private_key: ":my.pem",
4127			product_specific: true,
4128		}
4129
4130		filegroup {
4131			name: "my.avbpubkey",
4132			srcs: ["testkey2.avbpubkey"],
4133		}
4134
4135		filegroup {
4136			name: "my.pem",
4137			srcs: ["testkey2.pem"],
4138		}
4139	`)
4140
4141	apex_key := ctx.ModuleForTests("myapex.key", "android_common").Module().(*apexKey)
4142	expected_pubkey := "testkey2.avbpubkey"
4143	actual_pubkey := apex_key.publicKeyFile.String()
4144	if actual_pubkey != expected_pubkey {
4145		t.Errorf("wrong public key path. expected %q. actual %q", expected_pubkey, actual_pubkey)
4146	}
4147	expected_privkey := "testkey2.pem"
4148	actual_privkey := apex_key.privateKeyFile.String()
4149	if actual_privkey != expected_privkey {
4150		t.Errorf("wrong private key path. expected %q. actual %q", expected_privkey, actual_privkey)
4151	}
4152}
4153
4154func TestPrebuilt(t *testing.T) {
4155	ctx := testApex(t, `
4156		prebuilt_apex {
4157			name: "myapex",
4158			arch: {
4159				arm64: {
4160					src: "myapex-arm64.apex",
4161				},
4162				arm: {
4163					src: "myapex-arm.apex",
4164				},
4165			},
4166		}
4167	`)
4168
4169	prebuilt := ctx.ModuleForTests("myapex", "android_common_myapex").Module().(*Prebuilt)
4170
4171	expectedInput := "myapex-arm64.apex"
4172	if prebuilt.inputApex.String() != expectedInput {
4173		t.Errorf("inputApex invalid. expected: %q, actual: %q", expectedInput, prebuilt.inputApex.String())
4174	}
4175}
4176
4177func TestPrebuiltMissingSrc(t *testing.T) {
4178	testApexError(t, `module "myapex" variant "android_common_myapex".*: prebuilt_apex does not support "arm64_armv8-a"`, `
4179		prebuilt_apex {
4180			name: "myapex",
4181		}
4182	`)
4183}
4184
4185func TestPrebuiltFilenameOverride(t *testing.T) {
4186	ctx := testApex(t, `
4187		prebuilt_apex {
4188			name: "myapex",
4189			src: "myapex-arm.apex",
4190			filename: "notmyapex.apex",
4191		}
4192	`)
4193
4194	p := ctx.ModuleForTests("myapex", "android_common_myapex").Module().(*Prebuilt)
4195
4196	expected := "notmyapex.apex"
4197	if p.installFilename != expected {
4198		t.Errorf("installFilename invalid. expected: %q, actual: %q", expected, p.installFilename)
4199	}
4200}
4201
4202func TestPrebuiltOverrides(t *testing.T) {
4203	ctx := testApex(t, `
4204		prebuilt_apex {
4205			name: "myapex.prebuilt",
4206			src: "myapex-arm.apex",
4207			overrides: [
4208				"myapex",
4209			],
4210		}
4211	`)
4212
4213	p := ctx.ModuleForTests("myapex.prebuilt", "android_common_myapex.prebuilt").Module().(*Prebuilt)
4214
4215	expected := []string{"myapex"}
4216	actual := android.AndroidMkEntriesForTest(t, ctx, p)[0].EntryMap["LOCAL_OVERRIDES_MODULES"]
4217	if !reflect.DeepEqual(actual, expected) {
4218		t.Errorf("Incorrect LOCAL_OVERRIDES_MODULES value '%s', expected '%s'", actual, expected)
4219	}
4220}
4221
4222func TestPrebuiltApexName(t *testing.T) {
4223	testApex(t, `
4224		prebuilt_apex {
4225			name: "com.company.android.myapex",
4226			apex_name: "com.android.myapex",
4227			src: "company-myapex-arm.apex",
4228		}
4229	`).ModuleForTests("com.company.android.myapex", "android_common_com.android.myapex")
4230
4231	testApex(t, `
4232		apex_set {
4233			name: "com.company.android.myapex",
4234			apex_name: "com.android.myapex",
4235			set: "company-myapex.apks",
4236		}
4237	`).ModuleForTests("com.company.android.myapex", "android_common_com.android.myapex")
4238}
4239
4240func TestPrebuiltApexNameWithPlatformBootclasspath(t *testing.T) {
4241	_ = android.GroupFixturePreparers(
4242		java.PrepareForTestWithJavaDefaultModules,
4243		PrepareForTestWithApexBuildComponents,
4244		android.FixtureWithRootAndroidBp(`
4245			platform_bootclasspath {
4246				name: "platform-bootclasspath",
4247				fragments: [
4248					{
4249						apex: "com.android.art",
4250						module: "art-bootclasspath-fragment",
4251					},
4252				],
4253			}
4254
4255			prebuilt_apex {
4256				name: "com.company.android.art",
4257				apex_name: "com.android.art",
4258				src: "com.company.android.art-arm.apex",
4259				exported_bootclasspath_fragments: ["art-bootclasspath-fragment"],
4260			}
4261
4262			prebuilt_bootclasspath_fragment {
4263				name: "art-bootclasspath-fragment",
4264				contents: ["core-oj"],
4265			}
4266
4267			java_import {
4268				name: "core-oj",
4269				jars: ["prebuilt.jar"],
4270			}
4271		`),
4272	).RunTest(t)
4273}
4274
4275// These tests verify that the prebuilt_apex/deapexer to java_import wiring allows for the
4276// propagation of paths to dex implementation jars from the former to the latter.
4277func TestPrebuiltExportDexImplementationJars(t *testing.T) {
4278	transform := android.NullFixturePreparer
4279
4280	checkDexJarBuildPath := func(t *testing.T, ctx *android.TestContext, name string) {
4281		// Make sure the import has been given the correct path to the dex jar.
4282		p := ctx.ModuleForTests(name, "android_common_myapex").Module().(java.UsesLibraryDependency)
4283		dexJarBuildPath := p.DexJarBuildPath()
4284		stem := android.RemoveOptionalPrebuiltPrefix(name)
4285		if expected, actual := ".intermediates/myapex.deapexer/android_common/deapexer/javalib/"+stem+".jar", android.NormalizePathForTesting(dexJarBuildPath); actual != expected {
4286			t.Errorf("Incorrect DexJarBuildPath value '%s', expected '%s'", actual, expected)
4287		}
4288	}
4289
4290	ensureNoSourceVariant := func(t *testing.T, ctx *android.TestContext, name string) {
4291		// Make sure that an apex variant is not created for the source module.
4292		if expected, actual := []string{"android_common"}, ctx.ModuleVariantsForTests(name); !reflect.DeepEqual(expected, actual) {
4293			t.Errorf("invalid set of variants for %q: expected %q, found %q", "libfoo", expected, actual)
4294		}
4295	}
4296
4297	t.Run("prebuilt only", func(t *testing.T) {
4298		bp := `
4299		prebuilt_apex {
4300			name: "myapex",
4301			arch: {
4302				arm64: {
4303					src: "myapex-arm64.apex",
4304				},
4305				arm: {
4306					src: "myapex-arm.apex",
4307				},
4308			},
4309			exported_java_libs: ["libfoo", "libbar"],
4310		}
4311
4312		java_import {
4313			name: "libfoo",
4314			jars: ["libfoo.jar"],
4315		}
4316
4317		java_sdk_library_import {
4318			name: "libbar",
4319			public: {
4320				jars: ["libbar.jar"],
4321			},
4322		}
4323	`
4324
4325		// Make sure that dexpreopt can access dex implementation files from the prebuilt.
4326		ctx := testDexpreoptWithApexes(t, bp, "", transform)
4327
4328		// Make sure that the deapexer has the correct input APEX.
4329		deapexer := ctx.ModuleForTests("myapex.deapexer", "android_common")
4330		rule := deapexer.Rule("deapexer")
4331		if expected, actual := []string{"myapex-arm64.apex"}, android.NormalizePathsForTesting(rule.Implicits); !reflect.DeepEqual(expected, actual) {
4332			t.Errorf("expected: %q, found: %q", expected, actual)
4333		}
4334
4335		// Make sure that the prebuilt_apex has the correct input APEX.
4336		prebuiltApex := ctx.ModuleForTests("myapex", "android_common_myapex")
4337		rule = prebuiltApex.Rule("android/soong/android.Cp")
4338		if expected, actual := "myapex-arm64.apex", android.NormalizePathForTesting(rule.Input); !reflect.DeepEqual(expected, actual) {
4339			t.Errorf("expected: %q, found: %q", expected, actual)
4340		}
4341
4342		checkDexJarBuildPath(t, ctx, "libfoo")
4343
4344		checkDexJarBuildPath(t, ctx, "libbar")
4345	})
4346
4347	t.Run("prebuilt with source preferred", func(t *testing.T) {
4348
4349		bp := `
4350		prebuilt_apex {
4351			name: "myapex",
4352			arch: {
4353				arm64: {
4354					src: "myapex-arm64.apex",
4355				},
4356				arm: {
4357					src: "myapex-arm.apex",
4358				},
4359			},
4360			exported_java_libs: ["libfoo", "libbar"],
4361		}
4362
4363		java_import {
4364			name: "libfoo",
4365			jars: ["libfoo.jar"],
4366		}
4367
4368		java_library {
4369			name: "libfoo",
4370		}
4371
4372		java_sdk_library_import {
4373			name: "libbar",
4374			public: {
4375				jars: ["libbar.jar"],
4376			},
4377		}
4378
4379		java_sdk_library {
4380			name: "libbar",
4381			srcs: ["foo/bar/MyClass.java"],
4382			unsafe_ignore_missing_latest_api: true,
4383		}
4384	`
4385
4386		// Make sure that dexpreopt can access dex implementation files from the prebuilt.
4387		ctx := testDexpreoptWithApexes(t, bp, "", transform)
4388
4389		checkDexJarBuildPath(t, ctx, "prebuilt_libfoo")
4390		ensureNoSourceVariant(t, ctx, "libfoo")
4391
4392		checkDexJarBuildPath(t, ctx, "prebuilt_libbar")
4393		ensureNoSourceVariant(t, ctx, "libbar")
4394	})
4395
4396	t.Run("prebuilt preferred with source", func(t *testing.T) {
4397		bp := `
4398		prebuilt_apex {
4399			name: "myapex",
4400			arch: {
4401				arm64: {
4402					src: "myapex-arm64.apex",
4403				},
4404				arm: {
4405					src: "myapex-arm.apex",
4406				},
4407			},
4408			exported_java_libs: ["libfoo", "libbar"],
4409		}
4410
4411		java_import {
4412			name: "libfoo",
4413			prefer: true,
4414			jars: ["libfoo.jar"],
4415		}
4416
4417		java_library {
4418			name: "libfoo",
4419		}
4420
4421		java_sdk_library_import {
4422			name: "libbar",
4423			prefer: true,
4424			public: {
4425				jars: ["libbar.jar"],
4426			},
4427		}
4428
4429		java_sdk_library {
4430			name: "libbar",
4431			srcs: ["foo/bar/MyClass.java"],
4432			unsafe_ignore_missing_latest_api: true,
4433		}
4434	`
4435
4436		// Make sure that dexpreopt can access dex implementation files from the prebuilt.
4437		ctx := testDexpreoptWithApexes(t, bp, "", transform)
4438
4439		checkDexJarBuildPath(t, ctx, "prebuilt_libfoo")
4440		ensureNoSourceVariant(t, ctx, "libfoo")
4441
4442		checkDexJarBuildPath(t, ctx, "prebuilt_libbar")
4443		ensureNoSourceVariant(t, ctx, "libbar")
4444	})
4445}
4446
4447func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) {
4448	preparer := android.GroupFixturePreparers(
4449		java.FixtureConfigureBootJars("myapex:libfoo", "myapex:libbar"),
4450		// Make sure that the frameworks/base/Android.bp file exists as otherwise hidden API encoding
4451		// is disabled.
4452		android.FixtureAddTextFile("frameworks/base/Android.bp", ""),
4453	)
4454
4455	checkBootDexJarPath := func(t *testing.T, ctx *android.TestContext, stem string, bootDexJarPath string) {
4456		t.Helper()
4457		s := ctx.ModuleForTests("platform-bootclasspath", "android_common")
4458		foundLibfooJar := false
4459		base := stem + ".jar"
4460		for _, output := range s.AllOutputs() {
4461			if filepath.Base(output) == base {
4462				foundLibfooJar = true
4463				buildRule := s.Output(output)
4464				android.AssertStringEquals(t, "boot dex jar path", bootDexJarPath, buildRule.Input.String())
4465			}
4466		}
4467		if !foundLibfooJar {
4468			t.Errorf("Rule for libfoo.jar missing in dex_bootjars singleton outputs %q", android.StringPathsRelativeToTop(ctx.Config().BuildDir(), s.AllOutputs()))
4469		}
4470	}
4471
4472	checkHiddenAPIIndexInputs := func(t *testing.T, ctx *android.TestContext, expectedIntermediateInputs string) {
4473		t.Helper()
4474		platformBootclasspath := ctx.ModuleForTests("platform-bootclasspath", "android_common")
4475		var rule android.TestingBuildParams
4476
4477		rule = platformBootclasspath.Output("hiddenapi-monolithic/index-from-classes.csv")
4478		java.CheckHiddenAPIRuleInputs(t, "intermediate index", expectedIntermediateInputs, rule)
4479	}
4480
4481	fragment := java.ApexVariantReference{
4482		Apex:   proptools.StringPtr("myapex"),
4483		Module: proptools.StringPtr("my-bootclasspath-fragment"),
4484	}
4485
4486	t.Run("prebuilt only", func(t *testing.T) {
4487		bp := `
4488		prebuilt_apex {
4489			name: "myapex",
4490			arch: {
4491				arm64: {
4492					src: "myapex-arm64.apex",
4493				},
4494				arm: {
4495					src: "myapex-arm.apex",
4496				},
4497			},
4498			exported_bootclasspath_fragments: ["my-bootclasspath-fragment"],
4499		}
4500
4501		prebuilt_bootclasspath_fragment {
4502			name: "my-bootclasspath-fragment",
4503			contents: ["libfoo", "libbar"],
4504			apex_available: ["myapex"],
4505		}
4506
4507		java_import {
4508			name: "libfoo",
4509			jars: ["libfoo.jar"],
4510			apex_available: ["myapex"],
4511		}
4512
4513		java_sdk_library_import {
4514			name: "libbar",
4515			public: {
4516				jars: ["libbar.jar"],
4517			},
4518			apex_available: ["myapex"],
4519			shared_library: false,
4520		}
4521	`
4522
4523		ctx := testDexpreoptWithApexes(t, bp, "", preparer, fragment)
4524		checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar")
4525		checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libbar.jar")
4526
4527		// Verify the correct module jars contribute to the hiddenapi index file.
4528		checkHiddenAPIIndexInputs(t, ctx, `
4529			out/soong/.intermediates/libbar.stubs/android_common/combined/libbar.stubs.jar
4530			out/soong/.intermediates/libfoo/android_common_myapex/combined/libfoo.jar
4531		`)
4532	})
4533
4534	t.Run("apex_set only", func(t *testing.T) {
4535		bp := `
4536		apex_set {
4537			name: "myapex",
4538			set: "myapex.apks",
4539			exported_bootclasspath_fragments: ["my-bootclasspath-fragment"],
4540		}
4541
4542		prebuilt_bootclasspath_fragment {
4543			name: "my-bootclasspath-fragment",
4544			contents: ["libfoo", "libbar"],
4545			apex_available: ["myapex"],
4546		}
4547
4548		java_import {
4549			name: "libfoo",
4550			jars: ["libfoo.jar"],
4551			apex_available: ["myapex"],
4552		}
4553
4554		java_sdk_library_import {
4555			name: "libbar",
4556			public: {
4557				jars: ["libbar.jar"],
4558			},
4559			apex_available: ["myapex"],
4560			shared_library: false,
4561		}
4562	`
4563
4564		ctx := testDexpreoptWithApexes(t, bp, "", preparer, fragment)
4565		checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar")
4566		checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libbar.jar")
4567
4568		// Verify the correct module jars contribute to the hiddenapi index file.
4569		checkHiddenAPIIndexInputs(t, ctx, `
4570			out/soong/.intermediates/libbar.stubs/android_common/combined/libbar.stubs.jar
4571			out/soong/.intermediates/libfoo/android_common_myapex/combined/libfoo.jar
4572		`)
4573	})
4574
4575	t.Run("prebuilt with source library preferred", func(t *testing.T) {
4576		bp := `
4577		prebuilt_apex {
4578			name: "myapex",
4579			arch: {
4580				arm64: {
4581					src: "myapex-arm64.apex",
4582				},
4583				arm: {
4584					src: "myapex-arm.apex",
4585				},
4586			},
4587			exported_bootclasspath_fragments: ["my-bootclasspath-fragment"],
4588		}
4589
4590		prebuilt_bootclasspath_fragment {
4591			name: "my-bootclasspath-fragment",
4592			contents: ["libfoo", "libbar"],
4593			apex_available: ["myapex"],
4594		}
4595
4596		java_import {
4597			name: "libfoo",
4598			jars: ["libfoo.jar"],
4599			apex_available: ["myapex"],
4600		}
4601
4602		java_library {
4603			name: "libfoo",
4604			srcs: ["foo/bar/MyClass.java"],
4605			apex_available: ["myapex"],
4606		}
4607
4608		java_sdk_library_import {
4609			name: "libbar",
4610			public: {
4611				jars: ["libbar.jar"],
4612			},
4613			apex_available: ["myapex"],
4614			shared_library: false,
4615		}
4616
4617		java_sdk_library {
4618			name: "libbar",
4619			srcs: ["foo/bar/MyClass.java"],
4620			unsafe_ignore_missing_latest_api: true,
4621			apex_available: ["myapex"],
4622		}
4623	`
4624
4625		// In this test the source (java_library) libfoo is active since the
4626		// prebuilt (java_import) defaults to prefer:false. However the
4627		// prebuilt_apex module always depends on the prebuilt, and so it doesn't
4628		// find the dex boot jar in it. We either need to disable the source libfoo
4629		// or make the prebuilt libfoo preferred.
4630		testDexpreoptWithApexes(t, bp, "module libfoo does not provide a dex boot jar", preparer, fragment)
4631	})
4632
4633	t.Run("prebuilt library preferred with source", func(t *testing.T) {
4634		bp := `
4635		prebuilt_apex {
4636			name: "myapex",
4637			arch: {
4638				arm64: {
4639					src: "myapex-arm64.apex",
4640				},
4641				arm: {
4642					src: "myapex-arm.apex",
4643				},
4644			},
4645			exported_bootclasspath_fragments: ["my-bootclasspath-fragment"],
4646		}
4647
4648		prebuilt_bootclasspath_fragment {
4649			name: "my-bootclasspath-fragment",
4650			contents: ["libfoo", "libbar"],
4651			apex_available: ["myapex"],
4652		}
4653
4654		java_import {
4655			name: "libfoo",
4656			prefer: true,
4657			jars: ["libfoo.jar"],
4658			apex_available: ["myapex"],
4659		}
4660
4661		java_library {
4662			name: "libfoo",
4663			srcs: ["foo/bar/MyClass.java"],
4664			apex_available: ["myapex"],
4665		}
4666
4667		java_sdk_library_import {
4668			name: "libbar",
4669			prefer: true,
4670			public: {
4671				jars: ["libbar.jar"],
4672			},
4673			apex_available: ["myapex"],
4674			shared_library: false,
4675		}
4676
4677		java_sdk_library {
4678			name: "libbar",
4679			srcs: ["foo/bar/MyClass.java"],
4680			unsafe_ignore_missing_latest_api: true,
4681			apex_available: ["myapex"],
4682		}
4683	`
4684
4685		ctx := testDexpreoptWithApexes(t, bp, "", preparer, fragment)
4686		checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar")
4687		checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libbar.jar")
4688
4689		// Verify the correct module jars contribute to the hiddenapi index file.
4690		checkHiddenAPIIndexInputs(t, ctx, `
4691			out/soong/.intermediates/prebuilt_libbar.stubs/android_common/combined/libbar.stubs.jar
4692			out/soong/.intermediates/prebuilt_libfoo/android_common_myapex/combined/libfoo.jar
4693		`)
4694	})
4695
4696	t.Run("prebuilt with source apex preferred", func(t *testing.T) {
4697		bp := `
4698		apex {
4699			name: "myapex",
4700			key: "myapex.key",
4701			java_libs: ["libfoo", "libbar"],
4702			updatable: false,
4703		}
4704
4705		apex_key {
4706			name: "myapex.key",
4707			public_key: "testkey.avbpubkey",
4708			private_key: "testkey.pem",
4709		}
4710
4711		prebuilt_apex {
4712			name: "myapex",
4713			arch: {
4714				arm64: {
4715					src: "myapex-arm64.apex",
4716				},
4717				arm: {
4718					src: "myapex-arm.apex",
4719				},
4720			},
4721			exported_bootclasspath_fragments: ["my-bootclasspath-fragment"],
4722		}
4723
4724		prebuilt_bootclasspath_fragment {
4725			name: "my-bootclasspath-fragment",
4726			contents: ["libfoo", "libbar"],
4727			apex_available: ["myapex"],
4728		}
4729
4730		java_import {
4731			name: "libfoo",
4732			jars: ["libfoo.jar"],
4733			apex_available: ["myapex"],
4734		}
4735
4736		java_library {
4737			name: "libfoo",
4738			srcs: ["foo/bar/MyClass.java"],
4739			apex_available: ["myapex"],
4740		}
4741
4742		java_sdk_library_import {
4743			name: "libbar",
4744			public: {
4745				jars: ["libbar.jar"],
4746			},
4747			apex_available: ["myapex"],
4748			shared_library: false,
4749		}
4750
4751		java_sdk_library {
4752			name: "libbar",
4753			srcs: ["foo/bar/MyClass.java"],
4754			unsafe_ignore_missing_latest_api: true,
4755			apex_available: ["myapex"],
4756		}
4757	`
4758
4759		ctx := testDexpreoptWithApexes(t, bp, "", preparer, fragment)
4760		checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/libfoo/android_common_apex10000/hiddenapi/libfoo.jar")
4761		checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/libbar/android_common_myapex/hiddenapi/libbar.jar")
4762
4763		// Verify the correct module jars contribute to the hiddenapi index file.
4764		checkHiddenAPIIndexInputs(t, ctx, `
4765			out/soong/.intermediates/libbar/android_common_myapex/javac/libbar.jar
4766			out/soong/.intermediates/libfoo/android_common_apex10000/javac/libfoo.jar
4767		`)
4768	})
4769
4770	t.Run("prebuilt preferred with source apex disabled", func(t *testing.T) {
4771		bp := `
4772		apex {
4773			name: "myapex",
4774			enabled: false,
4775			key: "myapex.key",
4776			java_libs: ["libfoo", "libbar"],
4777		}
4778
4779		apex_key {
4780			name: "myapex.key",
4781			public_key: "testkey.avbpubkey",
4782			private_key: "testkey.pem",
4783		}
4784
4785		prebuilt_apex {
4786			name: "myapex",
4787			arch: {
4788				arm64: {
4789					src: "myapex-arm64.apex",
4790				},
4791				arm: {
4792					src: "myapex-arm.apex",
4793				},
4794			},
4795			exported_bootclasspath_fragments: ["my-bootclasspath-fragment"],
4796		}
4797
4798		prebuilt_bootclasspath_fragment {
4799			name: "my-bootclasspath-fragment",
4800			contents: ["libfoo", "libbar"],
4801			apex_available: ["myapex"],
4802		}
4803
4804		java_import {
4805			name: "libfoo",
4806			prefer: true,
4807			jars: ["libfoo.jar"],
4808			apex_available: ["myapex"],
4809		}
4810
4811		java_library {
4812			name: "libfoo",
4813			srcs: ["foo/bar/MyClass.java"],
4814			apex_available: ["myapex"],
4815		}
4816
4817		java_sdk_library_import {
4818			name: "libbar",
4819			prefer: true,
4820			public: {
4821				jars: ["libbar.jar"],
4822			},
4823			apex_available: ["myapex"],
4824			shared_library: false,
4825		}
4826
4827		java_sdk_library {
4828			name: "libbar",
4829			srcs: ["foo/bar/MyClass.java"],
4830			unsafe_ignore_missing_latest_api: true,
4831			apex_available: ["myapex"],
4832		}
4833	`
4834
4835		ctx := testDexpreoptWithApexes(t, bp, "", preparer, fragment)
4836		checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar")
4837		checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libbar.jar")
4838
4839		// Verify the correct module jars contribute to the hiddenapi index file.
4840		checkHiddenAPIIndexInputs(t, ctx, `
4841			out/soong/.intermediates/prebuilt_libbar.stubs/android_common/combined/libbar.stubs.jar
4842			out/soong/.intermediates/prebuilt_libfoo/android_common_myapex/combined/libfoo.jar
4843		`)
4844	})
4845}
4846
4847func TestApexWithTests(t *testing.T) {
4848	ctx := testApex(t, `
4849		apex_test {
4850			name: "myapex",
4851			key: "myapex.key",
4852			updatable: false,
4853			tests: [
4854				"mytest",
4855				"mytests",
4856			],
4857		}
4858
4859		apex_key {
4860			name: "myapex.key",
4861			public_key: "testkey.avbpubkey",
4862			private_key: "testkey.pem",
4863		}
4864
4865		filegroup {
4866			name: "fg",
4867			srcs: [
4868				"baz",
4869				"bar/baz"
4870			],
4871		}
4872
4873		cc_test {
4874			name: "mytest",
4875			gtest: false,
4876			srcs: ["mytest.cpp"],
4877			relative_install_path: "test",
4878			shared_libs: ["mylib"],
4879			system_shared_libs: [],
4880			static_executable: true,
4881			stl: "none",
4882			data: [":fg"],
4883		}
4884
4885		cc_library {
4886			name: "mylib",
4887			srcs: ["mylib.cpp"],
4888			system_shared_libs: [],
4889			stl: "none",
4890		}
4891
4892		filegroup {
4893			name: "fg2",
4894			srcs: [
4895				"testdata/baz"
4896			],
4897		}
4898
4899		cc_test {
4900			name: "mytests",
4901			gtest: false,
4902			srcs: [
4903				"mytest1.cpp",
4904				"mytest2.cpp",
4905				"mytest3.cpp",
4906			],
4907			test_per_src: true,
4908			relative_install_path: "test",
4909			system_shared_libs: [],
4910			static_executable: true,
4911			stl: "none",
4912			data: [
4913				":fg",
4914				":fg2",
4915			],
4916		}
4917	`)
4918
4919	apexRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("apexRule")
4920	copyCmds := apexRule.Args["copy_commands"]
4921
4922	// Ensure that test dep (and their transitive dependencies) are copied into apex.
4923	ensureContains(t, copyCmds, "image.apex/bin/test/mytest")
4924	ensureContains(t, copyCmds, "image.apex/lib64/mylib.so")
4925
4926	//Ensure that test data are copied into apex.
4927	ensureContains(t, copyCmds, "image.apex/bin/test/baz")
4928	ensureContains(t, copyCmds, "image.apex/bin/test/bar/baz")
4929
4930	// Ensure that test deps built with `test_per_src` are copied into apex.
4931	ensureContains(t, copyCmds, "image.apex/bin/test/mytest1")
4932	ensureContains(t, copyCmds, "image.apex/bin/test/mytest2")
4933	ensureContains(t, copyCmds, "image.apex/bin/test/mytest3")
4934
4935	// Ensure the module is correctly translated.
4936	bundle := ctx.ModuleForTests("myapex", "android_common_myapex_image").Module().(*apexBundle)
4937	data := android.AndroidMkDataForTest(t, ctx, bundle)
4938	name := bundle.BaseModuleName()
4939	prefix := "TARGET_"
4940	var builder strings.Builder
4941	data.Custom(&builder, name, prefix, "", data)
4942	androidMk := builder.String()
4943	ensureContains(t, androidMk, "LOCAL_MODULE := mytest.myapex\n")
4944	ensureContains(t, androidMk, "LOCAL_MODULE := mytest1.myapex\n")
4945	ensureContains(t, androidMk, "LOCAL_MODULE := mytest2.myapex\n")
4946	ensureContains(t, androidMk, "LOCAL_MODULE := mytest3.myapex\n")
4947	ensureContains(t, androidMk, "LOCAL_MODULE := apex_manifest.pb.myapex\n")
4948	ensureContains(t, androidMk, "LOCAL_MODULE := apex_pubkey.myapex\n")
4949	ensureContains(t, androidMk, "LOCAL_MODULE := myapex\n")
4950
4951	flatBundle := ctx.ModuleForTests("myapex", "android_common_myapex_flattened").Module().(*apexBundle)
4952	data = android.AndroidMkDataForTest(t, ctx, flatBundle)
4953	data.Custom(&builder, name, prefix, "", data)
4954	flatAndroidMk := builder.String()
4955	ensureContainsOnce(t, flatAndroidMk, "LOCAL_TEST_DATA := :baz :bar/baz\n")
4956	ensureContainsOnce(t, flatAndroidMk, "LOCAL_TEST_DATA := :testdata/baz\n")
4957}
4958
4959func TestInstallExtraFlattenedApexes(t *testing.T) {
4960	ctx := testApex(t, `
4961		apex {
4962			name: "myapex",
4963			key: "myapex.key",
4964			updatable: false,
4965		}
4966		apex_key {
4967			name: "myapex.key",
4968			public_key: "testkey.avbpubkey",
4969			private_key: "testkey.pem",
4970		}
4971	`,
4972		android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
4973			variables.InstallExtraFlattenedApexes = proptools.BoolPtr(true)
4974		}),
4975	)
4976	ab := ctx.ModuleForTests("myapex", "android_common_myapex_image").Module().(*apexBundle)
4977	ensureListContains(t, ab.requiredDeps, "myapex.flattened")
4978	mk := android.AndroidMkDataForTest(t, ctx, ab)
4979	var builder strings.Builder
4980	mk.Custom(&builder, ab.Name(), "TARGET_", "", mk)
4981	androidMk := builder.String()
4982	ensureContains(t, androidMk, "LOCAL_REQUIRED_MODULES += myapex.flattened")
4983}
4984
4985func TestErrorsIfDepsAreNotEnabled(t *testing.T) {
4986	testApexError(t, `module "myapex" .* depends on disabled module "libfoo"`, `
4987		apex {
4988			name: "myapex",
4989			key: "myapex.key",
4990			native_shared_libs: ["libfoo"],
4991		}
4992
4993		apex_key {
4994			name: "myapex.key",
4995			public_key: "testkey.avbpubkey",
4996			private_key: "testkey.pem",
4997		}
4998
4999		cc_library {
5000			name: "libfoo",
5001			stl: "none",
5002			system_shared_libs: [],
5003			enabled: false,
5004			apex_available: ["myapex"],
5005		}
5006	`)
5007	testApexError(t, `module "myapex" .* depends on disabled module "myjar"`, `
5008		apex {
5009			name: "myapex",
5010			key: "myapex.key",
5011			java_libs: ["myjar"],
5012		}
5013
5014		apex_key {
5015			name: "myapex.key",
5016			public_key: "testkey.avbpubkey",
5017			private_key: "testkey.pem",
5018		}
5019
5020		java_library {
5021			name: "myjar",
5022			srcs: ["foo/bar/MyClass.java"],
5023			sdk_version: "none",
5024			system_modules: "none",
5025			enabled: false,
5026			apex_available: ["myapex"],
5027		}
5028	`)
5029}
5030
5031func TestApexWithJavaImport(t *testing.T) {
5032	ctx := testApex(t, `
5033		apex {
5034			name: "myapex",
5035			key: "myapex.key",
5036			java_libs: ["myjavaimport"],
5037			updatable: false,
5038		}
5039
5040		apex_key {
5041			name: "myapex.key",
5042			public_key: "testkey.avbpubkey",
5043			private_key: "testkey.pem",
5044		}
5045
5046		java_import {
5047			name: "myjavaimport",
5048			apex_available: ["myapex"],
5049			jars: ["my.jar"],
5050			compile_dex: true,
5051		}
5052	`)
5053
5054	module := ctx.ModuleForTests("myapex", "android_common_myapex_image")
5055	apexRule := module.Rule("apexRule")
5056	copyCmds := apexRule.Args["copy_commands"]
5057	ensureContains(t, copyCmds, "image.apex/javalib/myjavaimport.jar")
5058}
5059
5060func TestApexWithApps(t *testing.T) {
5061	ctx := testApex(t, `
5062		apex {
5063			name: "myapex",
5064			key: "myapex.key",
5065			apps: [
5066				"AppFoo",
5067				"AppFooPriv",
5068			],
5069			updatable: false,
5070		}
5071
5072		apex_key {
5073			name: "myapex.key",
5074			public_key: "testkey.avbpubkey",
5075			private_key: "testkey.pem",
5076		}
5077
5078		android_app {
5079			name: "AppFoo",
5080			srcs: ["foo/bar/MyClass.java"],
5081			sdk_version: "current",
5082			system_modules: "none",
5083			jni_libs: ["libjni"],
5084			stl: "none",
5085			apex_available: [ "myapex" ],
5086		}
5087
5088		android_app {
5089			name: "AppFooPriv",
5090			srcs: ["foo/bar/MyClass.java"],
5091			sdk_version: "current",
5092			system_modules: "none",
5093			privileged: true,
5094			stl: "none",
5095			apex_available: [ "myapex" ],
5096		}
5097
5098		cc_library_shared {
5099			name: "libjni",
5100			srcs: ["mylib.cpp"],
5101			shared_libs: ["libfoo"],
5102			stl: "none",
5103			system_shared_libs: [],
5104			apex_available: [ "myapex" ],
5105			sdk_version: "current",
5106		}
5107
5108		cc_library_shared {
5109			name: "libfoo",
5110			stl: "none",
5111			system_shared_libs: [],
5112			apex_available: [ "myapex" ],
5113			sdk_version: "current",
5114		}
5115	`)
5116
5117	module := ctx.ModuleForTests("myapex", "android_common_myapex_image")
5118	apexRule := module.Rule("apexRule")
5119	copyCmds := apexRule.Args["copy_commands"]
5120
5121	ensureContains(t, copyCmds, "image.apex/app/AppFoo/AppFoo.apk")
5122	ensureContains(t, copyCmds, "image.apex/priv-app/AppFooPriv/AppFooPriv.apk")
5123
5124	appZipRule := ctx.ModuleForTests("AppFoo", "android_common_apex10000").Description("zip jni libs")
5125	// JNI libraries are uncompressed
5126	if args := appZipRule.Args["jarArgs"]; !strings.Contains(args, "-L 0") {
5127		t.Errorf("jni libs are not uncompressed for AppFoo")
5128	}
5129	// JNI libraries including transitive deps are
5130	for _, jni := range []string{"libjni", "libfoo"} {
5131		jniOutput := ctx.ModuleForTests(jni, "android_arm64_armv8-a_sdk_shared_apex10000").Module().(*cc.Module).OutputFile().RelativeToTop()
5132		// ... embedded inside APK (jnilibs.zip)
5133		ensureListContains(t, appZipRule.Implicits.Strings(), jniOutput.String())
5134		// ... and not directly inside the APEX
5135		ensureNotContains(t, copyCmds, "image.apex/lib64/"+jni+".so")
5136	}
5137}
5138
5139func TestApexWithAppImports(t *testing.T) {
5140	ctx := testApex(t, `
5141		apex {
5142			name: "myapex",
5143			key: "myapex.key",
5144			apps: [
5145				"AppFooPrebuilt",
5146				"AppFooPrivPrebuilt",
5147			],
5148			updatable: false,
5149		}
5150
5151		apex_key {
5152			name: "myapex.key",
5153			public_key: "testkey.avbpubkey",
5154			private_key: "testkey.pem",
5155		}
5156
5157		android_app_import {
5158			name: "AppFooPrebuilt",
5159			apk: "PrebuiltAppFoo.apk",
5160			presigned: true,
5161			dex_preopt: {
5162				enabled: false,
5163			},
5164			apex_available: ["myapex"],
5165		}
5166
5167		android_app_import {
5168			name: "AppFooPrivPrebuilt",
5169			apk: "PrebuiltAppFooPriv.apk",
5170			privileged: true,
5171			presigned: true,
5172			dex_preopt: {
5173				enabled: false,
5174			},
5175			filename: "AwesomePrebuiltAppFooPriv.apk",
5176			apex_available: ["myapex"],
5177		}
5178	`)
5179
5180	module := ctx.ModuleForTests("myapex", "android_common_myapex_image")
5181	apexRule := module.Rule("apexRule")
5182	copyCmds := apexRule.Args["copy_commands"]
5183
5184	ensureContains(t, copyCmds, "image.apex/app/AppFooPrebuilt/AppFooPrebuilt.apk")
5185	ensureContains(t, copyCmds, "image.apex/priv-app/AppFooPrivPrebuilt/AwesomePrebuiltAppFooPriv.apk")
5186}
5187
5188func TestApexWithAppImportsPrefer(t *testing.T) {
5189	ctx := testApex(t, `
5190		apex {
5191			name: "myapex",
5192			key: "myapex.key",
5193			apps: [
5194				"AppFoo",
5195			],
5196			updatable: false,
5197		}
5198
5199		apex_key {
5200			name: "myapex.key",
5201			public_key: "testkey.avbpubkey",
5202			private_key: "testkey.pem",
5203		}
5204
5205		android_app {
5206			name: "AppFoo",
5207			srcs: ["foo/bar/MyClass.java"],
5208			sdk_version: "none",
5209			system_modules: "none",
5210			apex_available: [ "myapex" ],
5211		}
5212
5213		android_app_import {
5214			name: "AppFoo",
5215			apk: "AppFooPrebuilt.apk",
5216			filename: "AppFooPrebuilt.apk",
5217			presigned: true,
5218			prefer: true,
5219			apex_available: ["myapex"],
5220		}
5221	`, withFiles(map[string][]byte{
5222		"AppFooPrebuilt.apk": nil,
5223	}))
5224
5225	ensureExactContents(t, ctx, "myapex", "android_common_myapex_image", []string{
5226		"app/AppFoo/AppFooPrebuilt.apk",
5227	})
5228}
5229
5230func TestApexWithTestHelperApp(t *testing.T) {
5231	ctx := testApex(t, `
5232		apex {
5233			name: "myapex",
5234			key: "myapex.key",
5235			apps: [
5236				"TesterHelpAppFoo",
5237			],
5238			updatable: false,
5239		}
5240
5241		apex_key {
5242			name: "myapex.key",
5243			public_key: "testkey.avbpubkey",
5244			private_key: "testkey.pem",
5245		}
5246
5247		android_test_helper_app {
5248			name: "TesterHelpAppFoo",
5249			srcs: ["foo/bar/MyClass.java"],
5250			apex_available: [ "myapex" ],
5251		}
5252
5253	`)
5254
5255	module := ctx.ModuleForTests("myapex", "android_common_myapex_image")
5256	apexRule := module.Rule("apexRule")
5257	copyCmds := apexRule.Args["copy_commands"]
5258
5259	ensureContains(t, copyCmds, "image.apex/app/TesterHelpAppFoo/TesterHelpAppFoo.apk")
5260}
5261
5262func TestApexPropertiesShouldBeDefaultable(t *testing.T) {
5263	// libfoo's apex_available comes from cc_defaults
5264	testApexError(t, `requires "libfoo" that doesn't list the APEX under 'apex_available'.`, `
5265	apex {
5266		name: "myapex",
5267		key: "myapex.key",
5268		native_shared_libs: ["libfoo"],
5269		updatable: false,
5270	}
5271
5272	apex_key {
5273		name: "myapex.key",
5274		public_key: "testkey.avbpubkey",
5275		private_key: "testkey.pem",
5276	}
5277
5278	apex {
5279		name: "otherapex",
5280		key: "myapex.key",
5281		native_shared_libs: ["libfoo"],
5282		updatable: false,
5283	}
5284
5285	cc_defaults {
5286		name: "libfoo-defaults",
5287		apex_available: ["otherapex"],
5288	}
5289
5290	cc_library {
5291		name: "libfoo",
5292		defaults: ["libfoo-defaults"],
5293		stl: "none",
5294		system_shared_libs: [],
5295	}`)
5296}
5297
5298func TestApexAvailable_DirectDep(t *testing.T) {
5299	// libfoo is not available to myapex, but only to otherapex
5300	testApexError(t, "requires \"libfoo\" that doesn't list the APEX under 'apex_available'.", `
5301	apex {
5302		name: "myapex",
5303		key: "myapex.key",
5304		native_shared_libs: ["libfoo"],
5305		updatable: false,
5306	}
5307
5308	apex_key {
5309		name: "myapex.key",
5310		public_key: "testkey.avbpubkey",
5311		private_key: "testkey.pem",
5312	}
5313
5314	apex {
5315		name: "otherapex",
5316		key: "otherapex.key",
5317		native_shared_libs: ["libfoo"],
5318		updatable: false,
5319	}
5320
5321	apex_key {
5322		name: "otherapex.key",
5323		public_key: "testkey.avbpubkey",
5324		private_key: "testkey.pem",
5325	}
5326
5327	cc_library {
5328		name: "libfoo",
5329		stl: "none",
5330		system_shared_libs: [],
5331		apex_available: ["otherapex"],
5332	}`)
5333}
5334
5335func TestApexAvailable_IndirectDep(t *testing.T) {
5336	// libbbaz is an indirect dep
5337	testApexError(t, `requires "libbaz" that doesn't list the APEX under 'apex_available'.\n\nDependency path:
5338.*via tag apex\.dependencyTag.*name:sharedLib.*
5339.*-> libfoo.*link:shared.*
5340.*via tag cc\.libraryDependencyTag.*Kind:sharedLibraryDependency.*
5341.*-> libbar.*link:shared.*
5342.*via tag cc\.libraryDependencyTag.*Kind:sharedLibraryDependency.*
5343.*-> libbaz.*link:shared.*`, `
5344	apex {
5345		name: "myapex",
5346		key: "myapex.key",
5347		native_shared_libs: ["libfoo"],
5348		updatable: false,
5349	}
5350
5351	apex_key {
5352		name: "myapex.key",
5353		public_key: "testkey.avbpubkey",
5354		private_key: "testkey.pem",
5355	}
5356
5357	cc_library {
5358		name: "libfoo",
5359		stl: "none",
5360		shared_libs: ["libbar"],
5361		system_shared_libs: [],
5362		apex_available: ["myapex"],
5363	}
5364
5365	cc_library {
5366		name: "libbar",
5367		stl: "none",
5368		shared_libs: ["libbaz"],
5369		system_shared_libs: [],
5370		apex_available: ["myapex"],
5371	}
5372
5373	cc_library {
5374		name: "libbaz",
5375		stl: "none",
5376		system_shared_libs: [],
5377	}`)
5378}
5379
5380func TestApexAvailable_InvalidApexName(t *testing.T) {
5381	testApexError(t, "\"otherapex\" is not a valid module name", `
5382	apex {
5383		name: "myapex",
5384		key: "myapex.key",
5385		native_shared_libs: ["libfoo"],
5386		updatable: false,
5387	}
5388
5389	apex_key {
5390		name: "myapex.key",
5391		public_key: "testkey.avbpubkey",
5392		private_key: "testkey.pem",
5393	}
5394
5395	cc_library {
5396		name: "libfoo",
5397		stl: "none",
5398		system_shared_libs: [],
5399		apex_available: ["otherapex"],
5400	}`)
5401
5402	testApex(t, `
5403	apex {
5404		name: "myapex",
5405		key: "myapex.key",
5406		native_shared_libs: ["libfoo", "libbar"],
5407		updatable: false,
5408	}
5409
5410	apex_key {
5411		name: "myapex.key",
5412		public_key: "testkey.avbpubkey",
5413		private_key: "testkey.pem",
5414	}
5415
5416	cc_library {
5417		name: "libfoo",
5418		stl: "none",
5419		system_shared_libs: [],
5420		runtime_libs: ["libbaz"],
5421		apex_available: ["myapex"],
5422	}
5423
5424	cc_library {
5425		name: "libbar",
5426		stl: "none",
5427		system_shared_libs: [],
5428		apex_available: ["//apex_available:anyapex"],
5429	}
5430
5431	cc_library {
5432		name: "libbaz",
5433		stl: "none",
5434		system_shared_libs: [],
5435		stubs: {
5436			versions: ["10", "20", "30"],
5437		},
5438	}`)
5439}
5440
5441func TestApexAvailable_CheckForPlatform(t *testing.T) {
5442	ctx := testApex(t, `
5443	apex {
5444		name: "myapex",
5445		key: "myapex.key",
5446		native_shared_libs: ["libbar", "libbaz"],
5447		updatable: false,
5448	}
5449
5450	apex_key {
5451		name: "myapex.key",
5452		public_key: "testkey.avbpubkey",
5453		private_key: "testkey.pem",
5454	}
5455
5456	cc_library {
5457		name: "libfoo",
5458		stl: "none",
5459		system_shared_libs: [],
5460		shared_libs: ["libbar"],
5461		apex_available: ["//apex_available:platform"],
5462	}
5463
5464	cc_library {
5465		name: "libfoo2",
5466		stl: "none",
5467		system_shared_libs: [],
5468		shared_libs: ["libbaz"],
5469		apex_available: ["//apex_available:platform"],
5470	}
5471
5472	cc_library {
5473		name: "libbar",
5474		stl: "none",
5475		system_shared_libs: [],
5476		apex_available: ["myapex"],
5477	}
5478
5479	cc_library {
5480		name: "libbaz",
5481		stl: "none",
5482		system_shared_libs: [],
5483		apex_available: ["myapex"],
5484		stubs: {
5485			versions: ["1"],
5486		},
5487	}`)
5488
5489	// libfoo shouldn't be available to platform even though it has "//apex_available:platform",
5490	// because it depends on libbar which isn't available to platform
5491	libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module().(*cc.Module)
5492	if libfoo.NotAvailableForPlatform() != true {
5493		t.Errorf("%q shouldn't be available to platform", libfoo.String())
5494	}
5495
5496	// libfoo2 however can be available to platform because it depends on libbaz which provides
5497	// stubs
5498	libfoo2 := ctx.ModuleForTests("libfoo2", "android_arm64_armv8-a_shared").Module().(*cc.Module)
5499	if libfoo2.NotAvailableForPlatform() == true {
5500		t.Errorf("%q should be available to platform", libfoo2.String())
5501	}
5502}
5503
5504func TestApexAvailable_CreatedForApex(t *testing.T) {
5505	ctx := testApex(t, `
5506	apex {
5507		name: "myapex",
5508		key: "myapex.key",
5509		native_shared_libs: ["libfoo"],
5510		updatable: false,
5511	}
5512
5513	apex_key {
5514		name: "myapex.key",
5515		public_key: "testkey.avbpubkey",
5516		private_key: "testkey.pem",
5517	}
5518
5519	cc_library {
5520		name: "libfoo",
5521		stl: "none",
5522		system_shared_libs: [],
5523		apex_available: ["myapex"],
5524		static: {
5525			apex_available: ["//apex_available:platform"],
5526		},
5527	}`)
5528
5529	libfooShared := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module().(*cc.Module)
5530	if libfooShared.NotAvailableForPlatform() != true {
5531		t.Errorf("%q shouldn't be available to platform", libfooShared.String())
5532	}
5533	libfooStatic := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_static").Module().(*cc.Module)
5534	if libfooStatic.NotAvailableForPlatform() != false {
5535		t.Errorf("%q should be available to platform", libfooStatic.String())
5536	}
5537}
5538
5539func TestOverrideApex(t *testing.T) {
5540	ctx := testApex(t, `
5541		apex {
5542			name: "myapex",
5543			key: "myapex.key",
5544			apps: ["app"],
5545			overrides: ["oldapex"],
5546			updatable: false,
5547		}
5548
5549		override_apex {
5550			name: "override_myapex",
5551			base: "myapex",
5552			apps: ["override_app"],
5553			overrides: ["unknownapex"],
5554			logging_parent: "com.foo.bar",
5555			package_name: "test.overridden.package",
5556			key: "mynewapex.key",
5557			certificate: ":myapex.certificate",
5558		}
5559
5560		apex_key {
5561			name: "myapex.key",
5562			public_key: "testkey.avbpubkey",
5563			private_key: "testkey.pem",
5564		}
5565
5566		apex_key {
5567			name: "mynewapex.key",
5568			public_key: "testkey2.avbpubkey",
5569			private_key: "testkey2.pem",
5570		}
5571
5572		android_app_certificate {
5573			name: "myapex.certificate",
5574			certificate: "testkey",
5575		}
5576
5577		android_app {
5578			name: "app",
5579			srcs: ["foo/bar/MyClass.java"],
5580			package_name: "foo",
5581			sdk_version: "none",
5582			system_modules: "none",
5583			apex_available: [ "myapex" ],
5584		}
5585
5586		override_android_app {
5587			name: "override_app",
5588			base: "app",
5589			package_name: "bar",
5590		}
5591	`, withManifestPackageNameOverrides([]string{"myapex:com.android.myapex"}))
5592
5593	originalVariant := ctx.ModuleForTests("myapex", "android_common_myapex_image").Module().(android.OverridableModule)
5594	overriddenVariant := ctx.ModuleForTests("myapex", "android_common_override_myapex_myapex_image").Module().(android.OverridableModule)
5595	if originalVariant.GetOverriddenBy() != "" {
5596		t.Errorf("GetOverriddenBy should be empty, but was %q", originalVariant.GetOverriddenBy())
5597	}
5598	if overriddenVariant.GetOverriddenBy() != "override_myapex" {
5599		t.Errorf("GetOverriddenBy should be \"override_myapex\", but was %q", overriddenVariant.GetOverriddenBy())
5600	}
5601
5602	module := ctx.ModuleForTests("myapex", "android_common_override_myapex_myapex_image")
5603	apexRule := module.Rule("apexRule")
5604	copyCmds := apexRule.Args["copy_commands"]
5605
5606	ensureNotContains(t, copyCmds, "image.apex/app/app/app.apk")
5607	ensureContains(t, copyCmds, "image.apex/app/override_app/override_app.apk")
5608
5609	apexBundle := module.Module().(*apexBundle)
5610	name := apexBundle.Name()
5611	if name != "override_myapex" {
5612		t.Errorf("name should be \"override_myapex\", but was %q", name)
5613	}
5614
5615	if apexBundle.overridableProperties.Logging_parent != "com.foo.bar" {
5616		t.Errorf("override_myapex should have logging parent (com.foo.bar), but was %q.", apexBundle.overridableProperties.Logging_parent)
5617	}
5618
5619	optFlags := apexRule.Args["opt_flags"]
5620	ensureContains(t, optFlags, "--override_apk_package_name test.overridden.package")
5621	ensureContains(t, optFlags, "--pubkey testkey2.avbpubkey")
5622
5623	signApkRule := module.Rule("signapk")
5624	ensureEquals(t, signApkRule.Args["certificates"], "testkey.x509.pem testkey.pk8")
5625
5626	data := android.AndroidMkDataForTest(t, ctx, apexBundle)
5627	var builder strings.Builder
5628	data.Custom(&builder, name, "TARGET_", "", data)
5629	androidMk := builder.String()
5630	ensureContains(t, androidMk, "LOCAL_MODULE := override_app.override_myapex")
5631	ensureContains(t, androidMk, "LOCAL_MODULE := apex_manifest.pb.override_myapex")
5632	ensureContains(t, androidMk, "LOCAL_MODULE_STEM := override_myapex.apex")
5633	ensureContains(t, androidMk, "LOCAL_OVERRIDES_MODULES := unknownapex myapex")
5634	ensureNotContains(t, androidMk, "LOCAL_MODULE := app.myapex")
5635	ensureNotContains(t, androidMk, "LOCAL_MODULE := override_app.myapex")
5636	ensureNotContains(t, androidMk, "LOCAL_MODULE := apex_manifest.pb.myapex")
5637	ensureNotContains(t, androidMk, "LOCAL_MODULE_STEM := myapex.apex")
5638}
5639
5640func TestLegacyAndroid10Support(t *testing.T) {
5641	ctx := testApex(t, `
5642		apex {
5643			name: "myapex",
5644			key: "myapex.key",
5645			native_shared_libs: ["mylib"],
5646			min_sdk_version: "29",
5647		}
5648
5649		apex_key {
5650			name: "myapex.key",
5651			public_key: "testkey.avbpubkey",
5652			private_key: "testkey.pem",
5653		}
5654
5655		cc_library {
5656			name: "mylib",
5657			srcs: ["mylib.cpp"],
5658			stl: "libc++",
5659			system_shared_libs: [],
5660			apex_available: [ "myapex" ],
5661			min_sdk_version: "29",
5662		}
5663	`, withUnbundledBuild)
5664
5665	module := ctx.ModuleForTests("myapex", "android_common_myapex_image")
5666	args := module.Rule("apexRule").Args
5667	ensureContains(t, args["opt_flags"], "--manifest_json "+module.Output("apex_manifest.json").Output.String())
5668	ensureNotContains(t, args["opt_flags"], "--no_hashtree")
5669
5670	// The copies of the libraries in the apex should have one more dependency than
5671	// the ones outside the apex, namely the unwinder. Ideally we should check
5672	// the dependency names directly here but for some reason the names are blank in
5673	// this test.
5674	for _, lib := range []string{"libc++", "mylib"} {
5675		apexImplicits := ctx.ModuleForTests(lib, "android_arm64_armv8-a_shared_apex29").Rule("ld").Implicits
5676		nonApexImplicits := ctx.ModuleForTests(lib, "android_arm64_armv8-a_shared").Rule("ld").Implicits
5677		if len(apexImplicits) != len(nonApexImplicits)+1 {
5678			t.Errorf("%q missing unwinder dep", lib)
5679		}
5680	}
5681}
5682
5683var filesForSdkLibrary = android.MockFS{
5684	"api/current.txt":        nil,
5685	"api/removed.txt":        nil,
5686	"api/system-current.txt": nil,
5687	"api/system-removed.txt": nil,
5688	"api/test-current.txt":   nil,
5689	"api/test-removed.txt":   nil,
5690
5691	"100/public/api/foo.txt":         nil,
5692	"100/public/api/foo-removed.txt": nil,
5693	"100/system/api/foo.txt":         nil,
5694	"100/system/api/foo-removed.txt": nil,
5695
5696	// For java_sdk_library_import
5697	"a.jar": nil,
5698}
5699
5700func TestJavaSDKLibrary(t *testing.T) {
5701	ctx := testApex(t, `
5702		apex {
5703			name: "myapex",
5704			key: "myapex.key",
5705			java_libs: ["foo"],
5706			updatable: false,
5707		}
5708
5709		apex_key {
5710			name: "myapex.key",
5711			public_key: "testkey.avbpubkey",
5712			private_key: "testkey.pem",
5713		}
5714
5715		java_sdk_library {
5716			name: "foo",
5717			srcs: ["a.java"],
5718			api_packages: ["foo"],
5719			apex_available: [ "myapex" ],
5720		}
5721
5722		prebuilt_apis {
5723			name: "sdk",
5724			api_dirs: ["100"],
5725		}
5726	`, withFiles(filesForSdkLibrary))
5727
5728	// java_sdk_library installs both impl jar and permission XML
5729	ensureExactContents(t, ctx, "myapex", "android_common_myapex_image", []string{
5730		"javalib/foo.jar",
5731		"etc/permissions/foo.xml",
5732	})
5733	// Permission XML should point to the activated path of impl jar of java_sdk_library
5734	sdkLibrary := ctx.ModuleForTests("foo.xml", "android_common_myapex").Rule("java_sdk_xml")
5735	ensureContains(t, sdkLibrary.RuleParams.Command, `<library name=\"foo\" file=\"/apex/myapex/javalib/foo.jar\"`)
5736}
5737
5738func TestJavaSDKLibrary_WithinApex(t *testing.T) {
5739	ctx := testApex(t, `
5740		apex {
5741			name: "myapex",
5742			key: "myapex.key",
5743			java_libs: ["foo", "bar"],
5744			updatable: false,
5745		}
5746
5747		apex_key {
5748			name: "myapex.key",
5749			public_key: "testkey.avbpubkey",
5750			private_key: "testkey.pem",
5751		}
5752
5753		java_sdk_library {
5754			name: "foo",
5755			srcs: ["a.java"],
5756			api_packages: ["foo"],
5757			apex_available: ["myapex"],
5758			sdk_version: "none",
5759			system_modules: "none",
5760		}
5761
5762		java_library {
5763			name: "bar",
5764			srcs: ["a.java"],
5765			libs: ["foo"],
5766			apex_available: ["myapex"],
5767			sdk_version: "none",
5768			system_modules: "none",
5769		}
5770
5771		prebuilt_apis {
5772			name: "sdk",
5773			api_dirs: ["100"],
5774		}
5775	`, withFiles(filesForSdkLibrary))
5776
5777	// java_sdk_library installs both impl jar and permission XML
5778	ensureExactContents(t, ctx, "myapex", "android_common_myapex_image", []string{
5779		"javalib/bar.jar",
5780		"javalib/foo.jar",
5781		"etc/permissions/foo.xml",
5782	})
5783
5784	// The bar library should depend on the implementation jar.
5785	barLibrary := ctx.ModuleForTests("bar", "android_common_myapex").Rule("javac")
5786	if expected, actual := `^-classpath [^:]*/turbine-combined/foo\.jar$`, barLibrary.Args["classpath"]; !regexp.MustCompile(expected).MatchString(actual) {
5787		t.Errorf("expected %q, found %#q", expected, actual)
5788	}
5789}
5790
5791func TestJavaSDKLibrary_CrossBoundary(t *testing.T) {
5792	ctx := testApex(t, `
5793		apex {
5794			name: "myapex",
5795			key: "myapex.key",
5796			java_libs: ["foo"],
5797			updatable: false,
5798		}
5799
5800		apex_key {
5801			name: "myapex.key",
5802			public_key: "testkey.avbpubkey",
5803			private_key: "testkey.pem",
5804		}
5805
5806		java_sdk_library {
5807			name: "foo",
5808			srcs: ["a.java"],
5809			api_packages: ["foo"],
5810			apex_available: ["myapex"],
5811			sdk_version: "none",
5812			system_modules: "none",
5813		}
5814
5815		java_library {
5816			name: "bar",
5817			srcs: ["a.java"],
5818			libs: ["foo"],
5819			sdk_version: "none",
5820			system_modules: "none",
5821		}
5822
5823		prebuilt_apis {
5824			name: "sdk",
5825			api_dirs: ["100"],
5826		}
5827	`, withFiles(filesForSdkLibrary))
5828
5829	// java_sdk_library installs both impl jar and permission XML
5830	ensureExactContents(t, ctx, "myapex", "android_common_myapex_image", []string{
5831		"javalib/foo.jar",
5832		"etc/permissions/foo.xml",
5833	})
5834
5835	// The bar library should depend on the stubs jar.
5836	barLibrary := ctx.ModuleForTests("bar", "android_common").Rule("javac")
5837	if expected, actual := `^-classpath [^:]*/turbine-combined/foo\.stubs\.jar$`, barLibrary.Args["classpath"]; !regexp.MustCompile(expected).MatchString(actual) {
5838		t.Errorf("expected %q, found %#q", expected, actual)
5839	}
5840}
5841
5842func TestJavaSDKLibrary_ImportPreferred(t *testing.T) {
5843	ctx := testApex(t, `
5844		prebuilt_apis {
5845			name: "sdk",
5846			api_dirs: ["100"],
5847		}`,
5848		withFiles(map[string][]byte{
5849			"apex/a.java":             nil,
5850			"apex/apex_manifest.json": nil,
5851			"apex/Android.bp": []byte(`
5852		package {
5853			default_visibility: ["//visibility:private"],
5854		}
5855
5856		apex {
5857			name: "myapex",
5858			key: "myapex.key",
5859			java_libs: ["foo", "bar"],
5860			updatable: false,
5861		}
5862
5863		apex_key {
5864			name: "myapex.key",
5865			public_key: "testkey.avbpubkey",
5866			private_key: "testkey.pem",
5867		}
5868
5869		java_library {
5870			name: "bar",
5871			srcs: ["a.java"],
5872			libs: ["foo"],
5873			apex_available: ["myapex"],
5874			sdk_version: "none",
5875			system_modules: "none",
5876		}
5877`),
5878			"source/a.java":          nil,
5879			"source/api/current.txt": nil,
5880			"source/api/removed.txt": nil,
5881			"source/Android.bp": []byte(`
5882		package {
5883			default_visibility: ["//visibility:private"],
5884		}
5885
5886		java_sdk_library {
5887			name: "foo",
5888			visibility: ["//apex"],
5889			srcs: ["a.java"],
5890			api_packages: ["foo"],
5891			apex_available: ["myapex"],
5892			sdk_version: "none",
5893			system_modules: "none",
5894			public: {
5895				enabled: true,
5896			},
5897		}
5898`),
5899			"prebuilt/a.jar": nil,
5900			"prebuilt/Android.bp": []byte(`
5901		package {
5902			default_visibility: ["//visibility:private"],
5903		}
5904
5905		java_sdk_library_import {
5906			name: "foo",
5907			visibility: ["//apex", "//source"],
5908			apex_available: ["myapex"],
5909			prefer: true,
5910			public: {
5911				jars: ["a.jar"],
5912			},
5913		}
5914`),
5915		}), withFiles(filesForSdkLibrary),
5916	)
5917
5918	// java_sdk_library installs both impl jar and permission XML
5919	ensureExactContents(t, ctx, "myapex", "android_common_myapex_image", []string{
5920		"javalib/bar.jar",
5921		"javalib/foo.jar",
5922		"etc/permissions/foo.xml",
5923	})
5924
5925	// The bar library should depend on the implementation jar.
5926	barLibrary := ctx.ModuleForTests("bar", "android_common_myapex").Rule("javac")
5927	if expected, actual := `^-classpath [^:]*/turbine-combined/foo\.impl\.jar$`, barLibrary.Args["classpath"]; !regexp.MustCompile(expected).MatchString(actual) {
5928		t.Errorf("expected %q, found %#q", expected, actual)
5929	}
5930}
5931
5932func TestJavaSDKLibrary_ImportOnly(t *testing.T) {
5933	testApexError(t, `java_libs: "foo" is not configured to be compiled into dex`, `
5934		apex {
5935			name: "myapex",
5936			key: "myapex.key",
5937			java_libs: ["foo"],
5938			updatable: false,
5939		}
5940
5941		apex_key {
5942			name: "myapex.key",
5943			public_key: "testkey.avbpubkey",
5944			private_key: "testkey.pem",
5945		}
5946
5947		java_sdk_library_import {
5948			name: "foo",
5949			apex_available: ["myapex"],
5950			prefer: true,
5951			public: {
5952				jars: ["a.jar"],
5953			},
5954		}
5955
5956	`, withFiles(filesForSdkLibrary))
5957}
5958
5959func TestCompatConfig(t *testing.T) {
5960	result := android.GroupFixturePreparers(
5961		prepareForApexTest,
5962		java.PrepareForTestWithPlatformCompatConfig,
5963	).RunTestWithBp(t, `
5964		apex {
5965			name: "myapex",
5966			key: "myapex.key",
5967			compat_configs: ["myjar-platform-compat-config"],
5968			java_libs: ["myjar"],
5969			updatable: false,
5970		}
5971
5972		apex_key {
5973			name: "myapex.key",
5974			public_key: "testkey.avbpubkey",
5975			private_key: "testkey.pem",
5976		}
5977
5978		platform_compat_config {
5979		    name: "myjar-platform-compat-config",
5980		    src: ":myjar",
5981		}
5982
5983		java_library {
5984			name: "myjar",
5985			srcs: ["foo/bar/MyClass.java"],
5986			sdk_version: "none",
5987			system_modules: "none",
5988			apex_available: [ "myapex" ],
5989		}
5990
5991		// Make sure that a preferred prebuilt does not affect the apex contents.
5992		prebuilt_platform_compat_config {
5993			name: "myjar-platform-compat-config",
5994			metadata: "compat-config/metadata.xml",
5995			prefer: true,
5996		}
5997	`)
5998	ctx := result.TestContext
5999	ensureExactContents(t, ctx, "myapex", "android_common_myapex_image", []string{
6000		"etc/compatconfig/myjar-platform-compat-config.xml",
6001		"javalib/myjar.jar",
6002	})
6003}
6004
6005func TestRejectNonInstallableJavaLibrary(t *testing.T) {
6006	testApexError(t, `"myjar" is not configured to be compiled into dex`, `
6007		apex {
6008			name: "myapex",
6009			key: "myapex.key",
6010			java_libs: ["myjar"],
6011			updatable: false,
6012		}
6013
6014		apex_key {
6015			name: "myapex.key",
6016			public_key: "testkey.avbpubkey",
6017			private_key: "testkey.pem",
6018		}
6019
6020		java_library {
6021			name: "myjar",
6022			srcs: ["foo/bar/MyClass.java"],
6023			sdk_version: "none",
6024			system_modules: "none",
6025			compile_dex: false,
6026			apex_available: ["myapex"],
6027		}
6028	`)
6029}
6030
6031func TestCarryRequiredModuleNames(t *testing.T) {
6032	ctx := testApex(t, `
6033		apex {
6034			name: "myapex",
6035			key: "myapex.key",
6036			native_shared_libs: ["mylib"],
6037			updatable: false,
6038		}
6039
6040		apex_key {
6041			name: "myapex.key",
6042			public_key: "testkey.avbpubkey",
6043			private_key: "testkey.pem",
6044		}
6045
6046		cc_library {
6047			name: "mylib",
6048			srcs: ["mylib.cpp"],
6049			system_shared_libs: [],
6050			stl: "none",
6051			required: ["a", "b"],
6052			host_required: ["c", "d"],
6053			target_required: ["e", "f"],
6054			apex_available: [ "myapex" ],
6055		}
6056	`)
6057
6058	apexBundle := ctx.ModuleForTests("myapex", "android_common_myapex_image").Module().(*apexBundle)
6059	data := android.AndroidMkDataForTest(t, ctx, apexBundle)
6060	name := apexBundle.BaseModuleName()
6061	prefix := "TARGET_"
6062	var builder strings.Builder
6063	data.Custom(&builder, name, prefix, "", data)
6064	androidMk := builder.String()
6065	ensureContains(t, androidMk, "LOCAL_REQUIRED_MODULES += a b\n")
6066	ensureContains(t, androidMk, "LOCAL_HOST_REQUIRED_MODULES += c d\n")
6067	ensureContains(t, androidMk, "LOCAL_TARGET_REQUIRED_MODULES += e f\n")
6068}
6069
6070func TestSymlinksFromApexToSystem(t *testing.T) {
6071	bp := `
6072		apex {
6073			name: "myapex",
6074			key: "myapex.key",
6075			native_shared_libs: ["mylib"],
6076			java_libs: ["myjar"],
6077			updatable: false,
6078		}
6079
6080		apex {
6081			name: "myapex.updatable",
6082			key: "myapex.key",
6083			native_shared_libs: ["mylib"],
6084			java_libs: ["myjar"],
6085			updatable: true,
6086			min_sdk_version: "current",
6087		}
6088
6089		apex_key {
6090			name: "myapex.key",
6091			public_key: "testkey.avbpubkey",
6092			private_key: "testkey.pem",
6093		}
6094
6095		cc_library {
6096			name: "mylib",
6097			srcs: ["mylib.cpp"],
6098			shared_libs: ["myotherlib"],
6099			system_shared_libs: [],
6100			stl: "none",
6101			apex_available: [
6102				"myapex",
6103				"myapex.updatable",
6104				"//apex_available:platform",
6105			],
6106			min_sdk_version: "current",
6107		}
6108
6109		cc_library {
6110			name: "myotherlib",
6111			srcs: ["mylib.cpp"],
6112			system_shared_libs: [],
6113			stl: "none",
6114			apex_available: [
6115				"myapex",
6116				"myapex.updatable",
6117				"//apex_available:platform",
6118			],
6119			min_sdk_version: "current",
6120		}
6121
6122		java_library {
6123			name: "myjar",
6124			srcs: ["foo/bar/MyClass.java"],
6125			sdk_version: "none",
6126			system_modules: "none",
6127			libs: ["myotherjar"],
6128			apex_available: [
6129				"myapex",
6130				"myapex.updatable",
6131				"//apex_available:platform",
6132			],
6133			min_sdk_version: "current",
6134		}
6135
6136		java_library {
6137			name: "myotherjar",
6138			srcs: ["foo/bar/MyClass.java"],
6139			sdk_version: "none",
6140			system_modules: "none",
6141			apex_available: [
6142				"myapex",
6143				"myapex.updatable",
6144				"//apex_available:platform",
6145			],
6146			min_sdk_version: "current",
6147		}
6148	`
6149
6150	ensureRealfileExists := func(t *testing.T, files []fileInApex, file string) {
6151		for _, f := range files {
6152			if f.path == file {
6153				if f.isLink {
6154					t.Errorf("%q is not a real file", file)
6155				}
6156				return
6157			}
6158		}
6159		t.Errorf("%q is not found", file)
6160	}
6161
6162	ensureSymlinkExists := func(t *testing.T, files []fileInApex, file string) {
6163		for _, f := range files {
6164			if f.path == file {
6165				if !f.isLink {
6166					t.Errorf("%q is not a symlink", file)
6167				}
6168				return
6169			}
6170		}
6171		t.Errorf("%q is not found", file)
6172	}
6173
6174	// For unbundled build, symlink shouldn't exist regardless of whether an APEX
6175	// is updatable or not
6176	ctx := testApex(t, bp, withUnbundledBuild)
6177	files := getFiles(t, ctx, "myapex", "android_common_myapex_image")
6178	ensureRealfileExists(t, files, "javalib/myjar.jar")
6179	ensureRealfileExists(t, files, "lib64/mylib.so")
6180	ensureRealfileExists(t, files, "lib64/myotherlib.so")
6181
6182	files = getFiles(t, ctx, "myapex.updatable", "android_common_myapex.updatable_image")
6183	ensureRealfileExists(t, files, "javalib/myjar.jar")
6184	ensureRealfileExists(t, files, "lib64/mylib.so")
6185	ensureRealfileExists(t, files, "lib64/myotherlib.so")
6186
6187	// For bundled build, symlink to the system for the non-updatable APEXes only
6188	ctx = testApex(t, bp)
6189	files = getFiles(t, ctx, "myapex", "android_common_myapex_image")
6190	ensureRealfileExists(t, files, "javalib/myjar.jar")
6191	ensureRealfileExists(t, files, "lib64/mylib.so")
6192	ensureSymlinkExists(t, files, "lib64/myotherlib.so") // this is symlink
6193
6194	files = getFiles(t, ctx, "myapex.updatable", "android_common_myapex.updatable_image")
6195	ensureRealfileExists(t, files, "javalib/myjar.jar")
6196	ensureRealfileExists(t, files, "lib64/mylib.so")
6197	ensureRealfileExists(t, files, "lib64/myotherlib.so") // this is a real file
6198}
6199
6200func TestSymlinksFromApexToSystemRequiredModuleNames(t *testing.T) {
6201	ctx := testApex(t, `
6202		apex {
6203			name: "myapex",
6204			key: "myapex.key",
6205			native_shared_libs: ["mylib"],
6206			updatable: false,
6207		}
6208
6209		apex_key {
6210			name: "myapex.key",
6211			public_key: "testkey.avbpubkey",
6212			private_key: "testkey.pem",
6213		}
6214
6215		cc_library_shared {
6216			name: "mylib",
6217			srcs: ["mylib.cpp"],
6218			shared_libs: ["myotherlib"],
6219			system_shared_libs: [],
6220			stl: "none",
6221			apex_available: [
6222				"myapex",
6223				"//apex_available:platform",
6224			],
6225		}
6226
6227		cc_prebuilt_library_shared {
6228			name: "myotherlib",
6229			srcs: ["prebuilt.so"],
6230			system_shared_libs: [],
6231			stl: "none",
6232			apex_available: [
6233				"myapex",
6234				"//apex_available:platform",
6235			],
6236		}
6237	`)
6238
6239	apexBundle := ctx.ModuleForTests("myapex", "android_common_myapex_image").Module().(*apexBundle)
6240	data := android.AndroidMkDataForTest(t, ctx, apexBundle)
6241	var builder strings.Builder
6242	data.Custom(&builder, apexBundle.BaseModuleName(), "TARGET_", "", data)
6243	androidMk := builder.String()
6244	// `myotherlib` is added to `myapex` as symlink
6245	ensureContains(t, androidMk, "LOCAL_MODULE := mylib.myapex\n")
6246	ensureNotContains(t, androidMk, "LOCAL_MODULE := prebuilt_myotherlib.myapex\n")
6247	ensureNotContains(t, androidMk, "LOCAL_MODULE := myotherlib.myapex\n")
6248	// `myapex` should have `myotherlib` in its required line, not `prebuilt_myotherlib`
6249	ensureContains(t, androidMk, "LOCAL_REQUIRED_MODULES += mylib.myapex:64 myotherlib:64 apex_manifest.pb.myapex apex_pubkey.myapex\n")
6250}
6251
6252func TestApexWithJniLibs(t *testing.T) {
6253	ctx := testApex(t, `
6254		apex {
6255			name: "myapex",
6256			key: "myapex.key",
6257			jni_libs: ["mylib"],
6258			updatable: false,
6259		}
6260
6261		apex_key {
6262			name: "myapex.key",
6263			public_key: "testkey.avbpubkey",
6264			private_key: "testkey.pem",
6265		}
6266
6267		cc_library {
6268			name: "mylib",
6269			srcs: ["mylib.cpp"],
6270			shared_libs: ["mylib2"],
6271			system_shared_libs: [],
6272			stl: "none",
6273			apex_available: [ "myapex" ],
6274		}
6275
6276		cc_library {
6277			name: "mylib2",
6278			srcs: ["mylib.cpp"],
6279			system_shared_libs: [],
6280			stl: "none",
6281			apex_available: [ "myapex" ],
6282		}
6283	`)
6284
6285	rule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("apexManifestRule")
6286	// Notice mylib2.so (transitive dep) is not added as a jni_lib
6287	ensureEquals(t, rule.Args["opt"], "-a jniLibs mylib.so")
6288	ensureExactContents(t, ctx, "myapex", "android_common_myapex_image", []string{
6289		"lib64/mylib.so",
6290		"lib64/mylib2.so",
6291	})
6292}
6293
6294func TestApexMutatorsDontRunIfDisabled(t *testing.T) {
6295	ctx := testApex(t, `
6296		apex {
6297			name: "myapex",
6298			key: "myapex.key",
6299			updatable: false,
6300		}
6301		apex_key {
6302			name: "myapex.key",
6303			public_key: "testkey.avbpubkey",
6304			private_key: "testkey.pem",
6305		}
6306	`,
6307		android.FixtureModifyConfig(func(config android.Config) {
6308			delete(config.Targets, android.Android)
6309			config.AndroidCommonTarget = android.Target{}
6310		}),
6311	)
6312
6313	if expected, got := []string{""}, ctx.ModuleVariantsForTests("myapex"); !reflect.DeepEqual(expected, got) {
6314		t.Errorf("Expected variants: %v, but got: %v", expected, got)
6315	}
6316}
6317
6318func TestAppBundle(t *testing.T) {
6319	ctx := testApex(t, `
6320		apex {
6321			name: "myapex",
6322			key: "myapex.key",
6323			apps: ["AppFoo"],
6324			updatable: false,
6325		}
6326
6327		apex_key {
6328			name: "myapex.key",
6329			public_key: "testkey.avbpubkey",
6330			private_key: "testkey.pem",
6331		}
6332
6333		android_app {
6334			name: "AppFoo",
6335			srcs: ["foo/bar/MyClass.java"],
6336			sdk_version: "none",
6337			system_modules: "none",
6338			apex_available: [ "myapex" ],
6339		}
6340		`, withManifestPackageNameOverrides([]string{"AppFoo:com.android.foo"}))
6341
6342	bundleConfigRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Output("bundle_config.json")
6343	content := bundleConfigRule.Args["content"]
6344
6345	ensureContains(t, content, `"compression":{"uncompressed_glob":["apex_payload.img","apex_manifest.*"]}`)
6346	ensureContains(t, content, `"apex_config":{"apex_embedded_apk_config":[{"package_name":"com.android.foo","path":"app/AppFoo/AppFoo.apk"}]}`)
6347}
6348
6349func TestAppSetBundle(t *testing.T) {
6350	ctx := testApex(t, `
6351		apex {
6352			name: "myapex",
6353			key: "myapex.key",
6354			apps: ["AppSet"],
6355			updatable: false,
6356		}
6357
6358		apex_key {
6359			name: "myapex.key",
6360			public_key: "testkey.avbpubkey",
6361			private_key: "testkey.pem",
6362		}
6363
6364		android_app_set {
6365			name: "AppSet",
6366			set: "AppSet.apks",
6367		}`)
6368	mod := ctx.ModuleForTests("myapex", "android_common_myapex_image")
6369	bundleConfigRule := mod.Output("bundle_config.json")
6370	content := bundleConfigRule.Args["content"]
6371	ensureContains(t, content, `"compression":{"uncompressed_glob":["apex_payload.img","apex_manifest.*"]}`)
6372	s := mod.Rule("apexRule").Args["copy_commands"]
6373	copyCmds := regexp.MustCompile(" *&& *").Split(s, -1)
6374	if len(copyCmds) != 3 {
6375		t.Fatalf("Expected 3 commands, got %d in:\n%s", len(copyCmds), s)
6376	}
6377	ensureMatches(t, copyCmds[0], "^rm -rf .*/app/AppSet$")
6378	ensureMatches(t, copyCmds[1], "^mkdir -p .*/app/AppSet$")
6379	ensureMatches(t, copyCmds[2], "^unzip .*-d .*/app/AppSet .*/AppSet.zip$")
6380}
6381
6382func TestAppSetBundlePrebuilt(t *testing.T) {
6383	bp := `
6384		apex_set {
6385			name: "myapex",
6386			filename: "foo_v2.apex",
6387			sanitized: {
6388				none: { set: "myapex.apks", },
6389				hwaddress: { set: "myapex.hwasan.apks", },
6390			},
6391		}
6392	`
6393	ctx := testApex(t, bp, prepareForTestWithSantitizeHwaddress)
6394
6395	// Check that the extractor produces the correct output file from the correct input file.
6396	extractorOutput := "out/soong/.intermediates/myapex.apex.extractor/android_common/extracted/myapex.hwasan.apks"
6397
6398	m := ctx.ModuleForTests("myapex.apex.extractor", "android_common")
6399	extractedApex := m.Output(extractorOutput)
6400
6401	android.AssertArrayString(t, "extractor input", []string{"myapex.hwasan.apks"}, extractedApex.Inputs.Strings())
6402
6403	// Ditto for the apex.
6404	m = ctx.ModuleForTests("myapex", "android_common_myapex")
6405	copiedApex := m.Output("out/soong/.intermediates/myapex/android_common_myapex/foo_v2.apex")
6406
6407	android.AssertStringEquals(t, "myapex input", extractorOutput, copiedApex.Input.String())
6408}
6409
6410func testNoUpdatableJarsInBootImage(t *testing.T, errmsg string, preparer android.FixturePreparer, fragments ...java.ApexVariantReference) {
6411	t.Helper()
6412
6413	bp := `
6414		java_library {
6415			name: "some-updatable-apex-lib",
6416			srcs: ["a.java"],
6417			sdk_version: "current",
6418			apex_available: [
6419				"some-updatable-apex",
6420			],
6421		}
6422
6423		java_library {
6424			name: "some-non-updatable-apex-lib",
6425			srcs: ["a.java"],
6426			apex_available: [
6427				"some-non-updatable-apex",
6428			],
6429			compile_dex: true,
6430		}
6431
6432		bootclasspath_fragment {
6433			name: "some-non-updatable-fragment",
6434			contents: ["some-non-updatable-apex-lib"],
6435			apex_available: [
6436				"some-non-updatable-apex",
6437			],
6438		}
6439
6440		java_library {
6441			name: "some-platform-lib",
6442			srcs: ["a.java"],
6443			sdk_version: "current",
6444			installable: true,
6445		}
6446
6447		java_library {
6448			name: "some-art-lib",
6449			srcs: ["a.java"],
6450			sdk_version: "current",
6451			apex_available: [
6452				"com.android.art.debug",
6453			],
6454			hostdex: true,
6455			compile_dex: true,
6456		}
6457
6458		apex {
6459			name: "some-updatable-apex",
6460			key: "some-updatable-apex.key",
6461			java_libs: ["some-updatable-apex-lib"],
6462			updatable: true,
6463			min_sdk_version: "current",
6464		}
6465
6466		apex {
6467			name: "some-non-updatable-apex",
6468			key: "some-non-updatable-apex.key",
6469			bootclasspath_fragments: ["some-non-updatable-fragment"],
6470			updatable: false,
6471		}
6472
6473		apex_key {
6474			name: "some-updatable-apex.key",
6475		}
6476
6477		apex_key {
6478			name: "some-non-updatable-apex.key",
6479		}
6480
6481		apex {
6482			name: "com.android.art.debug",
6483			key: "com.android.art.debug.key",
6484			bootclasspath_fragments: ["art-bootclasspath-fragment"],
6485			updatable: true,
6486			min_sdk_version: "current",
6487		}
6488
6489		bootclasspath_fragment {
6490			name: "art-bootclasspath-fragment",
6491			image_name: "art",
6492			contents: ["some-art-lib"],
6493			apex_available: [
6494				"com.android.art.debug",
6495			],
6496		}
6497
6498		apex_key {
6499			name: "com.android.art.debug.key",
6500		}
6501
6502		filegroup {
6503			name: "some-updatable-apex-file_contexts",
6504			srcs: [
6505				"system/sepolicy/apex/some-updatable-apex-file_contexts",
6506			],
6507		}
6508
6509		filegroup {
6510			name: "some-non-updatable-apex-file_contexts",
6511			srcs: [
6512				"system/sepolicy/apex/some-non-updatable-apex-file_contexts",
6513			],
6514		}
6515	`
6516
6517	testDexpreoptWithApexes(t, bp, errmsg, preparer, fragments...)
6518}
6519
6520func testDexpreoptWithApexes(t *testing.T, bp, errmsg string, preparer android.FixturePreparer, fragments ...java.ApexVariantReference) *android.TestContext {
6521	t.Helper()
6522
6523	fs := android.MockFS{
6524		"a.java":              nil,
6525		"a.jar":               nil,
6526		"apex_manifest.json":  nil,
6527		"AndroidManifest.xml": nil,
6528		"system/sepolicy/apex/myapex-file_contexts":                  nil,
6529		"system/sepolicy/apex/some-updatable-apex-file_contexts":     nil,
6530		"system/sepolicy/apex/some-non-updatable-apex-file_contexts": nil,
6531		"system/sepolicy/apex/com.android.art.debug-file_contexts":   nil,
6532		"framework/aidl/a.aidl":                                      nil,
6533	}
6534
6535	errorHandler := android.FixtureExpectsNoErrors
6536	if errmsg != "" {
6537		errorHandler = android.FixtureExpectsAtLeastOneErrorMatchingPattern(errmsg)
6538	}
6539
6540	result := android.GroupFixturePreparers(
6541		cc.PrepareForTestWithCcDefaultModules,
6542		java.PrepareForTestWithHiddenApiBuildComponents,
6543		java.PrepareForTestWithJavaDefaultModules,
6544		java.PrepareForTestWithJavaSdkLibraryFiles,
6545		PrepareForTestWithApexBuildComponents,
6546		preparer,
6547		fs.AddToFixture(),
6548		android.FixtureModifyMockFS(func(fs android.MockFS) {
6549			if _, ok := fs["frameworks/base/boot/Android.bp"]; !ok {
6550				insert := ""
6551				for _, fragment := range fragments {
6552					insert += fmt.Sprintf("{apex: %q, module: %q},\n", *fragment.Apex, *fragment.Module)
6553				}
6554				fs["frameworks/base/boot/Android.bp"] = []byte(fmt.Sprintf(`
6555					platform_bootclasspath {
6556						name: "platform-bootclasspath",
6557						fragments: [
6558  						%s
6559						],
6560					}
6561				`, insert))
6562			}
6563		}),
6564	).
6565		ExtendWithErrorHandler(errorHandler).
6566		RunTestWithBp(t, bp)
6567
6568	return result.TestContext
6569}
6570
6571func TestDuplicateDeapexeresFromPrebuiltApexes(t *testing.T) {
6572	preparers := android.GroupFixturePreparers(
6573		java.PrepareForTestWithJavaDefaultModules,
6574		PrepareForTestWithApexBuildComponents,
6575	).
6576		ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(
6577			`Ambiguous duplicate deapexer module dependencies "com.android.myapex.deapexer" and "com.mycompany.android.myapex.deapexer"`))
6578
6579	bpBase := `
6580		apex_set {
6581			name: "com.android.myapex",
6582			exported_bootclasspath_fragments: ["my-bootclasspath-fragment"],
6583			set: "myapex.apks",
6584		}
6585
6586		apex_set {
6587			name: "com.mycompany.android.myapex",
6588			apex_name: "com.android.myapex",
6589			exported_bootclasspath_fragments: ["my-bootclasspath-fragment"],
6590			set: "company-myapex.apks",
6591		}
6592
6593		prebuilt_bootclasspath_fragment {
6594			name: "my-bootclasspath-fragment",
6595			apex_available: ["com.android.myapex"],
6596			%s
6597		}
6598	`
6599
6600	t.Run("java_import", func(t *testing.T) {
6601		_ = preparers.RunTestWithBp(t, fmt.Sprintf(bpBase, `contents: ["libfoo"]`)+`
6602			java_import {
6603				name: "libfoo",
6604				jars: ["libfoo.jar"],
6605				apex_available: ["com.android.myapex"],
6606			}
6607		`)
6608	})
6609
6610	t.Run("java_sdk_library_import", func(t *testing.T) {
6611		_ = preparers.RunTestWithBp(t, fmt.Sprintf(bpBase, `contents: ["libfoo"]`)+`
6612			java_sdk_library_import {
6613				name: "libfoo",
6614				public: {
6615					jars: ["libbar.jar"],
6616				},
6617				apex_available: ["com.android.myapex"],
6618			}
6619		`)
6620	})
6621
6622	t.Run("prebuilt_bootclasspath_fragment", func(t *testing.T) {
6623		_ = preparers.RunTestWithBp(t, fmt.Sprintf(bpBase, `
6624			image_name: "art",
6625			contents: ["libfoo"],
6626		`)+`
6627			java_sdk_library_import {
6628				name: "libfoo",
6629				public: {
6630					jars: ["libbar.jar"],
6631				},
6632				apex_available: ["com.android.myapex"],
6633			}
6634		`)
6635	})
6636}
6637
6638func TestUpdatable_should_set_min_sdk_version(t *testing.T) {
6639	testApexError(t, `"myapex" .*: updatable: updatable APEXes should set min_sdk_version`, `
6640		apex {
6641			name: "myapex",
6642			key: "myapex.key",
6643			updatable: true,
6644		}
6645
6646		apex_key {
6647			name: "myapex.key",
6648			public_key: "testkey.avbpubkey",
6649			private_key: "testkey.pem",
6650		}
6651	`)
6652}
6653
6654func TestUpdatableDefault_should_set_min_sdk_version(t *testing.T) {
6655	testApexError(t, `"myapex" .*: updatable: updatable APEXes should set min_sdk_version`, `
6656		apex {
6657			name: "myapex",
6658			key: "myapex.key",
6659		}
6660
6661		apex_key {
6662			name: "myapex.key",
6663			public_key: "testkey.avbpubkey",
6664			private_key: "testkey.pem",
6665		}
6666	`)
6667}
6668
6669func TestNoUpdatableJarsInBootImage(t *testing.T) {
6670	// Set the BootJars in dexpreopt.GlobalConfig and productVariables to the same value. This can
6671	// result in an invalid configuration as it does not set the ArtApexJars and allows art apex
6672	// modules to be included in the BootJars.
6673	prepareSetBootJars := func(bootJars ...string) android.FixturePreparer {
6674		return android.GroupFixturePreparers(
6675			dexpreopt.FixtureSetBootJars(bootJars...),
6676			android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
6677				variables.BootJars = android.CreateTestConfiguredJarList(bootJars)
6678			}),
6679		)
6680	}
6681
6682	// Set the ArtApexJars and BootJars in dexpreopt.GlobalConfig and productVariables all to the
6683	// same value. This can result in an invalid configuration as it allows non art apex jars to be
6684	// specified in the ArtApexJars configuration.
6685	prepareSetArtJars := func(bootJars ...string) android.FixturePreparer {
6686		return android.GroupFixturePreparers(
6687			dexpreopt.FixtureSetArtBootJars(bootJars...),
6688			dexpreopt.FixtureSetBootJars(bootJars...),
6689			android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
6690				variables.BootJars = android.CreateTestConfiguredJarList(bootJars)
6691			}),
6692		)
6693	}
6694
6695	t.Run("updatable jar from ART apex in the ART boot image => ok", func(t *testing.T) {
6696		preparer := java.FixtureConfigureBootJars("com.android.art.debug:some-art-lib")
6697		fragment := java.ApexVariantReference{
6698			Apex:   proptools.StringPtr("com.android.art.debug"),
6699			Module: proptools.StringPtr("art-bootclasspath-fragment"),
6700		}
6701		testNoUpdatableJarsInBootImage(t, "", preparer, fragment)
6702	})
6703
6704	t.Run("updatable jar from ART apex in the framework boot image => error", func(t *testing.T) {
6705		err := `module "some-art-lib" from updatable apexes \["com.android.art.debug"\] is not allowed in the framework boot image`
6706		// Update the dexpreopt BootJars directly.
6707		preparer := prepareSetBootJars("com.android.art.debug:some-art-lib")
6708		testNoUpdatableJarsInBootImage(t, err, preparer)
6709	})
6710
6711	t.Run("updatable jar from some other apex in the ART boot image => error", func(t *testing.T) {
6712		err := `ArtApexJars expects this to be in apex "some-updatable-apex" but this is only in apexes.*"com.android.art.debug"`
6713		// Update the dexpreopt ArtApexJars directly.
6714		preparer := prepareSetArtJars("some-updatable-apex:some-updatable-apex-lib")
6715		testNoUpdatableJarsInBootImage(t, err, preparer)
6716	})
6717
6718	t.Run("non-updatable jar from some other apex in the ART boot image => error", func(t *testing.T) {
6719		err := `ArtApexJars expects this to be in apex "some-non-updatable-apex" but this is only in apexes.*"com.android.art.debug"`
6720		// Update the dexpreopt ArtApexJars directly.
6721		preparer := prepareSetArtJars("some-non-updatable-apex:some-non-updatable-apex-lib")
6722		testNoUpdatableJarsInBootImage(t, err, preparer)
6723	})
6724
6725	t.Run("updatable jar from some other apex in the framework boot image => error", func(t *testing.T) {
6726		err := `module "some-updatable-apex-lib" from updatable apexes \["some-updatable-apex"\] is not allowed in the framework boot image`
6727		preparer := java.FixtureConfigureBootJars("some-updatable-apex:some-updatable-apex-lib")
6728		testNoUpdatableJarsInBootImage(t, err, preparer)
6729	})
6730
6731	t.Run("non-updatable jar from some other apex in the framework boot image => ok", func(t *testing.T) {
6732		preparer := java.FixtureConfigureBootJars("some-non-updatable-apex:some-non-updatable-apex-lib")
6733		fragment := java.ApexVariantReference{
6734			Apex:   proptools.StringPtr("some-non-updatable-apex"),
6735			Module: proptools.StringPtr("some-non-updatable-fragment"),
6736		}
6737		testNoUpdatableJarsInBootImage(t, "", preparer, fragment)
6738	})
6739
6740	t.Run("nonexistent jar in the ART boot image => error", func(t *testing.T) {
6741		err := `"platform-bootclasspath" depends on undefined module "nonexistent"`
6742		preparer := java.FixtureConfigureBootJars("platform:nonexistent")
6743		testNoUpdatableJarsInBootImage(t, err, preparer)
6744	})
6745
6746	t.Run("nonexistent jar in the framework boot image => error", func(t *testing.T) {
6747		err := `"platform-bootclasspath" depends on undefined module "nonexistent"`
6748		preparer := java.FixtureConfigureBootJars("platform:nonexistent")
6749		testNoUpdatableJarsInBootImage(t, err, preparer)
6750	})
6751
6752	t.Run("platform jar in the ART boot image => error", func(t *testing.T) {
6753		err := `ArtApexJars is invalid as it requests a platform variant of "some-platform-lib"`
6754		// Update the dexpreopt ArtApexJars directly.
6755		preparer := prepareSetArtJars("platform:some-platform-lib")
6756		testNoUpdatableJarsInBootImage(t, err, preparer)
6757	})
6758
6759	t.Run("platform jar in the framework boot image => ok", func(t *testing.T) {
6760		preparer := java.FixtureConfigureBootJars("platform:some-platform-lib")
6761		testNoUpdatableJarsInBootImage(t, "", preparer)
6762	})
6763}
6764
6765func TestDexpreoptAccessDexFilesFromPrebuiltApex(t *testing.T) {
6766	preparer := java.FixtureConfigureBootJars("myapex:libfoo")
6767	t.Run("prebuilt no source", func(t *testing.T) {
6768		fragment := java.ApexVariantReference{
6769			Apex:   proptools.StringPtr("myapex"),
6770			Module: proptools.StringPtr("my-bootclasspath-fragment"),
6771		}
6772
6773		testDexpreoptWithApexes(t, `
6774			prebuilt_apex {
6775				name: "myapex" ,
6776				arch: {
6777					arm64: {
6778						src: "myapex-arm64.apex",
6779					},
6780					arm: {
6781						src: "myapex-arm.apex",
6782					},
6783				},
6784				exported_bootclasspath_fragments: ["my-bootclasspath-fragment"],
6785			}
6786
6787			prebuilt_bootclasspath_fragment {
6788				name: "my-bootclasspath-fragment",
6789				contents: ["libfoo"],
6790				apex_available: ["myapex"],
6791			}
6792
6793			java_import {
6794				name: "libfoo",
6795				jars: ["libfoo.jar"],
6796				apex_available: ["myapex"],
6797			}
6798		`, "", preparer, fragment)
6799	})
6800}
6801
6802func testApexPermittedPackagesRules(t *testing.T, errmsg, bp string, apexBootJars []string, rules []android.Rule) {
6803	t.Helper()
6804	bp += `
6805	apex_key {
6806		name: "myapex.key",
6807		public_key: "testkey.avbpubkey",
6808		private_key: "testkey.pem",
6809	}`
6810	fs := android.MockFS{
6811		"lib1/src/A.java": nil,
6812		"lib2/src/B.java": nil,
6813		"system/sepolicy/apex/myapex-file_contexts": nil,
6814	}
6815
6816	errorHandler := android.FixtureExpectsNoErrors
6817	if errmsg != "" {
6818		errorHandler = android.FixtureExpectsAtLeastOneErrorMatchingPattern(errmsg)
6819	}
6820
6821	android.GroupFixturePreparers(
6822		android.PrepareForTestWithAndroidBuildComponents,
6823		java.PrepareForTestWithJavaBuildComponents,
6824		PrepareForTestWithApexBuildComponents,
6825		android.PrepareForTestWithNeverallowRules(rules),
6826		android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
6827			updatableBootJars := make([]string, 0, len(apexBootJars))
6828			for _, apexBootJar := range apexBootJars {
6829				updatableBootJars = append(updatableBootJars, "myapex:"+apexBootJar)
6830			}
6831			variables.UpdatableBootJars = android.CreateTestConfiguredJarList(updatableBootJars)
6832		}),
6833		fs.AddToFixture(),
6834	).
6835		ExtendWithErrorHandler(errorHandler).
6836		RunTestWithBp(t, bp)
6837}
6838
6839func TestApexPermittedPackagesRules(t *testing.T) {
6840	testcases := []struct {
6841		name            string
6842		expectedError   string
6843		bp              string
6844		bootJars        []string
6845		modulesPackages map[string][]string
6846	}{
6847
6848		{
6849			name:          "Non-Bootclasspath apex jar not satisfying allowed module packages.",
6850			expectedError: "",
6851			bp: `
6852				java_library {
6853					name: "bcp_lib1",
6854					srcs: ["lib1/src/*.java"],
6855					permitted_packages: ["foo.bar"],
6856					apex_available: ["myapex"],
6857					sdk_version: "none",
6858					system_modules: "none",
6859				}
6860				java_library {
6861					name: "nonbcp_lib2",
6862					srcs: ["lib2/src/*.java"],
6863					apex_available: ["myapex"],
6864					permitted_packages: ["a.b"],
6865					sdk_version: "none",
6866					system_modules: "none",
6867				}
6868				apex {
6869					name: "myapex",
6870					key: "myapex.key",
6871					java_libs: ["bcp_lib1", "nonbcp_lib2"],
6872					updatable: false,
6873				}`,
6874			bootJars: []string{"bcp_lib1"},
6875			modulesPackages: map[string][]string{
6876				"myapex": []string{
6877					"foo.bar",
6878				},
6879			},
6880		},
6881		{
6882			name:          "Bootclasspath apex jar not satisfying allowed module packages.",
6883			expectedError: `module "bcp_lib2" .* which is restricted because jars that are part of the myapex module may only allow these packages: foo.bar. Please jarjar or move code around.`,
6884			bp: `
6885				java_library {
6886					name: "bcp_lib1",
6887					srcs: ["lib1/src/*.java"],
6888					apex_available: ["myapex"],
6889					permitted_packages: ["foo.bar"],
6890					sdk_version: "none",
6891					system_modules: "none",
6892				}
6893				java_library {
6894					name: "bcp_lib2",
6895					srcs: ["lib2/src/*.java"],
6896					apex_available: ["myapex"],
6897					permitted_packages: ["foo.bar", "bar.baz"],
6898					sdk_version: "none",
6899					system_modules: "none",
6900				}
6901				apex {
6902					name: "myapex",
6903					key: "myapex.key",
6904					java_libs: ["bcp_lib1", "bcp_lib2"],
6905					updatable: false,
6906				}
6907			`,
6908			bootJars: []string{"bcp_lib1", "bcp_lib2"},
6909			modulesPackages: map[string][]string{
6910				"myapex": []string{
6911					"foo.bar",
6912				},
6913			},
6914		},
6915	}
6916	for _, tc := range testcases {
6917		t.Run(tc.name, func(t *testing.T) {
6918			rules := createApexPermittedPackagesRules(tc.modulesPackages)
6919			testApexPermittedPackagesRules(t, tc.expectedError, tc.bp, tc.bootJars, rules)
6920		})
6921	}
6922}
6923
6924func TestTestFor(t *testing.T) {
6925	ctx := testApex(t, `
6926		apex {
6927			name: "myapex",
6928			key: "myapex.key",
6929			native_shared_libs: ["mylib", "myprivlib"],
6930			updatable: false,
6931		}
6932
6933		apex_key {
6934			name: "myapex.key",
6935			public_key: "testkey.avbpubkey",
6936			private_key: "testkey.pem",
6937		}
6938
6939		cc_library {
6940			name: "mylib",
6941			srcs: ["mylib.cpp"],
6942			system_shared_libs: [],
6943			stl: "none",
6944			stubs: {
6945				versions: ["1"],
6946			},
6947			apex_available: ["myapex"],
6948		}
6949
6950		cc_library {
6951			name: "myprivlib",
6952			srcs: ["mylib.cpp"],
6953			system_shared_libs: [],
6954			stl: "none",
6955			apex_available: ["myapex"],
6956		}
6957
6958
6959		cc_test {
6960			name: "mytest",
6961			gtest: false,
6962			srcs: ["mylib.cpp"],
6963			system_shared_libs: [],
6964			stl: "none",
6965			shared_libs: ["mylib", "myprivlib", "mytestlib"],
6966			test_for: ["myapex"]
6967		}
6968
6969		cc_library {
6970			name: "mytestlib",
6971			srcs: ["mylib.cpp"],
6972			system_shared_libs: [],
6973			shared_libs: ["mylib", "myprivlib"],
6974			stl: "none",
6975			test_for: ["myapex"],
6976		}
6977
6978		cc_benchmark {
6979			name: "mybench",
6980			srcs: ["mylib.cpp"],
6981			system_shared_libs: [],
6982			shared_libs: ["mylib", "myprivlib"],
6983			stl: "none",
6984			test_for: ["myapex"],
6985		}
6986	`)
6987
6988	ensureLinkedLibIs := func(mod, variant, linkedLib, expectedVariant string) {
6989		ldFlags := strings.Split(ctx.ModuleForTests(mod, variant).Rule("ld").Args["libFlags"], " ")
6990		mylibLdFlags := android.FilterListPred(ldFlags, func(s string) bool { return strings.HasPrefix(s, linkedLib) })
6991		android.AssertArrayString(t, "unexpected "+linkedLib+" link library for "+mod, []string{linkedLib + expectedVariant}, mylibLdFlags)
6992	}
6993
6994	// These modules are tests for the apex, therefore are linked to the
6995	// actual implementation of mylib instead of its stub.
6996	ensureLinkedLibIs("mytest", "android_arm64_armv8-a", "out/soong/.intermediates/mylib/", "android_arm64_armv8-a_shared/mylib.so")
6997	ensureLinkedLibIs("mytestlib", "android_arm64_armv8-a_shared", "out/soong/.intermediates/mylib/", "android_arm64_armv8-a_shared/mylib.so")
6998	ensureLinkedLibIs("mybench", "android_arm64_armv8-a", "out/soong/.intermediates/mylib/", "android_arm64_armv8-a_shared/mylib.so")
6999}
7000
7001func TestIndirectTestFor(t *testing.T) {
7002	ctx := testApex(t, `
7003		apex {
7004			name: "myapex",
7005			key: "myapex.key",
7006			native_shared_libs: ["mylib", "myprivlib"],
7007			updatable: false,
7008		}
7009
7010		apex_key {
7011			name: "myapex.key",
7012			public_key: "testkey.avbpubkey",
7013			private_key: "testkey.pem",
7014		}
7015
7016		cc_library {
7017			name: "mylib",
7018			srcs: ["mylib.cpp"],
7019			system_shared_libs: [],
7020			stl: "none",
7021			stubs: {
7022				versions: ["1"],
7023			},
7024			apex_available: ["myapex"],
7025		}
7026
7027		cc_library {
7028			name: "myprivlib",
7029			srcs: ["mylib.cpp"],
7030			system_shared_libs: [],
7031			stl: "none",
7032			shared_libs: ["mylib"],
7033			apex_available: ["myapex"],
7034		}
7035
7036		cc_library {
7037			name: "mytestlib",
7038			srcs: ["mylib.cpp"],
7039			system_shared_libs: [],
7040			shared_libs: ["myprivlib"],
7041			stl: "none",
7042			test_for: ["myapex"],
7043		}
7044	`)
7045
7046	ensureLinkedLibIs := func(mod, variant, linkedLib, expectedVariant string) {
7047		ldFlags := strings.Split(ctx.ModuleForTests(mod, variant).Rule("ld").Args["libFlags"], " ")
7048		mylibLdFlags := android.FilterListPred(ldFlags, func(s string) bool { return strings.HasPrefix(s, linkedLib) })
7049		android.AssertArrayString(t, "unexpected "+linkedLib+" link library for "+mod, []string{linkedLib + expectedVariant}, mylibLdFlags)
7050	}
7051
7052	// The platform variant of mytestlib links to the platform variant of the
7053	// internal myprivlib.
7054	ensureLinkedLibIs("mytestlib", "android_arm64_armv8-a_shared", "out/soong/.intermediates/myprivlib/", "android_arm64_armv8-a_shared/myprivlib.so")
7055
7056	// The platform variant of myprivlib links to the platform variant of mylib
7057	// and bypasses its stubs.
7058	ensureLinkedLibIs("myprivlib", "android_arm64_armv8-a_shared", "out/soong/.intermediates/mylib/", "android_arm64_armv8-a_shared/mylib.so")
7059}
7060
7061func TestTestForForLibInOtherApex(t *testing.T) {
7062	// This case is only allowed for known overlapping APEXes, i.e. the ART APEXes.
7063	_ = testApex(t, `
7064		apex {
7065			name: "com.android.art",
7066			key: "myapex.key",
7067			native_shared_libs: ["mylib"],
7068			updatable: false,
7069		}
7070
7071		apex {
7072			name: "com.android.art.debug",
7073			key: "myapex.key",
7074			native_shared_libs: ["mylib", "mytestlib"],
7075			updatable: false,
7076		}
7077
7078		apex_key {
7079			name: "myapex.key",
7080			public_key: "testkey.avbpubkey",
7081			private_key: "testkey.pem",
7082		}
7083
7084		cc_library {
7085			name: "mylib",
7086			srcs: ["mylib.cpp"],
7087			system_shared_libs: [],
7088			stl: "none",
7089			stubs: {
7090				versions: ["1"],
7091			},
7092			apex_available: ["com.android.art", "com.android.art.debug"],
7093		}
7094
7095		cc_library {
7096			name: "mytestlib",
7097			srcs: ["mylib.cpp"],
7098			system_shared_libs: [],
7099			shared_libs: ["mylib"],
7100			stl: "none",
7101			apex_available: ["com.android.art.debug"],
7102			test_for: ["com.android.art"],
7103		}
7104	`,
7105		android.MockFS{
7106			"system/sepolicy/apex/com.android.art-file_contexts":       nil,
7107			"system/sepolicy/apex/com.android.art.debug-file_contexts": nil,
7108		}.AddToFixture())
7109}
7110
7111// TODO(jungjw): Move this to proptools
7112func intPtr(i int) *int {
7113	return &i
7114}
7115
7116func TestApexSet(t *testing.T) {
7117	ctx := testApex(t, `
7118		apex_set {
7119			name: "myapex",
7120			set: "myapex.apks",
7121			filename: "foo_v2.apex",
7122			overrides: ["foo"],
7123		}
7124	`,
7125		android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
7126			variables.Platform_sdk_version = intPtr(30)
7127		}),
7128		android.FixtureModifyConfig(func(config android.Config) {
7129			config.Targets[android.Android] = []android.Target{
7130				{Os: android.Android, Arch: android.Arch{ArchType: android.Arm, ArchVariant: "armv7-a-neon", Abi: []string{"armeabi-v7a"}}},
7131				{Os: android.Android, Arch: android.Arch{ArchType: android.Arm64, ArchVariant: "armv8-a", Abi: []string{"arm64-v8a"}}},
7132			}
7133		}),
7134	)
7135
7136	m := ctx.ModuleForTests("myapex.apex.extractor", "android_common")
7137
7138	// Check extract_apks tool parameters.
7139	extractedApex := m.Output("extracted/myapex.apks")
7140	actual := extractedApex.Args["abis"]
7141	expected := "ARMEABI_V7A,ARM64_V8A"
7142	if actual != expected {
7143		t.Errorf("Unexpected abis parameter - expected %q vs actual %q", expected, actual)
7144	}
7145	actual = extractedApex.Args["sdk-version"]
7146	expected = "30"
7147	if actual != expected {
7148		t.Errorf("Unexpected abis parameter - expected %q vs actual %q", expected, actual)
7149	}
7150
7151	m = ctx.ModuleForTests("myapex", "android_common_myapex")
7152	a := m.Module().(*ApexSet)
7153	expectedOverrides := []string{"foo"}
7154	actualOverrides := android.AndroidMkEntriesForTest(t, ctx, a)[0].EntryMap["LOCAL_OVERRIDES_MODULES"]
7155	if !reflect.DeepEqual(actualOverrides, expectedOverrides) {
7156		t.Errorf("Incorrect LOCAL_OVERRIDES_MODULES - expected %q vs actual %q", expectedOverrides, actualOverrides)
7157	}
7158}
7159
7160func TestNoStaticLinkingToStubsLib(t *testing.T) {
7161	testApexError(t, `.*required by "mylib" is a native library providing stub.*`, `
7162		apex {
7163			name: "myapex",
7164			key: "myapex.key",
7165			native_shared_libs: ["mylib"],
7166			updatable: false,
7167		}
7168
7169		apex_key {
7170			name: "myapex.key",
7171			public_key: "testkey.avbpubkey",
7172			private_key: "testkey.pem",
7173		}
7174
7175		cc_library {
7176			name: "mylib",
7177			srcs: ["mylib.cpp"],
7178			static_libs: ["otherlib"],
7179			system_shared_libs: [],
7180			stl: "none",
7181			apex_available: [ "myapex" ],
7182		}
7183
7184		cc_library {
7185			name: "otherlib",
7186			srcs: ["mylib.cpp"],
7187			system_shared_libs: [],
7188			stl: "none",
7189			stubs: {
7190				versions: ["1", "2", "3"],
7191			},
7192			apex_available: [ "myapex" ],
7193		}
7194	`)
7195}
7196
7197func TestApexKeysTxt(t *testing.T) {
7198	ctx := testApex(t, `
7199		apex {
7200			name: "myapex",
7201			key: "myapex.key",
7202			updatable: false,
7203		}
7204
7205		apex_key {
7206			name: "myapex.key",
7207			public_key: "testkey.avbpubkey",
7208			private_key: "testkey.pem",
7209		}
7210
7211		prebuilt_apex {
7212			name: "myapex",
7213			prefer: true,
7214			arch: {
7215				arm64: {
7216					src: "myapex-arm64.apex",
7217				},
7218				arm: {
7219					src: "myapex-arm.apex",
7220				},
7221			},
7222		}
7223
7224		apex_set {
7225			name: "myapex_set",
7226			set: "myapex.apks",
7227			filename: "myapex_set.apex",
7228			overrides: ["myapex"],
7229		}
7230	`)
7231
7232	apexKeysText := ctx.SingletonForTests("apex_keys_text")
7233	content := apexKeysText.MaybeDescription("apexkeys.txt").BuildParams.Args["content"]
7234	ensureContains(t, content, `name="myapex_set.apex" public_key="PRESIGNED" private_key="PRESIGNED" container_certificate="PRESIGNED" container_private_key="PRESIGNED" partition="system"`)
7235	ensureContains(t, content, `name="myapex.apex" public_key="PRESIGNED" private_key="PRESIGNED" container_certificate="PRESIGNED" container_private_key="PRESIGNED" partition="system"`)
7236}
7237
7238func TestAllowedFiles(t *testing.T) {
7239	ctx := testApex(t, `
7240		apex {
7241			name: "myapex",
7242			key: "myapex.key",
7243			apps: ["app"],
7244			allowed_files: "allowed.txt",
7245			updatable: false,
7246		}
7247
7248		apex_key {
7249			name: "myapex.key",
7250			public_key: "testkey.avbpubkey",
7251			private_key: "testkey.pem",
7252		}
7253
7254		android_app {
7255			name: "app",
7256			srcs: ["foo/bar/MyClass.java"],
7257			package_name: "foo",
7258			sdk_version: "none",
7259			system_modules: "none",
7260			apex_available: [ "myapex" ],
7261		}
7262	`, withFiles(map[string][]byte{
7263		"sub/Android.bp": []byte(`
7264			override_apex {
7265				name: "override_myapex",
7266				base: "myapex",
7267				apps: ["override_app"],
7268				allowed_files: ":allowed",
7269			}
7270			// Overridable "path" property should be referenced indirectly
7271			filegroup {
7272				name: "allowed",
7273				srcs: ["allowed.txt"],
7274			}
7275			override_android_app {
7276				name: "override_app",
7277				base: "app",
7278				package_name: "bar",
7279			}
7280			`),
7281	}))
7282
7283	rule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("diffApexContentRule")
7284	if expected, actual := "allowed.txt", rule.Args["allowed_files_file"]; expected != actual {
7285		t.Errorf("allowed_files_file: expected %q but got %q", expected, actual)
7286	}
7287
7288	rule2 := ctx.ModuleForTests("myapex", "android_common_override_myapex_myapex_image").Rule("diffApexContentRule")
7289	if expected, actual := "sub/allowed.txt", rule2.Args["allowed_files_file"]; expected != actual {
7290		t.Errorf("allowed_files_file: expected %q but got %q", expected, actual)
7291	}
7292}
7293
7294func TestNonPreferredPrebuiltDependency(t *testing.T) {
7295	testApex(t, `
7296		apex {
7297			name: "myapex",
7298			key: "myapex.key",
7299			native_shared_libs: ["mylib"],
7300			updatable: false,
7301		}
7302
7303		apex_key {
7304			name: "myapex.key",
7305			public_key: "testkey.avbpubkey",
7306			private_key: "testkey.pem",
7307		}
7308
7309		cc_library {
7310			name: "mylib",
7311			srcs: ["mylib.cpp"],
7312			stubs: {
7313				versions: ["current"],
7314			},
7315			apex_available: ["myapex"],
7316		}
7317
7318		cc_prebuilt_library_shared {
7319			name: "mylib",
7320			prefer: false,
7321			srcs: ["prebuilt.so"],
7322			stubs: {
7323				versions: ["current"],
7324			},
7325			apex_available: ["myapex"],
7326		}
7327	`)
7328}
7329
7330func TestCompressedApex(t *testing.T) {
7331	ctx := testApex(t, `
7332		apex {
7333			name: "myapex",
7334			key: "myapex.key",
7335			compressible: true,
7336			updatable: false,
7337		}
7338		apex_key {
7339			name: "myapex.key",
7340			public_key: "testkey.avbpubkey",
7341			private_key: "testkey.pem",
7342		}
7343	`,
7344		android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
7345			variables.CompressedApex = proptools.BoolPtr(true)
7346		}),
7347	)
7348
7349	compressRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("compressRule")
7350	ensureContains(t, compressRule.Output.String(), "myapex.capex.unsigned")
7351
7352	signApkRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Description("sign compressedApex")
7353	ensureEquals(t, signApkRule.Input.String(), compressRule.Output.String())
7354
7355	// Make sure output of bundle is .capex
7356	ab := ctx.ModuleForTests("myapex", "android_common_myapex_image").Module().(*apexBundle)
7357	ensureContains(t, ab.outputFile.String(), "myapex.capex")
7358
7359	// Verify android.mk rules
7360	data := android.AndroidMkDataForTest(t, ctx, ab)
7361	var builder strings.Builder
7362	data.Custom(&builder, ab.BaseModuleName(), "TARGET_", "", data)
7363	androidMk := builder.String()
7364	ensureContains(t, androidMk, "LOCAL_MODULE_STEM := myapex.capex\n")
7365}
7366
7367func TestPreferredPrebuiltSharedLibDep(t *testing.T) {
7368	ctx := testApex(t, `
7369		apex {
7370			name: "myapex",
7371			key: "myapex.key",
7372			native_shared_libs: ["mylib"],
7373			updatable: false,
7374		}
7375
7376		apex_key {
7377			name: "myapex.key",
7378			public_key: "testkey.avbpubkey",
7379			private_key: "testkey.pem",
7380		}
7381
7382		cc_library {
7383			name: "mylib",
7384			srcs: ["mylib.cpp"],
7385			apex_available: ["myapex"],
7386			shared_libs: ["otherlib"],
7387			system_shared_libs: [],
7388		}
7389
7390		cc_library {
7391			name: "otherlib",
7392			srcs: ["mylib.cpp"],
7393			stubs: {
7394				versions: ["current"],
7395			},
7396		}
7397
7398		cc_prebuilt_library_shared {
7399			name: "otherlib",
7400			prefer: true,
7401			srcs: ["prebuilt.so"],
7402			stubs: {
7403				versions: ["current"],
7404			},
7405		}
7406	`)
7407
7408	ab := ctx.ModuleForTests("myapex", "android_common_myapex_image").Module().(*apexBundle)
7409	data := android.AndroidMkDataForTest(t, ctx, ab)
7410	var builder strings.Builder
7411	data.Custom(&builder, ab.BaseModuleName(), "TARGET_", "", data)
7412	androidMk := builder.String()
7413
7414	// The make level dependency needs to be on otherlib - prebuilt_otherlib isn't
7415	// a thing there.
7416	ensureContains(t, androidMk, "LOCAL_REQUIRED_MODULES += otherlib\n")
7417}
7418
7419func TestExcludeDependency(t *testing.T) {
7420	ctx := testApex(t, `
7421		apex {
7422			name: "myapex",
7423			key: "myapex.key",
7424			native_shared_libs: ["mylib"],
7425			updatable: false,
7426		}
7427
7428		apex_key {
7429			name: "myapex.key",
7430			public_key: "testkey.avbpubkey",
7431			private_key: "testkey.pem",
7432		}
7433
7434		cc_library {
7435			name: "mylib",
7436			srcs: ["mylib.cpp"],
7437			system_shared_libs: [],
7438			stl: "none",
7439			apex_available: ["myapex"],
7440			shared_libs: ["mylib2"],
7441			target: {
7442				apex: {
7443					exclude_shared_libs: ["mylib2"],
7444				},
7445			},
7446		}
7447
7448		cc_library {
7449			name: "mylib2",
7450			srcs: ["mylib.cpp"],
7451			system_shared_libs: [],
7452			stl: "none",
7453		}
7454	`)
7455
7456	// Check if mylib is linked to mylib2 for the non-apex target
7457	ldFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared").Rule("ld").Args["libFlags"]
7458	ensureContains(t, ldFlags, "mylib2/android_arm64_armv8-a_shared/mylib2.so")
7459
7460	// Make sure that the link doesn't occur for the apex target
7461	ldFlags = ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_apex10000").Rule("ld").Args["libFlags"]
7462	ensureNotContains(t, ldFlags, "mylib2/android_arm64_armv8-a_shared_apex10000/mylib2.so")
7463
7464	// It shouldn't appear in the copy cmd as well.
7465	copyCmds := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("apexRule").Args["copy_commands"]
7466	ensureNotContains(t, copyCmds, "image.apex/lib64/mylib2.so")
7467}
7468
7469func TestPrebuiltStubLibDep(t *testing.T) {
7470	bpBase := `
7471		apex {
7472			name: "myapex",
7473			key: "myapex.key",
7474			native_shared_libs: ["mylib"],
7475			updatable: false,
7476		}
7477		apex_key {
7478			name: "myapex.key",
7479			public_key: "testkey.avbpubkey",
7480			private_key: "testkey.pem",
7481		}
7482		cc_library {
7483			name: "mylib",
7484			srcs: ["mylib.cpp"],
7485			apex_available: ["myapex"],
7486			shared_libs: ["stublib"],
7487			system_shared_libs: [],
7488		}
7489		apex {
7490			name: "otherapex",
7491			enabled: %s,
7492			key: "myapex.key",
7493			native_shared_libs: ["stublib"],
7494			updatable: false,
7495		}
7496	`
7497
7498	stublibSourceBp := `
7499		cc_library {
7500			name: "stublib",
7501			srcs: ["mylib.cpp"],
7502			apex_available: ["otherapex"],
7503			system_shared_libs: [],
7504			stl: "none",
7505			stubs: {
7506				versions: ["1"],
7507			},
7508		}
7509	`
7510
7511	stublibPrebuiltBp := `
7512		cc_prebuilt_library_shared {
7513			name: "stublib",
7514			srcs: ["prebuilt.so"],
7515			apex_available: ["otherapex"],
7516			stubs: {
7517				versions: ["1"],
7518			},
7519			%s
7520		}
7521	`
7522
7523	tests := []struct {
7524		name             string
7525		stublibBp        string
7526		usePrebuilt      bool
7527		modNames         []string // Modules to collect AndroidMkEntries for
7528		otherApexEnabled []string
7529	}{
7530		{
7531			name:             "only_source",
7532			stublibBp:        stublibSourceBp,
7533			usePrebuilt:      false,
7534			modNames:         []string{"stublib"},
7535			otherApexEnabled: []string{"true", "false"},
7536		},
7537		{
7538			name:             "source_preferred",
7539			stublibBp:        stublibSourceBp + fmt.Sprintf(stublibPrebuiltBp, ""),
7540			usePrebuilt:      false,
7541			modNames:         []string{"stublib", "prebuilt_stublib"},
7542			otherApexEnabled: []string{"true", "false"},
7543		},
7544		{
7545			name:             "prebuilt_preferred",
7546			stublibBp:        stublibSourceBp + fmt.Sprintf(stublibPrebuiltBp, "prefer: true,"),
7547			usePrebuilt:      true,
7548			modNames:         []string{"stublib", "prebuilt_stublib"},
7549			otherApexEnabled: []string{"false"}, // No "true" since APEX cannot depend on prebuilt.
7550		},
7551		{
7552			name:             "only_prebuilt",
7553			stublibBp:        fmt.Sprintf(stublibPrebuiltBp, ""),
7554			usePrebuilt:      true,
7555			modNames:         []string{"stublib"},
7556			otherApexEnabled: []string{"false"}, // No "true" since APEX cannot depend on prebuilt.
7557		},
7558	}
7559
7560	for _, test := range tests {
7561		t.Run(test.name, func(t *testing.T) {
7562			for _, otherApexEnabled := range test.otherApexEnabled {
7563				t.Run("otherapex_enabled_"+otherApexEnabled, func(t *testing.T) {
7564					ctx := testApex(t, fmt.Sprintf(bpBase, otherApexEnabled)+test.stublibBp)
7565
7566					type modAndMkEntries struct {
7567						mod       *cc.Module
7568						mkEntries android.AndroidMkEntries
7569					}
7570					entries := []*modAndMkEntries{}
7571
7572					// Gather shared lib modules that are installable
7573					for _, modName := range test.modNames {
7574						for _, variant := range ctx.ModuleVariantsForTests(modName) {
7575							if !strings.HasPrefix(variant, "android_arm64_armv8-a_shared") {
7576								continue
7577							}
7578							mod := ctx.ModuleForTests(modName, variant).Module().(*cc.Module)
7579							if !mod.Enabled() || mod.IsHideFromMake() {
7580								continue
7581							}
7582							for _, ent := range android.AndroidMkEntriesForTest(t, ctx, mod) {
7583								if ent.Disabled {
7584									continue
7585								}
7586								entries = append(entries, &modAndMkEntries{
7587									mod:       mod,
7588									mkEntries: ent,
7589								})
7590							}
7591						}
7592					}
7593
7594					var entry *modAndMkEntries = nil
7595					for _, ent := range entries {
7596						if strings.Join(ent.mkEntries.EntryMap["LOCAL_MODULE"], ",") == "stublib" {
7597							if entry != nil {
7598								t.Errorf("More than one AndroidMk entry for \"stublib\": %s and %s", entry.mod, ent.mod)
7599							} else {
7600								entry = ent
7601							}
7602						}
7603					}
7604
7605					if entry == nil {
7606						t.Errorf("AndroidMk entry for \"stublib\" missing")
7607					} else {
7608						isPrebuilt := entry.mod.Prebuilt() != nil
7609						if isPrebuilt != test.usePrebuilt {
7610							t.Errorf("Wrong module for \"stublib\" AndroidMk entry: got prebuilt %t, want prebuilt %t", isPrebuilt, test.usePrebuilt)
7611						}
7612						if !entry.mod.IsStubs() {
7613							t.Errorf("Module for \"stublib\" AndroidMk entry isn't a stub: %s", entry.mod)
7614						}
7615						if entry.mkEntries.EntryMap["LOCAL_NOT_AVAILABLE_FOR_PLATFORM"] != nil {
7616							t.Errorf("AndroidMk entry for \"stublib\" has LOCAL_NOT_AVAILABLE_FOR_PLATFORM set: %+v", entry.mkEntries)
7617						}
7618						cflags := entry.mkEntries.EntryMap["LOCAL_EXPORT_CFLAGS"]
7619						expected := "-D__STUBLIB_API__=10000"
7620						if !android.InList(expected, cflags) {
7621							t.Errorf("LOCAL_EXPORT_CFLAGS expected to have %q, but got %q", expected, cflags)
7622						}
7623					}
7624				})
7625			}
7626		})
7627	}
7628}
7629
7630func TestApexJavaCoverage(t *testing.T) {
7631	bp := `
7632		apex {
7633			name: "myapex",
7634			key: "myapex.key",
7635			java_libs: ["mylib"],
7636			bootclasspath_fragments: ["mybootclasspathfragment"],
7637			systemserverclasspath_fragments: ["mysystemserverclasspathfragment"],
7638			updatable: false,
7639		}
7640
7641		apex_key {
7642			name: "myapex.key",
7643			public_key: "testkey.avbpubkey",
7644			private_key: "testkey.pem",
7645		}
7646
7647		java_library {
7648			name: "mylib",
7649			srcs: ["mylib.java"],
7650			apex_available: ["myapex"],
7651			compile_dex: true,
7652		}
7653
7654		bootclasspath_fragment {
7655			name: "mybootclasspathfragment",
7656			contents: ["mybootclasspathlib"],
7657			apex_available: ["myapex"],
7658		}
7659
7660		java_library {
7661			name: "mybootclasspathlib",
7662			srcs: ["mybootclasspathlib.java"],
7663			apex_available: ["myapex"],
7664			compile_dex: true,
7665		}
7666
7667		systemserverclasspath_fragment {
7668			name: "mysystemserverclasspathfragment",
7669			contents: ["mysystemserverclasspathlib"],
7670			apex_available: ["myapex"],
7671		}
7672
7673		java_library {
7674			name: "mysystemserverclasspathlib",
7675			srcs: ["mysystemserverclasspathlib.java"],
7676			apex_available: ["myapex"],
7677			compile_dex: true,
7678		}
7679	`
7680
7681	result := android.GroupFixturePreparers(
7682		PrepareForTestWithApexBuildComponents,
7683		prepareForTestWithMyapex,
7684		java.PrepareForTestWithJavaDefaultModules,
7685		android.PrepareForTestWithAndroidBuildComponents,
7686		android.FixtureWithRootAndroidBp(bp),
7687		android.FixtureMergeEnv(map[string]string{
7688			"EMMA_INSTRUMENT": "true",
7689		}),
7690	).RunTest(t)
7691
7692	// Make sure jacoco ran on both mylib and mybootclasspathlib
7693	if result.ModuleForTests("mylib", "android_common_apex10000").MaybeRule("jacoco").Rule == nil {
7694		t.Errorf("Failed to find jacoco rule for mylib")
7695	}
7696	if result.ModuleForTests("mybootclasspathlib", "android_common_apex10000").MaybeRule("jacoco").Rule == nil {
7697		t.Errorf("Failed to find jacoco rule for mybootclasspathlib")
7698	}
7699	if result.ModuleForTests("mysystemserverclasspathlib", "android_common_apex10000").MaybeRule("jacoco").Rule == nil {
7700		t.Errorf("Failed to find jacoco rule for mysystemserverclasspathlib")
7701	}
7702}
7703
7704func TestMain(m *testing.M) {
7705	os.Exit(m.Run())
7706}
7707