Home | History | Annotate | Download | only in androidfw
      1 /*
      2  * Copyright (C) 2016 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 LOADEDARSC_H_
     18 #define LOADEDARSC_H_
     19 
     20 #include <memory>
     21 #include <set>
     22 #include <vector>
     23 
     24 #include "android-base/macros.h"
     25 
     26 #include "androidfw/ByteBucketArray.h"
     27 #include "androidfw/Chunk.h"
     28 #include "androidfw/ResourceTypes.h"
     29 #include "androidfw/Util.h"
     30 
     31 namespace android {
     32 
     33 class DynamicPackageEntry {
     34  public:
     35   DynamicPackageEntry() = default;
     36   DynamicPackageEntry(std::string&& package_name, int package_id)
     37       : package_name(std::move(package_name)), package_id(package_id) {}
     38 
     39   std::string package_name;
     40   int package_id = 0;
     41 };
     42 
     43 struct LoadedArscEntry {
     44   // A pointer to the resource table entry for this resource.
     45   // If the size of the entry is > sizeof(ResTable_entry), it can be cast to
     46   // a ResTable_map_entry and processed as a bag/map.
     47   const ResTable_entry* entry = nullptr;
     48 
     49   // The dynamic package ID map for the package from which this resource came from.
     50   const DynamicRefTable* dynamic_ref_table = nullptr;
     51 
     52   // The string pool reference to the type's name. This uses a different string pool than
     53   // the global string pool, but this is hidden from the caller.
     54   StringPoolRef type_string_ref;
     55 
     56   // The string pool reference to the entry's name. This uses a different string pool than
     57   // the global string pool, but this is hidden from the caller.
     58   StringPoolRef entry_string_ref;
     59 };
     60 
     61 struct TypeSpec;
     62 class LoadedArsc;
     63 
     64 class LoadedPackage {
     65   friend class LoadedArsc;
     66 
     67  public:
     68   bool FindEntry(uint8_t type_idx, uint16_t entry_idx, const ResTable_config& config,
     69                  LoadedArscEntry* out_entry, ResTable_config* out_selected_config,
     70                  uint32_t* out_flags) const;
     71 
     72   // Returns the string pool where type names are stored.
     73   inline const ResStringPool* GetTypeStringPool() const { return &type_string_pool_; }
     74 
     75   // Returns the string pool where the names of resource entries are stored.
     76   inline const ResStringPool* GetKeyStringPool() const { return &key_string_pool_; }
     77 
     78   inline const std::string& GetPackageName() const { return package_name_; }
     79 
     80   inline int GetPackageId() const { return package_id_; }
     81 
     82   // Returns true if this package is dynamic (shared library) and needs to have an ID assigned.
     83   inline bool IsDynamic() const { return dynamic_; }
     84 
     85   // Returns true if this package originates from a system provided resource.
     86   inline bool IsSystem() const { return system_; }
     87 
     88   // Returns the map of package name to package ID used in this LoadedPackage. At runtime, a
     89   // package could have been assigned a different package ID than what this LoadedPackage was
     90   // compiled with. AssetManager rewrites the package IDs so that they are compatible at runtime.
     91   inline const std::vector<DynamicPackageEntry>& GetDynamicPackageMap() const {
     92     return dynamic_package_map_;
     93   }
     94 
     95   // Populates a set of ResTable_config structs, possibly excluding configurations defined for
     96   // the mipmap type.
     97   void CollectConfigurations(bool exclude_mipmap, std::set<ResTable_config>* out_configs) const;
     98 
     99   // Populates a set of strings representing locales.
    100   // If `canonicalize` is set to true, each locale is transformed into its canonical format
    101   // before being inserted into the set. This may cause some equivalent locales to de-dupe.
    102   void CollectLocales(bool canonicalize, std::set<std::string>* out_locales) const;
    103 
    104   // Finds the entry with the specified type name and entry name. The names are in UTF-16 because
    105   // the underlying ResStringPool API expects this. For now this is acceptable, but since
    106   // the default policy in AAPT2 is to build UTF-8 string pools, this needs to change.
    107   // Returns a partial resource ID, with the package ID left as 0x00. The caller is responsible
    108   // for patching the correct package ID to the resource ID.
    109   uint32_t FindEntryByName(const std::u16string& type_name, const std::u16string& entry_name) const;
    110 
    111  private:
    112   DISALLOW_COPY_AND_ASSIGN(LoadedPackage);
    113 
    114   static std::unique_ptr<LoadedPackage> Load(const Chunk& chunk);
    115 
    116   LoadedPackage() = default;
    117 
    118   ResStringPool type_string_pool_;
    119   ResStringPool key_string_pool_;
    120   std::string package_name_;
    121   int package_id_ = -1;
    122   int type_id_offset_ = 0;
    123   bool dynamic_ = false;
    124   bool system_ = false;
    125 
    126   ByteBucketArray<util::unique_cptr<TypeSpec>> type_specs_;
    127   std::vector<DynamicPackageEntry> dynamic_package_map_;
    128 };
    129 
    130 // Read-only view into a resource table. This class validates all data
    131 // when loading, including offsets and lengths.
    132 class LoadedArsc {
    133  public:
    134   // Load a resource table from memory pointed to by `data` of size `len`.
    135   // The lifetime of `data` must out-live the LoadedArsc returned from this method.
    136   // If `system` is set to true, the LoadedArsc is considered as a system provided resource.
    137   // If `load_as_shared_library` is set to true, the application package (0x7f) is treated
    138   // as a shared library (0x00). When loaded into an AssetManager, the package will be assigned an
    139   // ID.
    140   static std::unique_ptr<const LoadedArsc> Load(const void* data, size_t len, bool system = false,
    141                                                 bool load_as_shared_library = false);
    142 
    143   ~LoadedArsc();
    144 
    145   // Returns the string pool where all string resource values
    146   // (Res_value::dataType == Res_value::TYPE_STRING) are indexed.
    147   inline const ResStringPool* GetStringPool() const { return &global_string_pool_; }
    148 
    149   // Finds the resource with ID `resid` with the best value for configuration `config`.
    150   // The parameter `out_entry` will be filled with the resulting resource entry.
    151   // The resource entry can be a simple entry (ResTable_entry) or a complex bag
    152   // (ResTable_entry_map).
    153   bool FindEntry(uint32_t resid, const ResTable_config& config, LoadedArscEntry* out_entry,
    154                  ResTable_config* selected_config, uint32_t* out_flags) const;
    155 
    156   // Gets a pointer to the name of the package in `resid`, or nullptr if the package doesn't exist.
    157   const LoadedPackage* GetPackageForId(uint32_t resid) const;
    158 
    159   // Returns true if this is a system provided resource.
    160   inline bool IsSystem() const { return system_; }
    161 
    162   // Returns a vector of LoadedPackage pointers, representing the packages in this LoadedArsc.
    163   inline const std::vector<std::unique_ptr<const LoadedPackage>>& GetPackages() const {
    164     return packages_;
    165   }
    166 
    167  private:
    168   DISALLOW_COPY_AND_ASSIGN(LoadedArsc);
    169 
    170   LoadedArsc() = default;
    171   bool LoadTable(const Chunk& chunk, bool load_as_shared_library);
    172 
    173   ResStringPool global_string_pool_;
    174   std::vector<std::unique_ptr<const LoadedPackage>> packages_;
    175   bool system_ = false;
    176 };
    177 
    178 }  // namespace android
    179 
    180 #endif /* LOADEDARSC_H_ */
    181