Loading libs/androidfw/AssetManager2.cpp +38 −30 Original line number Diff line number Diff line Loading @@ -1319,7 +1319,7 @@ void Theme::SetTo(const Theme& o) { typedef std::map<int, int> SourceToDestinationRuntimePackageMap; std::map<ApkAssetsCookie, SourceToDestinationRuntimePackageMap> src_asset_cookie_id_map; // Determine which ApkAssets are loaded in both theme AssetManagers // Determine which ApkAssets are loaded in both theme AssetManagers. std::vector<const ApkAssets*> src_assets = o.asset_manager_->GetApkAssets(); for (size_t i = 0; i < src_assets.size(); i++) { const ApkAssets* src_asset = src_assets[i]; Loading @@ -1328,7 +1328,7 @@ void Theme::SetTo(const Theme& o) { for (size_t j = 0; j < dest_assets.size(); j++) { const ApkAssets* dest_asset = dest_assets[j]; // Map the runtime package of the source apk asset to the destination apk asset // Map the runtime package of the source apk asset to the destination apk asset. if (src_asset->GetPath() == dest_asset->GetPath()) { const std::vector<std::unique_ptr<const LoadedPackage>>& src_packages = src_asset->GetLoadedArsc()->GetPackages(); Loading @@ -1353,15 +1353,14 @@ void Theme::SetTo(const Theme& o) { package_map[src_package_id] = dest_package_id; } src_to_dest_asset_cookies.insert(std::pair<ApkAssetsCookie, ApkAssetsCookie>(i, j)); src_asset_cookie_id_map.insert( std::pair<ApkAssetsCookie, SourceToDestinationRuntimePackageMap>(i, package_map)); src_to_dest_asset_cookies.insert(std::make_pair(i, j)); src_asset_cookie_id_map.insert(std::make_pair(i, package_map)); break; } } } // Reset the data in the destination theme // Reset the data in the destination theme. for (size_t p = 0; p < packages_.size(); p++) { if (packages_[p] != nullptr) { packages_[p].reset(); Loading @@ -1387,16 +1386,17 @@ void Theme::SetTo(const Theme& o) { continue; } // If the attribute value represents an attribute or reference, the package id of the // value needs to be rewritten to the package id of the value in the destination uint32_t attribue_data = entry.value.data; if ((entry.value.dataType == Res_value::TYPE_ATTRIBUTE bool is_reference = (entry.value.dataType == Res_value::TYPE_ATTRIBUTE || entry.value.dataType == Res_value::TYPE_REFERENCE || entry.value.dataType == Res_value::TYPE_DYNAMIC_ATTRIBUTE || entry.value.dataType == Res_value::TYPE_DYNAMIC_REFERENCE) && attribue_data != 0x0) { && entry.value.data != 0x0; // Determine the package id of the reference in the destination AssetManager // If the attribute value represents an attribute or reference, the package id of the // value needs to be rewritten to the package id of the value in the destination. uint32_t attribute_data = entry.value.data; if (is_reference) { // Determine the package id of the reference in the destination AssetManager. auto value_package_map = src_asset_cookie_id_map.find(entry.cookie); if (value_package_map == src_asset_cookie_id_map.end()) { continue; Loading @@ -1408,14 +1408,28 @@ void Theme::SetTo(const Theme& o) { continue; } attribue_data = fix_package_id(entry.value.data, value_dest_package->second); attribute_data = fix_package_id(entry.value.data, value_dest_package->second); } // Find the cookie of the value in the destination. If the source apk is not loaded in the // destination, only copy resources that do not reference resources in the source. ApkAssetsCookie data_dest_cookie; auto value_dest_cookie = src_to_dest_asset_cookies.find(entry.cookie); if (value_dest_cookie != src_to_dest_asset_cookies.end()) { data_dest_cookie = value_dest_cookie->second; } else { if (is_reference || entry.value.dataType == Res_value::TYPE_STRING) { continue; } else { data_dest_cookie = 0x0; } } // The package id of the attribute needs to be rewritten to the package id of the // attribute in the destination // attribute in the destination. int attribute_dest_package_id = p; if (attribute_dest_package_id != 0x01) { // Find the cookie of the attribute resource id // Find the cookie of the attribute resource id in the source AssetManager FindEntryResult attribute_entry_result; ApkAssetsCookie attribute_cookie = o.asset_manager_->FindEntry(make_resid(p, t, e), 0 /* density_override */ , Loading @@ -1423,7 +1437,7 @@ void Theme::SetTo(const Theme& o) { true /* ignore_configuration */, &attribute_entry_result); // Determine the package id of the attribute in the destination AssetManager // Determine the package id of the attribute in the destination AssetManager. auto attribute_package_map = src_asset_cookie_id_map.find(attribute_cookie); if (attribute_package_map == src_asset_cookie_id_map.end()) { continue; Loading @@ -1436,13 +1450,13 @@ void Theme::SetTo(const Theme& o) { attribute_dest_package_id = attribute_dest_package->second; } // Lazily instantiate the destination package // Lazily instantiate the destination package. std::unique_ptr<Package>& dest_package = packages_[attribute_dest_package_id]; if (dest_package == nullptr) { dest_package.reset(new Package()); } // Lazily instantiate and resize the destination type // Lazily instantiate and resize the destination type. util::unique_cptr<ThemeType>& dest_type = dest_package->types[t]; if (dest_type == nullptr || dest_type->entry_count < type->entry_count) { const size_t type_alloc_size = sizeof(ThemeType) Loading @@ -1450,7 +1464,7 @@ void Theme::SetTo(const Theme& o) { void* dest_data = malloc(type_alloc_size); memset(dest_data, 0, type->entry_count * sizeof(ThemeEntry)); // Copy the existing destination type values if the type is resized // Copy the existing destination type values if the type is resized. if (dest_type != nullptr) { memcpy(dest_data, type, sizeof(ThemeType) + (dest_type->entry_count * sizeof(ThemeEntry))); Loading @@ -1460,15 +1474,9 @@ void Theme::SetTo(const Theme& o) { dest_type->entry_count = type->entry_count; } // Find the cookie of the value in the destination auto value_dest_cookie = src_to_dest_asset_cookies.find(entry.cookie); if (value_dest_cookie == src_to_dest_asset_cookies.end()) { continue; } dest_type->entries[e].cookie = value_dest_cookie->second; dest_type->entries[e].cookie = data_dest_cookie; dest_type->entries[e].value.dataType = entry.value.dataType; dest_type->entries[e].value.data = attribue_data; dest_type->entries[e].value.data = attribute_data; dest_type->entries[e].type_spec_flags = entry.type_spec_flags; } } Loading libs/androidfw/tests/Theme_test.cpp +53 −20 Original line number Diff line number Diff line Loading @@ -282,48 +282,81 @@ TEST_F(ThemeTest, CopyThemeSameAssetManager) { } TEST_F(ThemeTest, OnlyCopySameAssetsThemeWhenAssetManagersDiffer) { AssetManager2 assetmanager_one; assetmanager_one.SetApkAssets({system_assets_.get(), lib_one_assets_.get(), style_assets_.get(), AssetManager2 assetmanager_dst; assetmanager_dst.SetApkAssets({system_assets_.get(), lib_one_assets_.get(), style_assets_.get(), libclient_assets_.get()}); AssetManager2 assetmanager_two; assetmanager_two.SetApkAssets({system_assets_.get(), lib_two_assets_.get(), lib_one_assets_.get(), AssetManager2 assetmanager_src; assetmanager_src.SetApkAssets({system_assets_.get(), lib_two_assets_.get(), lib_one_assets_.get(), style_assets_.get()}); auto theme_one = assetmanager_one.NewTheme(); ASSERT_TRUE(theme_one->ApplyStyle(app::R::style::StyleOne)); auto theme_dst = assetmanager_dst.NewTheme(); ASSERT_TRUE(theme_dst->ApplyStyle(app::R::style::StyleOne)); auto theme_two = assetmanager_two.NewTheme(); ASSERT_TRUE(theme_two->ApplyStyle(R::style::Theme_One)); ASSERT_TRUE(theme_two->ApplyStyle(app::R::style::StyleTwo)); ASSERT_TRUE(theme_two->ApplyStyle(fix_package_id(lib_one::R::style::Theme, 0x03), auto theme_src = assetmanager_src.NewTheme(); ASSERT_TRUE(theme_src->ApplyStyle(R::style::Theme_One)); ASSERT_TRUE(theme_src->ApplyStyle(app::R::style::StyleTwo)); ASSERT_TRUE(theme_src->ApplyStyle(fix_package_id(lib_one::R::style::Theme, 0x03), false /*force*/)); ASSERT_TRUE(theme_two->ApplyStyle(fix_package_id(lib_two::R::style::Theme, 0x02), ASSERT_TRUE(theme_src->ApplyStyle(fix_package_id(lib_two::R::style::Theme, 0x02), false /*force*/)); theme_one->SetTo(*theme_two); theme_dst->SetTo(*theme_src); Res_value value; uint32_t flags; // System resources (present in destination asset manager) EXPECT_EQ(0, theme_one->GetAttribute(R::attr::foreground, &value, &flags)); // System resources (present in destination asset manager). EXPECT_EQ(0, theme_dst->GetAttribute(R::attr::foreground, &value, &flags)); // The cookie of the style asset is 3 in the source and 2 in the destination. // Check that the cookie has been rewritten to the destination values EXPECT_EQ(2, theme_one->GetAttribute(app::R::attr::attr_one, &value, &flags)); // Check that the cookie has been rewritten to the destination values. EXPECT_EQ(2, theme_dst->GetAttribute(app::R::attr::attr_one, &value, &flags)); // The cookie of the lib_one asset is 2 in the source and 1 in the destination. // The package id of the lib_one package is 0x03 in the source and 0x02 in the destination // Check that the cookie and packages have been rewritten to the destination values EXPECT_EQ(1, theme_one->GetAttribute(fix_package_id(lib_one::R::attr::attr1, 0x02), &value, // Check that the cookie and packages have been rewritten to the destination values. EXPECT_EQ(1, theme_dst->GetAttribute(fix_package_id(lib_one::R::attr::attr1, 0x02), &value, &flags)); EXPECT_EQ(1, theme_one->GetAttribute(fix_package_id(lib_one::R::attr::attr2, 0x02), &value, EXPECT_EQ(1, theme_dst->GetAttribute(fix_package_id(lib_one::R::attr::attr2, 0x02), &value, &flags)); // attr2 references an attribute in lib_one. Check that the resolution of the attribute value is // correct after the value of attr2 had its package id rewritten to the destination package id // correct after the value of attr2 had its package id rewritten to the destination package id. EXPECT_EQ(700, value.data); } TEST_F(ThemeTest, CopyNonReferencesWhenPackagesDiffer) { AssetManager2 assetmanager_dst; assetmanager_dst.SetApkAssets({system_assets_.get()}); AssetManager2 assetmanager_src; assetmanager_src.SetApkAssets({system_assets_.get(), style_assets_.get()}); auto theme_dst = assetmanager_dst.NewTheme(); auto theme_src = assetmanager_src.NewTheme(); ASSERT_TRUE(theme_src->ApplyStyle(app::R::style::StyleSeven)); theme_dst->SetTo(*theme_src); Res_value value; uint32_t flags; // Allow inline resource values to be copied even if the source apk asset is not present in the // destination. EXPECT_EQ(0, theme_dst->GetAttribute(0x0101021b /* android:versionCode */, &value, &flags)); // Do not copy strings since the data is an index into the values string pool of the source apk // asset. EXPECT_EQ(-1, theme_dst->GetAttribute(0x01010001 /* android:label */, &value, &flags)); // Do not copy values that reference another resource if the resource is not present in the // destination. EXPECT_EQ(-1, theme_dst->GetAttribute(0x01010002 /* android:icon */, &value, &flags)); EXPECT_EQ(-1, theme_dst->GetAttribute(0x010100d1 /* android:tag */, &value, &flags)); // Allow @empty to and @null to be copied. EXPECT_EQ(0, theme_dst->GetAttribute(0x010100d0 /* android:id */, &value, &flags)); EXPECT_EQ(0, theme_dst->GetAttribute(0x01010000 /* android:theme */, &value, &flags)); } } // namespace android libs/androidfw/tests/data/styles/R.h +1 −0 Original line number Diff line number Diff line Loading @@ -51,6 +51,7 @@ struct R { StyleFour = 0x7f020003u, StyleFive = 0x7f020004u, StyleSix = 0x7f020005u, StyleSeven = 0x7f020006u, }; }; }; Loading libs/androidfw/tests/data/styles/build +3 −1 Original line number Diff line number Diff line Loading @@ -2,5 +2,7 @@ set -e PATH_TO_FRAMEWORK_RES=${ANDROID_BUILD_TOP}/prebuilts/sdk/current/public/android.jar aapt2 compile -o compiled.flata --dir res aapt2 link -o styles.apk --manifest AndroidManifest.xml compiled.flata aapt2 link -o styles.apk --manifest AndroidManifest.xml -I $PATH_TO_FRAMEWORK_RES compiled.flata libs/androidfw/tests/data/styles/res/values/styles.xml +10 −0 Original line number Diff line number Diff line Loading @@ -79,4 +79,14 @@ <item name="attr_three">3</item> </style> <public type="style" name="StyleSeven" id="0x7f020006" /> <style name="StyleSeven" > <item name="android:versionCode">3</item> <item name="android:label">"string"</item> <item name="android:icon">?attr/attr_one</item> <item name="android:tag">@string/string_one</item> <item name="android:id">@null</item> <item name="android:theme">@empty</item> </style> </resources> Loading
libs/androidfw/AssetManager2.cpp +38 −30 Original line number Diff line number Diff line Loading @@ -1319,7 +1319,7 @@ void Theme::SetTo(const Theme& o) { typedef std::map<int, int> SourceToDestinationRuntimePackageMap; std::map<ApkAssetsCookie, SourceToDestinationRuntimePackageMap> src_asset_cookie_id_map; // Determine which ApkAssets are loaded in both theme AssetManagers // Determine which ApkAssets are loaded in both theme AssetManagers. std::vector<const ApkAssets*> src_assets = o.asset_manager_->GetApkAssets(); for (size_t i = 0; i < src_assets.size(); i++) { const ApkAssets* src_asset = src_assets[i]; Loading @@ -1328,7 +1328,7 @@ void Theme::SetTo(const Theme& o) { for (size_t j = 0; j < dest_assets.size(); j++) { const ApkAssets* dest_asset = dest_assets[j]; // Map the runtime package of the source apk asset to the destination apk asset // Map the runtime package of the source apk asset to the destination apk asset. if (src_asset->GetPath() == dest_asset->GetPath()) { const std::vector<std::unique_ptr<const LoadedPackage>>& src_packages = src_asset->GetLoadedArsc()->GetPackages(); Loading @@ -1353,15 +1353,14 @@ void Theme::SetTo(const Theme& o) { package_map[src_package_id] = dest_package_id; } src_to_dest_asset_cookies.insert(std::pair<ApkAssetsCookie, ApkAssetsCookie>(i, j)); src_asset_cookie_id_map.insert( std::pair<ApkAssetsCookie, SourceToDestinationRuntimePackageMap>(i, package_map)); src_to_dest_asset_cookies.insert(std::make_pair(i, j)); src_asset_cookie_id_map.insert(std::make_pair(i, package_map)); break; } } } // Reset the data in the destination theme // Reset the data in the destination theme. for (size_t p = 0; p < packages_.size(); p++) { if (packages_[p] != nullptr) { packages_[p].reset(); Loading @@ -1387,16 +1386,17 @@ void Theme::SetTo(const Theme& o) { continue; } // If the attribute value represents an attribute or reference, the package id of the // value needs to be rewritten to the package id of the value in the destination uint32_t attribue_data = entry.value.data; if ((entry.value.dataType == Res_value::TYPE_ATTRIBUTE bool is_reference = (entry.value.dataType == Res_value::TYPE_ATTRIBUTE || entry.value.dataType == Res_value::TYPE_REFERENCE || entry.value.dataType == Res_value::TYPE_DYNAMIC_ATTRIBUTE || entry.value.dataType == Res_value::TYPE_DYNAMIC_REFERENCE) && attribue_data != 0x0) { && entry.value.data != 0x0; // Determine the package id of the reference in the destination AssetManager // If the attribute value represents an attribute or reference, the package id of the // value needs to be rewritten to the package id of the value in the destination. uint32_t attribute_data = entry.value.data; if (is_reference) { // Determine the package id of the reference in the destination AssetManager. auto value_package_map = src_asset_cookie_id_map.find(entry.cookie); if (value_package_map == src_asset_cookie_id_map.end()) { continue; Loading @@ -1408,14 +1408,28 @@ void Theme::SetTo(const Theme& o) { continue; } attribue_data = fix_package_id(entry.value.data, value_dest_package->second); attribute_data = fix_package_id(entry.value.data, value_dest_package->second); } // Find the cookie of the value in the destination. If the source apk is not loaded in the // destination, only copy resources that do not reference resources in the source. ApkAssetsCookie data_dest_cookie; auto value_dest_cookie = src_to_dest_asset_cookies.find(entry.cookie); if (value_dest_cookie != src_to_dest_asset_cookies.end()) { data_dest_cookie = value_dest_cookie->second; } else { if (is_reference || entry.value.dataType == Res_value::TYPE_STRING) { continue; } else { data_dest_cookie = 0x0; } } // The package id of the attribute needs to be rewritten to the package id of the // attribute in the destination // attribute in the destination. int attribute_dest_package_id = p; if (attribute_dest_package_id != 0x01) { // Find the cookie of the attribute resource id // Find the cookie of the attribute resource id in the source AssetManager FindEntryResult attribute_entry_result; ApkAssetsCookie attribute_cookie = o.asset_manager_->FindEntry(make_resid(p, t, e), 0 /* density_override */ , Loading @@ -1423,7 +1437,7 @@ void Theme::SetTo(const Theme& o) { true /* ignore_configuration */, &attribute_entry_result); // Determine the package id of the attribute in the destination AssetManager // Determine the package id of the attribute in the destination AssetManager. auto attribute_package_map = src_asset_cookie_id_map.find(attribute_cookie); if (attribute_package_map == src_asset_cookie_id_map.end()) { continue; Loading @@ -1436,13 +1450,13 @@ void Theme::SetTo(const Theme& o) { attribute_dest_package_id = attribute_dest_package->second; } // Lazily instantiate the destination package // Lazily instantiate the destination package. std::unique_ptr<Package>& dest_package = packages_[attribute_dest_package_id]; if (dest_package == nullptr) { dest_package.reset(new Package()); } // Lazily instantiate and resize the destination type // Lazily instantiate and resize the destination type. util::unique_cptr<ThemeType>& dest_type = dest_package->types[t]; if (dest_type == nullptr || dest_type->entry_count < type->entry_count) { const size_t type_alloc_size = sizeof(ThemeType) Loading @@ -1450,7 +1464,7 @@ void Theme::SetTo(const Theme& o) { void* dest_data = malloc(type_alloc_size); memset(dest_data, 0, type->entry_count * sizeof(ThemeEntry)); // Copy the existing destination type values if the type is resized // Copy the existing destination type values if the type is resized. if (dest_type != nullptr) { memcpy(dest_data, type, sizeof(ThemeType) + (dest_type->entry_count * sizeof(ThemeEntry))); Loading @@ -1460,15 +1474,9 @@ void Theme::SetTo(const Theme& o) { dest_type->entry_count = type->entry_count; } // Find the cookie of the value in the destination auto value_dest_cookie = src_to_dest_asset_cookies.find(entry.cookie); if (value_dest_cookie == src_to_dest_asset_cookies.end()) { continue; } dest_type->entries[e].cookie = value_dest_cookie->second; dest_type->entries[e].cookie = data_dest_cookie; dest_type->entries[e].value.dataType = entry.value.dataType; dest_type->entries[e].value.data = attribue_data; dest_type->entries[e].value.data = attribute_data; dest_type->entries[e].type_spec_flags = entry.type_spec_flags; } } Loading
libs/androidfw/tests/Theme_test.cpp +53 −20 Original line number Diff line number Diff line Loading @@ -282,48 +282,81 @@ TEST_F(ThemeTest, CopyThemeSameAssetManager) { } TEST_F(ThemeTest, OnlyCopySameAssetsThemeWhenAssetManagersDiffer) { AssetManager2 assetmanager_one; assetmanager_one.SetApkAssets({system_assets_.get(), lib_one_assets_.get(), style_assets_.get(), AssetManager2 assetmanager_dst; assetmanager_dst.SetApkAssets({system_assets_.get(), lib_one_assets_.get(), style_assets_.get(), libclient_assets_.get()}); AssetManager2 assetmanager_two; assetmanager_two.SetApkAssets({system_assets_.get(), lib_two_assets_.get(), lib_one_assets_.get(), AssetManager2 assetmanager_src; assetmanager_src.SetApkAssets({system_assets_.get(), lib_two_assets_.get(), lib_one_assets_.get(), style_assets_.get()}); auto theme_one = assetmanager_one.NewTheme(); ASSERT_TRUE(theme_one->ApplyStyle(app::R::style::StyleOne)); auto theme_dst = assetmanager_dst.NewTheme(); ASSERT_TRUE(theme_dst->ApplyStyle(app::R::style::StyleOne)); auto theme_two = assetmanager_two.NewTheme(); ASSERT_TRUE(theme_two->ApplyStyle(R::style::Theme_One)); ASSERT_TRUE(theme_two->ApplyStyle(app::R::style::StyleTwo)); ASSERT_TRUE(theme_two->ApplyStyle(fix_package_id(lib_one::R::style::Theme, 0x03), auto theme_src = assetmanager_src.NewTheme(); ASSERT_TRUE(theme_src->ApplyStyle(R::style::Theme_One)); ASSERT_TRUE(theme_src->ApplyStyle(app::R::style::StyleTwo)); ASSERT_TRUE(theme_src->ApplyStyle(fix_package_id(lib_one::R::style::Theme, 0x03), false /*force*/)); ASSERT_TRUE(theme_two->ApplyStyle(fix_package_id(lib_two::R::style::Theme, 0x02), ASSERT_TRUE(theme_src->ApplyStyle(fix_package_id(lib_two::R::style::Theme, 0x02), false /*force*/)); theme_one->SetTo(*theme_two); theme_dst->SetTo(*theme_src); Res_value value; uint32_t flags; // System resources (present in destination asset manager) EXPECT_EQ(0, theme_one->GetAttribute(R::attr::foreground, &value, &flags)); // System resources (present in destination asset manager). EXPECT_EQ(0, theme_dst->GetAttribute(R::attr::foreground, &value, &flags)); // The cookie of the style asset is 3 in the source and 2 in the destination. // Check that the cookie has been rewritten to the destination values EXPECT_EQ(2, theme_one->GetAttribute(app::R::attr::attr_one, &value, &flags)); // Check that the cookie has been rewritten to the destination values. EXPECT_EQ(2, theme_dst->GetAttribute(app::R::attr::attr_one, &value, &flags)); // The cookie of the lib_one asset is 2 in the source and 1 in the destination. // The package id of the lib_one package is 0x03 in the source and 0x02 in the destination // Check that the cookie and packages have been rewritten to the destination values EXPECT_EQ(1, theme_one->GetAttribute(fix_package_id(lib_one::R::attr::attr1, 0x02), &value, // Check that the cookie and packages have been rewritten to the destination values. EXPECT_EQ(1, theme_dst->GetAttribute(fix_package_id(lib_one::R::attr::attr1, 0x02), &value, &flags)); EXPECT_EQ(1, theme_one->GetAttribute(fix_package_id(lib_one::R::attr::attr2, 0x02), &value, EXPECT_EQ(1, theme_dst->GetAttribute(fix_package_id(lib_one::R::attr::attr2, 0x02), &value, &flags)); // attr2 references an attribute in lib_one. Check that the resolution of the attribute value is // correct after the value of attr2 had its package id rewritten to the destination package id // correct after the value of attr2 had its package id rewritten to the destination package id. EXPECT_EQ(700, value.data); } TEST_F(ThemeTest, CopyNonReferencesWhenPackagesDiffer) { AssetManager2 assetmanager_dst; assetmanager_dst.SetApkAssets({system_assets_.get()}); AssetManager2 assetmanager_src; assetmanager_src.SetApkAssets({system_assets_.get(), style_assets_.get()}); auto theme_dst = assetmanager_dst.NewTheme(); auto theme_src = assetmanager_src.NewTheme(); ASSERT_TRUE(theme_src->ApplyStyle(app::R::style::StyleSeven)); theme_dst->SetTo(*theme_src); Res_value value; uint32_t flags; // Allow inline resource values to be copied even if the source apk asset is not present in the // destination. EXPECT_EQ(0, theme_dst->GetAttribute(0x0101021b /* android:versionCode */, &value, &flags)); // Do not copy strings since the data is an index into the values string pool of the source apk // asset. EXPECT_EQ(-1, theme_dst->GetAttribute(0x01010001 /* android:label */, &value, &flags)); // Do not copy values that reference another resource if the resource is not present in the // destination. EXPECT_EQ(-1, theme_dst->GetAttribute(0x01010002 /* android:icon */, &value, &flags)); EXPECT_EQ(-1, theme_dst->GetAttribute(0x010100d1 /* android:tag */, &value, &flags)); // Allow @empty to and @null to be copied. EXPECT_EQ(0, theme_dst->GetAttribute(0x010100d0 /* android:id */, &value, &flags)); EXPECT_EQ(0, theme_dst->GetAttribute(0x01010000 /* android:theme */, &value, &flags)); } } // namespace android
libs/androidfw/tests/data/styles/R.h +1 −0 Original line number Diff line number Diff line Loading @@ -51,6 +51,7 @@ struct R { StyleFour = 0x7f020003u, StyleFive = 0x7f020004u, StyleSix = 0x7f020005u, StyleSeven = 0x7f020006u, }; }; }; Loading
libs/androidfw/tests/data/styles/build +3 −1 Original line number Diff line number Diff line Loading @@ -2,5 +2,7 @@ set -e PATH_TO_FRAMEWORK_RES=${ANDROID_BUILD_TOP}/prebuilts/sdk/current/public/android.jar aapt2 compile -o compiled.flata --dir res aapt2 link -o styles.apk --manifest AndroidManifest.xml compiled.flata aapt2 link -o styles.apk --manifest AndroidManifest.xml -I $PATH_TO_FRAMEWORK_RES compiled.flata
libs/androidfw/tests/data/styles/res/values/styles.xml +10 −0 Original line number Diff line number Diff line Loading @@ -79,4 +79,14 @@ <item name="attr_three">3</item> </style> <public type="style" name="StyleSeven" id="0x7f020006" /> <style name="StyleSeven" > <item name="android:versionCode">3</item> <item name="android:label">"string"</item> <item name="android:icon">?attr/attr_one</item> <item name="android:tag">@string/string_one</item> <item name="android:id">@null</item> <item name="android:theme">@empty</item> </style> </resources>