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: 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 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 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 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 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 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 226 TEST_F(AssetManager2Test, FindsBagResourceFromMultipleApkAssets) {} 227 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 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 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 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 351 static bool IsConfigurationPresent(const std::set<ResTable_config>& configurations, 352 const ResTable_config& configuration) { 353 return configurations.count(configuration) > 0; 354 } 355 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 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 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 430 TEST_F(AssetManager2Test, OpensFileFromSingleApkAssets) {} 431 432 TEST_F(AssetManager2Test, OpensFileFromMultipleApkAssets) {} 433 434 } // namespace android 435