blob: b0321214c6cc41d4b68aa39cdb4540cddf41155a [file] [log] [blame]
Adam Lesinski6f6ceb72014-11-14 14:48:12 -08001/*
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"
Adam Lesinski1ab598f2015-08-14 14:26:04 -070021#include "Diagnostics.h"
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080022#include "Resource.h"
23#include "ResourceValues.h"
24#include "Source.h"
25#include "StringPool.h"
Adam Lesinski355f2852016-02-13 20:26:45 -080026#include "io/File.h"
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080027
Adam Lesinskid5083f62017-01-16 15:07:21 -080028#include "android-base/macros.h"
29#include "androidfw/StringPiece.h"
30
Adam Lesinski458b8772016-04-25 14:20:21 -070031#include <functional>
Adam Lesinskie4bb9eb2016-02-12 22:18:51 -080032#include <map>
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080033#include <memory>
34#include <string>
35#include <tuple>
Adam Lesinskie4bb9eb2016-02-12 22:18:51 -080036#include <unordered_map>
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080037#include <vector>
38
39namespace aapt {
40
Adam Lesinski9e10ac72015-10-16 14:37:48 -070041enum class SymbolState {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070042 kUndefined,
43 kPrivate,
44 kPublic,
Adam Lesinski9e10ac72015-10-16 14:37:48 -070045};
46
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080047/**
48 * The Public status of a resource.
49 */
Adam Lesinski9e10ac72015-10-16 14:37:48 -070050struct Symbol {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070051 SymbolState state = SymbolState::kUndefined;
52 Source source;
53 std::string comment;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080054};
55
Adam Lesinskie4bb9eb2016-02-12 22:18:51 -080056class ResourceConfigValue {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070057 public:
58 /**
59 * The configuration for which this value is defined.
60 */
61 const ConfigDescription config;
Adam Lesinskie4bb9eb2016-02-12 22:18:51 -080062
Adam Lesinskicacb28f2016-10-19 12:18:14 -070063 /**
64 * The product for which this value is defined.
65 */
66 const std::string product;
Adam Lesinskie4bb9eb2016-02-12 22:18:51 -080067
Adam Lesinskicacb28f2016-10-19 12:18:14 -070068 /**
69 * The actual Value.
70 */
71 std::unique_ptr<Value> value;
Adam Lesinskie4bb9eb2016-02-12 22:18:51 -080072
Adam Lesinskid5083f62017-01-16 15:07:21 -080073 ResourceConfigValue(const ConfigDescription& config, const android::StringPiece& product)
74 : config(config), product(product.to_string()) {}
Adam Lesinskie4bb9eb2016-02-12 22:18:51 -080075
Adam Lesinskicacb28f2016-10-19 12:18:14 -070076 private:
77 DISALLOW_COPY_AND_ASSIGN(ResourceConfigValue);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080078};
79
80/**
81 * Represents a resource entry, which may have
82 * varying values for each defined configuration.
83 */
Adam Lesinskie4bb9eb2016-02-12 22:18:51 -080084class ResourceEntry {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070085 public:
86 /**
87 * The name of the resource. Immutable, as
88 * this determines the order of this resource
89 * when doing lookups.
90 */
91 const std::string name;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080092
Adam Lesinskicacb28f2016-10-19 12:18:14 -070093 /**
94 * The entry ID for this resource.
95 */
96 Maybe<uint16_t> id;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080097
Adam Lesinskicacb28f2016-10-19 12:18:14 -070098 /**
99 * Whether this resource is public (and must maintain the same entry ID across
100 * builds).
101 */
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700102 Symbol symbol_status;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800103
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700104 /**
105 * The resource's values for each configuration.
106 */
107 std::vector<std::unique_ptr<ResourceConfigValue>> values;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800108
Adam Lesinskid5083f62017-01-16 15:07:21 -0800109 explicit ResourceEntry(const android::StringPiece& name) : name(name.to_string()) {}
Adam Lesinskie4bb9eb2016-02-12 22:18:51 -0800110
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700111 ResourceConfigValue* FindValue(const ConfigDescription& config);
112 ResourceConfigValue* FindValue(const ConfigDescription& config,
Adam Lesinskid5083f62017-01-16 15:07:21 -0800113 const android::StringPiece& product);
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700114 ResourceConfigValue* FindOrCreateValue(const ConfigDescription& config,
Adam Lesinskid5083f62017-01-16 15:07:21 -0800115 const android::StringPiece& product);
Adam Lesinskib1afa072017-03-29 13:52:38 -0700116 std::vector<ResourceConfigValue*> FindAllValues(const ConfigDescription& config);
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700117 std::vector<ResourceConfigValue*> FindValuesIf(
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700118 const std::function<bool(ResourceConfigValue*)>& f);
Adam Lesinski458b8772016-04-25 14:20:21 -0700119
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700120 private:
121 DISALLOW_COPY_AND_ASSIGN(ResourceEntry);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800122};
123
124/**
125 * Represents a resource type, which holds entries defined
126 * for this type.
127 */
Adam Lesinskie4bb9eb2016-02-12 22:18:51 -0800128class ResourceTableType {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700129 public:
130 /**
131 * The logical type of resource (string, drawable, layout, etc.).
132 */
133 const ResourceType type;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800134
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700135 /**
136 * The type ID for this resource.
137 */
138 Maybe<uint8_t> id;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800139
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700140 /**
141 * Whether this type is public (and must maintain the same
142 * type ID across builds).
143 */
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700144 Symbol symbol_status;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800145
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700146 /**
147 * List of resources for this type.
148 */
149 std::vector<std::unique_ptr<ResourceEntry>> entries;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800150
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700151 explicit ResourceTableType(const ResourceType type) : type(type) {}
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700152
Adam Lesinskid5083f62017-01-16 15:07:21 -0800153 ResourceEntry* FindEntry(const android::StringPiece& name);
154 ResourceEntry* FindOrCreateEntry(const android::StringPiece& name);
Adam Lesinskie4bb9eb2016-02-12 22:18:51 -0800155
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700156 private:
157 DISALLOW_COPY_AND_ASSIGN(ResourceTableType);
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700158};
159
Adam Lesinskie4bb9eb2016-02-12 22:18:51 -0800160class ResourceTablePackage {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700161 public:
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700162 Maybe<uint8_t> id;
163 std::string name;
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700164
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700165 std::vector<std::unique_ptr<ResourceTableType>> types;
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700166
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700167 ResourceTablePackage() = default;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700168 ResourceTableType* FindType(ResourceType type);
169 ResourceTableType* FindOrCreateType(const ResourceType type);
Adam Lesinskie4bb9eb2016-02-12 22:18:51 -0800170
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700171 private:
172 DISALLOW_COPY_AND_ASSIGN(ResourceTablePackage);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800173};
174
175/**
176 * The container and index for all resources defined for an app. This gets
177 * flattened into a binary resource table (resources.arsc).
178 */
179class ResourceTable {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700180 public:
181 ResourceTable() = default;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800182
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700183 enum class CollisionResult { kKeepOriginal, kConflict, kTakeNew };
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700184
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700185 using CollisionResolverFunc = std::function<CollisionResult(Value*, Value*)>;
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700186
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700187 /**
188 * When a collision of resources occurs, this method decides which value to
189 * keep.
190 */
Adam Lesinskib1afa072017-03-29 13:52:38 -0700191 static CollisionResult ResolveValueCollision(Value* existing, Value* incoming);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800192
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700193 bool AddResource(const ResourceNameRef& name, const ConfigDescription& config,
Adam Lesinskid5083f62017-01-16 15:07:21 -0800194 const android::StringPiece& product, std::unique_ptr<Value> value,
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700195 IDiagnostics* diag);
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700196
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700197 bool AddResource(const ResourceNameRef& name, const ResourceId& res_id,
Adam Lesinskid5083f62017-01-16 15:07:21 -0800198 const ConfigDescription& config, const android::StringPiece& product,
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700199 std::unique_ptr<Value> value, IDiagnostics* diag);
Adam Lesinskie4bb9eb2016-02-12 22:18:51 -0800200
Adam Lesinskid5083f62017-01-16 15:07:21 -0800201 bool AddFileReference(const ResourceNameRef& name, const ConfigDescription& config,
202 const Source& source, const android::StringPiece& path, IDiagnostics* diag);
Adam Lesinskifb48d292015-11-07 15:52:13 -0800203
Adam Lesinskid5083f62017-01-16 15:07:21 -0800204 bool AddFileReferenceAllowMangled(const ResourceNameRef& name, const ConfigDescription& config,
205 const Source& source, const android::StringPiece& path,
206 io::IFile* file, IDiagnostics* diag);
Adam Lesinskie78fd612015-10-22 12:48:43 -0700207
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700208 /**
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700209 * Same as AddResource, but doesn't verify the validity of the name. This is
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700210 * used
211 * when loading resources from an existing binary resource table that may have
212 * mangled
213 * names.
214 */
Adam Lesinskid5083f62017-01-16 15:07:21 -0800215 bool AddResourceAllowMangled(const ResourceNameRef& name, const ConfigDescription& config,
216 const android::StringPiece& product, std::unique_ptr<Value> value,
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700217 IDiagnostics* diag);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800218
Adam Lesinskid5083f62017-01-16 15:07:21 -0800219 bool AddResourceAllowMangled(const ResourceNameRef& name, const ResourceId& id,
220 const ConfigDescription& config, const android::StringPiece& product,
221 std::unique_ptr<Value> value, IDiagnostics* diag);
Adam Lesinski769de982015-04-10 19:43:55 -0700222
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700223 bool SetSymbolState(const ResourceNameRef& name, const ResourceId& res_id,
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700224 const Symbol& symbol, IDiagnostics* diag);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800225
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700226 bool SetSymbolStateAllowMangled(const ResourceNameRef& name,
227 const ResourceId& res_id,
228 const Symbol& symbol, IDiagnostics* diag);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800229
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700230 struct SearchResult {
231 ResourceTablePackage* package;
232 ResourceTableType* type;
233 ResourceEntry* entry;
234 };
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700235
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700236 Maybe<SearchResult> FindResource(const ResourceNameRef& name);
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700237
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700238 /**
Adam Lesinskiceb9b2f2017-02-16 12:05:42 -0800239 * Returns the package struct with the given name, or nullptr if such a
240 * package does not
241 * exist. The empty string is a valid package and typically is used to
242 * represent the
243 * 'current' package before it is known to the ResourceTable.
244 */
245 ResourceTablePackage* FindPackage(const android::StringPiece& name);
246
247 ResourceTablePackage* FindPackageById(uint8_t id);
248
249 ResourceTablePackage* CreatePackage(const android::StringPiece& name, Maybe<uint8_t> id = {});
250
251 /**
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700252 * The string pool used by this resource table. Values that reference strings
253 * must use
254 * this pool to create their strings.
255 *
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700256 * NOTE: `string_pool` must come before `packages` so that it is destroyed
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700257 * after.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700258 * When `string_pool` references are destroyed (as they will be when
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700259 * `packages`
260 * is destroyed), they decrement a refCount, which would cause invalid
261 * memory access if the pool was already destroyed.
262 */
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700263 StringPool string_pool;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800264
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700265 /**
266 * The list of packages in this table, sorted alphabetically by package name.
267 */
268 std::vector<std::unique_ptr<ResourceTablePackage>> packages;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800269
Adam Lesinskiceb9b2f2017-02-16 12:05:42 -0800270 // Set of dynamic packages that this table may reference. Their package names get encoded
271 // into the resources.arsc along with their compile-time assigned IDs.
272 std::map<size_t, std::string> included_packages_;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700273
274 private:
Adam Lesinskib1afa072017-03-29 13:52:38 -0700275 // The function type that validates a symbol name. Returns a non-empty StringPiece representing
276 // the offending character (which may be more than one byte in UTF-8). Returns an empty string
277 // if the name was valid.
278 using NameValidator = android::StringPiece(const android::StringPiece&);
279
Adam Lesinskid5083f62017-01-16 15:07:21 -0800280 ResourceTablePackage* FindOrCreatePackage(const android::StringPiece& name);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700281
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700282 bool AddResourceImpl(const ResourceNameRef& name, const ResourceId& res_id,
Adam Lesinskid5083f62017-01-16 15:07:21 -0800283 const ConfigDescription& config, const android::StringPiece& product,
Adam Lesinskib1afa072017-03-29 13:52:38 -0700284 std::unique_ptr<Value> value, NameValidator name_validator,
Adam Lesinskid5083f62017-01-16 15:07:21 -0800285 const CollisionResolverFunc& conflict_resolver, IDiagnostics* diag);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700286
Adam Lesinskid5083f62017-01-16 15:07:21 -0800287 bool AddFileReferenceImpl(const ResourceNameRef& name, const ConfigDescription& config,
288 const Source& source, const android::StringPiece& path, io::IFile* file,
Adam Lesinskib1afa072017-03-29 13:52:38 -0700289 NameValidator name_validator, IDiagnostics* diag);
Adam Lesinskie4bb9eb2016-02-12 22:18:51 -0800290
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700291 bool SetSymbolStateImpl(const ResourceNameRef& name, const ResourceId& res_id,
Adam Lesinskib1afa072017-03-29 13:52:38 -0700292 const Symbol& symbol, NameValidator name_validator, IDiagnostics* diag);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700293
294 DISALLOW_COPY_AND_ASSIGN(ResourceTable);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800295};
296
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700297} // namespace aapt
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800298
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700299#endif // AAPT_RESOURCE_TABLE_H