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 "TestHelpers.h"
21 #include "android-base/file.h"
22 #include "android-base/logging.h"
23 #include "androidfw/ResourceUtils.h"
24 #include "data/appaslib/R.h"
25 #include "data/basic/R.h"
26 #include "data/flagged/R.h"
27 #include "data/lib_one/R.h"
28 #include "data/lib_two/R.h"
29 #include "data/libclient/R.h"
30 #include "data/styles/R.h"
31 #include "data/system/R.h"
32
33 namespace app = com::android::app;
34 namespace appaslib = com::android::appaslib::app;
35 namespace basic = com::android::basic;
36 namespace flagged = com::android::flagged;
37 namespace lib_one = com::android::lib_one;
38 namespace lib_two = com::android::lib_two;
39 namespace libclient = com::android::libclient;
40
41 using ::testing::Eq;
42 using ::testing::NotNull;
43 using ::testing::StrEq;
44
45 namespace android {
46
47 class AssetManager2Test : public ::testing::Test {
48 public:
SetUp()49 void SetUp() override {
50 // Move to the test data directory so the idmap can locate the overlay APK.
51 std::string original_path = base::GetExecutableDirectory();
52 chdir(GetTestDataPath().c_str());
53
54 basic_assets_ = ApkAssets::Load("basic/basic.apk");
55 ASSERT_NE(nullptr, basic_assets_);
56
57 basic_de_fr_assets_ = ApkAssets::Load("basic/basic_de_fr.apk");
58 ASSERT_NE(nullptr, basic_de_fr_assets_);
59
60 basic_xhdpi_assets_ = ApkAssets::Load("basic/basic_xhdpi-v4.apk");
61 ASSERT_NE(nullptr, basic_de_fr_assets_);
62
63 basic_xxhdpi_assets_ = ApkAssets::Load("basic/basic_xxhdpi-v4.apk");
64 ASSERT_NE(nullptr, basic_de_fr_assets_);
65
66 style_assets_ = ApkAssets::Load("styles/styles.apk");
67 ASSERT_NE(nullptr, style_assets_);
68
69 lib_one_assets_ = ApkAssets::Load("lib_one/lib_one.apk");
70 ASSERT_NE(nullptr, lib_one_assets_);
71
72 lib_two_assets_ = ApkAssets::Load("lib_two/lib_two.apk");
73 ASSERT_NE(nullptr, lib_two_assets_);
74
75 libclient_assets_ = ApkAssets::Load("libclient/libclient.apk");
76 ASSERT_NE(nullptr, libclient_assets_);
77
78 appaslib_assets_ = ApkAssets::Load("appaslib/appaslib.apk", PROPERTY_DYNAMIC);
79 ASSERT_NE(nullptr, appaslib_assets_);
80
81 system_assets_ = ApkAssets::Load("system/system.apk", PROPERTY_SYSTEM);
82 ASSERT_NE(nullptr, system_assets_);
83
84 app_assets_ = ApkAssets::Load("app/app.apk");
85 ASSERT_THAT(app_assets_, NotNull());
86
87 overlay_assets_ = ApkAssets::LoadOverlay("overlay/overlay.idmap");
88 ASSERT_NE(nullptr, overlay_assets_);
89
90 overlayable_assets_ = ApkAssets::Load("overlayable/overlayable.apk");
91 ASSERT_THAT(overlayable_assets_, NotNull());
92
93 flagged_assets_ = ApkAssets::Load("flagged/flagged.apk");
94 ASSERT_THAT(app_assets_, NotNull());
95
96 chdir(original_path.c_str());
97 }
98
99 protected:
100 AssetManager2::ApkAssetsPtr basic_assets_;
101 AssetManager2::ApkAssetsPtr basic_de_fr_assets_;
102 AssetManager2::ApkAssetsPtr basic_xhdpi_assets_;
103 AssetManager2::ApkAssetsPtr basic_xxhdpi_assets_;
104 AssetManager2::ApkAssetsPtr style_assets_;
105 AssetManager2::ApkAssetsPtr lib_one_assets_;
106 AssetManager2::ApkAssetsPtr lib_two_assets_;
107 AssetManager2::ApkAssetsPtr libclient_assets_;
108 AssetManager2::ApkAssetsPtr appaslib_assets_;
109 AssetManager2::ApkAssetsPtr system_assets_;
110 AssetManager2::ApkAssetsPtr app_assets_;
111 AssetManager2::ApkAssetsPtr overlay_assets_;
112 AssetManager2::ApkAssetsPtr overlayable_assets_;
113 AssetManager2::ApkAssetsPtr flagged_assets_;
114 };
115
TEST_F(AssetManager2Test,FindsResourceFromSingleApkAssets)116 TEST_F(AssetManager2Test, FindsResourceFromSingleApkAssets) {
117 ResTable_config desired_config;
118 memset(&desired_config, 0, sizeof(desired_config));
119 desired_config.language[0] = 'd';
120 desired_config.language[1] = 'e';
121
122 AssetManager2 assetmanager;
123 assetmanager.SetConfigurations({{desired_config}});
124 assetmanager.SetApkAssets({basic_assets_});
125
126 auto value = assetmanager.GetResource(basic::R::string::test1);
127 ASSERT_TRUE(value.has_value());
128
129 // Came from our ApkAssets.
130 EXPECT_EQ(0, value->cookie);
131
132 // It is the default config.
133 EXPECT_EQ(0, value->config.language[0]);
134 EXPECT_EQ(0, value->config.language[1]);
135
136 // It is a string.
137 EXPECT_EQ(Res_value::TYPE_STRING, value->type);
138 }
139
TEST_F(AssetManager2Test,FindsResourceFromMultipleApkAssets)140 TEST_F(AssetManager2Test, FindsResourceFromMultipleApkAssets) {
141 ResTable_config desired_config;
142 memset(&desired_config, 0, sizeof(desired_config));
143 desired_config.language[0] = 'd';
144 desired_config.language[1] = 'e';
145
146 AssetManager2 assetmanager;
147 assetmanager.SetConfigurations({{desired_config}});
148 assetmanager.SetApkAssets({basic_assets_, basic_de_fr_assets_});
149
150 auto value = assetmanager.GetResource(basic::R::string::test1);
151 ASSERT_TRUE(value.has_value());
152
153 // Came from our de_fr ApkAssets.
154 EXPECT_EQ(1, value->cookie);
155
156 // The configuration is German.
157 EXPECT_EQ('d', value->config.language[0]);
158 EXPECT_EQ('e', value->config.language[1]);
159
160 // It is a string.
161 EXPECT_EQ(Res_value::TYPE_STRING, value->type);
162 }
163
TEST_F(AssetManager2Test,FindsResourceFromSharedLibrary)164 TEST_F(AssetManager2Test, FindsResourceFromSharedLibrary) {
165 AssetManager2 assetmanager;
166
167 // libclient is built with lib_one and then lib_two in order.
168 // Reverse the order to test that proper package ID re-assignment is happening.
169 assetmanager.SetApkAssets({lib_two_assets_, lib_one_assets_, libclient_assets_});
170
171 auto value = assetmanager.GetResource(libclient::R::string::foo_one);
172 ASSERT_TRUE(value.has_value());
173
174 // Reference comes from libclient.
175 EXPECT_EQ(2, value->cookie);
176 EXPECT_EQ(Res_value::TYPE_REFERENCE, value->type);
177
178 // Lookup the reference.
179 value = assetmanager.GetResource(value->data);
180 ASSERT_TRUE(value.has_value());
181 EXPECT_EQ(1, value->cookie);
182 EXPECT_EQ(Res_value::TYPE_STRING, value->type);
183 EXPECT_EQ(std::string("Foo from lib_one"),
184 GetStringFromPool(assetmanager.GetStringPoolForCookie(value->cookie), value->data));
185
186 value = assetmanager.GetResource(libclient::R::string::foo_two);
187 ASSERT_TRUE(value.has_value());
188
189 // Reference comes from libclient.
190 EXPECT_EQ(2, value->cookie);
191 EXPECT_EQ(Res_value::TYPE_REFERENCE, value->type);
192
193 // Lookup the reference.
194 value = assetmanager.GetResource(value->data);
195 ASSERT_TRUE(value.has_value());
196 EXPECT_EQ(0, value->cookie);
197 EXPECT_EQ(Res_value::TYPE_STRING, value->type);
198 EXPECT_EQ(std::string("Foo from lib_two"),
199 GetStringFromPool(assetmanager.GetStringPoolForCookie(value->cookie), value->data));
200 }
201
TEST_F(AssetManager2Test,FindsResourceFromAppLoadedAsSharedLibrary)202 TEST_F(AssetManager2Test, FindsResourceFromAppLoadedAsSharedLibrary) {
203 AssetManager2 assetmanager;
204 assetmanager.SetApkAssets({appaslib_assets_});
205
206 // The appaslib package will have been assigned the package ID 0x02.
207 auto value = assetmanager.GetResource(fix_package_id(appaslib::R::integer::number1, 0x02));
208 ASSERT_TRUE(value.has_value());
209 EXPECT_EQ(Res_value::TYPE_REFERENCE, value->type);
210 EXPECT_EQ(fix_package_id(appaslib::R::array::integerArray1, 0x02), value->data);
211 }
212
TEST_F(AssetManager2Test,AssignsOverlayPackageIdLast)213 TEST_F(AssetManager2Test, AssignsOverlayPackageIdLast) {
214 AssetManager2 assetmanager;
215 assetmanager.SetApkAssets({overlayable_assets_, overlay_assets_, lib_one_assets_});
216
217 ASSERT_EQ(3, assetmanager.GetApkAssetsCount());
218 auto op = assetmanager.StartOperation();
219 ASSERT_EQ(overlayable_assets_, assetmanager.GetApkAssets(0));
220 ASSERT_EQ(overlay_assets_, assetmanager.GetApkAssets(1));
221 ASSERT_EQ(lib_one_assets_, assetmanager.GetApkAssets(2));
222
223 auto get_first_package_id = [&assetmanager](auto apkAssets) -> uint8_t {
224 return assetmanager.GetAssignedPackageId(apkAssets->GetLoadedArsc()->GetPackages()[0].get());
225 };
226
227 ASSERT_EQ(0x7f, get_first_package_id(overlayable_assets_));
228 ASSERT_EQ(0x03, get_first_package_id(overlay_assets_));
229 ASSERT_EQ(0x02, get_first_package_id(lib_one_assets_));
230 }
231
TEST_F(AssetManager2Test,GetSharedLibraryResourceName)232 TEST_F(AssetManager2Test, GetSharedLibraryResourceName) {
233 AssetManager2 assetmanager;
234 assetmanager.SetApkAssets({lib_one_assets_});
235
236 auto name = assetmanager.GetResourceName(lib_one::R::string::foo);
237 ASSERT_TRUE(name.has_value());
238 ASSERT_EQ("com.android.lib_one:string/foo", ToFormattedResourceString(*name));
239 }
240
TEST_F(AssetManager2Test,GetResourceNameNonMatchingConfig)241 TEST_F(AssetManager2Test, GetResourceNameNonMatchingConfig) {
242 AssetManager2 assetmanager;
243 assetmanager.SetApkAssets({basic_de_fr_assets_});
244
245 auto value = assetmanager.GetResourceName(basic::R::string::test1);
246 ASSERT_TRUE(value.has_value());
247 EXPECT_EQ("com.android.basic:string/test1", ToFormattedResourceString(*value));
248 }
249
TEST_F(AssetManager2Test,GetResourceTypeSpecFlags)250 TEST_F(AssetManager2Test, GetResourceTypeSpecFlags) {
251 AssetManager2 assetmanager;
252 assetmanager.SetApkAssets({basic_de_fr_assets_});
253
254 auto value = assetmanager.GetResourceTypeSpecFlags(basic::R::string::test1);
255 ASSERT_TRUE(value.has_value());
256 EXPECT_EQ(ResTable_typeSpec::SPEC_PUBLIC | ResTable_config::CONFIG_LOCALE, *value);
257 }
258
TEST_F(AssetManager2Test,FindsBagResourceFromSingleApkAssets)259 TEST_F(AssetManager2Test, FindsBagResourceFromSingleApkAssets) {
260 AssetManager2 assetmanager;
261 assetmanager.SetApkAssets({basic_assets_});
262
263 auto bag = assetmanager.GetBag(basic::R::array::integerArray1);
264 ASSERT_TRUE(bag.has_value());
265
266 ASSERT_EQ(3u, (*bag)->entry_count);
267
268 EXPECT_EQ(static_cast<uint8_t>(Res_value::TYPE_INT_DEC), (*bag)->entries[0].value.dataType);
269 EXPECT_EQ(1u, (*bag)->entries[0].value.data);
270 EXPECT_EQ(0, (*bag)->entries[0].cookie);
271
272 EXPECT_EQ(static_cast<uint8_t>(Res_value::TYPE_INT_DEC), (*bag)->entries[1].value.dataType);
273 EXPECT_EQ(2u, (*bag)->entries[1].value.data);
274 EXPECT_EQ(0, (*bag)->entries[1].cookie);
275
276 EXPECT_EQ(static_cast<uint8_t>(Res_value::TYPE_INT_DEC), (*bag)->entries[2].value.dataType);
277 EXPECT_EQ(3u, (*bag)->entries[2].value.data);
278 EXPECT_EQ(0, (*bag)->entries[2].cookie);
279 }
280
TEST_F(AssetManager2Test,FindsBagResourceFromMultipleApkAssets)281 TEST_F(AssetManager2Test, FindsBagResourceFromMultipleApkAssets) {}
282
TEST_F(AssetManager2Test,FindsBagResourceFromSharedLibrary)283 TEST_F(AssetManager2Test, FindsBagResourceFromSharedLibrary) {
284 AssetManager2 assetmanager;
285
286 // libclient is built with lib_one and then lib_two in order.
287 // Reverse the order to test that proper package ID re-assignment is happening.
288 assetmanager.SetApkAssets({lib_two_assets_, lib_one_assets_, libclient_assets_});
289
290 auto bag = assetmanager.GetBag(fix_package_id(lib_one::R::style::Theme, 0x03));
291 ASSERT_TRUE(bag.has_value());
292
293 ASSERT_GE((*bag)->entry_count, 2u);
294
295 // First two attributes come from lib_one.
296 EXPECT_EQ(1, (*bag)->entries[0].cookie);
297 EXPECT_EQ(0x03, get_package_id((*bag)->entries[0].key));
298 EXPECT_EQ(1, (*bag)->entries[1].cookie);
299 EXPECT_EQ(0x03, get_package_id((*bag)->entries[1].key));
300 }
301
TEST_F(AssetManager2Test,FindsBagResourceFromMultipleSharedLibraries)302 TEST_F(AssetManager2Test, FindsBagResourceFromMultipleSharedLibraries) {
303 AssetManager2 assetmanager;
304
305 // libclient is built with lib_one and then lib_two in order.
306 // Reverse the order to test that proper package ID re-assignment is happening.
307 assetmanager.SetApkAssets({lib_two_assets_, lib_one_assets_, libclient_assets_});
308
309 auto bag = assetmanager.GetBag(libclient::R::style::ThemeMultiLib);
310 ASSERT_TRUE(bag.has_value());
311 ASSERT_EQ((*bag)->entry_count, 2u);
312
313 // First attribute comes from lib_two.
314 EXPECT_EQ(2, (*bag)->entries[0].cookie);
315 EXPECT_EQ(0x02, get_package_id((*bag)->entries[0].key));
316
317 // The next two attributes come from lib_one.
318 EXPECT_EQ(2, (*bag)->entries[1].cookie);
319 EXPECT_EQ(0x03, get_package_id((*bag)->entries[1].key));
320 }
321
TEST_F(AssetManager2Test,FindsStyleResourceWithParentFromSharedLibrary)322 TEST_F(AssetManager2Test, FindsStyleResourceWithParentFromSharedLibrary) {
323 AssetManager2 assetmanager;
324
325 // libclient is built with lib_one and then lib_two in order.
326 // Reverse the order to test that proper package ID re-assignment is happening.
327 assetmanager.SetApkAssets({lib_two_assets_, lib_one_assets_, libclient_assets_});
328
329 auto bag = assetmanager.GetBag(libclient::R::style::Theme);
330 ASSERT_TRUE(bag.has_value());
331 ASSERT_GE((*bag)->entry_count, 2u);
332
333 // First two attributes come from lib_one.
334 EXPECT_EQ(1, (*bag)->entries[0].cookie);
335 EXPECT_EQ(0x03, get_package_id((*bag)->entries[0].key));
336 EXPECT_EQ(1, (*bag)->entries[1].cookie);
337 EXPECT_EQ(0x03, get_package_id((*bag)->entries[1].key));
338 }
339
TEST_F(AssetManager2Test,MergesStylesWithParentFromSingleApkAssets)340 TEST_F(AssetManager2Test, MergesStylesWithParentFromSingleApkAssets) {
341 AssetManager2 assetmanager;
342 assetmanager.SetApkAssets({style_assets_});
343
344 auto bag_one = assetmanager.GetBag(app::R::style::StyleOne);
345 ASSERT_TRUE(bag_one.has_value());
346 ASSERT_EQ(2u, (*bag_one)->entry_count);
347
348 EXPECT_EQ(app::R::attr::attr_one, (*bag_one)->entries[0].key);
349 EXPECT_EQ(Res_value::TYPE_INT_DEC, (*bag_one)->entries[0].value.dataType);
350 EXPECT_EQ(1u, (*bag_one)->entries[0].value.data);
351 EXPECT_EQ(0, (*bag_one)->entries[0].cookie);
352
353 EXPECT_EQ(app::R::attr::attr_two, (*bag_one)->entries[1].key);
354 EXPECT_EQ(Res_value::TYPE_INT_DEC, (*bag_one)->entries[1].value.dataType);
355 EXPECT_EQ(2u, (*bag_one)->entries[1].value.data);
356 EXPECT_EQ(0, (*bag_one)->entries[1].cookie);
357
358 auto bag_two = assetmanager.GetBag(app::R::style::StyleTwo);
359 ASSERT_TRUE(bag_two.has_value());
360 ASSERT_EQ(6u, (*bag_two)->entry_count);
361
362 // attr_one is inherited from StyleOne.
363 EXPECT_EQ(app::R::attr::attr_one, (*bag_two)->entries[0].key);
364 EXPECT_EQ(Res_value::TYPE_INT_DEC, (*bag_two)->entries[0].value.dataType);
365 EXPECT_EQ(1u, (*bag_two)->entries[0].value.data);
366 EXPECT_EQ(0, (*bag_two)->entries[0].cookie);
367 EXPECT_EQ(app::R::style::StyleOne, (*bag_two)->entries[0].style);
368
369 // attr_two should be overridden from StyleOne by StyleTwo.
370 EXPECT_EQ(app::R::attr::attr_two, (*bag_two)->entries[1].key);
371 EXPECT_EQ(Res_value::TYPE_STRING, (*bag_two)->entries[1].value.dataType);
372 EXPECT_EQ(0, (*bag_two)->entries[1].cookie);
373 EXPECT_EQ(app::R::style::StyleTwo, (*bag_two)->entries[1].style);
374 EXPECT_EQ(std::string("string"), GetStringFromPool(assetmanager.GetStringPoolForCookie(0),
375 (*bag_two)->entries[1].value.data));
376
377 // The rest are new attributes.
378
379 EXPECT_EQ(app::R::attr::attr_three, (*bag_two)->entries[2].key);
380 EXPECT_EQ(Res_value::TYPE_ATTRIBUTE, (*bag_two)->entries[2].value.dataType);
381 EXPECT_EQ(app::R::attr::attr_indirect, (*bag_two)->entries[2].value.data);
382 EXPECT_EQ(0, (*bag_two)->entries[2].cookie);
383 EXPECT_EQ(app::R::style::StyleTwo, (*bag_two)->entries[2].style);
384
385 EXPECT_EQ(app::R::attr::attr_five, (*bag_two)->entries[3].key);
386 EXPECT_EQ(Res_value::TYPE_REFERENCE, (*bag_two)->entries[3].value.dataType);
387 EXPECT_EQ(app::R::string::string_one, (*bag_two)->entries[3].value.data);
388 EXPECT_EQ(0, (*bag_two)->entries[3].cookie);
389 EXPECT_EQ(app::R::style::StyleTwo, (*bag_two)->entries[3].style);
390
391 EXPECT_EQ(app::R::attr::attr_indirect, (*bag_two)->entries[4].key);
392 EXPECT_EQ(Res_value::TYPE_INT_DEC, (*bag_two)->entries[4].value.dataType);
393 EXPECT_EQ(3u, (*bag_two)->entries[4].value.data);
394 EXPECT_EQ(0, (*bag_two)->entries[4].cookie);
395 EXPECT_EQ(app::R::style::StyleTwo, (*bag_two)->entries[4].style);
396
397 EXPECT_EQ(app::R::attr::attr_empty, (*bag_two)->entries[5].key);
398 EXPECT_EQ(Res_value::TYPE_NULL, (*bag_two)->entries[5].value.dataType);
399 EXPECT_EQ(Res_value::DATA_NULL_EMPTY, (*bag_two)->entries[5].value.data);
400 EXPECT_EQ(0, (*bag_two)->entries[5].cookie);
401 EXPECT_EQ(app::R::style::StyleTwo, (*bag_two)->entries[5].style);
402 }
403
TEST_F(AssetManager2Test,MergeStylesCircularDependency)404 TEST_F(AssetManager2Test, MergeStylesCircularDependency) {
405 AssetManager2 assetmanager;
406 assetmanager.SetApkAssets({style_assets_});
407
408 // GetBag should stop traversing the parents of styles when a circular
409 // dependency is detected
410 auto bag = assetmanager.GetBag(app::R::style::StyleFour);
411 ASSERT_TRUE(bag.has_value());
412 ASSERT_EQ(3u, (*bag)->entry_count);
413 }
414
TEST_F(AssetManager2Test,ResolveReferenceToResource)415 TEST_F(AssetManager2Test, ResolveReferenceToResource) {
416 AssetManager2 assetmanager;
417 assetmanager.SetApkAssets({basic_assets_});
418
419 auto value = assetmanager.GetResource(basic::R::integer::ref1);
420 ASSERT_TRUE(value.has_value());
421 EXPECT_EQ(Res_value::TYPE_REFERENCE, value->type);
422 EXPECT_EQ(basic::R::integer::ref2, value->data);
423
424 auto result = assetmanager.ResolveReference(*value);
425 ASSERT_TRUE(result.has_value());
426 EXPECT_EQ(Res_value::TYPE_INT_DEC, value->type);
427 EXPECT_EQ(12000u, value->data);
428 EXPECT_EQ(basic::R::integer::ref2, value->resid);
429 }
430
TEST_F(AssetManager2Test,ResolveReferenceToBag)431 TEST_F(AssetManager2Test, ResolveReferenceToBag) {
432 AssetManager2 assetmanager;
433 assetmanager.SetApkAssets({basic_assets_});
434
435 auto value = assetmanager.GetResource(basic::R::integer::number2, true /*may_be_bag*/);
436 ASSERT_TRUE(value.has_value());
437 EXPECT_EQ(Res_value::TYPE_REFERENCE, value->type);
438 EXPECT_EQ(basic::R::array::integerArray1, value->data);
439
440 auto result = assetmanager.ResolveReference(*value);
441 ASSERT_TRUE(result.has_value());
442 EXPECT_EQ(Res_value::TYPE_REFERENCE, value->type);
443 EXPECT_EQ(basic::R::array::integerArray1, value->data);
444 EXPECT_EQ(basic::R::array::integerArray1, value->resid);
445 }
446
TEST_F(AssetManager2Test,ResolveDeepIdReference)447 TEST_F(AssetManager2Test, ResolveDeepIdReference) {
448 AssetManager2 assetmanager;
449 assetmanager.SetApkAssets({basic_assets_});
450
451 // Set up the resource ids
452 auto high_ref = assetmanager.GetResourceId("@id/high_ref", "values", "com.android.basic");
453 ASSERT_TRUE(high_ref.has_value());
454
455 auto middle_ref = assetmanager.GetResourceId("@id/middle_ref", "values", "com.android.basic");
456 ASSERT_TRUE(middle_ref.has_value());
457
458 auto low_ref = assetmanager.GetResourceId("@id/low_ref", "values", "com.android.basic");
459 ASSERT_TRUE(low_ref.has_value());
460
461 // Retrieve the most shallow resource
462 auto value = assetmanager.GetResource(*high_ref);
463 ASSERT_TRUE(value.has_value());
464 EXPECT_EQ(Res_value::TYPE_REFERENCE, value->type);
465 EXPECT_EQ(*middle_ref, value->data);;
466
467 // Check that resolving the reference resolves to the deepest id
468 auto result = assetmanager.ResolveReference(*value);
469 ASSERT_TRUE(result.has_value());
470 EXPECT_EQ(*low_ref, value->resid);
471 }
472
TEST_F(AssetManager2Test,DensityOverride)473 TEST_F(AssetManager2Test, DensityOverride) {
474 AssetManager2 assetmanager;
475 assetmanager.SetApkAssets({basic_assets_, basic_xhdpi_assets_, basic_xxhdpi_assets_});
476 assetmanager.SetConfigurations({{{
477 .density = ResTable_config::DENSITY_XHIGH,
478 .sdkVersion = 21,
479 }}});
480
481 auto value = assetmanager.GetResource(basic::R::string::density, false /*may_be_bag*/);
482 ASSERT_TRUE(value.has_value());
483 EXPECT_EQ(Res_value::TYPE_STRING, value->type);
484 EXPECT_EQ("xhdpi", GetStringFromPool(assetmanager.GetStringPoolForCookie(value->cookie),
485 value->data));
486
487 value = assetmanager.GetResource(basic::R::string::density, false /*may_be_bag*/,
488 ResTable_config::DENSITY_XXHIGH);
489 ASSERT_TRUE(value.has_value());
490 EXPECT_EQ(Res_value::TYPE_STRING, value->type);
491 EXPECT_EQ("xxhdpi", GetStringFromPool(assetmanager.GetStringPoolForCookie(value->cookie),
492 value->data));
493 }
494
TEST_F(AssetManager2Test,KeepLastReferenceIdUnmodifiedIfNoReferenceIsResolved)495 TEST_F(AssetManager2Test, KeepLastReferenceIdUnmodifiedIfNoReferenceIsResolved) {
496 AssetManager2 assetmanager;
497 assetmanager.SetApkAssets({basic_assets_});
498
499 // Create some kind of value that is NOT a reference.
500 AssetManager2::SelectedValue value{};
501 value.cookie = 1;
502 value.type = Res_value::TYPE_STRING;
503 value.resid = basic::R::string::test1;
504
505 auto result = assetmanager.ResolveReference(value);
506 ASSERT_TRUE(result.has_value());
507 EXPECT_EQ(1, value.cookie);
508 EXPECT_EQ(basic::R::string::test1, value.resid);
509 }
510
TEST_F(AssetManager2Test,ResolveReferenceMissingResourceDoNotCacheFlags)511 TEST_F(AssetManager2Test, ResolveReferenceMissingResourceDoNotCacheFlags) {
512 AssetManager2 assetmanager;
513 assetmanager.SetApkAssets({basic_assets_});
514 {
515 AssetManager2::SelectedValue value{};
516 value.data = basic::R::string::test1;
517 value.type = Res_value::TYPE_REFERENCE;
518 value.flags = ResTable_config::CONFIG_KEYBOARD;
519
520 auto result = assetmanager.ResolveReference(value);
521 ASSERT_TRUE(result.has_value());
522 EXPECT_EQ(Res_value::TYPE_STRING, value.type);
523 EXPECT_EQ(0, value.cookie);
524 EXPECT_EQ(basic::R::string::test1, value.resid);
525 EXPECT_EQ(ResTable_typeSpec::SPEC_PUBLIC | ResTable_config::CONFIG_KEYBOARD, value.flags);
526 }
527 {
528 AssetManager2::SelectedValue value{};
529 value.data = basic::R::string::test1;
530 value.type = Res_value::TYPE_REFERENCE;
531 value.flags = ResTable_config::CONFIG_COLOR_MODE;
532
533 auto result = assetmanager.ResolveReference(value);
534 ASSERT_TRUE(result.has_value());
535 EXPECT_EQ(Res_value::TYPE_STRING, value.type);
536 EXPECT_EQ(0, value.cookie);
537 EXPECT_EQ(basic::R::string::test1, value.resid);
538 EXPECT_EQ(ResTable_typeSpec::SPEC_PUBLIC | ResTable_config::CONFIG_COLOR_MODE, value.flags);
539 }
540 }
541
TEST_F(AssetManager2Test,ResolveReferenceMissingResource)542 TEST_F(AssetManager2Test, ResolveReferenceMissingResource) {
543 AssetManager2 assetmanager;
544 assetmanager.SetApkAssets({basic_assets_});
545
546 const uint32_t kMissingResId = 0x8001ffff;
547 AssetManager2::SelectedValue value{};
548 value.type = Res_value::TYPE_REFERENCE;
549 value.data = kMissingResId;
550
551 auto result = assetmanager.ResolveReference(value);
552 ASSERT_FALSE(result.has_value());
553 EXPECT_EQ(Res_value::TYPE_REFERENCE, value.type);
554 EXPECT_EQ(kMissingResId, value.data);
555 EXPECT_EQ(kMissingResId, value.resid);
556 EXPECT_EQ(-1, value.cookie);
557 EXPECT_EQ(0, value.flags);
558 }
559
TEST_F(AssetManager2Test,ResolveReferenceMissingResourceLib)560 TEST_F(AssetManager2Test, ResolveReferenceMissingResourceLib) {
561 AssetManager2 assetmanager;
562 assetmanager.SetApkAssets({libclient_assets_});
563
564 AssetManager2::SelectedValue value{};
565 value.type = Res_value::TYPE_REFERENCE;
566 value.data = libclient::R::string::foo_one;
567
568 auto result = assetmanager.ResolveReference(value);
569 ASSERT_TRUE(result.has_value());
570 EXPECT_EQ(Res_value::TYPE_DYNAMIC_REFERENCE, value.type);
571 EXPECT_EQ(lib_one::R::string::foo, value.data);
572 EXPECT_EQ(libclient::R::string::foo_one, value.resid);
573 EXPECT_EQ(0, value.cookie);
574 EXPECT_EQ(static_cast<uint32_t>(ResTable_typeSpec::SPEC_PUBLIC), value.flags);
575 }
576
IsConfigurationPresent(const std::set<ResTable_config> & configurations,const ResTable_config & configuration)577 static bool IsConfigurationPresent(const std::set<ResTable_config>& configurations,
578 const ResTable_config& configuration) {
579 return configurations.count(configuration) > 0;
580 }
581
TEST_F(AssetManager2Test,GetResourceConfigurations)582 TEST_F(AssetManager2Test, GetResourceConfigurations) {
583 AssetManager2 assetmanager;
584 assetmanager.SetApkAssets({system_assets_, basic_de_fr_assets_});
585
586 auto configurations = assetmanager.GetResourceConfigurations();
587 ASSERT_TRUE(configurations.has_value());
588
589 // We expect the locale sv from the system assets, and de and fr from basic_de_fr assets.
590 // And one extra for the default configuration.
591 EXPECT_EQ(4u, configurations->size());
592
593 ResTable_config expected_config;
594 memset(&expected_config, 0, sizeof(expected_config));
595 expected_config.language[0] = 's';
596 expected_config.language[1] = 'v';
597 EXPECT_TRUE(IsConfigurationPresent(*configurations, expected_config));
598
599 expected_config.language[0] = 'd';
600 expected_config.language[1] = 'e';
601 EXPECT_TRUE(IsConfigurationPresent(*configurations, expected_config));
602
603 expected_config.language[0] = 'f';
604 expected_config.language[1] = 'r';
605 EXPECT_TRUE(IsConfigurationPresent(*configurations, expected_config));
606
607 // Take out the system assets.
608 configurations = assetmanager.GetResourceConfigurations(true /* exclude_system */);
609 ASSERT_TRUE(configurations.has_value());
610
611 // We expect de and fr from basic_de_fr assets.
612 EXPECT_EQ(2u, configurations->size());
613
614 expected_config.language[0] = 's';
615 expected_config.language[1] = 'v';
616 EXPECT_FALSE(IsConfigurationPresent(*configurations, expected_config));
617
618 expected_config.language[0] = 'd';
619 expected_config.language[1] = 'e';
620 EXPECT_TRUE(IsConfigurationPresent(*configurations, expected_config));
621
622 expected_config.language[0] = 'f';
623 expected_config.language[1] = 'r';
624 EXPECT_TRUE(IsConfigurationPresent(*configurations, expected_config));
625 }
626
TEST_F(AssetManager2Test,GetResourceLocales)627 TEST_F(AssetManager2Test, GetResourceLocales) {
628 AssetManager2 assetmanager;
629 assetmanager.SetApkAssets({system_assets_, basic_de_fr_assets_});
630
631 auto locales = assetmanager.GetResourceLocales();
632
633 // We expect the locale sv from the system assets, and de and fr from basic_de_fr assets.
634 EXPECT_EQ(3u, locales.size());
635 EXPECT_GT(locales.count("sv"), 0u);
636 EXPECT_GT(locales.count("de"), 0u);
637 EXPECT_GT(locales.count("fr"), 0u);
638
639 locales = assetmanager.GetResourceLocales(true /*exclude_system*/);
640 // We expect the de and fr locales from basic_de_fr assets.
641 EXPECT_EQ(2u, locales.size());
642 EXPECT_GT(locales.count("de"), 0u);
643 EXPECT_GT(locales.count("fr"), 0u);
644 }
645
TEST_F(AssetManager2Test,GetResourceId)646 TEST_F(AssetManager2Test, GetResourceId) {
647 AssetManager2 assetmanager;
648 assetmanager.SetApkAssets({basic_assets_});
649
650 auto resid = assetmanager.GetResourceId("com.android.basic:layout/main", "", "");
651 ASSERT_TRUE(resid.has_value());
652 EXPECT_EQ(basic::R::layout::main, *resid);
653
654 resid = assetmanager.GetResourceId("layout/main", "", "com.android.basic");
655 ASSERT_TRUE(resid.has_value());
656 EXPECT_EQ(basic::R::layout::main, *resid);
657
658 resid = assetmanager.GetResourceId("main", "layout", "com.android.basic");
659 ASSERT_TRUE(resid.has_value());
660 EXPECT_EQ(basic::R::layout::main, *resid);
661 }
662
TEST_F(AssetManager2Test,OpensFileFromSingleApkAssets)663 TEST_F(AssetManager2Test, OpensFileFromSingleApkAssets) {
664 AssetManager2 assetmanager;
665 assetmanager.SetApkAssets({system_assets_});
666
667 std::unique_ptr<Asset> asset = assetmanager.Open("file.txt", Asset::ACCESS_BUFFER);
668 ASSERT_THAT(asset, NotNull());
669
670 const char* data = reinterpret_cast<const char*>(asset->getBuffer(false /*wordAligned*/));
671 ASSERT_THAT(data, NotNull());
672 EXPECT_THAT(std::string(data, asset->getLength()), StrEq("file\n"));
673 }
674
TEST_F(AssetManager2Test,OpensFileFromMultipleApkAssets)675 TEST_F(AssetManager2Test, OpensFileFromMultipleApkAssets) {
676 AssetManager2 assetmanager;
677 assetmanager.SetApkAssets({system_assets_, app_assets_});
678
679 std::unique_ptr<Asset> asset = assetmanager.Open("file.txt", Asset::ACCESS_BUFFER);
680 ASSERT_THAT(asset, NotNull());
681
682 const char* data = reinterpret_cast<const char*>(asset->getBuffer(false /*wordAligned*/));
683 ASSERT_THAT(data, NotNull());
684 EXPECT_THAT(std::string(data, asset->getLength()), StrEq("app override file\n"));
685 }
686
TEST_F(AssetManager2Test,OpenDir)687 TEST_F(AssetManager2Test, OpenDir) {
688 AssetManager2 assetmanager;
689 assetmanager.SetApkAssets({system_assets_});
690
691 std::unique_ptr<AssetDir> asset_dir = assetmanager.OpenDir("");
692 ASSERT_THAT(asset_dir, NotNull());
693 ASSERT_THAT(asset_dir->getFileCount(), Eq(2u));
694
695 EXPECT_THAT(asset_dir->getFileName(0), Eq(String8("file.txt")));
696 EXPECT_THAT(asset_dir->getFileType(0), Eq(FileType::kFileTypeRegular));
697
698 EXPECT_THAT(asset_dir->getFileName(1), Eq(String8("subdir")));
699 EXPECT_THAT(asset_dir->getFileType(1), Eq(FileType::kFileTypeDirectory));
700
701 asset_dir = assetmanager.OpenDir("subdir");
702 ASSERT_THAT(asset_dir, NotNull());
703 ASSERT_THAT(asset_dir->getFileCount(), Eq(1u));
704
705 EXPECT_THAT(asset_dir->getFileName(0), Eq(String8("subdir_file.txt")));
706 EXPECT_THAT(asset_dir->getFileType(0), Eq(FileType::kFileTypeRegular));
707 }
708
TEST_F(AssetManager2Test,OpenDirFromManyApks)709 TEST_F(AssetManager2Test, OpenDirFromManyApks) {
710 AssetManager2 assetmanager;
711 assetmanager.SetApkAssets({system_assets_, app_assets_});
712
713 std::unique_ptr<AssetDir> asset_dir = assetmanager.OpenDir("");
714 ASSERT_THAT(asset_dir, NotNull());
715 ASSERT_THAT(asset_dir->getFileCount(), Eq(3u));
716
717 EXPECT_THAT(asset_dir->getFileName(0), Eq(String8("app_file.txt")));
718 EXPECT_THAT(asset_dir->getFileType(0), Eq(FileType::kFileTypeRegular));
719
720 EXPECT_THAT(asset_dir->getFileName(1), Eq(String8("file.txt")));
721 EXPECT_THAT(asset_dir->getFileType(1), Eq(FileType::kFileTypeRegular));
722
723 EXPECT_THAT(asset_dir->getFileName(2), Eq(String8("subdir")));
724 EXPECT_THAT(asset_dir->getFileType(2), Eq(FileType::kFileTypeDirectory));
725 }
726
TEST_F(AssetManager2Test,GetLastPathWithoutEnablingReturnsEmpty)727 TEST_F(AssetManager2Test, GetLastPathWithoutEnablingReturnsEmpty) {
728 ResTable_config desired_config;
729
730 AssetManager2 assetmanager;
731 assetmanager.SetConfigurations({{desired_config}});
732 assetmanager.SetApkAssets({basic_assets_});
733 assetmanager.SetResourceResolutionLoggingEnabled(false);
734
735 auto value = assetmanager.GetResource(basic::R::string::test1);
736 ASSERT_TRUE(value.has_value());
737
738 auto result = assetmanager.GetLastResourceResolution();
739 EXPECT_EQ("", result);
740 }
741
TEST_F(AssetManager2Test,GetLastPathWithoutResolutionReturnsEmpty)742 TEST_F(AssetManager2Test, GetLastPathWithoutResolutionReturnsEmpty) {
743 ResTable_config desired_config;
744
745 AssetManager2 assetmanager;
746 assetmanager.SetConfigurations({{desired_config}});
747 assetmanager.SetApkAssets({basic_assets_});
748
749 auto result = assetmanager.GetLastResourceResolution();
750 EXPECT_EQ("", result);
751 }
752
TEST_F(AssetManager2Test,GetLastPathWithSingleApkAssets)753 TEST_F(AssetManager2Test, GetLastPathWithSingleApkAssets) {
754 ResTable_config desired_config;
755 memset(&desired_config, 0, sizeof(desired_config));
756 desired_config.language[0] = 'd';
757 desired_config.language[1] = 'e';
758
759 AssetManager2 assetmanager;
760 assetmanager.SetResourceResolutionLoggingEnabled(true);
761 assetmanager.SetConfigurations({{desired_config}});
762 assetmanager.SetApkAssets({basic_assets_});
763
764 auto value = assetmanager.GetResource(basic::R::string::test1);
765 ASSERT_TRUE(value.has_value());
766
767 auto result = assetmanager.GetLastResourceResolution();
768 EXPECT_EQ(
769 "Resolution for 0x7f030000 com.android.basic:string/test1\n"
770 "\tFor config - de\n"
771 "\tFound initial: basic/basic.apk #0\n"
772 "Best matching is from default configuration of com.android.basic",
773 result);
774 }
775
TEST_F(AssetManager2Test,GetLastPathWithMultipleApkAssets)776 TEST_F(AssetManager2Test, GetLastPathWithMultipleApkAssets) {
777 ResTable_config desired_config;
778 memset(&desired_config, 0, sizeof(desired_config));
779 desired_config.language[0] = 'd';
780 desired_config.language[1] = 'e';
781
782 AssetManager2 assetmanager;
783 assetmanager.SetResourceResolutionLoggingEnabled(true);
784 assetmanager.SetConfigurations({{desired_config}});
785 assetmanager.SetApkAssets({basic_assets_, basic_de_fr_assets_});
786
787 auto value = assetmanager.GetResource(basic::R::string::test1);
788 ASSERT_TRUE(value.has_value());
789
790 auto result = assetmanager.GetLastResourceResolution();
791 EXPECT_EQ(
792 "Resolution for 0x7f030000 com.android.basic:string/test1\n"
793 "\tFor config - de\n"
794 "\tFound initial: basic/basic.apk #0\n"
795 "\tFound better: basic/basic_de_fr.apk #1 - de\n"
796 "Best matching is from de configuration of com.android.basic",
797 result);
798 }
799
TEST_F(AssetManager2Test,GetLastPathAfterDisablingReturnsEmpty)800 TEST_F(AssetManager2Test, GetLastPathAfterDisablingReturnsEmpty) {
801 ResTable_config desired_config;
802 memset(&desired_config, 0, sizeof(desired_config));
803
804 AssetManager2 assetmanager;
805 assetmanager.SetResourceResolutionLoggingEnabled(true);
806 assetmanager.SetConfigurations({{desired_config}});
807 assetmanager.SetApkAssets({basic_assets_});
808
809 auto value = assetmanager.GetResource(basic::R::string::test1);
810 ASSERT_TRUE(value.has_value());
811
812 auto resultEnabled = assetmanager.GetLastResourceResolution();
813 ASSERT_NE("", resultEnabled);
814
815 assetmanager.SetResourceResolutionLoggingEnabled(false);
816
817 auto resultDisabled = assetmanager.GetLastResourceResolution();
818 EXPECT_EQ("", resultDisabled);
819 }
820
TEST_F(AssetManager2Test,GetOverlayablesToString)821 TEST_F(AssetManager2Test, GetOverlayablesToString) {
822 ResTable_config desired_config;
823 memset(&desired_config, 0, sizeof(desired_config));
824
825 AssetManager2 assetmanager;
826 assetmanager.SetResourceResolutionLoggingEnabled(true);
827 assetmanager.SetConfigurations({{desired_config}});
828 assetmanager.SetApkAssets({overlayable_assets_});
829
830 const auto map = assetmanager.GetOverlayableMapForPackage(0x7f);
831 ASSERT_NE(nullptr, map);
832 ASSERT_EQ(3, map->size());
833 ASSERT_EQ(map->at("OverlayableResources1"), "overlay://theme");
834 ASSERT_EQ(map->at("OverlayableResources2"), "overlay://com.android.overlayable");
835 ASSERT_EQ(map->at("OverlayableResources3"), "");
836
837 std::string api;
838 ASSERT_TRUE(assetmanager.GetOverlayablesToString("com.android.overlayable", &api));
839 ASSERT_EQ(api.find("not_overlayable"), std::string::npos);
840 ASSERT_NE(api.find("resource='com.android.overlayable:string/overlayable2' overlayable='OverlayableResources1' actor='overlay://theme' policy='0x0000000a'\n"),
841 std::string::npos);
842 }
843
TEST_F(AssetManager2Test,GetApkAssets)844 TEST_F(AssetManager2Test, GetApkAssets) {
845 AssetManager2 assetmanager;
846 assetmanager.SetApkAssets({overlayable_assets_, overlay_assets_, lib_one_assets_});
847
848 ASSERT_EQ(3, assetmanager.GetApkAssetsCount());
849 EXPECT_EQ(1, overlayable_assets_->getStrongCount());
850 EXPECT_EQ(1, overlay_assets_->getStrongCount());
851 EXPECT_EQ(1, lib_one_assets_->getStrongCount());
852
853 {
854 auto op = assetmanager.StartOperation();
855 ASSERT_EQ(overlayable_assets_, assetmanager.GetApkAssets(0));
856 ASSERT_EQ(overlay_assets_, assetmanager.GetApkAssets(1));
857 EXPECT_EQ(2, overlayable_assets_->getStrongCount());
858 EXPECT_EQ(2, overlay_assets_->getStrongCount());
859 EXPECT_EQ(1, lib_one_assets_->getStrongCount());
860 }
861 EXPECT_EQ(1, overlayable_assets_->getStrongCount());
862 EXPECT_EQ(1, overlay_assets_->getStrongCount());
863 EXPECT_EQ(1, lib_one_assets_->getStrongCount());
864 }
865
TEST_F(AssetManager2Test,GetFlaggedAssets)866 TEST_F(AssetManager2Test, GetFlaggedAssets) {
867 AssetManager2 assetmanager;
868 assetmanager.SetApkAssets({flagged_assets_});
869 auto value = assetmanager.GetResource(flagged::R::xml::flagged, false, 0);
870 ASSERT_TRUE(value.has_value());
871 EXPECT_TRUE(value->entry_flags & ResTable_entry::FLAG_USES_FEATURE_FLAGS);
872 }
873
874 } // namespace android
875