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 19#include "android-base/logging.h" 20 21#include "TestHelpers.h" 22#include "androidfw/ResourceUtils.h" 23#include "data/lib_one/R.h" 24#include "data/libclient/R.h" 25#include "data/styles/R.h" 26 27namespace app = com::android::app; 28namespace lib_one = com::android::lib_one; 29namespace libclient = com::android::libclient; 30 31namespace android { 32 33class ThemeTest : public ::testing::Test { 34 public: 35 void SetUp() override { 36 style_assets_ = ApkAssets::Load(GetTestDataPath() + "/styles/styles.apk"); 37 ASSERT_NE(nullptr, style_assets_); 38 39 libclient_assets_ = ApkAssets::Load(GetTestDataPath() + "/libclient/libclient.apk"); 40 ASSERT_NE(nullptr, libclient_assets_); 41 42 lib_one_assets_ = ApkAssets::Load(GetTestDataPath() + "/lib_one/lib_one.apk"); 43 ASSERT_NE(nullptr, lib_one_assets_); 44 45 lib_two_assets_ = ApkAssets::Load(GetTestDataPath() + "/lib_two/lib_two.apk"); 46 ASSERT_NE(nullptr, lib_two_assets_); 47 } 48 49 protected: 50 std::unique_ptr<const ApkAssets> style_assets_; 51 std::unique_ptr<const ApkAssets> libclient_assets_; 52 std::unique_ptr<const ApkAssets> lib_one_assets_; 53 std::unique_ptr<const ApkAssets> lib_two_assets_; 54}; 55 56TEST_F(ThemeTest, EmptyTheme) { 57 AssetManager2 assetmanager; 58 assetmanager.SetApkAssets({style_assets_.get()}); 59 60 std::unique_ptr<Theme> theme = assetmanager.NewTheme(); 61 EXPECT_EQ(0u, theme->GetChangingConfigurations()); 62 EXPECT_EQ(&assetmanager, theme->GetAssetManager()); 63 64 Res_value value; 65 uint32_t flags; 66 EXPECT_EQ(kInvalidCookie, theme->GetAttribute(app::R::attr::attr_one, &value, &flags)); 67} 68 69TEST_F(ThemeTest, SingleThemeNoParent) { 70 AssetManager2 assetmanager; 71 assetmanager.SetApkAssets({style_assets_.get()}); 72 73 std::unique_ptr<Theme> theme = assetmanager.NewTheme(); 74 ASSERT_TRUE(theme->ApplyStyle(app::R::style::StyleOne)); 75 76 Res_value value; 77 uint32_t flags; 78 ApkAssetsCookie cookie; 79 80 cookie = theme->GetAttribute(app::R::attr::attr_one, &value, &flags); 81 ASSERT_NE(kInvalidCookie, cookie); 82 EXPECT_EQ(Res_value::TYPE_INT_DEC, value.dataType); 83 EXPECT_EQ(1u, value.data); 84 EXPECT_EQ(static_cast<uint32_t>(ResTable_typeSpec::SPEC_PUBLIC), flags); 85 86 cookie = theme->GetAttribute(app::R::attr::attr_two, &value, &flags); 87 ASSERT_NE(kInvalidCookie, cookie); 88 EXPECT_EQ(Res_value::TYPE_INT_DEC, value.dataType); 89 EXPECT_EQ(2u, value.data); 90 EXPECT_EQ(static_cast<uint32_t>(ResTable_typeSpec::SPEC_PUBLIC), flags); 91} 92 93TEST_F(ThemeTest, SingleThemeWithParent) { 94 AssetManager2 assetmanager; 95 assetmanager.SetApkAssets({style_assets_.get()}); 96 97 std::unique_ptr<Theme> theme = assetmanager.NewTheme(); 98 ASSERT_TRUE(theme->ApplyStyle(app::R::style::StyleTwo)); 99 100 Res_value value; 101 uint32_t flags; 102 ApkAssetsCookie cookie; 103 104 cookie = theme->GetAttribute(app::R::attr::attr_one, &value, &flags); 105 ASSERT_NE(kInvalidCookie, cookie); 106 EXPECT_EQ(Res_value::TYPE_INT_DEC, value.dataType); 107 EXPECT_EQ(1u, value.data); 108 EXPECT_EQ(static_cast<uint32_t>(ResTable_typeSpec::SPEC_PUBLIC), flags); 109 110 cookie = theme->GetAttribute(app::R::attr::attr_two, &value, &flags); 111 ASSERT_NE(kInvalidCookie, cookie); 112 EXPECT_EQ(Res_value::TYPE_STRING, value.dataType); 113 EXPECT_EQ(0, cookie); 114 EXPECT_EQ(std::string("string"), 115 GetStringFromPool(assetmanager.GetStringPoolForCookie(0), value.data)); 116 EXPECT_EQ(static_cast<uint32_t>(ResTable_typeSpec::SPEC_PUBLIC), flags); 117 118 // This attribute should point to an attr_indirect, so the result should be 3. 119 cookie = theme->GetAttribute(app::R::attr::attr_three, &value, &flags); 120 ASSERT_NE(kInvalidCookie, cookie); 121 EXPECT_EQ(Res_value::TYPE_INT_DEC, value.dataType); 122 EXPECT_EQ(3u, value.data); 123 EXPECT_EQ(static_cast<uint32_t>(ResTable_typeSpec::SPEC_PUBLIC), flags); 124} 125 126TEST_F(ThemeTest, MultipleThemesOverlaidNotForce) { 127 AssetManager2 assetmanager; 128 assetmanager.SetApkAssets({style_assets_.get()}); 129 130 std::unique_ptr<Theme> theme = assetmanager.NewTheme(); 131 ASSERT_TRUE(theme->ApplyStyle(app::R::style::StyleTwo)); 132 ASSERT_TRUE(theme->ApplyStyle(app::R::style::StyleThree)); 133 134 Res_value value; 135 uint32_t flags; 136 ApkAssetsCookie cookie; 137 138 // attr_one is still here from the base. 139 cookie = theme->GetAttribute(app::R::attr::attr_one, &value, &flags); 140 ASSERT_NE(kInvalidCookie, cookie); 141 EXPECT_EQ(Res_value::TYPE_INT_DEC, value.dataType); 142 EXPECT_EQ(1u, value.data); 143 EXPECT_EQ(static_cast<uint32_t>(ResTable_typeSpec::SPEC_PUBLIC), flags); 144 145 // check for the new attr_six 146 cookie = theme->GetAttribute(app::R::attr::attr_six, &value, &flags); 147 ASSERT_NE(kInvalidCookie, cookie); 148 EXPECT_EQ(Res_value::TYPE_INT_DEC, value.dataType); 149 EXPECT_EQ(6u, value.data); 150 EXPECT_EQ(static_cast<uint32_t>(ResTable_typeSpec::SPEC_PUBLIC), flags); 151 152 // check for the old attr_five (force=true was not used). 153 cookie = theme->GetAttribute(app::R::attr::attr_five, &value, &flags); 154 ASSERT_NE(kInvalidCookie, cookie); 155 EXPECT_EQ(Res_value::TYPE_REFERENCE, value.dataType); 156 EXPECT_EQ(app::R::string::string_one, value.data); 157 EXPECT_EQ(static_cast<uint32_t>(ResTable_typeSpec::SPEC_PUBLIC), flags); 158} 159 160TEST_F(ThemeTest, MultipleThemesOverlaidForced) { 161 AssetManager2 assetmanager; 162 assetmanager.SetApkAssets({style_assets_.get()}); 163 164 std::unique_ptr<Theme> theme = assetmanager.NewTheme(); 165 ASSERT_TRUE(theme->ApplyStyle(app::R::style::StyleTwo)); 166 ASSERT_TRUE(theme->ApplyStyle(app::R::style::StyleThree, true /* force */)); 167 168 Res_value value; 169 uint32_t flags; 170 ApkAssetsCookie cookie; 171 172 // attr_one is still here from the base. 173 cookie = theme->GetAttribute(app::R::attr::attr_one, &value, &flags); 174 ASSERT_NE(kInvalidCookie, cookie); 175 EXPECT_EQ(Res_value::TYPE_INT_DEC, value.dataType); 176 EXPECT_EQ(1u, value.data); 177 EXPECT_EQ(static_cast<uint32_t>(ResTable_typeSpec::SPEC_PUBLIC), flags); 178 179 // check for the new attr_six 180 cookie = theme->GetAttribute(app::R::attr::attr_six, &value, &flags); 181 ASSERT_NE(kInvalidCookie, cookie); 182 EXPECT_EQ(Res_value::TYPE_INT_DEC, value.dataType); 183 EXPECT_EQ(6u, value.data); 184 EXPECT_EQ(static_cast<uint32_t>(ResTable_typeSpec::SPEC_PUBLIC), flags); 185 186 // check for the new attr_five (force=true was used). 187 cookie = theme->GetAttribute(app::R::attr::attr_five, &value, &flags); 188 ASSERT_NE(kInvalidCookie, cookie); 189 EXPECT_EQ(Res_value::TYPE_INT_DEC, value.dataType); 190 EXPECT_EQ(5u, value.data); 191 EXPECT_EQ(static_cast<uint32_t>(ResTable_typeSpec::SPEC_PUBLIC), flags); 192} 193 194TEST_F(ThemeTest, ResolveDynamicAttributesAndReferencesToSharedLibrary) { 195 AssetManager2 assetmanager; 196 assetmanager.SetApkAssets( 197 {lib_two_assets_.get(), lib_one_assets_.get(), libclient_assets_.get()}); 198 199 std::unique_ptr<Theme> theme = assetmanager.NewTheme(); 200 ASSERT_TRUE(theme->ApplyStyle(libclient::R::style::Theme, false /*force*/)); 201 202 Res_value value; 203 uint32_t flags; 204 ApkAssetsCookie cookie; 205 206 // The attribute should be resolved to the final value. 207 cookie = theme->GetAttribute(libclient::R::attr::foo, &value, &flags); 208 ASSERT_NE(kInvalidCookie, cookie); 209 EXPECT_EQ(Res_value::TYPE_INT_DEC, value.dataType); 210 EXPECT_EQ(700u, value.data); 211 EXPECT_EQ(static_cast<uint32_t>(ResTable_typeSpec::SPEC_PUBLIC), flags); 212 213 // The reference should be resolved to a TYPE_REFERENCE. 214 cookie = theme->GetAttribute(libclient::R::attr::bar, &value, &flags); 215 ASSERT_NE(kInvalidCookie, cookie); 216 EXPECT_EQ(Res_value::TYPE_REFERENCE, value.dataType); 217 218 // lib_one is assigned package ID 0x03. 219 EXPECT_EQ(3u, get_package_id(value.data)); 220 EXPECT_EQ(get_type_id(lib_one::R::string::foo), get_type_id(value.data)); 221 EXPECT_EQ(get_entry_id(lib_one::R::string::foo), get_entry_id(value.data)); 222} 223 224TEST_F(ThemeTest, CopyThemeSameAssetManager) { 225 AssetManager2 assetmanager; 226 assetmanager.SetApkAssets({style_assets_.get()}); 227 228 std::unique_ptr<Theme> theme_one = assetmanager.NewTheme(); 229 ASSERT_TRUE(theme_one->ApplyStyle(app::R::style::StyleOne)); 230 231 Res_value value; 232 uint32_t flags; 233 ApkAssetsCookie cookie; 234 235 // attr_one is still here from the base. 236 cookie = theme_one->GetAttribute(app::R::attr::attr_one, &value, &flags); 237 ASSERT_NE(kInvalidCookie, cookie); 238 EXPECT_EQ(Res_value::TYPE_INT_DEC, value.dataType); 239 EXPECT_EQ(1u, value.data); 240 EXPECT_EQ(static_cast<uint32_t>(ResTable_typeSpec::SPEC_PUBLIC), flags); 241 242 // attr_six is not here. 243 EXPECT_EQ(kInvalidCookie, theme_one->GetAttribute(app::R::attr::attr_six, &value, &flags)); 244 245 std::unique_ptr<Theme> theme_two = assetmanager.NewTheme(); 246 ASSERT_TRUE(theme_two->ApplyStyle(app::R::style::StyleThree)); 247 248 // Copy the theme to theme_one. 249 ASSERT_TRUE(theme_one->SetTo(*theme_two)); 250 251 // Clear theme_two to make sure we test that there WAS a copy. 252 theme_two->Clear(); 253 254 // attr_one is now not here. 255 EXPECT_EQ(kInvalidCookie, theme_one->GetAttribute(app::R::attr::attr_one, &value, &flags)); 256 257 // attr_six is now here because it was copied. 258 cookie = theme_one->GetAttribute(app::R::attr::attr_six, &value, &flags); 259 ASSERT_NE(kInvalidCookie, cookie); 260 EXPECT_EQ(Res_value::TYPE_INT_DEC, value.dataType); 261 EXPECT_EQ(6u, value.data); 262 EXPECT_EQ(static_cast<uint32_t>(ResTable_typeSpec::SPEC_PUBLIC), flags); 263} 264 265TEST_F(ThemeTest, FailToCopyThemeWithDifferentAssetManager) { 266 AssetManager2 assetmanager_one; 267 assetmanager_one.SetApkAssets({style_assets_.get()}); 268 269 AssetManager2 assetmanager_two; 270 assetmanager_two.SetApkAssets({style_assets_.get()}); 271 272 auto theme_one = assetmanager_one.NewTheme(); 273 ASSERT_TRUE(theme_one->ApplyStyle(app::R::style::StyleOne)); 274 275 auto theme_two = assetmanager_two.NewTheme(); 276 ASSERT_TRUE(theme_two->ApplyStyle(app::R::style::StyleTwo)); 277 278 EXPECT_FALSE(theme_one->SetTo(*theme_two)); 279} 280 281} // namespace android 282