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 "Diagnostics.h"
     21 #include "Resource.h"
     22 #include "ResourceValues.h"
     23 #include "Source.h"
     24 #include "StringPool.h"
     25 #include "io/File.h"
     26 
     27 #include "android-base/macros.h"
     28 #include "androidfw/ConfigDescription.h"
     29 #include "androidfw/StringPiece.h"
     30 
     31 #include <functional>
     32 #include <map>
     33 #include <memory>
     34 #include <string>
     35 #include <tuple>
     36 #include <unordered_map>
     37 #include <vector>
     38 
     39 namespace aapt {
     40 
     41 // The Public status of a resource.
     42 struct Visibility {
     43   enum class Level {
     44     kUndefined,
     45     kPrivate,
     46     kPublic,
     47   };
     48 
     49   Level level = Level::kUndefined;
     50   Source source;
     51   std::string comment;
     52 };
     53 
     54 // Represents <add-resource> in an overlay.
     55 struct AllowNew {
     56   Source source;
     57   std::string comment;
     58 };
     59 
     60 struct Overlayable {
     61   Overlayable() = default;
     62    Overlayable(const android::StringPiece& name, const android::StringPiece& actor)
     63        : name(name.to_string()), actor(actor.to_string()) {}
     64    Overlayable(const android::StringPiece& name, const android::StringPiece& actor,
     65                     const Source& source)
     66        : name(name.to_string()), actor(actor.to_string()), source(source ){}
     67 
     68   static const char* kActorScheme;
     69   std::string name;
     70   std::string actor;
     71   Source source;
     72 };
     73 
     74 // Represents a declaration that a resource is overlayable at runtime.
     75 struct OverlayableItem {
     76   explicit OverlayableItem(const std::shared_ptr<Overlayable>& overlayable)
     77       : overlayable(overlayable) {}
     78 
     79   // Represents the types overlays that are allowed to overlay the resource.
     80   typedef uint32_t PolicyFlags;
     81   enum Policy : uint32_t {
     82     kNone = 0x00000000,
     83 
     84     // The resource can be overlaid by any overlay.
     85     kPublic = 0x00000001,
     86 
     87     // The resource can be overlaid by any overlay on the system partition.
     88     kSystem = 0x00000002,
     89 
     90     // The resource can be overlaid by any overlay on the vendor partition.
     91     kVendor = 0x00000004,
     92 
     93     // The resource can be overlaid by any overlay on the product partition.
     94     kProduct = 0x00000008,
     95 
     96     // The resource can be overlaid by any overlay signed with the same signature as its actor.
     97     kSignature = 0x00000010,
     98 
     99     // The resource can be overlaid by any overlay on the odm partition.
    100     kOdm = 0x00000020,
    101 
    102     // The resource can be overlaid by any overlay on the oem partition.
    103     kOem = 0x00000040,
    104   };
    105 
    106   std::shared_ptr<Overlayable> overlayable;
    107   PolicyFlags policies = Policy::kNone;
    108   std::string comment;
    109   Source source;
    110 };
    111 
    112 class ResourceConfigValue {
    113  public:
    114   // The configuration for which this value is defined.
    115   const android::ConfigDescription config;
    116 
    117   // The product for which this value is defined.
    118   const std::string product;
    119 
    120   // The actual Value.
    121   std::unique_ptr<Value> value;
    122 
    123   ResourceConfigValue(const android::ConfigDescription& config, const android::StringPiece& product)
    124       : config(config), product(product.to_string()) {}
    125 
    126  private:
    127   DISALLOW_COPY_AND_ASSIGN(ResourceConfigValue);
    128 };
    129 
    130 // Represents a resource entry, which may have varying values for each defined configuration.
    131 class ResourceEntry {
    132  public:
    133   // The name of the resource. Immutable, as this determines the order of this resource
    134   // when doing lookups.
    135   const std::string name;
    136 
    137   // The entry ID for this resource (the EEEE in 0xPPTTEEEE).
    138   Maybe<uint16_t> id;
    139 
    140   // Whether this resource is public (and must maintain the same entry ID across builds).
    141   Visibility visibility;
    142 
    143   Maybe<AllowNew> allow_new;
    144 
    145   // The declarations of this resource as overlayable for RROs
    146   Maybe<OverlayableItem> overlayable_item;
    147 
    148   // The resource's values for each configuration.
    149   std::vector<std::unique_ptr<ResourceConfigValue>> values;
    150 
    151   explicit ResourceEntry(const android::StringPiece& name) : name(name.to_string()) {}
    152 
    153   ResourceConfigValue* FindValue(const android::ConfigDescription& config);
    154 
    155   ResourceConfigValue* FindValue(const android::ConfigDescription& config,
    156                                  const android::StringPiece& product);
    157 
    158   ResourceConfigValue* FindOrCreateValue(const android::ConfigDescription& config,
    159                                          const android::StringPiece& product);
    160   std::vector<ResourceConfigValue*> FindAllValues(const android::ConfigDescription& config);
    161 
    162   template <typename Func>
    163   std::vector<ResourceConfigValue*> FindValuesIf(Func f) {
    164     std::vector<ResourceConfigValue*> results;
    165     for (auto& config_value : values) {
    166       if (f(config_value.get())) {
    167         results.push_back(config_value.get());
    168       }
    169     }
    170     return results;
    171   }
    172 
    173   bool HasDefaultValue() const;
    174 
    175  private:
    176   DISALLOW_COPY_AND_ASSIGN(ResourceEntry);
    177 };
    178 
    179 // Represents a resource type (eg. string, drawable, layout, etc.) containing resource entries.
    180 class ResourceTableType {
    181  public:
    182   // The logical type of resource (string, drawable, layout, etc.).
    183   const ResourceType type;
    184 
    185   // The type ID for this resource (the TT in 0xPPTTEEEE).
    186   Maybe<uint8_t> id;
    187 
    188   // Whether this type is public (and must maintain the same type ID across builds).
    189   Visibility::Level visibility_level = Visibility::Level::kUndefined;
    190 
    191   // List of resources for this type.
    192   std::vector<std::unique_ptr<ResourceEntry>> entries;
    193 
    194   explicit ResourceTableType(const ResourceType type) : type(type) {}
    195 
    196   ResourceEntry* FindEntry(const android::StringPiece& name,
    197                            Maybe<uint16_t> id = Maybe<uint16_t>());
    198   ResourceEntry* FindOrCreateEntry(const android::StringPiece& name,
    199                                    Maybe<uint16_t> id = Maybe<uint16_t>());
    200 
    201  private:
    202   DISALLOW_COPY_AND_ASSIGN(ResourceTableType);
    203 };
    204 
    205 class ResourceTablePackage {
    206  public:
    207   std::string name;
    208 
    209   // The package ID (the PP in 0xPPTTEEEE).
    210   Maybe<uint8_t> id;
    211 
    212   std::vector<std::unique_ptr<ResourceTableType>> types;
    213 
    214   ResourceTablePackage() = default;
    215   ResourceTableType* FindType(ResourceType type, Maybe<uint8_t> id = Maybe<uint8_t>());
    216   ResourceTableType* FindOrCreateType(const ResourceType type,
    217                                       Maybe<uint8_t> id = Maybe<uint8_t>());
    218 
    219  private:
    220   DISALLOW_COPY_AND_ASSIGN(ResourceTablePackage);
    221 };
    222 
    223 // The container and index for all resources defined for an app.
    224 class ResourceTable {
    225  public:
    226   ResourceTable() = default;
    227   explicit ResourceTable(bool validate_resources) : validate_resources_(validate_resources) {}
    228 
    229   enum class CollisionResult { kKeepBoth, kKeepOriginal, kConflict, kTakeNew };
    230 
    231   using CollisionResolverFunc = std::function<CollisionResult(Value*, Value*, bool)>;
    232 
    233   // When a collision of resources occurs, this method decides which value to keep.
    234   static CollisionResult ResolveValueCollision(Value* existing, Value* incoming, bool overlay);
    235 
    236   // When a collision of resources occurs, this method keeps both values
    237   static CollisionResult IgnoreCollision(Value* existing, Value* incoming, bool overlay);
    238 
    239   bool AddResource(const ResourceNameRef& name, const android::ConfigDescription& config,
    240                    const android::StringPiece& product, std::unique_ptr<Value> value,
    241                    IDiagnostics* diag);
    242 
    243   bool AddResourceWithId(const ResourceNameRef& name, const ResourceId& res_id,
    244                          const android::ConfigDescription& config,
    245                          const android::StringPiece& product, std::unique_ptr<Value> value,
    246                          IDiagnostics* diag);
    247 
    248   // Same as AddResource, but doesn't verify the validity of the name. This is used
    249   // when loading resources from an existing binary resource table that may have mangled names.
    250   bool AddResourceMangled(const ResourceNameRef& name, const android::ConfigDescription& config,
    251                           const android::StringPiece& product, std::unique_ptr<Value> value,
    252                           IDiagnostics* diag);
    253 
    254   bool AddResourceWithIdMangled(const ResourceNameRef& name, const ResourceId& id,
    255                                 const android::ConfigDescription& config,
    256                                 const android::StringPiece& product, std::unique_ptr<Value> value,
    257                                 IDiagnostics* diag);
    258 
    259   bool GetValidateResources();
    260 
    261   bool SetVisibility(const ResourceNameRef& name, const Visibility& visibility, IDiagnostics* diag);
    262   bool SetVisibilityWithId(const ResourceNameRef& name, const Visibility& visibility,
    263                            const ResourceId& res_id, IDiagnostics* diag);
    264   bool SetVisibilityWithIdMangled(const ResourceNameRef& name, const Visibility& visibility,
    265                                   const ResourceId& res_id, IDiagnostics* diag);
    266 
    267   bool SetOverlayable(const ResourceNameRef& name, const OverlayableItem& overlayable,
    268                       IDiagnostics *diag);
    269 
    270   bool SetAllowNew(const ResourceNameRef& name, const AllowNew& allow_new, IDiagnostics* diag);
    271   bool SetAllowNewMangled(const ResourceNameRef& name, const AllowNew& allow_new,
    272                           IDiagnostics* diag);
    273 
    274   struct SearchResult {
    275     ResourceTablePackage* package;
    276     ResourceTableType* type;
    277     ResourceEntry* entry;
    278   };
    279 
    280   Maybe<SearchResult> FindResource(const ResourceNameRef& name) const;
    281 
    282   // Returns the package struct with the given name, or nullptr if such a package does not
    283   // exist. The empty string is a valid package and typically is used to represent the
    284   // 'current' package before it is known to the ResourceTable.
    285   ResourceTablePackage* FindPackage(const android::StringPiece& name) const;
    286 
    287   ResourceTablePackage* FindPackageById(uint8_t id) const;
    288 
    289   ResourceTablePackage* CreatePackage(const android::StringPiece& name, Maybe<uint8_t> id = {});
    290 
    291   // Attempts to find a package having the specified name and ID. If not found, a new package
    292   // of the specified parameters is created and returned.
    293   ResourceTablePackage* CreatePackageAllowingDuplicateNames(const android::StringPiece& name,
    294                                                             const Maybe<uint8_t> id);
    295 
    296   std::unique_ptr<ResourceTable> Clone() const;
    297 
    298   // The string pool used by this resource table. Values that reference strings must use
    299   // this pool to create their strings.
    300   // NOTE: `string_pool` must come before `packages` so that it is destroyed after.
    301   // When `string_pool` references are destroyed (as they will be when `packages` is destroyed),
    302   // they decrement a refCount, which would cause invalid memory access if the pool was already
    303   // destroyed.
    304   StringPool string_pool;
    305 
    306   // The list of packages in this table, sorted alphabetically by package name and increasing
    307   // package ID (missing ID being the lowest).
    308   std::vector<std::unique_ptr<ResourceTablePackage>> packages;
    309 
    310   // Set of dynamic packages that this table may reference. Their package names get encoded
    311   // into the resources.arsc along with their compile-time assigned IDs.
    312   std::map<size_t, std::string> included_packages_;
    313 
    314  private:
    315   // The function type that validates a symbol name. Returns a non-empty StringPiece representing
    316   // the offending character (which may be more than one byte in UTF-8). Returns an empty string
    317   // if the name was valid.
    318   using NameValidator = android::StringPiece(const android::StringPiece&);
    319 
    320   ResourceTablePackage* FindOrCreatePackage(const android::StringPiece& name);
    321 
    322   bool ValidateName(NameValidator validator, const ResourceNameRef& name, const Source& source,
    323                     IDiagnostics* diag);
    324 
    325   bool AddResourceImpl(const ResourceNameRef& name, const ResourceId& res_id,
    326                        const android::ConfigDescription& config,
    327                        const android::StringPiece& product, std::unique_ptr<Value> value,
    328                        NameValidator name_validator, const CollisionResolverFunc& conflict_resolver,
    329                        IDiagnostics* diag);
    330 
    331   bool SetVisibilityImpl(const ResourceNameRef& name, const Visibility& visibility,
    332                          const ResourceId& res_id, NameValidator name_validator,
    333                          IDiagnostics* diag);
    334 
    335   bool SetAllowNewImpl(const ResourceNameRef& name, const AllowNew& allow_new,
    336                        NameValidator name_validator, IDiagnostics* diag);
    337 
    338   bool SetOverlayableImpl(const ResourceNameRef &name, const OverlayableItem& overlayable,
    339                           NameValidator name_validator, IDiagnostics *diag);
    340 
    341   // Controls whether the table validates resource names and prevents duplicate resource names
    342   bool validate_resources_ = true;
    343 
    344   DISALLOW_COPY_AND_ASSIGN(ResourceTable);
    345 };
    346 
    347 }  // namespace aapt
    348 
    349 #endif  // AAPT_RESOURCE_TABLE_H
    350