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