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