14452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski/* 24452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski * Copyright (C) 2016 The Android Open Source Project 34452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski * 44452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski * Licensed under the Apache License, Version 2.0 (the "License"); 54452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski * you may not use this file except in compliance with the License. 64452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski * You may obtain a copy of the License at 74452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski * 84452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski * http://www.apache.org/licenses/LICENSE-2.0 94452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski * 104452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski * Unless required by applicable law or agreed to in writing, software 114452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski * distributed under the License is distributed on an "AS IS" BASIS, 124452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 134452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski * See the License for the specific language governing permissions and 144452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski * limitations under the License. 154452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski */ 164452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski 174452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski#include "androidfw/AttributeResolution.h" 184452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski 194452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski#include <cstdint> 204452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski 216f773a0d8717162f81ff21d943baaa539a2d6c7eMark Salyzyn#include <log/log.h> 224c67a475a334e4f65238d439a3339195e03c03beAdam Lesinski 234c67a475a334e4f65238d439a3339195e03c03beAdam Lesinski#include "androidfw/AttributeFinder.h" 244c67a475a334e4f65238d439a3339195e03c03beAdam Lesinski#include "androidfw/ResourceTypes.h" 254c67a475a334e4f65238d439a3339195e03c03beAdam Lesinski 264452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinskiconstexpr bool kDebugStyles = false; 274452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski 284452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinskinamespace android { 294452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski 304c67a475a334e4f65238d439a3339195e03c03beAdam Lesinskiclass XmlAttributeFinder 314c67a475a334e4f65238d439a3339195e03c03beAdam Lesinski : public BackTrackingAttributeFinder<XmlAttributeFinder, size_t> { 327a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski public: 337a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski explicit XmlAttributeFinder(const ResXMLParser* parser) 344c67a475a334e4f65238d439a3339195e03c03beAdam Lesinski : BackTrackingAttributeFinder( 354c67a475a334e4f65238d439a3339195e03c03beAdam Lesinski 0, parser != nullptr ? parser->getAttributeCount() : 0), 367a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski parser_(parser) {} 374452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski 384c67a475a334e4f65238d439a3339195e03c03beAdam Lesinski inline uint32_t GetAttribute(size_t index) const { 394c67a475a334e4f65238d439a3339195e03c03beAdam Lesinski return parser_->getAttributeNameResID(index); 404c67a475a334e4f65238d439a3339195e03c03beAdam Lesinski } 414452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski 427a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski private: 437a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski const ResXMLParser* parser_; 444452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski}; 454452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski 467a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinskiclass BagAttributeFinder 4732e7501a27f0f19bccdf9e91f9b87869c093f695Adam Lesinski : public BackTrackingAttributeFinder<BagAttributeFinder, const ResTable::bag_entry*> { 487a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski public: 494c67a475a334e4f65238d439a3339195e03c03beAdam Lesinski BagAttributeFinder(const ResTable::bag_entry* start, 504c67a475a334e4f65238d439a3339195e03c03beAdam Lesinski const ResTable::bag_entry* end) 517a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski : BackTrackingAttributeFinder(start, end) {} 524452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski 537a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski inline uint32_t GetAttribute(const ResTable::bag_entry* entry) const { 547a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski return entry->map.name.ident; 557a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski } 564452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski}; 574452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski 584c67a475a334e4f65238d439a3339195e03c03beAdam Lesinskibool ResolveAttrs(ResTable::Theme* theme, uint32_t def_style_attr, 594c67a475a334e4f65238d439a3339195e03c03beAdam Lesinski uint32_t def_style_res, uint32_t* src_values, 604c67a475a334e4f65238d439a3339195e03c03beAdam Lesinski size_t src_values_length, uint32_t* attrs, 614c67a475a334e4f65238d439a3339195e03c03beAdam Lesinski size_t attrs_length, uint32_t* out_values, 624c67a475a334e4f65238d439a3339195e03c03beAdam Lesinski uint32_t* out_indices) { 637a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski if (kDebugStyles) { 644c67a475a334e4f65238d439a3339195e03c03beAdam Lesinski ALOGI("APPLY STYLE: theme=0x%p defStyleAttr=0x%x defStyleRes=0x%x", theme, 654c67a475a334e4f65238d439a3339195e03c03beAdam Lesinski def_style_attr, def_style_res); 667a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski } 674452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski 687a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski const ResTable& res = theme->getResTable(); 697a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski ResTable_config config; 707a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski Res_value value; 714452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski 727a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski int indices_idx = 0; 734452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski 747a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski // Load default style from attribute, if specified... 757a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski uint32_t def_style_bag_type_set_flags = 0; 767a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski if (def_style_attr != 0) { 777a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski Res_value value; 7832e7501a27f0f19bccdf9e91f9b87869c093f695Adam Lesinski if (theme->getAttribute(def_style_attr, &value, &def_style_bag_type_set_flags) >= 0) { 797a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski if (value.dataType == Res_value::TYPE_REFERENCE) { 807a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski def_style_res = value.data; 817a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski } 824452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski } 837a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski } 847a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski 857a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski // Now lock down the resource object and start pulling stuff from it. 867a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski res.lock(); 877a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski 887a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski // Retrieve the default style bag, if requested. 894c67a475a334e4f65238d439a3339195e03c03beAdam Lesinski const ResTable::bag_entry* def_style_start = nullptr; 907a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski uint32_t def_style_type_set_flags = 0; 914c67a475a334e4f65238d439a3339195e03c03beAdam Lesinski ssize_t bag_off = def_style_res != 0 924c67a475a334e4f65238d439a3339195e03c03beAdam Lesinski ? res.getBagLocked(def_style_res, &def_style_start, 934c67a475a334e4f65238d439a3339195e03c03beAdam Lesinski &def_style_type_set_flags) 944c67a475a334e4f65238d439a3339195e03c03beAdam Lesinski : -1; 957a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski def_style_type_set_flags |= def_style_bag_type_set_flags; 964c67a475a334e4f65238d439a3339195e03c03beAdam Lesinski const ResTable::bag_entry* const def_style_end = 974c67a475a334e4f65238d439a3339195e03c03beAdam Lesinski def_style_start + (bag_off >= 0 ? bag_off : 0); 987a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski BagAttributeFinder def_style_attr_finder(def_style_start, def_style_end); 997a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski 1007a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski // Now iterate through all of the attributes that the client has requested, 1017a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski // filling in each with whatever data we can find. 1027a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski for (size_t ii = 0; ii < attrs_length; ii++) { 1037a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski const uint32_t cur_ident = attrs[ii]; 1044452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski 1057a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski if (kDebugStyles) { 1067a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski ALOGI("RETRIEVING ATTR 0x%08x...", cur_ident); 1077a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski } 1084452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski 1097a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski ssize_t block = -1; 1107a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski uint32_t type_set_flags = 0; 1114452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski 1127a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski value.dataType = Res_value::TYPE_NULL; 1137a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski value.data = Res_value::DATA_NULL_UNDEFINED; 1147a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski config.density = 0; 1154452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski 1167a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski // Try to find a value for this attribute... we prioritize values 1177a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski // coming from, first XML attributes, then XML style, then default 1187a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski // style, and finally the theme. 1194452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski 1207a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski // Retrieve the current input value if available. 1217a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski if (src_values_length > 0 && src_values[ii] != 0) { 1227a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski value.dataType = Res_value::TYPE_ATTRIBUTE; 1237a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski value.data = src_values[ii]; 1247a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski if (kDebugStyles) { 1254c67a475a334e4f65238d439a3339195e03c03beAdam Lesinski ALOGI("-> From values: type=0x%x, data=0x%08x", value.dataType, 1264c67a475a334e4f65238d439a3339195e03c03beAdam Lesinski value.data); 1277a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski } 12832e7501a27f0f19bccdf9e91f9b87869c093f695Adam Lesinski } else { 12932e7501a27f0f19bccdf9e91f9b87869c093f695Adam Lesinski const ResTable::bag_entry* const def_style_entry = def_style_attr_finder.Find(cur_ident); 1307a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski if (def_style_entry != def_style_end) { 1317a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski block = def_style_entry->stringBlock; 1327a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski type_set_flags = def_style_type_set_flags; 1337a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski value = def_style_entry->map.value; 1347a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski if (kDebugStyles) { 13532e7501a27f0f19bccdf9e91f9b87869c093f695Adam Lesinski ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType, value.data); 1364452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski } 1377a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski } 1387a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski } 1394452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski 1407a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski uint32_t resid = 0; 1417a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski if (value.dataType != Res_value::TYPE_NULL) { 1427a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski // Take care of resolving the found resource to its final value. 14332e7501a27f0f19bccdf9e91f9b87869c093f695Adam Lesinski ssize_t new_block = 14432e7501a27f0f19bccdf9e91f9b87869c093f695Adam Lesinski theme->resolveAttributeReference(&value, block, &resid, &type_set_flags, &config); 1457a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski if (new_block >= 0) block = new_block; 1467a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski if (kDebugStyles) { 14732e7501a27f0f19bccdf9e91f9b87869c093f695Adam Lesinski ALOGI("-> Resolved attr: type=0x%x, data=0x%08x", value.dataType, value.data); 1487a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski } 14932e7501a27f0f19bccdf9e91f9b87869c093f695Adam Lesinski } else if (value.data != Res_value::DATA_NULL_EMPTY) { 1507a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski // If we still don't have a value for this attribute, try to find 1517a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski // it in the theme! 15232e7501a27f0f19bccdf9e91f9b87869c093f695Adam Lesinski ssize_t new_block = theme->getAttribute(cur_ident, &value, &type_set_flags); 1537a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski if (new_block >= 0) { 1544452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski if (kDebugStyles) { 15532e7501a27f0f19bccdf9e91f9b87869c093f695Adam Lesinski ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType, value.data); 1564452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski } 15732e7501a27f0f19bccdf9e91f9b87869c093f695Adam Lesinski new_block = res.resolveReference(&value, new_block, &resid, &type_set_flags, &config); 1587a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski if (new_block >= 0) block = new_block; 1597a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski if (kDebugStyles) { 16032e7501a27f0f19bccdf9e91f9b87869c093f695Adam Lesinski ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.dataType, value.data); 1614452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski } 1627a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski } 1637a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski } 1644452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski 1657a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski // Deal with the special @null value -- it turns back to TYPE_NULL. 1667a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) { 1677a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski if (kDebugStyles) { 1687a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski ALOGI("-> Setting to @null!"); 1697a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski } 1707a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski value.dataType = Res_value::TYPE_NULL; 1717a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski value.data = Res_value::DATA_NULL_UNDEFINED; 1727a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski block = -1; 1734452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski } 1744452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski 1757a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski if (kDebugStyles) { 17632e7501a27f0f19bccdf9e91f9b87869c093f695Adam Lesinski ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x", cur_ident, value.dataType, value.data); 1777a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski } 1784452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski 1797a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski // Write the final value back to Java. 1807a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski out_values[STYLE_TYPE] = value.dataType; 1817a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski out_values[STYLE_DATA] = value.data; 1827a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski out_values[STYLE_ASSET_COOKIE] = 1834c67a475a334e4f65238d439a3339195e03c03beAdam Lesinski block != -1 ? static_cast<uint32_t>(res.getTableCookie(block)) 1844c67a475a334e4f65238d439a3339195e03c03beAdam Lesinski : static_cast<uint32_t>(-1); 1857a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski out_values[STYLE_RESOURCE_ID] = resid; 1867a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski out_values[STYLE_CHANGING_CONFIGURATIONS] = type_set_flags; 1877a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski out_values[STYLE_DENSITY] = config.density; 1887a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski 18932e7501a27f0f19bccdf9e91f9b87869c093f695Adam Lesinski if (out_indices != nullptr && 19032e7501a27f0f19bccdf9e91f9b87869c093f695Adam Lesinski (value.dataType != Res_value::TYPE_NULL || value.data == Res_value::DATA_NULL_EMPTY)) { 1917a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski indices_idx++; 1927a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski out_indices[indices_idx] = ii; 1934452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski } 1947a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski 1957a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski out_values += STYLE_NUM_ENTRIES; 1967a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski } 1977a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski 1987a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski res.unlock(); 1997a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski 2004c67a475a334e4f65238d439a3339195e03c03beAdam Lesinski if (out_indices != nullptr) { 2017a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski out_indices[0] = indices_idx; 2027a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski } 2037a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski return true; 2044452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski} 2054452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski 206f32adf447511d54c2aa0948d3c1ef44d461538acJohn Reckvoid ApplyStyle(ResTable::Theme* theme, ResXMLParser* xml_parser, uint32_t def_style_attr, 207f32adf447511d54c2aa0948d3c1ef44d461538acJohn Reck uint32_t def_style_res, const uint32_t* attrs, size_t attrs_length, 208f32adf447511d54c2aa0948d3c1ef44d461538acJohn Reck uint32_t* out_values, uint32_t* out_indices) { 2097a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski if (kDebugStyles) { 2104c67a475a334e4f65238d439a3339195e03c03beAdam Lesinski ALOGI("APPLY STYLE: theme=0x%p defStyleAttr=0x%x defStyleRes=0x%x xml=0x%p", 2114c67a475a334e4f65238d439a3339195e03c03beAdam Lesinski theme, def_style_attr, def_style_res, xml_parser); 2127a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski } 2134452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski 2147a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski const ResTable& res = theme->getResTable(); 2157a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski ResTable_config config; 2167a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski Res_value value; 2174452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski 2187a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski int indices_idx = 0; 2194452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski 2207a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski // Load default style from attribute, if specified... 2217a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski uint32_t def_style_bag_type_set_flags = 0; 2227a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski if (def_style_attr != 0) { 2237a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski Res_value value; 2244c67a475a334e4f65238d439a3339195e03c03beAdam Lesinski if (theme->getAttribute(def_style_attr, &value, 2254c67a475a334e4f65238d439a3339195e03c03beAdam Lesinski &def_style_bag_type_set_flags) >= 0) { 2267a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski if (value.dataType == Res_value::TYPE_REFERENCE) { 2277a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski def_style_res = value.data; 2287a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski } 2297a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski } 2307a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski } 2317a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski 2327a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski // Retrieve the style class associated with the current XML tag. 2337a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski int style = 0; 2347a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski uint32_t style_bag_type_set_flags = 0; 2354c67a475a334e4f65238d439a3339195e03c03beAdam Lesinski if (xml_parser != nullptr) { 2367a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski ssize_t idx = xml_parser->indexOfStyle(); 2377a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski if (idx >= 0 && xml_parser->getAttributeValue(idx, &value) >= 0) { 2387a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski if (value.dataType == value.TYPE_ATTRIBUTE) { 23932e7501a27f0f19bccdf9e91f9b87869c093f695Adam Lesinski if (theme->getAttribute(value.data, &value, &style_bag_type_set_flags) < 0) { 2407a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski value.dataType = Res_value::TYPE_NULL; 2414452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski } 2427a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski } 2437a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski if (value.dataType == value.TYPE_REFERENCE) { 2447a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski style = value.data; 2457a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski } 2464452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski } 2477a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski } 2487a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski 2497a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski // Now lock down the resource object and start pulling stuff from it. 2507a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski res.lock(); 2517a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski 2527a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski // Retrieve the default style bag, if requested. 2534c67a475a334e4f65238d439a3339195e03c03beAdam Lesinski const ResTable::bag_entry* def_style_attr_start = nullptr; 2547a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski uint32_t def_style_type_set_flags = 0; 2554c67a475a334e4f65238d439a3339195e03c03beAdam Lesinski ssize_t bag_off = def_style_res != 0 2564c67a475a334e4f65238d439a3339195e03c03beAdam Lesinski ? res.getBagLocked(def_style_res, &def_style_attr_start, 2574c67a475a334e4f65238d439a3339195e03c03beAdam Lesinski &def_style_type_set_flags) 2584c67a475a334e4f65238d439a3339195e03c03beAdam Lesinski : -1; 2597a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski def_style_type_set_flags |= def_style_bag_type_set_flags; 2607a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski const ResTable::bag_entry* const def_style_attr_end = 2617a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski def_style_attr_start + (bag_off >= 0 ? bag_off : 0); 2624c67a475a334e4f65238d439a3339195e03c03beAdam Lesinski BagAttributeFinder def_style_attr_finder(def_style_attr_start, 2634c67a475a334e4f65238d439a3339195e03c03beAdam Lesinski def_style_attr_end); 2647a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski 2657a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski // Retrieve the style class bag, if requested. 2664c67a475a334e4f65238d439a3339195e03c03beAdam Lesinski const ResTable::bag_entry* style_attr_start = nullptr; 2677a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski uint32_t style_type_set_flags = 0; 2684c67a475a334e4f65238d439a3339195e03c03beAdam Lesinski bag_off = 2694c67a475a334e4f65238d439a3339195e03c03beAdam Lesinski style != 0 2704c67a475a334e4f65238d439a3339195e03c03beAdam Lesinski ? res.getBagLocked(style, &style_attr_start, &style_type_set_flags) 2714c67a475a334e4f65238d439a3339195e03c03beAdam Lesinski : -1; 2727a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski style_type_set_flags |= style_bag_type_set_flags; 2734c67a475a334e4f65238d439a3339195e03c03beAdam Lesinski const ResTable::bag_entry* const style_attr_end = 2744c67a475a334e4f65238d439a3339195e03c03beAdam Lesinski style_attr_start + (bag_off >= 0 ? bag_off : 0); 2757a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski BagAttributeFinder style_attr_finder(style_attr_start, style_attr_end); 2767a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski 2777a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski // Retrieve the XML attributes, if requested. 2787a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski static const ssize_t kXmlBlock = 0x10000000; 2797a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski XmlAttributeFinder xml_attr_finder(xml_parser); 2804c67a475a334e4f65238d439a3339195e03c03beAdam Lesinski const size_t xml_attr_end = 2814c67a475a334e4f65238d439a3339195e03c03beAdam Lesinski xml_parser != nullptr ? xml_parser->getAttributeCount() : 0; 2827a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski 2837a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski // Now iterate through all of the attributes that the client has requested, 2847a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski // filling in each with whatever data we can find. 2857a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski for (size_t ii = 0; ii < attrs_length; ii++) { 2867a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski const uint32_t cur_ident = attrs[ii]; 2874452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski 2887a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski if (kDebugStyles) { 2897a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski ALOGI("RETRIEVING ATTR 0x%08x...", cur_ident); 2904452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski } 2914452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski 2927a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski ssize_t block = kXmlBlock; 2937a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski uint32_t type_set_flags = 0; 2947a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski 2957a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski value.dataType = Res_value::TYPE_NULL; 2967a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski value.data = Res_value::DATA_NULL_UNDEFINED; 2977a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski config.density = 0; 2987a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski 2997a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski // Try to find a value for this attribute... we prioritize values 3007a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski // coming from, first XML attributes, then XML style, then default 3017a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski // style, and finally the theme. 3027a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski 3037a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski // Walk through the xml attributes looking for the requested attribute. 3047a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski const size_t xml_attr_idx = xml_attr_finder.Find(cur_ident); 3057a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski if (xml_attr_idx != xml_attr_end) { 3067a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski // We found the attribute we were looking for. 3077a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski xml_parser->getAttributeValue(xml_attr_idx, &value); 3087a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski if (kDebugStyles) { 30932e7501a27f0f19bccdf9e91f9b87869c093f695Adam Lesinski ALOGI("-> From XML: type=0x%x, data=0x%08x", value.dataType, value.data); 3107a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski } 3117a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski } 3124452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski 31332e7501a27f0f19bccdf9e91f9b87869c093f695Adam Lesinski if (value.dataType == Res_value::TYPE_NULL && value.data != Res_value::DATA_NULL_EMPTY) { 31432e7501a27f0f19bccdf9e91f9b87869c093f695Adam Lesinski // Walk through the style class values looking for the requested attribute. 31532e7501a27f0f19bccdf9e91f9b87869c093f695Adam Lesinski const ResTable::bag_entry* const style_attr_entry = style_attr_finder.Find(cur_ident); 3167a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski if (style_attr_entry != style_attr_end) { 3177a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski // We found the attribute we were looking for. 3187a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski block = style_attr_entry->stringBlock; 3197a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski type_set_flags = style_type_set_flags; 3207a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski value = style_attr_entry->map.value; 3214452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski if (kDebugStyles) { 32232e7501a27f0f19bccdf9e91f9b87869c093f695Adam Lesinski ALOGI("-> From style: type=0x%x, data=0x%08x", value.dataType, value.data); 3234452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski } 3247a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski } 3257a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski } 3264452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski 32732e7501a27f0f19bccdf9e91f9b87869c093f695Adam Lesinski if (value.dataType == Res_value::TYPE_NULL && value.data != Res_value::DATA_NULL_EMPTY) { 32832e7501a27f0f19bccdf9e91f9b87869c093f695Adam Lesinski // Walk through the default style values looking for the requested attribute. 32932e7501a27f0f19bccdf9e91f9b87869c093f695Adam Lesinski const ResTable::bag_entry* const def_style_attr_entry = def_style_attr_finder.Find(cur_ident); 3307a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski if (def_style_attr_entry != def_style_attr_end) { 3317a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski // We found the attribute we were looking for. 3327a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski block = def_style_attr_entry->stringBlock; 3337a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski type_set_flags = style_type_set_flags; 3347a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski value = def_style_attr_entry->map.value; 3357a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski if (kDebugStyles) { 33632e7501a27f0f19bccdf9e91f9b87869c093f695Adam Lesinski ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType, value.data); 3374452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski } 3387a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski } 3397a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski } 3404452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski 3417a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski uint32_t resid = 0; 3427a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski if (value.dataType != Res_value::TYPE_NULL) { 3437a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski // Take care of resolving the found resource to its final value. 34432e7501a27f0f19bccdf9e91f9b87869c093f695Adam Lesinski ssize_t new_block = 34532e7501a27f0f19bccdf9e91f9b87869c093f695Adam Lesinski theme->resolveAttributeReference(&value, block, &resid, &type_set_flags, &config); 3467a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski if (new_block >= 0) { 3477a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski block = new_block; 3487a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski } 3497a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski 3507a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski if (kDebugStyles) { 35132e7501a27f0f19bccdf9e91f9b87869c093f695Adam Lesinski ALOGI("-> Resolved attr: type=0x%x, data=0x%08x", value.dataType, value.data); 3527a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski } 35332e7501a27f0f19bccdf9e91f9b87869c093f695Adam Lesinski } else if (value.data != Res_value::DATA_NULL_EMPTY) { 35432e7501a27f0f19bccdf9e91f9b87869c093f695Adam Lesinski // If we still don't have a value for this attribute, try to find it in the theme! 35532e7501a27f0f19bccdf9e91f9b87869c093f695Adam Lesinski ssize_t new_block = theme->getAttribute(cur_ident, &value, &type_set_flags); 3567a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski if (new_block >= 0) { 3577a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski if (kDebugStyles) { 35832e7501a27f0f19bccdf9e91f9b87869c093f695Adam Lesinski ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType, value.data); 3594452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski } 36032e7501a27f0f19bccdf9e91f9b87869c093f695Adam Lesinski new_block = res.resolveReference(&value, new_block, &resid, &type_set_flags, &config); 3617a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski if (new_block >= 0) { 3627a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski block = new_block; 3634452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski } 3644452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski 3654452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski if (kDebugStyles) { 36632e7501a27f0f19bccdf9e91f9b87869c093f695Adam Lesinski ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.dataType, value.data); 3674452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski } 3687a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski } 3697a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski } 3704452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski 3717a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski // Deal with the special @null value -- it turns back to TYPE_NULL. 3727a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) { 3737a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski if (kDebugStyles) { 3747a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski ALOGI("-> Setting to @null!"); 3757a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski } 3767a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski value.dataType = Res_value::TYPE_NULL; 3777a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski value.data = Res_value::DATA_NULL_UNDEFINED; 3787a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski block = kXmlBlock; 3794452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski } 3804452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski 3817a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski if (kDebugStyles) { 38232e7501a27f0f19bccdf9e91f9b87869c093f695Adam Lesinski ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x", cur_ident, value.dataType, value.data); 3837a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski } 3844452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski 3857a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski // Write the final value back to Java. 3867a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski out_values[STYLE_TYPE] = value.dataType; 3877a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski out_values[STYLE_DATA] = value.data; 3884c67a475a334e4f65238d439a3339195e03c03beAdam Lesinski out_values[STYLE_ASSET_COOKIE] = 3894c67a475a334e4f65238d439a3339195e03c03beAdam Lesinski block != kXmlBlock ? static_cast<uint32_t>(res.getTableCookie(block)) 3904c67a475a334e4f65238d439a3339195e03c03beAdam Lesinski : static_cast<uint32_t>(-1); 3917a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski out_values[STYLE_RESOURCE_ID] = resid; 3927a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski out_values[STYLE_CHANGING_CONFIGURATIONS] = type_set_flags; 3937a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski out_values[STYLE_DENSITY] = config.density; 3947a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski 39532e7501a27f0f19bccdf9e91f9b87869c093f695Adam Lesinski if (value.dataType != Res_value::TYPE_NULL || value.data == Res_value::DATA_NULL_EMPTY) { 3967a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski indices_idx++; 39706d3e8fec7e2b29f99d755bee849023d88957953Adam Lesinski 39806d3e8fec7e2b29f99d755bee849023d88957953Adam Lesinski // out_indices must NOT be nullptr. 3997a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski out_indices[indices_idx] = ii; 4004452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski } 4014452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski 4027a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski out_values += STYLE_NUM_ENTRIES; 4037a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski } 4044452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski 4057a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski res.unlock(); 4064452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski 40706d3e8fec7e2b29f99d755bee849023d88957953Adam Lesinski // out_indices must NOT be nullptr. 40806d3e8fec7e2b29f99d755bee849023d88957953Adam Lesinski out_indices[0] = indices_idx; 4097a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski} 4104452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski 4114c67a475a334e4f65238d439a3339195e03c03beAdam Lesinskibool RetrieveAttributes(const ResTable* res, ResXMLParser* xml_parser, 4124c67a475a334e4f65238d439a3339195e03c03beAdam Lesinski uint32_t* attrs, size_t attrs_length, 4134c67a475a334e4f65238d439a3339195e03c03beAdam Lesinski uint32_t* out_values, uint32_t* out_indices) { 4147a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski ResTable_config config; 4157a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski Res_value value; 4164452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski 4177a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski int indices_idx = 0; 4184452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski 4197a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski // Now lock down the resource object and start pulling stuff from it. 4207a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski res->lock(); 4214452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski 4227a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski // Retrieve the XML attributes, if requested. 4237a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski const size_t xml_attr_count = xml_parser->getAttributeCount(); 4247a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski size_t ix = 0; 4257a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski uint32_t cur_xml_attr = xml_parser->getAttributeNameResID(ix); 4264452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski 4277a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski static const ssize_t kXmlBlock = 0x10000000; 4284452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski 4297a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski // Now iterate through all of the attributes that the client has requested, 4307a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski // filling in each with whatever data we can find. 4317a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski for (size_t ii = 0; ii < attrs_length; ii++) { 4327a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski const uint32_t cur_ident = attrs[ii]; 4337a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski ssize_t block = kXmlBlock; 4347a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski uint32_t type_set_flags = 0; 4354452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski 4367a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski value.dataType = Res_value::TYPE_NULL; 4377a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski value.data = Res_value::DATA_NULL_UNDEFINED; 4387a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski config.density = 0; 4394452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski 4407a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski // Try to find a value for this attribute... 4417a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski // Skip through XML attributes until the end or the next possible match. 4427a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski while (ix < xml_attr_count && cur_ident > cur_xml_attr) { 4437a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski ix++; 4447a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski cur_xml_attr = xml_parser->getAttributeNameResID(ix); 4457a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski } 4467a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski // Retrieve the current XML attribute if it matches, and step to next. 4477a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski if (ix < xml_attr_count && cur_ident == cur_xml_attr) { 4487a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski xml_parser->getAttributeValue(ix, &value); 4497a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski ix++; 4507a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski cur_xml_attr = xml_parser->getAttributeNameResID(ix); 4517a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski } 4524452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski 4537a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski uint32_t resid = 0; 4547a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski if (value.dataType != Res_value::TYPE_NULL) { 4557a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski // Take care of resolving the found resource to its final value. 4567a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski // printf("Resolving attribute reference\n"); 4574c67a475a334e4f65238d439a3339195e03c03beAdam Lesinski ssize_t new_block = res->resolveReference(&value, block, &resid, 4584c67a475a334e4f65238d439a3339195e03c03beAdam Lesinski &type_set_flags, &config); 4597a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski if (new_block >= 0) block = new_block; 4607a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski } 4614452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski 4627a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski // Deal with the special @null value -- it turns back to TYPE_NULL. 4637a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) { 4647a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski value.dataType = Res_value::TYPE_NULL; 4657a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski value.data = Res_value::DATA_NULL_UNDEFINED; 4667a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski block = kXmlBlock; 4677a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski } 4684452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski 4697a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski // Write the final value back to Java. 4707a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski out_values[STYLE_TYPE] = value.dataType; 4717a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski out_values[STYLE_DATA] = value.data; 4724c67a475a334e4f65238d439a3339195e03c03beAdam Lesinski out_values[STYLE_ASSET_COOKIE] = 4734c67a475a334e4f65238d439a3339195e03c03beAdam Lesinski block != kXmlBlock ? static_cast<uint32_t>(res->getTableCookie(block)) 4744c67a475a334e4f65238d439a3339195e03c03beAdam Lesinski : static_cast<uint32_t>(-1); 4757a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski out_values[STYLE_RESOURCE_ID] = resid; 4767a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski out_values[STYLE_CHANGING_CONFIGURATIONS] = type_set_flags; 4777a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski out_values[STYLE_DENSITY] = config.density; 4787a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski 47932e7501a27f0f19bccdf9e91f9b87869c093f695Adam Lesinski if (out_indices != nullptr && 48032e7501a27f0f19bccdf9e91f9b87869c093f695Adam Lesinski (value.dataType != Res_value::TYPE_NULL || value.data == Res_value::DATA_NULL_EMPTY)) { 4817a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski indices_idx++; 4827a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski out_indices[indices_idx] = ii; 4834452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski } 4844452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski 4857a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski out_values += STYLE_NUM_ENTRIES; 4867a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski } 4874452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski 4887a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski res->unlock(); 4897a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski 4904c67a475a334e4f65238d439a3339195e03c03beAdam Lesinski if (out_indices != nullptr) { 4917a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski out_indices[0] = indices_idx; 4927a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski } 4937a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski return true; 4944452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski} 4954452e137ffc02ab4e32aab2b2ec7192b45d9f494Adam Lesinski 4967a37b74d37ff79e805c9e97d977e07bfec753c5aAdam Lesinski} // namespace android 497