11ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski/* 21ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * Copyright (C) 2015 The Android Open Source Project 31ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * 41ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * Licensed under the Apache License, Version 2.0 (the "License"); 51ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * you may not use this file except in compliance with the License. 61ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * You may obtain a copy of the License at 71ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * 81ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * http://www.apache.org/licenses/LICENSE-2.0 91ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * 101ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * Unless required by applicable law or agreed to in writing, software 111ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * distributed under the License is distributed on an "AS IS" BASIS, 121ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 131ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * See the License for the specific language governing permissions and 141ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * limitations under the License. 151ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski */ 161ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 171ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "ConfigDescription.h" 181ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "Resource.h" 19e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski#include "ValueVisitor.h" 201ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "process/SymbolTable.h" 21e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski#include "util/Util.h" 221ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 231ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include <androidfw/AssetManager.h> 241ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include <androidfw/ResourceTypes.h> 251ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 261ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskinamespace aapt { 271ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 2864587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinskivoid SymbolTable::appendSource(std::unique_ptr<ISymbolSource> source) { 2964587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski mSources.push_back(std::move(source)); 3064587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski 3164587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski // We do not clear the cache, because sources earlier in the list take precedent. 3264587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski} 3364587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski 3464587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinskivoid SymbolTable::prependSource(std::unique_ptr<ISymbolSource> source) { 3564587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski mSources.insert(mSources.begin(), std::move(source)); 3664587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski 3764587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski // We must clear the cache in case we did a lookup before adding this resource. 3864587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski mCache.clear(); 3964587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski} 4064587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski 4164587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinskiconst SymbolTable::Symbol* SymbolTable::findByName(const ResourceName& name) { 421ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (const std::shared_ptr<Symbol>& s = mCache.get(name)) { 431ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski return s.get(); 441ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 451ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 4664587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski // We did not find it in the cache, so look through the sources. 4764587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski for (auto& symbolSource : mSources) { 4864587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski std::unique_ptr<Symbol> symbol = symbolSource->findByName(name); 4964587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski if (symbol) { 5064587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski // Take ownership of the symbol into a shared_ptr. We do this because LruCache 5164587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski // doesn't support unique_ptr. 5264587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski std::shared_ptr<Symbol> sharedSymbol = std::shared_ptr<Symbol>(symbol.release()); 5364587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski mCache.put(name, sharedSymbol); 547656554f91b40bc93bf94c89afcad4a9a8ced884Adam Lesinski 557656554f91b40bc93bf94c89afcad4a9a8ced884Adam Lesinski if (sharedSymbol->id) { 567656554f91b40bc93bf94c89afcad4a9a8ced884Adam Lesinski // The symbol has an ID, so we can also cache this! 577656554f91b40bc93bf94c89afcad4a9a8ced884Adam Lesinski mIdCache.put(sharedSymbol->id.value(), sharedSymbol); 587656554f91b40bc93bf94c89afcad4a9a8ced884Adam Lesinski } 5964587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski return sharedSymbol.get(); 6064587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski } 6164587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski } 6264587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski return nullptr; 6364587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski} 6464587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski 6564587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinskiconst SymbolTable::Symbol* SymbolTable::findById(ResourceId id) { 6664587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski if (const std::shared_ptr<Symbol>& s = mIdCache.get(id)) { 6764587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski return s.get(); 6864587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski } 6964587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski 7064587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski // We did not find it in the cache, so look through the sources. 7164587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski for (auto& symbolSource : mSources) { 7264587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski std::unique_ptr<Symbol> symbol = symbolSource->findById(id); 7364587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski if (symbol) { 7464587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski // Take ownership of the symbol into a shared_ptr. We do this because LruCache 7564587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski // doesn't support unique_ptr. 7664587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski std::shared_ptr<Symbol> sharedSymbol = std::shared_ptr<Symbol>(symbol.release()); 7764587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski mIdCache.put(id, sharedSymbol); 7864587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski return sharedSymbol.get(); 7964587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski } 8064587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski } 8164587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski return nullptr; 8264587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski} 8364587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski 847656554f91b40bc93bf94c89afcad4a9a8ced884Adam Lesinskiconst SymbolTable::Symbol* SymbolTable::findByReference(const Reference& ref) { 857656554f91b40bc93bf94c89afcad4a9a8ced884Adam Lesinski // First try the ID. This is because when we lookup by ID, we only fill in the ID cache. 867656554f91b40bc93bf94c89afcad4a9a8ced884Adam Lesinski // Looking up by name fills in the name and ID cache. So a cache miss will cause a failed 877656554f91b40bc93bf94c89afcad4a9a8ced884Adam Lesinski // ID lookup, then a successfull name lookup. Subsequent look ups will hit immediately 887656554f91b40bc93bf94c89afcad4a9a8ced884Adam Lesinski // because the ID is cached too. 897656554f91b40bc93bf94c89afcad4a9a8ced884Adam Lesinski // 907656554f91b40bc93bf94c89afcad4a9a8ced884Adam Lesinski // If we looked up by name first, a cache miss would mean we failed to lookup by name, then 917656554f91b40bc93bf94c89afcad4a9a8ced884Adam Lesinski // succeeded to lookup by ID. Subsequent lookups will miss then hit. 927656554f91b40bc93bf94c89afcad4a9a8ced884Adam Lesinski const SymbolTable::Symbol* symbol = nullptr; 937656554f91b40bc93bf94c89afcad4a9a8ced884Adam Lesinski if (ref.id) { 947656554f91b40bc93bf94c89afcad4a9a8ced884Adam Lesinski symbol = findById(ref.id.value()); 957656554f91b40bc93bf94c89afcad4a9a8ced884Adam Lesinski } 967656554f91b40bc93bf94c89afcad4a9a8ced884Adam Lesinski 977656554f91b40bc93bf94c89afcad4a9a8ced884Adam Lesinski if (ref.name && !symbol) { 987656554f91b40bc93bf94c89afcad4a9a8ced884Adam Lesinski symbol = findByName(ref.name.value()); 997656554f91b40bc93bf94c89afcad4a9a8ced884Adam Lesinski } 1007656554f91b40bc93bf94c89afcad4a9a8ced884Adam Lesinski return symbol; 1017656554f91b40bc93bf94c89afcad4a9a8ced884Adam Lesinski} 1027656554f91b40bc93bf94c89afcad4a9a8ced884Adam Lesinski 10364587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinskistd::unique_ptr<SymbolTable::Symbol> ResourceTableSymbolSource::findByName( 10464587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski const ResourceName& name) { 1051ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski Maybe<ResourceTable::SearchResult> result = mTable->findResource(name); 1061ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (!result) { 1071ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (name.type == ResourceType::kAttr) { 1081ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski // Recurse and try looking up a private attribute. 109e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski return findByName(ResourceName(name.package, ResourceType::kAttrPrivate, name.entry)); 1101ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 1111ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski return {}; 1121ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 1131ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 1141ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski ResourceTable::SearchResult sr = result.value(); 1151ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 11664587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski std::unique_ptr<SymbolTable::Symbol> symbol = util::make_unique<SymbolTable::Symbol>(); 117467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski symbol->isPublic = (sr.entry->symbolStatus.state == SymbolState::kPublic); 1181ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 11964587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski if (sr.package->id && sr.type->id && sr.entry->id) { 12064587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski symbol->id = ResourceId(sr.package->id.value(), sr.type->id.value(), sr.entry->id.value()); 12164587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski } 12264587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski 1231ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (name.type == ResourceType::kAttr || name.type == ResourceType::kAttrPrivate) { 1241ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski const ConfigDescription kDefaultConfig; 125e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski ResourceConfigValue* configValue = sr.entry->findValue(kDefaultConfig); 126e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski if (configValue) { 1271ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski // This resource has an Attribute. 128e4bb9eb5af5b0899dc0921d5580220b20e15bd5aAdam Lesinski if (Attribute* attr = valueCast<Attribute>(configValue->value.get())) { 1297656554f91b40bc93bf94c89afcad4a9a8ced884Adam Lesinski symbol->attribute = std::make_shared<Attribute>(*attr); 130e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski } else { 131e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski return {}; 132e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski } 1331ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 1341ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 13564587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski return symbol; 13664587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski} 1371ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 13864587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinskibool AssetManagerSymbolSource::addAssetPath(const StringPiece& path) { 13964587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski int32_t cookie = 0; 14064587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski return mAssets.addAssetPath(android::String8(path.data(), path.size()), &cookie); 1411ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski} 1421ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 14364587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinskistatic std::unique_ptr<SymbolTable::Symbol> lookupAttributeInTable(const android::ResTable& table, 14464587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski ResourceId id) { 1451ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski // Try as a bag. 1461ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski const android::ResTable::bag_entry* entry; 1471ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski ssize_t count = table.lockBag(id.id, &entry); 1481ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (count < 0) { 1491ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski table.unlockBag(entry); 1501ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski return nullptr; 1511ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 1521ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 1531ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski // We found a resource. 15464587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski std::unique_ptr<SymbolTable::Symbol> s = util::make_unique<SymbolTable::Symbol>(); 1551ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski s->id = id; 1561ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 1571ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski // Check to see if it is an attribute. 1581ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski for (size_t i = 0; i < (size_t) count; i++) { 1591ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (entry[i].map.name.ident == android::ResTable_map::ATTR_TYPE) { 1607656554f91b40bc93bf94c89afcad4a9a8ced884Adam Lesinski s->attribute = std::make_shared<Attribute>(false); 1611ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski s->attribute->typeMask = entry[i].map.value.data; 1621ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski break; 1631ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 1641ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 1651ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 1661ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (s->attribute) { 1671ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski for (size_t i = 0; i < (size_t) count; i++) { 168a587065721053ad54e34f484868142407d59512dAdam Lesinski const android::ResTable_map& mapEntry = entry[i].map; 169a587065721053ad54e34f484868142407d59512dAdam Lesinski if (Res_INTERNALID(mapEntry.name.ident)) { 170a587065721053ad54e34f484868142407d59512dAdam Lesinski switch (mapEntry.name.ident) { 171a587065721053ad54e34f484868142407d59512dAdam Lesinski case android::ResTable_map::ATTR_MIN: 172a587065721053ad54e34f484868142407d59512dAdam Lesinski s->attribute->minInt = static_cast<int32_t>(mapEntry.value.data); 173a587065721053ad54e34f484868142407d59512dAdam Lesinski break; 174a587065721053ad54e34f484868142407d59512dAdam Lesinski case android::ResTable_map::ATTR_MAX: 175a587065721053ad54e34f484868142407d59512dAdam Lesinski s->attribute->maxInt = static_cast<int32_t>(mapEntry.value.data); 176a587065721053ad54e34f484868142407d59512dAdam Lesinski break; 1771ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 178a587065721053ad54e34f484868142407d59512dAdam Lesinski continue; 179a587065721053ad54e34f484868142407d59512dAdam Lesinski } 1801ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 181a587065721053ad54e34f484868142407d59512dAdam Lesinski android::ResTable::resource_name entryName; 182a587065721053ad54e34f484868142407d59512dAdam Lesinski if (!table.getResourceName(mapEntry.name.ident, false, &entryName)) { 183a587065721053ad54e34f484868142407d59512dAdam Lesinski table.unlockBag(entry); 184a587065721053ad54e34f484868142407d59512dAdam Lesinski return nullptr; 185a587065721053ad54e34f484868142407d59512dAdam Lesinski } 1861ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 187a587065721053ad54e34f484868142407d59512dAdam Lesinski const ResourceType* parsedType = parseResourceType( 188a587065721053ad54e34f484868142407d59512dAdam Lesinski StringPiece16(entryName.type, entryName.typeLen)); 189a587065721053ad54e34f484868142407d59512dAdam Lesinski if (!parsedType) { 190a587065721053ad54e34f484868142407d59512dAdam Lesinski table.unlockBag(entry); 191a587065721053ad54e34f484868142407d59512dAdam Lesinski return nullptr; 1921ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 193a587065721053ad54e34f484868142407d59512dAdam Lesinski 194a587065721053ad54e34f484868142407d59512dAdam Lesinski Attribute::Symbol symbol; 195a587065721053ad54e34f484868142407d59512dAdam Lesinski symbol.symbol.name = ResourceName( 196a587065721053ad54e34f484868142407d59512dAdam Lesinski StringPiece16(entryName.package, entryName.packageLen), 197a587065721053ad54e34f484868142407d59512dAdam Lesinski *parsedType, 198a587065721053ad54e34f484868142407d59512dAdam Lesinski StringPiece16(entryName.name, entryName.nameLen)); 199a587065721053ad54e34f484868142407d59512dAdam Lesinski symbol.symbol.id = ResourceId(mapEntry.name.ident); 200a587065721053ad54e34f484868142407d59512dAdam Lesinski symbol.value = mapEntry.value.data; 201a587065721053ad54e34f484868142407d59512dAdam Lesinski s->attribute->symbols.push_back(std::move(symbol)); 2021ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 2031ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 2041ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski table.unlockBag(entry); 2051ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski return s; 2061ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski} 2071ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 20864587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinskistd::unique_ptr<SymbolTable::Symbol> AssetManagerSymbolSource::findByName( 2091ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski const ResourceName& name) { 21064587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski const android::ResTable& table = mAssets.getResources(false); 21164587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski StringPiece16 typeStr = toString(name.type); 21264587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski uint32_t typeSpecFlags = 0; 21364587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski ResourceId resId = table.identifierForName(name.entry.data(), name.entry.size(), 21464587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski typeStr.data(), typeStr.size(), 21564587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski name.package.data(), name.package.size(), 21664587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski &typeSpecFlags); 21764587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski if (!resId.isValid()) { 21864587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski return {}; 2191ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 2201ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 22164587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski std::unique_ptr<SymbolTable::Symbol> s; 22264587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski if (name.type == ResourceType::kAttr) { 22364587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski s = lookupAttributeInTable(table, resId); 22464587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski } else { 22564587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski s = util::make_unique<SymbolTable::Symbol>(); 22664587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski s->id = resId; 22764587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski } 228e352b990e1dca7857a4d170f411ddad2065670caAdam Lesinski 22964587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski if (s) { 23064587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski s->isPublic = (typeSpecFlags & android::ResTable_typeSpec::SPEC_PUBLIC) != 0; 23164587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski return s; 2321ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 23364587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski return {}; 2341ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski} 2351ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 236467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinskistatic Maybe<ResourceName> getResourceName(const android::ResTable& table, ResourceId id) { 23764587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski android::ResTable::resource_name resName = {}; 238467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski if (!table.getResourceName(id.id, true, &resName)) { 239467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski return {}; 240467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski } 241467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski 242467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski ResourceName name; 243467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski if (resName.package) { 244467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski name.package = StringPiece16(resName.package, resName.packageLen).toString(); 245467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski } 246467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski 247467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski const ResourceType* type; 248467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski if (resName.type) { 249467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski type = parseResourceType(StringPiece16(resName.type, resName.typeLen)); 250467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski 251467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski } else if (resName.type8) { 252467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski type = parseResourceType(util::utf8ToUtf16(StringPiece(resName.type8, resName.typeLen))); 253467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski } else { 254467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski return {}; 255467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski } 256467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski 257467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski if (!type) { 258467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski return {}; 259467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski } 260467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski 261467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski name.type = *type; 262467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski 263467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski if (resName.name) { 264467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski name.entry = StringPiece16(resName.name, resName.nameLen).toString(); 265467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski } else if (resName.name8) { 266467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski name.entry = util::utf8ToUtf16(StringPiece(resName.name8, resName.nameLen)); 267467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski } else { 268467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski return {}; 269467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski } 270467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski 271467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski return name; 272467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski} 273467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski 27464587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinskistd::unique_ptr<SymbolTable::Symbol> AssetManagerSymbolSource::findById(ResourceId id) { 27564587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski const android::ResTable& table = mAssets.getResources(false); 27664587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski Maybe<ResourceName> maybeName = getResourceName(table, id); 27764587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski if (!maybeName) { 27864587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski return {}; 2791ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 2801ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 28164587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski uint32_t typeSpecFlags = 0; 28264587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski table.getResourceFlags(id.id, &typeSpecFlags); 283e352b990e1dca7857a4d170f411ddad2065670caAdam Lesinski 28464587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski std::unique_ptr<SymbolTable::Symbol> s; 28564587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski if (maybeName.value().type == ResourceType::kAttr) { 28664587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski s = lookupAttributeInTable(table, id); 28764587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski } else { 28864587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski s = util::make_unique<SymbolTable::Symbol>(); 28964587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski s->id = id; 2901ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 2911ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 29264587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski if (s) { 29364587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski s->isPublic = (typeSpecFlags & android::ResTable_typeSpec::SPEC_PUBLIC) != 0; 29464587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski return s; 2951ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 2961ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski return {}; 2971ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski} 2981ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 2997656554f91b40bc93bf94c89afcad4a9a8ced884Adam Lesinskistd::unique_ptr<SymbolTable::Symbol> AssetManagerSymbolSource::findByReference( 3007656554f91b40bc93bf94c89afcad4a9a8ced884Adam Lesinski const Reference& ref) { 3017656554f91b40bc93bf94c89afcad4a9a8ced884Adam Lesinski // AssetManager always prefers IDs. 3027656554f91b40bc93bf94c89afcad4a9a8ced884Adam Lesinski if (ref.id) { 3037656554f91b40bc93bf94c89afcad4a9a8ced884Adam Lesinski return findById(ref.id.value()); 3047656554f91b40bc93bf94c89afcad4a9a8ced884Adam Lesinski } else if (ref.name) { 3057656554f91b40bc93bf94c89afcad4a9a8ced884Adam Lesinski return findByName(ref.name.value()); 3067656554f91b40bc93bf94c89afcad4a9a8ced884Adam Lesinski } 3077656554f91b40bc93bf94c89afcad4a9a8ced884Adam Lesinski return {}; 3087656554f91b40bc93bf94c89afcad4a9a8ced884Adam Lesinski} 3097656554f91b40bc93bf94c89afcad4a9a8ced884Adam Lesinski 3101ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski} // namespace aapt 311