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