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