blob: 0fe966c5089b9957d9f51832cd6c9a2b25e06846 [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 Lesinskicacb28f2016-10-19 12:18:14 -0700116 std::vector<ResourceConfigValue*> findAllValues(
117 const ConfigDescription& config);
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700118 std::vector<ResourceConfigValue*> FindValuesIf(
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700119 const std::function<bool(ResourceConfigValue*)>& f);
Adam Lesinski458b8772016-04-25 14:20:21 -0700120
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700121 private:
122 DISALLOW_COPY_AND_ASSIGN(ResourceEntry);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800123};
124
125/**
126 * Represents a resource type, which holds entries defined
127 * for this type.
128 */
Adam Lesinskie4bb9eb2016-02-12 22:18:51 -0800129class ResourceTableType {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700130 public:
131 /**
132 * The logical type of resource (string, drawable, layout, etc.).
133 */
134 const ResourceType type;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800135
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700136 /**
137 * The type ID for this resource.
138 */
139 Maybe<uint8_t> id;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800140
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700141 /**
142 * Whether this type is public (and must maintain the same
143 * type ID across builds).
144 */
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700145 Symbol symbol_status;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800146
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700147 /**
148 * List of resources for this type.
149 */
150 std::vector<std::unique_ptr<ResourceEntry>> entries;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800151
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700152 explicit ResourceTableType(const ResourceType type) : type(type) {}
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700153
Adam Lesinskid5083f62017-01-16 15:07:21 -0800154 ResourceEntry* FindEntry(const android::StringPiece& name);
155 ResourceEntry* FindOrCreateEntry(const android::StringPiece& name);
Adam Lesinskie4bb9eb2016-02-12 22:18:51 -0800156
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700157 private:
158 DISALLOW_COPY_AND_ASSIGN(ResourceTableType);
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700159};
160
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700161enum class PackageType { System, Vendor, App, Dynamic };
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700162
Adam Lesinskie4bb9eb2016-02-12 22:18:51 -0800163class ResourceTablePackage {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700164 public:
165 PackageType type = PackageType::App;
166 Maybe<uint8_t> id;
167 std::string name;
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700168
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700169 std::vector<std::unique_ptr<ResourceTableType>> types;
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700170
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700171 ResourceTablePackage() = default;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700172 ResourceTableType* FindType(ResourceType type);
173 ResourceTableType* FindOrCreateType(const ResourceType type);
Adam Lesinskie4bb9eb2016-02-12 22:18:51 -0800174
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700175 private:
176 DISALLOW_COPY_AND_ASSIGN(ResourceTablePackage);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800177};
178
179/**
180 * The container and index for all resources defined for an app. This gets
181 * flattened into a binary resource table (resources.arsc).
182 */
183class ResourceTable {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700184 public:
185 ResourceTable() = default;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800186
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700187 enum class CollisionResult { kKeepOriginal, kConflict, kTakeNew };
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700188
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700189 using CollisionResolverFunc = std::function<CollisionResult(Value*, Value*)>;
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700190
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700191 /**
192 * When a collision of resources occurs, this method decides which value to
193 * keep.
194 */
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700195 static CollisionResult ResolveValueCollision(Value* existing,
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700196 Value* incoming);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800197
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700198 bool AddResource(const ResourceNameRef& name, const ConfigDescription& config,
Adam Lesinskid5083f62017-01-16 15:07:21 -0800199 const android::StringPiece& product, std::unique_ptr<Value> value,
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700200 IDiagnostics* diag);
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700201
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700202 bool AddResource(const ResourceNameRef& name, const ResourceId& res_id,
Adam Lesinskid5083f62017-01-16 15:07:21 -0800203 const ConfigDescription& config, const android::StringPiece& product,
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700204 std::unique_ptr<Value> value, IDiagnostics* diag);
Adam Lesinskie4bb9eb2016-02-12 22:18:51 -0800205
Adam Lesinskid5083f62017-01-16 15:07:21 -0800206 bool AddFileReference(const ResourceNameRef& name, const ConfigDescription& config,
207 const Source& source, const android::StringPiece& path, IDiagnostics* diag);
Adam Lesinskifb48d292015-11-07 15:52:13 -0800208
Adam Lesinskid5083f62017-01-16 15:07:21 -0800209 bool AddFileReferenceAllowMangled(const ResourceNameRef& name, const ConfigDescription& config,
210 const Source& source, const android::StringPiece& path,
211 io::IFile* file, IDiagnostics* diag);
Adam Lesinskie78fd612015-10-22 12:48:43 -0700212
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700213 /**
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700214 * Same as AddResource, but doesn't verify the validity of the name. This is
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700215 * used
216 * when loading resources from an existing binary resource table that may have
217 * mangled
218 * names.
219 */
Adam Lesinskid5083f62017-01-16 15:07:21 -0800220 bool AddResourceAllowMangled(const ResourceNameRef& name, const ConfigDescription& config,
221 const android::StringPiece& product, std::unique_ptr<Value> value,
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700222 IDiagnostics* diag);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800223
Adam Lesinskid5083f62017-01-16 15:07:21 -0800224 bool AddResourceAllowMangled(const ResourceNameRef& name, const ResourceId& id,
225 const ConfigDescription& config, const android::StringPiece& product,
226 std::unique_ptr<Value> value, IDiagnostics* diag);
Adam Lesinski769de982015-04-10 19:43:55 -0700227
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700228 bool SetSymbolState(const ResourceNameRef& name, const ResourceId& res_id,
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700229 const Symbol& symbol, IDiagnostics* diag);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800230
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700231 bool SetSymbolStateAllowMangled(const ResourceNameRef& name,
232 const ResourceId& res_id,
233 const Symbol& symbol, IDiagnostics* diag);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800234
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700235 struct SearchResult {
236 ResourceTablePackage* package;
237 ResourceTableType* type;
238 ResourceEntry* entry;
239 };
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700240
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700241 Maybe<SearchResult> FindResource(const ResourceNameRef& name);
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700242
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700243 /**
244 * The string pool used by this resource table. Values that reference strings
245 * must use
246 * this pool to create their strings.
247 *
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700248 * NOTE: `string_pool` must come before `packages` so that it is destroyed
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700249 * after.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700250 * When `string_pool` references are destroyed (as they will be when
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700251 * `packages`
252 * is destroyed), they decrement a refCount, which would cause invalid
253 * memory access if the pool was already destroyed.
254 */
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700255 StringPool string_pool;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800256
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700257 /**
258 * The list of packages in this table, sorted alphabetically by package name.
259 */
260 std::vector<std::unique_ptr<ResourceTablePackage>> packages;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800261
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700262 /**
263 * Returns the package struct with the given name, or nullptr if such a
264 * package does not
265 * exist. The empty string is a valid package and typically is used to
266 * represent the
267 * 'current' package before it is known to the ResourceTable.
268 */
Adam Lesinskid5083f62017-01-16 15:07:21 -0800269 ResourceTablePackage* FindPackage(const android::StringPiece& name);
Adam Lesinskifb48d292015-11-07 15:52:13 -0800270
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700271 ResourceTablePackage* FindPackageById(uint8_t id);
Adam Lesinski5eeaadd2016-08-25 12:26:56 -0700272
Adam Lesinskid5083f62017-01-16 15:07:21 -0800273 ResourceTablePackage* CreatePackage(const android::StringPiece& name, Maybe<uint8_t> id = {});
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700274
275 private:
Adam Lesinskid5083f62017-01-16 15:07:21 -0800276 ResourceTablePackage* FindOrCreatePackage(const android::StringPiece& name);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700277
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700278 bool AddResourceImpl(const ResourceNameRef& name, const ResourceId& res_id,
Adam Lesinskid5083f62017-01-16 15:07:21 -0800279 const ConfigDescription& config, const android::StringPiece& product,
280 std::unique_ptr<Value> value, const char* valid_chars,
281 const CollisionResolverFunc& conflict_resolver, IDiagnostics* diag);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700282
Adam Lesinskid5083f62017-01-16 15:07:21 -0800283 bool AddFileReferenceImpl(const ResourceNameRef& name, const ConfigDescription& config,
284 const Source& source, const android::StringPiece& path, io::IFile* file,
285 const char* valid_chars, IDiagnostics* diag);
Adam Lesinskie4bb9eb2016-02-12 22:18:51 -0800286
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700287 bool SetSymbolStateImpl(const ResourceNameRef& name, const ResourceId& res_id,
288 const Symbol& symbol, const char* valid_chars,
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700289 IDiagnostics* diag);
290
291 DISALLOW_COPY_AND_ASSIGN(ResourceTable);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800292};
293
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700294} // namespace aapt
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800295
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700296#endif // AAPT_RESOURCE_TABLE_H