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	"android/soong/genrule"
31)
32
33// testApp runs tests using the prepareForJavaTest
34//
35// See testJava for an explanation as to how to stop using this deprecated method.
36//
37// deprecated
38func testApp(t *testing.T, bp string) *android.TestContext {
39	t.Helper()
40	result := prepareForJavaTest.RunTestWithBp(t, bp)
41	return result.TestContext
42}
43
44func TestApp(t *testing.T) {
45	resourceFiles := []string{
46		"res/layout/layout.xml",
47		"res/values/strings.xml",
48		"res/values-en-rUS/strings.xml",
49	}
50
51	compiledResourceFiles := []string{
52		"aapt2/res/layout_layout.xml.flat",
53		"aapt2/res/values_strings.arsc.flat",
54		"aapt2/res/values-en-rUS_strings.arsc.flat",
55	}
56
57	for _, moduleType := range []string{"android_app", "android_library"} {
58		t.Run(moduleType, func(t *testing.T) {
59			result := android.GroupFixturePreparers(
60				prepareForJavaTest,
61				android.FixtureModifyMockFS(func(fs android.MockFS) {
62					for _, file := range resourceFiles {
63						fs[file] = nil
64					}
65				}),
66			).RunTestWithBp(t, moduleType+` {
67					name: "foo",
68					srcs: ["a.java"],
69					sdk_version: "current"
70				}
71			`)
72
73			foo := result.ModuleForTests("foo", "android_common")
74
75			var expectedLinkImplicits []string
76
77			manifestFixer := foo.Output("manifest_fixer/AndroidManifest.xml")
78			expectedLinkImplicits = append(expectedLinkImplicits, manifestFixer.Output.String())
79
80			frameworkRes := result.ModuleForTests("framework-res", "android_common")
81			expectedLinkImplicits = append(expectedLinkImplicits,
82				frameworkRes.Output("package-res.apk").Output.String())
83
84			// Test the mapping from input files to compiled output file names
85			compile := foo.Output(compiledResourceFiles[0])
86			android.AssertDeepEquals(t, "aapt2 compile inputs", resourceFiles, compile.Inputs.Strings())
87
88			compiledResourceOutputs := compile.Outputs.Strings()
89			sort.Strings(compiledResourceOutputs)
90
91			expectedLinkImplicits = append(expectedLinkImplicits, compiledResourceOutputs...)
92
93			list := foo.Output("aapt2/res.list")
94			expectedLinkImplicits = append(expectedLinkImplicits, list.Output.String())
95
96			// Check that the link rule uses
97			res := result.ModuleForTests("foo", "android_common").Output("package-res.apk")
98			android.AssertDeepEquals(t, "aapt2 link implicits", expectedLinkImplicits, res.Implicits.Strings())
99		})
100	}
101}
102
103func TestAppSplits(t *testing.T) {
104	ctx := testApp(t, `
105				android_app {
106					name: "foo",
107					srcs: ["a.java"],
108					package_splits: ["v4", "v7,hdpi"],
109					sdk_version: "current"
110				}`)
111
112	foo := ctx.ModuleForTests("foo", "android_common")
113
114	expectedOutputs := []string{
115		"out/soong/.intermediates/foo/android_common/foo.apk",
116		"out/soong/.intermediates/foo/android_common/foo_v4.apk",
117		"out/soong/.intermediates/foo/android_common/foo_v7_hdpi.apk",
118	}
119	for _, expectedOutput := range expectedOutputs {
120		foo.Output(expectedOutput)
121	}
122
123	outputFiles, err := foo.Module().(*AndroidApp).OutputFiles("")
124	if err != nil {
125		t.Fatal(err)
126	}
127	android.AssertPathsRelativeToTopEquals(t, `OutputFiles("")`, expectedOutputs, outputFiles)
128}
129
130func TestPlatformAPIs(t *testing.T) {
131	testJava(t, `
132		android_app {
133			name: "foo",
134			srcs: ["a.java"],
135			platform_apis: true,
136		}
137	`)
138
139	testJava(t, `
140		android_app {
141			name: "foo",
142			srcs: ["a.java"],
143			sdk_version: "current",
144		}
145	`)
146
147	testJavaError(t, "platform_apis must be true when sdk_version is empty.", `
148		android_app {
149			name: "bar",
150			srcs: ["b.java"],
151		}
152	`)
153
154	testJavaError(t, "platform_apis must be false when sdk_version is not empty.", `
155		android_app {
156			name: "bar",
157			srcs: ["b.java"],
158			sdk_version: "system_current",
159			platform_apis: true,
160		}
161	`)
162}
163
164func TestAndroidAppLinkType(t *testing.T) {
165	testJava(t, `
166		android_app {
167			name: "foo",
168			srcs: ["a.java"],
169			libs: ["bar"],
170			static_libs: ["baz"],
171			platform_apis: true,
172		}
173
174		java_library {
175			name: "bar",
176			sdk_version: "current",
177			srcs: ["b.java"],
178		}
179
180		android_library {
181			name: "baz",
182			sdk_version: "system_current",
183			srcs: ["c.java"],
184		}
185	`)
186
187	testJavaError(t, "consider adjusting sdk_version: OR platform_apis:", `
188		android_app {
189			name: "foo",
190			srcs: ["a.java"],
191			libs: ["bar"],
192			sdk_version: "current",
193			static_libs: ["baz"],
194		}
195
196		java_library {
197			name: "bar",
198			sdk_version: "current",
199			srcs: ["b.java"],
200		}
201
202		android_library {
203			name: "baz",
204			sdk_version: "system_current",
205			srcs: ["c.java"],
206		}
207	`)
208
209	testJava(t, `
210		android_app {
211			name: "foo",
212			srcs: ["a.java"],
213			libs: ["bar"],
214			sdk_version: "system_current",
215			static_libs: ["baz"],
216		}
217
218		java_library {
219			name: "bar",
220			sdk_version: "current",
221			srcs: ["b.java"],
222		}
223
224		android_library {
225			name: "baz",
226			sdk_version: "system_current",
227			srcs: ["c.java"],
228		}
229	`)
230
231	testJavaError(t, "consider adjusting sdk_version: OR platform_apis:", `
232		android_app {
233			name: "foo",
234			srcs: ["a.java"],
235			libs: ["bar"],
236			sdk_version: "system_current",
237			static_libs: ["baz"],
238		}
239
240		java_library {
241			name: "bar",
242			sdk_version: "current",
243			srcs: ["b.java"],
244		}
245
246		android_library {
247			name: "baz",
248			srcs: ["c.java"],
249		}
250	`)
251}
252
253func TestUpdatableApps(t *testing.T) {
254	testCases := []struct {
255		name          string
256		bp            string
257		expectedError string
258	}{
259		{
260			name: "Stable public SDK",
261			bp: `android_app {
262					name: "foo",
263					srcs: ["a.java"],
264					sdk_version: "29",
265					min_sdk_version: "29",
266					updatable: true,
267				}`,
268		},
269		{
270			name: "Stable system SDK",
271			bp: `android_app {
272					name: "foo",
273					srcs: ["a.java"],
274					sdk_version: "system_29",
275					min_sdk_version: "29",
276					updatable: true,
277				}`,
278		},
279		{
280			name: "Current public SDK",
281			bp: `android_app {
282					name: "foo",
283					srcs: ["a.java"],
284					sdk_version: "current",
285					min_sdk_version: "29",
286					updatable: true,
287				}`,
288		},
289		{
290			name: "Current system SDK",
291			bp: `android_app {
292					name: "foo",
293					srcs: ["a.java"],
294					sdk_version: "system_current",
295					min_sdk_version: "29",
296					updatable: true,
297				}`,
298		},
299		{
300			name: "Current module SDK",
301			bp: `android_app {
302					name: "foo",
303					srcs: ["a.java"],
304					sdk_version: "module_current",
305					min_sdk_version: "29",
306					updatable: true,
307				}`,
308		},
309		{
310			name: "Current core SDK",
311			bp: `android_app {
312					name: "foo",
313					srcs: ["a.java"],
314					sdk_version: "core_current",
315					min_sdk_version: "29",
316					updatable: true,
317				}`,
318		},
319		{
320			name: "No Platform APIs",
321			bp: `android_app {
322					name: "foo",
323					srcs: ["a.java"],
324					platform_apis: true,
325					min_sdk_version: "29",
326					updatable: true,
327				}`,
328			expectedError: "Updatable apps must use stable SDKs",
329		},
330		{
331			name: "No Core Platform APIs",
332			bp: `android_app {
333					name: "foo",
334					srcs: ["a.java"],
335					sdk_version: "core_platform",
336					min_sdk_version: "29",
337					updatable: true,
338				}`,
339			expectedError: "Updatable apps must use stable SDKs",
340		},
341		{
342			name: "No unspecified APIs",
343			bp: `android_app {
344					name: "foo",
345					srcs: ["a.java"],
346					updatable: true,
347					min_sdk_version: "29",
348				}`,
349			expectedError: "Updatable apps must use stable SDK",
350		},
351		{
352			name: "Must specify min_sdk_version",
353			bp: `android_app {
354					name: "app_without_min_sdk_version",
355					srcs: ["a.java"],
356					sdk_version: "29",
357					updatable: true,
358				}`,
359			expectedError: "updatable apps must set min_sdk_version.",
360		},
361	}
362
363	for _, test := range testCases {
364		t.Run(test.name, func(t *testing.T) {
365			errorHandler := android.FixtureExpectsNoErrors
366			if test.expectedError != "" {
367				errorHandler = android.FixtureExpectsAtLeastOneErrorMatchingPattern(test.expectedError)
368			}
369			android.GroupFixturePreparers(
370				prepareForJavaTest, FixtureWithPrebuiltApis(map[string][]string{
371					"29": {"foo"},
372				})).
373				ExtendWithErrorHandler(errorHandler).RunTestWithBp(t, test.bp)
374		})
375	}
376}
377
378func TestUpdatableApps_TransitiveDepsShouldSetMinSdkVersion(t *testing.T) {
379	testJavaError(t, `module "bar".*: should support min_sdk_version\(29\)`, cc.GatherRequiredDepsForTest(android.Android)+`
380		android_app {
381			name: "foo",
382			srcs: ["a.java"],
383			updatable: true,
384			sdk_version: "current",
385			min_sdk_version: "29",
386			static_libs: ["bar"],
387		}
388
389		java_library {
390			name: "bar",
391			sdk_version: "current",
392		}
393	`)
394}
395
396func TestUpdatableApps_JniLibsShouldShouldSupportMinSdkVersion(t *testing.T) {
397	testJava(t, cc.GatherRequiredDepsForTest(android.Android)+`
398		android_app {
399			name: "foo",
400			srcs: ["a.java"],
401			updatable: true,
402			sdk_version: "current",
403			min_sdk_version: "current",
404			jni_libs: ["libjni"],
405		}
406
407		cc_library {
408			name: "libjni",
409			stl: "none",
410			system_shared_libs: [],
411			sdk_version: "current",
412		}
413	`)
414}
415
416func TestUpdatableApps_JniLibShouldBeBuiltAgainstMinSdkVersion(t *testing.T) {
417	bp := cc.GatherRequiredDepsForTest(android.Android) + `
418		android_app {
419			name: "foo",
420			srcs: ["a.java"],
421			updatable: true,
422			sdk_version: "current",
423			min_sdk_version: "29",
424			jni_libs: ["libjni"],
425		}
426
427		cc_library {
428			name: "libjni",
429			stl: "none",
430			system_shared_libs: [],
431			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("partialLd").Output
447	expectedCrtEnd := ctx.ModuleForTests("crtend_so",
448		"android_arm64_armv8-a_sdk_29").Rule("partialLd").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		}
486	`
487	testJavaError(t, `"libjni" .*: sdk_version\(current\) is higher than min_sdk_version\(29\)`, bp)
488}
489
490func TestUpdatableApps_ErrorIfDepSdkVersionIsHigher(t *testing.T) {
491	bp := cc.GatherRequiredDepsForTest(android.Android) + `
492		android_app {
493			name: "foo",
494			srcs: ["a.java"],
495			updatable: true,
496			sdk_version: "current",
497			min_sdk_version: "29",  // this APK should support 29
498			jni_libs: ["libjni"],
499		}
500
501		cc_library {
502			name: "libjni",
503			stl: "none",
504			shared_libs: ["libbar"],
505			system_shared_libs: [],
506			sdk_version: "27",
507		}
508
509		cc_library {
510			name: "libbar",
511			stl: "none",
512			system_shared_libs: [],
513			sdk_version: "current",
514		}
515	`
516	testJavaError(t, `"libjni" .*: links "libbar" built against newer API version "current"`, bp)
517}
518
519func TestResourceDirs(t *testing.T) {
520	testCases := []struct {
521		name      string
522		prop      string
523		resources []string
524	}{
525		{
526			name:      "no resource_dirs",
527			prop:      "",
528			resources: []string{"res/res/values/strings.xml"},
529		},
530		{
531			name:      "resource_dirs",
532			prop:      `resource_dirs: ["res"]`,
533			resources: []string{"res/res/values/strings.xml"},
534		},
535		{
536			name:      "empty resource_dirs",
537			prop:      `resource_dirs: []`,
538			resources: nil,
539		},
540	}
541
542	fs := android.MockFS{
543		"res/res/values/strings.xml": nil,
544	}
545
546	bp := `
547			android_app {
548				name: "foo",
549				sdk_version: "current",
550				%s
551			}
552		`
553
554	for _, testCase := range testCases {
555		t.Run(testCase.name, func(t *testing.T) {
556			result := android.GroupFixturePreparers(
557				PrepareForTestWithJavaDefaultModules,
558				PrepareForTestWithOverlayBuildComponents,
559				fs.AddToFixture(),
560			).RunTestWithBp(t, fmt.Sprintf(bp, testCase.prop))
561
562			module := result.ModuleForTests("foo", "android_common")
563			resourceList := module.MaybeOutput("aapt2/res.list")
564
565			var resources []string
566			if resourceList.Rule != nil {
567				for _, compiledResource := range resourceList.Inputs.Strings() {
568					resources = append(resources, module.Output(compiledResource).Inputs.Strings()...)
569				}
570			}
571
572			android.AssertDeepEquals(t, "resource files", testCase.resources, resources)
573		})
574	}
575}
576
577func TestLibraryAssets(t *testing.T) {
578	bp := `
579			android_app {
580				name: "foo",
581				sdk_version: "current",
582				static_libs: ["lib1", "lib2", "lib3"],
583			}
584
585			android_library {
586				name: "lib1",
587				sdk_version: "current",
588				asset_dirs: ["assets_a"],
589			}
590
591			android_library {
592				name: "lib2",
593				sdk_version: "current",
594			}
595
596			android_library {
597				name: "lib3",
598				sdk_version: "current",
599				static_libs: ["lib4"],
600			}
601
602			android_library {
603				name: "lib4",
604				sdk_version: "current",
605				asset_dirs: ["assets_b"],
606			}
607		`
608
609	testCases := []struct {
610		name          string
611		assetFlag     string
612		assetPackages []string
613	}{
614		{
615			name: "foo",
616			// lib1 has its own asset. lib3 doesn't have any, but provides lib4's transitively.
617			assetPackages: []string{
618				"out/soong/.intermediates/foo/android_common/aapt2/package-res.apk",
619				"out/soong/.intermediates/lib1/android_common/assets.zip",
620				"out/soong/.intermediates/lib3/android_common/assets.zip",
621			},
622		},
623		{
624			name:      "lib1",
625			assetFlag: "-A assets_a",
626		},
627		{
628			name: "lib2",
629		},
630		{
631			name: "lib3",
632			assetPackages: []string{
633				"out/soong/.intermediates/lib3/android_common/aapt2/package-res.apk",
634				"out/soong/.intermediates/lib4/android_common/assets.zip",
635			},
636		},
637		{
638			name:      "lib4",
639			assetFlag: "-A assets_b",
640		},
641	}
642	ctx := testApp(t, bp)
643
644	for _, test := range testCases {
645		t.Run(test.name, func(t *testing.T) {
646			m := ctx.ModuleForTests(test.name, "android_common")
647
648			// Check asset flag in aapt2 link flags
649			var aapt2link android.TestingBuildParams
650			if len(test.assetPackages) > 0 {
651				aapt2link = m.Output("aapt2/package-res.apk")
652			} else {
653				aapt2link = m.Output("package-res.apk")
654			}
655			aapt2link = aapt2link
656			aapt2Flags := aapt2link.Args["flags"]
657			if test.assetFlag != "" {
658				android.AssertStringDoesContain(t, "asset flag", aapt2Flags, test.assetFlag)
659			} else {
660				android.AssertStringDoesNotContain(t, "aapt2 link flags", aapt2Flags, " -A ")
661			}
662
663			// Check asset merge rule.
664			if len(test.assetPackages) > 0 {
665				mergeAssets := m.Output("package-res.apk")
666				android.AssertPathsRelativeToTopEquals(t, "mergeAssets inputs", test.assetPackages, mergeAssets.Inputs)
667			}
668		})
669	}
670}
671
672func TestAppJavaResources(t *testing.T) {
673	bp := `
674			android_app {
675				name: "foo",
676				sdk_version: "current",
677				java_resources: ["resources/a"],
678				srcs: ["a.java"],
679			}
680
681			android_app {
682				name: "bar",
683				sdk_version: "current",
684				java_resources: ["resources/a"],
685			}
686		`
687
688	ctx := testApp(t, bp)
689
690	foo := ctx.ModuleForTests("foo", "android_common")
691	fooResources := foo.Output("res/foo.jar")
692	fooDexJar := foo.Output("dex-withres/foo.jar")
693	fooDexJarAligned := foo.Output("dex-withres-aligned/foo.jar")
694	fooApk := foo.Rule("combineApk")
695
696	if g, w := fooDexJar.Inputs.Strings(), fooResources.Output.String(); !android.InList(w, g) {
697		t.Errorf("expected resource jar %q in foo dex jar inputs %q", w, g)
698	}
699
700	if g, w := fooDexJarAligned.Input.String(), fooDexJar.Output.String(); g != w {
701		t.Errorf("expected dex jar %q in foo aligned dex jar inputs %q", w, g)
702	}
703
704	if g, w := fooApk.Inputs.Strings(), fooDexJarAligned.Output.String(); !android.InList(w, g) {
705		t.Errorf("expected aligned dex jar %q in foo apk inputs %q", w, g)
706	}
707
708	bar := ctx.ModuleForTests("bar", "android_common")
709	barResources := bar.Output("res/bar.jar")
710	barApk := bar.Rule("combineApk")
711
712	if g, w := barApk.Inputs.Strings(), barResources.Output.String(); !android.InList(w, g) {
713		t.Errorf("expected resources jar %q in bar apk inputs %q", w, g)
714	}
715}
716
717func TestAndroidResources(t *testing.T) {
718	testCases := []struct {
719		name                       string
720		enforceRROTargets          []string
721		enforceRROExcludedOverlays []string
722		resourceFiles              map[string][]string
723		overlayFiles               map[string][]string
724		rroDirs                    map[string][]string
725	}{
726		{
727			name:                       "no RRO",
728			enforceRROTargets:          nil,
729			enforceRROExcludedOverlays: nil,
730			resourceFiles: map[string][]string{
731				"foo":  nil,
732				"bar":  {"bar/res/res/values/strings.xml"},
733				"lib":  nil,
734				"lib2": {"lib2/res/res/values/strings.xml"},
735			},
736			overlayFiles: map[string][]string{
737				"foo": {
738					"out/soong/.intermediates/lib2/android_common/package-res.apk",
739					"out/soong/.intermediates/lib/android_common/package-res.apk",
740					"out/soong/.intermediates/lib3/android_common/package-res.apk",
741					"foo/res/res/values/strings.xml",
742					"device/vendor/blah/static_overlay/foo/res/values/strings.xml",
743					"device/vendor/blah/overlay/foo/res/values/strings.xml",
744					"product/vendor/blah/overlay/foo/res/values/strings.xml",
745				},
746				"bar": {
747					"device/vendor/blah/static_overlay/bar/res/values/strings.xml",
748					"device/vendor/blah/overlay/bar/res/values/strings.xml",
749				},
750				"lib": {
751					"out/soong/.intermediates/lib2/android_common/package-res.apk",
752					"lib/res/res/values/strings.xml",
753					"device/vendor/blah/overlay/lib/res/values/strings.xml",
754				},
755			},
756			rroDirs: map[string][]string{
757				"foo": nil,
758				"bar": nil,
759			},
760		},
761		{
762			name:                       "enforce RRO on foo",
763			enforceRROTargets:          []string{"foo"},
764			enforceRROExcludedOverlays: []string{"device/vendor/blah/static_overlay"},
765			resourceFiles: map[string][]string{
766				"foo":  nil,
767				"bar":  {"bar/res/res/values/strings.xml"},
768				"lib":  nil,
769				"lib2": {"lib2/res/res/values/strings.xml"},
770			},
771			overlayFiles: map[string][]string{
772				"foo": {
773					"out/soong/.intermediates/lib2/android_common/package-res.apk",
774					"out/soong/.intermediates/lib/android_common/package-res.apk",
775					"out/soong/.intermediates/lib3/android_common/package-res.apk",
776					"foo/res/res/values/strings.xml",
777					"device/vendor/blah/static_overlay/foo/res/values/strings.xml",
778				},
779				"bar": {
780					"device/vendor/blah/static_overlay/bar/res/values/strings.xml",
781					"device/vendor/blah/overlay/bar/res/values/strings.xml",
782				},
783				"lib": {
784					"out/soong/.intermediates/lib2/android_common/package-res.apk",
785					"lib/res/res/values/strings.xml",
786				},
787			},
788
789			rroDirs: map[string][]string{
790				"foo": {
791					"device:device/vendor/blah/overlay/foo/res",
792					"product:product/vendor/blah/overlay/foo/res",
793					"device:device/vendor/blah/overlay/lib/res",
794				},
795				"bar": nil,
796				"lib": {"device:device/vendor/blah/overlay/lib/res"},
797			},
798		},
799		{
800			name:              "enforce RRO on all",
801			enforceRROTargets: []string{"*"},
802			enforceRROExcludedOverlays: []string{
803				// Excluding specific apps/res directories also allowed.
804				"device/vendor/blah/static_overlay/foo",
805				"device/vendor/blah/static_overlay/bar/res",
806			},
807			resourceFiles: map[string][]string{
808				"foo":  nil,
809				"bar":  {"bar/res/res/values/strings.xml"},
810				"lib":  nil,
811				"lib2": {"lib2/res/res/values/strings.xml"},
812			},
813			overlayFiles: map[string][]string{
814				"foo": {
815					"out/soong/.intermediates/lib2/android_common/package-res.apk",
816					"out/soong/.intermediates/lib/android_common/package-res.apk",
817					"out/soong/.intermediates/lib3/android_common/package-res.apk",
818					"foo/res/res/values/strings.xml",
819					"device/vendor/blah/static_overlay/foo/res/values/strings.xml",
820				},
821				"bar": {"device/vendor/blah/static_overlay/bar/res/values/strings.xml"},
822				"lib": {
823					"out/soong/.intermediates/lib2/android_common/package-res.apk",
824					"lib/res/res/values/strings.xml",
825				},
826			},
827			rroDirs: map[string][]string{
828				"foo": {
829					"device:device/vendor/blah/overlay/foo/res",
830					"product:product/vendor/blah/overlay/foo/res",
831					// Lib dep comes after the direct deps
832					"device:device/vendor/blah/overlay/lib/res",
833				},
834				"bar": {"device:device/vendor/blah/overlay/bar/res"},
835				"lib": {"device:device/vendor/blah/overlay/lib/res"},
836			},
837		},
838	}
839
840	deviceResourceOverlays := []string{
841		"device/vendor/blah/overlay",
842		"device/vendor/blah/overlay2",
843		"device/vendor/blah/static_overlay",
844	}
845
846	productResourceOverlays := []string{
847		"product/vendor/blah/overlay",
848	}
849
850	fs := android.MockFS{
851		"foo/res/res/values/strings.xml":                               nil,
852		"bar/res/res/values/strings.xml":                               nil,
853		"lib/res/res/values/strings.xml":                               nil,
854		"lib2/res/res/values/strings.xml":                              nil,
855		"device/vendor/blah/overlay/foo/res/values/strings.xml":        nil,
856		"device/vendor/blah/overlay/bar/res/values/strings.xml":        nil,
857		"device/vendor/blah/overlay/lib/res/values/strings.xml":        nil,
858		"device/vendor/blah/static_overlay/foo/res/values/strings.xml": nil,
859		"device/vendor/blah/static_overlay/bar/res/values/strings.xml": nil,
860		"device/vendor/blah/overlay2/res/values/strings.xml":           nil,
861		"product/vendor/blah/overlay/foo/res/values/strings.xml":       nil,
862	}
863
864	bp := `
865			android_app {
866				name: "foo",
867				sdk_version: "current",
868				resource_dirs: ["foo/res"],
869				static_libs: ["lib", "lib3"],
870			}
871
872			android_app {
873				name: "bar",
874				sdk_version: "current",
875				resource_dirs: ["bar/res"],
876			}
877
878			android_library {
879				name: "lib",
880				sdk_version: "current",
881				resource_dirs: ["lib/res"],
882				static_libs: ["lib2"],
883			}
884
885			android_library {
886				name: "lib2",
887				sdk_version: "current",
888				resource_dirs: ["lib2/res"],
889			}
890
891			// This library has the same resources as lib (should not lead to dupe RROs)
892			android_library {
893				name: "lib3",
894				sdk_version: "current",
895				resource_dirs: ["lib/res"]
896			}
897		`
898
899	for _, testCase := range testCases {
900		t.Run(testCase.name, func(t *testing.T) {
901			result := android.GroupFixturePreparers(
902				PrepareForTestWithJavaDefaultModules,
903				PrepareForTestWithOverlayBuildComponents,
904				fs.AddToFixture(),
905				android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
906					variables.DeviceResourceOverlays = deviceResourceOverlays
907					variables.ProductResourceOverlays = productResourceOverlays
908					if testCase.enforceRROTargets != nil {
909						variables.EnforceRROTargets = testCase.enforceRROTargets
910					}
911					if testCase.enforceRROExcludedOverlays != nil {
912						variables.EnforceRROExcludedOverlays = testCase.enforceRROExcludedOverlays
913					}
914				}),
915			).RunTestWithBp(t, bp)
916
917			resourceListToFiles := func(module android.TestingModule, list []string) (files []string) {
918				for _, o := range list {
919					res := module.MaybeOutput(o)
920					if res.Rule != nil {
921						// If the overlay is compiled as part of this module (i.e. a .arsc.flat file),
922						// verify the inputs to the .arsc.flat rule.
923						files = append(files, res.Inputs.Strings()...)
924					} else {
925						// Otherwise, verify the full path to the output of the other module
926						files = append(files, o)
927					}
928				}
929				return files
930			}
931
932			getResources := func(moduleName string) (resourceFiles, overlayFiles, rroDirs []string) {
933				module := result.ModuleForTests(moduleName, "android_common")
934				resourceList := module.MaybeOutput("aapt2/res.list")
935				if resourceList.Rule != nil {
936					resourceFiles = resourceListToFiles(module, android.PathsRelativeToTop(resourceList.Inputs))
937				}
938				overlayList := module.MaybeOutput("aapt2/overlay.list")
939				if overlayList.Rule != nil {
940					overlayFiles = resourceListToFiles(module, android.PathsRelativeToTop(overlayList.Inputs))
941				}
942
943				for _, d := range module.Module().(AndroidLibraryDependency).ExportedRRODirs() {
944					var prefix string
945					if d.overlayType == device {
946						prefix = "device:"
947					} else if d.overlayType == product {
948						prefix = "product:"
949					} else {
950						t.Fatalf("Unexpected overlayType %d", d.overlayType)
951					}
952					rroDirs = append(rroDirs, prefix+android.PathRelativeToTop(d.path))
953				}
954
955				return resourceFiles, overlayFiles, rroDirs
956			}
957
958			modules := []string{"foo", "bar", "lib", "lib2"}
959			for _, module := range modules {
960				resourceFiles, overlayFiles, rroDirs := getResources(module)
961
962				if !reflect.DeepEqual(resourceFiles, testCase.resourceFiles[module]) {
963					t.Errorf("expected %s resource files:\n  %#v\n got:\n  %#v",
964						module, testCase.resourceFiles[module], resourceFiles)
965				}
966				if !reflect.DeepEqual(overlayFiles, testCase.overlayFiles[module]) {
967					t.Errorf("expected %s overlay files:\n  %#v\n got:\n  %#v",
968						module, testCase.overlayFiles[module], overlayFiles)
969				}
970				if !reflect.DeepEqual(rroDirs, testCase.rroDirs[module]) {
971					t.Errorf("expected %s rroDirs:  %#v\n got:\n  %#v",
972						module, testCase.rroDirs[module], rroDirs)
973				}
974			}
975		})
976	}
977}
978
979func checkSdkVersion(t *testing.T, result *android.TestResult, expectedSdkVersion string) {
980	foo := result.ModuleForTests("foo", "android_common")
981	link := foo.Output("package-res.apk")
982	linkFlags := strings.Split(link.Args["flags"], " ")
983	min := android.IndexList("--min-sdk-version", linkFlags)
984	target := android.IndexList("--target-sdk-version", linkFlags)
985
986	if min == -1 || target == -1 || min == len(linkFlags)-1 || target == len(linkFlags)-1 {
987		t.Fatalf("missing --min-sdk-version or --target-sdk-version in link flags: %q", linkFlags)
988	}
989
990	gotMinSdkVersion := linkFlags[min+1]
991	gotTargetSdkVersion := linkFlags[target+1]
992
993	android.AssertStringEquals(t, "incorrect --min-sdk-version", expectedSdkVersion, gotMinSdkVersion)
994
995	android.AssertStringEquals(t, "incorrect --target-sdk-version", expectedSdkVersion, gotTargetSdkVersion)
996}
997
998func TestAppSdkVersion(t *testing.T) {
999	testCases := []struct {
1000		name                  string
1001		sdkVersion            string
1002		platformSdkInt        int
1003		platformSdkCodename   string
1004		platformSdkFinal      bool
1005		expectedMinSdkVersion string
1006		platformApis          bool
1007		activeCodenames       []string
1008	}{
1009		{
1010			name:                  "current final SDK",
1011			sdkVersion:            "current",
1012			platformSdkInt:        27,
1013			platformSdkCodename:   "REL",
1014			platformSdkFinal:      true,
1015			expectedMinSdkVersion: "27",
1016		},
1017		{
1018			name:                  "current non-final SDK",
1019			sdkVersion:            "current",
1020			platformSdkInt:        27,
1021			platformSdkCodename:   "OMR1",
1022			platformSdkFinal:      false,
1023			expectedMinSdkVersion: "OMR1",
1024			activeCodenames:       []string{"OMR1"},
1025		},
1026		{
1027			name:                  "default final SDK",
1028			sdkVersion:            "",
1029			platformApis:          true,
1030			platformSdkInt:        27,
1031			platformSdkCodename:   "REL",
1032			platformSdkFinal:      true,
1033			expectedMinSdkVersion: "27",
1034		},
1035		{
1036			name:                  "default non-final SDK",
1037			sdkVersion:            "",
1038			platformApis:          true,
1039			platformSdkInt:        27,
1040			platformSdkCodename:   "OMR1",
1041			platformSdkFinal:      false,
1042			expectedMinSdkVersion: "OMR1",
1043			activeCodenames:       []string{"OMR1"},
1044		},
1045		{
1046			name:                  "14",
1047			sdkVersion:            "14",
1048			expectedMinSdkVersion: "14",
1049			platformSdkCodename:   "S",
1050			activeCodenames:       []string{"S"},
1051		},
1052	}
1053
1054	for _, moduleType := range []string{"android_app", "android_library"} {
1055		for _, test := range testCases {
1056			t.Run(moduleType+" "+test.name, func(t *testing.T) {
1057				platformApiProp := ""
1058				if test.platformApis {
1059					platformApiProp = "platform_apis: true,"
1060				}
1061				bp := fmt.Sprintf(`%s {
1062					name: "foo",
1063					srcs: ["a.java"],
1064					sdk_version: "%s",
1065					%s
1066				}`, moduleType, test.sdkVersion, platformApiProp)
1067
1068				result := android.GroupFixturePreparers(
1069					prepareForJavaTest,
1070					android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
1071						variables.Platform_sdk_version = &test.platformSdkInt
1072						variables.Platform_sdk_codename = &test.platformSdkCodename
1073						variables.Platform_version_active_codenames = test.activeCodenames
1074						variables.Platform_sdk_final = &test.platformSdkFinal
1075					}),
1076					FixtureWithPrebuiltApis(map[string][]string{
1077						"14": {"foo"},
1078					}),
1079				).RunTestWithBp(t, bp)
1080
1081				checkSdkVersion(t, result, test.expectedMinSdkVersion)
1082			})
1083		}
1084	}
1085}
1086
1087func TestVendorAppSdkVersion(t *testing.T) {
1088	testCases := []struct {
1089		name                                  string
1090		sdkVersion                            string
1091		platformSdkInt                        int
1092		platformSdkCodename                   string
1093		platformSdkFinal                      bool
1094		deviceCurrentApiLevelForVendorModules string
1095		expectedMinSdkVersion                 string
1096	}{
1097		{
1098			name:                                  "current final SDK",
1099			sdkVersion:                            "current",
1100			platformSdkInt:                        29,
1101			platformSdkCodename:                   "REL",
1102			platformSdkFinal:                      true,
1103			deviceCurrentApiLevelForVendorModules: "29",
1104			expectedMinSdkVersion:                 "29",
1105		},
1106		{
1107			name:                                  "current final SDK",
1108			sdkVersion:                            "current",
1109			platformSdkInt:                        29,
1110			platformSdkCodename:                   "REL",
1111			platformSdkFinal:                      true,
1112			deviceCurrentApiLevelForVendorModules: "28",
1113			expectedMinSdkVersion:                 "28",
1114		},
1115		{
1116			name:                                  "current final SDK",
1117			sdkVersion:                            "current",
1118			platformSdkInt:                        29,
1119			platformSdkCodename:                   "Q",
1120			platformSdkFinal:                      false,
1121			deviceCurrentApiLevelForVendorModules: "28",
1122			expectedMinSdkVersion:                 "28",
1123		},
1124	}
1125
1126	for _, moduleType := range []string{"android_app", "android_library"} {
1127		for _, sdkKind := range []string{"", "system_"} {
1128			for _, test := range testCases {
1129				t.Run(moduleType+" "+test.name, func(t *testing.T) {
1130					bp := fmt.Sprintf(`%s {
1131						name: "foo",
1132						srcs: ["a.java"],
1133						sdk_version: "%s%s",
1134						vendor: true,
1135					}`, moduleType, sdkKind, test.sdkVersion)
1136
1137					result := android.GroupFixturePreparers(
1138						prepareForJavaTest,
1139						android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
1140							variables.Platform_sdk_version = &test.platformSdkInt
1141							variables.Platform_sdk_codename = &test.platformSdkCodename
1142							variables.Platform_sdk_final = &test.platformSdkFinal
1143							variables.DeviceCurrentApiLevelForVendorModules = &test.deviceCurrentApiLevelForVendorModules
1144							variables.DeviceSystemSdkVersions = []string{"28", "29"}
1145						}),
1146						FixtureWithPrebuiltApis(map[string][]string{
1147							"28":      {"foo"},
1148							"29":      {"foo"},
1149							"current": {"foo"},
1150						}),
1151					).RunTestWithBp(t, bp)
1152
1153					checkSdkVersion(t, result, test.expectedMinSdkVersion)
1154				})
1155			}
1156		}
1157	}
1158}
1159
1160func TestJNIABI(t *testing.T) {
1161	ctx, _ := testJava(t, cc.GatherRequiredDepsForTest(android.Android)+`
1162		cc_library {
1163			name: "libjni",
1164			system_shared_libs: [],
1165			sdk_version: "current",
1166			stl: "none",
1167		}
1168
1169		android_test {
1170			name: "test",
1171			sdk_version: "core_platform",
1172			jni_libs: ["libjni"],
1173		}
1174
1175		android_test {
1176			name: "test_first",
1177			sdk_version: "core_platform",
1178			compile_multilib: "first",
1179			jni_libs: ["libjni"],
1180		}
1181
1182		android_test {
1183			name: "test_both",
1184			sdk_version: "core_platform",
1185			compile_multilib: "both",
1186			jni_libs: ["libjni"],
1187		}
1188
1189		android_test {
1190			name: "test_32",
1191			sdk_version: "core_platform",
1192			compile_multilib: "32",
1193			jni_libs: ["libjni"],
1194		}
1195
1196		android_test {
1197			name: "test_64",
1198			sdk_version: "core_platform",
1199			compile_multilib: "64",
1200			jni_libs: ["libjni"],
1201		}
1202		`)
1203
1204	testCases := []struct {
1205		name string
1206		abis []string
1207	}{
1208		{"test", []string{"arm64-v8a"}},
1209		{"test_first", []string{"arm64-v8a"}},
1210		{"test_both", []string{"arm64-v8a", "armeabi-v7a"}},
1211		{"test_32", []string{"armeabi-v7a"}},
1212		{"test_64", []string{"arm64-v8a"}},
1213	}
1214
1215	for _, test := range testCases {
1216		t.Run(test.name, func(t *testing.T) {
1217			app := ctx.ModuleForTests(test.name, "android_common")
1218			jniLibZip := app.Output("jnilibs.zip")
1219			var abis []string
1220			args := strings.Fields(jniLibZip.Args["jarArgs"])
1221			for i := 0; i < len(args); i++ {
1222				if args[i] == "-P" {
1223					abis = append(abis, filepath.Base(args[i+1]))
1224					i++
1225				}
1226			}
1227			if !reflect.DeepEqual(abis, test.abis) {
1228				t.Errorf("want abis %v, got %v", test.abis, abis)
1229			}
1230		})
1231	}
1232}
1233
1234func TestAppSdkVersionByPartition(t *testing.T) {
1235	testJavaError(t, "sdk_version must have a value when the module is located at vendor or product", `
1236		android_app {
1237			name: "foo",
1238			srcs: ["a.java"],
1239			vendor: true,
1240			platform_apis: true,
1241		}
1242	`)
1243
1244	testJava(t, `
1245		android_app {
1246			name: "bar",
1247			srcs: ["b.java"],
1248			platform_apis: true,
1249		}
1250	`)
1251
1252	for _, enforce := range []bool{true, false} {
1253		bp := `
1254			android_app {
1255				name: "foo",
1256				srcs: ["a.java"],
1257				product_specific: true,
1258				platform_apis: true,
1259			}
1260		`
1261
1262		errorHandler := android.FixtureExpectsNoErrors
1263		if enforce {
1264			errorHandler = android.FixtureExpectsAtLeastOneErrorMatchingPattern("sdk_version must have a value when the module is located at vendor or product")
1265		}
1266
1267		android.GroupFixturePreparers(
1268			PrepareForTestWithJavaDefaultModules,
1269			android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
1270				variables.EnforceProductPartitionInterface = proptools.BoolPtr(enforce)
1271			}),
1272		).
1273			ExtendWithErrorHandler(errorHandler).
1274			RunTestWithBp(t, bp)
1275	}
1276}
1277
1278func TestJNIPackaging(t *testing.T) {
1279	ctx, _ := testJava(t, cc.GatherRequiredDepsForTest(android.Android)+`
1280		cc_library {
1281			name: "libjni",
1282			system_shared_libs: [],
1283			stl: "none",
1284			sdk_version: "current",
1285		}
1286
1287		android_app {
1288			name: "app",
1289			jni_libs: ["libjni"],
1290			sdk_version: "current",
1291		}
1292
1293		android_app {
1294			name: "app_noembed",
1295			jni_libs: ["libjni"],
1296			use_embedded_native_libs: false,
1297			sdk_version: "current",
1298		}
1299
1300		android_app {
1301			name: "app_embed",
1302			jni_libs: ["libjni"],
1303			use_embedded_native_libs: true,
1304			sdk_version: "current",
1305		}
1306
1307		android_test {
1308			name: "test",
1309			sdk_version: "current",
1310			jni_libs: ["libjni"],
1311		}
1312
1313		android_test {
1314			name: "test_noembed",
1315			sdk_version: "current",
1316			jni_libs: ["libjni"],
1317			use_embedded_native_libs: false,
1318		}
1319
1320		android_test_helper_app {
1321			name: "test_helper",
1322			sdk_version: "current",
1323			jni_libs: ["libjni"],
1324		}
1325
1326		android_test_helper_app {
1327			name: "test_helper_noembed",
1328			sdk_version: "current",
1329			jni_libs: ["libjni"],
1330			use_embedded_native_libs: false,
1331		}
1332		`)
1333
1334	testCases := []struct {
1335		name       string
1336		packaged   bool
1337		compressed bool
1338	}{
1339		{"app", false, false},
1340		{"app_noembed", false, false},
1341		{"app_embed", true, false},
1342		{"test", true, false},
1343		{"test_noembed", true, true},
1344		{"test_helper", true, false},
1345		{"test_helper_noembed", true, true},
1346	}
1347
1348	for _, test := range testCases {
1349		t.Run(test.name, func(t *testing.T) {
1350			app := ctx.ModuleForTests(test.name, "android_common")
1351			jniLibZip := app.MaybeOutput("jnilibs.zip")
1352			if g, w := (jniLibZip.Rule != nil), test.packaged; g != w {
1353				t.Errorf("expected jni packaged %v, got %v", w, g)
1354			}
1355
1356			if jniLibZip.Rule != nil {
1357				if g, w := !strings.Contains(jniLibZip.Args["jarArgs"], "-L 0"), test.compressed; g != w {
1358					t.Errorf("expected jni compressed %v, got %v", w, g)
1359				}
1360
1361				if !strings.Contains(jniLibZip.Implicits[0].String(), "_sdk_") {
1362					t.Errorf("expected input %q to use sdk variant", jniLibZip.Implicits[0].String())
1363				}
1364			}
1365		})
1366	}
1367}
1368
1369func TestJNISDK(t *testing.T) {
1370	ctx, _ := testJava(t, cc.GatherRequiredDepsForTest(android.Android)+`
1371		cc_library {
1372			name: "libjni",
1373			system_shared_libs: [],
1374			stl: "none",
1375			sdk_version: "current",
1376		}
1377
1378		android_test {
1379			name: "app_platform",
1380			jni_libs: ["libjni"],
1381			platform_apis: true,
1382		}
1383
1384		android_test {
1385			name: "app_sdk",
1386			jni_libs: ["libjni"],
1387			sdk_version: "current",
1388		}
1389
1390		android_test {
1391			name: "app_force_platform",
1392			jni_libs: ["libjni"],
1393			sdk_version: "current",
1394			jni_uses_platform_apis: true,
1395		}
1396
1397		android_test {
1398			name: "app_force_sdk",
1399			jni_libs: ["libjni"],
1400			platform_apis: true,
1401			jni_uses_sdk_apis: true,
1402		}
1403
1404		cc_library {
1405			name: "libvendorjni",
1406			system_shared_libs: [],
1407			stl: "none",
1408			vendor: true,
1409		}
1410
1411		android_test {
1412			name: "app_vendor",
1413			jni_libs: ["libvendorjni"],
1414			sdk_version: "current",
1415			vendor: true,
1416		}
1417	`)
1418
1419	testCases := []struct {
1420		name      string
1421		sdkJNI    bool
1422		vendorJNI bool
1423	}{
1424		{name: "app_platform"},
1425		{name: "app_sdk", sdkJNI: true},
1426		{name: "app_force_platform"},
1427		{name: "app_force_sdk", sdkJNI: true},
1428		{name: "app_vendor", vendorJNI: true},
1429	}
1430
1431	platformJNI := ctx.ModuleForTests("libjni", "android_arm64_armv8-a_shared").
1432		Output("libjni.so").Output.String()
1433	sdkJNI := ctx.ModuleForTests("libjni", "android_arm64_armv8-a_sdk_shared").
1434		Output("libjni.so").Output.String()
1435	vendorJNI := ctx.ModuleForTests("libvendorjni", "android_arm64_armv8-a_shared").
1436		Output("libvendorjni.so").Output.String()
1437
1438	for _, test := range testCases {
1439		t.Run(test.name, func(t *testing.T) {
1440			app := ctx.ModuleForTests(test.name, "android_common")
1441
1442			jniLibZip := app.MaybeOutput("jnilibs.zip")
1443			if len(jniLibZip.Implicits) != 1 {
1444				t.Fatalf("expected exactly one jni library, got %q", jniLibZip.Implicits.Strings())
1445			}
1446			gotJNI := jniLibZip.Implicits[0].String()
1447
1448			if test.sdkJNI {
1449				if gotJNI != sdkJNI {
1450					t.Errorf("expected SDK JNI library %q, got %q", sdkJNI, gotJNI)
1451				}
1452			} else if test.vendorJNI {
1453				if gotJNI != vendorJNI {
1454					t.Errorf("expected platform JNI library %q, got %q", vendorJNI, gotJNI)
1455				}
1456			} else {
1457				if gotJNI != platformJNI {
1458					t.Errorf("expected platform JNI library %q, got %q", platformJNI, gotJNI)
1459				}
1460			}
1461		})
1462	}
1463
1464	t.Run("jni_uses_platform_apis_error", func(t *testing.T) {
1465		testJavaError(t, `jni_uses_platform_apis: can only be set for modules that set sdk_version`, `
1466			android_test {
1467				name: "app_platform",
1468				platform_apis: true,
1469				jni_uses_platform_apis: true,
1470			}
1471		`)
1472	})
1473
1474	t.Run("jni_uses_sdk_apis_error", func(t *testing.T) {
1475		testJavaError(t, `jni_uses_sdk_apis: can only be set for modules that do not set sdk_version`, `
1476			android_test {
1477				name: "app_sdk",
1478				sdk_version: "current",
1479				jni_uses_sdk_apis: true,
1480			}
1481		`)
1482	})
1483
1484}
1485
1486func TestCertificates(t *testing.T) {
1487	testCases := []struct {
1488		name                string
1489		bp                  string
1490		certificateOverride string
1491		expectedLineage     string
1492		expectedCertificate string
1493	}{
1494		{
1495			name: "default",
1496			bp: `
1497				android_app {
1498					name: "foo",
1499					srcs: ["a.java"],
1500					sdk_version: "current",
1501				}
1502			`,
1503			certificateOverride: "",
1504			expectedLineage:     "",
1505			expectedCertificate: "build/make/target/product/security/testkey.x509.pem build/make/target/product/security/testkey.pk8",
1506		},
1507		{
1508			name: "module certificate property",
1509			bp: `
1510				android_app {
1511					name: "foo",
1512					srcs: ["a.java"],
1513					certificate: ":new_certificate",
1514					sdk_version: "current",
1515				}
1516
1517				android_app_certificate {
1518					name: "new_certificate",
1519					certificate: "cert/new_cert",
1520				}
1521			`,
1522			certificateOverride: "",
1523			expectedLineage:     "",
1524			expectedCertificate: "cert/new_cert.x509.pem cert/new_cert.pk8",
1525		},
1526		{
1527			name: "path certificate property",
1528			bp: `
1529				android_app {
1530					name: "foo",
1531					srcs: ["a.java"],
1532					certificate: "expiredkey",
1533					sdk_version: "current",
1534				}
1535			`,
1536			certificateOverride: "",
1537			expectedLineage:     "",
1538			expectedCertificate: "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8",
1539		},
1540		{
1541			name: "certificate overrides",
1542			bp: `
1543				android_app {
1544					name: "foo",
1545					srcs: ["a.java"],
1546					certificate: "expiredkey",
1547					sdk_version: "current",
1548				}
1549
1550				android_app_certificate {
1551					name: "new_certificate",
1552					certificate: "cert/new_cert",
1553				}
1554			`,
1555			certificateOverride: "foo:new_certificate",
1556			expectedLineage:     "",
1557			expectedCertificate: "cert/new_cert.x509.pem cert/new_cert.pk8",
1558		},
1559		{
1560			name: "certificate lineage",
1561			bp: `
1562				android_app {
1563					name: "foo",
1564					srcs: ["a.java"],
1565					certificate: ":new_certificate",
1566					lineage: "lineage.bin",
1567					sdk_version: "current",
1568				}
1569
1570				android_app_certificate {
1571					name: "new_certificate",
1572					certificate: "cert/new_cert",
1573				}
1574			`,
1575			certificateOverride: "",
1576			expectedLineage:     "--lineage lineage.bin",
1577			expectedCertificate: "cert/new_cert.x509.pem cert/new_cert.pk8",
1578		},
1579		{
1580			name: "lineage from filegroup",
1581			bp: `
1582				android_app {
1583					name: "foo",
1584					srcs: ["a.java"],
1585					certificate: ":new_certificate",
1586					lineage: ":lineage_bin",
1587					sdk_version: "current",
1588				}
1589
1590				android_app_certificate {
1591					name: "new_certificate",
1592					certificate: "cert/new_cert",
1593				}
1594
1595				filegroup {
1596					name: "lineage_bin",
1597					srcs: ["lineage.bin"],
1598				}
1599			`,
1600			certificateOverride: "",
1601			expectedLineage:     "--lineage lineage.bin",
1602			expectedCertificate: "cert/new_cert.x509.pem cert/new_cert.pk8",
1603		},
1604	}
1605
1606	for _, test := range testCases {
1607		t.Run(test.name, func(t *testing.T) {
1608			result := android.GroupFixturePreparers(
1609				PrepareForTestWithJavaDefaultModules,
1610				android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
1611					if test.certificateOverride != "" {
1612						variables.CertificateOverrides = []string{test.certificateOverride}
1613					}
1614				}),
1615			).RunTestWithBp(t, test.bp)
1616
1617			foo := result.ModuleForTests("foo", "android_common")
1618
1619			signapk := foo.Output("foo.apk")
1620			signCertificateFlags := signapk.Args["certificates"]
1621			android.AssertStringEquals(t, "certificates flags", test.expectedCertificate, signCertificateFlags)
1622
1623			signFlags := signapk.Args["flags"]
1624			android.AssertStringEquals(t, "signing flags", test.expectedLineage, signFlags)
1625		})
1626	}
1627}
1628
1629func TestRequestV4SigningFlag(t *testing.T) {
1630	testCases := []struct {
1631		name     string
1632		bp       string
1633		expected string
1634	}{
1635		{
1636			name: "default",
1637			bp: `
1638				android_app {
1639					name: "foo",
1640					srcs: ["a.java"],
1641					sdk_version: "current",
1642				}
1643			`,
1644			expected: "",
1645		},
1646		{
1647			name: "default",
1648			bp: `
1649				android_app {
1650					name: "foo",
1651					srcs: ["a.java"],
1652					sdk_version: "current",
1653					v4_signature: false,
1654				}
1655			`,
1656			expected: "",
1657		},
1658		{
1659			name: "module certificate property",
1660			bp: `
1661				android_app {
1662					name: "foo",
1663					srcs: ["a.java"],
1664					sdk_version: "current",
1665					v4_signature: true,
1666				}
1667			`,
1668			expected: "--enable-v4",
1669		},
1670	}
1671
1672	for _, test := range testCases {
1673		t.Run(test.name, func(t *testing.T) {
1674			result := android.GroupFixturePreparers(
1675				PrepareForTestWithJavaDefaultModules,
1676			).RunTestWithBp(t, test.bp)
1677
1678			foo := result.ModuleForTests("foo", "android_common")
1679
1680			signapk := foo.Output("foo.apk")
1681			signFlags := signapk.Args["flags"]
1682			android.AssertStringEquals(t, "signing flags", test.expected, signFlags)
1683		})
1684	}
1685}
1686
1687func TestPackageNameOverride(t *testing.T) {
1688	testCases := []struct {
1689		name                string
1690		bp                  string
1691		packageNameOverride string
1692		expected            []string
1693	}{
1694		{
1695			name: "default",
1696			bp: `
1697				android_app {
1698					name: "foo",
1699					srcs: ["a.java"],
1700					sdk_version: "current",
1701				}
1702			`,
1703			packageNameOverride: "",
1704			expected: []string{
1705				"out/soong/.intermediates/foo/android_common/foo.apk",
1706				"out/soong/target/product/test_device/system/app/foo/foo.apk",
1707			},
1708		},
1709		{
1710			name: "overridden",
1711			bp: `
1712				android_app {
1713					name: "foo",
1714					srcs: ["a.java"],
1715					sdk_version: "current",
1716				}
1717			`,
1718			packageNameOverride: "foo:bar",
1719			expected: []string{
1720				// The package apk should be still be the original name for test dependencies.
1721				"out/soong/.intermediates/foo/android_common/bar.apk",
1722				"out/soong/target/product/test_device/system/app/bar/bar.apk",
1723			},
1724		},
1725	}
1726
1727	for _, test := range testCases {
1728		t.Run(test.name, func(t *testing.T) {
1729			result := android.GroupFixturePreparers(
1730				PrepareForTestWithJavaDefaultModules,
1731				android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
1732					if test.packageNameOverride != "" {
1733						variables.PackageNameOverrides = []string{test.packageNameOverride}
1734					}
1735				}),
1736			).RunTestWithBp(t, test.bp)
1737
1738			foo := result.ModuleForTests("foo", "android_common")
1739
1740			outSoongDir := result.Config.BuildDir()
1741
1742			outputs := foo.AllOutputs()
1743			outputMap := make(map[string]bool)
1744			for _, o := range outputs {
1745				outputMap[android.StringPathRelativeToTop(outSoongDir, o)] = true
1746			}
1747			for _, e := range test.expected {
1748				if _, exist := outputMap[e]; !exist {
1749					t.Errorf("Can't find %q in output files.\nAll outputs:%v", e, outputs)
1750				}
1751			}
1752		})
1753	}
1754}
1755
1756func TestInstrumentationTargetOverridden(t *testing.T) {
1757	bp := `
1758		android_app {
1759			name: "foo",
1760			srcs: ["a.java"],
1761			sdk_version: "current",
1762		}
1763
1764		android_test {
1765			name: "bar",
1766			instrumentation_for: "foo",
1767			sdk_version: "current",
1768		}
1769		`
1770
1771	result := android.GroupFixturePreparers(
1772		PrepareForTestWithJavaDefaultModules,
1773		android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
1774			variables.ManifestPackageNameOverrides = []string{"foo:org.dandroid.bp"}
1775		}),
1776	).RunTestWithBp(t, bp)
1777
1778	bar := result.ModuleForTests("bar", "android_common")
1779	res := bar.Output("package-res.apk")
1780	aapt2Flags := res.Args["flags"]
1781	e := "--rename-instrumentation-target-package org.dandroid.bp"
1782	if !strings.Contains(aapt2Flags, e) {
1783		t.Errorf("target package renaming flag, %q is missing in aapt2 link flags, %q", e, aapt2Flags)
1784	}
1785}
1786
1787func TestOverrideAndroidApp(t *testing.T) {
1788	result := PrepareForTestWithJavaDefaultModules.RunTestWithBp(
1789		t, `
1790		android_app {
1791			name: "foo",
1792			srcs: ["a.java"],
1793			certificate: "expiredkey",
1794			overrides: ["qux"],
1795			sdk_version: "current",
1796		}
1797
1798		override_android_app {
1799			name: "bar",
1800			base: "foo",
1801			certificate: ":new_certificate",
1802			lineage: "lineage.bin",
1803			logging_parent: "bah",
1804		}
1805
1806		android_app_certificate {
1807			name: "new_certificate",
1808			certificate: "cert/new_cert",
1809		}
1810
1811		override_android_app {
1812			name: "baz",
1813			base: "foo",
1814			package_name: "org.dandroid.bp",
1815		}
1816
1817		override_android_app {
1818			name: "baz_no_rename_resources",
1819			base: "foo",
1820			package_name: "org.dandroid.bp",
1821			rename_resources_package: false,
1822		}
1823
1824		android_app {
1825			name: "foo_no_rename_resources",
1826			srcs: ["a.java"],
1827			certificate: "expiredkey",
1828			overrides: ["qux"],
1829			rename_resources_package: false,
1830			sdk_version: "current",
1831		}
1832
1833		override_android_app {
1834			name: "baz_base_no_rename_resources",
1835			base: "foo_no_rename_resources",
1836			package_name: "org.dandroid.bp",
1837		}
1838
1839		override_android_app {
1840			name: "baz_override_base_rename_resources",
1841			base: "foo_no_rename_resources",
1842			package_name: "org.dandroid.bp",
1843			rename_resources_package: true,
1844		}
1845		`)
1846
1847	expectedVariants := []struct {
1848		name            string
1849		moduleName      string
1850		variantName     string
1851		apkName         string
1852		apkPath         string
1853		certFlag        string
1854		lineageFlag     string
1855		overrides       []string
1856		packageFlag     string
1857		renameResources bool
1858		logging_parent  string
1859	}{
1860		{
1861			name:            "foo",
1862			moduleName:      "foo",
1863			variantName:     "android_common",
1864			apkPath:         "out/soong/target/product/test_device/system/app/foo/foo.apk",
1865			certFlag:        "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8",
1866			lineageFlag:     "",
1867			overrides:       []string{"qux"},
1868			packageFlag:     "",
1869			renameResources: false,
1870			logging_parent:  "",
1871		},
1872		{
1873			name:            "foo",
1874			moduleName:      "bar",
1875			variantName:     "android_common_bar",
1876			apkPath:         "out/soong/target/product/test_device/system/app/bar/bar.apk",
1877			certFlag:        "cert/new_cert.x509.pem cert/new_cert.pk8",
1878			lineageFlag:     "--lineage lineage.bin",
1879			overrides:       []string{"qux", "foo"},
1880			packageFlag:     "",
1881			renameResources: false,
1882			logging_parent:  "bah",
1883		},
1884		{
1885			name:            "foo",
1886			moduleName:      "baz",
1887			variantName:     "android_common_baz",
1888			apkPath:         "out/soong/target/product/test_device/system/app/baz/baz.apk",
1889			certFlag:        "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8",
1890			lineageFlag:     "",
1891			overrides:       []string{"qux", "foo"},
1892			packageFlag:     "org.dandroid.bp",
1893			renameResources: true,
1894			logging_parent:  "",
1895		},
1896		{
1897			name:            "foo",
1898			moduleName:      "baz_no_rename_resources",
1899			variantName:     "android_common_baz_no_rename_resources",
1900			apkPath:         "out/soong/target/product/test_device/system/app/baz_no_rename_resources/baz_no_rename_resources.apk",
1901			certFlag:        "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8",
1902			lineageFlag:     "",
1903			overrides:       []string{"qux", "foo"},
1904			packageFlag:     "org.dandroid.bp",
1905			renameResources: false,
1906			logging_parent:  "",
1907		},
1908		{
1909			name:            "foo_no_rename_resources",
1910			moduleName:      "baz_base_no_rename_resources",
1911			variantName:     "android_common_baz_base_no_rename_resources",
1912			apkPath:         "out/soong/target/product/test_device/system/app/baz_base_no_rename_resources/baz_base_no_rename_resources.apk",
1913			certFlag:        "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8",
1914			lineageFlag:     "",
1915			overrides:       []string{"qux", "foo_no_rename_resources"},
1916			packageFlag:     "org.dandroid.bp",
1917			renameResources: false,
1918			logging_parent:  "",
1919		},
1920		{
1921			name:            "foo_no_rename_resources",
1922			moduleName:      "baz_override_base_rename_resources",
1923			variantName:     "android_common_baz_override_base_rename_resources",
1924			apkPath:         "out/soong/target/product/test_device/system/app/baz_override_base_rename_resources/baz_override_base_rename_resources.apk",
1925			certFlag:        "build/make/target/product/security/expiredkey.x509.pem build/make/target/product/security/expiredkey.pk8",
1926			lineageFlag:     "",
1927			overrides:       []string{"qux", "foo_no_rename_resources"},
1928			packageFlag:     "org.dandroid.bp",
1929			renameResources: true,
1930			logging_parent:  "",
1931		},
1932	}
1933	for _, expected := range expectedVariants {
1934		variant := result.ModuleForTests(expected.name, expected.variantName)
1935
1936		// Check the final apk name
1937		variant.Output(expected.apkPath)
1938
1939		// Check the certificate paths
1940		signapk := variant.Output(expected.moduleName + ".apk")
1941		certFlag := signapk.Args["certificates"]
1942		android.AssertStringEquals(t, "certificates flags", expected.certFlag, certFlag)
1943
1944		// Check the lineage flags
1945		lineageFlag := signapk.Args["flags"]
1946		android.AssertStringEquals(t, "signing flags", expected.lineageFlag, lineageFlag)
1947
1948		// Check if the overrides field values are correctly aggregated.
1949		mod := variant.Module().(*AndroidApp)
1950		android.AssertDeepEquals(t, "overrides property", expected.overrides, mod.appProperties.Overrides)
1951
1952		// Test Overridable property: Logging_parent
1953		logging_parent := mod.aapt.LoggingParent
1954		android.AssertStringEquals(t, "overrides property value for logging parent", expected.logging_parent, logging_parent)
1955
1956		// Check the package renaming flag, if exists.
1957		res := variant.Output("package-res.apk")
1958		aapt2Flags := res.Args["flags"]
1959		checkAapt2LinkFlag(t, aapt2Flags, "rename-manifest-package", expected.packageFlag)
1960		expectedPackage := expected.packageFlag
1961		if !expected.renameResources {
1962			expectedPackage = ""
1963		}
1964		checkAapt2LinkFlag(t, aapt2Flags, "rename-resources-package", expectedPackage)
1965	}
1966}
1967
1968func TestOverrideAndroidAppDependency(t *testing.T) {
1969	ctx, _ := testJava(t, `
1970		android_app {
1971			name: "foo",
1972			srcs: ["a.java"],
1973			sdk_version: "current",
1974		}
1975
1976		override_android_app {
1977			name: "bar",
1978			base: "foo",
1979			package_name: "org.dandroid.bp",
1980		}
1981
1982		android_test {
1983			name: "baz",
1984			srcs: ["b.java"],
1985			instrumentation_for: "foo",
1986		}
1987
1988		android_test {
1989			name: "qux",
1990			srcs: ["b.java"],
1991			instrumentation_for: "bar",
1992		}
1993		`)
1994
1995	// Verify baz, which depends on the overridden module foo, has the correct classpath javac arg.
1996	javac := ctx.ModuleForTests("baz", "android_common").Rule("javac")
1997	fooTurbine := "out/soong/.intermediates/foo/android_common/turbine-combined/foo.jar"
1998	if !strings.Contains(javac.Args["classpath"], fooTurbine) {
1999		t.Errorf("baz classpath %v does not contain %q", javac.Args["classpath"], fooTurbine)
2000	}
2001
2002	// Verify qux, which depends on the overriding module bar, has the correct classpath javac arg.
2003	javac = ctx.ModuleForTests("qux", "android_common").Rule("javac")
2004	barTurbine := "out/soong/.intermediates/foo/android_common_bar/turbine-combined/foo.jar"
2005	if !strings.Contains(javac.Args["classpath"], barTurbine) {
2006		t.Errorf("qux classpath %v does not contain %q", javac.Args["classpath"], barTurbine)
2007	}
2008}
2009
2010func TestOverrideAndroidTest(t *testing.T) {
2011	ctx, _ := testJava(t, `
2012		android_app {
2013			name: "foo",
2014			srcs: ["a.java"],
2015			package_name: "com.android.foo",
2016			sdk_version: "current",
2017		}
2018
2019		override_android_app {
2020			name: "bar",
2021			base: "foo",
2022			package_name: "com.android.bar",
2023		}
2024
2025		android_test {
2026			name: "foo_test",
2027			srcs: ["b.java"],
2028			instrumentation_for: "foo",
2029		}
2030
2031		override_android_test {
2032			name: "bar_test",
2033			base: "foo_test",
2034			package_name: "com.android.bar.test",
2035			instrumentation_for: "bar",
2036			instrumentation_target_package: "com.android.bar",
2037		}
2038		`)
2039
2040	expectedVariants := []struct {
2041		moduleName        string
2042		variantName       string
2043		apkPath           string
2044		overrides         []string
2045		targetVariant     string
2046		packageFlag       string
2047		targetPackageFlag string
2048	}{
2049		{
2050			variantName:       "android_common",
2051			apkPath:           "/target/product/test_device/testcases/foo_test/arm64/foo_test.apk",
2052			overrides:         nil,
2053			targetVariant:     "android_common",
2054			packageFlag:       "",
2055			targetPackageFlag: "",
2056		},
2057		{
2058			variantName:       "android_common_bar_test",
2059			apkPath:           "/target/product/test_device/testcases/bar_test/arm64/bar_test.apk",
2060			overrides:         []string{"foo_test"},
2061			targetVariant:     "android_common_bar",
2062			packageFlag:       "com.android.bar.test",
2063			targetPackageFlag: "com.android.bar",
2064		},
2065	}
2066	for _, expected := range expectedVariants {
2067		variant := ctx.ModuleForTests("foo_test", expected.variantName)
2068
2069		// Check the final apk name
2070		variant.Output("out/soong" + expected.apkPath)
2071
2072		// Check if the overrides field values are correctly aggregated.
2073		mod := variant.Module().(*AndroidTest)
2074		if !reflect.DeepEqual(expected.overrides, mod.appProperties.Overrides) {
2075			t.Errorf("Incorrect overrides property value, expected: %q, got: %q",
2076				expected.overrides, mod.appProperties.Overrides)
2077		}
2078
2079		// Check if javac classpath has the correct jar file path. This checks instrumentation_for overrides.
2080		javac := variant.Rule("javac")
2081		turbine := filepath.Join("out", "soong", ".intermediates", "foo", expected.targetVariant, "turbine-combined", "foo.jar")
2082		if !strings.Contains(javac.Args["classpath"], turbine) {
2083			t.Errorf("classpath %q does not contain %q", javac.Args["classpath"], turbine)
2084		}
2085
2086		// Check aapt2 flags.
2087		res := variant.Output("package-res.apk")
2088		aapt2Flags := res.Args["flags"]
2089		checkAapt2LinkFlag(t, aapt2Flags, "rename-manifest-package", expected.packageFlag)
2090		checkAapt2LinkFlag(t, aapt2Flags, "rename-resources-package", expected.packageFlag)
2091		checkAapt2LinkFlag(t, aapt2Flags, "rename-instrumentation-target-package", expected.targetPackageFlag)
2092	}
2093}
2094
2095func TestAndroidTest_FixTestConfig(t *testing.T) {
2096	ctx, _ := testJava(t, `
2097		android_app {
2098			name: "foo",
2099			srcs: ["a.java"],
2100			package_name: "com.android.foo",
2101			sdk_version: "current",
2102		}
2103
2104		android_test {
2105			name: "foo_test",
2106			srcs: ["b.java"],
2107			instrumentation_for: "foo",
2108		}
2109
2110		android_test {
2111			name: "bar_test",
2112			srcs: ["b.java"],
2113			package_name: "com.android.bar.test",
2114			instrumentation_for: "foo",
2115		}
2116
2117		override_android_test {
2118			name: "baz_test",
2119			base: "foo_test",
2120			package_name: "com.android.baz.test",
2121		}
2122		`)
2123
2124	testCases := []struct {
2125		moduleName    string
2126		variantName   string
2127		expectedFlags []string
2128	}{
2129		{
2130			moduleName:  "foo_test",
2131			variantName: "android_common",
2132		},
2133		{
2134			moduleName:  "bar_test",
2135			variantName: "android_common",
2136			expectedFlags: []string{
2137				"--manifest out/soong/.intermediates/bar_test/android_common/manifest_fixer/AndroidManifest.xml",
2138				"--package-name com.android.bar.test",
2139			},
2140		},
2141		{
2142			moduleName:  "foo_test",
2143			variantName: "android_common_baz_test",
2144			expectedFlags: []string{
2145				"--manifest out/soong/.intermediates/foo_test/android_common_baz_test/manifest_fixer/AndroidManifest.xml",
2146				"--package-name com.android.baz.test",
2147				"--test-file-name baz_test.apk",
2148			},
2149		},
2150	}
2151
2152	for _, test := range testCases {
2153		variant := ctx.ModuleForTests(test.moduleName, test.variantName)
2154		params := variant.MaybeOutput("test_config_fixer/AndroidTest.xml")
2155
2156		if len(test.expectedFlags) > 0 {
2157			if params.Rule == nil {
2158				t.Errorf("test_config_fixer was expected to run, but didn't")
2159			} else {
2160				for _, flag := range test.expectedFlags {
2161					if !strings.Contains(params.RuleParams.Command, flag) {
2162						t.Errorf("Flag %q was not found in command: %q", flag, params.RuleParams.Command)
2163					}
2164				}
2165			}
2166		} else {
2167			if params.Rule != nil {
2168				t.Errorf("test_config_fixer was not expected to run, but did: %q", params.RuleParams.Command)
2169			}
2170		}
2171
2172	}
2173}
2174
2175func TestStl(t *testing.T) {
2176	ctx, _ := testJava(t, cc.GatherRequiredDepsForTest(android.Android)+`
2177		cc_library {
2178			name: "libjni",
2179			sdk_version: "current",
2180			stl: "c++_shared",
2181		}
2182
2183		android_test {
2184			name: "stl",
2185			jni_libs: ["libjni"],
2186			compile_multilib: "both",
2187			sdk_version: "current",
2188			stl: "c++_shared",
2189		}
2190
2191		android_test {
2192			name: "system",
2193			jni_libs: ["libjni"],
2194			compile_multilib: "both",
2195			sdk_version: "current",
2196		}
2197		`)
2198
2199	testCases := []struct {
2200		name string
2201		jnis []string
2202	}{
2203		{"stl",
2204			[]string{
2205				"libjni.so",
2206				"libc++_shared.so",
2207			},
2208		},
2209		{"system",
2210			[]string{
2211				"libjni.so",
2212			},
2213		},
2214	}
2215
2216	for _, test := range testCases {
2217		t.Run(test.name, func(t *testing.T) {
2218			app := ctx.ModuleForTests(test.name, "android_common")
2219			jniLibZip := app.Output("jnilibs.zip")
2220			var jnis []string
2221			args := strings.Fields(jniLibZip.Args["jarArgs"])
2222			for i := 0; i < len(args); i++ {
2223				if args[i] == "-f" {
2224					jnis = append(jnis, args[i+1])
2225					i += 1
2226				}
2227			}
2228			jnisJoined := strings.Join(jnis, " ")
2229			for _, jni := range test.jnis {
2230				if !strings.Contains(jnisJoined, jni) {
2231					t.Errorf("missing jni %q in %q", jni, jnis)
2232				}
2233			}
2234		})
2235	}
2236}
2237
2238func TestUsesLibraries(t *testing.T) {
2239	bp := `
2240		java_sdk_library {
2241			name: "foo",
2242			srcs: ["a.java"],
2243			api_packages: ["foo"],
2244			sdk_version: "current",
2245		}
2246
2247		java_sdk_library {
2248			name: "qux",
2249			srcs: ["a.java"],
2250			api_packages: ["qux"],
2251			sdk_version: "current",
2252		}
2253
2254		java_sdk_library {
2255			name: "quuz",
2256			srcs: ["a.java"],
2257			api_packages: ["quuz"],
2258			sdk_version: "current",
2259		}
2260
2261		java_sdk_library {
2262			name: "fred",
2263			srcs: ["a.java"],
2264			api_packages: ["fred"],
2265			sdk_version: "current",
2266		}
2267
2268		java_sdk_library {
2269			name: "bar",
2270			srcs: ["a.java"],
2271			api_packages: ["bar"],
2272			sdk_version: "current",
2273		}
2274
2275		java_sdk_library {
2276			name: "runtime-library",
2277			srcs: ["a.java"],
2278			sdk_version: "current",
2279		}
2280
2281		java_library {
2282			name: "static-runtime-helper",
2283			srcs: ["a.java"],
2284			libs: ["runtime-library"],
2285			sdk_version: "current",
2286		}
2287
2288		// A library that has to use "provides_uses_lib", because:
2289		//    - it is not an SDK library
2290		//    - its library name is different from its module name
2291		java_library {
2292			name: "non-sdk-lib",
2293			provides_uses_lib: "com.non.sdk.lib",
2294			installable: true,
2295			srcs: ["a.java"],
2296		}
2297
2298		android_app {
2299			name: "app",
2300			srcs: ["a.java"],
2301			libs: [
2302				"qux",
2303				"quuz.stubs"
2304			],
2305			static_libs: [
2306				"static-runtime-helper",
2307				// statically linked component libraries should not pull their SDK libraries,
2308				// so "fred" should not be added to class loader context
2309				"fred.stubs",
2310			],
2311			uses_libs: [
2312				"foo",
2313				"non-sdk-lib"
2314			],
2315			sdk_version: "current",
2316			optional_uses_libs: [
2317				"bar",
2318				"baz",
2319			],
2320		}
2321
2322		android_app_import {
2323			name: "prebuilt",
2324			apk: "prebuilts/apk/app.apk",
2325			certificate: "platform",
2326			uses_libs: [
2327				"foo",
2328				"non-sdk-lib",
2329				"android.test.runner"
2330			],
2331			optional_uses_libs: [
2332				"bar",
2333				"baz",
2334			],
2335		}
2336	`
2337
2338	result := android.GroupFixturePreparers(
2339		prepareForJavaTest,
2340		PrepareForTestWithJavaSdkLibraryFiles,
2341		FixtureWithLastReleaseApis("runtime-library", "foo", "quuz", "qux", "bar", "fred"),
2342		android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
2343			variables.MissingUsesLibraries = []string{"baz"}
2344		}),
2345	).RunTestWithBp(t, bp)
2346
2347	app := result.ModuleForTests("app", "android_common")
2348	prebuilt := result.ModuleForTests("prebuilt", "android_common")
2349
2350	// Test that implicit dependencies on java_sdk_library instances are passed to the manifest.
2351	// This should not include explicit `uses_libs`/`optional_uses_libs` entries.
2352	actualManifestFixerArgs := app.Output("manifest_fixer/AndroidManifest.xml").Args["args"]
2353	expectManifestFixerArgs := `--extract-native-libs=true ` +
2354		`--uses-library qux ` +
2355		`--uses-library quuz ` +
2356		`--uses-library foo ` + // TODO(b/132357300): "foo" should not be passed to manifest_fixer
2357		`--uses-library com.non.sdk.lib ` + // TODO(b/132357300): "com.non.sdk.lib" should not be passed to manifest_fixer
2358		`--uses-library bar ` + // TODO(b/132357300): "bar" should not be passed to manifest_fixer
2359		`--uses-library runtime-library`
2360	android.AssertStringEquals(t, "manifest_fixer args", expectManifestFixerArgs, actualManifestFixerArgs)
2361
2362	// Test that all libraries are verified (library order matters).
2363	verifyCmd := app.Rule("verify_uses_libraries").RuleParams.Command
2364	verifyArgs := `--uses-library foo ` +
2365		`--uses-library com.non.sdk.lib ` +
2366		`--uses-library qux ` +
2367		`--uses-library quuz ` +
2368		`--uses-library runtime-library ` +
2369		`--optional-uses-library bar ` +
2370		`--optional-uses-library baz `
2371	android.AssertStringDoesContain(t, "verify cmd args", verifyCmd, verifyArgs)
2372
2373	// Test that all libraries are verified for an APK (library order matters).
2374	verifyApkCmd := prebuilt.Rule("verify_uses_libraries").RuleParams.Command
2375	verifyApkArgs := `--uses-library foo ` +
2376		`--uses-library com.non.sdk.lib ` +
2377		`--uses-library android.test.runner ` +
2378		`--optional-uses-library bar ` +
2379		`--optional-uses-library baz `
2380	android.AssertStringDoesContain(t, "verify apk cmd args", verifyApkCmd, verifyApkArgs)
2381
2382	// Test that all present libraries are preopted, including implicit SDK dependencies, possibly stubs
2383	cmd := app.Rule("dexpreopt").RuleParams.Command
2384	w := `--target-context-for-sdk any ` +
2385		`PCL[/system/framework/qux.jar]#` +
2386		`PCL[/system/framework/quuz.jar]#` +
2387		`PCL[/system/framework/foo.jar]#` +
2388		`PCL[/system/framework/non-sdk-lib.jar]#` +
2389		`PCL[/system/framework/bar.jar]#` +
2390		`PCL[/system/framework/runtime-library.jar]`
2391	android.AssertStringDoesContain(t, "dexpreopt app cmd args", cmd, w)
2392
2393	// Test conditional context for target SDK version 28.
2394	android.AssertStringDoesContain(t, "dexpreopt app cmd 28", cmd,
2395		`--target-context-for-sdk 28`+
2396			` PCL[/system/framework/org.apache.http.legacy.jar] `)
2397
2398	// Test conditional context for target SDK version 29.
2399	android.AssertStringDoesContain(t, "dexpreopt app cmd 29", cmd,
2400		`--target-context-for-sdk 29`+
2401			` PCL[/system/framework/android.hidl.manager-V1.0-java.jar]`+
2402			`#PCL[/system/framework/android.hidl.base-V1.0-java.jar] `)
2403
2404	// Test conditional context for target SDK version 30.
2405	// "android.test.mock" is absent because "android.test.runner" is not used.
2406	android.AssertStringDoesContain(t, "dexpreopt app cmd 30", cmd,
2407		`--target-context-for-sdk 30`+
2408			` PCL[/system/framework/android.test.base.jar] `)
2409
2410	cmd = prebuilt.Rule("dexpreopt").RuleParams.Command
2411	android.AssertStringDoesContain(t, "dexpreopt prebuilt cmd", cmd,
2412		`--target-context-for-sdk any`+
2413			` PCL[/system/framework/foo.jar]`+
2414			`#PCL[/system/framework/non-sdk-lib.jar]`+
2415			`#PCL[/system/framework/android.test.runner.jar]`+
2416			`#PCL[/system/framework/bar.jar] `)
2417
2418	// Test conditional context for target SDK version 30.
2419	// "android.test.mock" is present because "android.test.runner" is used.
2420	android.AssertStringDoesContain(t, "dexpreopt prebuilt cmd 30", cmd,
2421		`--target-context-for-sdk 30`+
2422			` PCL[/system/framework/android.test.base.jar]`+
2423			`#PCL[/system/framework/android.test.mock.jar] `)
2424}
2425
2426func TestDexpreoptBcp(t *testing.T) {
2427	bp := `
2428		java_sdk_library {
2429			name: "foo",
2430			srcs: ["a.java"],
2431			api_packages: ["foo"],
2432			sdk_version: "current",
2433		}
2434
2435		java_sdk_library {
2436			name: "bar",
2437			srcs: ["a.java"],
2438			api_packages: ["bar"],
2439			permitted_packages: ["bar"],
2440			sdk_version: "current",
2441		}
2442
2443		android_app {
2444			name: "app",
2445			srcs: ["a.java"],
2446			sdk_version: "current",
2447		}
2448	`
2449
2450	testCases := []struct {
2451		name   string
2452		with   bool
2453		expect string
2454	}{
2455		{
2456			name:   "with updatable bcp",
2457			with:   true,
2458			expect: "/system/framework/foo.jar:/system/framework/bar.jar",
2459		},
2460		{
2461			name:   "without updatable bcp",
2462			with:   false,
2463			expect: "/system/framework/foo.jar",
2464		},
2465	}
2466
2467	for _, test := range testCases {
2468		t.Run(test.name, func(t *testing.T) {
2469			result := android.GroupFixturePreparers(
2470				prepareForJavaTest,
2471				PrepareForTestWithJavaSdkLibraryFiles,
2472				FixtureWithLastReleaseApis("runtime-library", "foo", "bar"),
2473				dexpreopt.FixtureSetBootJars("platform:foo"),
2474				dexpreopt.FixtureSetUpdatableBootJars("platform:bar"),
2475				dexpreopt.FixtureSetPreoptWithUpdatableBcp(test.with),
2476			).RunTestWithBp(t, bp)
2477
2478			app := result.ModuleForTests("app", "android_common")
2479			cmd := app.Rule("dexpreopt").RuleParams.Command
2480			bcp := " -Xbootclasspath-locations:" + test.expect + " " // space at the end matters
2481			android.AssertStringDoesContain(t, "dexpreopt app bcp", cmd, bcp)
2482		})
2483	}
2484}
2485
2486func TestCodelessApp(t *testing.T) {
2487	testCases := []struct {
2488		name   string
2489		bp     string
2490		noCode bool
2491	}{
2492		{
2493			name: "normal",
2494			bp: `
2495				android_app {
2496					name: "foo",
2497					srcs: ["a.java"],
2498					sdk_version: "current",
2499				}
2500			`,
2501			noCode: false,
2502		},
2503		{
2504			name: "app without sources",
2505			bp: `
2506				android_app {
2507					name: "foo",
2508					sdk_version: "current",
2509				}
2510			`,
2511			noCode: true,
2512		},
2513		{
2514			name: "app with libraries",
2515			bp: `
2516				android_app {
2517					name: "foo",
2518					static_libs: ["lib"],
2519					sdk_version: "current",
2520				}
2521
2522				java_library {
2523					name: "lib",
2524					srcs: ["a.java"],
2525					sdk_version: "current",
2526				}
2527			`,
2528			noCode: false,
2529		},
2530		{
2531			name: "app with sourceless libraries",
2532			bp: `
2533				android_app {
2534					name: "foo",
2535					static_libs: ["lib"],
2536					sdk_version: "current",
2537				}
2538
2539				java_library {
2540					name: "lib",
2541					sdk_version: "current",
2542				}
2543			`,
2544			// TODO(jungjw): this should probably be true
2545			noCode: false,
2546		},
2547	}
2548
2549	for _, test := range testCases {
2550		t.Run(test.name, func(t *testing.T) {
2551			ctx := testApp(t, test.bp)
2552
2553			foo := ctx.ModuleForTests("foo", "android_common")
2554			manifestFixerArgs := foo.Output("manifest_fixer/AndroidManifest.xml").Args["args"]
2555			if strings.Contains(manifestFixerArgs, "--has-no-code") != test.noCode {
2556				t.Errorf("unexpected manifest_fixer args: %q", manifestFixerArgs)
2557			}
2558		})
2559	}
2560}
2561
2562func TestEmbedNotice(t *testing.T) {
2563	result := android.GroupFixturePreparers(
2564		PrepareForTestWithJavaDefaultModules,
2565		cc.PrepareForTestWithCcDefaultModules,
2566		genrule.PrepareForTestWithGenRuleBuildComponents,
2567		android.MockFS{
2568			"APP_NOTICE":     nil,
2569			"GENRULE_NOTICE": nil,
2570			"LIB_NOTICE":     nil,
2571			"TOOL_NOTICE":    nil,
2572		}.AddToFixture(),
2573	).RunTestWithBp(t, `
2574		android_app {
2575			name: "foo",
2576			srcs: ["a.java"],
2577			static_libs: ["javalib"],
2578			jni_libs: ["libjni"],
2579			notice: "APP_NOTICE",
2580			embed_notices: true,
2581			sdk_version: "current",
2582		}
2583
2584		// No embed_notice flag
2585		android_app {
2586			name: "bar",
2587			srcs: ["a.java"],
2588			jni_libs: ["libjni"],
2589			notice: "APP_NOTICE",
2590			sdk_version: "current",
2591		}
2592
2593		// No NOTICE files
2594		android_app {
2595			name: "baz",
2596			srcs: ["a.java"],
2597			embed_notices: true,
2598			sdk_version: "current",
2599		}
2600
2601		cc_library {
2602			name: "libjni",
2603			system_shared_libs: [],
2604			stl: "none",
2605			notice: "LIB_NOTICE",
2606			sdk_version: "current",
2607		}
2608
2609		java_library {
2610			name: "javalib",
2611			srcs: [
2612				":gen",
2613			],
2614			sdk_version: "current",
2615		}
2616
2617		genrule {
2618			name: "gen",
2619			tools: ["gentool"],
2620			out: ["gen.java"],
2621			notice: "GENRULE_NOTICE",
2622		}
2623
2624		java_binary_host {
2625			name: "gentool",
2626			srcs: ["b.java"],
2627			notice: "TOOL_NOTICE",
2628		}
2629	`)
2630
2631	// foo has NOTICE files to process, and embed_notices is true.
2632	foo := result.ModuleForTests("foo", "android_common")
2633	// verify merge notices rule.
2634	mergeNotices := foo.Rule("mergeNoticesRule")
2635	noticeInputs := mergeNotices.Inputs.Strings()
2636	// TOOL_NOTICE should be excluded as it's a host module.
2637	if len(mergeNotices.Inputs) != 3 {
2638		t.Errorf("number of input notice files: expected = 3, actual = %q", noticeInputs)
2639	}
2640	if !inList("APP_NOTICE", noticeInputs) {
2641		t.Errorf("APP_NOTICE is missing from notice files, %q", noticeInputs)
2642	}
2643	if !inList("LIB_NOTICE", noticeInputs) {
2644		t.Errorf("LIB_NOTICE is missing from notice files, %q", noticeInputs)
2645	}
2646	if !inList("GENRULE_NOTICE", noticeInputs) {
2647		t.Errorf("GENRULE_NOTICE is missing from notice files, %q", noticeInputs)
2648	}
2649	// aapt2 flags should include -A <NOTICE dir> so that its contents are put in the APK's /assets.
2650	res := foo.Output("package-res.apk")
2651	aapt2Flags := res.Args["flags"]
2652	e := "-A out/soong/.intermediates/foo/android_common/NOTICE"
2653	android.AssertStringDoesContain(t, "expected.apkPath", aapt2Flags, e)
2654
2655	// bar has NOTICE files to process, but embed_notices is not set.
2656	bar := result.ModuleForTests("bar", "android_common")
2657	res = bar.Output("package-res.apk")
2658	aapt2Flags = res.Args["flags"]
2659	e = "-A out/soong/.intermediates/bar/android_common/NOTICE"
2660	android.AssertStringDoesNotContain(t, "bar shouldn't have the asset dir flag for NOTICE", aapt2Flags, e)
2661
2662	// baz's embed_notice is true, but it doesn't have any NOTICE files.
2663	baz := result.ModuleForTests("baz", "android_common")
2664	res = baz.Output("package-res.apk")
2665	aapt2Flags = res.Args["flags"]
2666	e = "-A out/soong/.intermediates/baz/android_common/NOTICE"
2667	if strings.Contains(aapt2Flags, e) {
2668		t.Errorf("baz shouldn't have the asset dir flag for NOTICE: %q", e)
2669	}
2670}
2671
2672func TestUncompressDex(t *testing.T) {
2673	testCases := []struct {
2674		name string
2675		bp   string
2676
2677		uncompressedPlatform  bool
2678		uncompressedUnbundled bool
2679	}{
2680		{
2681			name: "normal",
2682			bp: `
2683				android_app {
2684					name: "foo",
2685					srcs: ["a.java"],
2686					sdk_version: "current",
2687				}
2688			`,
2689			uncompressedPlatform:  true,
2690			uncompressedUnbundled: false,
2691		},
2692		{
2693			name: "use_embedded_dex",
2694			bp: `
2695				android_app {
2696					name: "foo",
2697					use_embedded_dex: true,
2698					srcs: ["a.java"],
2699					sdk_version: "current",
2700				}
2701			`,
2702			uncompressedPlatform:  true,
2703			uncompressedUnbundled: true,
2704		},
2705		{
2706			name: "privileged",
2707			bp: `
2708				android_app {
2709					name: "foo",
2710					privileged: true,
2711					srcs: ["a.java"],
2712					sdk_version: "current",
2713				}
2714			`,
2715			uncompressedPlatform:  true,
2716			uncompressedUnbundled: true,
2717		},
2718		{
2719			name: "normal_uncompress_dex_true",
2720			bp: `
2721				android_app {
2722					name: "foo",
2723					srcs: ["a.java"],
2724					sdk_version: "current",
2725					uncompress_dex: true,
2726				}
2727			`,
2728			uncompressedPlatform:  true,
2729			uncompressedUnbundled: true,
2730		},
2731		{
2732			name: "normal_uncompress_dex_false",
2733			bp: `
2734				android_app {
2735					name: "foo",
2736					srcs: ["a.java"],
2737					sdk_version: "current",
2738					uncompress_dex: false,
2739				}
2740			`,
2741			uncompressedPlatform:  false,
2742			uncompressedUnbundled: false,
2743		},
2744	}
2745
2746	test := func(t *testing.T, bp string, want bool, unbundled bool) {
2747		t.Helper()
2748
2749		result := android.GroupFixturePreparers(
2750			prepareForJavaTest,
2751			PrepareForTestWithPrebuiltsOfCurrentApi,
2752			android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
2753				if unbundled {
2754					variables.Unbundled_build = proptools.BoolPtr(true)
2755					variables.Always_use_prebuilt_sdks = proptools.BoolPtr(true)
2756				}
2757			}),
2758		).RunTestWithBp(t, bp)
2759
2760		foo := result.ModuleForTests("foo", "android_common")
2761		dex := foo.Rule("r8")
2762		uncompressedInDexJar := strings.Contains(dex.Args["zipFlags"], "-L 0")
2763		aligned := foo.MaybeRule("zipalign").Rule != nil
2764
2765		android.AssertBoolEquals(t, "uncompressed in dex", want, uncompressedInDexJar)
2766
2767		android.AssertBoolEquals(t, "aligne", want, aligned)
2768	}
2769
2770	for _, tt := range testCases {
2771		t.Run(tt.name, func(t *testing.T) {
2772			t.Run("platform", func(t *testing.T) {
2773				test(t, tt.bp, tt.uncompressedPlatform, false)
2774			})
2775			t.Run("unbundled", func(t *testing.T) {
2776				test(t, tt.bp, tt.uncompressedUnbundled, true)
2777			})
2778		})
2779	}
2780}
2781
2782func checkAapt2LinkFlag(t *testing.T, aapt2Flags, flagName, expectedValue string) {
2783	if expectedValue != "" {
2784		expectedFlag := "--" + flagName + " " + expectedValue
2785		if !strings.Contains(aapt2Flags, expectedFlag) {
2786			t.Errorf("%q is missing in aapt2 link flags, %q", expectedFlag, aapt2Flags)
2787		}
2788	} else {
2789		unexpectedFlag := "--" + flagName
2790		if strings.Contains(aapt2Flags, unexpectedFlag) {
2791			t.Errorf("unexpected flag, %q is found in aapt2 link flags, %q", unexpectedFlag, aapt2Flags)
2792		}
2793	}
2794}
2795
2796func TestExportedProguardFlagFiles(t *testing.T) {
2797	ctx, _ := testJava(t, `
2798		android_app {
2799			name: "foo",
2800			sdk_version: "current",
2801			static_libs: ["lib1"],
2802		}
2803
2804		android_library {
2805			name: "lib1",
2806			sdk_version: "current",
2807			optimize: {
2808				proguard_flags_files: ["lib1proguard.cfg"],
2809			}
2810		}
2811	`)
2812
2813	m := ctx.ModuleForTests("foo", "android_common")
2814	hasLib1Proguard := false
2815	for _, s := range m.Rule("java.r8").Implicits.Strings() {
2816		if s == "lib1proguard.cfg" {
2817			hasLib1Proguard = true
2818			break
2819		}
2820	}
2821
2822	if !hasLib1Proguard {
2823		t.Errorf("App does not use library proguard config")
2824	}
2825}
2826