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