blob: 4295d06747740e399e26754656ca39fe42250eaa [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;
Adam Lesinski4488f1c2017-05-26 17:33:38 -070053
54 // Whether this entry (originating from an overlay) can be added as a new resource.
55 bool allow_new = false;
56
Adam Lesinskicacb28f2016-10-19 12:18:14 -070057 std::string comment;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080058};
59
Adam Lesinskie4bb9eb2016-02-12 22:18:51 -080060class ResourceConfigValue {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070061 public:
62 /**
63 * The configuration for which this value is defined.
64 */
65 const ConfigDescription config;
Adam Lesinskie4bb9eb2016-02-12 22:18:51 -080066
Adam Lesinskicacb28f2016-10-19 12:18:14 -070067 /**
68 * The product for which this value is defined.
69 */
70 const std::string product;
Adam Lesinskie4bb9eb2016-02-12 22:18:51 -080071
Adam Lesinskicacb28f2016-10-19 12:18:14 -070072 /**
73 * The actual Value.
74 */
75 std::unique_ptr<Value> value;
Adam Lesinskie4bb9eb2016-02-12 22:18:51 -080076
Adam Lesinskid5083f62017-01-16 15:07:21 -080077 ResourceConfigValue(const ConfigDescription& config, const android::StringPiece& product)
78 : config(config), product(product.to_string()) {}
Adam Lesinskie4bb9eb2016-02-12 22:18:51 -080079
Adam Lesinskicacb28f2016-10-19 12:18:14 -070080 private:
81 DISALLOW_COPY_AND_ASSIGN(ResourceConfigValue);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080082};
83
84/**
85 * Represents a resource entry, which may have
86 * varying values for each defined configuration.
87 */
Adam Lesinskie4bb9eb2016-02-12 22:18:51 -080088class ResourceEntry {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070089 public:
90 /**
91 * The name of the resource. Immutable, as
92 * this determines the order of this resource
93 * when doing lookups.
94 */
95 const std::string name;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080096
Adam Lesinskicacb28f2016-10-19 12:18:14 -070097 /**
98 * The entry ID for this resource.
99 */
100 Maybe<uint16_t> id;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800101
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700102 /**
103 * Whether this resource is public (and must maintain the same entry ID across
104 * builds).
105 */
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700106 Symbol symbol_status;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800107
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700108 /**
109 * The resource's values for each configuration.
110 */
111 std::vector<std::unique_ptr<ResourceConfigValue>> values;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800112
Adam Lesinskid5083f62017-01-16 15:07:21 -0800113 explicit ResourceEntry(const android::StringPiece& name) : name(name.to_string()) {}
Adam Lesinskie4bb9eb2016-02-12 22:18:51 -0800114
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700115 ResourceConfigValue* FindValue(const ConfigDescription& config);
116 ResourceConfigValue* FindValue(const ConfigDescription& config,
Adam Lesinskid5083f62017-01-16 15:07:21 -0800117 const android::StringPiece& product);
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700118 ResourceConfigValue* FindOrCreateValue(const ConfigDescription& config,
Adam Lesinskid5083f62017-01-16 15:07:21 -0800119 const android::StringPiece& product);
Adam Lesinskib1afa072017-03-29 13:52:38 -0700120 std::vector<ResourceConfigValue*> FindAllValues(const ConfigDescription& config);
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700121 std::vector<ResourceConfigValue*> FindValuesIf(
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700122 const std::function<bool(ResourceConfigValue*)>& f);
Adam Lesinski458b8772016-04-25 14:20:21 -0700123
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700124 private:
125 DISALLOW_COPY_AND_ASSIGN(ResourceEntry);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800126};
127
128/**
129 * Represents a resource type, which holds entries defined
130 * for this type.
131 */
Adam Lesinskie4bb9eb2016-02-12 22:18:51 -0800132class ResourceTableType {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700133 public:
134 /**
135 * The logical type of resource (string, drawable, layout, etc.).
136 */
137 const ResourceType type;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800138
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700139 /**
140 * The type ID for this resource.
141 */
142 Maybe<uint8_t> id;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800143
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700144 /**
145 * Whether this type is public (and must maintain the same
146 * type ID across builds).
147 */
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700148 Symbol symbol_status;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800149
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700150 /**
151 * List of resources for this type.
152 */
153 std::vector<std::unique_ptr<ResourceEntry>> entries;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800154
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700155 explicit ResourceTableType(const ResourceType type) : type(type) {}
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700156
Adam Lesinskid5083f62017-01-16 15:07:21 -0800157 ResourceEntry* FindEntry(const android::StringPiece& name);
158 ResourceEntry* FindOrCreateEntry(const android::StringPiece& name);
Adam Lesinskie4bb9eb2016-02-12 22:18:51 -0800159
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700160 private:
161 DISALLOW_COPY_AND_ASSIGN(ResourceTableType);
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700162};
163
Adam Lesinskie4bb9eb2016-02-12 22:18:51 -0800164class ResourceTablePackage {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700165 public:
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700166 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 Lesinskib1afa072017-03-29 13:52:38 -0700195 static CollisionResult ResolveValueCollision(Value* existing, Value* incoming);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800196
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700197 bool AddResource(const ResourceNameRef& name, const ConfigDescription& config,
Adam Lesinskid5083f62017-01-16 15:07:21 -0800198 const android::StringPiece& product, std::unique_ptr<Value> value,
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700199 IDiagnostics* diag);
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700200
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700201 bool AddResource(const ResourceNameRef& name, const ResourceId& res_id,
Adam Lesinskid5083f62017-01-16 15:07:21 -0800202 const ConfigDescription& config, const android::StringPiece& product,
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700203 std::unique_ptr<Value> value, IDiagnostics* diag);
Adam Lesinskie4bb9eb2016-02-12 22:18:51 -0800204
Adam Lesinskid5083f62017-01-16 15:07:21 -0800205 bool AddFileReference(const ResourceNameRef& name, const ConfigDescription& config,
206 const Source& source, const android::StringPiece& path, IDiagnostics* diag);
Adam Lesinskifb48d292015-11-07 15:52:13 -0800207
Adam Lesinskid5083f62017-01-16 15:07:21 -0800208 bool AddFileReferenceAllowMangled(const ResourceNameRef& name, const ConfigDescription& config,
209 const Source& source, const android::StringPiece& path,
210 io::IFile* file, IDiagnostics* diag);
Adam Lesinskie78fd612015-10-22 12:48:43 -0700211
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700212 /**
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700213 * Same as AddResource, but doesn't verify the validity of the name. This is
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700214 * used
215 * when loading resources from an existing binary resource table that may have
216 * mangled
217 * names.
218 */
Adam Lesinskid5083f62017-01-16 15:07:21 -0800219 bool AddResourceAllowMangled(const ResourceNameRef& name, const ConfigDescription& config,
220 const android::StringPiece& product, std::unique_ptr<Value> value,
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700221 IDiagnostics* diag);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800222
Adam Lesinskid5083f62017-01-16 15:07:21 -0800223 bool AddResourceAllowMangled(const ResourceNameRef& name, const ResourceId& id,
224 const ConfigDescription& config, const android::StringPiece& product,
225 std::unique_ptr<Value> value, IDiagnostics* diag);
Adam Lesinski769de982015-04-10 19:43:55 -0700226
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700227 bool SetSymbolState(const ResourceNameRef& name, const ResourceId& res_id,
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700228 const Symbol& symbol, IDiagnostics* diag);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800229
Adam Lesinski4488f1c2017-05-26 17:33:38 -0700230 bool SetSymbolStateAllowMangled(const ResourceNameRef& name, const ResourceId& res_id,
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700231 const Symbol& symbol, IDiagnostics* diag);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800232
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700233 struct SearchResult {
234 ResourceTablePackage* package;
235 ResourceTableType* type;
236 ResourceEntry* entry;
237 };
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700238
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700239 Maybe<SearchResult> FindResource(const ResourceNameRef& name);
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700240
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700241 /**
Adam Lesinskiceb9b2f2017-02-16 12:05:42 -0800242 * Returns the package struct with the given name, or nullptr if such a
243 * package does not
244 * exist. The empty string is a valid package and typically is used to
245 * represent the
246 * 'current' package before it is known to the ResourceTable.
247 */
248 ResourceTablePackage* FindPackage(const android::StringPiece& name);
249
250 ResourceTablePackage* FindPackageById(uint8_t id);
251
252 ResourceTablePackage* CreatePackage(const android::StringPiece& name, Maybe<uint8_t> id = {});
253
254 /**
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700255 * The string pool used by this resource table. Values that reference strings
256 * must use
257 * this pool to create their strings.
258 *
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700259 * NOTE: `string_pool` must come before `packages` so that it is destroyed
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700260 * after.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700261 * When `string_pool` references are destroyed (as they will be when
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700262 * `packages`
263 * is destroyed), they decrement a refCount, which would cause invalid
264 * memory access if the pool was already destroyed.
265 */
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700266 StringPool string_pool;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800267
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700268 /**
269 * The list of packages in this table, sorted alphabetically by package name.
270 */
271 std::vector<std::unique_ptr<ResourceTablePackage>> packages;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800272
Adam Lesinskiceb9b2f2017-02-16 12:05:42 -0800273 // Set of dynamic packages that this table may reference. Their package names get encoded
274 // into the resources.arsc along with their compile-time assigned IDs.
275 std::map<size_t, std::string> included_packages_;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700276
277 private:
Adam Lesinskib1afa072017-03-29 13:52:38 -0700278 // The function type that validates a symbol name. Returns a non-empty StringPiece representing
279 // the offending character (which may be more than one byte in UTF-8). Returns an empty string
280 // if the name was valid.
281 using NameValidator = android::StringPiece(const android::StringPiece&);
282
Adam Lesinskid5083f62017-01-16 15:07:21 -0800283 ResourceTablePackage* FindOrCreatePackage(const android::StringPiece& name);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700284
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700285 bool AddResourceImpl(const ResourceNameRef& name, const ResourceId& res_id,
Adam Lesinskid5083f62017-01-16 15:07:21 -0800286 const ConfigDescription& config, const android::StringPiece& product,
Adam Lesinskib1afa072017-03-29 13:52:38 -0700287 std::unique_ptr<Value> value, NameValidator name_validator,
Adam Lesinskid5083f62017-01-16 15:07:21 -0800288 const CollisionResolverFunc& conflict_resolver, IDiagnostics* diag);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700289
Adam Lesinskid5083f62017-01-16 15:07:21 -0800290 bool AddFileReferenceImpl(const ResourceNameRef& name, const ConfigDescription& config,
291 const Source& source, const android::StringPiece& path, io::IFile* file,
Adam Lesinskib1afa072017-03-29 13:52:38 -0700292 NameValidator name_validator, IDiagnostics* diag);
Adam Lesinskie4bb9eb2016-02-12 22:18:51 -0800293
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700294 bool SetSymbolStateImpl(const ResourceNameRef& name, const ResourceId& res_id,
Adam Lesinskib1afa072017-03-29 13:52:38 -0700295 const Symbol& symbol, NameValidator name_validator, IDiagnostics* diag);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700296
297 DISALLOW_COPY_AND_ASSIGN(ResourceTable);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800298};
299
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700300} // namespace aapt
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800301
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700302#endif // AAPT_RESOURCE_TABLE_H