diff options
author | Steven Laver <lavers@google.com> | 2019-11-05 13:42:59 -0800 |
---|---|---|
committer | Steven Laver <lavers@google.com> | 2019-11-09 01:16:30 +0000 |
commit | 7c6cc72e18cc1df5205fd2bc47664e6cc2534ad2 (patch) | |
tree | fc34e4ad6037cf231cccc3b56ccd13e82917520a /libs/androidfw/tests/Idmap_test.cpp | |
parent | 8f4f93bf3ba75d8e83cb0a8618cb80f226ada5ac (diff) | |
parent | da5e1bd24a9a0ca24e7e49fad9e604409e573376 (diff) |
Merge RP1A.191024.001
Change-Id: I5cda3bba276e99d948b752be87d4599e9f882e0f
Diffstat (limited to 'libs/androidfw/tests/Idmap_test.cpp')
-rw-r--r-- | libs/androidfw/tests/Idmap_test.cpp | 269 |
1 files changed, 193 insertions, 76 deletions
diff --git a/libs/androidfw/tests/Idmap_test.cpp b/libs/androidfw/tests/Idmap_test.cpp index 10b83a75304d..b679672ab34e 100644 --- a/libs/androidfw/tests/Idmap_test.cpp +++ b/libs/androidfw/tests/Idmap_test.cpp @@ -14,114 +14,231 @@ * limitations under the License. */ +#include "android-base/file.h" +#include "androidfw/ApkAssets.h" +#include "androidfw/AssetManager2.h" #include "androidfw/ResourceTypes.h" #include "utils/String16.h" #include "utils/String8.h" #include "TestHelpers.h" -#include "data/basic/R.h" +#include "data/overlay/R.h" +#include "data/overlayable/R.h" +#include "data/system/R.h" -using ::com::android::basic::R; +namespace overlay = com::android::overlay; +namespace overlayable = com::android::overlayable; namespace android { +namespace { + class IdmapTest : public ::testing::Test { protected: void SetUp() override { - std::string contents; - ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/basic/basic.apk", "resources.arsc", - &contents)); - ASSERT_EQ(NO_ERROR, target_table_.add(contents.data(), contents.size(), 0, true)); - - ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/overlay/overlay.apk", - "resources.arsc", &overlay_data_)); - ResTable overlay_table; - ASSERT_EQ(NO_ERROR, overlay_table.add(overlay_data_.data(), overlay_data_.size())); - - char target_name[256] = "com.android.basic"; - ASSERT_EQ(NO_ERROR, overlay_table.createIdmap(target_table_, 0, 0, target_name, target_name, - &data_, &data_size_)); - } + // Move to the test data directory so the idmap can locate the overlay APK. + std::string original_path = base::GetExecutableDirectory(); + chdir(GetTestDataPath().c_str()); + + system_assets_ = ApkAssets::Load("system/system.apk"); + ASSERT_NE(nullptr, system_assets_); - void TearDown() override { - ::free(data_); + overlay_assets_ = ApkAssets::LoadOverlay("overlay/overlay.idmap"); + ASSERT_NE(nullptr, overlay_assets_); + + overlayable_assets_ = ApkAssets::Load("overlayable/overlayable.apk"); + ASSERT_NE(nullptr, overlayable_assets_); + chdir(original_path.c_str()); } - ResTable target_table_; - std::string overlay_data_; - void* data_ = nullptr; - size_t data_size_ = 0; + protected: + std::unique_ptr<const ApkAssets> system_assets_; + std::unique_ptr<const ApkAssets> overlay_assets_; + std::unique_ptr<const ApkAssets> overlayable_assets_; }; -TEST_F(IdmapTest, CanLoadIdmap) { - ASSERT_EQ(NO_ERROR, - target_table_.add(overlay_data_.data(), overlay_data_.size(), data_, data_size_)); +std::string GetStringFromApkAssets(const AssetManager2& asset_manager, const Res_value& value, + ApkAssetsCookie cookie) { + auto assets = asset_manager.GetApkAssets(); + const ResStringPool* string_pool = assets[cookie]->GetLoadedArsc()->GetStringPool(); + return GetStringFromPool(string_pool, value.data); +} + } TEST_F(IdmapTest, OverlayOverridesResourceValue) { + AssetManager2 asset_manager; + asset_manager.SetApkAssets({system_assets_.get(), overlayable_assets_.get(), + overlay_assets_.get()}); Res_value val; - ssize_t block = target_table_.getResource(R::string::test2, &val, false); - ASSERT_GE(block, 0); - ASSERT_EQ(Res_value::TYPE_STRING, val.dataType); - const ResStringPool* pool = target_table_.getTableStringBlock(block); - ASSERT_TRUE(pool != NULL); - ASSERT_LT(val.data, pool->size()); - - size_t str_len; - const char16_t* target_str16 = pool->stringAt(val.data, &str_len); - ASSERT_TRUE(target_str16 != NULL); - ASSERT_EQ(String16("test2"), String16(target_str16, str_len)); - - ASSERT_EQ(NO_ERROR, - target_table_.add(overlay_data_.data(), overlay_data_.size(), data_, data_size_)); - - ssize_t new_block = target_table_.getResource(R::string::test2, &val, false); - ASSERT_GE(new_block, 0); - ASSERT_NE(block, new_block); - ASSERT_EQ(Res_value::TYPE_STRING, val.dataType); - pool = target_table_.getTableStringBlock(new_block); - ASSERT_TRUE(pool != NULL); - ASSERT_LT(val.data, pool->size()); - - target_str16 = pool->stringAt(val.data, &str_len); - ASSERT_TRUE(target_str16 != NULL); - ASSERT_EQ(String16("test2-overlay"), String16(target_str16, str_len)); + ResTable_config config; + uint32_t flags; + ApkAssetsCookie cookie = asset_manager.GetResource(overlayable::R::string::overlayable5, + false /* may_be_bag */, + 0 /* density_override */, &val, &config, + &flags); + ASSERT_EQ(cookie, 2U); + ASSERT_EQ(val.dataType, Res_value::TYPE_STRING); + ASSERT_EQ(GetStringFromApkAssets(asset_manager, val, cookie), "Overlay One"); } -TEST_F(IdmapTest, OverlaidResourceHasSameName) { - ASSERT_EQ(NO_ERROR, - target_table_.add(overlay_data_.data(), overlay_data_.size(), data_, data_size_)); +TEST_F(IdmapTest, OverlayOverridesResourceValueUsingDifferentPackage) { + AssetManager2 asset_manager; + asset_manager.SetApkAssets({system_assets_.get(), overlayable_assets_.get(), + overlay_assets_.get()}); + Res_value val; + ResTable_config config; + uint32_t flags; + ApkAssetsCookie cookie = asset_manager.GetResource(overlayable::R::string::overlayable10, + false /* may_be_bag */, + 0 /* density_override */, &val, &config, + &flags); + ASSERT_EQ(cookie, 0U); + ASSERT_EQ(val.dataType, Res_value::TYPE_STRING); + ASSERT_EQ(GetStringFromApkAssets(asset_manager, val, cookie), "yes"); +} + +TEST_F(IdmapTest, OverlayOverridesResourceValueUsingInternalResource) { + AssetManager2 asset_manager; + asset_manager.SetApkAssets({system_assets_.get(), overlayable_assets_.get(), + overlay_assets_.get()}); + Res_value val; + ResTable_config config; + uint32_t flags; + ApkAssetsCookie cookie = asset_manager.GetResource(overlayable::R::string::overlayable8, + false /* may_be_bag */, + 0 /* density_override */, &val, &config, + &flags); + ASSERT_EQ(cookie, 2U); + ASSERT_EQ(val.dataType, Res_value::TYPE_REFERENCE); + ASSERT_EQ(val.data, (overlay::R::string::internal & 0x00ffffff) | (0x02 << 24)); +} + +TEST_F(IdmapTest, OverlayOverridesResourceValueUsingInlineInteger) { + AssetManager2 asset_manager; + asset_manager.SetApkAssets({system_assets_.get(), overlayable_assets_.get(), + overlay_assets_.get()}); + Res_value val; + ResTable_config config; + uint32_t flags; + ApkAssetsCookie cookie = asset_manager.GetResource(overlayable::R::integer::config_integer, + false /* may_be_bag */, + 0 /* density_override */, &val, &config, + &flags); + ASSERT_EQ(cookie, 2U); + ASSERT_EQ(val.dataType, Res_value::TYPE_INT_DEC); + ASSERT_EQ(val.data, 42); +} + +TEST_F(IdmapTest, OverlayOverridesResourceValueUsingInlineString) { + AssetManager2 asset_manager; + asset_manager.SetApkAssets({system_assets_.get(), overlayable_assets_.get(), + overlay_assets_.get()}); + Res_value val; + ResTable_config config; + uint32_t flags; + + ApkAssetsCookie cookie = asset_manager.GetResource(overlayable::R::string::overlayable11, + false /* may_be_bag */, + 0 /* density_override */, &val, &config, + &flags); + ASSERT_EQ(cookie, 2U); + ASSERT_EQ(val.dataType, Res_value::TYPE_STRING); + ASSERT_EQ(GetStringFromApkAssets(asset_manager, val, cookie), "Hardcoded string"); +} - ResTable::resource_name res_name; - ASSERT_TRUE(target_table_.getResourceName(R::array::integerArray1, true, &res_name)); +TEST_F(IdmapTest, OverlayOverridesResourceValueUsingOverlayingResource) { + AssetManager2 asset_manager; + asset_manager.SetApkAssets({system_assets_.get(), overlayable_assets_.get(), + overlay_assets_.get()}); + Res_value val; + ResTable_config config; + uint32_t flags; + ApkAssetsCookie cookie = asset_manager.GetResource(overlayable::R::string::overlayable9, + false /* may_be_bag */, + 0 /* density_override */, &val, &config, + &flags); + ASSERT_EQ(cookie, 2U); + ASSERT_EQ(val.dataType, Res_value::TYPE_REFERENCE); + ASSERT_EQ(val.data, overlayable::R::string::overlayable7); +} - ASSERT_TRUE(res_name.package != NULL); - ASSERT_TRUE(res_name.type != NULL); - ASSERT_TRUE(res_name.name8 != NULL); +TEST_F(IdmapTest, OverlayOverridesXmlParser) { + AssetManager2 asset_manager; + asset_manager.SetApkAssets({system_assets_.get(), overlayable_assets_.get(), + overlay_assets_.get()}); + Res_value val; + ResTable_config config; + uint32_t flags; + ApkAssetsCookie cookie = asset_manager.GetResource(overlayable::R::layout::hello_view, + false /* may_be_bag */, + 0 /* density_override */, &val, &config, + &flags); + ASSERT_EQ(cookie, 2U); + ASSERT_EQ(val.dataType, Res_value::TYPE_STRING); + ASSERT_EQ(GetStringFromApkAssets(asset_manager, val, cookie), "res/layout/hello_view.xml"); + + auto asset = asset_manager.OpenNonAsset("res/layout/hello_view.xml", cookie, + Asset::ACCESS_RANDOM); + auto dynamic_ref_table = asset_manager.GetDynamicRefTableForCookie(cookie); + auto xml_tree = util::make_unique<ResXMLTree>(std::move(dynamic_ref_table)); + status_t err = xml_tree->setTo(asset->getBuffer(true), asset->getLength(), false); + ASSERT_EQ(err, NO_ERROR); + + while (xml_tree->next() != ResXMLParser::START_TAG) { } + + // The resource id of @id/hello_view should be rewritten to the resource id/hello_view within the + // target. + ASSERT_EQ(xml_tree->getAttributeNameResID(0), 0x010100d0 /* android:attr/id */); + ASSERT_EQ(xml_tree->getAttributeDataType(0), Res_value::TYPE_REFERENCE); + ASSERT_EQ(xml_tree->getAttributeData(0), overlayable::R::id::hello_view); + + // The resource id of @android:string/yes should not be rewritten even though it overlays + // string/overlayable10 in the target. + ASSERT_EQ(xml_tree->getAttributeNameResID(1), 0x0101014f /* android:attr/text */); + ASSERT_EQ(xml_tree->getAttributeDataType(1), Res_value::TYPE_REFERENCE); + ASSERT_EQ(xml_tree->getAttributeData(1), 0x01040013 /* android:string/yes */); + + // The resource id of the attribute within the overlay should be rewritten to the resource id of + // the attribute in the target. + ASSERT_EQ(xml_tree->getAttributeNameResID(2), overlayable::R::attr::max_lines); + ASSERT_EQ(xml_tree->getAttributeDataType(2), Res_value::TYPE_INT_DEC); + ASSERT_EQ(xml_tree->getAttributeData(2), 4); +} - EXPECT_EQ(String16("com.android.basic"), String16(res_name.package, res_name.packageLen)); - EXPECT_EQ(String16("array"), String16(res_name.type, res_name.typeLen)); - EXPECT_EQ(String8("integerArray1"), String8(res_name.name8, res_name.nameLen)); +TEST_F(IdmapTest, OverlaidResourceHasSameName) { + AssetManager2 asset_manager; + asset_manager.SetApkAssets({system_assets_.get(), overlayable_assets_.get(), + overlay_assets_.get()}); + + AssetManager2::ResourceName name; + ASSERT_TRUE(asset_manager.GetResourceName(overlayable::R::string::overlayable9, &name)); + ASSERT_EQ(std::string(name.package), "com.android.overlayable"); + ASSERT_EQ(String16(name.type16), u"string"); + ASSERT_EQ(std::string(name.entry), "overlayable9"); } -constexpr const uint32_t kNonOverlaidResourceId = 0x7fff0000u; +TEST_F(IdmapTest, OverlayLoaderInterop) { + std::string contents; + auto loader_assets = ApkAssets::LoadArsc(GetTestDataPath() + "/loader/resources.arsc", + /* for_loader */ true); -TEST_F(IdmapTest, OverlayDoesNotIncludeNonOverlaidResources) { - // First check that the resource we're trying to not include when overlaid is present when - // the overlay is loaded as a standalone APK. - ResTable table; - ASSERT_EQ(NO_ERROR, table.add(overlay_data_.data(), overlay_data_.size(), 0, true)); + AssetManager2 asset_manager; + asset_manager.SetApkAssets({overlayable_assets_.get(), loader_assets.get(), + overlay_assets_.get()}); Res_value val; - ssize_t block = table.getResource(kNonOverlaidResourceId, &val, false /*mayBeBag*/); - ASSERT_GE(block, 0); - - // Now add the overlay and verify that the unoverlaid resource is gone. - ASSERT_EQ(NO_ERROR, - target_table_.add(overlay_data_.data(), overlay_data_.size(), data_, data_size_)); - block = target_table_.getResource(kNonOverlaidResourceId, &val, false /*mayBeBag*/); - ASSERT_LT(block, 0); + ResTable_config config; + uint32_t flags; + ApkAssetsCookie cookie = asset_manager.GetResource(overlayable::R::string::overlayable11, + false /* may_be_bag */, + 0 /* density_override */, &val, &config, + &flags); + std::cout << asset_manager.GetLastResourceResolution(); + ASSERT_EQ(cookie, 1U); + ASSERT_EQ(val.dataType, Res_value::TYPE_STRING); + ASSERT_EQ(GetStringFromApkAssets(asset_manager, val, cookie), "loader"); } } // namespace |