blob: fd3a4c035076e21135324689b8865343b29b84d4 [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
Adam Lesinskifca5e422017-12-20 15:03:36 -080033static bool RequiredNameIsNotEmpty(xml::Element* el, SourcePathDiagnostics* diag) {
34 xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "name");
35 if (attr == nullptr) {
36 diag->Error(DiagMessage(el->line_number)
37 << "<" << el->name << "> is missing attribute 'android:name'");
38 return false;
39 }
40
41 if (attr->value.empty()) {
42 diag->Error(DiagMessage(el->line_number)
43 << "attribute 'android:name' in <" << el->name << "> tag must not be empty");
44 return false;
45 }
46 return true;
47}
48
Adam Lesinskib0c47ef2017-03-06 20:05:57 -080049// This is how PackageManager builds class names from AndroidManifest.xml entries.
Adam Lesinskice5e56e2016-10-21 17:56:45 -070050static bool NameIsJavaClassName(xml::Element* el, xml::Attribute* attr,
Adam Lesinskicc5609d2016-04-05 12:41:07 -070051 SourcePathDiagnostics* diag) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070052 // We allow unqualified class names (ie: .HelloActivity)
53 // Since we don't know the package name, we can just make a fake one here and
54 // the test will be identical as long as the real package name is valid too.
Adam Lesinskice5e56e2016-10-21 17:56:45 -070055 Maybe<std::string> fully_qualified_class_name =
56 util::GetFullyQualifiedClassName("a", attr->value);
Adam Lesinskicc5609d2016-04-05 12:41:07 -070057
Adam Lesinskice5e56e2016-10-21 17:56:45 -070058 StringPiece qualified_class_name = fully_qualified_class_name
59 ? fully_qualified_class_name.value()
60 : attr->value;
Adam Lesinskid0f116b2016-07-08 15:00:32 -070061
Adam Lesinskice5e56e2016-10-21 17:56:45 -070062 if (!util::IsJavaClassName(qualified_class_name)) {
63 diag->Error(DiagMessage(el->line_number)
Adam Lesinskicacb28f2016-10-19 12:18:14 -070064 << "attribute 'android:name' in <" << el->name
65 << "> tag must be a valid Java class name");
Adam Lesinski52364f72016-01-11 13:10:24 -080066 return false;
Adam Lesinskicacb28f2016-10-19 12:18:14 -070067 }
68 return true;
69}
70
Adam Lesinskiceb9b2f2017-02-16 12:05:42 -080071static bool OptionalNameIsJavaClassName(xml::Element* el, SourcePathDiagnostics* diag) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -070072 if (xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "name")) {
73 return NameIsJavaClassName(el, attr, diag);
Adam Lesinskicacb28f2016-10-19 12:18:14 -070074 }
75 return true;
76}
77
Adam Lesinskiceb9b2f2017-02-16 12:05:42 -080078static bool RequiredNameIsJavaClassName(xml::Element* el, SourcePathDiagnostics* diag) {
Adam Lesinskifca5e422017-12-20 15:03:36 -080079 xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "name");
80 if (attr == nullptr) {
81 diag->Error(DiagMessage(el->line_number)
82 << "<" << el->name << "> is missing attribute 'android:name'");
83 return false;
Adam Lesinskicacb28f2016-10-19 12:18:14 -070084 }
Adam Lesinskifca5e422017-12-20 15:03:36 -080085 return NameIsJavaClassName(el, attr, diag);
Adam Lesinski52364f72016-01-11 13:10:24 -080086}
87
Adam Lesinskiceb9b2f2017-02-16 12:05:42 -080088static bool RequiredNameIsJavaPackage(xml::Element* el, SourcePathDiagnostics* diag) {
Adam Lesinskifca5e422017-12-20 15:03:36 -080089 xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "name");
90 if (attr == nullptr) {
91 diag->Error(DiagMessage(el->line_number)
92 << "<" << el->name << "> is missing attribute 'android:name'");
93 return false;
Adam Lesinskiceb9b2f2017-02-16 12:05:42 -080094 }
Adam Lesinskifca5e422017-12-20 15:03:36 -080095
96 if (!util::IsJavaPackageName(attr->value)) {
97 diag->Error(DiagMessage(el->line_number) << "attribute 'android:name' in <" << el->name
98 << "> tag must be a valid Java package name");
99 return false;
100 }
101 return true;
Adam Lesinskiceb9b2f2017-02-16 12:05:42 -0800102}
103
Adam Lesinskib5dc4bd2017-02-22 19:29:29 -0800104static xml::XmlNodeAction::ActionFuncWithDiag RequiredAndroidAttribute(const std::string& attr) {
105 return [=](xml::Element* el, SourcePathDiagnostics* diag) -> bool {
106 if (el->FindAttribute(xml::kSchemaAndroid, attr) == nullptr) {
107 diag->Error(DiagMessage(el->line_number)
108 << "<" << el->name << "> is missing required attribute 'android:" << attr << "'");
109 return false;
110 }
111 return true;
112 };
113}
114
Todd Kennedyce3e1292020-10-29 17:14:24 -0700115static xml::XmlNodeAction::ActionFuncWithDiag RequiredOneAndroidAttribute(
116 const std::string& attrName1, const std::string& attrName2) {
117 return [=](xml::Element* el, SourcePathDiagnostics* diag) -> bool {
118 xml::Attribute* attr1 = el->FindAttribute(xml::kSchemaAndroid, attrName1);
119 xml::Attribute* attr2 = el->FindAttribute(xml::kSchemaAndroid, attrName2);
120 if (attr1 == nullptr && attr2 == nullptr) {
121 diag->Error(DiagMessage(el->line_number)
122 << "<" << el->name << "> is missing required attribute 'android:" << attrName1
123 << "' or 'android:" << attrName2 << "'");
124 return false;
125 }
126 if (attr1 != nullptr && attr2 != nullptr) {
127 diag->Error(DiagMessage(el->line_number)
128 << "<" << el->name << "> can only specify one of attribute 'android:" << attrName1
129 << "' or 'android:" << attrName2 << "'");
130 return false;
131 }
132 return true;
133 };
134}
135
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800136static bool AutoGenerateIsFeatureSplit(xml::Element* el, SourcePathDiagnostics* diag) {
137 constexpr const char* kFeatureSplit = "featureSplit";
138 constexpr const char* kIsFeatureSplit = "isFeatureSplit";
139
140 xml::Attribute* attr = el->FindAttribute({}, kFeatureSplit);
141 if (attr != nullptr) {
142 // Rewrite the featureSplit attribute to be "split". This is what the
143 // platform recognizes.
144 attr->name = "split";
145
146 // Now inject the android:isFeatureSplit="true" attribute.
147 xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, kIsFeatureSplit);
148 if (attr != nullptr) {
149 if (!ResourceUtils::ParseBool(attr->value).value_or_default(false)) {
150 // The isFeatureSplit attribute is false, which conflicts with the use
151 // of "featureSplit".
152 diag->Error(DiagMessage(el->line_number)
153 << "attribute 'featureSplit' used in <manifest> but 'android:isFeatureSplit' "
154 "is not 'true'");
155 return false;
156 }
157
158 // The attribute is already there and set to true, nothing to do.
159 } else {
160 el->attributes.push_back(xml::Attribute{xml::kSchemaAndroid, kIsFeatureSplit, "true"});
161 }
162 }
163 return true;
164}
165
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700166static bool VerifyManifest(xml::Element* el, SourcePathDiagnostics* diag) {
167 xml::Attribute* attr = el->FindAttribute({}, "package");
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700168 if (!attr) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700169 diag->Error(DiagMessage(el->line_number)
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700170 << "<manifest> tag is missing 'package' attribute");
171 return false;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700172 } else if (ResourceUtils::IsReference(attr->value)) {
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800173 diag->Error(DiagMessage(el->line_number)
174 << "attribute 'package' in <manifest> tag must not be a reference");
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700175 return false;
Adam Lesinski96ea08f2017-11-06 10:44:46 -0800176 } else if (!util::IsAndroidPackageName(attr->value)) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700177 diag->Error(DiagMessage(el->line_number)
Adam Lesinski96ea08f2017-11-06 10:44:46 -0800178 << "attribute 'package' in <manifest> tag is not a valid Android package name: '"
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700179 << attr->value << "'");
180 return false;
181 }
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800182
183 attr = el->FindAttribute({}, "split");
184 if (attr) {
185 if (!util::IsJavaPackageName(attr->value)) {
186 diag->Error(DiagMessage(el->line_number) << "attribute 'split' in <manifest> tag is not a "
187 "valid split name");
188 return false;
189 }
190 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700191 return true;
Adam Lesinski52364f72016-01-11 13:10:24 -0800192}
193
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800194// The coreApp attribute in <manifest> is not a regular AAPT attribute, so type
195// checking on it is manual.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700196static bool FixCoreAppAttribute(xml::Element* el, SourcePathDiagnostics* diag) {
197 if (xml::Attribute* attr = el->FindAttribute("", "coreApp")) {
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800198 std::unique_ptr<BinaryPrimitive> result = ResourceUtils::TryParseBool(attr->value);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700199 if (!result) {
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800200 diag->Error(DiagMessage(el->line_number) << "attribute coreApp must be a boolean");
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700201 return false;
Adam Lesinski6b17d2c2016-08-10 11:37:06 -0700202 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700203 attr->compiled_value = std::move(result);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700204 }
205 return true;
Adam Lesinski6b17d2c2016-08-10 11:37:06 -0700206}
207
Adam Lesinski86d67df2017-01-31 13:47:27 -0800208// Checks that <uses-feature> has android:glEsVersion or android:name, not both (or neither).
209static bool VerifyUsesFeature(xml::Element* el, SourcePathDiagnostics* diag) {
210 bool has_name = false;
211 if (xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "name")) {
212 if (attr->value.empty()) {
213 diag->Error(DiagMessage(el->line_number)
214 << "android:name in <uses-feature> must not be empty");
215 return false;
216 }
217 has_name = true;
218 }
219
220 bool has_gl_es_version = false;
221 if (xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "glEsVersion")) {
222 if (has_name) {
223 diag->Error(DiagMessage(el->line_number)
224 << "cannot define both android:name and android:glEsVersion in <uses-feature>");
225 return false;
226 }
227 has_gl_es_version = true;
228 }
229
230 if (!has_name && !has_gl_es_version) {
231 diag->Error(DiagMessage(el->line_number)
232 << "<uses-feature> must have either android:name or android:glEsVersion attribute");
233 return false;
234 }
235 return true;
236}
237
Donald Chai6e497352019-05-19 21:07:50 -0700238// Ensure that 'ns_decls' contains a declaration for 'uri', using 'prefix' as
239// the xmlns prefix if possible.
240static void EnsureNamespaceIsDeclared(const std::string& prefix, const std::string& uri,
241 std::vector<xml::NamespaceDecl>* ns_decls) {
242 if (std::find_if(ns_decls->begin(), ns_decls->end(), [&](const xml::NamespaceDecl& ns_decl) {
243 return ns_decl.uri == uri;
244 }) != ns_decls->end()) {
245 return;
246 }
247
248 std::set<std::string> used_prefixes;
249 for (const auto& ns_decl : *ns_decls) {
250 used_prefixes.insert(ns_decl.prefix);
251 }
252
253 // Make multiple attempts in the unlikely event that 'prefix' is already taken.
254 std::string disambiguator;
255 for (int i = 0; i < used_prefixes.size() + 1; i++) {
256 std::string attempted_prefix = prefix + disambiguator;
257 if (used_prefixes.find(attempted_prefix) == used_prefixes.end()) {
258 ns_decls->push_back(xml::NamespaceDecl{attempted_prefix, uri});
259 return;
260 }
261 disambiguator = std::to_string(i);
262 }
263}
264
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700265bool ManifestFixer::BuildRules(xml::XmlActionExecutor* executor,
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700266 IDiagnostics* diag) {
267 // First verify some options.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700268 if (options_.rename_manifest_package) {
269 if (!util::IsJavaPackageName(options_.rename_manifest_package.value())) {
270 diag->Error(DiagMessage() << "invalid manifest package override '"
271 << options_.rename_manifest_package.value()
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700272 << "'");
273 return false;
274 }
275 }
276
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700277 if (options_.rename_instrumentation_target_package) {
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800278 if (!util::IsJavaPackageName(options_.rename_instrumentation_target_package.value())) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700279 diag->Error(DiagMessage()
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700280 << "invalid instrumentation target package override '"
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700281 << options_.rename_instrumentation_target_package.value()
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700282 << "'");
283 return false;
284 }
285 }
286
Roshan Piusae12ce42020-04-25 16:08:55 -0700287 if (options_.rename_overlay_target_package) {
288 if (!util::IsJavaPackageName(options_.rename_overlay_target_package.value())) {
289 diag->Error(DiagMessage()
290 << "invalid overlay target package override '"
291 << options_.rename_overlay_target_package.value()
292 << "'");
293 return false;
294 }
295 }
296
Adam Lesinski86d67df2017-01-31 13:47:27 -0800297 // Common <intent-filter> actions.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700298 xml::XmlNodeAction intent_filter_action;
Adam Lesinskifca5e422017-12-20 15:03:36 -0800299 intent_filter_action["action"].Action(RequiredNameIsNotEmpty);
300 intent_filter_action["category"].Action(RequiredNameIsNotEmpty);
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700301 intent_filter_action["data"];
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700302
Adam Lesinski86d67df2017-01-31 13:47:27 -0800303 // Common <meta-data> actions.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700304 xml::XmlNodeAction meta_data_action;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700305
Todd Kennedyce3e1292020-10-29 17:14:24 -0700306 // Common <property> actions.
307 xml::XmlNodeAction property_action;
308 property_action.Action(RequiredOneAndroidAttribute("resource", "value"));
309
Adam Lesinski86d67df2017-01-31 13:47:27 -0800310 // Common <uses-feature> actions.
311 xml::XmlNodeAction uses_feature_action;
312 uses_feature_action.Action(VerifyUsesFeature);
313
314 // Common component actions.
315 xml::XmlNodeAction component_action;
316 component_action.Action(RequiredNameIsJavaClassName);
317 component_action["intent-filter"] = intent_filter_action;
Ryan Mitchell28afe682018-09-07 14:33:14 -0700318 component_action["preferred"] = intent_filter_action;
Adam Lesinski86d67df2017-01-31 13:47:27 -0800319 component_action["meta-data"] = meta_data_action;
Todd Kennedyce3e1292020-10-29 17:14:24 -0700320 component_action["property"] = property_action;
Adam Lesinski86d67df2017-01-31 13:47:27 -0800321
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700322 // Manifest actions.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700323 xml::XmlNodeAction& manifest_action = (*executor)["manifest"];
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800324 manifest_action.Action(AutoGenerateIsFeatureSplit);
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700325 manifest_action.Action(VerifyManifest);
326 manifest_action.Action(FixCoreAppAttribute);
327 manifest_action.Action([&](xml::Element* el) -> bool {
Donald Chai6e497352019-05-19 21:07:50 -0700328 EnsureNamespaceIsDeclared("android", xml::kSchemaAndroid, &el->namespace_decls);
329
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700330 if (options_.version_name_default) {
Colin Crossdcd58c42018-05-25 22:46:35 -0700331 if (options_.replace_version) {
332 el->RemoveAttribute(xml::kSchemaAndroid, "versionName");
333 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700334 if (el->FindAttribute(xml::kSchemaAndroid, "versionName") == nullptr) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700335 el->attributes.push_back(
336 xml::Attribute{xml::kSchemaAndroid, "versionName",
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700337 options_.version_name_default.value()});
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700338 }
Adam Lesinskicc5609d2016-04-05 12:41:07 -0700339 }
340
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700341 if (options_.version_code_default) {
Colin Crossdcd58c42018-05-25 22:46:35 -0700342 if (options_.replace_version) {
343 el->RemoveAttribute(xml::kSchemaAndroid, "versionCode");
344 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700345 if (el->FindAttribute(xml::kSchemaAndroid, "versionCode") == nullptr) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700346 el->attributes.push_back(
347 xml::Attribute{xml::kSchemaAndroid, "versionCode",
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700348 options_.version_code_default.value()});
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700349 }
Adam Lesinskicc5609d2016-04-05 12:41:07 -0700350 }
Ryan Mitchell7cb82a82018-05-10 15:35:31 -0700351
Ryan Mitchell704090e2018-07-31 14:59:25 -0700352 if (options_.version_code_major_default) {
353 if (options_.replace_version) {
354 el->RemoveAttribute(xml::kSchemaAndroid, "versionCodeMajor");
355 }
356 if (el->FindAttribute(xml::kSchemaAndroid, "versionCodeMajor") == nullptr) {
357 el->attributes.push_back(
358 xml::Attribute{xml::kSchemaAndroid, "versionCodeMajor",
359 options_.version_code_major_default.value()});
360 }
361 }
362
Adam Lesinski2ae4a872015-11-02 16:10:55 -0800363 return true;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700364 });
365
366 // Meta tags.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700367 manifest_action["eat-comment"];
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700368
369 // Uses-sdk actions.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700370 manifest_action["uses-sdk"].Action([&](xml::Element* el) -> bool {
371 if (options_.min_sdk_version_default &&
372 el->FindAttribute(xml::kSchemaAndroid, "minSdkVersion") == nullptr) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700373 // There was no minSdkVersion defined and we have a default to assign.
374 el->attributes.push_back(
375 xml::Attribute{xml::kSchemaAndroid, "minSdkVersion",
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700376 options_.min_sdk_version_default.value()});
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700377 }
378
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700379 if (options_.target_sdk_version_default &&
380 el->FindAttribute(xml::kSchemaAndroid, "targetSdkVersion") == nullptr) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700381 // There was no targetSdkVersion defined and we have a default to assign.
382 el->attributes.push_back(
383 xml::Attribute{xml::kSchemaAndroid, "targetSdkVersion",
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700384 options_.target_sdk_version_default.value()});
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700385 }
386 return true;
387 });
Anton Hanssonb2f709d2020-01-09 10:25:23 +0000388 manifest_action["uses-sdk"]["extension-sdk"];
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700389
390 // Instrumentation actions.
Adam Lesinski86d67df2017-01-31 13:47:27 -0800391 manifest_action["instrumentation"].Action(RequiredNameIsJavaClassName);
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700392 manifest_action["instrumentation"].Action([&](xml::Element* el) -> bool {
393 if (!options_.rename_instrumentation_target_package) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700394 return true;
395 }
396
397 if (xml::Attribute* attr =
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700398 el->FindAttribute(xml::kSchemaAndroid, "targetPackage")) {
399 attr->value = options_.rename_instrumentation_target_package.value();
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700400 }
401 return true;
402 });
Adam Lesinski86d67df2017-01-31 13:47:27 -0800403 manifest_action["instrumentation"]["meta-data"] = meta_data_action;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700404
Philip P. Moltmann12ac3f42020-03-05 15:01:29 -0800405 manifest_action["attribution"];
406 manifest_action["attribution"]["inherit-from"];
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700407 manifest_action["original-package"];
Roshan Piusae12ce42020-04-25 16:08:55 -0700408 manifest_action["overlay"].Action([&](xml::Element* el) -> bool {
409 if (!options_.rename_overlay_target_package) {
410 return true;
411 }
412
413 if (xml::Attribute* attr =
414 el->FindAttribute(xml::kSchemaAndroid, "targetPackage")) {
415 attr->value = options_.rename_overlay_target_package.value();
416 }
417 return true;
418 });
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700419 manifest_action["protected-broadcast"];
Alan Viverettecf5326f2018-01-05 16:03:50 -0500420 manifest_action["adopt-permissions"];
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700421 manifest_action["uses-permission"];
Sergey Nikolaienkov65f90992020-09-30 08:17:09 +0000422 manifest_action["uses-permission"]["required-feature"].Action(RequiredNameIsNotEmpty);
423 manifest_action["uses-permission"]["required-not-feature"].Action(RequiredNameIsNotEmpty);
Adam Lesinski4b585db2017-05-12 15:25:50 -0700424 manifest_action["uses-permission-sdk-23"];
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700425 manifest_action["permission"];
Ryan Mitchell66f6cfb2018-07-25 16:15:17 -0700426 manifest_action["permission"]["meta-data"] = meta_data_action;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700427 manifest_action["permission-tree"];
428 manifest_action["permission-group"];
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700429 manifest_action["uses-configuration"];
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700430 manifest_action["supports-screens"];
Adam Lesinski86d67df2017-01-31 13:47:27 -0800431 manifest_action["uses-feature"] = uses_feature_action;
432 manifest_action["feature-group"]["uses-feature"] = uses_feature_action;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700433 manifest_action["compatible-screens"];
434 manifest_action["compatible-screens"]["screen"];
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700435 manifest_action["supports-gl-texture"];
Ryan Mitchell66f6cfb2018-07-25 16:15:17 -0700436 manifest_action["restrict-update"];
437 manifest_action["package-verifier"];
Adam Lesinski5119e512016-12-05 19:48:20 -0800438 manifest_action["meta-data"] = meta_data_action;
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800439 manifest_action["uses-split"].Action(RequiredNameIsJavaPackage);
Patrick Baumanna4ffb452019-06-24 15:01:49 -0700440 manifest_action["queries"]["package"].Action(RequiredNameIsJavaPackage);
441 manifest_action["queries"]["intent"] = intent_filter_action;
Patrick Baumann99181232020-01-28 10:55:25 -0800442 manifest_action["queries"]["provider"].Action(RequiredAndroidAttribute("authorities"));
Patrick Baumanna4ffb452019-06-24 15:01:49 -0700443 // TODO: more complicated component name tag
Adam Lesinski5119e512016-12-05 19:48:20 -0800444
Adam Lesinski87f1e0f2017-06-27 16:21:58 -0700445 manifest_action["key-sets"]["key-set"]["public-key"];
446 manifest_action["key-sets"]["upgrade-key-set"];
447
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700448 // Application actions.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700449 xml::XmlNodeAction& application_action = manifest_action["application"];
450 application_action.Action(OptionalNameIsJavaClassName);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700451
Adam Lesinskifca5e422017-12-20 15:03:36 -0800452 application_action["uses-library"].Action(RequiredNameIsNotEmpty);
Jiyong Park6a5b8b12020-06-30 13:23:36 +0900453 application_action["uses-native-library"].Action(RequiredNameIsNotEmpty);
Adam Lesinskifca5e422017-12-20 15:03:36 -0800454 application_action["library"].Action(RequiredNameIsNotEmpty);
Chris Craik335b5652019-04-04 12:46:47 -0700455 application_action["profileable"];
Todd Kennedyce3e1292020-10-29 17:14:24 -0700456 application_action["property"] = property_action;
Adam Lesinskib5dc4bd2017-02-22 19:29:29 -0800457
458 xml::XmlNodeAction& static_library_action = application_action["static-library"];
459 static_library_action.Action(RequiredNameIsJavaPackage);
460 static_library_action.Action(RequiredAndroidAttribute("version"));
461
462 xml::XmlNodeAction& uses_static_library_action = application_action["uses-static-library"];
463 uses_static_library_action.Action(RequiredNameIsJavaPackage);
464 uses_static_library_action.Action(RequiredAndroidAttribute("version"));
465 uses_static_library_action.Action(RequiredAndroidAttribute("certDigest"));
Ryan Mitchell66f6cfb2018-07-25 16:15:17 -0700466 uses_static_library_action["additional-certificate"];
Adam Lesinskib5dc4bd2017-02-22 19:29:29 -0800467
Dianne Hackborn813d7502018-10-02 16:59:46 -0700468 xml::XmlNodeAction& uses_package_action = application_action["uses-package"];
469 uses_package_action.Action(RequiredNameIsJavaPackage);
470 uses_package_action["additional-certificate"];
471
Ryan Mitchelle5b38a62018-03-23 13:35:00 -0700472 if (options_.debug_mode) {
473 application_action.Action([&](xml::Element* el) -> bool {
474 xml::Attribute *attr = el->FindOrCreateAttribute(xml::kSchemaAndroid, "debuggable");
475 attr->value = "true";
476 return true;
477 });
478 }
479
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700480 application_action["meta-data"] = meta_data_action;
Adam Lesinski7a917a22017-06-02 12:55:24 -0700481
Dianne Hackbornfc0839a2020-01-31 11:02:28 -0800482 application_action["processes"];
483 application_action["processes"]["deny-permission"];
484 application_action["processes"]["allow-permission"];
485 application_action["processes"]["process"]["deny-permission"];
486 application_action["processes"]["process"]["allow-permission"];
487
Adam Lesinski86d67df2017-01-31 13:47:27 -0800488 application_action["activity"] = component_action;
Adam Lesinski7a917a22017-06-02 12:55:24 -0700489 application_action["activity"]["layout"];
490
Adam Lesinski86d67df2017-01-31 13:47:27 -0800491 application_action["activity-alias"] = component_action;
492 application_action["service"] = component_action;
493 application_action["receiver"] = component_action;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700494
495 // Provider actions.
Adam Lesinski86d67df2017-01-31 13:47:27 -0800496 application_action["provider"] = component_action;
Adam Lesinskic10c0d02017-04-28 12:54:08 -0700497 application_action["provider"]["grant-uri-permission"];
Adam Lesinski25783ca2017-04-24 13:33:47 -0700498 application_action["provider"]["path-permission"];
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700499
Ryan Mitchell28afe682018-09-07 14:33:14 -0700500 manifest_action["package"] = manifest_action;
501
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700502 return true;
Adam Lesinski2ae4a872015-11-02 16:10:55 -0800503}
504
Adam Lesinski23034b92017-11-29 16:27:44 -0800505static void FullyQualifyClassName(const StringPiece& package, const StringPiece& attr_ns,
506 const StringPiece& attr_name, xml::Element* el) {
507 xml::Attribute* attr = el->FindAttribute(attr_ns, attr_name);
508 if (attr != nullptr) {
509 if (Maybe<std::string> new_value = util::GetFullyQualifiedClassName(package, attr->value)) {
510 attr->value = std::move(new_value.value());
Adam Lesinski52364f72016-01-11 13:10:24 -0800511 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700512 }
Adam Lesinski23034b92017-11-29 16:27:44 -0800513}
Adam Lesinski52364f72016-01-11 13:10:24 -0800514
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800515static bool RenameManifestPackage(const StringPiece& package_override, xml::Element* manifest_el) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700516 xml::Attribute* attr = manifest_el->FindAttribute({}, "package");
Adam Lesinski52364f72016-01-11 13:10:24 -0800517
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700518 // We've already verified that the manifest element is present, with a package
519 // name specified.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700520 CHECK(attr != nullptr);
Adam Lesinski52364f72016-01-11 13:10:24 -0800521
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700522 std::string original_package = std::move(attr->value);
Adam Lesinskid5083f62017-01-16 15:07:21 -0800523 attr->value = package_override.to_string();
Adam Lesinski52364f72016-01-11 13:10:24 -0800524
Adam Lesinski23034b92017-11-29 16:27:44 -0800525 xml::Element* application_el = manifest_el->FindChild({}, "application");
526 if (application_el != nullptr) {
527 FullyQualifyClassName(original_package, xml::kSchemaAndroid, "name", application_el);
528 FullyQualifyClassName(original_package, xml::kSchemaAndroid, "backupAgent", application_el);
529
530 for (xml::Element* child_el : application_el->GetChildElements()) {
531 if (child_el->namespace_uri.empty()) {
532 if (child_el->name == "activity" || child_el->name == "activity-alias" ||
533 child_el->name == "provider" || child_el->name == "receiver" ||
534 child_el->name == "service") {
535 FullyQualifyClassName(original_package, xml::kSchemaAndroid, "name", child_el);
536 }
537
538 if (child_el->name == "activity-alias") {
539 FullyQualifyClassName(original_package, xml::kSchemaAndroid, "targetActivity", child_el);
540 }
541 }
542 }
543 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700544 return true;
Adam Lesinski52364f72016-01-11 13:10:24 -0800545}
546
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700547bool ManifestFixer::Consume(IAaptContext* context, xml::XmlResource* doc) {
Fabien Sanglard2d34e762019-02-21 15:13:29 -0800548 TRACE_CALL();
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700549 xml::Element* root = xml::FindRootElement(doc->root.get());
550 if (!root || !root->namespace_uri.empty() || root->name != "manifest") {
551 context->GetDiagnostics()->Error(DiagMessage(doc->file.source)
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700552 << "root tag must be <manifest>");
553 return false;
554 }
Adam Lesinski2ae4a872015-11-02 16:10:55 -0800555
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800556 if ((options_.min_sdk_version_default || options_.target_sdk_version_default) &&
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700557 root->FindChild({}, "uses-sdk") == nullptr) {
Adam Lesinskie343eb12016-10-27 16:31:58 -0700558 // Auto insert a <uses-sdk> element. This must be inserted before the
559 // <application> tag. The device runtime PackageParser will make SDK version
560 // decisions while parsing <application>.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700561 std::unique_ptr<xml::Element> uses_sdk = util::make_unique<xml::Element>();
562 uses_sdk->name = "uses-sdk";
Adam Lesinskie343eb12016-10-27 16:31:58 -0700563 root->InsertChild(0, std::move(uses_sdk));
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700564 }
Adam Lesinski2ae4a872015-11-02 16:10:55 -0800565
Adam Lesinskic6284372017-12-04 13:46:23 -0800566 if (options_.compile_sdk_version) {
567 xml::Attribute* attr = root->FindOrCreateAttribute(xml::kSchemaAndroid, "compileSdkVersion");
568
569 // Make sure we un-compile the value if it was set to something else.
570 attr->compiled_value = {};
Adam Lesinskic6284372017-12-04 13:46:23 -0800571 attr->value = options_.compile_sdk_version.value();
Ryan Mitchellaada89c2019-02-12 08:06:26 -0800572
573 attr = root->FindOrCreateAttribute("", "platformBuildVersionCode");
574
575 // Make sure we un-compile the value if it was set to something else.
576 attr->compiled_value = {};
577 attr->value = options_.compile_sdk_version.value();
578
Adam Lesinskic6284372017-12-04 13:46:23 -0800579 }
580
581 if (options_.compile_sdk_version_codename) {
582 xml::Attribute* attr =
583 root->FindOrCreateAttribute(xml::kSchemaAndroid, "compileSdkVersionCodename");
584
585 // Make sure we un-compile the value if it was set to something else.
586 attr->compiled_value = {};
Ryan Mitchellaada89c2019-02-12 08:06:26 -0800587 attr->value = options_.compile_sdk_version_codename.value();
Adam Lesinskic6284372017-12-04 13:46:23 -0800588
Ryan Mitchellaada89c2019-02-12 08:06:26 -0800589 attr = root->FindOrCreateAttribute("", "platformBuildVersionName");
590
591 // Make sure we un-compile the value if it was set to something else.
592 attr->compiled_value = {};
Adam Lesinskic6284372017-12-04 13:46:23 -0800593 attr->value = options_.compile_sdk_version_codename.value();
594 }
595
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700596 xml::XmlActionExecutor executor;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700597 if (!BuildRules(&executor, context->GetDiagnostics())) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700598 return false;
599 }
Adam Lesinskicc5609d2016-04-05 12:41:07 -0700600
Izabela Orlowskaad9e1322017-12-19 16:22:42 +0000601 xml::XmlActionExecutorPolicy policy = options_.warn_validation
Ryan Mitchell4ea90752020-07-31 08:21:43 -0700602 ? xml::XmlActionExecutorPolicy::kAllowListWarning
603 : xml::XmlActionExecutorPolicy::kAllowList;
Izabela Orlowskaad9e1322017-12-19 16:22:42 +0000604 if (!executor.Execute(policy, context->GetDiagnostics(), doc)) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700605 return false;
606 }
Adam Lesinskicc5609d2016-04-05 12:41:07 -0700607
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700608 if (options_.rename_manifest_package) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700609 // Rename manifest package outside of the XmlActionExecutor.
Adam Lesinskie343eb12016-10-27 16:31:58 -0700610 // We need to extract the old package name and FullyQualify all class
611 // names.
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800612 if (!RenameManifestPackage(options_.rename_manifest_package.value(), root)) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700613 return false;
Adam Lesinskicc5609d2016-04-05 12:41:07 -0700614 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700615 }
616 return true;
Adam Lesinski2ae4a872015-11-02 16:10:55 -0800617}
618
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700619} // namespace aapt