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; OverlayableOverlayable62 Overlayable(const android::StringPiece& name, const android::StringPiece& actor) 63 : name(name.to_string()), actor(actor.to_string()) {} OverlayableOverlayable64 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 { OverlayableItemOverlayableItem76 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 ResourceConfigValue(const android::ConfigDescription & config,const android::StringPiece & product)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 ResourceEntry(const android::StringPiece & name)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> FindValuesIf(Func f)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 ResourceTableType(const ResourceType type)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; ResourceTable(bool validate_resources)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