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 ResourceConfigValue(const ConfigDescription & config,const StringPiece & product)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 ResourceEntry(const StringPiece16 & name)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 ResourceTableType(const ResourceType type)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