• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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		PrepareForTestWithOverlayBuildComponents,
66		android.FixtureModifyConfig(android.SetKatiEnabledForTests),
67		fs.AddToFixture(),
68	).RunTestWithBp(t, bp)
69
70	m := result.ModuleForTests("foo", "android_common")
71
72	// Check AAPT2 link flags.
73	aapt2Flags := m.Output("package-res.apk").Args["flags"]
74	expectedFlags := []string{"--keep-raw-values", "--no-resource-deduping", "--no-resource-removal"}
75	absentFlags := android.RemoveListFromList(expectedFlags, strings.Split(aapt2Flags, " "))
76	if len(absentFlags) > 0 {
77		t.Errorf("expected values, %q are missing in aapt2 link flags, %q", absentFlags, aapt2Flags)
78	}
79
80	// Check overlay.list output for static_libs dependency.
81	overlayList := android.PathsRelativeToTop(m.Output("aapt2/overlay.list").Inputs)
82	staticLibPackage := "out/soong/.intermediates/bar/android_common/package-res.apk"
83	if !inList(staticLibPackage, overlayList) {
84		t.Errorf("Stactic lib res package %q missing in overlay list: %q", staticLibPackage, overlayList)
85	}
86
87	// Check AAPT2 link flags for resource_libs dependency.
88	resourceLibFlag := "-I " + "out/soong/.intermediates/baz/android_common/package-res.apk"
89	if !strings.Contains(aapt2Flags, resourceLibFlag) {
90		t.Errorf("Resource lib flag %q missing in aapt2 link flags: %q", resourceLibFlag, aapt2Flags)
91	}
92
93	// Check cert signing flags.
94	signedApk := m.Output("signed/foo.apk")
95	actualCertSigningFlags := signedApk.Args["flags"]
96	expectedCertSigningFlags := "--lineage lineage.bin --rotation-min-sdk-version 32"
97	if expectedCertSigningFlags != actualCertSigningFlags {
98		t.Errorf("Incorrect cert signing flags, expected: %q, got: %q", expectedCertSigningFlags, actualCertSigningFlags)
99	}
100
101	signingFlag := signedApk.Args["certificates"]
102	expected := "build/make/target/product/security/platform.x509.pem build/make/target/product/security/platform.pk8"
103	if expected != signingFlag {
104		t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected, signingFlag)
105	}
106	androidMkEntries := android.AndroidMkEntriesForTest(t, result.TestContext, m.Module())[0]
107	path := androidMkEntries.EntryMap["LOCAL_CERTIFICATE"]
108	expectedPath := []string{"build/make/target/product/security/platform.x509.pem"}
109	if !reflect.DeepEqual(path, expectedPath) {
110		t.Errorf("Unexpected LOCAL_CERTIFICATE value: %v, expected: %v", path, expectedPath)
111	}
112
113	// Check device location.
114	path = androidMkEntries.EntryMap["LOCAL_MODULE_PATH"]
115	expectedPath = []string{shared.JoinPath("out/target/product/test_device/product/overlay")}
116	android.AssertStringPathsRelativeToTopEquals(t, "LOCAL_MODULE_PATH", result.Config, expectedPath, path)
117
118	// A themed module has a different device location
119	m = result.ModuleForTests("foo_themed", "android_common")
120	androidMkEntries = android.AndroidMkEntriesForTest(t, result.TestContext, m.Module())[0]
121	path = androidMkEntries.EntryMap["LOCAL_MODULE_PATH"]
122	expectedPath = []string{shared.JoinPath("out/target/product/test_device/product/overlay/faza")}
123	android.AssertStringPathsRelativeToTopEquals(t, "LOCAL_MODULE_PATH", result.Config, expectedPath, path)
124
125	overrides := androidMkEntries.EntryMap["LOCAL_OVERRIDES_PACKAGES"]
126	expectedOverrides := []string{"foo"}
127	if !reflect.DeepEqual(overrides, expectedOverrides) {
128		t.Errorf("Unexpected LOCAL_OVERRIDES_PACKAGES value: %v, expected: %v", overrides, expectedOverrides)
129	}
130}
131
132func TestRuntimeResourceOverlay_JavaDefaults(t *testing.T) {
133	result := android.GroupFixturePreparers(
134		PrepareForTestWithJavaDefaultModules,
135		android.FixtureModifyConfig(android.SetKatiEnabledForTests),
136	).RunTestWithBp(t, `
137		java_defaults {
138			name: "rro_defaults",
139			theme: "default_theme",
140			product_specific: true,
141			aaptflags: ["--keep-raw-values"],
142		}
143
144		runtime_resource_overlay {
145			name: "foo_with_defaults",
146			defaults: ["rro_defaults"],
147		}
148
149		runtime_resource_overlay {
150			name: "foo_barebones",
151		}
152		`)
153
154	//
155	// RRO module with defaults
156	//
157	m := result.ModuleForTests("foo_with_defaults", "android_common")
158
159	// Check AAPT2 link flags.
160	aapt2Flags := strings.Split(m.Output("package-res.apk").Args["flags"], " ")
161	expectedFlags := []string{"--keep-raw-values", "--no-resource-deduping", "--no-resource-removal"}
162	absentFlags := android.RemoveListFromList(expectedFlags, aapt2Flags)
163	if len(absentFlags) > 0 {
164		t.Errorf("expected values, %q are missing in aapt2 link flags, %q", absentFlags, aapt2Flags)
165	}
166
167	// Check device location.
168	path := android.AndroidMkEntriesForTest(t, result.TestContext, m.Module())[0].EntryMap["LOCAL_MODULE_PATH"]
169	expectedPath := []string{shared.JoinPath("out/target/product/test_device/product/overlay/default_theme")}
170	android.AssertStringPathsRelativeToTopEquals(t, "LOCAL_MODULE_PATH", result.Config, expectedPath, path)
171
172	//
173	// RRO module without defaults
174	//
175	m = result.ModuleForTests("foo_barebones", "android_common")
176
177	// Check AAPT2 link flags.
178	aapt2Flags = strings.Split(m.Output("package-res.apk").Args["flags"], " ")
179	unexpectedFlags := "--keep-raw-values"
180	if inList(unexpectedFlags, aapt2Flags) {
181		t.Errorf("unexpected value, %q is present in aapt2 link flags, %q", unexpectedFlags, aapt2Flags)
182	}
183
184	// Check device location.
185	path = android.AndroidMkEntriesForTest(t, result.TestContext, m.Module())[0].EntryMap["LOCAL_MODULE_PATH"]
186	expectedPath = []string{shared.JoinPath("out/target/product/test_device/product/overlay")}
187	android.AssertStringPathsRelativeToTopEquals(t, "LOCAL_MODULE_PATH", result.Config, expectedPath, path)
188}
189
190func TestOverrideRuntimeResourceOverlay(t *testing.T) {
191	ctx, _ := testJava(t, `
192		runtime_resource_overlay {
193			name: "foo_overlay",
194			certificate: "platform",
195			product_specific: true,
196			sdk_version: "current",
197		}
198
199		override_runtime_resource_overlay {
200			name: "bar_overlay",
201			base: "foo_overlay",
202			package_name: "com.android.bar.overlay",
203			target_package_name: "com.android.bar",
204			category: "mycategory",
205		}
206		`)
207
208	expectedVariants := []struct {
209		moduleName        string
210		variantName       string
211		apkPath           string
212		overrides         []string
213		targetVariant     string
214		packageFlag       string
215		targetPackageFlag string
216		categoryFlag      string
217	}{
218		{
219			variantName:       "android_common",
220			apkPath:           "out/soong/target/product/test_device/product/overlay/foo_overlay.apk",
221			overrides:         nil,
222			targetVariant:     "android_common",
223			packageFlag:       "",
224			targetPackageFlag: "",
225		},
226		{
227			variantName:       "android_common_bar_overlay",
228			apkPath:           "out/soong/target/product/test_device/product/overlay/bar_overlay.apk",
229			overrides:         []string{"foo_overlay"},
230			targetVariant:     "android_common_bar",
231			packageFlag:       "com.android.bar.overlay",
232			targetPackageFlag: "com.android.bar",
233			categoryFlag:      "mycategory",
234		},
235	}
236	for _, expected := range expectedVariants {
237		variant := ctx.ModuleForTests("foo_overlay", expected.variantName)
238
239		// Check the final apk name
240		variant.Output(expected.apkPath)
241
242		// Check if the overrides field values are correctly aggregated.
243		mod := variant.Module().(*RuntimeResourceOverlay)
244		if !reflect.DeepEqual(expected.overrides, mod.properties.Overrides) {
245			t.Errorf("Incorrect overrides property value, expected: %q, got: %q",
246				expected.overrides, mod.properties.Overrides)
247		}
248
249		// Check aapt2 flags.
250		res := variant.Output("package-res.apk")
251		aapt2Flags := res.Args["flags"]
252		checkAapt2LinkFlag(t, aapt2Flags, "rename-manifest-package", expected.packageFlag)
253		checkAapt2LinkFlag(t, aapt2Flags, "rename-resources-package", "")
254		checkAapt2LinkFlag(t, aapt2Flags, "rename-overlay-target-package", expected.targetPackageFlag)
255		checkAapt2LinkFlag(t, aapt2Flags, "rename-overlay-category", expected.categoryFlag)
256	}
257}
258
259func TestEnforceRRO_propagatesToDependencies(t *testing.T) {
260	testCases := []struct {
261		name              string
262		enforceRROTargets []string
263		rroDirs           map[string][]string
264	}{
265		{
266			name:              "no RRO",
267			enforceRROTargets: nil,
268			rroDirs: map[string][]string{
269				"foo": nil,
270				"bar": nil,
271			},
272		},
273		{
274			name:              "enforce RRO on all",
275			enforceRROTargets: []string{"*"},
276			rroDirs: map[string][]string{
277				"foo": {"product/vendor/blah/overlay/lib2/res"},
278				"bar": {"product/vendor/blah/overlay/lib2/res"},
279			},
280		},
281		{
282			name:              "enforce RRO on foo",
283			enforceRROTargets: []string{"foo"},
284			rroDirs: map[string][]string{
285				"foo": {"product/vendor/blah/overlay/lib2/res"},
286				"bar": {"product/vendor/blah/overlay/lib2/res"},
287			},
288		},
289	}
290
291	productResourceOverlays := []string{
292		"product/vendor/blah/overlay",
293	}
294
295	fs := android.MockFS{
296		"lib2/res/values/strings.xml":                             nil,
297		"product/vendor/blah/overlay/lib2/res/values/strings.xml": nil,
298	}
299
300	bp := `
301			android_app {
302				name: "foo",
303				sdk_version: "current",
304				resource_dirs: [],
305				static_libs: ["lib"],
306			}
307
308			android_app {
309				name: "bar",
310				sdk_version: "current",
311				resource_dirs: [],
312				static_libs: ["lib"],
313			}
314
315			android_library {
316				name: "lib",
317				sdk_version: "current",
318				resource_dirs: [],
319				static_libs: ["lib2"],
320			}
321
322			android_library {
323				name: "lib2",
324				sdk_version: "current",
325				resource_dirs: ["lib2/res"],
326			}
327		`
328
329	for _, testCase := range testCases {
330		t.Run(testCase.name, func(t *testing.T) {
331			result := android.GroupFixturePreparers(
332				PrepareForTestWithJavaDefaultModules,
333				PrepareForTestWithOverlayBuildComponents,
334				fs.AddToFixture(),
335				android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
336					variables.ProductResourceOverlays = productResourceOverlays
337					if testCase.enforceRROTargets != nil {
338						variables.EnforceRROTargets = testCase.enforceRROTargets
339					}
340				}),
341			).RunTestWithBp(t, bp)
342
343			modules := []string{"foo", "bar"}
344			for _, moduleName := range modules {
345				module := result.ModuleForTests(moduleName, "android_common")
346				mkEntries := android.AndroidMkEntriesForTest(t, result.TestContext, module.Module())[0]
347				actualRRODirs := mkEntries.EntryMap["LOCAL_SOONG_PRODUCT_RRO_DIRS"]
348				if !reflect.DeepEqual(actualRRODirs, testCase.rroDirs[moduleName]) {
349					t.Errorf("exected %s LOCAL_SOONG_PRODUCT_RRO_DIRS entry: %v\ngot:%q",
350						moduleName, testCase.rroDirs[moduleName], actualRRODirs)
351				}
352			}
353		})
354	}
355}
356
357func TestRuntimeResourceOverlayPartition(t *testing.T) {
358	bp := `
359		runtime_resource_overlay {
360			name: "device_specific",
361			device_specific: true,
362		}
363		runtime_resource_overlay {
364			name: "soc_specific",
365			soc_specific: true,
366		}
367		runtime_resource_overlay {
368			name: "system_ext_specific",
369			system_ext_specific: true,
370		}
371		runtime_resource_overlay {
372			name: "product_specific",
373			product_specific: true,
374		}
375		runtime_resource_overlay {
376			name: "default"
377		}
378	`
379	testCases := []struct {
380		name         string
381		expectedPath string
382	}{
383		{
384			name:         "device_specific",
385			expectedPath: "out/soong/target/product/test_device/odm/overlay",
386		},
387		{
388			name:         "soc_specific",
389			expectedPath: "out/soong/target/product/test_device/vendor/overlay",
390		},
391		{
392			name:         "system_ext_specific",
393			expectedPath: "out/soong/target/product/test_device/system_ext/overlay",
394		},
395		{
396			name:         "product_specific",
397			expectedPath: "out/soong/target/product/test_device/product/overlay",
398		},
399		{
400			name:         "default",
401			expectedPath: "out/soong/target/product/test_device/product/overlay",
402		},
403	}
404	for _, testCase := range testCases {
405		ctx, _ := testJava(t, bp)
406		mod := ctx.ModuleForTests(testCase.name, "android_common").Module().(*RuntimeResourceOverlay)
407		android.AssertPathRelativeToTopEquals(t, "Install dir is not correct for "+testCase.name, testCase.expectedPath, mod.installDir)
408	}
409}
410