rro_test.go 13 KB

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