blob: 080ecc20558bee6a3ec1bc0844a77a488fb5c769 [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
Adam Lesinski1ab598f2015-08-14 14:26:04 -070020#include "Diagnostics.h"
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080021#include "Resource.h"
22#include "ResourceValues.h"
23#include "Source.h"
24#include "StringPool.h"
Adam Lesinski355f2852016-02-13 20:26:45 -080025#include "io/File.h"
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080026
Adam Lesinskid5083f62017-01-16 15:07:21 -080027#include "android-base/macros.h"
Mårten Kongstad24c9aa62018-06-20 08:46:41 +020028#include "androidfw/ConfigDescription.h"
Adam Lesinskid5083f62017-01-16 15:07:21 -080029#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
Winson62ac8b52019-12-04 08:36:48 -080039using PolicyFlags = android::ResTable_overlayable_policy_header::PolicyFlags;
40
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080041namespace aapt {
42
Adam Lesinski71be7052017-12-12 16:48:07 -080043// The Public status of a resource.
44struct Visibility {
45 enum class Level {
46 kUndefined,
47 kPrivate,
48 kPublic,
49 };
50
51 Level level = Level::kUndefined;
52 Source source;
53 std::string comment;
Ryan Mitchell2e9bec12021-03-22 09:31:00 -070054
55 // Indicates that the resource id may change across builds and that the public R.java identifier
56 // for this resource should not be final. This is set to `true` for resources in `staging-group`
57 // tags.
58 bool staged_api = false;
Adam Lesinski9e10ac72015-10-16 14:37:48 -070059};
60
Adam Lesinski71be7052017-12-12 16:48:07 -080061// Represents <add-resource> in an overlay.
62struct AllowNew {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070063 Source source;
Adam Lesinski71be7052017-12-12 16:48:07 -080064 std::string comment;
65};
Adam Lesinski4488f1c2017-05-26 17:33:38 -070066
Adam Lesinski71be7052017-12-12 16:48:07 -080067struct Overlayable {
Ryan Mitchell54237ff2018-12-13 15:44:29 -080068 Overlayable() = default;
69 Overlayable(const android::StringPiece& name, const android::StringPiece& actor)
70 : name(name.to_string()), actor(actor.to_string()) {}
71 Overlayable(const android::StringPiece& name, const android::StringPiece& actor,
72 const Source& source)
73 : name(name.to_string()), actor(actor.to_string()), source(source ){}
74
75 static const char* kActorScheme;
76 std::string name;
77 std::string actor;
78 Source source;
79};
80
81// Represents a declaration that a resource is overlayable at runtime.
82struct OverlayableItem {
83 explicit OverlayableItem(const std::shared_ptr<Overlayable>& overlayable)
84 : overlayable(overlayable) {}
Ryan Mitchell54237ff2018-12-13 15:44:29 -080085 std::shared_ptr<Overlayable> overlayable;
Winson62ac8b52019-12-04 08:36:48 -080086 PolicyFlags policies = PolicyFlags::NONE;
Adam Lesinskicacb28f2016-10-19 12:18:14 -070087 std::string comment;
Ryan Mitchell54237ff2018-12-13 15:44:29 -080088 Source source;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -080089};
90
Adam Lesinskie4bb9eb2016-02-12 22:18:51 -080091class ResourceConfigValue {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070092 public:
Adam Lesinski71be7052017-12-12 16:48:07 -080093 // The configuration for which this value is defined.
Mårten Kongstad24c9aa62018-06-20 08:46:41 +020094 const android::ConfigDescription config;
Adam Lesinskie4bb9eb2016-02-12 22:18:51 -080095
Adam Lesinski71be7052017-12-12 16:48:07 -080096 // The product for which this value is defined.
Adam Lesinskicacb28f2016-10-19 12:18:14 -070097 const std::string product;
Adam Lesinskie4bb9eb2016-02-12 22:18:51 -080098
Adam Lesinski71be7052017-12-12 16:48:07 -080099 // The actual Value.
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700100 std::unique_ptr<Value> value;
Adam Lesinskie4bb9eb2016-02-12 22:18:51 -0800101
Mårten Kongstad24c9aa62018-06-20 08:46:41 +0200102 ResourceConfigValue(const android::ConfigDescription& config, const android::StringPiece& product)
Adam Lesinskid5083f62017-01-16 15:07:21 -0800103 : config(config), product(product.to_string()) {}
Adam Lesinskie4bb9eb2016-02-12 22:18:51 -0800104
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700105 private:
106 DISALLOW_COPY_AND_ASSIGN(ResourceConfigValue);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800107};
108
Adam Lesinski73bff1e2017-12-08 16:06:10 -0800109// Represents a resource entry, which may have varying values for each defined configuration.
Adam Lesinskie4bb9eb2016-02-12 22:18:51 -0800110class ResourceEntry {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700111 public:
Adam Lesinski71be7052017-12-12 16:48:07 -0800112 // The name of the resource. Immutable, as this determines the order of this resource
113 // when doing lookups.
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700114 const std::string name;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800115
Adam Lesinski71be7052017-12-12 16:48:07 -0800116 // The entry ID for this resource (the EEEE in 0xPPTTEEEE).
Ryan Mitchell9634efb2021-03-19 14:53:17 -0700117 Maybe<ResourceId> id;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800118
Adam Lesinski71be7052017-12-12 16:48:07 -0800119 // Whether this resource is public (and must maintain the same entry ID across builds).
120 Visibility visibility;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800121
Adam Lesinski71be7052017-12-12 16:48:07 -0800122 Maybe<AllowNew> allow_new;
123
Ryan Mitchelle4e989c2018-10-29 02:21:50 -0700124 // The declarations of this resource as overlayable for RROs
Ryan Mitchell54237ff2018-12-13 15:44:29 -0800125 Maybe<OverlayableItem> overlayable_item;
Adam Lesinski71be7052017-12-12 16:48:07 -0800126
127 // The resource's values for each configuration.
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700128 std::vector<std::unique_ptr<ResourceConfigValue>> values;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800129
Adam Lesinskid5083f62017-01-16 15:07:21 -0800130 explicit ResourceEntry(const android::StringPiece& name) : name(name.to_string()) {}
Adam Lesinskie4bb9eb2016-02-12 22:18:51 -0800131
Mårten Kongstad24c9aa62018-06-20 08:46:41 +0200132 ResourceConfigValue* FindValue(const android::ConfigDescription& config,
Ryan Mitchell9634efb2021-03-19 14:53:17 -0700133 android::StringPiece product = {});
134 const ResourceConfigValue* FindValue(const android::ConfigDescription& config,
135 android::StringPiece product = {}) const;
Adam Lesinski34a16872018-02-23 16:18:10 -0800136
Mårten Kongstad24c9aa62018-06-20 08:46:41 +0200137 ResourceConfigValue* FindOrCreateValue(const android::ConfigDescription& config,
Adam Lesinskid5083f62017-01-16 15:07:21 -0800138 const android::StringPiece& product);
Mårten Kongstad24c9aa62018-06-20 08:46:41 +0200139 std::vector<ResourceConfigValue*> FindAllValues(const android::ConfigDescription& config);
Adam Lesinski34a16872018-02-23 16:18:10 -0800140
141 template <typename Func>
142 std::vector<ResourceConfigValue*> FindValuesIf(Func f) {
143 std::vector<ResourceConfigValue*> results;
144 for (auto& config_value : values) {
145 if (f(config_value.get())) {
146 results.push_back(config_value.get());
147 }
148 }
149 return results;
150 }
151
152 bool HasDefaultValue() const;
Adam Lesinski458b8772016-04-25 14:20:21 -0700153
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700154 private:
155 DISALLOW_COPY_AND_ASSIGN(ResourceEntry);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800156};
157
Adam Lesinski71be7052017-12-12 16:48:07 -0800158// Represents a resource type (eg. string, drawable, layout, etc.) containing resource entries.
Adam Lesinskie4bb9eb2016-02-12 22:18:51 -0800159class ResourceTableType {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700160 public:
Adam Lesinski71be7052017-12-12 16:48:07 -0800161 // The logical type of resource (string, drawable, layout, etc.).
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700162 const ResourceType type;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800163
Adam Lesinski71be7052017-12-12 16:48:07 -0800164 // Whether this type is public (and must maintain the same type ID across builds).
165 Visibility::Level visibility_level = Visibility::Level::kUndefined;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800166
Adam Lesinski71be7052017-12-12 16:48:07 -0800167 // List of resources for this type.
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700168 std::vector<std::unique_ptr<ResourceEntry>> entries;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800169
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700170 explicit ResourceTableType(const ResourceType type) : type(type) {}
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700171
Ryan Mitchell9634efb2021-03-19 14:53:17 -0700172 ResourceEntry* CreateEntry(const android::StringPiece& name);
173 ResourceEntry* FindEntry(const android::StringPiece& name) const;
174 ResourceEntry* FindOrCreateEntry(const android::StringPiece& name);
Adam Lesinskie4bb9eb2016-02-12 22:18:51 -0800175
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700176 private:
177 DISALLOW_COPY_AND_ASSIGN(ResourceTableType);
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700178};
179
Adam Lesinskie4bb9eb2016-02-12 22:18:51 -0800180class ResourceTablePackage {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700181 public:
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700182 std::string name;
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700183
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700184 std::vector<std::unique_ptr<ResourceTableType>> types;
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700185
Ryan Mitchell9634efb2021-03-19 14:53:17 -0700186 explicit ResourceTablePackage(const android::StringPiece& name) : name(name.to_string()) {
187 }
188
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700189 ResourceTablePackage() = default;
Ryan Mitchell9634efb2021-03-19 14:53:17 -0700190 ResourceTableType* FindType(ResourceType type) const;
191 ResourceTableType* FindOrCreateType(ResourceType type);
Adam Lesinskie4bb9eb2016-02-12 22:18:51 -0800192
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700193 private:
194 DISALLOW_COPY_AND_ASSIGN(ResourceTablePackage);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800195};
196
Ryan Mitchell9634efb2021-03-19 14:53:17 -0700197struct ResourceTableTypeView {
198 ResourceType type;
199 Maybe<uint8_t> id;
200 Visibility::Level visibility_level = Visibility::Level::kUndefined;
201
202 // Entries sorted in ascending entry id order. If ids have not been assigned, the entries are
203 // // sorted lexicographically.
204 std::vector<const ResourceEntry*> entries;
205};
206
207struct ResourceTablePackageView {
208 std::string name;
209 Maybe<uint8_t> id;
210 // Types sorted in ascending type id order. If ids have not been assigned, the types are sorted by
211 // their declaration order in the ResourceType enum.
212 std::vector<ResourceTableTypeView> types;
213};
214
215struct ResourceTableView {
216 // Packages sorted in ascending package id order. If ids have not been assigned, the packages are
217 // sorted lexicographically.
218 std::vector<ResourceTablePackageView> packages;
219};
220
221enum class OnIdConflict {
222 // If the resource entry already exists but has a different resource id, the resource value will
223 // not be added to the table.
224 ERROR,
225
226 // If the resource entry already exists but has a different resource id, create a new resource
227 // with this resource name and id combination.
228 CREATE_ENTRY,
229};
230
231struct NewResource {
232 ResourceName name;
233 std::unique_ptr<Value> value;
234 android::ConfigDescription config;
235 std::string product;
236 std::optional<std::pair<ResourceId, OnIdConflict>> id;
237 std::optional<Visibility> visibility;
238 std::optional<OverlayableItem> overlayable;
239 std::optional<AllowNew> allow_new;
240 bool allow_mangled = false;
241};
242
243struct NewResourceBuilder {
244 explicit NewResourceBuilder(const ResourceNameRef& name);
245 explicit NewResourceBuilder(const std::string& name);
246 NewResourceBuilder& SetValue(std::unique_ptr<Value> value, android::ConfigDescription config = {},
247 std::string product = {});
248 NewResourceBuilder& SetId(ResourceId id, OnIdConflict on_conflict = OnIdConflict::ERROR);
249 NewResourceBuilder& SetVisibility(Visibility id);
250 NewResourceBuilder& SetOverlayable(OverlayableItem overlayable);
251 NewResourceBuilder& SetAllowNew(AllowNew allow_new);
252 NewResourceBuilder& SetAllowMangled(bool allow_mangled);
253 NewResource Build();
254
255 private:
256 NewResource res_;
257};
258
Adam Lesinski71be7052017-12-12 16:48:07 -0800259// The container and index for all resources defined for an app.
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800260class ResourceTable {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700261 public:
Ryan Mitchell9634efb2021-03-19 14:53:17 -0700262 enum class Validation {
263 kEnabled,
264 kDisabled,
265 };
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800266
Ryan Mitchell83a37ad2018-08-06 16:32:24 -0700267 enum class CollisionResult { kKeepBoth, kKeepOriginal, kConflict, kTakeNew };
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700268
Ryan Mitchell9634efb2021-03-19 14:53:17 -0700269 ResourceTable() = default;
270 explicit ResourceTable(Validation validation);
Adam Lesinski5c3464c2016-08-24 16:03:48 -0700271
Ryan Mitchell9634efb2021-03-19 14:53:17 -0700272 bool AddResource(NewResource&& res, IDiagnostics* diag);
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800273
Ryan Mitchell9634efb2021-03-19 14:53:17 -0700274 // Retrieves a sorted a view of the packages, types, and entries sorted in ascending resource id
275 // order.
276 ResourceTableView GetPartitionedView() const;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800277
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700278 struct SearchResult {
279 ResourceTablePackage* package;
280 ResourceTableType* type;
281 ResourceEntry* entry;
282 };
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700283
Adam Lesinski71be7052017-12-12 16:48:07 -0800284 Maybe<SearchResult> FindResource(const ResourceNameRef& name) const;
Ryan Mitchell9634efb2021-03-19 14:53:17 -0700285 Maybe<SearchResult> FindResource(const ResourceNameRef& name, ResourceId id) const;
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700286
Adam Lesinski71be7052017-12-12 16:48:07 -0800287 // Returns the package struct with the given name, or nullptr if such a package does not
288 // exist. The empty string is a valid package and typically is used to represent the
289 // 'current' package before it is known to the ResourceTable.
290 ResourceTablePackage* FindPackage(const android::StringPiece& name) const;
Ryan Mitchell9634efb2021-03-19 14:53:17 -0700291 ResourceTablePackage* FindOrCreatePackage(const android::StringPiece& name);
David Chaloupkae3c1a4a2018-01-18 13:44:36 +0000292
Shane Farmer0a5b2012017-06-22 12:24:12 -0700293 std::unique_ptr<ResourceTable> Clone() const;
294
Ryan Mitchell9634efb2021-03-19 14:53:17 -0700295 // When a collision of resources occurs, this method decides which value to keep.
296 static CollisionResult ResolveValueCollision(Value* existing, Value* incoming);
297
Adam Lesinski71be7052017-12-12 16:48:07 -0800298 // 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.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700304 StringPool string_pool;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800305
David Chaloupkae3c1a4a2018-01-18 13:44:36 +0000306 // The list of packages in this table, sorted alphabetically by package name and increasing
307 // package ID (missing ID being the lowest).
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700308 std::vector<std::unique_ptr<ResourceTablePackage>> packages;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800309
Adam Lesinskiceb9b2f2017-02-16 12:05:42 -0800310 // 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_;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700313
314 private:
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700315 DISALLOW_COPY_AND_ASSIGN(ResourceTable);
Ryan Mitchell9634efb2021-03-19 14:53:17 -0700316
317 Validation validation_ = Validation::kEnabled;
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800318};
319
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700320} // namespace aapt
Adam Lesinski6f6ceb72014-11-14 14:48:12 -0800321
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700322#endif // AAPT_RESOURCE_TABLE_H