blob: 95e30c442042a58e40a45c7ceae50a657cf058b2 [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 Lesinski71be7052017-12-12 16:48:07 -080041// The Public status of a resource.
42struct 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;
Adam Lesinski9e10ac72015-10-16 14:37:48 -070052};
53
Adam Lesinski71be7052017-12-12 16:48:07 -080054// Represents <add-resource> in an overlay.
55struct AllowNew {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070056 Source source;
Adam Lesinski71be7052017-12-12 16:48:07 -080057 std::string comment;
58};
Adam Lesinski4488f1c2017-05-26 17:33:38 -070059
Adam Lesinski71be7052017-12-12 16:48:07 -080060// The policy dictating whether an entry is overlayable at runtime by RROs.
61struct Overlayable {
62 Source source;
Adam Lesinskicacb28f2016-10-19 12:18:14 -070063 std::string comment;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080064};
65
Adam Lesinskie4bb9eb2016-02-12 22:18:51 -080066class ResourceConfigValue {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070067 public:
Adam Lesinski71be7052017-12-12 16:48:07 -080068 // The configuration for which this value is defined.
Adam Lesinskicacb28f2016-10-19 12:18:14 -070069 const ConfigDescription config;
Adam Lesinskie4bb9eb2016-02-12 22:18:51 -080070
Adam Lesinski71be7052017-12-12 16:48:07 -080071 // The product for which this value is defined.
Adam Lesinskicacb28f2016-10-19 12:18:14 -070072 const std::string product;
Adam Lesinskie4bb9eb2016-02-12 22:18:51 -080073
Adam Lesinski71be7052017-12-12 16:48:07 -080074 // The actual Value.
Adam Lesinskicacb28f2016-10-19 12:18:14 -070075 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
Adam Lesinski73bff1e2017-12-08 16:06:10 -080084// Represents a resource entry, which may have varying values for each defined configuration.
Adam Lesinskie4bb9eb2016-02-12 22:18:51 -080085class ResourceEntry {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070086 public:
Adam Lesinski71be7052017-12-12 16:48:07 -080087 // The name of the resource. Immutable, as this determines the order of this resource
88 // when doing lookups.
Adam Lesinskicacb28f2016-10-19 12:18:14 -070089 const std::string name;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080090
Adam Lesinski71be7052017-12-12 16:48:07 -080091 // The entry ID for this resource (the EEEE in 0xPPTTEEEE).
Adam Lesinskicacb28f2016-10-19 12:18:14 -070092 Maybe<uint16_t> id;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080093
Adam Lesinski71be7052017-12-12 16:48:07 -080094 // Whether this resource is public (and must maintain the same entry ID across builds).
95 Visibility visibility;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080096
Adam Lesinski71be7052017-12-12 16:48:07 -080097 Maybe<AllowNew> allow_new;
98
99 Maybe<Overlayable> overlayable;
100
101 // The resource's values for each configuration.
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700102 std::vector<std::unique_ptr<ResourceConfigValue>> values;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800103
Adam Lesinskid5083f62017-01-16 15:07:21 -0800104 explicit ResourceEntry(const android::StringPiece& name) : name(name.to_string()) {}
Adam Lesinskie4bb9eb2016-02-12 22:18:51 -0800105
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700106 ResourceConfigValue* FindValue(const ConfigDescription& config);
107 ResourceConfigValue* FindValue(const ConfigDescription& config,
Adam Lesinskid5083f62017-01-16 15:07:21 -0800108 const android::StringPiece& product);
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700109 ResourceConfigValue* FindOrCreateValue(const ConfigDescription& config,
Adam Lesinskid5083f62017-01-16 15:07:21 -0800110 const android::StringPiece& product);
Adam Lesinskib1afa072017-03-29 13:52:38 -0700111 std::vector<ResourceConfigValue*> FindAllValues(const ConfigDescription& config);
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700112 std::vector<ResourceConfigValue*> FindValuesIf(
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700113 const std::function<bool(ResourceConfigValue*)>& f);
Adam Lesinski458b8772016-04-25 14:20:21 -0700114
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700115 private:
116 DISALLOW_COPY_AND_ASSIGN(ResourceEntry);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800117};
118
Adam Lesinski71be7052017-12-12 16:48:07 -0800119// Represents a resource type (eg. string, drawable, layout, etc.) containing resource entries.
Adam Lesinskie4bb9eb2016-02-12 22:18:51 -0800120class ResourceTableType {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700121 public:
Adam Lesinski71be7052017-12-12 16:48:07 -0800122 // The logical type of resource (string, drawable, layout, etc.).
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700123 const ResourceType type;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800124
Adam Lesinski71be7052017-12-12 16:48:07 -0800125 // The type ID for this resource (the TT in 0xPPTTEEEE).
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700126 Maybe<uint8_t> id;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800127
Adam Lesinski71be7052017-12-12 16:48:07 -0800128 // Whether this type is public (and must maintain the same type ID across builds).
129 Visibility::Level visibility_level = Visibility::Level::kUndefined;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800130
Adam Lesinski71be7052017-12-12 16:48:07 -0800131 // List of resources for this type.
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700132 std::vector<std::unique_ptr<ResourceEntry>> entries;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800133
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700134 explicit ResourceTableType(const ResourceType type) : type(type) {}
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700135
Adam Lesinskid5083f62017-01-16 15:07:21 -0800136 ResourceEntry* FindEntry(const android::StringPiece& name);
137 ResourceEntry* FindOrCreateEntry(const android::StringPiece& name);
Adam Lesinskie4bb9eb2016-02-12 22:18:51 -0800138
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700139 private:
140 DISALLOW_COPY_AND_ASSIGN(ResourceTableType);
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700141};
142
Adam Lesinskie4bb9eb2016-02-12 22:18:51 -0800143class ResourceTablePackage {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700144 public:
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700145 std::string name;
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700146
Adam Lesinski71be7052017-12-12 16:48:07 -0800147 // The package ID (the PP in 0xPPTTEEEE).
148 Maybe<uint8_t> id;
149
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700150 std::vector<std::unique_ptr<ResourceTableType>> types;
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700151
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700152 ResourceTablePackage() = default;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700153 ResourceTableType* FindType(ResourceType type);
154 ResourceTableType* FindOrCreateType(const ResourceType type);
Adam Lesinskie4bb9eb2016-02-12 22:18:51 -0800155
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700156 private:
157 DISALLOW_COPY_AND_ASSIGN(ResourceTablePackage);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800158};
159
Adam Lesinski71be7052017-12-12 16:48:07 -0800160// The container and index for all resources defined for an app.
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800161class ResourceTable {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700162 public:
163 ResourceTable() = default;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800164
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700165 enum class CollisionResult { kKeepOriginal, kConflict, kTakeNew };
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700166
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700167 using CollisionResolverFunc = std::function<CollisionResult(Value*, Value*)>;
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700168
Adam Lesinski71be7052017-12-12 16:48:07 -0800169 // When a collision of resources occurs, this method decides which value to keep.
Adam Lesinskib1afa072017-03-29 13:52:38 -0700170 static CollisionResult ResolveValueCollision(Value* existing, Value* incoming);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800171
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700172 bool AddResource(const ResourceNameRef& name, const ConfigDescription& config,
Adam Lesinskid5083f62017-01-16 15:07:21 -0800173 const android::StringPiece& product, std::unique_ptr<Value> value,
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700174 IDiagnostics* diag);
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700175
Adam Lesinski71be7052017-12-12 16:48:07 -0800176 bool AddResourceWithId(const ResourceNameRef& name, const ResourceId& res_id,
177 const ConfigDescription& config, const android::StringPiece& product,
178 std::unique_ptr<Value> value, IDiagnostics* diag);
Adam Lesinskie4bb9eb2016-02-12 22:18:51 -0800179
Adam Lesinskid5083f62017-01-16 15:07:21 -0800180 bool AddFileReference(const ResourceNameRef& name, const ConfigDescription& config,
181 const Source& source, const android::StringPiece& path, IDiagnostics* diag);
Adam Lesinskifb48d292015-11-07 15:52:13 -0800182
Adam Lesinski71be7052017-12-12 16:48:07 -0800183 bool AddFileReferenceMangled(const ResourceNameRef& name, const ConfigDescription& config,
184 const Source& source, const android::StringPiece& path,
185 io::IFile* file, IDiagnostics* diag);
Adam Lesinskie78fd612015-10-22 12:48:43 -0700186
Adam Lesinski71be7052017-12-12 16:48:07 -0800187 // Same as AddResource, but doesn't verify the validity of the name. This is used
188 // when loading resources from an existing binary resource table that may have mangled names.
189 bool AddResourceMangled(const ResourceNameRef& name, const ConfigDescription& config,
190 const android::StringPiece& product, std::unique_ptr<Value> value,
191 IDiagnostics* diag);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800192
Adam Lesinski71be7052017-12-12 16:48:07 -0800193 bool AddResourceWithIdMangled(const ResourceNameRef& name, const ResourceId& id,
194 const ConfigDescription& config,
195 const android::StringPiece& product, std::unique_ptr<Value> value,
196 IDiagnostics* diag);
Adam Lesinski769de982015-04-10 19:43:55 -0700197
Adam Lesinski71be7052017-12-12 16:48:07 -0800198 bool SetVisibility(const ResourceNameRef& name, const Visibility& visibility, IDiagnostics* diag);
199 bool SetVisibilityMangled(const ResourceNameRef& name, const Visibility& visibility,
200 IDiagnostics* diag);
201 bool SetVisibilityWithId(const ResourceNameRef& name, const Visibility& visibility,
202 const ResourceId& res_id, IDiagnostics* diag);
203 bool SetVisibilityWithIdMangled(const ResourceNameRef& name, const Visibility& visibility,
204 const ResourceId& res_id, IDiagnostics* diag);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800205
Adam Lesinski71be7052017-12-12 16:48:07 -0800206 bool SetOverlayable(const ResourceNameRef& name, const Overlayable& overlayable,
207 IDiagnostics* diag);
208 bool SetOverlayableMangled(const ResourceNameRef& name, const Overlayable& overlayable,
209 IDiagnostics* diag);
210
211 bool SetAllowNew(const ResourceNameRef& name, const AllowNew& allow_new, IDiagnostics* diag);
212 bool SetAllowNewMangled(const ResourceNameRef& name, const AllowNew& allow_new,
213 IDiagnostics* diag);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800214
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700215 struct SearchResult {
216 ResourceTablePackage* package;
217 ResourceTableType* type;
218 ResourceEntry* entry;
219 };
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700220
Adam Lesinski71be7052017-12-12 16:48:07 -0800221 Maybe<SearchResult> FindResource(const ResourceNameRef& name) const;
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700222
Adam Lesinski71be7052017-12-12 16:48:07 -0800223 // Returns the package struct with the given name, or nullptr if such a package does not
224 // exist. The empty string is a valid package and typically is used to represent the
225 // 'current' package before it is known to the ResourceTable.
226 ResourceTablePackage* FindPackage(const android::StringPiece& name) const;
Adam Lesinskiceb9b2f2017-02-16 12:05:42 -0800227
Adam Lesinski71be7052017-12-12 16:48:07 -0800228 ResourceTablePackage* FindPackageById(uint8_t id) const;
Adam Lesinskiceb9b2f2017-02-16 12:05:42 -0800229
230 ResourceTablePackage* CreatePackage(const android::StringPiece& name, Maybe<uint8_t> id = {});
231
Shane Farmer0a5b2012017-06-22 12:24:12 -0700232 std::unique_ptr<ResourceTable> Clone() const;
233
Adam Lesinski71be7052017-12-12 16:48:07 -0800234 // The string pool used by this resource table. Values that reference strings must use
235 // this pool to create their strings.
236 // NOTE: `string_pool` must come before `packages` so that it is destroyed after.
237 // When `string_pool` references are destroyed (as they will be when `packages` is destroyed),
238 // they decrement a refCount, which would cause invalid memory access if the pool was already
239 // destroyed.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700240 StringPool string_pool;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800241
Adam Lesinski71be7052017-12-12 16:48:07 -0800242 // The list of packages in this table, sorted alphabetically by package name.
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700243 std::vector<std::unique_ptr<ResourceTablePackage>> packages;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800244
Adam Lesinskiceb9b2f2017-02-16 12:05:42 -0800245 // Set of dynamic packages that this table may reference. Their package names get encoded
246 // into the resources.arsc along with their compile-time assigned IDs.
247 std::map<size_t, std::string> included_packages_;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700248
249 private:
Adam Lesinskib1afa072017-03-29 13:52:38 -0700250 // The function type that validates a symbol name. Returns a non-empty StringPiece representing
251 // the offending character (which may be more than one byte in UTF-8). Returns an empty string
252 // if the name was valid.
253 using NameValidator = android::StringPiece(const android::StringPiece&);
254
Adam Lesinskid5083f62017-01-16 15:07:21 -0800255 ResourceTablePackage* FindOrCreatePackage(const android::StringPiece& name);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700256
Adam Lesinski71be7052017-12-12 16:48:07 -0800257 bool ValidateName(NameValidator validator, const ResourceNameRef& name, const Source& source,
258 IDiagnostics* diag);
259
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700260 bool AddResourceImpl(const ResourceNameRef& name, const ResourceId& res_id,
Adam Lesinskid5083f62017-01-16 15:07:21 -0800261 const ConfigDescription& config, const android::StringPiece& product,
Adam Lesinskib1afa072017-03-29 13:52:38 -0700262 std::unique_ptr<Value> value, NameValidator name_validator,
Adam Lesinskid5083f62017-01-16 15:07:21 -0800263 const CollisionResolverFunc& conflict_resolver, IDiagnostics* diag);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700264
Adam Lesinskid5083f62017-01-16 15:07:21 -0800265 bool AddFileReferenceImpl(const ResourceNameRef& name, const ConfigDescription& config,
266 const Source& source, const android::StringPiece& path, io::IFile* file,
Adam Lesinskib1afa072017-03-29 13:52:38 -0700267 NameValidator name_validator, IDiagnostics* diag);
Adam Lesinskie4bb9eb2016-02-12 22:18:51 -0800268
Adam Lesinski71be7052017-12-12 16:48:07 -0800269 bool SetVisibilityImpl(const ResourceNameRef& name, const Visibility& visibility,
270 const ResourceId& res_id, NameValidator name_validator,
271 IDiagnostics* diag);
272
273 bool SetAllowNewImpl(const ResourceNameRef& name, const AllowNew& allow_new,
274 NameValidator name_validator, IDiagnostics* diag);
275
276 bool SetOverlayableImpl(const ResourceNameRef& name, const Overlayable& overlayable,
277 NameValidator name_validator, IDiagnostics* diag);
278
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700279 bool SetSymbolStateImpl(const ResourceNameRef& name, const ResourceId& res_id,
Adam Lesinski71be7052017-12-12 16:48:07 -0800280 const Visibility& symbol, NameValidator name_validator,
281 IDiagnostics* diag);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700282
283 DISALLOW_COPY_AND_ASSIGN(ResourceTable);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800284};
285
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700286} // namespace aapt
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800287
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700288#endif // AAPT_RESOURCE_TABLE_H