rro_test.go 13 KB

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