xref: /aosp_15_r20/build/soong/java/rro_test.go (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
1// Copyright 2020 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	"reflect"
19	"strings"
20	"testing"
21
22	"android/soong/android"
23	"android/soong/shared"
24)
25
26func TestRuntimeResourceOverlay(t *testing.T) {
27	fs := android.MockFS{
28		"baz/res/res/values/strings.xml": nil,
29		"bar/res/res/values/strings.xml": nil,
30	}
31	bp := `
32		runtime_resource_overlay {
33			name: "foo",
34			certificate: "platform",
35			lineage: "lineage.bin",
36			rotationMinSdkVersion: "32",
37			product_specific: true,
38			static_libs: ["bar"],
39			resource_libs: ["baz"],
40			aaptflags: ["--keep-raw-values"],
41		}
42
43		runtime_resource_overlay {
44			name: "foo_themed",
45			certificate: "platform",
46			product_specific: true,
47			theme: "faza",
48			overrides: ["foo"],
49		}
50
51		android_library {
52			name: "bar",
53			resource_dirs: ["bar/res"],
54		}
55
56		android_app {
57			name: "baz",
58			sdk_version: "current",
59			resource_dirs: ["baz/res"],
60		}
61	`
62
63	result := android.GroupFixturePreparers(
64		PrepareForTestWithJavaDefaultModules,
65		android.FixtureModifyConfig(android.SetKatiEnabledForTests),
66		fs.AddToFixture(),
67	).RunTestWithBp(t, bp)
68
69	m := result.ModuleForTests("foo", "android_common")
70
71	// Check AAPT2 link flags.
72	aapt2Flags := m.Output("package-res.apk").Args["flags"]
73	expectedFlags := []string{"--keep-raw-values", "--no-resource-deduping", "--no-resource-removal"}
74	absentFlags := android.RemoveListFromList(expectedFlags, strings.Split(aapt2Flags, " "))
75	if len(absentFlags) > 0 {
76		t.Errorf("expected values, %q are missing in aapt2 link flags, %q", absentFlags, aapt2Flags)
77	}
78
79	// Check overlay.list output for static_libs dependency.
80	overlayList := android.PathsRelativeToTop(m.Output("aapt2/overlay.list").Inputs)
81	staticLibPackage := "out/soong/.intermediates/bar/android_common/package-res.apk"
82	if !inList(staticLibPackage, overlayList) {
83		t.Errorf("Stactic lib res package %q missing in overlay list: %q", staticLibPackage, overlayList)
84	}
85
86	// Check AAPT2 link flags for resource_libs dependency.
87	resourceLibFlag := "-I " + "out/soong/.intermediates/baz/android_common/package-res.apk"
88	if !strings.Contains(aapt2Flags, resourceLibFlag) {
89		t.Errorf("Resource lib flag %q missing in aapt2 link flags: %q", resourceLibFlag, aapt2Flags)
90	}
91
92	// Check cert signing flags.
93	signedApk := m.Output("signed/foo.apk")
94	actualCertSigningFlags := signedApk.Args["flags"]
95	expectedCertSigningFlags := "--lineage lineage.bin --rotation-min-sdk-version 32"
96	if expectedCertSigningFlags != actualCertSigningFlags {
97		t.Errorf("Incorrect cert signing flags, expected: %q, got: %q", expectedCertSigningFlags, actualCertSigningFlags)
98	}
99
100	signingFlag := signedApk.Args["certificates"]
101	expected := "build/make/target/product/security/platform.x509.pem build/make/target/product/security/platform.pk8"
102	if expected != signingFlag {
103		t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected, signingFlag)
104	}
105	androidMkEntries := android.AndroidMkEntriesForTest(t, result.TestContext, m.Module())[0]
106	path := androidMkEntries.EntryMap["LOCAL_CERTIFICATE"]
107	expectedPath := []string{"build/make/target/product/security/platform.x509.pem"}
108	if !reflect.DeepEqual(path, expectedPath) {
109		t.Errorf("Unexpected LOCAL_CERTIFICATE value: %v, expected: %v", path, expectedPath)
110	}
111
112	// Check device location.
113	path = androidMkEntries.EntryMap["LOCAL_MODULE_PATH"]
114	expectedPath = []string{shared.JoinPath("out/target/product/test_device/product/overlay")}
115	android.AssertStringPathsRelativeToTopEquals(t, "LOCAL_MODULE_PATH", result.Config, expectedPath, path)
116
117	// A themed module has a different device location
118	m = result.ModuleForTests("foo_themed", "android_common")
119	androidMkEntries = android.AndroidMkEntriesForTest(t, result.TestContext, m.Module())[0]
120	path = androidMkEntries.EntryMap["LOCAL_MODULE_PATH"]
121	expectedPath = []string{shared.JoinPath("out/target/product/test_device/product/overlay/faza")}
122	android.AssertStringPathsRelativeToTopEquals(t, "LOCAL_MODULE_PATH", result.Config, expectedPath, path)
123
124	overrides := androidMkEntries.EntryMap["LOCAL_OVERRIDES_PACKAGES"]
125	expectedOverrides := []string{"foo"}
126	if !reflect.DeepEqual(overrides, expectedOverrides) {
127		t.Errorf("Unexpected LOCAL_OVERRIDES_PACKAGES value: %v, expected: %v", overrides, expectedOverrides)
128	}
129}
130
131func TestRuntimeResourceOverlay_JavaDefaults(t *testing.T) {
132	result := android.GroupFixturePreparers(
133		PrepareForTestWithJavaDefaultModules,
134		android.FixtureModifyConfig(android.SetKatiEnabledForTests),
135	).RunTestWithBp(t, `
136		java_defaults {
137			name: "rro_defaults",
138			theme: "default_theme",
139			product_specific: true,
140			aaptflags: ["--keep-raw-values"],
141		}
142
143		runtime_resource_overlay {
144			name: "foo_with_defaults",
145			defaults: ["rro_defaults"],
146		}
147
148		runtime_resource_overlay {
149			name: "foo_barebones",
150		}
151		`)
152
153	//
154	// RRO module with defaults
155	//
156	m := result.ModuleForTests("foo_with_defaults", "android_common")
157
158	// Check AAPT2 link flags.
159	aapt2Flags := strings.Split(m.Output("package-res.apk").Args["flags"], " ")
160	expectedFlags := []string{"--keep-raw-values", "--no-resource-deduping", "--no-resource-removal"}
161	absentFlags := android.RemoveListFromList(expectedFlags, aapt2Flags)
162	if len(absentFlags) > 0 {
163		t.Errorf("expected values, %q are missing in aapt2 link flags, %q", absentFlags, aapt2Flags)
164	}
165
166	// Check device location.
167	path := android.AndroidMkEntriesForTest(t, result.TestContext, m.Module())[0].EntryMap["LOCAL_MODULE_PATH"]
168	expectedPath := []string{shared.JoinPath("out/target/product/test_device/product/overlay/default_theme")}
169	android.AssertStringPathsRelativeToTopEquals(t, "LOCAL_MODULE_PATH", result.Config, expectedPath, path)
170
171	//
172	// RRO module without defaults
173	//
174	m = result.ModuleForTests("foo_barebones", "android_common")
175
176	// Check AAPT2 link flags.
177	aapt2Flags = strings.Split(m.Output("package-res.apk").Args["flags"], " ")
178	unexpectedFlags := "--keep-raw-values"
179	if inList(unexpectedFlags, aapt2Flags) {
180		t.Errorf("unexpected value, %q is present in aapt2 link flags, %q", unexpectedFlags, aapt2Flags)
181	}
182
183	// Check device location.
184	path = android.AndroidMkEntriesForTest(t, result.TestContext, m.Module())[0].EntryMap["LOCAL_MODULE_PATH"]
185	expectedPath = []string{shared.JoinPath("out/target/product/test_device/product/overlay")}
186	android.AssertStringPathsRelativeToTopEquals(t, "LOCAL_MODULE_PATH", result.Config, expectedPath, path)
187}
188
189func TestOverrideRuntimeResourceOverlay(t *testing.T) {
190	ctx, _ := testJava(t, `
191		runtime_resource_overlay {
192			name: "foo_overlay",
193			certificate: "platform",
194			product_specific: true,
195			sdk_version: "current",
196		}
197
198		override_runtime_resource_overlay {
199			name: "bar_overlay",
200			base: "foo_overlay",
201			package_name: "com.android.bar.overlay",
202			target_package_name: "com.android.bar",
203			category: "mycategory",
204		}
205		`)
206
207	expectedVariants := []struct {
208		moduleName        string
209		variantName       string
210		apkPath           string
211		overrides         []string
212		targetVariant     string
213		packageFlag       string
214		targetPackageFlag string
215		categoryFlag      string
216	}{
217		{
218			variantName:       "android_common",
219			apkPath:           "out/soong/target/product/test_device/product/overlay/foo_overlay.apk",
220			overrides:         nil,
221			targetVariant:     "android_common",
222			packageFlag:       "",
223			targetPackageFlag: "",
224		},
225		{
226			variantName:       "android_common_bar_overlay",
227			apkPath:           "out/soong/target/product/test_device/product/overlay/bar_overlay.apk",
228			overrides:         []string{"foo_overlay"},
229			targetVariant:     "android_common_bar",
230			packageFlag:       "com.android.bar.overlay",
231			targetPackageFlag: "com.android.bar",
232			categoryFlag:      "mycategory",
233		},
234	}
235	for _, expected := range expectedVariants {
236		variant := ctx.ModuleForTests("foo_overlay", expected.variantName)
237
238		// Check the final apk name
239		variant.Output(expected.apkPath)
240
241		// Check if the overrides field values are correctly aggregated.
242		mod := variant.Module().(*RuntimeResourceOverlay)
243		if !reflect.DeepEqual(expected.overrides, mod.properties.Overrides) {
244			t.Errorf("Incorrect overrides property value, expected: %q, got: %q",
245				expected.overrides, mod.properties.Overrides)
246		}
247
248		// Check aapt2 flags.
249		res := variant.Output("package-res.apk")
250		aapt2Flags := res.Args["flags"]
251		checkAapt2LinkFlag(t, aapt2Flags, "rename-manifest-package", expected.packageFlag)
252		checkAapt2LinkFlag(t, aapt2Flags, "rename-resources-package", "")
253		checkAapt2LinkFlag(t, aapt2Flags, "rename-overlay-target-package", expected.targetPackageFlag)
254		checkAapt2LinkFlag(t, aapt2Flags, "rename-overlay-category", expected.categoryFlag)
255	}
256}
257
258func TestRuntimeResourceOverlayPartition(t *testing.T) {
259	bp := `
260		runtime_resource_overlay {
261			name: "device_specific",
262			device_specific: true,
263		}
264		runtime_resource_overlay {
265			name: "soc_specific",
266			soc_specific: true,
267		}
268		runtime_resource_overlay {
269			name: "system_ext_specific",
270			system_ext_specific: true,
271		}
272		runtime_resource_overlay {
273			name: "product_specific",
274			product_specific: true,
275		}
276		runtime_resource_overlay {
277			name: "default"
278		}
279	`
280	testCases := []struct {
281		name         string
282		expectedPath string
283	}{
284		{
285			name:         "device_specific",
286			expectedPath: "out/soong/target/product/test_device/odm/overlay",
287		},
288		{
289			name:         "soc_specific",
290			expectedPath: "out/soong/target/product/test_device/vendor/overlay",
291		},
292		{
293			name:         "system_ext_specific",
294			expectedPath: "out/soong/target/product/test_device/system_ext/overlay",
295		},
296		{
297			name:         "product_specific",
298			expectedPath: "out/soong/target/product/test_device/product/overlay",
299		},
300		{
301			name:         "default",
302			expectedPath: "out/soong/target/product/test_device/product/overlay",
303		},
304	}
305	for _, testCase := range testCases {
306		ctx, _ := testJava(t, bp)
307		mod := ctx.ModuleForTests(testCase.name, "android_common").Module().(*RuntimeResourceOverlay)
308		android.AssertPathRelativeToTopEquals(t, "Install dir is not correct for "+testCase.name, testCase.expectedPath, mod.installDir)
309	}
310}
311
312func TestRuntimeResourceOverlayFlagsPackages(t *testing.T) {
313	result := android.GroupFixturePreparers(
314		prepareForJavaTest,
315	).RunTestWithBp(t, `
316		runtime_resource_overlay {
317			name: "foo",
318			sdk_version: "current",
319			flags_packages: [
320				"bar",
321				"baz",
322			],
323		}
324		aconfig_declarations {
325			name: "bar",
326			package: "com.example.package.bar",
327			container: "com.android.foo",
328			srcs: [
329				"bar.aconfig",
330			],
331		}
332		aconfig_declarations {
333			name: "baz",
334			package: "com.example.package.baz",
335			container: "com.android.foo",
336			srcs: [
337				"baz.aconfig",
338			],
339		}
340	`)
341
342	foo := result.ModuleForTests("foo", "android_common")
343
344	// runtime_resource_overlay module depends on aconfig_declarations listed in flags_packages
345	android.AssertBoolEquals(t, "foo expected to depend on bar", true,
346		CheckModuleHasDependency(t, result.TestContext, "foo", "android_common", "bar"))
347
348	android.AssertBoolEquals(t, "foo expected to depend on baz", true,
349		CheckModuleHasDependency(t, result.TestContext, "foo", "android_common", "baz"))
350
351	aapt2LinkRule := foo.Rule("android/soong/java.aapt2Link")
352	linkInFlags := aapt2LinkRule.Args["inFlags"]
353	android.AssertStringDoesContain(t,
354		"aapt2 link command expected to pass feature flags arguments",
355		linkInFlags,
356		"--feature-flags @out/soong/.intermediates/bar/intermediate.txt --feature-flags @out/soong/.intermediates/baz/intermediate.txt",
357	)
358}
359