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#ifndef AAPT_PROCESS_SYMBOLTABLE_H 181ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#define AAPT_PROCESS_SYMBOLTABLE_H 191ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 201ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "Resource.h" 211ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "ResourceTable.h" 221ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "ResourceValues.h" 231ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "util/Util.h" 241ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 251ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include <utils/JenkinsHash.h> 261ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include <utils/LruCache.h> 271ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 2864587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski#include <android-base/macros.h> 291ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include <androidfw/AssetManager.h> 301ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include <algorithm> 311ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include <memory> 321ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include <vector> 331ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 341ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskinamespace aapt { 351ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 361ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskiinline android::hash_t hash_type(const ResourceName& name) { 371ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski std::hash<std::u16string> strHash; 381ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski android::hash_t hash = 0; 3964587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski hash = android::JenkinsHashMix(hash, (uint32_t) strHash(name.package)); 401ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski hash = android::JenkinsHashMix(hash, (uint32_t) name.type); 4164587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski hash = android::JenkinsHashMix(hash, (uint32_t) strHash(name.entry)); 421ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski return hash; 431ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski} 441ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 451ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskiinline android::hash_t hash_type(const ResourceId& id) { 461ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski return android::hash_type(id.id); 471ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski} 481ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 4964587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinskiclass ISymbolSource; 501ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 5164587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinskiclass SymbolTable { 521ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskipublic: 5364587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski struct Symbol { 54626b3dbf74f02ae630ae0089632f5962340694dcAdam Lesinski Symbol() : Symbol(Maybe<ResourceId>{}) { 55626b3dbf74f02ae630ae0089632f5962340694dcAdam Lesinski } 56626b3dbf74f02ae630ae0089632f5962340694dcAdam Lesinski 57626b3dbf74f02ae630ae0089632f5962340694dcAdam Lesinski Symbol(const Maybe<ResourceId>& i) : Symbol(i, nullptr) { 58626b3dbf74f02ae630ae0089632f5962340694dcAdam Lesinski } 59626b3dbf74f02ae630ae0089632f5962340694dcAdam Lesinski 60626b3dbf74f02ae630ae0089632f5962340694dcAdam Lesinski Symbol(const Maybe<ResourceId>& i, const std::shared_ptr<Attribute>& attr) : 61626b3dbf74f02ae630ae0089632f5962340694dcAdam Lesinski Symbol(i, attr, false) { 62626b3dbf74f02ae630ae0089632f5962340694dcAdam Lesinski } 63626b3dbf74f02ae630ae0089632f5962340694dcAdam Lesinski 64626b3dbf74f02ae630ae0089632f5962340694dcAdam Lesinski Symbol(const Maybe<ResourceId>& i, const std::shared_ptr<Attribute>& attr, bool pub) : 65626b3dbf74f02ae630ae0089632f5962340694dcAdam Lesinski id(i), attribute(attr), isPublic(pub) { 66626b3dbf74f02ae630ae0089632f5962340694dcAdam Lesinski } 67626b3dbf74f02ae630ae0089632f5962340694dcAdam Lesinski 68626b3dbf74f02ae630ae0089632f5962340694dcAdam Lesinski Symbol(const Symbol&) = default; 69626b3dbf74f02ae630ae0089632f5962340694dcAdam Lesinski Symbol(Symbol&&) = default; 70626b3dbf74f02ae630ae0089632f5962340694dcAdam Lesinski Symbol& operator=(const Symbol&) = default; 71626b3dbf74f02ae630ae0089632f5962340694dcAdam Lesinski Symbol& operator=(Symbol&&) = default; 72626b3dbf74f02ae630ae0089632f5962340694dcAdam Lesinski 7364587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski Maybe<ResourceId> id; 747656554f91b40bc93bf94c89afcad4a9a8ced884Adam Lesinski std::shared_ptr<Attribute> attribute; 75626b3dbf74f02ae630ae0089632f5962340694dcAdam Lesinski bool isPublic = false; 7664587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski }; 7764587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski 7864587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski SymbolTable() : mCache(200), mIdCache(200) { 791ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 801ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 8164587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski void appendSource(std::unique_ptr<ISymbolSource> source); 8264587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski void prependSource(std::unique_ptr<ISymbolSource> source); 831ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 8464587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski /** 8564587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski * Never hold on to the result between calls to findByName or findById. The results 8664587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski * are typically stored in a cache which may evict entries. 8764587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski */ 8864587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski const Symbol* findByName(const ResourceName& name); 8964587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski const Symbol* findById(ResourceId id); 901ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 917656554f91b40bc93bf94c89afcad4a9a8ced884Adam Lesinski /** 927656554f91b40bc93bf94c89afcad4a9a8ced884Adam Lesinski * Let's the ISymbolSource decide whether looking up by name or ID is faster, if both 937656554f91b40bc93bf94c89afcad4a9a8ced884Adam Lesinski * are available. 947656554f91b40bc93bf94c89afcad4a9a8ced884Adam Lesinski */ 957656554f91b40bc93bf94c89afcad4a9a8ced884Adam Lesinski const Symbol* findByReference(const Reference& ref); 967656554f91b40bc93bf94c89afcad4a9a8ced884Adam Lesinski 971ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskiprivate: 9864587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski std::vector<std::unique_ptr<ISymbolSource>> mSources; 991ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 10064587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski // We use shared_ptr because unique_ptr is not supported and 10164587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski // we need automatic deletion. 10264587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski android::LruCache<ResourceName, std::shared_ptr<Symbol>> mCache; 10364587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski android::LruCache<ResourceId, std::shared_ptr<Symbol>> mIdCache; 1041ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 10564587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski DISALLOW_COPY_AND_ASSIGN(SymbolTable); 10664587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski}; 1071ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 10864587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski/** 10964587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski * An interface that a symbol source implements in order to surface symbol information 11064587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski * to the symbol table. 11164587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski */ 11264587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinskiclass ISymbolSource { 11364587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinskipublic: 11464587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski virtual ~ISymbolSource() = default; 1151ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 11664587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski virtual std::unique_ptr<SymbolTable::Symbol> findByName(const ResourceName& name) = 0; 11764587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski virtual std::unique_ptr<SymbolTable::Symbol> findById(ResourceId id) = 0; 1187656554f91b40bc93bf94c89afcad4a9a8ced884Adam Lesinski 1197656554f91b40bc93bf94c89afcad4a9a8ced884Adam Lesinski /** 1207656554f91b40bc93bf94c89afcad4a9a8ced884Adam Lesinski * Default implementation tries the name if it exists, else the ID. 1217656554f91b40bc93bf94c89afcad4a9a8ced884Adam Lesinski */ 1227656554f91b40bc93bf94c89afcad4a9a8ced884Adam Lesinski virtual std::unique_ptr<SymbolTable::Symbol> findByReference(const Reference& ref) { 1237656554f91b40bc93bf94c89afcad4a9a8ced884Adam Lesinski if (ref.name) { 1247656554f91b40bc93bf94c89afcad4a9a8ced884Adam Lesinski return findByName(ref.name.value()); 1257656554f91b40bc93bf94c89afcad4a9a8ced884Adam Lesinski } else if (ref.id) { 1267656554f91b40bc93bf94c89afcad4a9a8ced884Adam Lesinski return findById(ref.id.value()); 1277656554f91b40bc93bf94c89afcad4a9a8ced884Adam Lesinski } 1287656554f91b40bc93bf94c89afcad4a9a8ced884Adam Lesinski return {}; 1297656554f91b40bc93bf94c89afcad4a9a8ced884Adam Lesinski } 13064587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski}; 1311ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 13264587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski/** 13364587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski * Exposes the resources in a ResourceTable as symbols for SymbolTable. 13464587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski * Instances of this class must outlive the encompassed ResourceTable. 13564587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski * Lookups by ID are ignored. 13664587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski */ 13764587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinskiclass ResourceTableSymbolSource : public ISymbolSource { 1381ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskipublic: 13964587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski explicit ResourceTableSymbolSource(ResourceTable* table) : mTable(table) { 1401ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 1411ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 14264587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski std::unique_ptr<SymbolTable::Symbol> findByName(const ResourceName& name) override; 14364587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski 14464587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski std::unique_ptr<SymbolTable::Symbol> findById(ResourceId id) override { 14564587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski return {}; 1461ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 1471ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 1481ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskiprivate: 14964587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski ResourceTable* mTable; 1501ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 15164587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski DISALLOW_COPY_AND_ASSIGN(ResourceTableSymbolSource); 15264587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski}; 1531ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 15464587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinskiclass AssetManagerSymbolSource : public ISymbolSource { 1551ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskipublic: 15664587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski AssetManagerSymbolSource() = default; 1571ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 15864587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski bool addAssetPath(const StringPiece& path); 15964587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski 16064587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski std::unique_ptr<SymbolTable::Symbol> findByName(const ResourceName& name) override; 16164587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski std::unique_ptr<SymbolTable::Symbol> findById(ResourceId id) override; 1627656554f91b40bc93bf94c89afcad4a9a8ced884Adam Lesinski std::unique_ptr<SymbolTable::Symbol> findByReference(const Reference& ref) override; 16364587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski 16464587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinskiprivate: 16564587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski android::AssetManager mAssets; 16664587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski 16764587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski DISALLOW_COPY_AND_ASSIGN(AssetManagerSymbolSource); 1681ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski}; 1691ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 1701ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski} // namespace aapt 1711ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski 1721ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#endif /* AAPT_PROCESS_SYMBOLTABLE_H */ 173