Home | History | Annotate | Download | only in aapt2
      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_RESOURCE_TABLE_H
     18 #define AAPT_RESOURCE_TABLE_H
     19 
     20 #include "ConfigDescription.h"
     21 #include "Diagnostics.h"
     22 #include "Resource.h"
     23 #include "ResourceValues.h"
     24 #include "Source.h"
     25 #include "StringPool.h"
     26 #include "io/File.h"
     27 
     28 #include <android-base/macros.h>
     29 #include <functional>
     30 #include <map>
     31 #include <memory>
     32 #include <string>
     33 #include <tuple>
     34 #include <unordered_map>
     35 #include <vector>
     36 
     37 namespace aapt {
     38 
     39 enum class SymbolState {
     40     kUndefined,
     41     kPublic,
     42     kPrivate
     43 };
     44 
     45 /**
     46  * The Public status of a resource.
     47  */
     48 struct Symbol {
     49     SymbolState state = SymbolState::kUndefined;
     50     Source source;
     51     std::u16string comment;
     52 };
     53 
     54 class ResourceConfigValue {
     55 public:
     56     /**
     57      * The configuration for which this value is defined.
     58      */
     59     const ConfigDescription config;
     60 
     61     /**
     62      * The product for which this value is defined.
     63      */
     64     const std::string product;
     65 
     66     /**
     67      * The actual Value.
     68      */
     69     std::unique_ptr<Value> value;
     70 
     71     ResourceConfigValue(const ConfigDescription& config, const StringPiece& product) :
     72             config(config), product(product.toString()) { }
     73 
     74 private:
     75     DISALLOW_COPY_AND_ASSIGN(ResourceConfigValue);
     76 };
     77 
     78 /**
     79  * Represents a resource entry, which may have
     80  * varying values for each defined configuration.
     81  */
     82 class ResourceEntry {
     83 public:
     84     /**
     85      * The name of the resource. Immutable, as
     86      * this determines the order of this resource
     87      * when doing lookups.
     88      */
     89     const std::u16string name;
     90 
     91     /**
     92      * The entry ID for this resource.
     93      */
     94     Maybe<uint16_t> id;
     95 
     96     /**
     97      * Whether this resource is public (and must maintain the same entry ID across builds).
     98      */
     99     Symbol symbolStatus;
    100 
    101     /**
    102      * The resource's values for each configuration.
    103      */
    104     std::vector<std::unique_ptr<ResourceConfigValue>> values;
    105 
    106     ResourceEntry(const StringPiece16& name) : name(name.toString()) { }
    107 
    108     ResourceConfigValue* findValue(const ConfigDescription& config);
    109     ResourceConfigValue* findValue(const ConfigDescription& config, const StringPiece& product);
    110     ResourceConfigValue* findOrCreateValue(const ConfigDescription& config,
    111                                            const StringPiece& product);
    112     std::vector<ResourceConfigValue*> findAllValues(const ConfigDescription& config);
    113     std::vector<ResourceConfigValue*> findValuesIf(
    114             const std::function<bool(ResourceConfigValue*)>& f);
    115 
    116 
    117 private:
    118     DISALLOW_COPY_AND_ASSIGN(ResourceEntry);
    119 };
    120 
    121 /**
    122  * Represents a resource type, which holds entries defined
    123  * for this type.
    124  */
    125 class ResourceTableType {
    126 public:
    127     /**
    128      * The logical type of resource (string, drawable, layout, etc.).
    129      */
    130     const ResourceType type;
    131 
    132     /**
    133      * The type ID for this resource.
    134      */
    135     Maybe<uint8_t> id;
    136 
    137     /**
    138      * Whether this type is public (and must maintain the same
    139      * type ID across builds).
    140      */
    141     Symbol symbolStatus;
    142 
    143     /**
    144      * List of resources for this type.
    145      */
    146     std::vector<std::unique_ptr<ResourceEntry>> entries;
    147 
    148     explicit ResourceTableType(const ResourceType type) : type(type) { }
    149 
    150     ResourceEntry* findEntry(const StringPiece16& name);
    151     ResourceEntry* findOrCreateEntry(const StringPiece16& name);
    152 
    153 private:
    154     DISALLOW_COPY_AND_ASSIGN(ResourceTableType);
    155 };
    156 
    157 enum class PackageType {
    158     System,
    159     Vendor,
    160     App,
    161     Dynamic
    162 };
    163 
    164 class ResourceTablePackage {
    165 public:
    166     PackageType type = PackageType::App;
    167     Maybe<uint8_t> id;
    168     std::u16string name;
    169 
    170     std::vector<std::unique_ptr<ResourceTableType>> types;
    171 
    172     ResourceTablePackage() = default;
    173     ResourceTableType* findType(ResourceType type);
    174     ResourceTableType* findOrCreateType(const ResourceType type);
    175 
    176 private:
    177     DISALLOW_COPY_AND_ASSIGN(ResourceTablePackage);
    178 };
    179 
    180 /**
    181  * The container and index for all resources defined for an app. This gets
    182  * flattened into a binary resource table (resources.arsc).
    183  */
    184 class ResourceTable {
    185 public:
    186     ResourceTable() = default;
    187 
    188     /**
    189      * When a collision of resources occurs, this method decides which value to keep.
    190      * Returns -1 if the existing value should be chosen.
    191      * Returns 0 if the collision can not be resolved (error).
    192      * Returns 1 if the incoming value should be chosen.
    193      */
    194     static int resolveValueCollision(Value* existing, Value* incoming);
    195 
    196     bool addResource(const ResourceNameRef& name,
    197                      const ConfigDescription& config,
    198                      const StringPiece& product,
    199                      std::unique_ptr<Value> value,
    200                      IDiagnostics* diag);
    201 
    202     bool addResource(const ResourceNameRef& name,
    203                      const ResourceId resId,
    204                      const ConfigDescription& config,
    205                      const StringPiece& product,
    206                      std::unique_ptr<Value> value,
    207                      IDiagnostics* diag);
    208 
    209     bool addFileReference(const ResourceNameRef& name,
    210                               const ConfigDescription& config,
    211                               const Source& source,
    212                               const StringPiece16& path,
    213                               IDiagnostics* diag);
    214 
    215     bool addFileReferenceAllowMangled(const ResourceNameRef& name,
    216                                       const ConfigDescription& config,
    217                                       const Source& source,
    218                                       const StringPiece16& path,
    219                                       io::IFile* file,
    220                                       IDiagnostics* diag);
    221 
    222     /**
    223      * Same as addResource, but doesn't verify the validity of the name. This is used
    224      * when loading resources from an existing binary resource table that may have mangled
    225      * names.
    226      */
    227     bool addResourceAllowMangled(const ResourceNameRef& name,
    228                                  const ConfigDescription& config,
    229                                  const StringPiece& product,
    230                                  std::unique_ptr<Value> value,
    231                                  IDiagnostics* diag);
    232 
    233     bool addResourceAllowMangled(const ResourceNameRef& name,
    234                                  const ResourceId id,
    235                                  const ConfigDescription& config,
    236                                  const StringPiece& product,
    237                                  std::unique_ptr<Value> value,
    238                                  IDiagnostics* diag);
    239 
    240     bool setSymbolState(const ResourceNameRef& name,
    241                         const ResourceId resId,
    242                         const Symbol& symbol,
    243                         IDiagnostics* diag);
    244 
    245     bool setSymbolStateAllowMangled(const ResourceNameRef& name,
    246                                     const ResourceId resId,
    247                                     const Symbol& symbol,
    248                                     IDiagnostics* diag);
    249 
    250     struct SearchResult {
    251         ResourceTablePackage* package;
    252         ResourceTableType* type;
    253         ResourceEntry* entry;
    254     };
    255 
    256     Maybe<SearchResult> findResource(const ResourceNameRef& name);
    257 
    258     /**
    259      * The string pool used by this resource table. Values that reference strings must use
    260      * this pool to create their strings.
    261      *
    262      * NOTE: `stringPool` must come before `packages` so that it is destroyed after.
    263      * When `string pool` references are destroyed (as they will be when `packages`
    264      * is destroyed), they decrement a refCount, which would cause invalid
    265      * memory access if the pool was already destroyed.
    266      */
    267     StringPool stringPool;
    268 
    269     /**
    270      * The list of packages in this table, sorted alphabetically by package name.
    271      */
    272     std::vector<std::unique_ptr<ResourceTablePackage>> packages;
    273 
    274     /**
    275      * Returns the package struct with the given name, or nullptr if such a package does not
    276      * exist. The empty string is a valid package and typically is used to represent the
    277      * 'current' package before it is known to the ResourceTable.
    278      */
    279     ResourceTablePackage* findPackage(const StringPiece16& name);
    280 
    281     ResourceTablePackage* findPackageById(uint8_t id);
    282 
    283     ResourceTablePackage* createPackage(const StringPiece16& name, Maybe<uint8_t> id = {});
    284 
    285 private:
    286     ResourceTablePackage* findOrCreatePackage(const StringPiece16& name);
    287 
    288     bool addFileReferenceImpl(const ResourceNameRef& name,
    289                               const ConfigDescription& config,
    290                               const Source& source,
    291                               const StringPiece16& path,
    292                               io::IFile* file,
    293                               const char16_t* validChars,
    294                               IDiagnostics* diag);
    295 
    296     bool addResourceImpl(const ResourceNameRef& name,
    297                          ResourceId resId,
    298                          const ConfigDescription& config,
    299                          const StringPiece& product,
    300                          std::unique_ptr<Value> value,
    301                          const char16_t* validChars,
    302                          std::function<int(Value*,Value*)> conflictResolver,
    303                          IDiagnostics* diag);
    304 
    305     bool setSymbolStateImpl(const ResourceNameRef& name,
    306                             ResourceId resId,
    307                             const Symbol& symbol,
    308                             const char16_t* validChars,
    309                             IDiagnostics* diag);
    310 
    311     DISALLOW_COPY_AND_ASSIGN(ResourceTable);
    312 };
    313 
    314 } // namespace aapt
    315 
    316 #endif // AAPT_RESOURCE_TABLE_H
    317