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
32 namespace app = com::android::app;
33 namespace appaslib = com::android::appaslib::app;
34 namespace basic = com::android::basic;
35 namespace lib_one = com::android::lib_one;
36 namespace lib_two = com::android::lib_two;
37 namespace libclient = com::android::libclient;
38
39 namespace android {
40
41 class AssetManager2Test : public ::testing::Test {
42 public:
SetUp()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
TEST_F(AssetManager2Test,FindsResourceFromSingleApkAssets)80 TEST_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
TEST_F(AssetManager2Test,FindsResourceFromMultipleApkAssets)110 TEST_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
TEST_F(AssetManager2Test,FindsResourceFromSharedLibrary)140 TEST_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
TEST_F(AssetManager2Test,FindsResourceFromAppLoadedAsSharedLibrary)188 TEST_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
TEST_F(AssetManager2Test,FindsBagResourceFromSingleApkAssets)205 TEST_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
TEST_F(AssetManager2Test,FindsBagResourceFromMultipleApkAssets)226 TEST_F(AssetManager2Test, FindsBagResourceFromMultipleApkAssets) {}
227
TEST_F(AssetManager2Test,FindsBagResourceFromSharedLibrary)228 TEST_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
TEST_F(AssetManager2Test,MergesStylesWithParentFromSingleApkAssets)247 TEST_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
TEST_F(AssetManager2Test,ResolveReferenceToResource)305 TEST_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
TEST_F(AssetManager2Test,ResolveReferenceToBag)328 TEST_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
IsConfigurationPresent(const std::set<ResTable_config> & configurations,const ResTable_config & configuration)351 static bool IsConfigurationPresent(const std::set<ResTable_config>& configurations,
352 const ResTable_config& configuration) {
353 return configurations.count(configuration) > 0;
354 }
355
TEST_F(AssetManager2Test,GetResourceConfigurations)356 TEST_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
TEST_F(AssetManager2Test,GetResourceLocales)399 TEST_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
TEST_F(AssetManager2Test,GetResourceId)418 TEST_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
TEST_F(AssetManager2Test,OpensFileFromSingleApkAssets)430 TEST_F(AssetManager2Test, OpensFileFromSingleApkAssets) {}
431
TEST_F(AssetManager2Test,OpensFileFromMultipleApkAssets)432 TEST_F(AssetManager2Test, OpensFileFromMultipleApkAssets) {}
433
434 } // namespace android
435