blob: c5d3284c33f45b50051c96dbd53d95337e1781d9 [file] [log] [blame]
Shane Farmer74cdea32017-05-12 16:22:36 -07001/*
2 * Copyright (C) 2017 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 AAPT2_CONFIGURATION_H
18#define AAPT2_CONFIGURATION_H
19
Shane Farmer810fd182017-09-21 14:37:44 -070020#include <set>
Shane Farmer74cdea32017-05-12 16:22:36 -070021#include <string>
22#include <unordered_map>
23#include <vector>
Shane Farmer74cdea32017-05-12 16:22:36 -070024
Shane Farmer9f0e7f12017-06-22 12:26:44 -070025#include "ConfigDescription.h"
26#include "Diagnostics.h"
Shane Farmer74cdea32017-05-12 16:22:36 -070027#include "util/Maybe.h"
28
29namespace aapt {
30
31namespace configuration {
32
33/** A mapping of group labels to group of configuration items. */
34template<class T>
35using Group = std::unordered_map<std::string, std::vector<T>>;
36
Shane Farmerefe45392017-08-21 14:39:28 -070037/** A mapping of group label to a single configuration item. */
38template <class T>
39using Entry = std::unordered_map<std::string, T>;
40
Shane Farmer74cdea32017-05-12 16:22:36 -070041/** Output artifact configuration options. */
42struct Artifact {
43 /** Name to use for output of processing foo.apk -> foo.<name>.apk. */
Shane Farmer0a5b2012017-06-22 12:24:12 -070044 Maybe<std::string> name;
Shane Farmer810fd182017-09-21 14:37:44 -070045 /**
46 * Value to add to the base Android manifest versionCode. If it is not present in the
47 * configuration file, it is set to the previous artifact + 1. If the first artifact does not have
48 * a value, artifacts are a 1 based index.
49 */
50 int version;
Shane Farmer74cdea32017-05-12 16:22:36 -070051 /** If present, uses the ABI group with this name. */
52 Maybe<std::string> abi_group;
53 /** If present, uses the screen density group with this name. */
54 Maybe<std::string> screen_density_group;
55 /** If present, uses the locale group with this name. */
56 Maybe<std::string> locale_group;
57 /** If present, uses the Android SDK group with this name. */
58 Maybe<std::string> android_sdk_group;
59 /** If present, uses the device feature group with this name. */
60 Maybe<std::string> device_feature_group;
61 /** If present, uses the OpenGL texture group with this name. */
62 Maybe<std::string> gl_texture_group;
Shane Farmer9f0e7f12017-06-22 12:26:44 -070063
64 /** Convert an artifact name template into a name string based on configuration contents. */
Shane Farmer9ecc0752017-08-24 15:55:36 -070065 Maybe<std::string> ToArtifactName(const android::StringPiece& format,
66 const android::StringPiece& apk_name, IDiagnostics* diag) const;
Shane Farmer0a5b2012017-06-22 12:24:12 -070067
68 /** Convert an artifact name template into a name string based on configuration contents. */
Shane Farmer9ecc0752017-08-24 15:55:36 -070069 Maybe<std::string> Name(const android::StringPiece& apk_name, IDiagnostics* diag) const;
Shane Farmer810fd182017-09-21 14:37:44 -070070
71 bool operator<(const Artifact& rhs) const {
72 // TODO(safarmer): Order by play store multi-APK requirements.
73 return version < rhs.version;
74 }
75
76 bool operator==(const Artifact& rhs) const {
77 return version == rhs.version;
78 }
Shane Farmer74cdea32017-05-12 16:22:36 -070079};
80
81/** Enumeration of currently supported ABIs. */
82enum class Abi {
83 kArmeV6,
84 kArmV7a,
85 kArm64V8a,
86 kX86,
87 kX86_64,
88 kMips,
89 kMips64,
90 kUniversal
91};
92
Shane Farmer57669432017-06-19 12:52:04 -070093/** Helper method to convert an ABI to a string representing the path within the APK. */
94const std::string& AbiToString(Abi abi);
95
Shane Farmer74cdea32017-05-12 16:22:36 -070096/**
97 * Represents an individual locale. When a locale is included, it must be
98 * declared from least specific to most specific, as a region does not make
99 * sense without a language. If neither the language or region are specified it
100 * acts as a special case for catch all. This can allow all locales to be kept,
101 * or compressed.
102 */
103struct Locale {
104 /** The ISO<?> standard locale language code. */
105 Maybe<std::string> lang;
106 /** The ISO<?> standard locale region code. */
107 Maybe<std::string> region;
108
109 inline friend bool operator==(const Locale& lhs, const Locale& rhs) {
110 return lhs.lang == rhs.lang && lhs.region == rhs.region;
111 }
112};
113
114// TODO: Encapsulate manifest modifications from the configuration file.
115struct AndroidManifest {
116 inline friend bool operator==(const AndroidManifest& lhs, const AndroidManifest& rhs) {
117 return true; // nothing to compare yet.
118 }
119};
120
121struct AndroidSdk {
Shane Farmer3edd4722017-09-01 14:34:22 -0700122 Maybe<int> min_sdk_version;
123 Maybe<int> target_sdk_version;
124 Maybe<int> max_sdk_version;
Shane Farmer74cdea32017-05-12 16:22:36 -0700125 Maybe<AndroidManifest> manifest;
126
Shane Farmer3edd4722017-09-01 14:34:22 -0700127 static AndroidSdk ForMinSdk(int min_sdk) {
Shane Farmerefe45392017-08-21 14:39:28 -0700128 AndroidSdk sdk;
Shane Farmer3edd4722017-09-01 14:34:22 -0700129 sdk.min_sdk_version = min_sdk;
Shane Farmerefe45392017-08-21 14:39:28 -0700130 return sdk;
131 }
132
Shane Farmer74cdea32017-05-12 16:22:36 -0700133 inline friend bool operator==(const AndroidSdk& lhs, const AndroidSdk& rhs) {
134 return lhs.min_sdk_version == rhs.min_sdk_version &&
135 lhs.target_sdk_version == rhs.target_sdk_version &&
136 lhs.max_sdk_version == rhs.max_sdk_version &&
137 lhs.manifest == rhs.manifest;
138 }
139};
140
141// TODO: Make device features more than just an arbitrary string?
142using DeviceFeature = std::string;
143
144/** Represents a mapping of texture paths to a GL texture format. */
145struct GlTexture {
146 std::string name;
147 std::vector<std::string> texture_paths;
148
149 inline friend bool operator==(const GlTexture& lhs, const GlTexture& rhs) {
150 return lhs.name == rhs.name && lhs.texture_paths == rhs.texture_paths;
151 }
152};
153
Shane Farmer280be342017-06-21 15:20:15 -0700154/** AAPT2 XML configuration file binary representation. */
155struct PostProcessingConfiguration {
Shane Farmer57669432017-06-19 12:52:04 -0700156 // TODO: Support named artifacts?
157 std::vector<Artifact> artifacts;
Shane Farmer74cdea32017-05-12 16:22:36 -0700158 Maybe<std::string> artifact_format;
159
160 Group<Abi> abi_groups;
161 Group<ConfigDescription> screen_density_groups;
Shane Farmer0a5b2012017-06-22 12:24:12 -0700162 Group<ConfigDescription> locale_groups;
Shane Farmerefe45392017-08-21 14:39:28 -0700163 Entry<AndroidSdk> android_sdk_groups;
Shane Farmer74cdea32017-05-12 16:22:36 -0700164 Group<DeviceFeature> device_feature_groups;
165 Group<GlTexture> gl_texture_groups;
Shane Farmer9ecc0752017-08-24 15:55:36 -0700166
167 /** Helper method that generates a list of artifact names and returns true on success. */
168 bool AllArtifactNames(const android::StringPiece& apk_name,
169 std::vector<std::string>* artifact_names, IDiagnostics* diag) const;
Shane Farmer74cdea32017-05-12 16:22:36 -0700170};
171
172} // namespace configuration
173
174// Forward declaration of classes used in the API.
175struct IDiagnostics;
176namespace xml {
177class Element;
178}
179
180/**
181 * XML configuration file parser for the split and optimize commands.
182 */
183class ConfigurationParser {
184 public:
Shane Farmerb1027272017-06-14 09:10:28 -0700185
186 /** Returns a ConfigurationParser for the file located at the provided path. */
187 static Maybe<ConfigurationParser> ForPath(const std::string& path);
188
Shane Farmer74cdea32017-05-12 16:22:36 -0700189 /** Returns a ConfigurationParser for the configuration in the provided file contents. */
190 static ConfigurationParser ForContents(const std::string& contents) {
191 ConfigurationParser parser{contents};
192 return parser;
193 }
194
Shane Farmer74cdea32017-05-12 16:22:36 -0700195 /** Sets the diagnostics context to use when parsing. */
196 ConfigurationParser& WithDiagnostics(IDiagnostics* diagnostics) {
197 diag_ = diagnostics;
198 return *this;
199 }
200
201 /**
202 * Parses the configuration file and returns the results. If the configuration could not be parsed
203 * the result is empty and any errors will be displayed with the provided diagnostics context.
204 */
Shane Farmer280be342017-06-21 15:20:15 -0700205 Maybe<configuration::PostProcessingConfiguration> Parse();
Shane Farmer74cdea32017-05-12 16:22:36 -0700206
207 protected:
208 /**
209 * Instantiates a new ConfigurationParser with the provided configuration file and a no-op
210 * diagnostics context. The default diagnostics context can be overridden with a call to
211 * WithDiagnostics(IDiagnostics *).
212 */
213 explicit ConfigurationParser(std::string contents);
214
215 /** Returns the current diagnostics context to any subclasses. */
216 IDiagnostics* diagnostics() {
217 return diag_;
218 }
219
220 /**
221 * An ActionHandler for processing XML elements in the XmlActionExecutor. Returns true if the
222 * element was successfully processed, otherwise returns false.
223 */
Shane Farmer280be342017-06-21 15:20:15 -0700224 using ActionHandler = std::function<bool(configuration::PostProcessingConfiguration* config,
225 xml::Element* element, IDiagnostics* diag)>;
Shane Farmer74cdea32017-05-12 16:22:36 -0700226
227 /** Handler for <artifact> tags. */
228 static ActionHandler artifact_handler_;
229 /** Handler for <artifact-format> tags. */
230 static ActionHandler artifact_format_handler_;
231 /** Handler for <abi-group> tags. */
232 static ActionHandler abi_group_handler_;
233 /** Handler for <screen-density-group> tags. */
234 static ActionHandler screen_density_group_handler_;
235 /** Handler for <locale-group> tags. */
236 static ActionHandler locale_group_handler_;
237 /** Handler for <android-sdk-group> tags. */
238 static ActionHandler android_sdk_group_handler_;
239 /** Handler for <gl-texture-group> tags. */
240 static ActionHandler gl_texture_group_handler_;
241 /** Handler for <device-feature-group> tags. */
242 static ActionHandler device_feature_group_handler_;
243
244 private:
245 /** The contents of the configuration file to parse. */
246 const std::string contents_;
247 /** The diagnostics context to send messages to. */
248 IDiagnostics* diag_;
249};
250
251} // namespace aapt
252
Shane Farmer9f0e7f12017-06-22 12:26:44 -0700253#endif // AAPT2_CONFIGURATION_H