xref: /aosp_15_r20/build/soong/java/app_test.go (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
1// Copyright 2017 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 java
16
17import (
18	"fmt"
19	"path/filepath"
20	"reflect"
21	"sort"
22	"strings"
23	"testing"
24
25	"github.com/google/blueprint/proptools"
26
27	"android/soong/android"
28	"android/soong/cc"
29	"android/soong/dexpreopt"
30)
31
32// testApp runs tests using the prepareForJavaTest
33//
34// See testJava for an explanation as to how to stop using this deprecated method.
35//
36// deprecated
37func testApp(t *testing.T, bp string) *android.TestContext {
38	t.Helper()
39	result := prepareForJavaTest.RunTestWithBp(t, bp)
40	return result.TestContext
41}
42
43func TestApp(t *testing.T) {
44	resourceFiles := []string{
45		"res/layout/layout.xml",
46		"res/values/strings.xml",
47		"res/values-en-rUS/strings.xml",
48	}
49
50	compiledResourceFiles := []string{
51		"aapt2/res/layout_layout.xml.flat",
52		"aapt2/res/values_strings.arsc.flat",
53		"aapt2/res/values-en-rUS_strings.arsc.flat",
54	}
55
56	for _, moduleType := range []string{"android_app", "android_library"} {
57		t.Run(moduleType, func(t *testing.T) {
58			result := android.GroupFixturePreparers(
59				prepareForJavaTest,
60				android.FixtureModifyMockFS(func(fs android.MockFS) {
61					for _, file := range resourceFiles {
62						fs[file] = nil
63					}
64				}),
65			).RunTestWithBp(t, moduleType+` {
66					name: "foo",
67					srcs: ["a.java"],
68					sdk_version: "current"
69				}
70			`)
71
72			foo := result.ModuleForTests("foo", "android_common")
73
74			var expectedLinkImplicits []string
75
76			manifestFixer := foo.Output("manifest_fixer/AndroidManifest.xml")
77			expectedLinkImplicits = append(expectedLinkImplicits, manifestFixer.Output.String())
78
79			frameworkRes := result.ModuleForTests("framework-res", "android_common")
80			expectedLinkImplicits = append(expectedLinkImplicits,
81				frameworkRes.Output("package-res.apk").Output.String())
82
83			// Test the mapping from input files to compiled output file names
84			compile := foo.Output(compiledResourceFiles[0])
85			android.AssertDeepEquals(t, "aapt2 compile inputs", resourceFiles, compile.Inputs.Strings())
86
87			compiledResourceOutputs := compile.Outputs.Strings()
88			sort.Strings(compiledResourceOutputs)
89
90			expectedLinkImplicits = append(expectedLinkImplicits, compiledResourceOutputs...)
91
92			list := foo.Output("aapt2/res.list")
93			expectedLinkImplicits = append(expectedLinkImplicits, list.Output.String())
94
95			// Check that the link rule uses
96			res := result.ModuleForTests("foo", "android_common").Output("package-res.apk")
97			android.AssertDeepEquals(t, "aapt2 link implicits", expectedLinkImplicits, res.Implicits.Strings())
98		})
99	}
100}
101
102func TestAppSplits(t *testing.T) {
103	ctx := testApp(t, `
104				android_app {
105					name: "foo",
106					srcs: ["a.java"],
107					package_splits: ["v4", "v7,hdpi"],
108					sdk_version: "current"
109				}`)
110
111	foo := ctx.ModuleForTests("foo", "android_common")
112
113	expectedOutputs := []string{
114		"out/soong/.intermediates/foo/android_common/foo.apk",
115		"out/soong/.intermediates/foo/android_common/foo_v4.apk",
116		"out/soong/.intermediates/foo/android_common/foo_v7_hdpi.apk",
117	}
118	for _, expectedOutput := range expectedOutputs {
119		foo.Output(expectedOutput)
120	}
121
122	outputFiles := foo.OutputFiles(ctx, t, "")
123	android.AssertPathsRelativeToTopEquals(t, `OutputFiles("")`, expectedOutputs, outputFiles)
124}
125
126func TestPlatformAPIs(t *testing.T) {
127	testJava(t, `
128		android_app {
129			name: "foo",
130			srcs: ["a.java"],
131			platform_apis: true,
132		}
133	`)
134
135	testJava(t, `
136		android_app {
137			name: "foo",
138			srcs: ["a.java"],
139			sdk_version: "current",
140		}
141	`)
142
143	testJavaError(t, "This module has conflicting settings. sdk_version is empty, which means that this module is build against platform APIs. However platform_apis is not set to true", `
144		android_app {
145			name: "bar",
146			srcs: ["b.java"],
147		}
148	`)
149
150	testJavaError(t, "This module has conflicting settings. sdk_version is not empty, which means this module cannot use platform APIs. However platform_apis is set to true.", `
151		android_app {
152			name: "bar",
153			srcs: ["b.java"],
154			sdk_version: "system_current",
155			platform_apis: true,
156		}
157	`)
158}
159
160func TestAndroidAppLinkType(t *testing.T) {
161	testJava(t, `
162		android_app {
163			name: "foo",
164			srcs: ["a.java"],
165			libs: ["bar"],
166			static_libs: ["baz"],
167			platform_apis: true,
168		}
169
170		java_library {
171			name: "bar",
172			sdk_version: "current",
173			srcs: ["b.java"],
174		}
175
176		android_library {
177			name: "baz",
178			sdk_version: "system_current",
179			srcs: ["c.java"],
180		}
181	`)
182
183	testJavaError(t, "consider adjusting sdk_version: OR platform_apis:", `
184		android_app {
185			name: "foo",
186			srcs: ["a.java"],
187			libs: ["bar"],
188			sdk_version: "current",
189			static_libs: ["baz"],
190		}
191
192		java_library {
193			name: "bar",
194			sdk_version: "current",
195			srcs: ["b.java"],
196		}
197
198		android_library {
199			name: "baz",
200			sdk_version: "system_current",
201			srcs: ["c.java"],
202		}
203	`)
204
205	testJava(t, `
206		android_app {
207			name: "foo",
208			srcs: ["a.java"],
209			libs: ["bar"],
210			sdk_version: "system_current",
211			static_libs: ["baz"],
212		}
213
214		java_library {
215			name: "bar",
216			sdk_version: "current",
217			srcs: ["b.java"],
218		}
219
220		android_library {
221			name: "baz",
222			sdk_version: "system_current",
223			srcs: ["c.java"],
224		}
225	`)
226
227	testJavaError(t, "consider adjusting sdk_version: OR platform_apis:", `
228		android_app {
229			name: "foo",
230			srcs: ["a.java"],
231			libs: ["bar"],
232			sdk_version: "system_current",
233			static_libs: ["baz"],
234		}
235
236		java_library {
237			name: "bar",
238			sdk_version: "current",
239			srcs: ["b.java"],
240		}
241
242		android_library {
243			name: "baz",
244			srcs: ["c.java"],
245		}
246	`)
247}
248
249func TestUpdatableApps(t *testing.T) {
250	testCases := []struct {
251		name          string
252		bp            string
253		expectedError string
254	}{
255		{
256			name: "Stable public SDK",
257			bp: `android_app {
258					name: "foo",
259					srcs: ["a.java"],
260					sdk_version: "29",
261					min_sdk_version: "29",
262					updatable: true,
263				}`,
264		},
265		{
266			name: "Stable system SDK",
267			bp: `android_app {
268					name: "foo",
269					srcs: ["a.java"],
270					sdk_version: "system_29",
271					min_sdk_version: "29",
272					updatable: true,
273				}`,
274		},
275		{
276			name: "Current public SDK",
277			bp: `android_app {
278					name: "foo",
279					srcs: ["a.java"],
280					sdk_version: "current",
281					min_sdk_version: "29",
282					updatable: true,
283				}`,
284		},
285		{
286			name: "Current system SDK",
287			bp: `android_app {
288					name: "foo",
289					srcs: ["a.java"],
290					sdk_version: "system_current",
291					min_sdk_version: "29",
292					updatable: true,
293				}`,
294		},
295		{
296			name: "Current module SDK",
297			bp: `android_app {
298					name: "foo",
299					srcs: ["a.java"],
300					sdk_version: "module_current",
301					min_sdk_version: "29",
302					updatable: true,
303				}`,
304		},
305		{
306			name: "Current core SDK",
307			bp: `android_app {
308					name: "foo",
309					srcs: ["a.java"],
310					sdk_version: "core_current",
311					min_sdk_version: "29",
312					updatable: true,
313				}`,
314		},
315		{
316			name: "No Platform APIs",
317			bp: `android_app {
318					name: "foo",
319					srcs: ["a.java"],
320					platform_apis: true,
321					min_sdk_version: "29",
322					updatable: true,
323				}`,
324			expectedError: "Updatable apps must use stable SDKs",
325		},
326		{
327			name: "No Core Platform APIs",
328			bp: `android_app {
329					name: "foo",
330					srcs: ["a.java"],
331					sdk_version: "core_platform",
332					min_sdk_version: "29",
333					updatable: true,
334				}`,
335			expectedError: "Updatable apps must use stable SDKs",
336		},
337		{
338			name: "No unspecified APIs",
339			bp: `android_app {
340					name: "foo",
341					srcs: ["a.java"],
342					updatable: true,
343					min_sdk_version: "29",
344				}`,
345			expectedError: "Updatable apps must use stable SDK",
346		},
347		{
348			name: "Must specify min_sdk_version",
349			bp: `android_app {
350					name: "app_without_min_sdk_version",
351					srcs: ["a.java"],
352					sdk_version: "29",
353					updatable: true,
354				}`,
355			expectedError: "updatable apps must set min_sdk_version.",
356		},
357	}
358
359	for _, test := range testCases {
360		t.Run(test.name, func(t *testing.T) {
361			errorHandler := android.FixtureExpectsNoErrors
362			if test.expectedError != "" {
363				errorHandler = android.FixtureExpectsAtLeastOneErrorMatchingPattern(test.expectedError)
364			}
365			android.GroupFixturePreparers(
366				prepareForJavaTest, FixtureWithPrebuiltApis(map[string][]string{
367					"29": {"foo"},
368				})).
369				ExtendWithErrorHandler(errorHandler).RunTestWithBp(t, test.bp)
370		})
371	}
372}
373
374func TestUpdatableApps_TransitiveDepsShouldSetMinSdkVersion(t *testing.T) {
375	testJavaError(t, `module "bar".*: should support min_sdk_version\(29\)`, cc.GatherRequiredDepsForTest(android.Android)+`
376		android_app {
377			name: "foo",
378			srcs: ["a.java"],
379			updatable: true,
380			sdk_version: "current",
381			min_sdk_version: "29",
382			static_libs: ["bar"],
383		}
384
385		java_library {
386			name: "bar",
387			sdk_version: "current",
388		}
389	`)
390}
391
392func TestUpdatableApps_JniLibsShouldShouldSupportMinSdkVersion(t *testing.T) {
393	testJava(t, cc.GatherRequiredDepsForTest(android.Android)+`
394		android_app {
395			name: "foo",
396			srcs: ["a.java"],
397			updatable: true,
398			sdk_version: "current",
399			min_sdk_version: "current",
400			jni_libs: ["libjni"],
401		}
402
403		cc_library {
404			name: "libjni",
405			stl: "none",
406			system_shared_libs: [],
407			sdk_version: "current",
408		}
409	`)
410}
411
412func TestUpdatableApps_JniLibShouldBeBuiltAgainstMinSdkVersion(t *testing.T) {
413	bp := cc.GatherRequiredDepsForTest(android.Android) + `
414		android_app {
415			name: "foo",
416			srcs: ["a.java"],
417			updatable: true,
418			sdk_version: "current",
419			min_sdk_version: "29",
420			jni_libs: ["libjni"],
421		}
422
423		cc_library {
424			name: "libjni",
425			stl: "none",
426			system_shared_libs: [],
427			sdk_version: "current",
428			min_sdk_version: "29",
429		}
430	`
431	fs := map[string][]byte{
432		"prebuilts/ndk/current/platforms/android-29/arch-arm64/usr/lib/crtbegin_so.o": nil,
433		"prebuilts/ndk/current/platforms/android-29/arch-arm64/usr/lib/crtend_so.o":   nil,
434		"prebuilts/ndk/current/platforms/android-29/arch-arm/usr/lib/crtbegin_so.o":   nil,
435		"prebuilts/ndk/current/platforms/android-29/arch-arm/usr/lib/crtend_so.o":     nil,
436	}
437
438	ctx, _ := testJavaWithFS(t, bp, fs)
439
440	inputs := ctx.ModuleForTests("libjni", "android_arm64_armv8-a_sdk_shared").Description("link").Implicits
441	var crtbeginFound, crtendFound bool
442	expectedCrtBegin := ctx.ModuleForTests("crtbegin_so",
443		"android_arm64_armv8-a_sdk_29").Rule("noAddrSig").Output
444	expectedCrtEnd := ctx.ModuleForTests("crtend_so",
445		"android_arm64_armv8-a_sdk_29").Rule("noAddrSig").Output
446	implicits := []string{}
447	for _, input := range inputs {
448		implicits = append(implicits, input.String())
449		if strings.HasSuffix(input.String(), expectedCrtBegin.String()) {
450			crtbeginFound = true
451		} else if strings.HasSuffix(input.String(), expectedCrtEnd.String()) {
452			crtendFound = true
453		}
454	}
455	if !crtbeginFound {
456		t.Error(fmt.Sprintf(
457			"expected implicit with suffix %q, have the following implicits:\n%s",
458			expectedCrtBegin, strings.Join(implicits, "\n")))
459	}
460	if !crtendFound {
461		t.Error(fmt.Sprintf(
462			"expected implicit with suffix %q, have the following implicits:\n%s",
463			expectedCrtEnd, strings.Join(implicits, "\n")))
464	}
465}
466
467func TestUpdatableApps_ErrorIfJniLibDoesntSupportMinSdkVersion(t *testing.T) {
468	bp := cc.GatherRequiredDepsForTest(android.Android) + `
469		android_app {
470			name: "foo",
471			srcs: ["a.java"],
472			updatable: true,
473			sdk_version: "current",
474			min_sdk_version: "29",  // this APK should support 29
475			jni_libs: ["libjni"],
476		}
477
478		cc_library {
479			name: "libjni",
480			stl: "none",
481			sdk_version: "current",
482			min_sdk_version: "current",
483		}
484	`
485	testJavaError(t, `"libjni" .*: min_sdk_version\(current\) is higher than min_sdk_version\(29\)`, bp)
486}
487
488func TestUpdatableApps_ErrorIfDepMinSdkVersionIsHigher(t *testing.T) {
489	bp := cc.GatherRequiredDepsForTest(android.Android) + `
490		android_app {
491			name: "foo",
492			srcs: ["a.java"],
493			updatable: true,
494			sdk_version: "current",
495			min_sdk_version: "29",  // this APK should support 29
496			jni_libs: ["libjni"],
497		}
498
499		cc_library {
500			name: "libjni",
501			stl: "none",
502			shared_libs: ["libbar"],
503			system_shared_libs: [],
504			sdk_version: "27",
505			min_sdk_version: "27",
506		}
507
508		cc_library {
509			name: "libbar",
510			stl: "none",
511			system_shared_libs: [],
512			sdk_version: "current",
513			min_sdk_version: "current",
514		}
515	`
516	testJavaError(t, `"libjni" .*: links "libbar" built against newer API version "current"`, bp)
517}
518
519func TestUpdatableApps_ApplyDefaultUpdatableModuleVersion(t *testing.T) {
520	result := android.GroupFixturePreparers(
521		PrepareForTestWithJavaDefaultModules,
522	).RunTestWithBp(t, `
523		android_app {
524			name: "com.android.foo",
525			srcs: ["a.java"],
526			sdk_version: "current",
527			min_sdk_version: "31",
528			updatable: true,
529		}
530	`)
531	foo := result.ModuleForTests("com.android.foo", "android_common").Rule("manifestFixer")
532	android.AssertStringDoesContain(t,
533		"com.android.foo: expected manifest fixer to set override-placeholder-version to RELEASE_DEFAULT_UPDATABLE_MODULE_VERSION",
534		foo.BuildParams.Args["args"],
535		fmt.Sprintf("--override-placeholder-version %s", testDefaultUpdatableModuleVersion),
536	)
537}
538
539func TestUpdatableApps_ApplyOverrideApexManifestDefaultVersion(t *testing.T) {
540	result := android.GroupFixturePreparers(
541		PrepareForTestWithJavaDefaultModules,
542		android.FixtureMergeEnv(map[string]string{
543			"OVERRIDE_APEX_MANIFEST_DEFAULT_VERSION": "1234",
544		}),
545	).RunTestWithBp(t, `
546		android_app {
547			name: "com.android.foo",
548			srcs: ["a.java"],
549			sdk_version: "current",
550			min_sdk_version: "31",
551			updatable: true,
552		}
553	`)
554	foo := result.ModuleForTests("com.android.foo", "android_common").Rule("manifestFixer")
555	android.AssertStringDoesContain(t,
556		"com.android.foo: expected manifest fixer to set override-placeholder-version to 1234",
557		foo.BuildParams.Args["args"],
558		"--override-placeholder-version 1234",
559	)
560}
561
562func TestResourceDirs(t *testing.T) {
563	testCases := []struct {
564		name      string
565		prop      string
566		resources []string
567	}{
568		{
569			name:      "no resource_dirs",
570			prop:      "",
571			resources: []string{"res/res/values/strings.xml"},
572		},
573		{
574			name:      "resource_dirs",
575			prop:      `resource_dirs: ["res"]`,
576			resources: []string{"res/res/values/strings.xml"},
577		},
578		{
579			name:      "empty resource_dirs",
580			prop:      `resource_dirs: []`,
581			resources: nil,
582		},
583	}
584
585	fs := android.MockFS{
586		"res/res/values/strings.xml": nil,
587	}
588
589	bp := `
590			android_app {
591				name: "foo",
592				sdk_version: "current",
593				%s
594			}
595		`
596
597	for _, testCase := range testCases {
598		t.Run(testCase.name, func(t *testing.T) {
599			result := android.GroupFixturePreparers(
600				PrepareForTestWithJavaDefaultModules,
601				fs.AddToFixture(),
602			).RunTestWithBp(t, fmt.Sprintf(bp, testCase.prop))
603
604			module := result.ModuleForTests("foo", "android_common")
605			resourceList := module.MaybeOutput("aapt2/res.list")
606
607			var resources []string
608			if resourceList.Rule != nil {
609				for _, compiledResource := range resourceList.Inputs.Strings() {
610					resources = append(resources, module.Output(compiledResource).Inputs.Strings()...)
611				}
612			}
613
614			android.AssertDeepEquals(t, "resource files", testCase.resources, resources)
615		})
616	}
617}
618
619func TestLibraryAssets(t *testing.T) {
620	bp := `
621			android_app {
622				name: "foo",
623				sdk_version: "current",
624				static_libs: ["lib1", "lib2", "lib3"],
625			}
626
627			android_library {
628				name: "lib1",
629				sdk_version: "current",
630				asset_dirs: ["assets_a"],
631			}
632
633			android_library {
634				name: "lib2",
635				sdk_version: "current",
636			}
637
638			android_library {
639				name: "lib3",
640				sdk_version: "current",
641				static_libs: ["lib4", "import"],
642			}
643
644			android_library {
645				name: "lib4",
646				sdk_version: "current",
647				asset_dirs: ["assets_b"],
648			}
649
650			android_library {
651				name: "lib5",
652				sdk_version: "current",
653				assets: [
654					"path/to/asset_file_1",
655					"path/to/asset_file_2",
656				],
657			}
658
659			android_library_import {
660				name: "import",
661				sdk_version: "current",
662				aars: ["import.aar"],
663			}
664		`
665
666	testCases := []struct {
667		name               string
668		assetFlag          string
669		assetPackages      []string
670		tmpAssetDirInputs  []string
671		tmpAssetDirOutputs []string
672	}{
673		{
674			name: "foo",
675			// lib1 has its own assets. lib3 doesn't have any, but lib4 and import have assets.
676			assetPackages: []string{
677				"out/soong/.intermediates/foo/android_common/aapt2/package-res.apk",
678				"out/soong/.intermediates/lib1/android_common/assets.zip",
679				"out/soong/.intermediates/lib4/android_common/assets.zip",
680				"out/soong/.intermediates/import/android_common/assets.zip",
681			},
682		},
683		{
684			name:      "lib1",
685			assetFlag: "-A assets_a",
686		},
687		{
688			name: "lib2",
689		},
690		{
691			name: "lib3",
692		},
693		{
694			name:      "lib4",
695			assetFlag: "-A assets_b",
696		},
697		{
698			name:      "lib5",
699			assetFlag: "-A out/soong/.intermediates/lib5/android_common/tmp_asset_dir",
700			tmpAssetDirInputs: []string{
701				"path/to/asset_file_1",
702				"path/to/asset_file_2",
703			},
704			tmpAssetDirOutputs: []string{
705				"out/soong/.intermediates/lib5/android_common/tmp_asset_dir/path/to/asset_file_1",
706				"out/soong/.intermediates/lib5/android_common/tmp_asset_dir/path/to/asset_file_2",
707			},
708		},
709	}
710	ctx := testApp(t, bp)
711
712	for _, test := range testCases {
713		t.Run(test.name, func(t *testing.T) {
714			m := ctx.ModuleForTests(test.name, "android_common")
715
716			// Check asset flag in aapt2 link flags
717			var aapt2link android.TestingBuildParams
718			if len(test.assetPackages) > 0 {
719				aapt2link = m.Output("aapt2/package-res.apk")
720			} else {
721				aapt2link = m.Output("package-res.apk")
722			}
723			aapt2link = aapt2link
724			aapt2Flags := aapt2link.Args["flags"]
725			if test.assetFlag != "" {
726				android.AssertStringDoesContain(t, "asset flag", aapt2Flags, test.assetFlag)
727			} else {
728				android.AssertStringDoesNotContain(t, "aapt2 link flags", aapt2Flags, " -A ")
729			}
730
731			// Check asset merge rule.
732			if len(test.assetPackages) > 0 {
733				mergeAssets := m.Output("package-res.apk")
734				android.AssertPathsRelativeToTopEquals(t, "mergeAssets inputs", test.assetPackages, mergeAssets.Inputs)
735			}
736
737			if len(test.tmpAssetDirInputs) > 0 {
738				rule := m.Rule("tmp_asset_dir")
739				inputs := rule.Implicits
740				outputs := append(android.WritablePaths{rule.Output}, rule.ImplicitOutputs...).Paths()
741				android.AssertPathsRelativeToTopEquals(t, "tmp_asset_dir inputs", test.tmpAssetDirInputs, inputs)
742				android.AssertPathsRelativeToTopEquals(t, "tmp_asset_dir outputs", test.tmpAssetDirOutputs, outputs)
743			}
744		})
745	}
746}
747
748func TestAppJavaResources(t *testing.T) {
749	bp := `
750			android_app {
751				name: "foo",
752				sdk_version: "current",
753				java_resources: ["resources/a"],
754				srcs: ["a.java"],
755			}
756
757			android_app {
758				name: "bar",
759				sdk_version: "current",
760				java_resources: ["resources/a"],
761			}
762		`
763
764	ctx := testApp(t, bp)
765
766	foo := ctx.ModuleForTests("foo", "android_common")
767	fooResources := foo.Output("res/foo.jar")
768	fooDexJar := foo.Output("dex-withres/foo.jar")
769	fooDexJarAligned := foo.Output("dex-withres-aligned/foo.jar")
770	fooApk := foo.Rule("combineApk")
771
772	if g, w := fooDexJar.Inputs.Strings(), fooResources.Output.String(); !android.InList(w, g) {
773		t.Errorf("expected resource jar %q in foo dex jar inputs %q", w, g)
774	}
775
776	if g, w := fooDexJarAligned.Input.String(), fooDexJar.Output.String(); g != w {
777		t.Errorf("expected dex jar %q in foo aligned dex jar inputs %q", w, g)
778	}
779
780	if g, w := fooApk.Inputs.Strings(), fooDexJarAligned.Output.String(); !android.InList(w, g) {
781		t.Errorf("expected aligned dex jar %q in foo apk inputs %q", w, g)
782	}
783
784	bar := ctx.ModuleForTests("bar", "android_common")
785	barResources := bar.Output("res/bar.jar")
786	barApk := bar.Rule("combineApk")
787
788	if g, w := barApk.Inputs.Strings(), barResources.Output.String(); !android.InList(w, g) {
789		t.Errorf("expected resources jar %q in bar apk inputs %q", w, g)
790	}
791}
792
793func TestAndroidResourceProcessor(t *testing.T) {
794	testCases := []struct {
795		name                            string
796		appUsesRP                       bool
797		directLibUsesRP                 bool
798		transitiveLibUsesRP             bool
799		sharedLibUsesRP                 bool
800		sharedTransitiveStaticLibUsesRP bool
801		sharedTransitiveSharedLibUsesRP bool
802
803		dontVerifyApp bool
804		appResources  []string
805		appOverlays   []string
806		appImports    []string
807		appSrcJars    []string
808		appClasspath  []string
809		appCombined   []string
810
811		dontVerifyDirect bool
812		directResources  []string
813		directOverlays   []string
814		directImports    []string
815		directSrcJars    []string
816		directClasspath  []string
817		directCombined   []string
818
819		dontVerifyTransitive bool
820		transitiveResources  []string
821		transitiveOverlays   []string
822		transitiveImports    []string
823		transitiveSrcJars    []string
824		transitiveClasspath  []string
825		transitiveCombined   []string
826
827		dontVerifyDirectImport bool
828		directImportResources  []string
829		directImportOverlays   []string
830		directImportImports    []string
831
832		dontVerifyTransitiveImport bool
833		transitiveImportResources  []string
834		transitiveImportOverlays   []string
835		transitiveImportImports    []string
836
837		dontVerifyShared bool
838		sharedResources  []string
839		sharedOverlays   []string
840		sharedImports    []string
841		sharedSrcJars    []string
842		sharedClasspath  []string
843		sharedCombined   []string
844	}{
845		{
846			// Test with all modules set to use_resource_processor: false (except android_library_import modules,
847			// which always use resource processor).
848			name:                "legacy",
849			appUsesRP:           false,
850			directLibUsesRP:     false,
851			transitiveLibUsesRP: false,
852
853			appResources: nil,
854			appOverlays: []string{
855				"out/soong/.intermediates/transitive/android_common/package-res.apk",
856				"out/soong/.intermediates/transitive_import_dep/android_common/package-res.apk",
857				"out/soong/.intermediates/transitive_import/android_common/package-res.apk",
858				"out/soong/.intermediates/direct/android_common/package-res.apk",
859				"out/soong/.intermediates/direct_import_dep/android_common/package-res.apk",
860				"out/soong/.intermediates/direct_import/android_common/package-res.apk",
861				"out/soong/.intermediates/app/android_common/aapt2/app/res/values_strings.arsc.flat",
862			},
863			appImports: []string{
864				"out/soong/.intermediates/shared/android_common/package-res.apk",
865				"out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk",
866			},
867			appSrcJars: []string{"out/soong/.intermediates/app/android_common/gen/android/R.srcjar"},
868			appClasspath: []string{
869				"out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar",
870				"out/soong/.intermediates/shared/android_common/turbine-combined/shared.jar",
871				"out/soong/.intermediates/direct/android_common/turbine-combined/direct.jar",
872				"out/soong/.intermediates/direct_import/android_common/turbine-combined/direct_import.jar",
873			},
874			appCombined: []string{
875				"out/soong/.intermediates/app/android_common/javac/app.jar",
876				"out/soong/.intermediates/direct/android_common/combined/direct.jar",
877				"out/soong/.intermediates/direct_import/android_common/combined/direct_import.jar",
878			},
879
880			directResources: nil,
881			directOverlays: []string{
882				"out/soong/.intermediates/transitive/android_common/package-res.apk",
883				"out/soong/.intermediates/transitive_import_dep/android_common/package-res.apk",
884				"out/soong/.intermediates/transitive_import/android_common/package-res.apk",
885				"out/soong/.intermediates/direct/android_common/aapt2/direct/res/values_strings.arsc.flat",
886			},
887			directImports: []string{"out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk"},
888			directSrcJars: []string{"out/soong/.intermediates/direct/android_common/gen/android/R.srcjar"},
889			directClasspath: []string{
890				"out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar",
891				"out/soong/.intermediates/transitive/android_common/turbine-combined/transitive.jar",
892				"out/soong/.intermediates/transitive_import/android_common/turbine-combined/transitive_import.jar",
893			},
894			directCombined: []string{
895				"out/soong/.intermediates/direct/android_common/javac/direct.jar",
896				"out/soong/.intermediates/transitive/android_common/javac/transitive.jar",
897				"out/soong/.intermediates/transitive_import/android_common/combined/transitive_import.jar",
898			},
899
900			transitiveResources: []string{"out/soong/.intermediates/transitive/android_common/aapt2/transitive/res/values_strings.arsc.flat"},
901			transitiveOverlays:  nil,
902			transitiveImports:   []string{"out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk"},
903			transitiveSrcJars:   []string{"out/soong/.intermediates/transitive/android_common/gen/android/R.srcjar"},
904			transitiveClasspath: []string{"out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar"},
905			transitiveCombined:  nil,
906
907			sharedResources: nil,
908			sharedOverlays: []string{
909				"out/soong/.intermediates/shared_transitive_static/android_common/package-res.apk",
910				"out/soong/.intermediates/shared/android_common/aapt2/shared/res/values_strings.arsc.flat",
911			},
912			sharedImports: []string{
913				"out/soong/.intermediates/shared_transitive_shared/android_common/package-res.apk",
914				"out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk",
915			},
916			sharedSrcJars: []string{"out/soong/.intermediates/shared/android_common/gen/android/R.srcjar"},
917			sharedClasspath: []string{
918				"out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar",
919				"out/soong/.intermediates/shared_transitive_shared/android_common/turbine-combined/shared_transitive_shared.jar",
920				"out/soong/.intermediates/shared_transitive_static/android_common/turbine-combined/shared_transitive_static.jar",
921			},
922			sharedCombined: []string{
923				"out/soong/.intermediates/shared/android_common/javac/shared.jar",
924				"out/soong/.intermediates/shared_transitive_static/android_common/javac/shared_transitive_static.jar",
925			},
926
927			directImportResources: nil,
928			directImportOverlays:  []string{"out/soong/.intermediates/direct_import/android_common/flat-res/gen_res.flata"},
929			directImportImports: []string{
930				"out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk",
931				"out/soong/.intermediates/direct_import_dep/android_common/package-res.apk",
932			},
933
934			transitiveImportResources: nil,
935			transitiveImportOverlays:  []string{"out/soong/.intermediates/transitive_import/android_common/flat-res/gen_res.flata"},
936			transitiveImportImports: []string{
937				"out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk",
938				"out/soong/.intermediates/transitive_import_dep/android_common/package-res.apk",
939			},
940		},
941		{
942			// Test with all modules set to use_resource_processor: true.
943			name:                            "resource_processor",
944			appUsesRP:                       true,
945			directLibUsesRP:                 true,
946			transitiveLibUsesRP:             true,
947			sharedLibUsesRP:                 true,
948			sharedTransitiveSharedLibUsesRP: true,
949			sharedTransitiveStaticLibUsesRP: true,
950
951			appResources: nil,
952			appOverlays: []string{
953				"out/soong/.intermediates/transitive/android_common/package-res.apk",
954				"out/soong/.intermediates/transitive_import_dep/android_common/package-res.apk",
955				"out/soong/.intermediates/transitive_import/android_common/package-res.apk",
956				"out/soong/.intermediates/direct/android_common/package-res.apk",
957				"out/soong/.intermediates/direct_import_dep/android_common/package-res.apk",
958				"out/soong/.intermediates/direct_import/android_common/package-res.apk",
959				"out/soong/.intermediates/app/android_common/aapt2/app/res/values_strings.arsc.flat",
960			},
961			appImports: []string{
962				"out/soong/.intermediates/shared/android_common/package-res.apk",
963				"out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk",
964			},
965			appSrcJars: nil,
966			appClasspath: []string{
967				"out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar",
968				"out/soong/.intermediates/app/android_common/busybox/R.jar",
969				"out/soong/.intermediates/shared/android_common/turbine-combined/shared.jar",
970				"out/soong/.intermediates/direct/android_common/turbine-combined/direct.jar",
971				"out/soong/.intermediates/direct_import/android_common/turbine-combined/direct_import.jar",
972			},
973			appCombined: []string{
974				"out/soong/.intermediates/app/android_common/javac/app.jar",
975				"out/soong/.intermediates/app/android_common/busybox/R.jar",
976				"out/soong/.intermediates/direct/android_common/combined/direct.jar",
977				"out/soong/.intermediates/direct_import/android_common/combined/direct_import.jar",
978			},
979
980			directResources: nil,
981			directOverlays:  []string{"out/soong/.intermediates/direct/android_common/aapt2/direct/res/values_strings.arsc.flat"},
982			directImports: []string{
983				"out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk",
984				"out/soong/.intermediates/transitive_import/android_common/package-res.apk",
985				"out/soong/.intermediates/transitive_import_dep/android_common/package-res.apk",
986				"out/soong/.intermediates/transitive/android_common/package-res.apk",
987			},
988			directSrcJars: nil,
989			directClasspath: []string{
990				"out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar",
991				"out/soong/.intermediates/direct/android_common/busybox/R.jar",
992				"out/soong/.intermediates/transitive/android_common/busybox/R.jar",
993				"out/soong/.intermediates/transitive_import_dep/android_common/busybox/R.jar",
994				"out/soong/.intermediates/transitive_import/android_common/busybox/R.jar",
995				"out/soong/.intermediates/transitive/android_common/turbine-combined/transitive.jar",
996				"out/soong/.intermediates/transitive_import/android_common/turbine-combined/transitive_import.jar",
997			},
998			directCombined: []string{
999				"out/soong/.intermediates/direct/android_common/javac/direct.jar",
1000				"out/soong/.intermediates/transitive/android_common/javac/transitive.jar",
1001				"out/soong/.intermediates/transitive_import/android_common/combined/transitive_import.jar",
1002			},
1003
1004			transitiveResources: []string{"out/soong/.intermediates/transitive/android_common/aapt2/transitive/res/values_strings.arsc.flat"},
1005			transitiveOverlays:  nil,
1006			transitiveImports:   []string{"out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk"},
1007			transitiveSrcJars:   nil,
1008			transitiveClasspath: []string{
1009				"out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar",
1010				"out/soong/.intermediates/transitive/android_common/busybox/R.jar",
1011			},
1012			transitiveCombined: nil,
1013
1014			sharedResources: nil,
1015			sharedOverlays:  []string{"out/soong/.intermediates/shared/android_common/aapt2/shared/res/values_strings.arsc.flat"},
1016			sharedImports: []string{
1017				"out/soong/.intermediates/shared_transitive_shared/android_common/package-res.apk",
1018				"out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk",
1019				"out/soong/.intermediates/shared_transitive_static/android_common/package-res.apk",
1020			},
1021			sharedSrcJars: nil,
1022			sharedClasspath: []string{
1023				"out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar",
1024				"out/soong/.intermediates/shared/android_common/busybox/R.jar",
1025				"out/soong/.intermediates/shared_transitive_static/android_common/busybox/R.jar",
1026				"out/soong/.intermediates/shared_transitive_shared/android_common/busybox/R.jar",
1027				"out/soong/.intermediates/shared_transitive_shared/android_common/turbine-combined/shared_transitive_shared.jar",
1028				"out/soong/.intermediates/shared_transitive_static/android_common/turbine-combined/shared_transitive_static.jar",
1029			},
1030			sharedCombined: []string{
1031				"out/soong/.intermediates/shared/android_common/javac/shared.jar",
1032				"out/soong/.intermediates/shared_transitive_static/android_common/javac/shared_transitive_static.jar",
1033			},
1034
1035			directImportResources: nil,
1036			directImportOverlays:  []string{"out/soong/.intermediates/direct_import/android_common/flat-res/gen_res.flata"},
1037			directImportImports: []string{
1038				"out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk",
1039				"out/soong/.intermediates/direct_import_dep/android_common/package-res.apk",
1040			},
1041
1042			transitiveImportResources: nil,
1043			transitiveImportOverlays:  []string{"out/soong/.intermediates/transitive_import/android_common/flat-res/gen_res.flata"},
1044			transitiveImportImports: []string{
1045				"out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk",
1046				"out/soong/.intermediates/transitive_import_dep/android_common/package-res.apk",
1047			},
1048		}, {
1049			// Test an app building with resource processor enabled but with dependencies built without
1050			// resource processor.
1051			name:                "app_resource_processor",
1052			appUsesRP:           true,
1053			directLibUsesRP:     false,
1054			transitiveLibUsesRP: false,
1055
1056			appResources: nil,
1057			appOverlays: []string{
1058				"out/soong/.intermediates/transitive/android_common/package-res.apk",
1059				"out/soong/.intermediates/transitive_import_dep/android_common/package-res.apk",
1060				"out/soong/.intermediates/transitive_import/android_common/package-res.apk",
1061				"out/soong/.intermediates/direct/android_common/package-res.apk",
1062				"out/soong/.intermediates/direct_import_dep/android_common/package-res.apk",
1063				"out/soong/.intermediates/direct_import/android_common/package-res.apk",
1064				"out/soong/.intermediates/app/android_common/aapt2/app/res/values_strings.arsc.flat",
1065			},
1066			appImports: []string{
1067				"out/soong/.intermediates/shared/android_common/package-res.apk",
1068				"out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk",
1069			},
1070			appSrcJars: nil,
1071			appClasspath: []string{
1072				"out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar",
1073				// R.jar has to come before direct.jar
1074				"out/soong/.intermediates/app/android_common/busybox/R.jar",
1075				"out/soong/.intermediates/shared/android_common/turbine-combined/shared.jar",
1076				"out/soong/.intermediates/direct/android_common/turbine-combined/direct.jar",
1077				"out/soong/.intermediates/direct_import/android_common/turbine-combined/direct_import.jar",
1078			},
1079			appCombined: []string{
1080				"out/soong/.intermediates/app/android_common/javac/app.jar",
1081				"out/soong/.intermediates/app/android_common/busybox/R.jar",
1082				"out/soong/.intermediates/direct/android_common/combined/direct.jar",
1083				"out/soong/.intermediates/direct_import/android_common/combined/direct_import.jar",
1084			},
1085
1086			dontVerifyDirect:           true,
1087			dontVerifyTransitive:       true,
1088			dontVerifyShared:           true,
1089			dontVerifyDirectImport:     true,
1090			dontVerifyTransitiveImport: true,
1091		},
1092		{
1093			// Test an app building without resource processor enabled but with a dependency built with
1094			// resource processor.
1095			name:                "app_dependency_lib_resource_processor",
1096			appUsesRP:           false,
1097			directLibUsesRP:     true,
1098			transitiveLibUsesRP: false,
1099
1100			appOverlays: []string{
1101				"out/soong/.intermediates/transitive/android_common/package-res.apk",
1102				"out/soong/.intermediates/transitive_import_dep/android_common/package-res.apk",
1103				"out/soong/.intermediates/transitive_import/android_common/package-res.apk",
1104				"out/soong/.intermediates/direct/android_common/package-res.apk",
1105				"out/soong/.intermediates/direct_import_dep/android_common/package-res.apk",
1106				"out/soong/.intermediates/direct_import/android_common/package-res.apk",
1107				"out/soong/.intermediates/app/android_common/aapt2/app/res/values_strings.arsc.flat",
1108			},
1109			appImports: []string{
1110				"out/soong/.intermediates/shared/android_common/package-res.apk",
1111				"out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk",
1112			},
1113			appSrcJars: []string{"out/soong/.intermediates/app/android_common/gen/android/R.srcjar"},
1114			appClasspath: []string{
1115				"out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar",
1116				"out/soong/.intermediates/shared/android_common/turbine-combined/shared.jar",
1117				"out/soong/.intermediates/direct/android_common/turbine-combined/direct.jar",
1118				"out/soong/.intermediates/direct_import/android_common/turbine-combined/direct_import.jar",
1119			},
1120			appCombined: []string{
1121				"out/soong/.intermediates/app/android_common/javac/app.jar",
1122				"out/soong/.intermediates/direct/android_common/combined/direct.jar",
1123				"out/soong/.intermediates/direct_import/android_common/combined/direct_import.jar",
1124			},
1125
1126			directResources: nil,
1127			directOverlays:  []string{"out/soong/.intermediates/direct/android_common/aapt2/direct/res/values_strings.arsc.flat"},
1128			directImports: []string{
1129				"out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk",
1130				"out/soong/.intermediates/transitive_import/android_common/package-res.apk",
1131				"out/soong/.intermediates/transitive_import_dep/android_common/package-res.apk",
1132				"out/soong/.intermediates/transitive/android_common/package-res.apk",
1133			},
1134			directSrcJars: nil,
1135			directClasspath: []string{
1136				"out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar",
1137				"out/soong/.intermediates/direct/android_common/busybox/R.jar",
1138				"out/soong/.intermediates/transitive_import_dep/android_common/busybox/R.jar",
1139				"out/soong/.intermediates/transitive_import/android_common/busybox/R.jar",
1140				"out/soong/.intermediates/transitive/android_common/turbine-combined/transitive.jar",
1141				"out/soong/.intermediates/transitive_import/android_common/turbine-combined/transitive_import.jar",
1142			},
1143			directCombined: []string{
1144				"out/soong/.intermediates/direct/android_common/javac/direct.jar",
1145				"out/soong/.intermediates/transitive/android_common/javac/transitive.jar",
1146				"out/soong/.intermediates/transitive_import/android_common/combined/transitive_import.jar",
1147			},
1148
1149			dontVerifyTransitive:       true,
1150			dontVerifyShared:           true,
1151			dontVerifyDirectImport:     true,
1152			dontVerifyTransitiveImport: true,
1153		},
1154		{
1155			// Test a library building without resource processor enabled but with a dependency built with
1156			// resource processor.
1157			name:                "lib_dependency_lib_resource_processor",
1158			appUsesRP:           false,
1159			directLibUsesRP:     false,
1160			transitiveLibUsesRP: true,
1161
1162			appOverlays: []string{
1163				"out/soong/.intermediates/transitive/android_common/package-res.apk",
1164				"out/soong/.intermediates/transitive_import_dep/android_common/package-res.apk",
1165				"out/soong/.intermediates/transitive_import/android_common/package-res.apk",
1166				"out/soong/.intermediates/direct/android_common/package-res.apk",
1167				"out/soong/.intermediates/direct_import_dep/android_common/package-res.apk",
1168				"out/soong/.intermediates/direct_import/android_common/package-res.apk",
1169				"out/soong/.intermediates/app/android_common/aapt2/app/res/values_strings.arsc.flat",
1170			},
1171			appImports: []string{
1172				"out/soong/.intermediates/shared/android_common/package-res.apk",
1173				"out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk",
1174			},
1175			appSrcJars: []string{"out/soong/.intermediates/app/android_common/gen/android/R.srcjar"},
1176			appClasspath: []string{
1177				"out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar",
1178				"out/soong/.intermediates/shared/android_common/turbine-combined/shared.jar",
1179				"out/soong/.intermediates/direct/android_common/turbine-combined/direct.jar",
1180				"out/soong/.intermediates/direct_import/android_common/turbine-combined/direct_import.jar",
1181			},
1182			appCombined: []string{
1183				"out/soong/.intermediates/app/android_common/javac/app.jar",
1184				"out/soong/.intermediates/direct/android_common/combined/direct.jar",
1185				"out/soong/.intermediates/direct_import/android_common/combined/direct_import.jar",
1186			},
1187
1188			directResources: nil,
1189			directOverlays: []string{
1190				"out/soong/.intermediates/transitive/android_common/package-res.apk",
1191				"out/soong/.intermediates/transitive_import_dep/android_common/package-res.apk",
1192				"out/soong/.intermediates/transitive_import/android_common/package-res.apk",
1193				"out/soong/.intermediates/direct/android_common/aapt2/direct/res/values_strings.arsc.flat",
1194			},
1195			directImports: []string{"out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk"},
1196			directSrcJars: []string{"out/soong/.intermediates/direct/android_common/gen/android/R.srcjar"},
1197			directClasspath: []string{
1198				"out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar",
1199				"out/soong/.intermediates/transitive/android_common/turbine-combined/transitive.jar",
1200				"out/soong/.intermediates/transitive_import/android_common/turbine-combined/transitive_import.jar",
1201			},
1202			directCombined: []string{
1203				"out/soong/.intermediates/direct/android_common/javac/direct.jar",
1204				"out/soong/.intermediates/transitive/android_common/javac/transitive.jar",
1205				"out/soong/.intermediates/transitive_import/android_common/combined/transitive_import.jar",
1206			},
1207
1208			transitiveResources: []string{"out/soong/.intermediates/transitive/android_common/aapt2/transitive/res/values_strings.arsc.flat"},
1209			transitiveOverlays:  nil,
1210			transitiveImports:   []string{"out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk"},
1211			transitiveSrcJars:   nil,
1212			transitiveClasspath: []string{
1213				"out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar",
1214				"out/soong/.intermediates/transitive/android_common/busybox/R.jar",
1215			},
1216			transitiveCombined: nil,
1217
1218			dontVerifyShared:           true,
1219			dontVerifyDirectImport:     true,
1220			dontVerifyTransitiveImport: true,
1221		},
1222	}
1223
1224	for _, testCase := range testCases {
1225		t.Run(testCase.name, func(t *testing.T) {
1226			bp := fmt.Sprintf(`
1227				android_app {
1228					name: "app",
1229					sdk_version: "current",
1230					srcs: ["app/app.java"],
1231					resource_dirs: ["app/res"],
1232					manifest: "app/AndroidManifest.xml",
1233					libs: ["shared"],
1234					static_libs: ["direct", "direct_import"],
1235					use_resource_processor: %v,
1236				}
1237
1238				android_library {
1239					name: "direct",
1240					sdk_version: "current",
1241					srcs: ["direct/direct.java"],
1242					resource_dirs: ["direct/res"],
1243					manifest: "direct/AndroidManifest.xml",
1244					static_libs: ["transitive", "transitive_import"],
1245					use_resource_processor: %v,
1246				}
1247
1248				android_library {
1249					name: "transitive",
1250					sdk_version: "current",
1251					srcs: ["transitive/transitive.java"],
1252					resource_dirs: ["transitive/res"],
1253					manifest: "transitive/AndroidManifest.xml",
1254					use_resource_processor: %v,
1255				}
1256
1257				android_library {
1258					name: "shared",
1259					sdk_version: "current",
1260					srcs: ["shared/shared.java"],
1261					resource_dirs: ["shared/res"],
1262					manifest: "shared/AndroidManifest.xml",
1263					use_resource_processor: %v,
1264					libs: ["shared_transitive_shared"],
1265					static_libs: ["shared_transitive_static"],
1266				}
1267
1268				android_library {
1269					name: "shared_transitive_shared",
1270					sdk_version: "current",
1271					srcs: ["shared_transitive_shared/shared_transitive_shared.java"],
1272					resource_dirs: ["shared_transitive_shared/res"],
1273					manifest: "shared_transitive_shared/AndroidManifest.xml",
1274					use_resource_processor: %v,
1275				}
1276
1277				android_library {
1278					name: "shared_transitive_static",
1279					sdk_version: "current",
1280					srcs: ["shared_transitive_static/shared.java"],
1281					resource_dirs: ["shared_transitive_static/res"],
1282					manifest: "shared_transitive_static/AndroidManifest.xml",
1283					use_resource_processor: %v,
1284				}
1285
1286				android_library_import {
1287					name: "direct_import",
1288					sdk_version: "current",
1289					aars: ["direct_import.aar"],
1290					static_libs: ["direct_import_dep"],
1291				}
1292
1293				android_library_import {
1294					name: "direct_import_dep",
1295					sdk_version: "current",
1296					aars: ["direct_import_dep.aar"],
1297				}
1298
1299				android_library_import {
1300					name: "transitive_import",
1301					sdk_version: "current",
1302					aars: ["transitive_import.aar"],
1303					static_libs: ["transitive_import_dep"],
1304				}
1305
1306				android_library_import {
1307					name: "transitive_import_dep",
1308					sdk_version: "current",
1309					aars: ["transitive_import_dep.aar"],
1310				}
1311			`, testCase.appUsesRP, testCase.directLibUsesRP, testCase.transitiveLibUsesRP,
1312				testCase.sharedLibUsesRP, testCase.sharedTransitiveSharedLibUsesRP, testCase.sharedTransitiveStaticLibUsesRP)
1313
1314			fs := android.MockFS{
1315				"app/res/values/strings.xml":                      nil,
1316				"direct/res/values/strings.xml":                   nil,
1317				"transitive/res/values/strings.xml":               nil,
1318				"shared/res/values/strings.xml":                   nil,
1319				"shared_transitive_static/res/values/strings.xml": nil,
1320				"shared_transitive_shared/res/values/strings.xml": nil,
1321			}
1322
1323			result := android.GroupFixturePreparers(
1324				PrepareForTestWithJavaDefaultModules,
1325				fs.AddToFixture(),
1326			).RunTestWithBp(t, bp)
1327
1328			type aaptInfo struct {
1329				resources, overlays, imports, srcJars, classpath, combined android.Paths
1330			}
1331
1332			getAaptInfo := func(moduleName string) (aaptInfo aaptInfo) {
1333				mod := result.ModuleForTests(moduleName, "android_common")
1334				resourceListRule := mod.MaybeOutput("aapt2/res.list")
1335				overlayListRule := mod.MaybeOutput("aapt2/overlay.list")
1336				aaptRule := mod.Rule("aapt2Link")
1337				javacRule := mod.MaybeRule("javac")
1338				combinedRule := mod.MaybeOutput("combined/" + moduleName + ".jar")
1339
1340				aaptInfo.resources = resourceListRule.Inputs
1341				aaptInfo.overlays = overlayListRule.Inputs
1342
1343				aaptFlags := strings.Split(aaptRule.Args["flags"], " ")
1344				for i, flag := range aaptFlags {
1345					if flag == "-I" && i+1 < len(aaptFlags) {
1346						aaptInfo.imports = append(aaptInfo.imports, android.PathForTesting(aaptFlags[i+1]))
1347					}
1348				}
1349
1350				if len(javacRule.Args["srcJars"]) > 0 {
1351					aaptInfo.srcJars = android.PathsForTesting(strings.Split(javacRule.Args["srcJars"], " ")...)
1352				}
1353
1354				if len(javacRule.Args["classpath"]) > 0 {
1355					classpathArg := strings.TrimPrefix(javacRule.Args["classpath"], "-classpath ")
1356					aaptInfo.classpath = android.PathsForTesting(strings.Split(classpathArg, ":")...)
1357				}
1358
1359				aaptInfo.combined = combinedRule.Inputs
1360				return
1361			}
1362
1363			app := getAaptInfo("app")
1364			direct := getAaptInfo("direct")
1365			transitive := getAaptInfo("transitive")
1366			shared := getAaptInfo("shared")
1367			directImport := getAaptInfo("direct_import")
1368			transitiveImport := getAaptInfo("transitive_import")
1369
1370			if !testCase.dontVerifyApp {
1371				android.AssertPathsRelativeToTopEquals(t, "app resources", testCase.appResources, app.resources)
1372				android.AssertPathsRelativeToTopEquals(t, "app overlays", testCase.appOverlays, app.overlays)
1373				android.AssertPathsRelativeToTopEquals(t, "app imports", testCase.appImports, app.imports)
1374				android.AssertPathsRelativeToTopEquals(t, "app srcjars", testCase.appSrcJars, app.srcJars)
1375				android.AssertPathsRelativeToTopEquals(t, "app classpath", testCase.appClasspath, app.classpath)
1376				android.AssertPathsRelativeToTopEquals(t, "app combined", testCase.appCombined, app.combined)
1377			}
1378
1379			if !testCase.dontVerifyDirect {
1380				android.AssertPathsRelativeToTopEquals(t, "direct resources", testCase.directResources, direct.resources)
1381				android.AssertPathsRelativeToTopEquals(t, "direct overlays", testCase.directOverlays, direct.overlays)
1382				android.AssertPathsRelativeToTopEquals(t, "direct imports", testCase.directImports, direct.imports)
1383				android.AssertPathsRelativeToTopEquals(t, "direct srcjars", testCase.directSrcJars, direct.srcJars)
1384				android.AssertPathsRelativeToTopEquals(t, "direct classpath", testCase.directClasspath, direct.classpath)
1385				android.AssertPathsRelativeToTopEquals(t, "direct combined", testCase.directCombined, direct.combined)
1386			}
1387
1388			if !testCase.dontVerifyTransitive {
1389				android.AssertPathsRelativeToTopEquals(t, "transitive resources", testCase.transitiveResources, transitive.resources)
1390				android.AssertPathsRelativeToTopEquals(t, "transitive overlays", testCase.transitiveOverlays, transitive.overlays)
1391				android.AssertPathsRelativeToTopEquals(t, "transitive imports", testCase.transitiveImports, transitive.imports)
1392				android.AssertPathsRelativeToTopEquals(t, "transitive srcjars", testCase.transitiveSrcJars, transitive.srcJars)
1393				android.AssertPathsRelativeToTopEquals(t, "transitive classpath", testCase.transitiveClasspath, transitive.classpath)
1394				android.AssertPathsRelativeToTopEquals(t, "transitive combined", testCase.transitiveCombined, transitive.combined)
1395			}
1396
1397			if !testCase.dontVerifyShared {
1398				android.AssertPathsRelativeToTopEquals(t, "shared resources", testCase.sharedResources, shared.resources)
1399				android.AssertPathsRelativeToTopEquals(t, "shared overlays", testCase.sharedOverlays, shared.overlays)
1400				android.AssertPathsRelativeToTopEquals(t, "shared imports", testCase.sharedImports, shared.imports)
1401				android.AssertPathsRelativeToTopEquals(t, "shared srcjars", testCase.sharedSrcJars, shared.srcJars)
1402				android.AssertPathsRelativeToTopEquals(t, "shared classpath", testCase.sharedClasspath, shared.classpath)
1403				android.AssertPathsRelativeToTopEquals(t, "shared combined", testCase.sharedCombined, shared.combined)
1404			}
1405
1406			if !testCase.dontVerifyDirectImport {
1407				android.AssertPathsRelativeToTopEquals(t, "direct_import resources", testCase.directImportResources, directImport.resources)
1408				android.AssertPathsRelativeToTopEquals(t, "direct_import overlays", testCase.directImportOverlays, directImport.overlays)
1409				android.AssertPathsRelativeToTopEquals(t, "direct_import imports", testCase.directImportImports, directImport.imports)
1410			}
1411
1412			if !testCase.dontVerifyTransitiveImport {
1413				android.AssertPathsRelativeToTopEquals(t, "transitive_import resources", testCase.transitiveImportResources, transitiveImport.resources)
1414				android.AssertPathsRelativeToTopEquals(t, "transitive_import overlays", testCase.transitiveImportOverlays, transitiveImport.overlays)
1415				android.AssertPathsRelativeToTopEquals(t, "transitive_import imports", testCase.transitiveImportImports, transitiveImport.imports)
1416			}
1417		})
1418	}
1419}
1420
1421func TestAndroidResourceOverlays(t *testing.T) {
1422	type moduleAndVariant struct {
1423		module  string
1424		variant string
1425	}
1426
1427	testCases := []struct {
1428		name                       string
1429		enforceRROTargets          []string
1430		enforceRROExcludedOverlays []string
1431		resourceFiles              map[moduleAndVariant][]string
1432		overlayFiles               map[moduleAndVariant][]string
1433		rroDirs                    map[moduleAndVariant][]string
1434	}{
1435		{
1436			name:                       "no RRO",
1437			enforceRROTargets:          nil,
1438			enforceRROExcludedOverlays: nil,
1439			resourceFiles: map[moduleAndVariant][]string{
1440				{"foo", "android_common"}:  nil,
1441				{"bar", "android_common"}:  {"bar/res/res/values/strings.xml"},
1442				{"lib", "android_common"}:  nil,
1443				{"lib2", "android_common"}: {"lib2/res/res/values/strings.xml"},
1444			},
1445			overlayFiles: map[moduleAndVariant][]string{
1446				{"foo", "android_common"}: {
1447					"out/soong/.intermediates/lib2/android_common/package-res.apk",
1448					"out/soong/.intermediates/lib/android_common/package-res.apk",
1449					"out/soong/.intermediates/lib3/android_common/package-res.apk",
1450					"foo/res/res/values/strings.xml",
1451					"device/vendor/blah/static_overlay/foo/res/values/strings.xml",
1452					"device/vendor/blah/overlay/foo/res/values/strings.xml",
1453					"product/vendor/blah/overlay/foo/res/values/strings.xml",
1454				},
1455				{"bar", "android_common"}: {
1456					"device/vendor/blah/static_overlay/bar/res/values/strings.xml",
1457					"device/vendor/blah/overlay/bar/res/values/strings.xml",
1458				},
1459				{"lib", "android_common"}: {
1460					"out/soong/.intermediates/lib2/android_common/package-res.apk",
1461					"lib/res/res/values/strings.xml",
1462					"device/vendor/blah/overlay/lib/res/values/strings.xml",
1463				},
1464			},
1465			rroDirs: map[moduleAndVariant][]string{
1466				{"foo", "android_common"}: nil,
1467				{"bar", "android_common"}: nil,
1468			},
1469		},
1470		{
1471			name:                       "enforce RRO on foo",
1472			enforceRROTargets:          []string{"foo"},
1473			enforceRROExcludedOverlays: []string{"device/vendor/blah/static_overlay"},
1474			resourceFiles: map[moduleAndVariant][]string{
1475				{"foo", "android_common"}:      nil,
1476				{"bar", "android_common"}:      {"bar/res/res/values/strings.xml"},
1477				{"lib", "android_common"}:      nil,
1478				{"lib", "android_common_rro"}:  nil,
1479				{"lib2", "android_common"}:     {"lib2/res/res/values/strings.xml"},
1480				{"lib2", "android_common_rro"}: {"lib2/res/res/values/strings.xml"},
1481			},
1482			overlayFiles: map[moduleAndVariant][]string{
1483				{"foo", "android_common"}: {
1484					"out/soong/.intermediates/lib2/android_common_rro/package-res.apk",
1485					"out/soong/.intermediates/lib/android_common_rro/package-res.apk",
1486					"out/soong/.intermediates/lib3/android_common_rro/package-res.apk",
1487					"foo/res/res/values/strings.xml",
1488					"device/vendor/blah/static_overlay/foo/res/values/strings.xml",
1489				},
1490				{"bar", "android_common"}: {
1491					"device/vendor/blah/static_overlay/bar/res/values/strings.xml",
1492					"device/vendor/blah/overlay/bar/res/values/strings.xml",
1493				},
1494				{"lib", "android_common"}: {
1495					"out/soong/.intermediates/lib2/android_common/package-res.apk",
1496					"lib/res/res/values/strings.xml",
1497					"device/vendor/blah/overlay/lib/res/values/strings.xml",
1498				},
1499				{"lib", "android_common_rro"}: {
1500					"out/soong/.intermediates/lib2/android_common_rro/package-res.apk",
1501					"lib/res/res/values/strings.xml",
1502				},
1503			},
1504
1505			rroDirs: map[moduleAndVariant][]string{
1506				{"foo", "android_common"}: {
1507					"device:device/vendor/blah/overlay/foo/res",
1508					"product:product/vendor/blah/overlay/foo/res",
1509					"device:device/vendor/blah/overlay/lib/res",
1510				},
1511				{"bar", "android_common"}:     nil,
1512				{"lib", "android_common"}:     nil,
1513				{"lib", "android_common_rro"}: {"device:device/vendor/blah/overlay/lib/res"},
1514			},
1515		},
1516		{
1517			name:              "enforce RRO on all",
1518			enforceRROTargets: []string{"*"},
1519			enforceRROExcludedOverlays: []string{
1520				// Excluding specific apps/res directories also allowed.
1521				"device/vendor/blah/static_overlay/foo",
1522				"device/vendor/blah/static_overlay/bar/res",
1523			},
1524			resourceFiles: map[moduleAndVariant][]string{
1525				{"foo", "android_common"}:  nil,
1526				{"bar", "android_common"}:  {"bar/res/res/values/strings.xml"},
1527				{"lib", "android_common"}:  nil,
1528				{"lib2", "android_common"}: {"lib2/res/res/values/strings.xml"},
1529			},
1530			overlayFiles: map[moduleAndVariant][]string{
1531				{"foo", "android_common"}: {
1532					"out/soong/.intermediates/lib2/android_common/package-res.apk",
1533					"out/soong/.intermediates/lib/android_common/package-res.apk",
1534					"out/soong/.intermediates/lib3/android_common/package-res.apk",
1535					"foo/res/res/values/strings.xml",
1536					"device/vendor/blah/static_overlay/foo/res/values/strings.xml",
1537				},
1538				{"bar", "android_common"}: {"device/vendor/blah/static_overlay/bar/res/values/strings.xml"},
1539				{"lib", "android_common"}: {
1540					"out/soong/.intermediates/lib2/android_common/package-res.apk",
1541					"lib/res/res/values/strings.xml",
1542				},
1543			},
1544			rroDirs: map[moduleAndVariant][]string{
1545				{"foo", "android_common"}: {
1546					"device:device/vendor/blah/overlay/foo/res",
1547					"product:product/vendor/blah/overlay/foo/res",
1548					// Lib dep comes after the direct deps
1549					"device:device/vendor/blah/overlay/lib/res",
1550				},
1551				{"bar", "android_common"}: {"device:device/vendor/blah/overlay/bar/res"},
1552				{"lib", "android_common"}: {"device:device/vendor/blah/overlay/lib/res"},
1553			},
1554		},
1555	}
1556
1557	deviceResourceOverlays := []string{
1558		"device/vendor/blah/overlay",
1559		"device/vendor/blah/overlay2",
1560		"device/vendor/blah/static_overlay",
1561	}
1562
1563	productResourceOverlays := []string{
1564		"product/vendor/blah/overlay",
1565	}
1566
1567	fs := android.MockFS{
1568		"foo/res/res/values/strings.xml":                               nil,
1569		"bar/res/res/values/strings.xml":                               nil,
1570		"lib/res/res/values/strings.xml":                               nil,
1571		"lib2/res/res/values/strings.xml":                              nil,
1572		"device/vendor/blah/overlay/foo/res/values/strings.xml":        nil,
1573		"device/vendor/blah/overlay/bar/res/values/strings.xml":        nil,
1574		"device/vendor/blah/overlay/lib/res/values/strings.xml":        nil,
1575		"device/vendor/blah/static_overlay/foo/res/values/strings.xml": nil,
1576		"device/vendor/blah/static_overlay/bar/res/values/strings.xml": nil,
1577		"device/vendor/blah/overlay2/res/values/strings.xml":           nil,
1578		"product/vendor/blah/overlay/foo/res/values/strings.xml":       nil,
1579	}
1580
1581	bp := `
1582			android_app {
1583				name: "foo",
1584				sdk_version: "current",
1585				resource_dirs: ["foo/res"],
1586				static_libs: ["lib", "lib3"],
1587			}
1588
1589			android_app {
1590				name: "bar",
1591				sdk_version: "current",
1592				resource_dirs: ["bar/res"],
1593			}
1594
1595			android_library {
1596				name: "lib",
1597				sdk_version: "current",
1598				resource_dirs: ["lib/res"],
1599				static_libs: ["lib2"],
1600			}
1601
1602			android_library {
1603				name: "lib2",
1604				sdk_version: "current",
1605				resource_dirs: ["lib2/res"],
1606			}
1607
1608			// This library has the same resources as lib (should not lead to dupe RROs)
1609			android_library {
1610				name: "lib3",
1611				sdk_version: "current",
1612				resource_dirs: ["lib/res"]
1613			}
1614		`
1615
1616	for _, testCase := range testCases {
1617		t.Run(testCase.name, func(t *testing.T) {
1618			result := android.GroupFixturePreparers(
1619				PrepareForTestWithJavaDefaultModules,
1620				fs.AddToFixture(),
1621				android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
1622					variables.DeviceResourceOverlays = deviceResourceOverlays
1623					variables.ProductResourceOverlays = productResourceOverlays
1624					if testCase.enforceRROTargets != nil {
1625						variables.EnforceRROTargets = testCase.enforceRROTargets
1626					}
1627					if testCase.enforceRROExcludedOverlays != nil {
1628						variables.EnforceRROExcludedOverlays = testCase.enforceRROExcludedOverlays
1629					}
1630				}),
1631			).RunTestWithBp(t, bp)
1632
1633			resourceListToFiles := func(module android.TestingModule, list []string) (files []string) {
1634				for _, o := range list {
1635					res := module.MaybeOutput(o)
1636					if res.Rule != nil {
1637						// If the overlay is compiled as part of this moduleAndVariant (i.e. a .arsc.flat file),
1638						// verify the inputs to the .arsc.flat rule.
1639						files = append(files, res.Inputs.Strings()...)
1640					} else {
1641						// Otherwise, verify the full path to the output of the other moduleAndVariant
1642						files = append(files, o)
1643					}
1644				}
1645				return files
1646			}
1647
1648			getResources := func(moduleName, variantName string) (resourceFiles, overlayFiles, rroDirs []string) {
1649				module := result.ModuleForTests(moduleName, variantName)
1650				resourceList := module.MaybeOutput("aapt2/res.list")
1651				if resourceList.Rule != nil {
1652					resourceFiles = resourceListToFiles(module, android.PathsRelativeToTop(resourceList.Inputs))
1653				}
1654				overlayList := module.MaybeOutput("aapt2/overlay.list")
1655				if overlayList.Rule != nil {
1656					overlayFiles = resourceListToFiles(module, android.PathsRelativeToTop(overlayList.Inputs))
1657				}
1658
1659				for _, d := range module.Module().(AndroidLibraryDependency).RRODirsDepSet().ToList() {
1660					var prefix string
1661					if d.overlayType == device {
1662						prefix = "device:"
1663					} else if d.overlayType == product {
1664						prefix = "product:"
1665					} else {
1666						t.Fatalf("Unexpected overlayType %d", d.overlayType)
1667					}
1668					rroDirs = append(rroDirs, prefix+android.PathRelativeToTop(d.path))
1669				}
1670
1671				return resourceFiles, overlayFiles, rroDirs
1672			}
1673
1674			modules := []moduleAndVariant{
1675				{"foo", "android_common"},
1676				{"foo", "android_common_rro"},
1677				{"bar", "android_common"},
1678				{"bar", "android_common_rro"},
1679				{"lib", "android_common"},
1680				{"lib", "android_common_rro"},
1681				{"lib2", "android_common"},
1682				{"lib2", "android_common_rro"},
1683			}
1684			for _, moduleAndVariant := range modules {
1685				if _, exists := testCase.resourceFiles[moduleAndVariant]; !exists {
1686					continue
1687				}
1688				resourceFiles, overlayFiles, rroDirs := getResources(moduleAndVariant.module, moduleAndVariant.variant)
1689
1690				if !reflect.DeepEqual(resourceFiles, testCase.resourceFiles[moduleAndVariant]) {
1691					t.Errorf("expected %s resource files:\n  %#v\n got:\n  %#v",
1692						moduleAndVariant, testCase.resourceFiles[moduleAndVariant], resourceFiles)
1693				}
1694				if !reflect.DeepEqual(overlayFiles, testCase.overlayFiles[moduleAndVariant]) {
1695					t.Errorf("expected %s overlay files:\n  %#v\n got:\n  %#v",
1696						moduleAndVariant, testCase.overlayFiles[moduleAndVariant], overlayFiles)
1697				}
1698				if !reflect.DeepEqual(rroDirs, testCase.rroDirs[moduleAndVariant]) {
1699					t.Errorf("expected %s rroDirs:  %#v\n got:\n  %#v",
1700						moduleAndVariant, testCase.rroDirs[moduleAndVariant], rroDirs)
1701				}
1702			}
1703		})
1704	}
1705}
1706
1707func checkSdkVersion(t *testing.T, result *android.TestResult, expectedSdkVersion string) {
1708	foo := result.ModuleForTests("foo", "android_common")
1709	link := foo.Output("package-res.apk")
1710	linkFlags := strings.Split(link.Args["flags"], " ")
1711	min := android.IndexList("--min-sdk-version", linkFlags)
1712	target := android.IndexList("--target-sdk-version", linkFlags)
1713
1714	if min == -1 || target == -1 || min == len(linkFlags)-1 || target == len(linkFlags)-1 {
1715		t.Fatalf("missing --min-sdk-version or --target-sdk-version in link flags: %q", linkFlags)
1716	}
1717
1718	gotMinSdkVersion := linkFlags[min+1]
1719	gotTargetSdkVersion := linkFlags[target+1]
1720
1721	android.AssertStringEquals(t, "incorrect --min-sdk-version", expectedSdkVersion, gotMinSdkVersion)
1722
1723	android.AssertStringEquals(t, "incorrect --target-sdk-version", expectedSdkVersion, gotTargetSdkVersion)
1724}
1725
1726func TestAppSdkVersion(t *testing.T) {
1727	testCases := []struct {
1728		name                  string
1729		sdkVersion            string
1730		platformSdkInt        int
1731		platformSdkCodename   string
1732		platformSdkFinal      bool
1733		minSdkVersionBp       string
1734		expectedMinSdkVersion string
1735		platformApis          bool
1736		activeCodenames       []string
1737	}{
1738		{
1739			name:                  "current final SDK",
1740			sdkVersion:            "current",
1741			platformSdkInt:        27,
1742			platformSdkCodename:   "REL",
1743			platformSdkFinal:      true,
1744			expectedMinSdkVersion: "27",
1745		},
1746		{
1747			name:                  "current non-final SDK",
1748			sdkVersion:            "current",
1749			platformSdkInt:        27,
1750			platformSdkCodename:   "OMR1",
1751			platformSdkFinal:      false,
1752			expectedMinSdkVersion: "OMR1",
1753			activeCodenames:       []string{"OMR1"},
1754		},
1755		{
1756			name:                  "default final SDK",
1757			sdkVersion:            "",
1758			platformApis:          true,
1759			platformSdkInt:        27,
1760			platformSdkCodename:   "REL",
1761			platformSdkFinal:      true,
1762			expectedMinSdkVersion: "27",
1763		},
1764		{
1765			name:                  "default non-final SDK",
1766			sdkVersion:            "",
1767			platformApis:          true,
1768			platformSdkInt:        27,
1769			platformSdkCodename:   "OMR1",
1770			platformSdkFinal:      false,
1771			expectedMinSdkVersion: "OMR1",
1772			activeCodenames:       []string{"OMR1"},
1773		},
1774		{
1775			name:                  "14",
1776			sdkVersion:            "14",
1777			expectedMinSdkVersion: "14",
1778			platformSdkCodename:   "S",
1779			activeCodenames:       []string{"S"},
1780		},
1781		{
1782			name:                  "two active SDKs",
1783			sdkVersion:            "module_current",
1784			minSdkVersionBp:       "UpsideDownCake",
1785			expectedMinSdkVersion: "UpsideDownCake", // And not VanillaIceCream
1786			platformSdkCodename:   "VanillaIceCream",
1787			activeCodenames:       []string{"UpsideDownCake", "VanillaIceCream"},
1788		},
1789	}
1790
1791	for _, moduleType := range []string{"android_app", "android_library"} {
1792		for _, test := range testCases {
1793			t.Run(moduleType+" "+test.name, func(t *testing.T) {
1794				platformApiProp := ""
1795				if test.platformApis {
1796					platformApiProp = "platform_apis: true,"
1797				}
1798				minSdkVersionProp := ""
1799				if test.minSdkVersionBp != "" {
1800					minSdkVersionProp = fmt.Sprintf(` min_sdk_version: "%s",`, test.minSdkVersionBp)
1801				}
1802				bp := fmt.Sprintf(`%s {
1803					name: "foo",
1804					srcs: ["a.java"],
1805					sdk_version: "%s",
1806					%s
1807					%s
1808				}`, moduleType, test.sdkVersion, platformApiProp, minSdkVersionProp)
1809
1810				result := android.GroupFixturePreparers(
1811					prepareForJavaTest,
1812					android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
1813						variables.Platform_sdk_version = &test.platformSdkInt
1814						variables.Platform_sdk_codename = &test.platformSdkCodename
1815						variables.Platform_version_active_codenames = test.activeCodenames
1816						variables.Platform_sdk_final = &test.platformSdkFinal
1817					}),
1818					FixtureWithPrebuiltApis(map[string][]string{
1819						"14": {"foo"},
1820					}),
1821				).RunTestWithBp(t, bp)
1822
1823				checkSdkVersion(t, result, test.expectedMinSdkVersion)
1824			})
1825		}
1826	}
1827}
1828
1829func TestVendorAppSdkVersion(t *testing.T) {
1830	testCases := []struct {
1831		name                                  string
1832		sdkVersion                            string
1833		platformSdkInt                        int
1834		platformSdkCodename                   string
1835		platformSdkFinal                      bool
1836		deviceCurrentApiLevelForVendorModules string
1837		expectedMinSdkVersion                 string
1838	}{
1839		{
1840			name:                                  "current final SDK",
1841			sdkVersion:                            "current",
1842			platformSdkInt:                        29,
1843			platformSdkCodename:                   "REL",
1844			platformSdkFinal:                      true,
1845			deviceCurrentApiLevelForVendorModules: "29",
1846			expectedMinSdkVersion:                 "29",
1847		},
1848		{
1849			name:                                  "current final SDK",
1850			sdkVersion:                            "current",
1851			platformSdkInt:                        29,
1852			platformSdkCodename:                   "REL",
1853			platformSdkFinal:                      true,
1854			deviceCurrentApiLevelForVendorModules: "28",
1855			expectedMinSdkVersion:                 "28",
1856		},
1857		{
1858			name:                                  "current final SDK",
1859			sdkVersion:                            "current",
1860			platformSdkInt:                        29,
1861			platformSdkCodename:                   "Q",
1862			platformSdkFinal:                      false,
1863			deviceCurrentApiLevelForVendorModules: "28",
1864			expectedMinSdkVersion:                 "28",
1865		},
1866	}
1867
1868	for _, moduleType := range []string{"android_app", "android_library"} {
1869		for _, sdkKind := range []string{"", "system_"} {
1870			for _, test := range testCases {
1871				t.Run(moduleType+" "+test.name, func(t *testing.T) {
1872					bp := fmt.Sprintf(`%s {
1873						name: "foo",
1874						srcs: ["a.java"],
1875						sdk_version: "%s%s",
1876						vendor: true,
1877					}`, moduleType, sdkKind, test.sdkVersion)
1878
1879					result := android.GroupFixturePreparers(
1880						prepareForJavaTest,
1881						android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
1882							variables.Platform_sdk_version = &test.platformSdkInt
1883							variables.Platform_sdk_codename = &test.platformSdkCodename
1884							variables.Platform_sdk_final = &test.platformSdkFinal
1885							variables.DeviceCurrentApiLevelForVendorModules = &test.deviceCurrentApiLevelForVendorModules
1886							variables.DeviceSystemSdkVersions = []string{"28", "29"}
1887						}),
1888						FixtureWithPrebuiltApis(map[string][]string{
1889							"28":      {"foo"},
1890							"29":      {"foo"},
1891							"current": {"foo"},
1892						}),
1893					).RunTestWithBp(t, bp)
1894
1895					checkSdkVersion(t, result, test.expectedMinSdkVersion)
1896				})
1897			}
1898		}
1899	}
1900}
1901
1902func TestJNIABI(t *testing.T) {
1903	ctx, _ := testJava(t, cc.GatherRequiredDepsForTest(android.Android)+`
1904		cc_library {
1905			name: "libjni",
1906			system_shared_libs: [],
1907			sdk_version: "current",
1908			stl: "none",
1909		}
1910
1911		android_test {
1912			name: "test",
1913			sdk_version: "core_platform",
1914			jni_libs: ["libjni"],
1915		}
1916
1917		android_test {
1918			name: "test_first",
1919			sdk_version: "core_platform",
1920			compile_multilib: "first",
1921			jni_libs: ["libjni"],
1922		}
1923
1924		android_test {
1925			name: "test_both",
1926			sdk_version: "core_platform",
1927			compile_multilib: "both",
1928			jni_libs: ["libjni"],
1929		}
1930
1931		android_test {
1932			name: "test_32",
1933			sdk_version: "core_platform",
1934			compile_multilib: "32",
1935			jni_libs: ["libjni"],
1936		}
1937
1938		android_test {
1939			name: "test_64",
1940			sdk_version: "core_platform",
1941			compile_multilib: "64",
1942			jni_libs: ["libjni"],
1943		}
1944		`)
1945
1946	testCases := []struct {
1947		name string
1948		abis []string
1949	}{
1950		{"test", []string{"arm64-v8a"}},
1951		{"test_first", []string{"arm64-v8a"}},
1952		{"test_both", []string{"arm64-v8a", "armeabi-v7a"}},
1953		{"test_32", []string{"armeabi-v7a"}},
1954		{"test_64", []string{"arm64-v8a"}},
1955	}
1956
1957	for _, test := range testCases {
1958		t.Run(test.name, func(t *testing.T) {
1959			app := ctx.ModuleForTests(test.name, "android_common")
1960			jniLibZip := app.Output("jnilibs.zip")
1961			var abis []string
1962			args := strings.Fields(jniLibZip.Args["jarArgs"])
1963			for i := 0; i < len(args); i++ {
1964				if args[i] == "-P" {
1965					abis = append(abis, filepath.Base(args[i+1]))
1966					i++
1967				}
1968			}
1969			if !reflect.DeepEqual(abis, test.abis) {
1970				t.Errorf("want abis %v, got %v", test.abis, abis)
1971			}
1972		})
1973	}
1974}
1975
1976func TestAppSdkVersionByPartition(t *testing.T) {
1977	testJavaError(t, "sdk_version must have a value when the module is located at vendor or product", `
1978		android_app {
1979			name: "foo",
1980			srcs: ["a.java"],
1981			vendor: true,
1982			platform_apis: true,
1983		}
1984	`)
1985
1986	testJava(t, `
1987		android_app {
1988			name: "bar",
1989			srcs: ["b.java"],
1990			platform_apis: true,
1991		}
1992	`)
1993
1994	for _, enforce := range []bool{true, false} {
1995		bp := `
1996			android_app {
1997				name: "foo",
1998				srcs: ["a.java"],
1999				product_specific: true,
2000				platform_apis: true,
2001			}
2002		`
2003
2004		errorHandler := android.FixtureExpectsNoErrors
2005		if enforce {
2006			errorHandler = android.FixtureExpectsAtLeastOneErrorMatchingPattern("sdk_version must have a value when the module is located at vendor or product")
2007		}
2008
2009		android.GroupFixturePreparers(
2010			PrepareForTestWithJavaDefaultModules,
2011			android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
2012				variables.EnforceProductPartitionInterface = proptools.BoolPtr(enforce)
2013			}),
2014		).
2015			ExtendWithErrorHandler(errorHandler).
2016			RunTestWithBp(t, bp)
2017	}
2018}
2019
2020func TestJNIPackaging(t *testing.T) {
2021	ctx, _ := testJava(t, cc.GatherRequiredDepsForTest(android.Android)+`
2022		cc_library {
2023			name: "libjni",
2024			system_shared_libs: [],
2025			stl: "none",
2026			sdk_version: "current",
2027		}
2028
2029		android_app {
2030			name: "app",
2031			jni_libs: ["libjni"],
2032			sdk_version: "current",
2033		}
2034
2035		android_app {
2036			name: "app_noembed",
2037			jni_libs: ["libjni"],
2038			use_embedded_native_libs: false,
2039			sdk_version: "current",
2040		}
2041
2042		android_app {
2043			name: "app_embed",
2044			jni_libs: ["libjni"],
2045			use_embedded_native_libs: true,
2046			sdk_version: "current",
2047		}
2048
2049		android_test {
2050			name: "test",
2051			sdk_version: "current",
2052			jni_libs: ["libjni"],
2053		}
2054
2055		android_test {
2056			name: "test_noembed",
2057			sdk_version: "current",
2058			jni_libs: ["libjni"],
2059			use_embedded_native_libs: false,
2060		}
2061
2062		android_test_helper_app {
2063			name: "test_helper",
2064			sdk_version: "current",
2065			jni_libs: ["libjni"],
2066		}
2067
2068		android_test_helper_app {
2069			name: "test_helper_noembed",
2070			sdk_version: "current",
2071			jni_libs: ["libjni"],
2072			use_embedded_native_libs: false,
2073		}
2074		`)
2075
2076	testCases := []struct {
2077		name       string
2078		packaged   bool
2079		compressed bool
2080	}{
2081		{"app", false, false},
2082		{"app_noembed", false, false},
2083		{"app_embed", true, false},
2084		{"test", true, false},
2085		{"test_noembed", true, true},
2086		{"test_helper", true, false},
2087		{"test_helper_noembed", true, true},
2088	}
2089
2090	for _, test := range testCases {
2091		t.Run(test.name, func(t *testing.T) {
2092			app := ctx.ModuleForTests(test.name, "android_common")
2093			jniLibZip := app.MaybeOutput("jnilibs.zip")
2094			if g, w := (jniLibZip.Rule != nil), test.packaged; g != w {
2095				t.Errorf("expected jni packaged %v, got %v", w, g)
2096			}
2097
2098			if jniLibZip.Rule != nil {
2099				if g, w := !strings.Contains(jniLibZip.Args["jarArgs"], "-L 0"), test.compressed; g != w {
2100					t.Errorf("expected jni compressed %v, got %v", w, g)
2101				}
2102
2103				if !strings.Contains(jniLibZip.Implicits[0].String(), "_sdk_") {
2104					t.Errorf("expected input %q to use sdk variant", jniLibZip.Implicits[0].String())
2105				}
2106			}
2107		})
2108	}
2109}
2110
2111func TestJNISDK(t *testing.T) {
2112	ctx, _ := testJava(t, cc.GatherRequiredDepsForTest(android.Android)+`
2113		cc_library {
2114			name: "libjni",
2115			system_shared_libs: [],
2116			stl: "none",
2117			sdk_version: "current",
2118		}
2119
2120		android_test {
2121			name: "app_platform",
2122			jni_libs: ["libjni"],
2123			platform_apis: true,
2124		}
2125
2126		android_test {
2127			name: "app_sdk",
2128			jni_libs: ["libjni"],
2129			sdk_version: "current",
2130		}
2131
2132		android_test {
2133			name: "app_force_platform",
2134			jni_libs: ["libjni"],
2135			sdk_version: "current",
2136			jni_uses_platform_apis: true,
2137		}
2138
2139		android_test {
2140			name: "app_force_sdk",
2141			jni_libs: ["libjni"],
2142			platform_apis: true,
2143			jni_uses_sdk_apis: true,
2144		}
2145
2146		cc_library {
2147			name: "libvendorjni",
2148			system_shared_libs: [],
2149			stl: "none",
2150			vendor: true,
2151		}
2152
2153		android_test {
2154			name: "app_vendor",
2155			jni_libs: ["libvendorjni"],
2156			sdk_version: "current",
2157			vendor: true,
2158		}
2159	`)
2160
2161	testCases := []struct {
2162		name      string
2163		sdkJNI    bool
2164		vendorJNI bool
2165	}{
2166		{name: "app_platform"},
2167		{name: "app_sdk", sdkJNI: true},
2168		{name: "app_force_platform"},
2169		{name: "app_force_sdk", sdkJNI: true},
2170		{name: "app_vendor", vendorJNI: true},
2171	}
2172
2173	platformJNI := ctx.ModuleForTests("libjni", "android_arm64_armv8-a_shared").
2174		Output("libjni.so").Output.String()
2175	sdkJNI := ctx.ModuleForTests("libjni", "android_arm64_armv8-a_sdk_shared").
2176		Output("libjni.so").Output.String()
2177	vendorJNI := ctx.ModuleForTests("libvendorjni", "android_vendor_arm64_armv8-a_shared").
2178		Output("libvendorjni.so").Output.String()
2179
2180	for _, test := range testCases {
2181		t.Run(test.name, func(t *testing.T) {
2182			app := ctx.ModuleForTests(test.name, "android_common")
2183
2184			jniLibZip := app.MaybeOutput("jnilibs.zip")
2185			if len(jniLibZip.Implicits) != 1 {
2186				t.Fatalf("expected exactly one jni library, got %q", jniLibZip.Implicits.Strings())
2187			}
2188			gotJNI := jniLibZip.Implicits[0].String()
2189
2190			if test.sdkJNI {
2191				if gotJNI != sdkJNI {
2192					t.Errorf("expected SDK JNI library %q, got %q", sdkJNI, gotJNI)
2193				}
2194			} else if test.vendorJNI {
2195				if gotJNI != vendorJNI {
2196					t.Errorf("expected platform JNI library %q, got %q", vendorJNI, gotJNI)
2197				}
2198			} else {
2199				if gotJNI != platformJNI {
2200					t.Errorf("expected platform JNI library %q, got %q", platformJNI, gotJNI)
2201				}
2202			}
2203		})
2204	}
2205
2206	t.Run("jni_uses_platform_apis_error", func(t *testing.T) {
2207		testJavaError(t, `jni_uses_platform_apis: can only be set for modules that set sdk_version`, `
2208			android_test {
2209				name: "app_platform",
2210				platform_apis: true,
2211				jni_uses_platform_apis: true,
2212			}
2213		`)
2214	})
2215
2216	t.Run("jni_uses_sdk_apis_error", func(t *testing.T) {
2217		testJavaError(t, `jni_uses_sdk_apis: can only be set for modules that do not set sdk_version`, `
2218			android_test {
2219				name: "app_sdk",
2220				sdk_version: "current",
2221				jni_uses_sdk_apis: true,
2222			}
2223		`)
2224	})
2225
2226}
2227
2228func TestCertificates(t *testing.T) {
2229	testCases := []struct {
2230		name                     string
2231		bp                       string
2232		allowMissingDependencies bool
2233		certificateOverride      string
2234		expectedCertSigningFlags string
2235		expectedCertificate      string
2236	}{
2237		{
2238			name: "default",
2239			bp: `
2240				android_app {
2241					name: "foo",
2242					srcs: ["a.java"],
2243					sdk_version: "current",
2244				}
2245			`,
2246			certificateOverride:      "",
2247			expectedCertSigningFlags: "",
2248			expectedCertificate:      "build/make/target/product/security/testkey",
2249		},
2250		{
2251			name: "module certificate property",
2252			bp: `
2253				android_app {
2254					name: "foo",
2255					srcs: ["a.java"],
2256					certificate: ":new_certificate",
2257					sdk_version: "current",
2258				}
2259
2260				android_app_certificate {
2261					name: "new_certificate",
2262					certificate: "cert/new_cert",
2263				}
2264			`,
2265			certificateOverride:      "",
2266			expectedCertSigningFlags: "",
2267			expectedCertificate:      "cert/new_cert",
2268		},
2269		{
2270			name: "path certificate property",
2271			bp: `
2272				android_app {
2273					name: "foo",
2274					srcs: ["a.java"],
2275					certificate: "expiredkey",
2276					sdk_version: "current",
2277				}
2278			`,
2279			certificateOverride:      "",
2280			expectedCertSigningFlags: "",
2281			expectedCertificate:      "build/make/target/product/security/expiredkey",
2282		},
2283		{
2284			name: "certificate overrides",
2285			bp: `
2286				android_app {
2287					name: "foo",
2288					srcs: ["a.java"],
2289					certificate: "expiredkey",
2290					sdk_version: "current",
2291				}
2292
2293				android_app_certificate {
2294					name: "new_certificate",
2295					certificate: "cert/new_cert",
2296				}
2297			`,
2298			certificateOverride:      "foo:new_certificate",
2299			expectedCertSigningFlags: "",
2300			expectedCertificate:      "cert/new_cert",
2301		},
2302		{
2303			name: "certificate signing flags",
2304			bp: `
2305				android_app {
2306					name: "foo",
2307					srcs: ["a.java"],
2308					certificate: ":new_certificate",
2309					lineage: "lineage.bin",
2310					rotationMinSdkVersion: "32",
2311					sdk_version: "current",
2312				}
2313
2314				android_app_certificate {
2315					name: "new_certificate",
2316					certificate: "cert/new_cert",
2317				}
2318			`,
2319			certificateOverride:      "",
2320			expectedCertSigningFlags: "--lineage lineage.bin --rotation-min-sdk-version 32",
2321			expectedCertificate:      "cert/new_cert",
2322		},
2323		{
2324			name: "cert signing flags from filegroup",
2325			bp: `
2326				android_app {
2327					name: "foo",
2328					srcs: ["a.java"],
2329					certificate: ":new_certificate",
2330					lineage: ":lineage_bin",
2331					rotationMinSdkVersion: "32",
2332					sdk_version: "current",
2333				}
2334
2335				android_app_certificate {
2336					name: "new_certificate",
2337					certificate: "cert/new_cert",
2338				}
2339
2340				filegroup {
2341					name: "lineage_bin",
2342					srcs: ["lineage.bin"],
2343				}
2344			`,
2345			certificateOverride:      "",
2346			expectedCertSigningFlags: "--lineage lineage.bin --rotation-min-sdk-version 32",
2347			expectedCertificate:      "cert/new_cert",
2348		},
2349		{
2350			name: "missing with AllowMissingDependencies",
2351			bp: `
2352				android_app {
2353					name: "foo",
2354					srcs: ["a.java"],
2355					certificate: ":new_certificate",
2356					sdk_version: "current",
2357				}
2358			`,
2359			expectedCertificate:      "out/soong/.intermediates/foo/android_common/missing",
2360			allowMissingDependencies: true,
2361		},
2362	}
2363
2364	for _, test := range testCases {
2365		t.Run(test.name, func(t *testing.T) {
2366			result := android.GroupFixturePreparers(
2367				PrepareForTestWithJavaDefaultModules,
2368				android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
2369					if test.certificateOverride != "" {
2370						variables.CertificateOverrides = []string{test.certificateOverride}
2371					}
2372					if test.allowMissingDependencies {
2373						variables.Allow_missing_dependencies = proptools.BoolPtr(true)
2374					}
2375				}),
2376				android.FixtureModifyContext(func(ctx *android.TestContext) {
2377					ctx.SetAllowMissingDependencies(test.allowMissingDependencies)
2378				}),
2379			).RunTestWithBp(t, test.bp)
2380
2381			foo := result.ModuleForTests("foo", "android_common")
2382
2383			certificate := foo.Module().(*AndroidApp).certificate
2384			android.AssertPathRelativeToTopEquals(t, "certificates key", test.expectedCertificate+".pk8", certificate.Key)
2385			// The sign_target_files_apks and check_target_files_signatures
2386			// tools require that certificates have a .x509.pem extension.
2387			android.AssertPathRelativeToTopEquals(t, "certificates pem", test.expectedCertificate+".x509.pem", certificate.Pem)
2388
2389			signapk := foo.Output("foo.apk")
2390			if signapk.Rule != android.ErrorRule {
2391				signCertificateFlags := signapk.Args["certificates"]
2392				expectedFlags := certificate.Pem.String() + " " + certificate.Key.String()
2393				android.AssertStringEquals(t, "certificates flags", expectedFlags, signCertificateFlags)
2394
2395				certSigningFlags := signapk.Args["flags"]
2396				android.AssertStringEquals(t, "cert signing flags", test.expectedCertSigningFlags, certSigningFlags)
2397			}
2398		})
2399	}
2400}
2401
2402func TestRequestV4SigningFlag(t *testing.T) {
2403	testCases := []struct {
2404		name     string
2405		bp       string
2406		expected string
2407	}{
2408		{
2409			name: "default",
2410			bp: `
2411				android_app {
2412					name: "foo",
2413					srcs: ["a.java"],
2414					sdk_version: "current",
2415				}
2416			`,
2417			expected: "",
2418		},
2419		{
2420			name: "default",
2421			bp: `
2422				android_app {
2423					name: "foo",
2424					srcs: ["a.java"],
2425					sdk_version: "current",
2426					v4_signature: false,
2427				}
2428			`,
2429			expected: "",
2430		},
2431		{
2432			name: "module certificate property",
2433			bp: `
2434				android_app {
2435					name: "foo",
2436					srcs: ["a.java"],
2437					sdk_version: "current",
2438					v4_signature: true,
2439				}
2440			`,
2441			expected: "--enable-v4",
2442		},
2443	}
2444
2445	for _, test := range testCases {
2446		t.Run(test.name, func(t *testing.T) {
2447			result := android.GroupFixturePreparers(
2448				PrepareForTestWithJavaDefaultModules,
2449			).RunTestWithBp(t, test.bp)
2450
2451			foo := result.ModuleForTests("foo", "android_common")
2452
2453			signapk := foo.Output("foo.apk")
2454			signFlags := signapk.Args["flags"]
2455			android.AssertStringEquals(t, "signing flags", test.expected, signFlags)
2456		})
2457	}
2458}
2459
2460func TestPackageNameOverride(t *testing.T) {
2461	testCases := []struct {
2462		name                string
2463		bp                  string
2464		packageNameOverride string
2465		expected            []string
2466	}{
2467		{
2468			name: "default",
2469			bp: `
2470				android_app {
2471					name: "foo",
2472					srcs: ["a.java"],
2473					sdk_version: "current",
2474				}
2475			`,
2476			packageNameOverride: "",
2477			expected: []string{
2478				"out/soong/.intermediates/foo/android_common/foo.apk",
2479				"out/soong/target/product/test_device/system/app/foo/foo.apk",
2480			},
2481		},
2482		{
2483			name: "overridden via PRODUCT_PACKAGE_NAME_OVERRIDES",
2484			bp: `
2485				android_app {
2486					name: "foo",
2487					srcs: ["a.java"],
2488					sdk_version: "current",
2489				}
2490			`,
2491			packageNameOverride: "foo:bar",
2492			expected: []string{
2493				// The package apk should be still be the original name for test dependencies.
2494				"out/soong/.intermediates/foo/android_common/bar.apk",
2495				"out/soong/target/product/test_device/system/app/bar/bar.apk",
2496			},
2497		},
2498		{
2499			name: "overridden via stem",
2500			bp: `
2501				android_app {
2502					name: "foo",
2503					srcs: ["a.java"],
2504					sdk_version: "current",
2505					stem: "bar",
2506				}
2507			`,
2508			packageNameOverride: "",
2509			expected: []string{
2510				"out/soong/.intermediates/foo/android_common/bar.apk",
2511				"out/soong/target/product/test_device/system/app/bar/bar.apk",
2512			},
2513		},
2514	}
2515
2516	for _, test := range testCases {
2517		t.Run(test.name, func(t *testing.T) {
2518			result := android.GroupFixturePreparers(
2519				PrepareForTestWithJavaDefaultModules,
2520				android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
2521					if test.packageNameOverride != "" {
2522						variables.PackageNameOverrides = []string{test.packageNameOverride}
2523					}
2524				}),
2525			).RunTestWithBp(t, test.bp)
2526
2527			foo := result.ModuleForTests("foo", "android_common")
2528
2529			outSoongDir := result.Config.SoongOutDir()
2530
2531			outputs := foo.AllOutputs()
2532			outputMap := make(map[string]bool)
2533			for _, o := range outputs {
2534				outputMap[android.StringPathRelativeToTop(outSoongDir, o)] = true
2535			}
2536			for _, e := range test.expected {
2537				if _, exist := outputMap[e]; !exist {
2538					t.Errorf("Can't find %q in output files.\nAll outputs:%v", e, outputs)
2539				}
2540			}
2541		})
2542	}
2543}
2544
2545func TestInstrumentationTargetOverridden(t *testing.T) {
2546	bp := `
2547		android_app {
2548			name: "foo",
2549			srcs: ["a.java"],
2550			sdk_version: "current",
2551		}
2552
2553		android_test {
2554			name: "bar",
2555			instrumentation_for: "foo",
2556			sdk_version: "current",
2557		}
2558		`
2559
2560	result := android.GroupFixturePreparers(
2561		PrepareForTestWithJavaDefaultModules,
2562		android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
2563			variables.ManifestPackageNameOverrides = []string{"foo:org.dandroid.bp"}
2564		}),
2565	).RunTestWithBp(t, bp)
2566
2567	bar := result.ModuleForTests("bar", "android_common")
2568	res := bar.Output("package-res.apk")
2569	aapt2Flags := res.Args["flags"]
2570	e := "--rename-instrumentation-target-package org.dandroid.bp"
2571	if !strings.Contains(aapt2Flags, e) {
2572		t.Errorf("target package renaming flag, %q is missing in aapt2 link flags, %q", e, aapt2Flags)
2573	}
2574}
2575
2576func TestOverrideAndroidApp(t *testing.T) {
2577	result := PrepareForTestWithJavaDefaultModules.RunTestWithBp(
2578		t, `
2579		android_app {
2580			name: "foo",
2581			srcs: ["a.java"],
2582			certificate: "expiredkey",
2583			overrides: ["qux"],
2584			sdk_version: "current",
2585		}
2586
2587		override_android_app {
2588			name: "bar",
2589			base: "foo",
2590			certificate: ":new_certificate",
2591			lineage: "lineage.bin",
2592			rotationMinSdkVersion: "32",
2593			logging_parent: "bah",
2594		}
2595
2596		android_app_certificate {
2597			name: "new_certificate",
2598			certificate: "cert/new_cert",
2599		}
2600
2601		override_android_app {
2602			name: "baz",
2603			base: "foo",
2604			package_name: "org.dandroid.bp",
2605		}
2606
2607		override_android_app {
2608			name: "baz_no_rename_resources",
2609			base: "foo",
2610			package_name: "org.dandroid.bp",
2611			rename_resources_package: false,
2612		}
2613
2614		android_app {
2615			name: "foo_no_rename_resources",
2616			srcs: ["a.java"],
2617			certificate: "expiredkey",
2618			overrides: ["qux"],
2619			rename_resources_package: false,
2620			sdk_version: "current",
2621		}
2622
2623		override_android_app {
2624			name: "baz_base_no_rename_resources",
2625			base: "foo_no_rename_resources",
2626			package_name: "org.dandroid.bp",
2627		}
2628
2629		override_android_app {
2630			name: "baz_override_base_rename_resources",
2631			base: "foo_no_rename_resources",
2632			package_name: "org.dandroid.bp",
2633			rename_resources_package: true,
2634		}
2635		`)
2636
2637	expectedVariants := []struct {
2638		name             string
2639		moduleName       string
2640		variantName      string
2641		apkName          string
2642		apkPath          string
2643		certFlag         string
2644		certSigningFlags string
2645		overrides        []string
2646		packageFlag      string
2647		renameResources  bool
2648		logging_parent   string
2649	}{
2650		{
2651			name:             "foo",
2652			moduleName:       "foo",
2653			variantName:      "android_common",
2654			apkPath:          "out/soong/target/product/test_device/system/app/foo/foo.apk",
2655			certFlag:         "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8",
2656			certSigningFlags: "",
2657			overrides:        []string{"qux"},
2658			packageFlag:      "",
2659			renameResources:  false,
2660			logging_parent:   "",
2661		},
2662		{
2663			name:             "foo",
2664			moduleName:       "bar",
2665			variantName:      "android_common_bar",
2666			apkPath:          "out/soong/target/product/test_device/system/app/bar/bar.apk",
2667			certFlag:         "cert/new_cert.x509.pem cert/new_cert.pk8",
2668			certSigningFlags: "--lineage lineage.bin --rotation-min-sdk-version 32",
2669			overrides:        []string{"qux", "foo"},
2670			packageFlag:      "",
2671			renameResources:  false,
2672			logging_parent:   "bah",
2673		},
2674		{
2675			name:             "foo",
2676			moduleName:       "baz",
2677			variantName:      "android_common_baz",
2678			apkPath:          "out/soong/target/product/test_device/system/app/baz/baz.apk",
2679			certFlag:         "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8",
2680			certSigningFlags: "",
2681			overrides:        []string{"qux", "foo"},
2682			packageFlag:      "org.dandroid.bp",
2683			renameResources:  true,
2684			logging_parent:   "",
2685		},
2686		{
2687			name:             "foo",
2688			moduleName:       "baz_no_rename_resources",
2689			variantName:      "android_common_baz_no_rename_resources",
2690			apkPath:          "out/soong/target/product/test_device/system/app/baz_no_rename_resources/baz_no_rename_resources.apk",
2691			certFlag:         "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8",
2692			certSigningFlags: "",
2693			overrides:        []string{"qux", "foo"},
2694			packageFlag:      "org.dandroid.bp",
2695			renameResources:  false,
2696			logging_parent:   "",
2697		},
2698		{
2699			name:             "foo_no_rename_resources",
2700			moduleName:       "baz_base_no_rename_resources",
2701			variantName:      "android_common_baz_base_no_rename_resources",
2702			apkPath:          "out/soong/target/product/test_device/system/app/baz_base_no_rename_resources/baz_base_no_rename_resources.apk",
2703			certFlag:         "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8",
2704			certSigningFlags: "",
2705			overrides:        []string{"qux", "foo_no_rename_resources"},
2706			packageFlag:      "org.dandroid.bp",
2707			renameResources:  false,
2708			logging_parent:   "",
2709		},
2710		{
2711			name:             "foo_no_rename_resources",
2712			moduleName:       "baz_override_base_rename_resources",
2713			variantName:      "android_common_baz_override_base_rename_resources",
2714			apkPath:          "out/soong/target/product/test_device/system/app/baz_override_base_rename_resources/baz_override_base_rename_resources.apk",
2715			certFlag:         "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8",
2716			certSigningFlags: "",
2717			overrides:        []string{"qux", "foo_no_rename_resources"},
2718			packageFlag:      "org.dandroid.bp",
2719			renameResources:  true,
2720			logging_parent:   "",
2721		},
2722	}
2723	for _, expected := range expectedVariants {
2724		variant := result.ModuleForTests(expected.name, expected.variantName)
2725
2726		// Check the final apk name
2727		variant.Output(expected.apkPath)
2728
2729		// Check the certificate paths
2730		signapk := variant.Output(expected.moduleName + ".apk")
2731		certFlag := signapk.Args["certificates"]
2732		android.AssertStringEquals(t, "certificates flags", expected.certFlag, certFlag)
2733
2734		// Check the cert signing flags
2735		certSigningFlags := signapk.Args["flags"]
2736		android.AssertStringEquals(t, "cert signing flags", expected.certSigningFlags, certSigningFlags)
2737
2738		// Check if the overrides field values are correctly aggregated.
2739		mod := variant.Module().(*AndroidApp)
2740		android.AssertDeepEquals(t, "overrides property", expected.overrides, mod.overridableAppProperties.Overrides)
2741
2742		// Test Overridable property: Logging_parent
2743		logging_parent := mod.aapt.LoggingParent
2744		android.AssertStringEquals(t, "overrides property value for logging parent", expected.logging_parent, logging_parent)
2745
2746		// Check the package renaming flag, if exists.
2747		res := variant.Output("package-res.apk")
2748		aapt2Flags := res.Args["flags"]
2749		checkAapt2LinkFlag(t, aapt2Flags, "rename-manifest-package", expected.packageFlag)
2750		expectedPackage := expected.packageFlag
2751		if !expected.renameResources {
2752			expectedPackage = ""
2753		}
2754		checkAapt2LinkFlag(t, aapt2Flags, "rename-resources-package", expectedPackage)
2755	}
2756}
2757
2758func TestOverrideAndroidAppOverrides(t *testing.T) {
2759	ctx, _ := testJava(
2760		t, `
2761		android_app {
2762			name: "foo",
2763			srcs: ["a.java"],
2764			sdk_version: "current",
2765			overrides: ["qux"]
2766		}
2767
2768		android_app {
2769			name: "bar",
2770			srcs: ["b.java"],
2771			sdk_version: "current",
2772			overrides: ["foo"]
2773		}
2774
2775		override_android_app {
2776			name: "foo_override",
2777			base: "foo",
2778			overrides: ["bar"]
2779		}
2780		`)
2781
2782	expectedVariants := []struct {
2783		name        string
2784		moduleName  string
2785		variantName string
2786		overrides   []string
2787	}{
2788		{
2789			name:        "foo",
2790			moduleName:  "foo",
2791			variantName: "android_common",
2792			overrides:   []string{"qux"},
2793		},
2794		{
2795			name:        "bar",
2796			moduleName:  "bar",
2797			variantName: "android_common",
2798			overrides:   []string{"foo"},
2799		},
2800		{
2801			name:        "foo",
2802			moduleName:  "foo_override",
2803			variantName: "android_common_foo_override",
2804			overrides:   []string{"bar", "foo"},
2805		},
2806	}
2807	for _, expected := range expectedVariants {
2808		variant := ctx.ModuleForTests(expected.name, expected.variantName)
2809
2810		// Check if the overrides field values are correctly aggregated.
2811		mod := variant.Module().(*AndroidApp)
2812		android.AssertDeepEquals(t, "overrides property", expected.overrides, mod.overridableAppProperties.Overrides)
2813	}
2814}
2815
2816func TestOverrideAndroidAppWithPrebuilt(t *testing.T) {
2817	result := PrepareForTestWithJavaDefaultModules.RunTestWithBp(
2818		t, `
2819		android_app {
2820			name: "foo",
2821			srcs: ["a.java"],
2822			sdk_version: "current",
2823		}
2824
2825		override_android_app {
2826			name: "bar",
2827			base: "foo",
2828		}
2829
2830		android_app_import {
2831			name: "bar",
2832			prefer: true,
2833			apk: "bar.apk",
2834			presigned: true,
2835		}
2836		`)
2837
2838	// An app that has an override that also has a prebuilt should not be hidden.
2839	foo := result.ModuleForTests("foo", "android_common")
2840	if foo.Module().IsHideFromMake() {
2841		t.Errorf("expected foo to have HideFromMake false")
2842	}
2843
2844	// An override that also has a prebuilt should be hidden.
2845	barOverride := result.ModuleForTests("foo", "android_common_bar")
2846	if !barOverride.Module().IsHideFromMake() {
2847		t.Errorf("expected bar override variant of foo to have HideFromMake true")
2848	}
2849}
2850
2851func TestOverrideAndroidAppStem(t *testing.T) {
2852	ctx, _ := testJava(t, `
2853		android_app {
2854			name: "foo",
2855			srcs: ["a.java"],
2856			sdk_version: "current",
2857		}
2858		override_android_app {
2859			name: "bar",
2860			base: "foo",
2861		}
2862		override_android_app {
2863			name: "baz",
2864			base: "foo",
2865			stem: "baz_stem",
2866		}
2867		android_app {
2868			name: "foo2",
2869			srcs: ["a.java"],
2870			sdk_version: "current",
2871			stem: "foo2_stem",
2872		}
2873		override_android_app {
2874			name: "bar2",
2875			base: "foo2",
2876		}
2877		override_android_app {
2878			name: "baz2",
2879			base: "foo2",
2880			stem: "baz2_stem",
2881		}
2882	`)
2883	for _, expected := range []struct {
2884		moduleName  string
2885		variantName string
2886		apkPath     string
2887	}{
2888		{
2889			moduleName:  "foo",
2890			variantName: "android_common",
2891			apkPath:     "out/soong/target/product/test_device/system/app/foo/foo.apk",
2892		},
2893		{
2894			moduleName:  "foo",
2895			variantName: "android_common_bar",
2896			apkPath:     "out/soong/target/product/test_device/system/app/bar/bar.apk",
2897		},
2898		{
2899			moduleName:  "foo",
2900			variantName: "android_common_baz",
2901			apkPath:     "out/soong/target/product/test_device/system/app/baz_stem/baz_stem.apk",
2902		},
2903		{
2904			moduleName:  "foo2",
2905			variantName: "android_common",
2906			apkPath:     "out/soong/target/product/test_device/system/app/foo2_stem/foo2_stem.apk",
2907		},
2908		{
2909			moduleName:  "foo2",
2910			variantName: "android_common_bar2",
2911			// Note that this may cause the duplicate output error.
2912			apkPath: "out/soong/target/product/test_device/system/app/foo2_stem/foo2_stem.apk",
2913		},
2914		{
2915			moduleName:  "foo2",
2916			variantName: "android_common_baz2",
2917			apkPath:     "out/soong/target/product/test_device/system/app/baz2_stem/baz2_stem.apk",
2918		},
2919	} {
2920		variant := ctx.ModuleForTests(expected.moduleName, expected.variantName)
2921		variant.Output(expected.apkPath)
2922	}
2923}
2924
2925func TestOverrideAndroidAppDependency(t *testing.T) {
2926	ctx, _ := testJava(t, `
2927		android_app {
2928			name: "foo",
2929			srcs: ["a.java"],
2930			sdk_version: "current",
2931		}
2932
2933		override_android_app {
2934			name: "bar",
2935			base: "foo",
2936			package_name: "org.dandroid.bp",
2937		}
2938
2939		android_test {
2940			name: "baz",
2941			srcs: ["b.java"],
2942			instrumentation_for: "foo",
2943		}
2944
2945		android_test {
2946			name: "qux",
2947			srcs: ["b.java"],
2948			instrumentation_for: "bar",
2949		}
2950		`)
2951
2952	// Verify baz, which depends on the overridden module foo, has the correct classpath javac arg.
2953	javac := ctx.ModuleForTests("baz", "android_common").Rule("javac")
2954	fooTurbine := "out/soong/.intermediates/foo/android_common/turbine-combined/foo.jar"
2955	if !strings.Contains(javac.Args["classpath"], fooTurbine) {
2956		t.Errorf("baz classpath %v does not contain %q", javac.Args["classpath"], fooTurbine)
2957	}
2958
2959	// Verify qux, which depends on the overriding module bar, has the correct classpath javac arg.
2960	javac = ctx.ModuleForTests("qux", "android_common").Rule("javac")
2961	barTurbine := "out/soong/.intermediates/foo/android_common_bar/turbine-combined/foo.jar"
2962	if !strings.Contains(javac.Args["classpath"], barTurbine) {
2963		t.Errorf("qux classpath %v does not contain %q", javac.Args["classpath"], barTurbine)
2964	}
2965}
2966
2967func TestOverrideAndroidTest(t *testing.T) {
2968	ctx, _ := testJava(t, `
2969		android_app {
2970			name: "foo",
2971			srcs: ["a.java"],
2972			package_name: "com.android.foo",
2973			sdk_version: "current",
2974		}
2975
2976		override_android_app {
2977			name: "bar",
2978			base: "foo",
2979			package_name: "com.android.bar",
2980		}
2981
2982		android_test {
2983			name: "foo_test",
2984			srcs: ["b.java"],
2985			instrumentation_for: "foo",
2986		}
2987
2988		override_android_test {
2989			name: "bar_test",
2990			base: "foo_test",
2991			package_name: "com.android.bar.test",
2992			instrumentation_for: "bar",
2993			instrumentation_target_package: "com.android.bar",
2994		}
2995		`)
2996
2997	expectedVariants := []struct {
2998		moduleName        string
2999		variantName       string
3000		apkPath           string
3001		overrides         []string
3002		targetVariant     string
3003		packageFlag       string
3004		targetPackageFlag string
3005	}{
3006		{
3007			variantName:       "android_common",
3008			apkPath:           "/target/product/test_device/testcases/foo_test/arm64/foo_test.apk",
3009			overrides:         nil,
3010			targetVariant:     "android_common",
3011			packageFlag:       "",
3012			targetPackageFlag: "",
3013		},
3014		{
3015			variantName:       "android_common_bar_test",
3016			apkPath:           "/target/product/test_device/testcases/bar_test/arm64/bar_test.apk",
3017			overrides:         []string{"foo_test"},
3018			targetVariant:     "android_common_bar",
3019			packageFlag:       "com.android.bar.test",
3020			targetPackageFlag: "com.android.bar",
3021		},
3022	}
3023	for _, expected := range expectedVariants {
3024		variant := ctx.ModuleForTests("foo_test", expected.variantName)
3025
3026		// Check the final apk name
3027		variant.Output("out/soong" + expected.apkPath)
3028
3029		// Check if the overrides field values are correctly aggregated.
3030		mod := variant.Module().(*AndroidTest)
3031		if !reflect.DeepEqual(expected.overrides, mod.overridableAppProperties.Overrides) {
3032			t.Errorf("Incorrect overrides property value, expected: %q, got: %q",
3033				expected.overrides, mod.overridableAppProperties.Overrides)
3034		}
3035
3036		// Check if javac classpath has the correct jar file path. This checks instrumentation_for overrides.
3037		javac := variant.Rule("javac")
3038		turbine := filepath.Join("out", "soong", ".intermediates", "foo", expected.targetVariant, "turbine-combined", "foo.jar")
3039		if !strings.Contains(javac.Args["classpath"], turbine) {
3040			t.Errorf("classpath %q does not contain %q", javac.Args["classpath"], turbine)
3041		}
3042
3043		// Check aapt2 flags.
3044		res := variant.Output("package-res.apk")
3045		aapt2Flags := res.Args["flags"]
3046		checkAapt2LinkFlag(t, aapt2Flags, "rename-manifest-package", expected.packageFlag)
3047		checkAapt2LinkFlag(t, aapt2Flags, "rename-resources-package", expected.packageFlag)
3048		checkAapt2LinkFlag(t, aapt2Flags, "rename-instrumentation-target-package", expected.targetPackageFlag)
3049	}
3050}
3051
3052func TestAndroidTest_FixTestConfig(t *testing.T) {
3053	ctx, _ := testJava(t, `
3054		android_app {
3055			name: "foo",
3056			srcs: ["a.java"],
3057			package_name: "com.android.foo",
3058			sdk_version: "current",
3059		}
3060
3061		android_test {
3062			name: "foo_test",
3063			srcs: ["b.java"],
3064			instrumentation_for: "foo",
3065		}
3066
3067		android_test {
3068			name: "bar_test",
3069			srcs: ["b.java"],
3070			package_name: "com.android.bar.test",
3071			instrumentation_for: "foo",
3072			mainline_package_name: "com.android.bar",
3073		}
3074
3075		override_android_test {
3076			name: "baz_test",
3077			base: "foo_test",
3078			package_name: "com.android.baz.test",
3079			mainline_package_name: "com.android.baz",
3080		}
3081		`)
3082
3083	testCases := []struct {
3084		moduleName    string
3085		variantName   string
3086		expectedFlags []string
3087	}{
3088		{
3089			moduleName:  "foo_test",
3090			variantName: "android_common",
3091		},
3092		{
3093			moduleName:  "bar_test",
3094			variantName: "android_common",
3095			expectedFlags: []string{
3096				"--manifest out/soong/.intermediates/bar_test/android_common/manifest_fixer/AndroidManifest.xml",
3097				"--package-name com.android.bar.test",
3098				"--mainline-package-name com.android.bar",
3099			},
3100		},
3101		{
3102			moduleName:  "foo_test",
3103			variantName: "android_common_baz_test",
3104			expectedFlags: []string{
3105				"--manifest out/soong/.intermediates/foo_test/android_common_baz_test/manifest_fixer/AndroidManifest.xml",
3106				"--package-name com.android.baz.test",
3107				"--test-file-name baz_test.apk",
3108				"out/soong/.intermediates/foo_test/android_common_baz_test/test_config_fixer/AndroidTest.xml",
3109				"--mainline-package-name com.android.baz",
3110			},
3111		},
3112	}
3113
3114	for _, test := range testCases {
3115		variant := ctx.ModuleForTests(test.moduleName, test.variantName)
3116		params := variant.MaybeOutput("test_config_fixer/AndroidTest.xml")
3117
3118		if len(test.expectedFlags) > 0 {
3119			if params.Rule == nil {
3120				t.Errorf("test_config_fixer was expected to run, but didn't")
3121			} else {
3122				for _, flag := range test.expectedFlags {
3123					if !strings.Contains(params.RuleParams.Command, flag) {
3124						t.Errorf("Flag %q was not found in command: %q", flag, params.RuleParams.Command)
3125					}
3126				}
3127			}
3128		} else {
3129			if params.Rule != nil {
3130				t.Errorf("test_config_fixer was not expected to run, but did: %q", params.RuleParams.Command)
3131			}
3132		}
3133	}
3134}
3135
3136func TestInstrumentationTargetPrebuilt(t *testing.T) {
3137	bp := `
3138		android_app_import {
3139			name: "foo",
3140			apk: "foo.apk",
3141			presigned: true,
3142		}
3143
3144		android_test {
3145			name: "bar",
3146			srcs: ["a.java"],
3147			instrumentation_for: "foo",
3148			sdk_version: "current",
3149		}
3150		`
3151
3152	android.GroupFixturePreparers(
3153		PrepareForTestWithJavaDefaultModules,
3154	).ExtendWithErrorHandler(
3155		android.FixtureExpectsAtLeastOneErrorMatchingPattern(
3156			"instrumentation_for: dependency \"foo\" of type \"android_app_import\" does not provide JavaInfo so is unsuitable for use with this property")).
3157		RunTestWithBp(t, bp)
3158}
3159
3160func TestStl(t *testing.T) {
3161	ctx, _ := testJava(t, cc.GatherRequiredDepsForTest(android.Android)+`
3162		cc_library {
3163			name: "libjni",
3164			sdk_version: "current",
3165			stl: "c++_shared",
3166		}
3167
3168		android_test {
3169			name: "stl",
3170			jni_libs: ["libjni"],
3171			compile_multilib: "both",
3172			sdk_version: "current",
3173			stl: "c++_shared",
3174		}
3175
3176		android_test {
3177			name: "system",
3178			jni_libs: ["libjni"],
3179			compile_multilib: "both",
3180			sdk_version: "current",
3181		}
3182		`)
3183
3184	testCases := []struct {
3185		name string
3186		jnis []string
3187	}{
3188		{"stl",
3189			[]string{
3190				"libjni.so",
3191				"libc++_shared.so",
3192			},
3193		},
3194		{"system",
3195			[]string{
3196				"libjni.so",
3197			},
3198		},
3199	}
3200
3201	for _, test := range testCases {
3202		t.Run(test.name, func(t *testing.T) {
3203			app := ctx.ModuleForTests(test.name, "android_common")
3204			jniLibZip := app.Output("jnilibs.zip")
3205			var jnis []string
3206			args := strings.Fields(jniLibZip.Args["jarArgs"])
3207			for i := 0; i < len(args); i++ {
3208				if args[i] == "-f" {
3209					jnis = append(jnis, args[i+1])
3210					i += 1
3211				}
3212			}
3213			jnisJoined := strings.Join(jnis, " ")
3214			for _, jni := range test.jnis {
3215				if !strings.Contains(jnisJoined, jni) {
3216					t.Errorf("missing jni %q in %q", jni, jnis)
3217				}
3218			}
3219		})
3220	}
3221}
3222
3223func TestUsesLibraries(t *testing.T) {
3224	bp := `
3225		java_sdk_library {
3226			name: "foo",
3227			srcs: ["a.java"],
3228			api_packages: ["foo"],
3229			sdk_version: "current",
3230		}
3231
3232		java_sdk_library {
3233			name: "qux",
3234			srcs: ["a.java"],
3235			api_packages: ["qux"],
3236			sdk_version: "current",
3237		}
3238
3239		java_sdk_library {
3240			name: "quuz",
3241			srcs: ["a.java"],
3242			api_packages: ["quuz"],
3243			sdk_version: "current",
3244		}
3245
3246		java_sdk_library {
3247			name: "fred",
3248			srcs: ["a.java"],
3249			api_packages: ["fred"],
3250			sdk_version: "current",
3251		}
3252
3253		java_sdk_library {
3254			name: "bar",
3255			srcs: ["a.java"],
3256			api_packages: ["bar"],
3257			sdk_version: "current",
3258		}
3259
3260		java_sdk_library {
3261			name: "runtime-library",
3262			srcs: ["a.java"],
3263			sdk_version: "current",
3264		}
3265
3266		java_library {
3267			name: "static-runtime-helper",
3268			srcs: ["a.java"],
3269			libs: ["runtime-library.impl"],
3270			sdk_version: "current",
3271		}
3272
3273		java_library {
3274			name: "runtime-required-x",
3275			srcs: ["a.java"],
3276			installable: true,
3277			sdk_version: "current",
3278		}
3279
3280		java_library {
3281			name: "runtime-optional-x",
3282			srcs: ["a.java"],
3283			installable: true,
3284			sdk_version: "current",
3285		}
3286
3287		android_library {
3288			name: "static-x",
3289			uses_libs: ["runtime-required-x"],
3290			optional_uses_libs: ["runtime-optional-x"],
3291			sdk_version: "current",
3292		}
3293
3294		java_library {
3295			name: "runtime-required-y",
3296			srcs: ["a.java"],
3297			installable: true,
3298			sdk_version: "current",
3299		}
3300
3301		java_library {
3302			name: "runtime-optional-y",
3303			srcs: ["a.java"],
3304			installable: true,
3305			sdk_version: "current",
3306		}
3307
3308		java_library {
3309			name: "static-y",
3310			srcs: ["a.java"],
3311			uses_libs: ["runtime-required-y"],
3312			optional_uses_libs: [
3313				"runtime-optional-y",
3314				"missing-lib-a",
3315			],
3316			sdk_version: "current",
3317		}
3318
3319		// A library that has to use "provides_uses_lib", because:
3320		//    - it is not an SDK library
3321		//    - its library name is different from its module name
3322		java_library {
3323			name: "non-sdk-lib",
3324			provides_uses_lib: "com.non.sdk.lib",
3325			installable: true,
3326			srcs: ["a.java"],
3327		}
3328
3329		android_app {
3330			name: "app",
3331			srcs: ["a.java"],
3332			libs: [
3333				"qux.impl",
3334				"quuz.stubs"
3335			],
3336			static_libs: [
3337				"static-runtime-helper",
3338				// statically linked component libraries should not pull their SDK libraries,
3339				// so "fred" should not be added to class loader context
3340				"fred.stubs",
3341				"static-x",
3342				"static-y",
3343			],
3344			uses_libs: [
3345				"foo",
3346				"non-sdk-lib"
3347			],
3348			sdk_version: "current",
3349			optional_uses_libs: [
3350				"bar",
3351				"missing-lib-b",
3352			],
3353		}
3354
3355		android_app_import {
3356			name: "prebuilt",
3357			apk: "prebuilts/apk/app.apk",
3358			certificate: "platform",
3359			uses_libs: [
3360				"foo",
3361				"non-sdk-lib",
3362				"android.test.runner"
3363			],
3364			optional_uses_libs: [
3365				"bar",
3366				"missing-lib-b",
3367			],
3368		}
3369	`
3370
3371	result := android.GroupFixturePreparers(
3372		prepareForJavaTest,
3373		PrepareForTestWithJavaSdkLibraryFiles,
3374		FixtureWithLastReleaseApis("runtime-library", "foo", "quuz", "qux", "bar", "fred"),
3375		android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
3376			variables.BuildWarningBadOptionalUsesLibsAllowlist = []string{"app", "prebuilt"}
3377		}),
3378	).RunTestWithBp(t, bp)
3379
3380	app := result.ModuleForTests("app", "android_common")
3381	prebuilt := result.ModuleForTests("prebuilt", "android_common")
3382
3383	// Test that implicit dependencies on java_sdk_library instances are passed to the manifest.
3384	// These also include explicit `uses_libs`/`optional_uses_libs` entries, as they may be
3385	// propagated from dependencies.
3386	actualManifestFixerArgs := app.Output("manifest_fixer/AndroidManifest.xml").Args["args"]
3387	expectManifestFixerArgs := `--extract-native-libs=true ` +
3388		`--uses-library foo ` +
3389		`--uses-library com.non.sdk.lib ` +
3390		`--uses-library qux ` +
3391		`--uses-library quuz ` +
3392		`--uses-library runtime-library ` +
3393		`--uses-library runtime-required-x ` +
3394		`--uses-library runtime-required-y ` +
3395		`--optional-uses-library bar ` +
3396		`--optional-uses-library runtime-optional-x ` +
3397		`--optional-uses-library runtime-optional-y`
3398	android.AssertStringDoesContain(t, "manifest_fixer args", actualManifestFixerArgs, expectManifestFixerArgs)
3399
3400	// Test that all libraries are verified (library order matters).
3401	verifyCmd := app.Rule("verify_uses_libraries").RuleParams.Command
3402	verifyArgs := `--uses-library foo ` +
3403		`--uses-library com.non.sdk.lib ` +
3404		`--uses-library qux ` +
3405		`--uses-library quuz ` +
3406		`--uses-library runtime-library ` +
3407		`--uses-library runtime-required-x ` +
3408		`--uses-library runtime-required-y ` +
3409		`--optional-uses-library bar ` +
3410		`--optional-uses-library runtime-optional-x ` +
3411		`--optional-uses-library runtime-optional-y ` +
3412		`--missing-optional-uses-library missing-lib-b ` +
3413		`--missing-optional-uses-library missing-lib-a`
3414	android.AssertStringDoesContain(t, "verify cmd args", verifyCmd, verifyArgs)
3415
3416	// Test that all libraries are verified for an APK (library order matters).
3417	verifyApkCmd := prebuilt.Rule("verify_uses_libraries").RuleParams.Command
3418	verifyApkArgs := `--uses-library foo ` +
3419		`--uses-library com.non.sdk.lib ` +
3420		`--uses-library android.test.runner ` +
3421		`--optional-uses-library bar ` +
3422		`--missing-optional-uses-library missing-lib-b `
3423	android.AssertStringDoesContain(t, "verify apk cmd args", verifyApkCmd, verifyApkArgs)
3424
3425	// Test that necessary args are passed for constructing CLC in Ninja phase.
3426	cmd := app.Rule("dexpreopt").RuleParams.Command
3427	android.AssertStringDoesContain(t, "dexpreopt app cmd context", cmd, "--context-json=")
3428	android.AssertStringDoesContain(t, "dexpreopt app cmd product_packages", cmd,
3429		"--product-packages=out/soong/.intermediates/app/android_common/dexpreopt/app/product_packages.txt")
3430}
3431
3432func TestDexpreoptBcp(t *testing.T) {
3433	bp := `
3434		java_sdk_library {
3435			name: "foo",
3436			srcs: ["a.java"],
3437			api_packages: ["foo"],
3438			sdk_version: "current",
3439		}
3440
3441		java_sdk_library {
3442			name: "bar",
3443			srcs: ["a.java"],
3444			api_packages: ["bar"],
3445			permitted_packages: ["bar"],
3446			sdk_version: "current",
3447		}
3448
3449		android_app {
3450			name: "app",
3451			srcs: ["a.java"],
3452			sdk_version: "current",
3453		}
3454	`
3455
3456	testCases := []struct {
3457		name   string
3458		with   bool
3459		expect string
3460	}{
3461		{
3462			name:   "with updatable bcp",
3463			with:   true,
3464			expect: "/system/framework/foo.jar:/system/framework/bar.jar",
3465		},
3466		{
3467			name:   "without updatable bcp",
3468			with:   false,
3469			expect: "/system/framework/foo.jar",
3470		},
3471	}
3472
3473	for _, test := range testCases {
3474		t.Run(test.name, func(t *testing.T) {
3475			result := android.GroupFixturePreparers(
3476				prepareForJavaTest,
3477				PrepareForTestWithJavaSdkLibraryFiles,
3478				FixtureWithLastReleaseApis("runtime-library", "foo", "bar"),
3479				dexpreopt.FixtureSetBootJars("platform:foo"),
3480				dexpreopt.FixtureSetApexBootJars("platform:bar"),
3481				dexpreopt.FixtureSetPreoptWithUpdatableBcp(test.with),
3482			).RunTestWithBp(t, bp)
3483
3484			app := result.ModuleForTests("app", "android_common")
3485			cmd := app.Rule("dexpreopt").RuleParams.Command
3486			bcp := " -Xbootclasspath-locations:" + test.expect + " " // space at the end matters
3487			android.AssertStringDoesContain(t, "dexpreopt app bcp", cmd, bcp)
3488		})
3489	}
3490}
3491
3492func TestCodelessApp(t *testing.T) {
3493	testCases := []struct {
3494		name   string
3495		bp     string
3496		noCode bool
3497	}{
3498		{
3499			name: "normal",
3500			bp: `
3501				android_app {
3502					name: "foo",
3503					srcs: ["a.java"],
3504					sdk_version: "current",
3505				}
3506			`,
3507			noCode: false,
3508		},
3509		{
3510			name: "app without sources",
3511			bp: `
3512				android_app {
3513					name: "foo",
3514					sdk_version: "current",
3515				}
3516			`,
3517			noCode: true,
3518		},
3519		{
3520			name: "app with libraries",
3521			bp: `
3522				android_app {
3523					name: "foo",
3524					static_libs: ["lib"],
3525					sdk_version: "current",
3526				}
3527
3528				java_library {
3529					name: "lib",
3530					srcs: ["a.java"],
3531					sdk_version: "current",
3532				}
3533			`,
3534			noCode: false,
3535		},
3536		{
3537			name: "app with sourceless libraries",
3538			bp: `
3539				android_app {
3540					name: "foo",
3541					static_libs: ["lib"],
3542					sdk_version: "current",
3543				}
3544
3545				java_library {
3546					name: "lib",
3547					sdk_version: "current",
3548				}
3549			`,
3550			// TODO(jungjw): this should probably be true
3551			noCode: false,
3552		},
3553	}
3554
3555	for _, test := range testCases {
3556		t.Run(test.name, func(t *testing.T) {
3557			ctx := testApp(t, test.bp)
3558
3559			foo := ctx.ModuleForTests("foo", "android_common")
3560			manifestFixerArgs := foo.Output("manifest_fixer/AndroidManifest.xml").Args["args"]
3561			if strings.Contains(manifestFixerArgs, "--has-no-code") != test.noCode {
3562				t.Errorf("unexpected manifest_fixer args: %q", manifestFixerArgs)
3563			}
3564		})
3565	}
3566}
3567
3568func TestUncompressDex(t *testing.T) {
3569	testCases := []struct {
3570		name string
3571		bp   string
3572
3573		uncompressedPlatform  bool
3574		uncompressedUnbundled bool
3575	}{
3576		{
3577			name: "normal",
3578			bp: `
3579				android_app {
3580					name: "foo",
3581					srcs: ["a.java"],
3582					sdk_version: "current",
3583				}
3584			`,
3585			uncompressedPlatform:  true,
3586			uncompressedUnbundled: false,
3587		},
3588		{
3589			name: "use_embedded_dex",
3590			bp: `
3591				android_app {
3592					name: "foo",
3593					use_embedded_dex: true,
3594					srcs: ["a.java"],
3595					sdk_version: "current",
3596				}
3597			`,
3598			uncompressedPlatform:  true,
3599			uncompressedUnbundled: true,
3600		},
3601		{
3602			name: "privileged",
3603			bp: `
3604				android_app {
3605					name: "foo",
3606					privileged: true,
3607					srcs: ["a.java"],
3608					sdk_version: "current",
3609				}
3610			`,
3611			uncompressedPlatform:  true,
3612			uncompressedUnbundled: true,
3613		},
3614		{
3615			name: "normal_uncompress_dex_true",
3616			bp: `
3617				android_app {
3618					name: "foo",
3619					srcs: ["a.java"],
3620					sdk_version: "current",
3621					uncompress_dex: true,
3622				}
3623			`,
3624			uncompressedPlatform:  true,
3625			uncompressedUnbundled: true,
3626		},
3627		{
3628			name: "normal_uncompress_dex_false",
3629			bp: `
3630				android_app {
3631					name: "foo",
3632					srcs: ["a.java"],
3633					sdk_version: "current",
3634					uncompress_dex: false,
3635				}
3636			`,
3637			uncompressedPlatform:  false,
3638			uncompressedUnbundled: false,
3639		},
3640	}
3641
3642	test := func(t *testing.T, bp string, want bool, unbundled bool) {
3643		t.Helper()
3644
3645		result := android.GroupFixturePreparers(
3646			prepareForJavaTest,
3647			PrepareForTestWithPrebuiltsOfCurrentApi,
3648			android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
3649				if unbundled {
3650					variables.Unbundled_build = proptools.BoolPtr(true)
3651					variables.Always_use_prebuilt_sdks = proptools.BoolPtr(true)
3652				}
3653			}),
3654		).RunTestWithBp(t, bp)
3655
3656		foo := result.ModuleForTests("foo", "android_common")
3657		dex := foo.Rule("r8")
3658		uncompressedInDexJar := strings.Contains(dex.Args["zipFlags"], "-L 0")
3659		aligned := foo.MaybeRule("zipalign").Rule != nil
3660
3661		android.AssertBoolEquals(t, "uncompressed in dex", want, uncompressedInDexJar)
3662
3663		android.AssertBoolEquals(t, "aligne", want, aligned)
3664	}
3665
3666	for _, tt := range testCases {
3667		t.Run(tt.name, func(t *testing.T) {
3668			t.Run("platform", func(t *testing.T) {
3669				test(t, tt.bp, tt.uncompressedPlatform, false)
3670			})
3671			t.Run("unbundled", func(t *testing.T) {
3672				test(t, tt.bp, tt.uncompressedUnbundled, true)
3673			})
3674		})
3675	}
3676}
3677
3678func checkAapt2LinkFlag(t *testing.T, aapt2Flags, flagName, expectedValue string) {
3679	if expectedValue != "" {
3680		expectedFlag := "--" + flagName + " " + expectedValue
3681		if !strings.Contains(aapt2Flags, expectedFlag) {
3682			t.Errorf("%q is missing in aapt2 link flags, %q", expectedFlag, aapt2Flags)
3683		}
3684	} else {
3685		unexpectedFlag := "--" + flagName
3686		if strings.Contains(aapt2Flags, unexpectedFlag) {
3687			t.Errorf("unexpected flag, %q is found in aapt2 link flags, %q", unexpectedFlag, aapt2Flags)
3688		}
3689	}
3690}
3691
3692func TestExportedProguardFlagFiles(t *testing.T) {
3693	ctx, _ := testJava(t, `
3694		android_app {
3695			name: "foo",
3696			sdk_version: "current",
3697			static_libs: [
3698				"lib1",
3699				"lib3",
3700			],
3701		}
3702
3703		android_library {
3704			name: "lib1",
3705			sdk_version: "current",
3706			optimize: {
3707				proguard_flags_files: ["lib1proguard.cfg"],
3708			},
3709			static_libs: ["lib2"],
3710		}
3711
3712		android_library {
3713			name: "lib2",
3714			sdk_version: "current",
3715			optimize: {
3716				proguard_flags_files: ["lib2proguard.cfg"],
3717			}
3718		}
3719
3720		android_library_import {
3721			name: "lib3",
3722			sdk_version: "current",
3723			aars: ["lib3.aar"],
3724			static_libs: ["lib4"],
3725		}
3726
3727		android_library {
3728			name: "lib4",
3729			sdk_version: "current",
3730			optimize: {
3731				proguard_flags_files: ["lib4proguard.cfg"],
3732			}
3733		}
3734
3735
3736	`)
3737
3738	m := ctx.ModuleForTests("foo", "android_common")
3739	r8 := m.Rule("java.r8")
3740	implicits := r8.Implicits.RelativeToTop().Strings()
3741	android.AssertStringListContains(t, "r8 implicits", implicits, "lib1proguard.cfg")
3742	android.AssertStringListContains(t, "r8 implicits", implicits, "lib2proguard.cfg")
3743	android.AssertStringListContains(t, "r8 implicits", implicits, "lib4proguard.cfg")
3744	android.AssertStringListContains(t, "r8 implicits", implicits, "out/soong/.intermediates/lib3/android_common/aar/proguard.txt")
3745
3746	flags := r8.Args["r8Flags"]
3747	android.AssertStringDoesContain(t, "r8 flags", flags, "-include lib1proguard.cfg")
3748	android.AssertStringDoesContain(t, "r8 flags", flags, "-include lib2proguard.cfg")
3749	android.AssertStringDoesContain(t, "r8 flags", flags, "-include lib4proguard.cfg")
3750	android.AssertStringDoesContain(t, "r8 flags", flags, "-include out/soong/.intermediates/lib3/android_common/aar/proguard.txt")
3751}
3752
3753func TestTargetSdkVersionManifestFixer(t *testing.T) {
3754	platform_sdk_codename := "Tiramisu"
3755	platform_sdk_version := 33
3756	testCases := []struct {
3757		name                     string
3758		targetSdkVersionInBp     string
3759		targetSdkVersionExpected string
3760		unbundledBuild           bool
3761		platformSdkFinal         bool
3762	}{
3763		{
3764			name:                     "Non-Unbundled build: Android.bp has targetSdkVersion",
3765			targetSdkVersionInBp:     "30",
3766			targetSdkVersionExpected: "30",
3767			unbundledBuild:           false,
3768		},
3769		{
3770			name:                     "Unbundled build: Android.bp has targetSdkVersion",
3771			targetSdkVersionInBp:     "30",
3772			targetSdkVersionExpected: "30",
3773			unbundledBuild:           true,
3774		},
3775		{
3776			name:                     "Non-Unbundled build: Android.bp has targetSdkVersion equal to platform_sdk_codename",
3777			targetSdkVersionInBp:     platform_sdk_codename,
3778			targetSdkVersionExpected: platform_sdk_codename,
3779			unbundledBuild:           false,
3780		},
3781		{
3782			name:                     "Unbundled build: Android.bp has targetSdkVersion equal to platform_sdk_codename",
3783			targetSdkVersionInBp:     platform_sdk_codename,
3784			targetSdkVersionExpected: "10000",
3785			unbundledBuild:           true,
3786		},
3787
3788		{
3789			name:                     "Non-Unbundled build: Android.bp has no targetSdkVersion",
3790			targetSdkVersionExpected: platform_sdk_codename,
3791			unbundledBuild:           false,
3792		},
3793		{
3794			name:                     "Unbundled build: Android.bp has no targetSdkVersion",
3795			targetSdkVersionExpected: "10000",
3796			unbundledBuild:           true,
3797		},
3798		{
3799			name:                     "Bundled build in REL branches",
3800			targetSdkVersionExpected: "33",
3801			unbundledBuild:           false,
3802			platformSdkFinal:         true,
3803		},
3804	}
3805	for _, testCase := range testCases {
3806		targetSdkVersionTemplate := ""
3807		if testCase.targetSdkVersionInBp != "" {
3808			targetSdkVersionTemplate = fmt.Sprintf(`target_sdk_version: "%s",`, testCase.targetSdkVersionInBp)
3809		}
3810		bp := fmt.Sprintf(`
3811			android_app {
3812				name: "foo",
3813				sdk_version: "current",
3814				%s
3815			}
3816			`, targetSdkVersionTemplate)
3817		fixture := android.GroupFixturePreparers(
3818			prepareForJavaTest,
3819			android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
3820				if testCase.platformSdkFinal {
3821					variables.Platform_sdk_final = proptools.BoolPtr(true)
3822				}
3823				// explicitly set platform_sdk_codename to make the test deterministic
3824				variables.Platform_sdk_codename = &platform_sdk_codename
3825				variables.Platform_sdk_version = &platform_sdk_version
3826				variables.Platform_version_active_codenames = []string{platform_sdk_codename}
3827				// create a non-empty list if unbundledBuild==true
3828				if testCase.unbundledBuild {
3829					variables.Unbundled_build_apps = []string{"apex_a", "apex_b"}
3830				}
3831			}),
3832		)
3833
3834		result := fixture.RunTestWithBp(t, bp)
3835		foo := result.ModuleForTests("foo", "android_common")
3836
3837		manifestFixerArgs := foo.Output("manifest_fixer/AndroidManifest.xml").Args["args"]
3838		android.AssertStringDoesContain(t, testCase.name, manifestFixerArgs, "--targetSdkVersion  "+testCase.targetSdkVersionExpected)
3839	}
3840}
3841
3842func TestDefaultAppTargetSdkVersionForUpdatableModules(t *testing.T) {
3843	platform_sdk_codename := "Tiramisu"
3844	platform_sdk_version := 33
3845	testCases := []struct {
3846		name                     string
3847		platform_sdk_final       bool
3848		targetSdkVersionInBp     *string
3849		targetSdkVersionExpected *string
3850		updatable                bool
3851	}{
3852		{
3853			name:                     "Non-Updatable Module: Android.bp has older targetSdkVersion",
3854			targetSdkVersionInBp:     proptools.StringPtr("29"),
3855			targetSdkVersionExpected: proptools.StringPtr("29"),
3856			updatable:                false,
3857		},
3858		{
3859			name:                     "Updatable Module: Android.bp has older targetSdkVersion",
3860			targetSdkVersionInBp:     proptools.StringPtr("30"),
3861			targetSdkVersionExpected: proptools.StringPtr("30"),
3862			updatable:                true,
3863		},
3864		{
3865			name:                     "Updatable Module: Android.bp has no targetSdkVersion",
3866			targetSdkVersionExpected: proptools.StringPtr("10000"),
3867			updatable:                true,
3868		},
3869		{
3870			name:                     "[SDK finalised] Non-Updatable Module: Android.bp has older targetSdkVersion",
3871			platform_sdk_final:       true,
3872			targetSdkVersionInBp:     proptools.StringPtr("30"),
3873			targetSdkVersionExpected: proptools.StringPtr("30"),
3874			updatable:                false,
3875		},
3876		{
3877			name:                     "[SDK finalised] Updatable Module: Android.bp has older targetSdkVersion",
3878			platform_sdk_final:       true,
3879			targetSdkVersionInBp:     proptools.StringPtr("30"),
3880			targetSdkVersionExpected: proptools.StringPtr("30"),
3881			updatable:                true,
3882		},
3883		{
3884			name:                     "[SDK finalised] Updatable Module: Android.bp has targetSdkVersion as platform sdk codename",
3885			platform_sdk_final:       true,
3886			targetSdkVersionInBp:     proptools.StringPtr(platform_sdk_codename),
3887			targetSdkVersionExpected: proptools.StringPtr("33"),
3888			updatable:                true,
3889		},
3890		{
3891			name:                     "[SDK finalised] Updatable Module: Android.bp has no targetSdkVersion",
3892			platform_sdk_final:       true,
3893			targetSdkVersionExpected: proptools.StringPtr("33"),
3894			updatable:                true,
3895		},
3896	}
3897	for _, testCase := range testCases {
3898		targetSdkVersionTemplate := ""
3899		if testCase.targetSdkVersionInBp != nil {
3900			targetSdkVersionTemplate = fmt.Sprintf(`target_sdk_version: "%s",`, *testCase.targetSdkVersionInBp)
3901		}
3902		bp := fmt.Sprintf(`
3903			android_app {
3904				name: "foo",
3905				sdk_version: "current",
3906				min_sdk_version: "29",
3907				%s
3908				updatable: %t,
3909				enforce_default_target_sdk_version: %t
3910			}
3911			`, targetSdkVersionTemplate, testCase.updatable, testCase.updatable) // enforce default target sdk version if app is updatable
3912
3913		fixture := android.GroupFixturePreparers(
3914			PrepareForTestWithJavaDefaultModules,
3915			android.PrepareForTestWithAllowMissingDependencies,
3916			android.PrepareForTestWithAndroidMk,
3917			android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
3918				// explicitly set following platform variables to make the test deterministic
3919				variables.Platform_sdk_final = &testCase.platform_sdk_final
3920				variables.Platform_sdk_version = &platform_sdk_version
3921				variables.Platform_sdk_codename = &platform_sdk_codename
3922				variables.Platform_version_active_codenames = []string{platform_sdk_codename}
3923				variables.Unbundled_build = proptools.BoolPtr(true)
3924				variables.Unbundled_build_apps = []string{"sampleModule"}
3925			}),
3926		)
3927
3928		result := fixture.RunTestWithBp(t, bp)
3929		foo := result.ModuleForTests("foo", "android_common")
3930
3931		manifestFixerArgs := foo.Output("manifest_fixer/AndroidManifest.xml").Args["args"]
3932		android.AssertStringDoesContain(t, testCase.name, manifestFixerArgs, "--targetSdkVersion  "+*testCase.targetSdkVersionExpected)
3933	}
3934}
3935
3936func TestEnforceDefaultAppTargetSdkVersionFlag(t *testing.T) {
3937	platform_sdk_codename := "Tiramisu"
3938	platform_sdk_version := 33
3939	testCases := []struct {
3940		name                           string
3941		enforceDefaultTargetSdkVersion bool
3942		expectedError                  string
3943		platform_sdk_final             bool
3944		targetSdkVersionInBp           string
3945		targetSdkVersionExpected       string
3946		updatable                      bool
3947	}{
3948		{
3949			name:                           "Not enforcing Target SDK Version: Android.bp has older targetSdkVersion",
3950			enforceDefaultTargetSdkVersion: false,
3951			targetSdkVersionInBp:           "29",
3952			targetSdkVersionExpected:       "29",
3953			updatable:                      false,
3954		},
3955		{
3956			name:                           "[SDK finalised] Enforce Target SDK Version: Android.bp has current targetSdkVersion",
3957			enforceDefaultTargetSdkVersion: true,
3958			platform_sdk_final:             true,
3959			targetSdkVersionInBp:           "current",
3960			targetSdkVersionExpected:       "33",
3961			updatable:                      true,
3962		},
3963		{
3964			name:                           "Enforce Target SDK Version: Android.bp has current targetSdkVersion",
3965			enforceDefaultTargetSdkVersion: true,
3966			platform_sdk_final:             false,
3967			targetSdkVersionInBp:           "current",
3968			targetSdkVersionExpected:       "10000",
3969			updatable:                      false,
3970		},
3971		{
3972			name:                           "Not enforcing Target SDK Version for Updatable app",
3973			enforceDefaultTargetSdkVersion: false,
3974			expectedError:                  "Updatable apps must enforce default target sdk version",
3975			targetSdkVersionInBp:           "29",
3976			targetSdkVersionExpected:       "29",
3977			updatable:                      true,
3978		},
3979	}
3980	for _, testCase := range testCases {
3981		errExpected := testCase.expectedError != ""
3982		bp := fmt.Sprintf(`
3983			android_app {
3984				name: "foo",
3985				enforce_default_target_sdk_version: %t,
3986				sdk_version: "current",
3987				min_sdk_version: "29",
3988				target_sdk_version: "%v",
3989				updatable: %t
3990			}
3991			`, testCase.enforceDefaultTargetSdkVersion, testCase.targetSdkVersionInBp, testCase.updatable)
3992
3993		fixture := android.GroupFixturePreparers(
3994			PrepareForTestWithJavaDefaultModules,
3995			android.PrepareForTestWithAllowMissingDependencies,
3996			android.PrepareForTestWithAndroidMk,
3997			android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
3998				// explicitly set following platform variables to make the test deterministic
3999				variables.Platform_sdk_final = &testCase.platform_sdk_final
4000				variables.Platform_sdk_version = &platform_sdk_version
4001				variables.Platform_sdk_codename = &platform_sdk_codename
4002				variables.Unbundled_build = proptools.BoolPtr(true)
4003				variables.Unbundled_build_apps = []string{"sampleModule"}
4004			}),
4005		)
4006
4007		errorHandler := android.FixtureExpectsNoErrors
4008		if errExpected {
4009			errorHandler = android.FixtureExpectsAtLeastOneErrorMatchingPattern(testCase.expectedError)
4010		}
4011		result := fixture.ExtendWithErrorHandler(errorHandler).RunTestWithBp(t, bp)
4012
4013		if !errExpected {
4014			foo := result.ModuleForTests("foo", "android_common")
4015			manifestFixerArgs := foo.Output("manifest_fixer/AndroidManifest.xml").Args["args"]
4016			android.AssertStringDoesContain(t, testCase.name, manifestFixerArgs, "--targetSdkVersion  "+testCase.targetSdkVersionExpected)
4017		}
4018	}
4019}
4020
4021func TestEnforceDefaultAppTargetSdkVersionFlagForTests(t *testing.T) {
4022	platform_sdk_codename := "Tiramisu"
4023	platform_sdk_version := 33
4024	testCases := []struct {
4025		name                           string
4026		enforceDefaultTargetSdkVersion bool
4027		expectedError                  string
4028		platform_sdk_final             bool
4029		targetSdkVersionInBp           string
4030		targetSdkVersionExpected       string
4031	}{
4032		{
4033			name:                           "Not enforcing Target SDK Version: Android.bp has older targetSdkVersion",
4034			enforceDefaultTargetSdkVersion: false,
4035			targetSdkVersionInBp:           "29",
4036			targetSdkVersionExpected:       "29",
4037		},
4038		{
4039			name:                           "[SDK finalised] Enforce Target SDK Version: Android.bp has current targetSdkVersion",
4040			enforceDefaultTargetSdkVersion: true,
4041			platform_sdk_final:             true,
4042			targetSdkVersionInBp:           "current",
4043			targetSdkVersionExpected:       "33",
4044		},
4045		{
4046			name:                           "Enforce Target SDK Version: Android.bp has current targetSdkVersion",
4047			enforceDefaultTargetSdkVersion: true,
4048			platform_sdk_final:             false,
4049			targetSdkVersionInBp:           "current",
4050			targetSdkVersionExpected:       "10000",
4051		},
4052	}
4053	for _, testCase := range testCases {
4054		errExpected := testCase.expectedError != ""
4055		bp := fmt.Sprintf(`
4056			android_test {
4057				name: "foo",
4058				enforce_default_target_sdk_version: %t,
4059				min_sdk_version: "29",
4060				target_sdk_version: "%v",
4061			}
4062		`, testCase.enforceDefaultTargetSdkVersion, testCase.targetSdkVersionInBp)
4063
4064		fixture := android.GroupFixturePreparers(
4065			PrepareForTestWithJavaDefaultModules,
4066			android.PrepareForTestWithAllowMissingDependencies,
4067			android.PrepareForTestWithAndroidMk,
4068			android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
4069				// explicitly set following platform variables to make the test deterministic
4070				variables.Platform_sdk_final = &testCase.platform_sdk_final
4071				variables.Platform_sdk_version = &platform_sdk_version
4072				variables.Platform_sdk_codename = &platform_sdk_codename
4073				variables.Unbundled_build = proptools.BoolPtr(true)
4074				variables.Unbundled_build_apps = []string{"sampleModule"}
4075			}),
4076		)
4077
4078		errorHandler := android.FixtureExpectsNoErrors
4079		if errExpected {
4080			errorHandler = android.FixtureExpectsAtLeastOneErrorMatchingPattern(testCase.expectedError)
4081		}
4082		result := fixture.ExtendWithErrorHandler(errorHandler).RunTestWithBp(t, bp)
4083
4084		if !errExpected {
4085			foo := result.ModuleForTests("foo", "android_common")
4086			manifestFixerArgs := foo.Output("manifest_fixer/AndroidManifest.xml").Args["args"]
4087			android.AssertStringDoesContain(t, testCase.name, manifestFixerArgs, "--targetSdkVersion  "+testCase.targetSdkVersionExpected)
4088		}
4089	}
4090}
4091
4092func TestAppMissingCertificateAllowMissingDependencies(t *testing.T) {
4093	result := android.GroupFixturePreparers(
4094		PrepareForTestWithJavaDefaultModules,
4095		android.PrepareForTestWithAllowMissingDependencies,
4096		android.PrepareForTestWithAndroidMk,
4097	).RunTestWithBp(t, `
4098		android_app {
4099			name: "foo",
4100			srcs: ["a.java"],
4101			certificate: ":missing_certificate",
4102			sdk_version: "current",
4103		}
4104
4105		android_app {
4106			name: "bar",
4107			srcs: ["a.java"],
4108			certificate: ":missing_certificate",
4109			product_specific: true,
4110			sdk_version: "current",
4111		}`)
4112
4113	foo := result.ModuleForTests("foo", "android_common")
4114	fooApk := foo.Output("foo.apk")
4115	if fooApk.Rule != android.ErrorRule {
4116		t.Fatalf("expected ErrorRule for foo.apk, got %s", fooApk.Rule.String())
4117	}
4118	android.AssertStringDoesContain(t, "expected error rule message", fooApk.Args["error"], "missing dependencies: missing_certificate\n")
4119}
4120
4121func TestAppIncludesJniPackages(t *testing.T) {
4122	ctx := android.GroupFixturePreparers(
4123		PrepareForTestWithJavaDefaultModules,
4124	).RunTestWithBp(t, `
4125		android_library_import {
4126			name: "aary-nodeps",
4127			aars: ["aary.aar"],
4128			extract_jni: true,
4129		}
4130
4131		android_library {
4132			name: "aary-lib",
4133			sdk_version: "current",
4134			min_sdk_version: "21",
4135			static_libs: ["aary-nodeps"],
4136		}
4137
4138		android_app {
4139			name: "aary-lib-dep",
4140			sdk_version: "current",
4141			min_sdk_version: "21",
4142			manifest: "AndroidManifest.xml",
4143			static_libs: ["aary-lib"],
4144			use_embedded_native_libs: true,
4145		}
4146
4147		android_app {
4148			name: "aary-import-dep",
4149			sdk_version: "current",
4150			min_sdk_version: "21",
4151			manifest: "AndroidManifest.xml",
4152			static_libs: ["aary-nodeps"],
4153			use_embedded_native_libs: true,
4154		}
4155
4156		android_app {
4157			name: "aary-no-use-embedded",
4158			sdk_version: "current",
4159			min_sdk_version: "21",
4160			manifest: "AndroidManifest.xml",
4161			static_libs: ["aary-nodeps"],
4162		}`)
4163
4164	testCases := []struct {
4165		name       string
4166		hasPackage bool
4167	}{
4168		{
4169			name:       "aary-import-dep",
4170			hasPackage: true,
4171		},
4172		{
4173			name:       "aary-lib-dep",
4174			hasPackage: true,
4175		},
4176		{
4177			name:       "aary-no-use-embedded",
4178			hasPackage: false,
4179		},
4180	}
4181
4182	for _, tc := range testCases {
4183		t.Run(tc.name, func(t *testing.T) {
4184			app := ctx.ModuleForTests(tc.name, "android_common")
4185
4186			outputFile := "jnilibs.zip"
4187			jniOutputLibZip := app.MaybeOutput(outputFile)
4188			if jniOutputLibZip.Rule == nil && !tc.hasPackage {
4189				return
4190			}
4191
4192			jniPackage := "arm64-v8a_jni.zip"
4193			inputs := jniOutputLibZip.Inputs
4194			foundPackage := false
4195			for i := 0; i < len(inputs); i++ {
4196				if strings.Contains(inputs[i].String(), jniPackage) {
4197					foundPackage = true
4198				}
4199			}
4200			if foundPackage != tc.hasPackage {
4201				t.Errorf("expected to find %v in %v inputs; inputs = %v", jniPackage, outputFile, inputs)
4202			}
4203		})
4204	}
4205}
4206
4207func TestTargetSdkVersionMtsTests(t *testing.T) {
4208	platformSdkCodename := "Tiramisu"
4209	android_test := "android_test"
4210	android_test_helper_app := "android_test_helper_app"
4211	bpTemplate := `
4212	%v {
4213		name: "mytest",
4214		min_sdk_version: "34",
4215		target_sdk_version: "%v",
4216		test_suites: ["othersuite", "%v"],
4217	}
4218	`
4219	testCases := []struct {
4220		desc                     string
4221		moduleType               string
4222		targetSdkVersionInBp     string
4223		targetSdkVersionExpected string
4224		testSuites               string
4225	}{
4226		{
4227			desc:                     "Non-MTS android_test_apps targeting current should not be upgraded to 10000",
4228			moduleType:               android_test,
4229			targetSdkVersionInBp:     "current",
4230			targetSdkVersionExpected: platformSdkCodename,
4231			testSuites:               "non-mts-suite",
4232		},
4233		{
4234			desc:                     "MTS android_test_apps targeting released sdks should not be upgraded to 10000",
4235			moduleType:               android_test,
4236			targetSdkVersionInBp:     "29",
4237			targetSdkVersionExpected: "29",
4238			testSuites:               "mts-suite",
4239		},
4240		{
4241			desc:                     "MTS android_test_apps targeting current should be upgraded to 10000",
4242			moduleType:               android_test,
4243			targetSdkVersionInBp:     "current",
4244			targetSdkVersionExpected: "10000",
4245			testSuites:               "mts-suite",
4246		},
4247		{
4248			desc:                     "MTS android_test_helper_apps targeting current should be upgraded to 10000",
4249			moduleType:               android_test_helper_app,
4250			targetSdkVersionInBp:     "current",
4251			targetSdkVersionExpected: "10000",
4252			testSuites:               "mts-suite",
4253		},
4254	}
4255	fixture := android.GroupFixturePreparers(
4256		prepareForJavaTest,
4257		android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
4258			variables.Platform_sdk_codename = &platformSdkCodename
4259			variables.Platform_version_active_codenames = []string{platformSdkCodename}
4260		}),
4261	)
4262	for _, testCase := range testCases {
4263		result := fixture.RunTestWithBp(t, fmt.Sprintf(bpTemplate, testCase.moduleType, testCase.targetSdkVersionInBp, testCase.testSuites))
4264		mytest := result.ModuleForTests("mytest", "android_common")
4265		manifestFixerArgs := mytest.Output("manifest_fixer/AndroidManifest.xml").Args["args"]
4266		android.AssertStringDoesContain(t, testCase.desc, manifestFixerArgs, "--targetSdkVersion  "+testCase.targetSdkVersionExpected)
4267	}
4268}
4269
4270func TestPrivappAllowlist(t *testing.T) {
4271	testJavaError(t, "privileged must be set in order to use privapp_allowlist", `
4272		android_app {
4273			name: "foo",
4274			srcs: ["a.java"],
4275			privapp_allowlist: "perms.xml",
4276		}
4277	`)
4278
4279	result := PrepareForTestWithJavaDefaultModules.RunTestWithBp(
4280		t,
4281		`
4282		android_app {
4283			name: "foo",
4284			srcs: ["a.java"],
4285			privapp_allowlist: "privapp_allowlist_com.android.foo.xml",
4286			privileged: true,
4287			sdk_version: "current",
4288		}
4289		override_android_app {
4290			name: "bar",
4291			base: "foo",
4292			package_name: "com.google.android.foo",
4293		}
4294		`,
4295	)
4296	app := result.ModuleForTests("foo", "android_common")
4297	overrideApp := result.ModuleForTests("foo", "android_common_bar")
4298
4299	// verify that privapp allowlist is created for override apps
4300	overrideApp.Output("out/soong/.intermediates/foo/android_common_bar/privapp_allowlist_com.google.android.foo.xml")
4301	expectedAllowlistInput := "privapp_allowlist_com.android.foo.xml"
4302	overrideActualAllowlistInput := overrideApp.Rule("modifyAllowlist").Input.String()
4303	if expectedAllowlistInput != overrideActualAllowlistInput {
4304		t.Errorf("expected override allowlist to be %q; got %q", expectedAllowlistInput, overrideActualAllowlistInput)
4305	}
4306
4307	// verify that permissions are copied to device
4308	app.Output("out/soong/target/product/test_device/system/etc/permissions/foo.xml")
4309	overrideApp.Output("out/soong/target/product/test_device/system/etc/permissions/bar.xml")
4310}
4311
4312func TestPrivappAllowlistAndroidMk(t *testing.T) {
4313	result := android.GroupFixturePreparers(
4314		PrepareForTestWithJavaDefaultModules,
4315		android.PrepareForTestWithAndroidMk,
4316	).RunTestWithBp(
4317		t,
4318		`
4319		android_app {
4320			name: "foo",
4321			srcs: ["a.java"],
4322			privapp_allowlist: "privapp_allowlist_com.android.foo.xml",
4323			privileged: true,
4324			sdk_version: "current",
4325		}
4326		override_android_app {
4327			name: "bar",
4328			base: "foo",
4329			package_name: "com.google.android.foo",
4330		}
4331		`,
4332	)
4333	baseApp := result.ModuleForTests("foo", "android_common")
4334	overrideApp := result.ModuleForTests("foo", "android_common_bar")
4335
4336	baseAndroidApp := baseApp.Module().(*AndroidApp)
4337	baseEntries := android.AndroidMkEntriesForTest(t, result.TestContext, baseAndroidApp)[0]
4338	android.AssertStringMatches(
4339		t,
4340		"androidmk has incorrect LOCAL_SOONG_INSTALLED_MODULE; expected to find foo.apk",
4341		baseEntries.EntryMap["LOCAL_SOONG_INSTALLED_MODULE"][0],
4342		"\\S+foo.apk",
4343	)
4344	android.AssertStringMatches(
4345		t,
4346		"androidmk has incorrect LOCAL_SOONG_INSTALL_PAIRS; expected to it to include foo.apk",
4347		baseEntries.EntryMap["LOCAL_SOONG_INSTALL_PAIRS"][0],
4348		"\\S+foo.apk",
4349	)
4350	android.AssertStringMatches(
4351		t,
4352		"androidmk has incorrect LOCAL_SOONG_INSTALL_PAIRS; expected to it to include app",
4353		baseEntries.EntryMap["LOCAL_SOONG_INSTALL_PAIRS"][0],
4354		"\\S+foo.apk:\\S+/target/product/test_device/system/priv-app/foo/foo.apk",
4355	)
4356	android.AssertStringMatches(
4357		t,
4358		"androidmk has incorrect LOCAL_SOONG_INSTALL_PAIRS; expected to it to include privapp_allowlist",
4359		baseEntries.EntryMap["LOCAL_SOONG_INSTALL_PAIRS"][0],
4360		"privapp_allowlist_com.android.foo.xml:\\S+/target/product/test_device/system/etc/permissions/foo.xml",
4361	)
4362
4363	overrideAndroidApp := overrideApp.Module().(*AndroidApp)
4364	overrideEntries := android.AndroidMkEntriesForTest(t, result.TestContext, overrideAndroidApp)[0]
4365	android.AssertStringMatches(
4366		t,
4367		"androidmk has incorrect LOCAL_SOONG_INSTALLED_MODULE; expected to find bar.apk",
4368		overrideEntries.EntryMap["LOCAL_SOONG_INSTALLED_MODULE"][0],
4369		"\\S+bar.apk",
4370	)
4371	android.AssertStringMatches(
4372		t,
4373		"androidmk has incorrect LOCAL_SOONG_INSTALL_PAIRS; expected to it to include bar.apk",
4374		overrideEntries.EntryMap["LOCAL_SOONG_INSTALL_PAIRS"][0],
4375		"\\S+bar.apk",
4376	)
4377	android.AssertStringMatches(
4378		t,
4379		"androidmk has incorrect LOCAL_SOONG_INSTALL_PAIRS; expected to it to include app",
4380		overrideEntries.EntryMap["LOCAL_SOONG_INSTALL_PAIRS"][0],
4381		"\\S+bar.apk:\\S+/target/product/test_device/system/priv-app/bar/bar.apk",
4382	)
4383	android.AssertStringMatches(
4384		t,
4385		"androidmk has incorrect LOCAL_SOONG_INSTALL_PAIRS; expected to it to include privapp_allowlist",
4386		overrideEntries.EntryMap["LOCAL_SOONG_INSTALL_PAIRS"][0],
4387		"\\S+soong/.intermediates/foo/android_common_bar/privapp_allowlist_com.google.android.foo.xml:\\S+/target/product/test_device/system/etc/permissions/bar.xml",
4388	)
4389}
4390
4391func TestAppFlagsPackages(t *testing.T) {
4392	ctx := android.GroupFixturePreparers(
4393		prepareForJavaTest,
4394		android.FixtureMergeMockFs(
4395			map[string][]byte{
4396				"res/layout/layout.xml":         nil,
4397				"res/values/strings.xml":        nil,
4398				"res/values-en-rUS/strings.xml": nil,
4399			},
4400		),
4401	).RunTestWithBp(t, `
4402		android_app {
4403			name: "foo",
4404			srcs: ["a.java"],
4405			sdk_version: "current",
4406			flags_packages: [
4407				"bar",
4408				"baz",
4409			],
4410		}
4411		aconfig_declarations {
4412			name: "bar",
4413			package: "com.example.package.bar",
4414			container: "com.android.foo",
4415			srcs: [
4416				"bar.aconfig",
4417			],
4418		}
4419		aconfig_declarations {
4420			name: "baz",
4421			package: "com.example.package.baz",
4422			container: "com.android.foo",
4423			srcs: [
4424				"baz.aconfig",
4425			],
4426		}
4427	`)
4428
4429	foo := ctx.ModuleForTests("foo", "android_common")
4430
4431	// android_app module depends on aconfig_declarations listed in flags_packages
4432	android.AssertBoolEquals(t, "foo expected to depend on bar", true,
4433		CheckModuleHasDependency(t, ctx.TestContext, "foo", "android_common", "bar"))
4434
4435	android.AssertBoolEquals(t, "foo expected to depend on baz", true,
4436		CheckModuleHasDependency(t, ctx.TestContext, "foo", "android_common", "baz"))
4437
4438	aapt2LinkRule := foo.Rule("android/soong/java.aapt2Link")
4439	linkInFlags := aapt2LinkRule.Args["inFlags"]
4440	android.AssertStringDoesContain(t,
4441		"aapt2 link command expected to pass feature flags arguments",
4442		linkInFlags,
4443		"--feature-flags @out/soong/.intermediates/bar/intermediate.txt --feature-flags @out/soong/.intermediates/baz/intermediate.txt",
4444	)
4445
4446	aapt2CompileRule := foo.Rule("android/soong/java.aapt2Compile")
4447	compileFlags := aapt2CompileRule.Args["cFlags"]
4448	android.AssertStringDoesContain(t,
4449		"aapt2 compile command expected to pass feature flags arguments",
4450		compileFlags,
4451		"--feature-flags @out/soong/.intermediates/bar/intermediate.txt --feature-flags @out/soong/.intermediates/baz/intermediate.txt",
4452	)
4453}
4454
4455func TestAppFlagsPackagesPropagation(t *testing.T) {
4456	ctx := testApp(t, `
4457		aconfig_declarations {
4458			name: "foo",
4459			package: "com.example.package.foo",
4460			container: "com.android.foo",
4461			srcs: [
4462				"foo.aconfig",
4463			],
4464		}
4465		aconfig_declarations {
4466			name: "bar",
4467			package: "com.example.package.bar",
4468			container: "com.android.bar",
4469			srcs: [
4470				"bar.aconfig",
4471			],
4472		}
4473		aconfig_declarations {
4474			name: "baz",
4475			package: "com.example.package.baz",
4476			container: "com.android.baz",
4477			srcs: [
4478				"baz.aconfig",
4479			],
4480		}
4481		android_library {
4482			name: "foo_lib",
4483			srcs: ["a.java"],
4484			sdk_version: "current",
4485			flags_packages: [
4486				"foo",
4487			],
4488		}
4489		android_library {
4490			name: "bar_lib",
4491			srcs: ["a.java"],
4492			sdk_version: "current",
4493			flags_packages: [
4494				"bar",
4495			],
4496		}
4497		android_app {
4498			name: "baz_app",
4499			srcs: ["a.java"],
4500			sdk_version: "current",
4501			flags_packages: [
4502				"baz",
4503			],
4504			static_libs: [
4505				"bar_lib",
4506			],
4507			libs: [
4508				"foo_lib",
4509			],
4510		}
4511	`)
4512
4513	bazApp := ctx.ModuleForTests("baz_app", "android_common")
4514
4515	// android_app module depends on aconfig_declarations listed in flags_packages
4516	// and that of static libs, but not libs
4517	aapt2LinkRule := bazApp.Rule("android/soong/java.aapt2Link")
4518	linkInFlags := aapt2LinkRule.Args["inFlags"]
4519	android.AssertStringDoesContain(t,
4520		"aapt2 link command expected to pass feature flags arguments of flags_packages and that of its static libs",
4521		linkInFlags,
4522		"--feature-flags @out/soong/.intermediates/bar/intermediate.txt --feature-flags @out/soong/.intermediates/baz/intermediate.txt",
4523	)
4524	android.AssertStringDoesNotContain(t,
4525		"aapt2 link command expected to not pass feature flags arguments of flags_packages of its libs",
4526		linkInFlags,
4527		"--feature-flags @out/soong/.intermediates/foo/intermediate.txt",
4528	)
4529}
4530
4531// Test that dexpreopt is disabled if an optional_uses_libs exists, but does not provide an implementation.
4532func TestNoDexpreoptOptionalUsesLibDoesNotHaveImpl(t *testing.T) {
4533	bp := `
4534		java_sdk_library_import {
4535			name: "sdklib_noimpl",
4536			public: {
4537				jars: ["stub.jar"],
4538			},
4539		}
4540		android_app {
4541			name: "app",
4542			srcs: ["a.java"],
4543			sdk_version: "current",
4544			optional_uses_libs: [
4545				"sdklib_noimpl",
4546			],
4547		}
4548	`
4549	result := prepareForJavaTest.RunTestWithBp(t, bp)
4550	dexpreopt := result.ModuleForTests("app", "android_common").MaybeRule("dexpreopt").Rule
4551	android.AssertBoolEquals(t, "dexpreopt should be disabled if optional_uses_libs does not have an implementation", true, dexpreopt == nil)
4552}
4553
4554func TestTestOnlyApp(t *testing.T) {
4555	t.Parallel()
4556	ctx := android.GroupFixturePreparers(
4557		prepareForJavaTest,
4558	).RunTestWithBp(t, `
4559                // These should be test-only
4560                android_test {
4561                        name: "android-test",
4562                }
4563                android_test_helper_app {
4564                        name: "helper-app",
4565                }
4566                override_android_test {
4567                        name: "override-test",
4568                        base: "android-app",
4569                }
4570                // And these should not be
4571		android_app {
4572			name: "android-app",
4573                        srcs: ["b.java"],
4574			sdk_version: "current",
4575		}
4576	`)
4577
4578	expectedTestOnly := []string{
4579		"android-test",
4580		"helper-app",
4581		"override-test",
4582	}
4583
4584	expectedTopLevel := []string{
4585		"android-test",
4586		"override-test",
4587	}
4588
4589	assertTestOnlyAndTopLevel(t, ctx, expectedTestOnly, expectedTopLevel)
4590}
4591
4592func TestAppStem(t *testing.T) {
4593	ctx := testApp(t, `
4594				android_app {
4595					name: "foo",
4596					srcs: ["a.java"],
4597					stem: "foo-new",
4598					sdk_version: "current",
4599				}`)
4600
4601	foo := ctx.ModuleForTests("foo", "android_common")
4602
4603	outputs := fmt.Sprint(foo.AllOutputs())
4604	if !strings.Contains(outputs, "foo-new.apk") {
4605		t.Errorf("Module output does not contain expected apk %s", "foo-new.apk")
4606	}
4607}
4608
4609func TestAppMinSdkVersionOverride(t *testing.T) {
4610	result := android.GroupFixturePreparers(
4611		PrepareForTestWithJavaDefaultModules,
4612	).RunTestWithBp(t, `
4613		android_app {
4614			name: "com.android.foo",
4615			srcs: ["a.java"],
4616			sdk_version: "current",
4617			min_sdk_version: "31",
4618			updatable: true,
4619		}
4620		override_android_app {
4621			name: "com.android.go.foo",
4622			base: "com.android.foo",
4623			min_sdk_version: "33",
4624		}
4625	`)
4626	foo := result.ModuleForTests("com.android.foo", "android_common").Rule("manifestFixer")
4627	fooOverride := result.ModuleForTests("com.android.foo", "android_common_com.android.go.foo").Rule("manifestFixer")
4628
4629	android.AssertStringDoesContain(t,
4630		"com.android.foo: expected manifest fixer to set minSdkVersion to T",
4631		foo.BuildParams.Args["args"],
4632		"--minSdkVersion  31",
4633	)
4634	android.AssertStringDoesContain(t,
4635		"com.android.go.foo: expected manifest fixer to set minSdkVersion to T",
4636		fooOverride.BuildParams.Args["args"],
4637		"--minSdkVersion  33",
4638	)
4639
4640}
4641
4642func TestNotApplyDefaultUpdatableModuleVersion(t *testing.T) {
4643	result := android.GroupFixturePreparers(
4644		PrepareForTestWithJavaDefaultModules,
4645	).RunTestWithBp(t, `
4646		android_app {
4647			name: "com.android.foo",
4648			srcs: ["a.java"],
4649			sdk_version: "current",
4650			min_sdk_version: "31",
4651		}
4652	`)
4653	foo := result.ModuleForTests("com.android.foo", "android_common").Rule("manifestFixer")
4654	android.AssertStringDoesNotContain(t,
4655		"com.android.foo: expected manifest fixer to not set override-placeholder-version",
4656		foo.BuildParams.Args["args"],
4657		"--override-placeholder-version",
4658	)
4659}
4660
4661func TestNotApplyOverrideApexManifestDefaultVersion(t *testing.T) {
4662	result := android.GroupFixturePreparers(
4663		PrepareForTestWithJavaDefaultModules,
4664		android.FixtureMergeEnv(map[string]string{
4665			"OVERRIDE_APEX_MANIFEST_DEFAULT_VERSION": "1234",
4666		}),
4667	).RunTestWithBp(t, `
4668		android_app {
4669			name: "com.android.foo",
4670			srcs: ["a.java"],
4671			sdk_version: "current",
4672			min_sdk_version: "31",
4673		}
4674	`)
4675	foo := result.ModuleForTests("com.android.foo", "android_common").Rule("manifestFixer")
4676	android.AssertStringDoesNotContain(t,
4677		"com.android.foo: expected manifest fixer to not set override-placeholder-version",
4678		foo.BuildParams.Args["args"],
4679		"--override-placeholder-version",
4680	)
4681}
4682
4683func TestResourcesWithFlagDirectories(t *testing.T) {
4684	result := android.GroupFixturePreparers(
4685		PrepareForTestWithJavaDefaultModules,
4686		android.FixtureMergeMockFs(android.MockFS{
4687			"res/flag(test.package.flag1)/values/bools.xml":                          nil,
4688			"res/flag(!test.package.flag2)/values/bools.xml":                         nil,
4689			"res/flag(test.package.flag1)/values-config/strings_google_services.xml": nil,
4690			"res/flags(test.package.flag1)/values/strings.xml":                       nil,
4691		}),
4692	).RunTestWithBp(t, `
4693		android_library {
4694			name: "foo",
4695			srcs: ["a.java"],
4696			use_resource_processor: true,
4697			resource_dirs: [
4698				"res",
4699			],
4700		}
4701	`)
4702	fooModule := result.ModuleForTests("foo", "android_common")
4703	compileOutputPaths := fooModule.Rule("aapt2Compile").Outputs.Strings()
4704
4705	android.AssertStringListContains(
4706		t,
4707		"Expected to generate flag path",
4708		compileOutputPaths,
4709		"out/soong/.intermediates/foo/android_common/aapt2/res/values_bools.(test.package.flag1).arsc.flat",
4710	)
4711	android.AssertStringListContains(
4712		t,
4713		"Expected to generate flag path with ! prefix in name",
4714		compileOutputPaths,
4715		"out/soong/.intermediates/foo/android_common/aapt2/res/values_bools.(!test.package.flag2).arsc.flat",
4716	)
4717	android.AssertStringListContains(
4718		t,
4719		"Expected to generate flag path with configs",
4720		compileOutputPaths,
4721		"out/soong/.intermediates/foo/android_common/aapt2/res/values-config_strings_google_services.(test.package.flag1).arsc.flat",
4722	)
4723	android.AssertStringListDoesNotContain(
4724		t,
4725		"Expected to not generate flag path with non-flag(flag_name) pattern",
4726		compileOutputPaths,
4727		"out/soong/.intermediates/foo/android_common/aapt2/res/values_strings.(test.package.flag1).arsc.flat",
4728	)
4729}
4730
4731func TestAutogeneratedStaticRro(t *testing.T) {
4732	t.Parallel()
4733	bp := `
4734android_app {
4735	name: "foo",
4736	srcs: ["foo.java"],
4737	platform_apis: true,
4738}
4739override_android_app {
4740	name: "override_foo",
4741	base: "foo",
4742}
4743`
4744	testCases := []struct {
4745		desc               string
4746		preparer           android.FixturePreparer
4747		overlayApkExpected bool
4748	}{
4749		{
4750			desc:               "No DEVICE_PACKAGE_OVERLAYS, no overlay .apk file",
4751			overlayApkExpected: false,
4752		},
4753		{
4754			desc:               "DEVICE_PACKAGE_OVERLAYS exists, but the directory is empty",
4755			overlayApkExpected: false,
4756			preparer: android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
4757				variables.DeviceResourceOverlays = []string{"device/company/test_product"}
4758			}),
4759		},
4760		{
4761			desc:               "DEVICE_PACKAGE_OVERLAYS exists, directory is non-empty, but does not contain a matching resource dir",
4762			overlayApkExpected: false,
4763			preparer: android.GroupFixturePreparers(
4764				android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
4765					variables.DeviceResourceOverlays = []string{"device/company/test_product"}
4766				}),
4767				android.MockFS{
4768					"res/foo.xml": nil,
4769					"device/company/test_product/different_res/foo.xml": nil, // different dir
4770				}.AddToFixture(),
4771			),
4772		},
4773		{
4774			desc:               "DEVICE_PACKAGE_OVERLAYS and the directory contain a matching resource dir",
4775			overlayApkExpected: true,
4776			preparer: android.GroupFixturePreparers(
4777				android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
4778					variables.DeviceResourceOverlays = []string{"device/company/test_product"}
4779				}),
4780				android.MockFS{
4781					"res/foo.xml": nil,
4782					"device/company/test_product/res/foo.xml": nil,
4783				}.AddToFixture(),
4784			),
4785		},
4786	}
4787	for _, tc := range testCases {
4788		result := android.GroupFixturePreparers(
4789			PrepareForTestWithJavaDefaultModules,
4790			android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
4791				variables.EnforceRROTargets = []string{"*"}
4792			}),
4793			android.OptionalFixturePreparer(tc.preparer),
4794		).RunTestWithBp(t, bp)
4795		vendorOverlayApk := result.ModuleForTests("foo__test_product__auto_generated_rro_vendor", "android_arm64_armv8-a").MaybeOutput("foo__test_product__auto_generated_rro_vendor.apk")
4796		android.AssertBoolEquals(t, tc.desc, tc.overlayApkExpected, vendorOverlayApk.Rule != nil)
4797		overrideVendorOverlayApk := result.ModuleForTests("override_foo__test_product__auto_generated_rro_vendor", "android_arm64_armv8-a").MaybeOutput("override_foo__test_product__auto_generated_rro_vendor.apk")
4798		android.AssertBoolEquals(t, tc.desc, tc.overlayApkExpected, overrideVendorOverlayApk.Rule != nil)
4799	}
4800}
4801
4802func TestNoAutogeneratedStaticRroForDisabledOverrideApps(t *testing.T) {
4803	t.Parallel()
4804	bp := `
4805soong_config_module_type {
4806	name: "my_custom_override_android_app",
4807	module_type: "override_android_app",
4808	config_namespace: "my_namespace",
4809	value_variables: ["my_app_enabled"],
4810	properties: ["enabled"],
4811}
4812soong_config_bool_variable {
4813	name: "my_app_enabled",
4814}
4815android_app {
4816	name: "foo",
4817	srcs: ["foo.java"],
4818	platform_apis: true,
4819}
4820my_custom_override_android_app {
4821	name: "override_foo",
4822	base: "foo",
4823	soong_config_variables: {
4824		my_app_enabled: {
4825			enabled: true,
4826			conditions_default: {
4827				enabled: false
4828			},
4829		},
4830	}
4831}
4832`
4833	testCases := []struct {
4834		desc               string
4835		preparer           android.FixturePreparer
4836		overlayApkExpected bool
4837	}{
4838		{
4839			desc:               "my_app_enabled is empty",
4840			overlayApkExpected: false,
4841		},
4842		{
4843			desc:               "my_app_enabled is true",
4844			overlayApkExpected: true,
4845			preparer: android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
4846				variables.VendorVars = map[string]map[string]string{
4847					"my_namespace": {
4848						"my_app_enabled": "true",
4849					},
4850				}
4851			}),
4852		},
4853	}
4854	for _, tc := range testCases {
4855		result := android.GroupFixturePreparers(
4856			PrepareForTestWithJavaDefaultModules,
4857			android.PrepareForTestWithSoongConfigModuleBuildComponents,
4858			android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
4859				variables.EnforceRROTargets = []string{"*"}
4860			}),
4861			android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
4862				variables.DeviceResourceOverlays = []string{"device/company/test_product"}
4863			}),
4864			android.MockFS{
4865				"res/foo.xml": nil,
4866				"device/company/test_product/res/foo.xml": nil,
4867			}.AddToFixture(),
4868			android.OptionalFixturePreparer(tc.preparer),
4869		).RunTestWithBp(t, bp)
4870		overrideVendorOverlayApk := result.ModuleForTests("override_foo__test_product__auto_generated_rro_vendor", "android_arm64_armv8-a").Module().(*AutogenRuntimeResourceOverlay)
4871		android.AssertBoolEquals(t, tc.desc, tc.overlayApkExpected, overrideVendorOverlayApk.exportPackage != nil)
4872	}
4873}
4874