blob: df09e47aa946910c25734aaf67d54662231e2e44 [file] [log] [blame]
Adam Lesinski2ae4a872015-11-02 16:10:55 -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
Adam Lesinski2ae4a872015-11-02 16:10:55 -080017#include "link/ManifestFixer.h"
Adam Lesinskice5e56e2016-10-21 17:56:45 -070018
19#include <unordered_set>
20
21#include "android-base/logging.h"
22
Adam Lesinskicacb28f2016-10-19 12:18:14 -070023#include "ResourceUtils.h"
Fabien Sanglard2d34e762019-02-21 15:13:29 -080024#include "trace/TraceBuffer.h"
Adam Lesinski2ae4a872015-11-02 16:10:55 -080025#include "util/Util.h"
Adam Lesinskicc5609d2016-04-05 12:41:07 -070026#include "xml/XmlActionExecutor.h"
Adam Lesinski467f1712015-11-16 17:35:44 -080027#include "xml/XmlDom.h"
Adam Lesinski2ae4a872015-11-02 16:10:55 -080028
Adam Lesinskid5083f62017-01-16 15:07:21 -080029using android::StringPiece;
30
Adam Lesinski2ae4a872015-11-02 16:10:55 -080031namespace aapt {
32
Brandon Liu3cff2552022-10-19 18:51:07 +000033// This is to detect whether an <intent-filter> contains deeplink.
34// See https://developer.android.com/training/app-links/deep-linking.
35static bool HasDeepLink(xml::Element* intent_filter_el) {
36 xml::Element* action_el = intent_filter_el->FindChild({}, "action");
37 xml::Element* category_el = intent_filter_el->FindChild({}, "category");
38 xml::Element* data_el = intent_filter_el->FindChild({}, "data");
39 if (action_el == nullptr || category_el == nullptr || data_el == nullptr) {
40 return false;
41 }
42
43 // Deeplinks must specify the ACTION_VIEW intent action.
44 constexpr const char* action_view = "android.intent.action.VIEW";
45 if (intent_filter_el->FindChildWithAttribute({}, "action", xml::kSchemaAndroid, "name",
46 action_view) == nullptr) {
47 return false;
48 }
49
50 // Deeplinks must have scheme included in <data> tag.
51 xml::Attribute* data_scheme_attr = data_el->FindAttribute(xml::kSchemaAndroid, "scheme");
52 if (data_scheme_attr == nullptr || data_scheme_attr->value.empty()) {
53 return false;
54 }
55
56 // Deeplinks must include BROWSABLE category.
57 constexpr const char* category_browsable = "android.intent.category.BROWSABLE";
58 if (intent_filter_el->FindChildWithAttribute({}, "category", xml::kSchemaAndroid, "name",
59 category_browsable) == nullptr) {
60 return false;
61 }
62 return true;
63}
64
65static bool VerifyDeeplinkPathAttribute(xml::Element* data_el, android::SourcePathDiagnostics* diag,
66 const std::string& attr_name) {
67 xml::Attribute* attr = data_el->FindAttribute(xml::kSchemaAndroid, attr_name);
68 if (attr != nullptr && !attr->value.empty()) {
69 StringPiece attr_value = attr->value;
70 const char* startChar = attr_value.begin();
71 if (attr_name == "pathPattern") {
72 if (*startChar == '/' || *startChar == '.' || *startChar == '*') {
73 return true;
74 } else {
75 diag->Error(android::DiagMessage(data_el->line_number)
76 << "attribute 'android:" << attr_name << "' in <" << data_el->name
77 << "> tag has value of '" << attr_value
78 << "', it must be in a pattern start with '.' or '*', otherwise must start "
79 "with a leading slash '/'");
80 return false;
81 }
82 } else {
83 if (*startChar == '/') {
84 return true;
85 } else {
86 diag->Error(android::DiagMessage(data_el->line_number)
87 << "attribute 'android:" << attr_name << "' in <" << data_el->name
88 << "> tag has value of '" << attr_value
89 << "', it must start with a leading slash '/'");
90 return false;
91 }
92 }
93 }
94 return true;
95}
96
97static bool VerifyDeepLinkIntentAction(xml::Element* intent_filter_el,
98 android::SourcePathDiagnostics* diag) {
99 if (!HasDeepLink(intent_filter_el)) {
100 return true;
101 }
102
103 xml::Element* data_el = intent_filter_el->FindChild({}, "data");
104 if (data_el != nullptr) {
105 if (!VerifyDeeplinkPathAttribute(data_el, diag, "path")) {
106 return false;
107 }
108 if (!VerifyDeeplinkPathAttribute(data_el, diag, "pathPrefix")) {
109 return false;
110 }
111 if (!VerifyDeeplinkPathAttribute(data_el, diag, "pathPattern")) {
112 return false;
113 }
114 }
115 return true;
116}
117
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000118static bool RequiredNameIsNotEmpty(xml::Element* el, android::SourcePathDiagnostics* diag) {
Adam Lesinskifca5e422017-12-20 15:03:36 -0800119 xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "name");
120 if (attr == nullptr) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000121 diag->Error(android::DiagMessage(el->line_number)
Adam Lesinskifca5e422017-12-20 15:03:36 -0800122 << "<" << el->name << "> is missing attribute 'android:name'");
123 return false;
124 }
125
126 if (attr->value.empty()) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000127 diag->Error(android::DiagMessage(el->line_number)
Adam Lesinskifca5e422017-12-20 15:03:36 -0800128 << "attribute 'android:name' in <" << el->name << "> tag must not be empty");
129 return false;
130 }
131 return true;
132}
133
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800134// This is how PackageManager builds class names from AndroidManifest.xml entries.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700135static bool NameIsJavaClassName(xml::Element* el, xml::Attribute* attr,
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000136 android::SourcePathDiagnostics* diag) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700137 // We allow unqualified class names (ie: .HelloActivity)
138 // Since we don't know the package name, we can just make a fake one here and
139 // the test will be identical as long as the real package name is valid too.
Ryan Mitchell4382e442021-07-14 12:53:01 -0700140 std::optional<std::string> fully_qualified_class_name =
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700141 util::GetFullyQualifiedClassName("a", attr->value);
Adam Lesinskicc5609d2016-04-05 12:41:07 -0700142
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700143 StringPiece qualified_class_name = fully_qualified_class_name
144 ? fully_qualified_class_name.value()
145 : attr->value;
Adam Lesinskid0f116b2016-07-08 15:00:32 -0700146
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700147 if (!util::IsJavaClassName(qualified_class_name)) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000148 diag->Error(android::DiagMessage(el->line_number) << "attribute 'android:name' in <" << el->name
149 << "> tag must be a valid Java class name");
Adam Lesinski52364f72016-01-11 13:10:24 -0800150 return false;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700151 }
152 return true;
153}
154
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000155static bool OptionalNameIsJavaClassName(xml::Element* el, android::SourcePathDiagnostics* diag) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700156 if (xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "name")) {
157 return NameIsJavaClassName(el, attr, diag);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700158 }
159 return true;
160}
161
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000162static bool RequiredNameIsJavaClassName(xml::Element* el, android::SourcePathDiagnostics* diag) {
Adam Lesinskifca5e422017-12-20 15:03:36 -0800163 xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "name");
164 if (attr == nullptr) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000165 diag->Error(android::DiagMessage(el->line_number)
Adam Lesinskifca5e422017-12-20 15:03:36 -0800166 << "<" << el->name << "> is missing attribute 'android:name'");
167 return false;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700168 }
Adam Lesinskifca5e422017-12-20 15:03:36 -0800169 return NameIsJavaClassName(el, attr, diag);
Adam Lesinski52364f72016-01-11 13:10:24 -0800170}
171
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000172static bool RequiredNameIsJavaPackage(xml::Element* el, android::SourcePathDiagnostics* diag) {
Adam Lesinskifca5e422017-12-20 15:03:36 -0800173 xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "name");
174 if (attr == nullptr) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000175 diag->Error(android::DiagMessage(el->line_number)
Adam Lesinskifca5e422017-12-20 15:03:36 -0800176 << "<" << el->name << "> is missing attribute 'android:name'");
177 return false;
Adam Lesinskiceb9b2f2017-02-16 12:05:42 -0800178 }
Adam Lesinskifca5e422017-12-20 15:03:36 -0800179
180 if (!util::IsJavaPackageName(attr->value)) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000181 diag->Error(android::DiagMessage(el->line_number) << "attribute 'android:name' in <" << el->name
182 << "> tag must be a valid Java package name");
Adam Lesinskifca5e422017-12-20 15:03:36 -0800183 return false;
184 }
185 return true;
Adam Lesinskiceb9b2f2017-02-16 12:05:42 -0800186}
187
Adam Lesinskib5dc4bd2017-02-22 19:29:29 -0800188static xml::XmlNodeAction::ActionFuncWithDiag RequiredAndroidAttribute(const std::string& attr) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000189 return [=](xml::Element* el, android::SourcePathDiagnostics* diag) -> bool {
Adam Lesinskib5dc4bd2017-02-22 19:29:29 -0800190 if (el->FindAttribute(xml::kSchemaAndroid, attr) == nullptr) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000191 diag->Error(android::DiagMessage(el->line_number)
Adam Lesinskib5dc4bd2017-02-22 19:29:29 -0800192 << "<" << el->name << "> is missing required attribute 'android:" << attr << "'");
193 return false;
194 }
195 return true;
196 };
197}
198
Todd Kennedyce3e1292020-10-29 17:14:24 -0700199static xml::XmlNodeAction::ActionFuncWithDiag RequiredOneAndroidAttribute(
200 const std::string& attrName1, const std::string& attrName2) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000201 return [=](xml::Element* el, android::SourcePathDiagnostics* diag) -> bool {
Todd Kennedyce3e1292020-10-29 17:14:24 -0700202 xml::Attribute* attr1 = el->FindAttribute(xml::kSchemaAndroid, attrName1);
203 xml::Attribute* attr2 = el->FindAttribute(xml::kSchemaAndroid, attrName2);
204 if (attr1 == nullptr && attr2 == nullptr) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000205 diag->Error(android::DiagMessage(el->line_number)
Todd Kennedyce3e1292020-10-29 17:14:24 -0700206 << "<" << el->name << "> is missing required attribute 'android:" << attrName1
207 << "' or 'android:" << attrName2 << "'");
208 return false;
209 }
210 if (attr1 != nullptr && attr2 != nullptr) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000211 diag->Error(android::DiagMessage(el->line_number)
Todd Kennedyce3e1292020-10-29 17:14:24 -0700212 << "<" << el->name << "> can only specify one of attribute 'android:" << attrName1
213 << "' or 'android:" << attrName2 << "'");
214 return false;
215 }
216 return true;
217 };
218}
219
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000220static bool AutoGenerateIsFeatureSplit(xml::Element* el, android::SourcePathDiagnostics* diag) {
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800221 constexpr const char* kFeatureSplit = "featureSplit";
222 constexpr const char* kIsFeatureSplit = "isFeatureSplit";
223
224 xml::Attribute* attr = el->FindAttribute({}, kFeatureSplit);
225 if (attr != nullptr) {
226 // Rewrite the featureSplit attribute to be "split". This is what the
227 // platform recognizes.
228 attr->name = "split";
229
230 // Now inject the android:isFeatureSplit="true" attribute.
231 xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, kIsFeatureSplit);
232 if (attr != nullptr) {
Ryan Mitchell4382e442021-07-14 12:53:01 -0700233 if (!ResourceUtils::ParseBool(attr->value).value_or(false)) {
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800234 // The isFeatureSplit attribute is false, which conflicts with the use
235 // of "featureSplit".
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000236 diag->Error(android::DiagMessage(el->line_number)
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800237 << "attribute 'featureSplit' used in <manifest> but 'android:isFeatureSplit' "
238 "is not 'true'");
239 return false;
240 }
241
242 // The attribute is already there and set to true, nothing to do.
243 } else {
244 el->attributes.push_back(xml::Attribute{xml::kSchemaAndroid, kIsFeatureSplit, "true"});
245 }
246 }
247 return true;
248}
249
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000250static bool AutoGenerateIsSplitRequired(xml::Element* el, android::SourcePathDiagnostics* diag) {
Jackal Guo0c01abb2021-07-30 22:17:43 +0800251 constexpr const char* kRequiredSplitTypes = "requiredSplitTypes";
252 constexpr const char* kIsSplitRequired = "isSplitRequired";
253
254 xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, kRequiredSplitTypes);
255 if (attr != nullptr) {
256 // Now inject the android:isSplitRequired="true" attribute.
257 xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, kIsSplitRequired);
258 if (attr != nullptr) {
259 if (!ResourceUtils::ParseBool(attr->value).value_or(false)) {
260 // The isFeatureSplit attribute is false, which conflicts with the use
261 // of "featureSplit".
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000262 diag->Error(android::DiagMessage(el->line_number)
Jackal Guo0c01abb2021-07-30 22:17:43 +0800263 << "attribute 'requiredSplitTypes' used in <manifest> but "
264 "'android:isSplitRequired' is not 'true'");
265 return false;
266 }
267 // The attribute is already there and set to true, nothing to do.
268 } else {
269 el->attributes.push_back(xml::Attribute{xml::kSchemaAndroid, kIsSplitRequired, "true"});
270 }
271 }
272 return true;
273}
274
Rhed Jao2c434422020-11-12 10:48:03 +0800275static bool VerifyManifest(xml::Element* el, xml::XmlActionExecutorPolicy policy,
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000276 android::SourcePathDiagnostics* diag) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700277 xml::Attribute* attr = el->FindAttribute({}, "package");
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700278 if (!attr) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000279 diag->Error(android::DiagMessage(el->line_number)
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700280 << "<manifest> tag is missing 'package' attribute");
281 return false;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700282 } else if (ResourceUtils::IsReference(attr->value)) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000283 diag->Error(android::DiagMessage(el->line_number)
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800284 << "attribute 'package' in <manifest> tag must not be a reference");
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700285 return false;
Adam Lesinski96ea08f2017-11-06 10:44:46 -0800286 } else if (!util::IsAndroidPackageName(attr->value)) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000287 android::DiagMessage error_msg(el->line_number);
Rhed Jao2c434422020-11-12 10:48:03 +0800288 error_msg << "attribute 'package' in <manifest> tag is not a valid Android package name: '"
289 << attr->value << "'";
290 if (policy == xml::XmlActionExecutorPolicy::kAllowListWarning) {
291 // Treat the error only as a warning.
292 diag->Warn(error_msg);
293 } else {
294 diag->Error(error_msg);
295 return false;
296 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700297 }
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800298
299 attr = el->FindAttribute({}, "split");
300 if (attr) {
301 if (!util::IsJavaPackageName(attr->value)) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000302 diag->Error(android::DiagMessage(el->line_number)
303 << "attribute 'split' in <manifest> tag is not a "
304 "valid split name");
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800305 return false;
306 }
307 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700308 return true;
Adam Lesinski52364f72016-01-11 13:10:24 -0800309}
310
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800311// The coreApp attribute in <manifest> is not a regular AAPT attribute, so type
312// checking on it is manual.
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000313static bool FixCoreAppAttribute(xml::Element* el, android::SourcePathDiagnostics* diag) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700314 if (xml::Attribute* attr = el->FindAttribute("", "coreApp")) {
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800315 std::unique_ptr<BinaryPrimitive> result = ResourceUtils::TryParseBool(attr->value);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700316 if (!result) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000317 diag->Error(android::DiagMessage(el->line_number) << "attribute coreApp must be a boolean");
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700318 return false;
Adam Lesinski6b17d2c2016-08-10 11:37:06 -0700319 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700320 attr->compiled_value = std::move(result);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700321 }
322 return true;
Adam Lesinski6b17d2c2016-08-10 11:37:06 -0700323}
324
Adam Lesinski86d67df2017-01-31 13:47:27 -0800325// Checks that <uses-feature> has android:glEsVersion or android:name, not both (or neither).
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000326static bool VerifyUsesFeature(xml::Element* el, android::SourcePathDiagnostics* diag) {
Adam Lesinski86d67df2017-01-31 13:47:27 -0800327 bool has_name = false;
328 if (xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "name")) {
329 if (attr->value.empty()) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000330 diag->Error(android::DiagMessage(el->line_number)
Adam Lesinski86d67df2017-01-31 13:47:27 -0800331 << "android:name in <uses-feature> must not be empty");
332 return false;
333 }
334 has_name = true;
335 }
336
337 bool has_gl_es_version = false;
338 if (xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "glEsVersion")) {
339 if (has_name) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000340 diag->Error(android::DiagMessage(el->line_number)
Adam Lesinski86d67df2017-01-31 13:47:27 -0800341 << "cannot define both android:name and android:glEsVersion in <uses-feature>");
342 return false;
343 }
344 has_gl_es_version = true;
345 }
346
347 if (!has_name && !has_gl_es_version) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000348 diag->Error(android::DiagMessage(el->line_number)
Adam Lesinski86d67df2017-01-31 13:47:27 -0800349 << "<uses-feature> must have either android:name or android:glEsVersion attribute");
350 return false;
351 }
352 return true;
353}
354
Donald Chai6e497352019-05-19 21:07:50 -0700355// Ensure that 'ns_decls' contains a declaration for 'uri', using 'prefix' as
356// the xmlns prefix if possible.
357static void EnsureNamespaceIsDeclared(const std::string& prefix, const std::string& uri,
358 std::vector<xml::NamespaceDecl>* ns_decls) {
359 if (std::find_if(ns_decls->begin(), ns_decls->end(), [&](const xml::NamespaceDecl& ns_decl) {
360 return ns_decl.uri == uri;
361 }) != ns_decls->end()) {
362 return;
363 }
364
365 std::set<std::string> used_prefixes;
366 for (const auto& ns_decl : *ns_decls) {
367 used_prefixes.insert(ns_decl.prefix);
368 }
369
370 // Make multiple attempts in the unlikely event that 'prefix' is already taken.
371 std::string disambiguator;
372 for (int i = 0; i < used_prefixes.size() + 1; i++) {
373 std::string attempted_prefix = prefix + disambiguator;
374 if (used_prefixes.find(attempted_prefix) == used_prefixes.end()) {
375 ns_decls->push_back(xml::NamespaceDecl{attempted_prefix, uri});
376 return;
377 }
378 disambiguator = std::to_string(i);
379 }
380}
381
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000382bool ManifestFixer::BuildRules(xml::XmlActionExecutor* executor, android::IDiagnostics* diag) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700383 // First verify some options.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700384 if (options_.rename_manifest_package) {
385 if (!util::IsJavaPackageName(options_.rename_manifest_package.value())) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000386 diag->Error(android::DiagMessage() << "invalid manifest package override '"
387 << options_.rename_manifest_package.value() << "'");
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700388 return false;
389 }
390 }
391
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700392 if (options_.rename_instrumentation_target_package) {
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800393 if (!util::IsJavaPackageName(options_.rename_instrumentation_target_package.value())) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000394 diag->Error(android::DiagMessage()
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700395 << "invalid instrumentation target package override '"
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000396 << options_.rename_instrumentation_target_package.value() << "'");
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700397 return false;
398 }
399 }
400
Roshan Piusae12ce42020-04-25 16:08:55 -0700401 if (options_.rename_overlay_target_package) {
402 if (!util::IsJavaPackageName(options_.rename_overlay_target_package.value())) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000403 diag->Error(android::DiagMessage() << "invalid overlay target package override '"
404 << options_.rename_overlay_target_package.value() << "'");
Roshan Piusae12ce42020-04-25 16:08:55 -0700405 return false;
406 }
407 }
408
Adam Lesinski86d67df2017-01-31 13:47:27 -0800409 // Common <intent-filter> actions.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700410 xml::XmlNodeAction intent_filter_action;
Brandon Liu3cff2552022-10-19 18:51:07 +0000411 intent_filter_action.Action(VerifyDeepLinkIntentAction);
Adam Lesinskifca5e422017-12-20 15:03:36 -0800412 intent_filter_action["action"].Action(RequiredNameIsNotEmpty);
413 intent_filter_action["category"].Action(RequiredNameIsNotEmpty);
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700414 intent_filter_action["data"];
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700415
Adam Lesinski86d67df2017-01-31 13:47:27 -0800416 // Common <meta-data> actions.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700417 xml::XmlNodeAction meta_data_action;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700418
Todd Kennedyce3e1292020-10-29 17:14:24 -0700419 // Common <property> actions.
420 xml::XmlNodeAction property_action;
421 property_action.Action(RequiredOneAndroidAttribute("resource", "value"));
422
Adam Lesinski86d67df2017-01-31 13:47:27 -0800423 // Common <uses-feature> actions.
424 xml::XmlNodeAction uses_feature_action;
425 uses_feature_action.Action(VerifyUsesFeature);
426
427 // Common component actions.
428 xml::XmlNodeAction component_action;
429 component_action.Action(RequiredNameIsJavaClassName);
430 component_action["intent-filter"] = intent_filter_action;
Ryan Mitchell28afe682018-09-07 14:33:14 -0700431 component_action["preferred"] = intent_filter_action;
Adam Lesinski86d67df2017-01-31 13:47:27 -0800432 component_action["meta-data"] = meta_data_action;
Todd Kennedyce3e1292020-10-29 17:14:24 -0700433 component_action["property"] = property_action;
Adam Lesinski86d67df2017-01-31 13:47:27 -0800434
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700435 // Manifest actions.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700436 xml::XmlNodeAction& manifest_action = (*executor)["manifest"];
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800437 manifest_action.Action(AutoGenerateIsFeatureSplit);
Jackal Guo0c01abb2021-07-30 22:17:43 +0800438 manifest_action.Action(AutoGenerateIsSplitRequired);
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700439 manifest_action.Action(VerifyManifest);
440 manifest_action.Action(FixCoreAppAttribute);
441 manifest_action.Action([&](xml::Element* el) -> bool {
Donald Chai6e497352019-05-19 21:07:50 -0700442 EnsureNamespaceIsDeclared("android", xml::kSchemaAndroid, &el->namespace_decls);
443
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700444 if (options_.version_name_default) {
Colin Crossdcd58c42018-05-25 22:46:35 -0700445 if (options_.replace_version) {
446 el->RemoveAttribute(xml::kSchemaAndroid, "versionName");
447 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700448 if (el->FindAttribute(xml::kSchemaAndroid, "versionName") == nullptr) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700449 el->attributes.push_back(
450 xml::Attribute{xml::kSchemaAndroid, "versionName",
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700451 options_.version_name_default.value()});
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700452 }
Adam Lesinskicc5609d2016-04-05 12:41:07 -0700453 }
454
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700455 if (options_.version_code_default) {
Colin Crossdcd58c42018-05-25 22:46:35 -0700456 if (options_.replace_version) {
457 el->RemoveAttribute(xml::kSchemaAndroid, "versionCode");
458 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700459 if (el->FindAttribute(xml::kSchemaAndroid, "versionCode") == nullptr) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700460 el->attributes.push_back(
461 xml::Attribute{xml::kSchemaAndroid, "versionCode",
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700462 options_.version_code_default.value()});
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700463 }
Adam Lesinskicc5609d2016-04-05 12:41:07 -0700464 }
Ryan Mitchell7cb82a82018-05-10 15:35:31 -0700465
Ryan Mitchell704090e2018-07-31 14:59:25 -0700466 if (options_.version_code_major_default) {
467 if (options_.replace_version) {
468 el->RemoveAttribute(xml::kSchemaAndroid, "versionCodeMajor");
469 }
470 if (el->FindAttribute(xml::kSchemaAndroid, "versionCodeMajor") == nullptr) {
471 el->attributes.push_back(
472 xml::Attribute{xml::kSchemaAndroid, "versionCodeMajor",
473 options_.version_code_major_default.value()});
474 }
475 }
476
Rhed Jaob9ccb8a42020-11-30 21:42:16 +0800477 if (options_.revision_code_default) {
478 if (options_.replace_version) {
479 el->RemoveAttribute(xml::kSchemaAndroid, "revisionCode");
480 }
481 if (el->FindAttribute(xml::kSchemaAndroid, "revisionCode") == nullptr) {
482 el->attributes.push_back(xml::Attribute{xml::kSchemaAndroid, "revisionCode",
483 options_.revision_code_default.value()});
484 }
485 }
486
Adam Lesinski2ae4a872015-11-02 16:10:55 -0800487 return true;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700488 });
489
490 // Meta tags.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700491 manifest_action["eat-comment"];
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700492
493 // Uses-sdk actions.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700494 manifest_action["uses-sdk"].Action([&](xml::Element* el) -> bool {
495 if (options_.min_sdk_version_default &&
496 el->FindAttribute(xml::kSchemaAndroid, "minSdkVersion") == nullptr) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700497 // There was no minSdkVersion defined and we have a default to assign.
498 el->attributes.push_back(
499 xml::Attribute{xml::kSchemaAndroid, "minSdkVersion",
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700500 options_.min_sdk_version_default.value()});
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700501 }
502
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700503 if (options_.target_sdk_version_default &&
504 el->FindAttribute(xml::kSchemaAndroid, "targetSdkVersion") == nullptr) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700505 // There was no targetSdkVersion defined and we have a default to assign.
506 el->attributes.push_back(
507 xml::Attribute{xml::kSchemaAndroid, "targetSdkVersion",
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700508 options_.target_sdk_version_default.value()});
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700509 }
510 return true;
511 });
Anton Hanssonb2f709d2020-01-09 10:25:23 +0000512 manifest_action["uses-sdk"]["extension-sdk"];
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700513
514 // Instrumentation actions.
Adam Lesinski86d67df2017-01-31 13:47:27 -0800515 manifest_action["instrumentation"].Action(RequiredNameIsJavaClassName);
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700516 manifest_action["instrumentation"].Action([&](xml::Element* el) -> bool {
517 if (!options_.rename_instrumentation_target_package) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700518 return true;
519 }
520
521 if (xml::Attribute* attr =
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700522 el->FindAttribute(xml::kSchemaAndroid, "targetPackage")) {
523 attr->value = options_.rename_instrumentation_target_package.value();
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700524 }
525 return true;
526 });
Adam Lesinski86d67df2017-01-31 13:47:27 -0800527 manifest_action["instrumentation"]["meta-data"] = meta_data_action;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700528
Philip P. Moltmann12ac3f42020-03-05 15:01:29 -0800529 manifest_action["attribution"];
530 manifest_action["attribution"]["inherit-from"];
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700531 manifest_action["original-package"];
Roshan Piusae12ce42020-04-25 16:08:55 -0700532 manifest_action["overlay"].Action([&](xml::Element* el) -> bool {
Jeremy Meyer6b05b7d2022-09-30 22:22:24 +0000533 if (options_.rename_overlay_target_package) {
534 if (xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "targetPackage")) {
535 attr->value = options_.rename_overlay_target_package.value();
536 }
Roshan Piusae12ce42020-04-25 16:08:55 -0700537 }
Jeremy Meyer6b05b7d2022-09-30 22:22:24 +0000538 if (options_.rename_overlay_category) {
539 if (xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "category")) {
540 attr->value = options_.rename_overlay_category.value();
541 } else {
542 el->attributes.push_back(xml::Attribute{xml::kSchemaAndroid, "category",
543 options_.rename_overlay_category.value()});
544 }
Roshan Piusae12ce42020-04-25 16:08:55 -0700545 }
546 return true;
547 });
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700548 manifest_action["protected-broadcast"];
Alan Viverettecf5326f2018-01-05 16:03:50 -0500549 manifest_action["adopt-permissions"];
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700550 manifest_action["uses-permission"];
Sergey Nikolaienkov65f90992020-09-30 08:17:09 +0000551 manifest_action["uses-permission"]["required-feature"].Action(RequiredNameIsNotEmpty);
552 manifest_action["uses-permission"]["required-not-feature"].Action(RequiredNameIsNotEmpty);
Adam Lesinski4b585db2017-05-12 15:25:50 -0700553 manifest_action["uses-permission-sdk-23"];
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700554 manifest_action["permission"];
Ryan Mitchell66f6cfb2018-07-25 16:15:17 -0700555 manifest_action["permission"]["meta-data"] = meta_data_action;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700556 manifest_action["permission-tree"];
557 manifest_action["permission-group"];
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700558 manifest_action["uses-configuration"];
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700559 manifest_action["supports-screens"];
Adam Lesinski86d67df2017-01-31 13:47:27 -0800560 manifest_action["uses-feature"] = uses_feature_action;
561 manifest_action["feature-group"]["uses-feature"] = uses_feature_action;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700562 manifest_action["compatible-screens"];
563 manifest_action["compatible-screens"]["screen"];
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700564 manifest_action["supports-gl-texture"];
Ryan Mitchell66f6cfb2018-07-25 16:15:17 -0700565 manifest_action["restrict-update"];
MÃ¥rten Kongstadb0502bb2022-05-16 15:23:40 +0200566 manifest_action["install-constraints"]["fingerprint-prefix"];
Ryan Mitchell66f6cfb2018-07-25 16:15:17 -0700567 manifest_action["package-verifier"];
Adam Lesinski5119e512016-12-05 19:48:20 -0800568 manifest_action["meta-data"] = meta_data_action;
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800569 manifest_action["uses-split"].Action(RequiredNameIsJavaPackage);
Patrick Baumanna4ffb452019-06-24 15:01:49 -0700570 manifest_action["queries"]["package"].Action(RequiredNameIsJavaPackage);
571 manifest_action["queries"]["intent"] = intent_filter_action;
Patrick Baumann99181232020-01-28 10:55:25 -0800572 manifest_action["queries"]["provider"].Action(RequiredAndroidAttribute("authorities"));
Patrick Baumanna4ffb452019-06-24 15:01:49 -0700573 // TODO: more complicated component name tag
Adam Lesinski5119e512016-12-05 19:48:20 -0800574
Adam Lesinski87f1e0f2017-06-27 16:21:58 -0700575 manifest_action["key-sets"]["key-set"]["public-key"];
576 manifest_action["key-sets"]["upgrade-key-set"];
577
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700578 // Application actions.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700579 xml::XmlNodeAction& application_action = manifest_action["application"];
580 application_action.Action(OptionalNameIsJavaClassName);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700581
Adam Lesinskifca5e422017-12-20 15:03:36 -0800582 application_action["uses-library"].Action(RequiredNameIsNotEmpty);
Jiyong Park6a5b8b12020-06-30 13:23:36 +0900583 application_action["uses-native-library"].Action(RequiredNameIsNotEmpty);
Adam Lesinskifca5e422017-12-20 15:03:36 -0800584 application_action["library"].Action(RequiredNameIsNotEmpty);
Chris Craik335b5652019-04-04 12:46:47 -0700585 application_action["profileable"];
Todd Kennedyce3e1292020-10-29 17:14:24 -0700586 application_action["property"] = property_action;
Adam Lesinskib5dc4bd2017-02-22 19:29:29 -0800587
588 xml::XmlNodeAction& static_library_action = application_action["static-library"];
589 static_library_action.Action(RequiredNameIsJavaPackage);
590 static_library_action.Action(RequiredAndroidAttribute("version"));
591
592 xml::XmlNodeAction& uses_static_library_action = application_action["uses-static-library"];
593 uses_static_library_action.Action(RequiredNameIsJavaPackage);
594 uses_static_library_action.Action(RequiredAndroidAttribute("version"));
595 uses_static_library_action.Action(RequiredAndroidAttribute("certDigest"));
Ryan Mitchell66f6cfb2018-07-25 16:15:17 -0700596 uses_static_library_action["additional-certificate"];
Adam Lesinskib5dc4bd2017-02-22 19:29:29 -0800597
Alex Buynytskyya16137052021-12-02 13:26:54 +0000598 xml::XmlNodeAction& sdk_library_action = application_action["sdk-library"];
599 sdk_library_action.Action(RequiredNameIsJavaPackage);
600 sdk_library_action.Action(RequiredAndroidAttribute("versionMajor"));
601
602 xml::XmlNodeAction& uses_sdk_library_action = application_action["uses-sdk-library"];
603 uses_sdk_library_action.Action(RequiredNameIsJavaPackage);
604 uses_sdk_library_action.Action(RequiredAndroidAttribute("versionMajor"));
605 uses_sdk_library_action.Action(RequiredAndroidAttribute("certDigest"));
606 uses_sdk_library_action["additional-certificate"];
607
Dianne Hackborn813d7502018-10-02 16:59:46 -0700608 xml::XmlNodeAction& uses_package_action = application_action["uses-package"];
609 uses_package_action.Action(RequiredNameIsJavaPackage);
610 uses_package_action["additional-certificate"];
611
Ryan Mitchelle5b38a62018-03-23 13:35:00 -0700612 if (options_.debug_mode) {
613 application_action.Action([&](xml::Element* el) -> bool {
614 xml::Attribute *attr = el->FindOrCreateAttribute(xml::kSchemaAndroid, "debuggable");
615 attr->value = "true";
616 return true;
617 });
618 }
619
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700620 application_action["meta-data"] = meta_data_action;
Adam Lesinski7a917a22017-06-02 12:55:24 -0700621
Dianne Hackbornfc0839a2020-01-31 11:02:28 -0800622 application_action["processes"];
623 application_action["processes"]["deny-permission"];
624 application_action["processes"]["allow-permission"];
625 application_action["processes"]["process"]["deny-permission"];
626 application_action["processes"]["process"]["allow-permission"];
627
Adam Lesinski86d67df2017-01-31 13:47:27 -0800628 application_action["activity"] = component_action;
Adam Lesinski7a917a22017-06-02 12:55:24 -0700629 application_action["activity"]["layout"];
630
Adam Lesinski86d67df2017-01-31 13:47:27 -0800631 application_action["activity-alias"] = component_action;
632 application_action["service"] = component_action;
633 application_action["receiver"] = component_action;
Gavin Corkeryad5d4ba2021-10-26 12:24:43 +0100634 application_action["apex-system-service"] = component_action;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700635
636 // Provider actions.
Adam Lesinski86d67df2017-01-31 13:47:27 -0800637 application_action["provider"] = component_action;
Adam Lesinskic10c0d02017-04-28 12:54:08 -0700638 application_action["provider"]["grant-uri-permission"];
Adam Lesinski25783ca2017-04-24 13:33:47 -0700639 application_action["provider"]["path-permission"];
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700640
Ryan Mitchell28afe682018-09-07 14:33:14 -0700641 manifest_action["package"] = manifest_action;
642
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700643 return true;
Adam Lesinski2ae4a872015-11-02 16:10:55 -0800644}
645
Adam Lesinski23034b92017-11-29 16:27:44 -0800646static void FullyQualifyClassName(const StringPiece& package, const StringPiece& attr_ns,
647 const StringPiece& attr_name, xml::Element* el) {
648 xml::Attribute* attr = el->FindAttribute(attr_ns, attr_name);
649 if (attr != nullptr) {
Ryan Mitchell4382e442021-07-14 12:53:01 -0700650 if (std::optional<std::string> new_value =
651 util::GetFullyQualifiedClassName(package, attr->value)) {
Adam Lesinski23034b92017-11-29 16:27:44 -0800652 attr->value = std::move(new_value.value());
Adam Lesinski52364f72016-01-11 13:10:24 -0800653 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700654 }
Adam Lesinski23034b92017-11-29 16:27:44 -0800655}
Adam Lesinski52364f72016-01-11 13:10:24 -0800656
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800657static bool RenameManifestPackage(const StringPiece& package_override, xml::Element* manifest_el) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700658 xml::Attribute* attr = manifest_el->FindAttribute({}, "package");
Adam Lesinski52364f72016-01-11 13:10:24 -0800659
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700660 // We've already verified that the manifest element is present, with a package
661 // name specified.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700662 CHECK(attr != nullptr);
Adam Lesinski52364f72016-01-11 13:10:24 -0800663
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700664 std::string original_package = std::move(attr->value);
Adam Lesinskid5083f62017-01-16 15:07:21 -0800665 attr->value = package_override.to_string();
Adam Lesinski52364f72016-01-11 13:10:24 -0800666
Adam Lesinski23034b92017-11-29 16:27:44 -0800667 xml::Element* application_el = manifest_el->FindChild({}, "application");
668 if (application_el != nullptr) {
669 FullyQualifyClassName(original_package, xml::kSchemaAndroid, "name", application_el);
670 FullyQualifyClassName(original_package, xml::kSchemaAndroid, "backupAgent", application_el);
671
672 for (xml::Element* child_el : application_el->GetChildElements()) {
673 if (child_el->namespace_uri.empty()) {
674 if (child_el->name == "activity" || child_el->name == "activity-alias" ||
675 child_el->name == "provider" || child_el->name == "receiver" ||
676 child_el->name == "service") {
677 FullyQualifyClassName(original_package, xml::kSchemaAndroid, "name", child_el);
Makoto Onuki808fd192021-12-10 09:40:54 -0800678 continue;
Adam Lesinski23034b92017-11-29 16:27:44 -0800679 }
680
681 if (child_el->name == "activity-alias") {
682 FullyQualifyClassName(original_package, xml::kSchemaAndroid, "targetActivity", child_el);
Makoto Onuki808fd192021-12-10 09:40:54 -0800683 continue;
684 }
685
686 if (child_el->name == "processes") {
687 for (xml::Element* grand_child_el : child_el->GetChildElements()) {
688 if (grand_child_el->name == "process") {
689 FullyQualifyClassName(original_package, xml::kSchemaAndroid, "name", grand_child_el);
690 }
691 }
692 continue;
Adam Lesinski23034b92017-11-29 16:27:44 -0800693 }
694 }
695 }
696 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700697 return true;
Adam Lesinski52364f72016-01-11 13:10:24 -0800698}
699
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700700bool ManifestFixer::Consume(IAaptContext* context, xml::XmlResource* doc) {
Fabien Sanglard2d34e762019-02-21 15:13:29 -0800701 TRACE_CALL();
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700702 xml::Element* root = xml::FindRootElement(doc->root.get());
703 if (!root || !root->namespace_uri.empty() || root->name != "manifest") {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000704 context->GetDiagnostics()->Error(android::DiagMessage(doc->file.source)
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700705 << "root tag must be <manifest>");
706 return false;
707 }
Adam Lesinski2ae4a872015-11-02 16:10:55 -0800708
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800709 if ((options_.min_sdk_version_default || options_.target_sdk_version_default) &&
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700710 root->FindChild({}, "uses-sdk") == nullptr) {
Adam Lesinskie343eb12016-10-27 16:31:58 -0700711 // Auto insert a <uses-sdk> element. This must be inserted before the
712 // <application> tag. The device runtime PackageParser will make SDK version
713 // decisions while parsing <application>.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700714 std::unique_ptr<xml::Element> uses_sdk = util::make_unique<xml::Element>();
715 uses_sdk->name = "uses-sdk";
Adam Lesinskie343eb12016-10-27 16:31:58 -0700716 root->InsertChild(0, std::move(uses_sdk));
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700717 }
Adam Lesinski2ae4a872015-11-02 16:10:55 -0800718
Adam Lesinskic6284372017-12-04 13:46:23 -0800719 if (options_.compile_sdk_version) {
720 xml::Attribute* attr = root->FindOrCreateAttribute(xml::kSchemaAndroid, "compileSdkVersion");
721
722 // Make sure we un-compile the value if it was set to something else.
723 attr->compiled_value = {};
Adam Lesinskic6284372017-12-04 13:46:23 -0800724 attr->value = options_.compile_sdk_version.value();
Ryan Mitchellaada89c2019-02-12 08:06:26 -0800725
726 attr = root->FindOrCreateAttribute("", "platformBuildVersionCode");
727
728 // Make sure we un-compile the value if it was set to something else.
729 attr->compiled_value = {};
730 attr->value = options_.compile_sdk_version.value();
731
Adam Lesinskic6284372017-12-04 13:46:23 -0800732 }
733
734 if (options_.compile_sdk_version_codename) {
735 xml::Attribute* attr =
736 root->FindOrCreateAttribute(xml::kSchemaAndroid, "compileSdkVersionCodename");
737
738 // Make sure we un-compile the value if it was set to something else.
739 attr->compiled_value = {};
Ryan Mitchellaada89c2019-02-12 08:06:26 -0800740 attr->value = options_.compile_sdk_version_codename.value();
Adam Lesinskic6284372017-12-04 13:46:23 -0800741
Ryan Mitchellaada89c2019-02-12 08:06:26 -0800742 attr = root->FindOrCreateAttribute("", "platformBuildVersionName");
743
744 // Make sure we un-compile the value if it was set to something else.
745 attr->compiled_value = {};
Adam Lesinskic6284372017-12-04 13:46:23 -0800746 attr->value = options_.compile_sdk_version_codename.value();
747 }
748
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700749 xml::XmlActionExecutor executor;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700750 if (!BuildRules(&executor, context->GetDiagnostics())) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700751 return false;
752 }
Adam Lesinskicc5609d2016-04-05 12:41:07 -0700753
Izabela Orlowskaad9e1322017-12-19 16:22:42 +0000754 xml::XmlActionExecutorPolicy policy = options_.warn_validation
Ryan Mitchell4ea90752020-07-31 08:21:43 -0700755 ? xml::XmlActionExecutorPolicy::kAllowListWarning
756 : xml::XmlActionExecutorPolicy::kAllowList;
Izabela Orlowskaad9e1322017-12-19 16:22:42 +0000757 if (!executor.Execute(policy, context->GetDiagnostics(), doc)) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700758 return false;
759 }
Adam Lesinskicc5609d2016-04-05 12:41:07 -0700760
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700761 if (options_.rename_manifest_package) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700762 // Rename manifest package outside of the XmlActionExecutor.
Adam Lesinskie343eb12016-10-27 16:31:58 -0700763 // We need to extract the old package name and FullyQualify all class
764 // names.
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800765 if (!RenameManifestPackage(options_.rename_manifest_package.value(), root)) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700766 return false;
Adam Lesinskicc5609d2016-04-05 12:41:07 -0700767 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700768 }
769 return true;
Adam Lesinski2ae4a872015-11-02 16:10:55 -0800770}
771
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700772} // namespace aapt