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; DynamicPackageEntry(std::string && package_name,int package_id)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. GetTypeStringPool()73 inline const ResStringPool* GetTypeStringPool() const { return &type_string_pool_; } 74 75 // Returns the string pool where the names of resource entries are stored. GetKeyStringPool()76 inline const ResStringPool* GetKeyStringPool() const { return &key_string_pool_; } 77 GetPackageName()78 inline const std::string& GetPackageName() const { return package_name_; } 79 GetPackageId()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. IsDynamic()83 inline bool IsDynamic() const { return dynamic_; } 84 85 // Returns true if this package originates from a system provided resource. IsSystem()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. GetDynamicPackageMap()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. GetStringPool()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. IsSystem()160 inline bool IsSystem() const { return system_; } 161 162 // Returns a vector of LoadedPackage pointers, representing the packages in this LoadedArsc. GetPackages()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