Home | History | Annotate | Download | only in process
      1 /*
      2  * Copyright (C) 2015 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 #ifndef AAPT_PROCESS_SYMBOLTABLE_H
     18 #define AAPT_PROCESS_SYMBOLTABLE_H
     19 
     20 #include "Resource.h"
     21 #include "ResourceTable.h"
     22 #include "ResourceValues.h"
     23 #include "util/Util.h"
     24 
     25 #include <utils/JenkinsHash.h>
     26 #include <utils/LruCache.h>
     27 
     28 #include <android-base/macros.h>
     29 #include <androidfw/AssetManager.h>
     30 #include <algorithm>
     31 #include <memory>
     32 #include <vector>
     33 
     34 namespace aapt {
     35 
     36 inline android::hash_t hash_type(const ResourceName& name) {
     37     std::hash<std::u16string> strHash;
     38     android::hash_t hash = 0;
     39     hash = android::JenkinsHashMix(hash, (uint32_t) strHash(name.package));
     40     hash = android::JenkinsHashMix(hash, (uint32_t) name.type);
     41     hash = android::JenkinsHashMix(hash, (uint32_t) strHash(name.entry));
     42     return hash;
     43 }
     44 
     45 inline android::hash_t hash_type(const ResourceId& id) {
     46     return android::hash_type(id.id);
     47 }
     48 
     49 class ISymbolSource;
     50 
     51 class SymbolTable {
     52 public:
     53     struct Symbol {
     54         Symbol() : Symbol(Maybe<ResourceId>{}) {
     55         }
     56 
     57         Symbol(const Maybe<ResourceId>& i) : Symbol(i, nullptr) {
     58         }
     59 
     60         Symbol(const Maybe<ResourceId>& i, const std::shared_ptr<Attribute>& attr) :
     61                 Symbol(i, attr, false) {
     62         }
     63 
     64         Symbol(const Maybe<ResourceId>& i, const std::shared_ptr<Attribute>& attr, bool pub) :
     65                 id(i), attribute(attr), isPublic(pub) {
     66         }
     67 
     68         Symbol(const Symbol&) = default;
     69         Symbol(Symbol&&) = default;
     70         Symbol& operator=(const Symbol&) = default;
     71         Symbol& operator=(Symbol&&) = default;
     72 
     73         Maybe<ResourceId> id;
     74         std::shared_ptr<Attribute> attribute;
     75         bool isPublic = false;
     76     };
     77 
     78     SymbolTable() : mCache(200), mIdCache(200) {
     79     }
     80 
     81     void appendSource(std::unique_ptr<ISymbolSource> source);
     82     void prependSource(std::unique_ptr<ISymbolSource> source);
     83 
     84     /**
     85      * Never hold on to the result between calls to findByName or findById. The results
     86      * are typically stored in a cache which may evict entries.
     87      */
     88     const Symbol* findByName(const ResourceName& name);
     89     const Symbol* findById(ResourceId id);
     90 
     91     /**
     92      * Let's the ISymbolSource decide whether looking up by name or ID is faster, if both
     93      * are available.
     94      */
     95     const Symbol* findByReference(const Reference& ref);
     96 
     97 private:
     98     std::vector<std::unique_ptr<ISymbolSource>> mSources;
     99 
    100     // We use shared_ptr because unique_ptr is not supported and
    101     // we need automatic deletion.
    102     android::LruCache<ResourceName, std::shared_ptr<Symbol>> mCache;
    103     android::LruCache<ResourceId, std::shared_ptr<Symbol>> mIdCache;
    104 
    105     DISALLOW_COPY_AND_ASSIGN(SymbolTable);
    106 };
    107 
    108 /**
    109  * An interface that a symbol source implements in order to surface symbol information
    110  * to the symbol table.
    111  */
    112 class ISymbolSource {
    113 public:
    114     virtual ~ISymbolSource() = default;
    115 
    116     virtual std::unique_ptr<SymbolTable::Symbol> findByName(const ResourceName& name) = 0;
    117     virtual std::unique_ptr<SymbolTable::Symbol> findById(ResourceId id) = 0;
    118 
    119     /**
    120      * Default implementation tries the name if it exists, else the ID.
    121      */
    122     virtual std::unique_ptr<SymbolTable::Symbol> findByReference(const Reference& ref) {
    123         if (ref.name) {
    124             return findByName(ref.name.value());
    125         } else if (ref.id) {
    126             return findById(ref.id.value());
    127         }
    128         return {};
    129     }
    130 };
    131 
    132 /**
    133  * Exposes the resources in a ResourceTable as symbols for SymbolTable.
    134  * Instances of this class must outlive the encompassed ResourceTable.
    135  * Lookups by ID are ignored.
    136  */
    137 class ResourceTableSymbolSource : public ISymbolSource {
    138 public:
    139     explicit ResourceTableSymbolSource(ResourceTable* table) : mTable(table) {
    140     }
    141 
    142     std::unique_ptr<SymbolTable::Symbol> findByName(const ResourceName& name) override;
    143 
    144     std::unique_ptr<SymbolTable::Symbol> findById(ResourceId id) override {
    145         return {};
    146     }
    147 
    148 private:
    149     ResourceTable* mTable;
    150 
    151     DISALLOW_COPY_AND_ASSIGN(ResourceTableSymbolSource);
    152 };
    153 
    154 class AssetManagerSymbolSource : public ISymbolSource {
    155 public:
    156     AssetManagerSymbolSource() = default;
    157 
    158     bool addAssetPath(const StringPiece& path);
    159 
    160     std::unique_ptr<SymbolTable::Symbol> findByName(const ResourceName& name) override;
    161     std::unique_ptr<SymbolTable::Symbol> findById(ResourceId id) override;
    162     std::unique_ptr<SymbolTable::Symbol> findByReference(const Reference& ref) override;
    163 
    164 private:
    165     android::AssetManager mAssets;
    166 
    167     DISALLOW_COPY_AND_ASSIGN(AssetManagerSymbolSource);
    168 };
    169 
    170 } // namespace aapt
    171 
    172 #endif /* AAPT_PROCESS_SYMBOLTABLE_H */
    173