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