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/AttributeResolution.h" 18 19 #include <array> 20 21 #include "android-base/file.h" 22 #include "android-base/logging.h" 23 #include "android-base/macros.h" 24 #include "androidfw/AssetManager2.h" 25 #include "androidfw/ResourceUtils.h" 26 27 #include "TestHelpers.h" 28 #include "data/styles/R.h" 29 30 using com::android::app::R; 31 32 namespace android { 33 34 class AttributeResolutionTest : public ::testing::Test { 35 public: 36 virtual void SetUp() override { 37 styles_assets_ = ApkAssets::Load(GetTestDataPath() + "/styles/styles.apk"); 38 ASSERT_NE(nullptr, styles_assets_); 39 assetmanager_.SetApkAssets({styles_assets_.get()}); 40 } 41 42 protected: 43 std::unique_ptr<const ApkAssets> styles_assets_; 44 AssetManager2 assetmanager_; 45 }; 46 47 class AttributeResolutionXmlTest : public AttributeResolutionTest { 48 public: 49 virtual void SetUp() override { 50 AttributeResolutionTest::SetUp(); 51 52 std::unique_ptr<Asset> asset = 53 assetmanager_.OpenNonAsset("res/layout/layout.xml", Asset::ACCESS_BUFFER); 54 ASSERT_NE(nullptr, asset); 55 56 ASSERT_EQ(NO_ERROR, 57 xml_parser_.setTo(asset->getBuffer(true), asset->getLength(), true /*copyData*/)); 58 59 // Skip to the first tag. 60 while (xml_parser_.next() != ResXMLParser::START_TAG) { 61 } 62 } 63 64 protected: 65 ResXMLTree xml_parser_; 66 }; 67 68 TEST(AttributeResolutionLibraryTest, ApplyStyleWithDefaultStyleResId) { 69 AssetManager2 assetmanager; 70 auto apk_assets = ApkAssets::LoadAsSharedLibrary(GetTestDataPath() + "/styles/styles.apk"); 71 ASSERT_NE(nullptr, apk_assets); 72 assetmanager.SetApkAssets({apk_assets.get()}); 73 74 std::unique_ptr<Theme> theme = assetmanager.NewTheme(); 75 76 std::array<uint32_t, 2> attrs{ 77 {fix_package_id(R::attr::attr_one, 0x02), fix_package_id(R::attr::attr_two, 0x02)}}; 78 std::array<uint32_t, attrs.size() * STYLE_NUM_ENTRIES> values; 79 std::array<uint32_t, attrs.size() + 1> indices; 80 ApplyStyle(theme.get(), nullptr /*xml_parser*/, 0u /*def_style_attr*/, 81 fix_package_id(R::style::StyleOne, 0x02), attrs.data(), attrs.size(), values.data(), 82 indices.data()); 83 84 const uint32_t public_flag = ResTable_typeSpec::SPEC_PUBLIC; 85 86 const uint32_t* values_cursor = values.data(); 87 EXPECT_EQ(Res_value::TYPE_INT_DEC, values_cursor[STYLE_TYPE]); 88 EXPECT_EQ(1u, values_cursor[STYLE_DATA]); 89 EXPECT_EQ(0u, values_cursor[STYLE_RESOURCE_ID]); 90 EXPECT_EQ(1u, values_cursor[STYLE_ASSET_COOKIE]); 91 EXPECT_EQ(0u, values_cursor[STYLE_DENSITY]); 92 EXPECT_EQ(public_flag, values_cursor[STYLE_CHANGING_CONFIGURATIONS]); 93 94 values_cursor += STYLE_NUM_ENTRIES; 95 EXPECT_EQ(Res_value::TYPE_INT_DEC, values_cursor[STYLE_TYPE]); 96 EXPECT_EQ(2u, values_cursor[STYLE_DATA]); 97 EXPECT_EQ(0u, values_cursor[STYLE_RESOURCE_ID]); 98 EXPECT_EQ(1u, values_cursor[STYLE_ASSET_COOKIE]); 99 EXPECT_EQ(0u, values_cursor[STYLE_DENSITY]); 100 EXPECT_EQ(public_flag, values_cursor[STYLE_CHANGING_CONFIGURATIONS]); 101 } 102 103 TEST_F(AttributeResolutionTest, Theme) { 104 std::unique_ptr<Theme> theme = assetmanager_.NewTheme(); 105 ASSERT_TRUE(theme->ApplyStyle(R::style::StyleTwo)); 106 107 std::array<uint32_t, 5> attrs{{R::attr::attr_one, R::attr::attr_two, R::attr::attr_three, 108 R::attr::attr_four, R::attr::attr_empty}}; 109 std::array<uint32_t, attrs.size() * STYLE_NUM_ENTRIES> values; 110 111 ASSERT_TRUE(ResolveAttrs(theme.get(), 0u /*def_style_attr*/, 0u /*def_style_res*/, 112 nullptr /*src_values*/, 0 /*src_values_length*/, attrs.data(), 113 attrs.size(), values.data(), nullptr /*out_indices*/)); 114 115 const uint32_t public_flag = ResTable_typeSpec::SPEC_PUBLIC; 116 117 const uint32_t* values_cursor = values.data(); 118 EXPECT_EQ(Res_value::TYPE_INT_DEC, values_cursor[STYLE_TYPE]); 119 EXPECT_EQ(1u, values_cursor[STYLE_DATA]); 120 EXPECT_EQ(0u, values_cursor[STYLE_RESOURCE_ID]); 121 EXPECT_EQ(1u, values_cursor[STYLE_ASSET_COOKIE]); 122 EXPECT_EQ(0u, values_cursor[STYLE_DENSITY]); 123 EXPECT_EQ(public_flag, values_cursor[STYLE_CHANGING_CONFIGURATIONS]); 124 125 values_cursor += STYLE_NUM_ENTRIES; 126 EXPECT_EQ(Res_value::TYPE_STRING, values_cursor[STYLE_TYPE]); 127 EXPECT_EQ(0u, values_cursor[STYLE_RESOURCE_ID]); 128 EXPECT_EQ(1u, values_cursor[STYLE_ASSET_COOKIE]); 129 EXPECT_EQ(0u, values_cursor[STYLE_DENSITY]); 130 EXPECT_EQ(public_flag, values_cursor[STYLE_CHANGING_CONFIGURATIONS]); 131 132 values_cursor += STYLE_NUM_ENTRIES; 133 EXPECT_EQ(Res_value::TYPE_INT_DEC, values_cursor[STYLE_TYPE]); 134 EXPECT_EQ(3u, values_cursor[STYLE_DATA]); 135 EXPECT_EQ(0u, values_cursor[STYLE_RESOURCE_ID]); 136 EXPECT_EQ(1u, values_cursor[STYLE_ASSET_COOKIE]); 137 EXPECT_EQ(0u, values_cursor[STYLE_DENSITY]); 138 EXPECT_EQ(public_flag, values_cursor[STYLE_CHANGING_CONFIGURATIONS]); 139 140 values_cursor += STYLE_NUM_ENTRIES; 141 EXPECT_EQ(Res_value::TYPE_NULL, values_cursor[STYLE_TYPE]); 142 EXPECT_EQ(Res_value::DATA_NULL_UNDEFINED, values_cursor[STYLE_DATA]); 143 EXPECT_EQ(0u, values_cursor[STYLE_RESOURCE_ID]); 144 EXPECT_EQ(uint32_t(-1), values_cursor[STYLE_ASSET_COOKIE]); 145 EXPECT_EQ(0u, values_cursor[STYLE_DENSITY]); 146 EXPECT_EQ(0u, values_cursor[STYLE_CHANGING_CONFIGURATIONS]); 147 148 // @empty comes from the theme, so it has the same asset cookie and changing configurations flags 149 // as the theme. 150 values_cursor += STYLE_NUM_ENTRIES; 151 EXPECT_EQ(Res_value::TYPE_NULL, values_cursor[STYLE_TYPE]); 152 EXPECT_EQ(Res_value::DATA_NULL_EMPTY, values_cursor[STYLE_DATA]); 153 EXPECT_EQ(0u, values_cursor[STYLE_RESOURCE_ID]); 154 EXPECT_EQ(1u, values_cursor[STYLE_ASSET_COOKIE]); 155 EXPECT_EQ(0u, values_cursor[STYLE_DENSITY]); 156 EXPECT_EQ(public_flag, values_cursor[STYLE_CHANGING_CONFIGURATIONS]); 157 } 158 159 TEST_F(AttributeResolutionXmlTest, XmlParser) { 160 std::array<uint32_t, 5> attrs{{R::attr::attr_one, R::attr::attr_two, R::attr::attr_three, 161 R::attr::attr_four, R::attr::attr_empty}}; 162 std::array<uint32_t, attrs.size() * STYLE_NUM_ENTRIES> values; 163 164 ASSERT_TRUE(RetrieveAttributes(&assetmanager_, &xml_parser_, attrs.data(), attrs.size(), 165 values.data(), nullptr /*out_indices*/)); 166 167 uint32_t* values_cursor = values.data(); 168 EXPECT_EQ(Res_value::TYPE_NULL, values_cursor[STYLE_TYPE]); 169 EXPECT_EQ(Res_value::DATA_NULL_EMPTY, values_cursor[STYLE_DATA]); 170 EXPECT_EQ(0u, values_cursor[STYLE_RESOURCE_ID]); 171 EXPECT_EQ(uint32_t(-1), values_cursor[STYLE_ASSET_COOKIE]); 172 EXPECT_EQ(0u, values_cursor[STYLE_DENSITY]); 173 EXPECT_EQ(0u, values_cursor[STYLE_CHANGING_CONFIGURATIONS]); 174 175 values_cursor += STYLE_NUM_ENTRIES; 176 EXPECT_EQ(Res_value::TYPE_NULL, values_cursor[STYLE_TYPE]); 177 EXPECT_EQ(0u, values_cursor[STYLE_DATA]); 178 EXPECT_EQ(0u, values_cursor[STYLE_RESOURCE_ID]); 179 EXPECT_EQ(uint32_t(-1), values_cursor[STYLE_ASSET_COOKIE]); 180 EXPECT_EQ(0u, values_cursor[STYLE_DENSITY]); 181 EXPECT_EQ(0u, values_cursor[STYLE_CHANGING_CONFIGURATIONS]); 182 183 values_cursor += STYLE_NUM_ENTRIES; 184 EXPECT_EQ(Res_value::TYPE_INT_DEC, values_cursor[STYLE_TYPE]); 185 EXPECT_EQ(10u, values_cursor[STYLE_DATA]); 186 EXPECT_EQ(0u, values_cursor[STYLE_RESOURCE_ID]); 187 EXPECT_EQ(uint32_t(-1), values_cursor[STYLE_ASSET_COOKIE]); 188 EXPECT_EQ(0u, values_cursor[STYLE_DENSITY]); 189 EXPECT_EQ(0u, values_cursor[STYLE_CHANGING_CONFIGURATIONS]); 190 191 values_cursor += STYLE_NUM_ENTRIES; 192 EXPECT_EQ(Res_value::TYPE_ATTRIBUTE, values_cursor[STYLE_TYPE]); 193 EXPECT_EQ(R::attr::attr_indirect, values_cursor[STYLE_DATA]); 194 EXPECT_EQ(0u, values_cursor[STYLE_RESOURCE_ID]); 195 EXPECT_EQ(uint32_t(-1), values_cursor[STYLE_ASSET_COOKIE]); 196 EXPECT_EQ(0u, values_cursor[STYLE_DENSITY]); 197 EXPECT_EQ(0u, values_cursor[STYLE_CHANGING_CONFIGURATIONS]); 198 199 values_cursor += STYLE_NUM_ENTRIES; 200 EXPECT_EQ(Res_value::TYPE_NULL, values_cursor[STYLE_TYPE]); 201 EXPECT_EQ(Res_value::DATA_NULL_UNDEFINED, values_cursor[STYLE_DATA]); 202 EXPECT_EQ(0u, values_cursor[STYLE_RESOURCE_ID]); 203 EXPECT_EQ(uint32_t(-1), values_cursor[STYLE_ASSET_COOKIE]); 204 EXPECT_EQ(0u, values_cursor[STYLE_DENSITY]); 205 EXPECT_EQ(0u, values_cursor[STYLE_CHANGING_CONFIGURATIONS]); 206 } 207 208 TEST_F(AttributeResolutionXmlTest, ThemeAndXmlParser) { 209 std::unique_ptr<Theme> theme = assetmanager_.NewTheme(); 210 ASSERT_TRUE(theme->ApplyStyle(R::style::StyleTwo)); 211 212 std::array<uint32_t, 6> attrs{{R::attr::attr_one, R::attr::attr_two, R::attr::attr_three, 213 R::attr::attr_four, R::attr::attr_five, R::attr::attr_empty}}; 214 std::array<uint32_t, attrs.size() * STYLE_NUM_ENTRIES> values; 215 std::array<uint32_t, attrs.size() + 1> indices; 216 217 ApplyStyle(theme.get(), &xml_parser_, 0u /*def_style_attr*/, 0u /*def_style_res*/, attrs.data(), 218 attrs.size(), values.data(), indices.data()); 219 220 const uint32_t public_flag = ResTable_typeSpec::SPEC_PUBLIC; 221 222 uint32_t* values_cursor = values.data(); 223 EXPECT_EQ(Res_value::TYPE_NULL, values_cursor[STYLE_TYPE]); 224 EXPECT_EQ(Res_value::DATA_NULL_EMPTY, values_cursor[STYLE_DATA]); 225 EXPECT_EQ(0u, values_cursor[STYLE_RESOURCE_ID]); 226 EXPECT_EQ(uint32_t(-1), values_cursor[STYLE_ASSET_COOKIE]); 227 EXPECT_EQ(0u, values_cursor[STYLE_DENSITY]); 228 EXPECT_EQ(0u, values_cursor[STYLE_CHANGING_CONFIGURATIONS]); 229 230 values_cursor += STYLE_NUM_ENTRIES; 231 EXPECT_EQ(Res_value::TYPE_STRING, values_cursor[STYLE_TYPE]); 232 EXPECT_EQ(0u, values_cursor[STYLE_RESOURCE_ID]); 233 EXPECT_EQ(1u, values_cursor[STYLE_ASSET_COOKIE]); 234 EXPECT_EQ(0u, values_cursor[STYLE_DENSITY]); 235 EXPECT_EQ(public_flag, values_cursor[STYLE_CHANGING_CONFIGURATIONS]); 236 237 values_cursor += STYLE_NUM_ENTRIES; 238 EXPECT_EQ(Res_value::TYPE_INT_DEC, values_cursor[STYLE_TYPE]); 239 EXPECT_EQ(10u, values_cursor[STYLE_DATA]); 240 EXPECT_EQ(0u, values_cursor[STYLE_RESOURCE_ID]); 241 EXPECT_EQ(uint32_t(-1), values_cursor[STYLE_ASSET_COOKIE]); 242 EXPECT_EQ(0u, values_cursor[STYLE_DENSITY]); 243 EXPECT_EQ(0u, values_cursor[STYLE_CHANGING_CONFIGURATIONS]); 244 245 values_cursor += STYLE_NUM_ENTRIES; 246 EXPECT_EQ(Res_value::TYPE_INT_DEC, values_cursor[STYLE_TYPE]); 247 EXPECT_EQ(3u, values_cursor[STYLE_DATA]); 248 EXPECT_EQ(0u, values_cursor[STYLE_RESOURCE_ID]); 249 EXPECT_EQ(1u, values_cursor[STYLE_ASSET_COOKIE]); 250 EXPECT_EQ(0u, values_cursor[STYLE_DENSITY]); 251 EXPECT_EQ(public_flag, values_cursor[STYLE_CHANGING_CONFIGURATIONS]); 252 253 values_cursor += STYLE_NUM_ENTRIES; 254 EXPECT_EQ(Res_value::TYPE_STRING, values_cursor[STYLE_TYPE]); 255 EXPECT_EQ(R::string::string_one, values_cursor[STYLE_RESOURCE_ID]); 256 EXPECT_EQ(1u, values_cursor[STYLE_ASSET_COOKIE]); 257 EXPECT_EQ(0u, values_cursor[STYLE_DENSITY]); 258 EXPECT_EQ(public_flag, values_cursor[STYLE_CHANGING_CONFIGURATIONS]); 259 260 // @empty comes from the theme, so it has the same asset cookie and changing configurations flags 261 // as the theme. 262 values_cursor += STYLE_NUM_ENTRIES; 263 EXPECT_EQ(Res_value::TYPE_NULL, values_cursor[STYLE_TYPE]); 264 EXPECT_EQ(Res_value::DATA_NULL_EMPTY, values_cursor[STYLE_DATA]); 265 EXPECT_EQ(0u, values_cursor[STYLE_RESOURCE_ID]); 266 EXPECT_EQ(1u, values_cursor[STYLE_ASSET_COOKIE]); 267 EXPECT_EQ(0u, values_cursor[STYLE_DENSITY]); 268 EXPECT_EQ(public_flag, values_cursor[STYLE_CHANGING_CONFIGURATIONS]); 269 270 // The first element of indices contains the number of indices. 271 std::array<uint32_t, 7> expected_indices = {{6u, 0u, 1u, 2u, 3u, 4u, 5u}}; 272 EXPECT_EQ(expected_indices, indices); 273 } 274 275 } // namespace android 276 277