1/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "androidfw/AssetManager2.h"
18#include "androidfw/AssetManager.h"
19
20#include "android-base/logging.h"
21
22#include "TestHelpers.h"
23#include "androidfw/ResourceUtils.h"
24#include "data/appaslib/R.h"
25#include "data/basic/R.h"
26#include "data/lib_one/R.h"
27#include "data/lib_two/R.h"
28#include "data/libclient/R.h"
29#include "data/styles/R.h"
30#include "data/system/R.h"
31
32namespace app = com::android::app;
33namespace appaslib = com::android::appaslib::app;
34namespace basic = com::android::basic;
35namespace lib_one = com::android::lib_one;
36namespace lib_two = com::android::lib_two;
37namespace libclient = com::android::libclient;
38
39namespace android {
40
41class AssetManager2Test : public ::testing::Test {
42 public:
43  void SetUp() override {
44    basic_assets_ = ApkAssets::Load(GetTestDataPath() + "/basic/basic.apk");
45    ASSERT_NE(nullptr, basic_assets_);
46
47    basic_de_fr_assets_ = ApkAssets::Load(GetTestDataPath() + "/basic/basic_de_fr.apk");
48    ASSERT_NE(nullptr, basic_de_fr_assets_);
49
50    style_assets_ = ApkAssets::Load(GetTestDataPath() + "/styles/styles.apk");
51    ASSERT_NE(nullptr, style_assets_);
52
53    lib_one_assets_ = ApkAssets::Load(GetTestDataPath() + "/lib_one/lib_one.apk");
54    ASSERT_NE(nullptr, lib_one_assets_);
55
56    lib_two_assets_ = ApkAssets::Load(GetTestDataPath() + "/lib_two/lib_two.apk");
57    ASSERT_NE(nullptr, lib_two_assets_);
58
59    libclient_assets_ = ApkAssets::Load(GetTestDataPath() + "/libclient/libclient.apk");
60    ASSERT_NE(nullptr, libclient_assets_);
61
62    appaslib_assets_ = ApkAssets::Load(GetTestDataPath() + "/appaslib/appaslib.apk");
63    ASSERT_NE(nullptr, appaslib_assets_);
64
65    system_assets_ = ApkAssets::Load(GetTestDataPath() + "/system/system.apk", true /*system*/);
66    ASSERT_NE(nullptr, system_assets_);
67  }
68
69 protected:
70  std::unique_ptr<const ApkAssets> basic_assets_;
71  std::unique_ptr<const ApkAssets> basic_de_fr_assets_;
72  std::unique_ptr<const ApkAssets> style_assets_;
73  std::unique_ptr<const ApkAssets> lib_one_assets_;
74  std::unique_ptr<const ApkAssets> lib_two_assets_;
75  std::unique_ptr<const ApkAssets> libclient_assets_;
76  std::unique_ptr<const ApkAssets> appaslib_assets_;
77  std::unique_ptr<const ApkAssets> system_assets_;
78};
79
80TEST_F(AssetManager2Test, FindsResourceFromSingleApkAssets) {
81  ResTable_config desired_config;
82  memset(&desired_config, 0, sizeof(desired_config));
83  desired_config.language[0] = 'd';
84  desired_config.language[1] = 'e';
85
86  AssetManager2 assetmanager;
87  assetmanager.SetConfiguration(desired_config);
88  assetmanager.SetApkAssets({basic_assets_.get()});
89
90  Res_value value;
91  ResTable_config selected_config;
92  uint32_t flags;
93
94  ApkAssetsCookie cookie =
95      assetmanager.GetResource(basic::R::string::test1, false /*may_be_bag*/,
96                               0 /*density_override*/, &value, &selected_config, &flags);
97  ASSERT_NE(kInvalidCookie, cookie);
98
99  // Came from our ApkAssets.
100  EXPECT_EQ(0, cookie);
101
102  // It is the default config.
103  EXPECT_EQ(0, selected_config.language[0]);
104  EXPECT_EQ(0, selected_config.language[1]);
105
106  // It is a string.
107  EXPECT_EQ(Res_value::TYPE_STRING, value.dataType);
108}
109
110TEST_F(AssetManager2Test, FindsResourceFromMultipleApkAssets) {
111  ResTable_config desired_config;
112  memset(&desired_config, 0, sizeof(desired_config));
113  desired_config.language[0] = 'd';
114  desired_config.language[1] = 'e';
115
116  AssetManager2 assetmanager;
117  assetmanager.SetConfiguration(desired_config);
118  assetmanager.SetApkAssets({basic_assets_.get(), basic_de_fr_assets_.get()});
119
120  Res_value value;
121  ResTable_config selected_config;
122  uint32_t flags;
123
124  ApkAssetsCookie cookie =
125      assetmanager.GetResource(basic::R::string::test1, false /*may_be_bag*/,
126                               0 /*density_override*/, &value, &selected_config, &flags);
127  ASSERT_NE(kInvalidCookie, cookie);
128
129  // Came from our de_fr ApkAssets.
130  EXPECT_EQ(1, cookie);
131
132  // The configuration is German.
133  EXPECT_EQ('d', selected_config.language[0]);
134  EXPECT_EQ('e', selected_config.language[1]);
135
136  // It is a string.
137  EXPECT_EQ(Res_value::TYPE_STRING, value.dataType);
138}
139
140TEST_F(AssetManager2Test, FindsResourceFromSharedLibrary) {
141  AssetManager2 assetmanager;
142
143  // libclient is built with lib_one and then lib_two in order.
144  // Reverse the order to test that proper package ID re-assignment is happening.
145  assetmanager.SetApkAssets(
146      {lib_two_assets_.get(), lib_one_assets_.get(), libclient_assets_.get()});
147
148  Res_value value;
149  ResTable_config selected_config;
150  uint32_t flags;
151
152  ApkAssetsCookie cookie =
153      assetmanager.GetResource(libclient::R::string::foo_one, false /*may_be_bag*/,
154                               0 /*density_override*/, &value, &selected_config, &flags);
155  ASSERT_NE(kInvalidCookie, cookie);
156
157  // Reference comes from libclient.
158  EXPECT_EQ(2, cookie);
159  EXPECT_EQ(Res_value::TYPE_REFERENCE, value.dataType);
160
161  // Lookup the reference.
162  cookie = assetmanager.GetResource(value.data, false /* may_be_bag */, 0 /* density_override*/,
163                                    &value, &selected_config, &flags);
164  ASSERT_NE(kInvalidCookie, cookie);
165  EXPECT_EQ(1, cookie);
166  EXPECT_EQ(Res_value::TYPE_STRING, value.dataType);
167  EXPECT_EQ(std::string("Foo from lib_one"),
168            GetStringFromPool(assetmanager.GetStringPoolForCookie(cookie), value.data));
169
170  cookie = assetmanager.GetResource(libclient::R::string::foo_two, false /*may_be_bag*/,
171                                    0 /*density_override*/, &value, &selected_config, &flags);
172  ASSERT_NE(kInvalidCookie, cookie);
173
174  // Reference comes from libclient.
175  EXPECT_EQ(2, cookie);
176  EXPECT_EQ(Res_value::TYPE_REFERENCE, value.dataType);
177
178  // Lookup the reference.
179  cookie = assetmanager.GetResource(value.data, false /* may_be_bag */, 0 /* density_override*/,
180                                    &value, &selected_config, &flags);
181  ASSERT_NE(kInvalidCookie, cookie);
182  EXPECT_EQ(0, cookie);
183  EXPECT_EQ(Res_value::TYPE_STRING, value.dataType);
184  EXPECT_EQ(std::string("Foo from lib_two"),
185            GetStringFromPool(assetmanager.GetStringPoolForCookie(cookie), value.data));
186}
187
188TEST_F(AssetManager2Test, FindsResourceFromAppLoadedAsSharedLibrary) {
189  AssetManager2 assetmanager;
190  assetmanager.SetApkAssets({appaslib_assets_.get()});
191
192  // The appaslib package will have been assigned the package ID 0x02.
193
194  Res_value value;
195  ResTable_config selected_config;
196  uint32_t flags;
197  ApkAssetsCookie cookie = assetmanager.GetResource(
198      fix_package_id(appaslib::R::integer::number1, 0x02), false /*may_be_bag*/,
199      0u /*density_override*/, &value, &selected_config, &flags);
200  ASSERT_NE(kInvalidCookie, cookie);
201  EXPECT_EQ(Res_value::TYPE_REFERENCE, value.dataType);
202  EXPECT_EQ(fix_package_id(appaslib::R::array::integerArray1, 0x02), value.data);
203}
204
205TEST_F(AssetManager2Test, FindsBagResourceFromSingleApkAssets) {
206  AssetManager2 assetmanager;
207  assetmanager.SetApkAssets({basic_assets_.get()});
208
209  const ResolvedBag* bag = assetmanager.GetBag(basic::R::array::integerArray1);
210  ASSERT_NE(nullptr, bag);
211  ASSERT_EQ(3u, bag->entry_count);
212
213  EXPECT_EQ(static_cast<uint8_t>(Res_value::TYPE_INT_DEC), bag->entries[0].value.dataType);
214  EXPECT_EQ(1u, bag->entries[0].value.data);
215  EXPECT_EQ(0, bag->entries[0].cookie);
216
217  EXPECT_EQ(static_cast<uint8_t>(Res_value::TYPE_INT_DEC), bag->entries[1].value.dataType);
218  EXPECT_EQ(2u, bag->entries[1].value.data);
219  EXPECT_EQ(0, bag->entries[1].cookie);
220
221  EXPECT_EQ(static_cast<uint8_t>(Res_value::TYPE_INT_DEC), bag->entries[2].value.dataType);
222  EXPECT_EQ(3u, bag->entries[2].value.data);
223  EXPECT_EQ(0, bag->entries[2].cookie);
224}
225
226TEST_F(AssetManager2Test, FindsBagResourceFromMultipleApkAssets) {}
227
228TEST_F(AssetManager2Test, FindsBagResourceFromSharedLibrary) {
229  AssetManager2 assetmanager;
230
231  // libclient is built with lib_one and then lib_two in order.
232  // Reverse the order to test that proper package ID re-assignment is happening.
233  assetmanager.SetApkAssets(
234      {lib_two_assets_.get(), lib_one_assets_.get(), libclient_assets_.get()});
235
236  const ResolvedBag* bag = assetmanager.GetBag(libclient::R::style::Theme);
237  ASSERT_NE(nullptr, bag);
238  ASSERT_GE(bag->entry_count, 2u);
239
240  // First two attributes come from lib_one.
241  EXPECT_EQ(1, bag->entries[0].cookie);
242  EXPECT_EQ(0x03, get_package_id(bag->entries[0].key));
243  EXPECT_EQ(1, bag->entries[1].cookie);
244  EXPECT_EQ(0x03, get_package_id(bag->entries[1].key));
245}
246
247TEST_F(AssetManager2Test, MergesStylesWithParentFromSingleApkAssets) {
248  AssetManager2 assetmanager;
249  assetmanager.SetApkAssets({style_assets_.get()});
250
251  const ResolvedBag* bag_one = assetmanager.GetBag(app::R::style::StyleOne);
252  ASSERT_NE(nullptr, bag_one);
253  ASSERT_EQ(2u, bag_one->entry_count);
254
255  EXPECT_EQ(app::R::attr::attr_one, bag_one->entries[0].key);
256  EXPECT_EQ(Res_value::TYPE_INT_DEC, bag_one->entries[0].value.dataType);
257  EXPECT_EQ(1u, bag_one->entries[0].value.data);
258  EXPECT_EQ(0, bag_one->entries[0].cookie);
259
260  EXPECT_EQ(app::R::attr::attr_two, bag_one->entries[1].key);
261  EXPECT_EQ(Res_value::TYPE_INT_DEC, bag_one->entries[1].value.dataType);
262  EXPECT_EQ(2u, bag_one->entries[1].value.data);
263  EXPECT_EQ(0, bag_one->entries[1].cookie);
264
265  const ResolvedBag* bag_two = assetmanager.GetBag(app::R::style::StyleTwo);
266  ASSERT_NE(nullptr, bag_two);
267  ASSERT_EQ(6u, bag_two->entry_count);
268
269  // attr_one is inherited from StyleOne.
270  EXPECT_EQ(app::R::attr::attr_one, bag_two->entries[0].key);
271  EXPECT_EQ(Res_value::TYPE_INT_DEC, bag_two->entries[0].value.dataType);
272  EXPECT_EQ(1u, bag_two->entries[0].value.data);
273  EXPECT_EQ(0, bag_two->entries[0].cookie);
274
275  // attr_two should be overridden from StyleOne by StyleTwo.
276  EXPECT_EQ(app::R::attr::attr_two, bag_two->entries[1].key);
277  EXPECT_EQ(Res_value::TYPE_STRING, bag_two->entries[1].value.dataType);
278  EXPECT_EQ(0, bag_two->entries[1].cookie);
279  EXPECT_EQ(std::string("string"), GetStringFromPool(assetmanager.GetStringPoolForCookie(0),
280                                                     bag_two->entries[1].value.data));
281
282  // The rest are new attributes.
283
284  EXPECT_EQ(app::R::attr::attr_three, bag_two->entries[2].key);
285  EXPECT_EQ(Res_value::TYPE_ATTRIBUTE, bag_two->entries[2].value.dataType);
286  EXPECT_EQ(app::R::attr::attr_indirect, bag_two->entries[2].value.data);
287  EXPECT_EQ(0, bag_two->entries[2].cookie);
288
289  EXPECT_EQ(app::R::attr::attr_five, bag_two->entries[3].key);
290  EXPECT_EQ(Res_value::TYPE_REFERENCE, bag_two->entries[3].value.dataType);
291  EXPECT_EQ(app::R::string::string_one, bag_two->entries[3].value.data);
292  EXPECT_EQ(0, bag_two->entries[3].cookie);
293
294  EXPECT_EQ(app::R::attr::attr_indirect, bag_two->entries[4].key);
295  EXPECT_EQ(Res_value::TYPE_INT_DEC, bag_two->entries[4].value.dataType);
296  EXPECT_EQ(3u, bag_two->entries[4].value.data);
297  EXPECT_EQ(0, bag_two->entries[4].cookie);
298
299  EXPECT_EQ(app::R::attr::attr_empty, bag_two->entries[5].key);
300  EXPECT_EQ(Res_value::TYPE_NULL, bag_two->entries[5].value.dataType);
301  EXPECT_EQ(Res_value::DATA_NULL_EMPTY, bag_two->entries[5].value.data);
302  EXPECT_EQ(0, bag_two->entries[5].cookie);
303}
304
305TEST_F(AssetManager2Test, ResolveReferenceToResource) {
306  AssetManager2 assetmanager;
307  assetmanager.SetApkAssets({basic_assets_.get()});
308
309  Res_value value;
310  ResTable_config selected_config;
311  uint32_t flags;
312  ApkAssetsCookie cookie =
313      assetmanager.GetResource(basic::R::integer::ref1, false /*may_be_bag*/,
314                               0u /*density_override*/, &value, &selected_config, &flags);
315  ASSERT_NE(kInvalidCookie, cookie);
316
317  EXPECT_EQ(Res_value::TYPE_REFERENCE, value.dataType);
318  EXPECT_EQ(basic::R::integer::ref2, value.data);
319
320  uint32_t last_ref;
321  cookie = assetmanager.ResolveReference(cookie, &value, &selected_config, &flags, &last_ref);
322  ASSERT_NE(kInvalidCookie, cookie);
323  EXPECT_EQ(Res_value::TYPE_INT_DEC, value.dataType);
324  EXPECT_EQ(12000u, value.data);
325  EXPECT_EQ(basic::R::integer::ref2, last_ref);
326}
327
328TEST_F(AssetManager2Test, ResolveReferenceToBag) {
329  AssetManager2 assetmanager;
330  assetmanager.SetApkAssets({basic_assets_.get()});
331
332  Res_value value;
333  ResTable_config selected_config;
334  uint32_t flags;
335  ApkAssetsCookie cookie =
336      assetmanager.GetResource(basic::R::integer::number2, true /*may_be_bag*/,
337                               0u /*density_override*/, &value, &selected_config, &flags);
338  ASSERT_NE(kInvalidCookie, cookie);
339
340  EXPECT_EQ(Res_value::TYPE_REFERENCE, value.dataType);
341  EXPECT_EQ(basic::R::array::integerArray1, value.data);
342
343  uint32_t last_ref;
344  cookie = assetmanager.ResolveReference(cookie, &value, &selected_config, &flags, &last_ref);
345  ASSERT_NE(kInvalidCookie, cookie);
346  EXPECT_EQ(Res_value::TYPE_REFERENCE, value.dataType);
347  EXPECT_EQ(basic::R::array::integerArray1, value.data);
348  EXPECT_EQ(basic::R::array::integerArray1, last_ref);
349}
350
351static bool IsConfigurationPresent(const std::set<ResTable_config>& configurations,
352                                   const ResTable_config& configuration) {
353  return configurations.count(configuration) > 0;
354}
355
356TEST_F(AssetManager2Test, GetResourceConfigurations) {
357  AssetManager2 assetmanager;
358  assetmanager.SetApkAssets({system_assets_.get(), basic_de_fr_assets_.get()});
359
360  std::set<ResTable_config> configurations = assetmanager.GetResourceConfigurations();
361
362  // We expect the locale sv from the system assets, and de and fr from basic_de_fr assets.
363  // And one extra for the default configuration.
364  EXPECT_EQ(4u, configurations.size());
365
366  ResTable_config expected_config;
367  memset(&expected_config, 0, sizeof(expected_config));
368  expected_config.language[0] = 's';
369  expected_config.language[1] = 'v';
370  EXPECT_TRUE(IsConfigurationPresent(configurations, expected_config));
371
372  expected_config.language[0] = 'd';
373  expected_config.language[1] = 'e';
374  EXPECT_TRUE(IsConfigurationPresent(configurations, expected_config));
375
376  expected_config.language[0] = 'f';
377  expected_config.language[1] = 'r';
378  EXPECT_TRUE(IsConfigurationPresent(configurations, expected_config));
379
380  // Take out the system assets.
381  configurations = assetmanager.GetResourceConfigurations(true /* exclude_system */);
382
383  // We expect de and fr from basic_de_fr assets.
384  EXPECT_EQ(2u, configurations.size());
385
386  expected_config.language[0] = 's';
387  expected_config.language[1] = 'v';
388  EXPECT_FALSE(IsConfigurationPresent(configurations, expected_config));
389
390  expected_config.language[0] = 'd';
391  expected_config.language[1] = 'e';
392  EXPECT_TRUE(IsConfigurationPresent(configurations, expected_config));
393
394  expected_config.language[0] = 'f';
395  expected_config.language[1] = 'r';
396  EXPECT_TRUE(IsConfigurationPresent(configurations, expected_config));
397}
398
399TEST_F(AssetManager2Test, GetResourceLocales) {
400  AssetManager2 assetmanager;
401  assetmanager.SetApkAssets({system_assets_.get(), basic_de_fr_assets_.get()});
402
403  std::set<std::string> locales = assetmanager.GetResourceLocales();
404
405  // We expect the locale sv from the system assets, and de and fr from basic_de_fr assets.
406  EXPECT_EQ(3u, locales.size());
407  EXPECT_GT(locales.count("sv"), 0u);
408  EXPECT_GT(locales.count("de"), 0u);
409  EXPECT_GT(locales.count("fr"), 0u);
410
411  locales = assetmanager.GetResourceLocales(true /*exclude_system*/);
412  // We expect the de and fr locales from basic_de_fr assets.
413  EXPECT_EQ(2u, locales.size());
414  EXPECT_GT(locales.count("de"), 0u);
415  EXPECT_GT(locales.count("fr"), 0u);
416}
417
418TEST_F(AssetManager2Test, GetResourceId) {
419  AssetManager2 assetmanager;
420  assetmanager.SetApkAssets({basic_assets_.get()});
421
422  EXPECT_EQ(basic::R::layout::main,
423            assetmanager.GetResourceId("com.android.basic:layout/main", "", ""));
424  EXPECT_EQ(basic::R::layout::main,
425            assetmanager.GetResourceId("layout/main", "", "com.android.basic"));
426  EXPECT_EQ(basic::R::layout::main,
427            assetmanager.GetResourceId("main", "layout", "com.android.basic"));
428}
429
430TEST_F(AssetManager2Test, OpensFileFromSingleApkAssets) {}
431
432TEST_F(AssetManager2Test, OpensFileFromMultipleApkAssets) {}
433
434}  // namespace android
435