blob: 382b088e4bbad579c61a0f1fb3c98f2f438b9d86 [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
Adam Lesinskicacb28f2016-10-19 12:18:14 -070021#include "ResourceUtils.h"
Brandon Liu7de701f2024-06-11 18:51:39 +000022#include "android-base/logging.h"
23#include "process/SymbolTable.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") {
Brandon Liua35bf782022-11-03 19:04:31 +000072 // pathPattern starts with '.' or '*' does not need leading slash.
73 // Reference starts with @ does not need leading slash.
74 if (*startChar == '/' || *startChar == '.' || *startChar == '*' || *startChar == '@') {
Brandon Liu3cff2552022-10-19 18:51:07 +000075 return true;
76 } else {
77 diag->Error(android::DiagMessage(data_el->line_number)
78 << "attribute 'android:" << attr_name << "' in <" << data_el->name
79 << "> tag has value of '" << attr_value
80 << "', it must be in a pattern start with '.' or '*', otherwise must start "
81 "with a leading slash '/'");
82 return false;
83 }
84 } else {
Brandon Liua35bf782022-11-03 19:04:31 +000085 // Reference starts with @ does not need leading slash.
86 if (*startChar == '/' || *startChar == '@') {
Brandon Liu3cff2552022-10-19 18:51:07 +000087 return true;
88 } else {
89 diag->Error(android::DiagMessage(data_el->line_number)
90 << "attribute 'android:" << attr_name << "' in <" << data_el->name
91 << "> tag has value of '" << attr_value
92 << "', it must start with a leading slash '/'");
93 return false;
94 }
95 }
96 }
97 return true;
98}
99
100static bool VerifyDeepLinkIntentAction(xml::Element* intent_filter_el,
101 android::SourcePathDiagnostics* diag) {
102 if (!HasDeepLink(intent_filter_el)) {
103 return true;
104 }
105
106 xml::Element* data_el = intent_filter_el->FindChild({}, "data");
107 if (data_el != nullptr) {
108 if (!VerifyDeeplinkPathAttribute(data_el, diag, "path")) {
109 return false;
110 }
111 if (!VerifyDeeplinkPathAttribute(data_el, diag, "pathPrefix")) {
112 return false;
113 }
114 if (!VerifyDeeplinkPathAttribute(data_el, diag, "pathPattern")) {
115 return false;
116 }
117 }
118 return true;
119}
120
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000121static bool RequiredNameIsNotEmpty(xml::Element* el, android::SourcePathDiagnostics* diag) {
Adam Lesinskifca5e422017-12-20 15:03:36 -0800122 xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "name");
123 if (attr == nullptr) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000124 diag->Error(android::DiagMessage(el->line_number)
Adam Lesinskifca5e422017-12-20 15:03:36 -0800125 << "<" << el->name << "> is missing attribute 'android:name'");
126 return false;
127 }
128
129 if (attr->value.empty()) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000130 diag->Error(android::DiagMessage(el->line_number)
Adam Lesinskifca5e422017-12-20 15:03:36 -0800131 << "attribute 'android:name' in <" << el->name << "> tag must not be empty");
132 return false;
133 }
134 return true;
135}
136
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800137// This is how PackageManager builds class names from AndroidManifest.xml entries.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700138static bool NameIsJavaClassName(xml::Element* el, xml::Attribute* attr,
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000139 android::SourcePathDiagnostics* diag) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700140 // We allow unqualified class names (ie: .HelloActivity)
141 // Since we don't know the package name, we can just make a fake one here and
142 // the test will be identical as long as the real package name is valid too.
Ryan Mitchell4382e442021-07-14 12:53:01 -0700143 std::optional<std::string> fully_qualified_class_name =
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700144 util::GetFullyQualifiedClassName("a", attr->value);
Adam Lesinskicc5609d2016-04-05 12:41:07 -0700145
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700146 StringPiece qualified_class_name = fully_qualified_class_name
147 ? fully_qualified_class_name.value()
148 : attr->value;
Adam Lesinskid0f116b2016-07-08 15:00:32 -0700149
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700150 if (!util::IsJavaClassName(qualified_class_name)) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000151 diag->Error(android::DiagMessage(el->line_number) << "attribute 'android:name' in <" << el->name
152 << "> tag must be a valid Java class name");
Adam Lesinski52364f72016-01-11 13:10:24 -0800153 return false;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700154 }
155 return true;
156}
157
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000158static bool OptionalNameIsJavaClassName(xml::Element* el, android::SourcePathDiagnostics* diag) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700159 if (xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "name")) {
160 return NameIsJavaClassName(el, attr, diag);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700161 }
162 return true;
163}
164
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000165static bool RequiredNameIsJavaClassName(xml::Element* el, android::SourcePathDiagnostics* diag) {
Adam Lesinskifca5e422017-12-20 15:03:36 -0800166 xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "name");
167 if (attr == nullptr) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000168 diag->Error(android::DiagMessage(el->line_number)
Adam Lesinskifca5e422017-12-20 15:03:36 -0800169 << "<" << el->name << "> is missing attribute 'android:name'");
170 return false;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700171 }
Adam Lesinskifca5e422017-12-20 15:03:36 -0800172 return NameIsJavaClassName(el, attr, diag);
Adam Lesinski52364f72016-01-11 13:10:24 -0800173}
174
Brandon Liu7de701f2024-06-11 18:51:39 +0000175static bool UpdateConfigChangesIfNeeded(xml::Element* el, IAaptContext* context) {
176 xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "configChanges");
177 if (attr == nullptr) {
178 return true;
179 }
180
181 if (attr->value != "allKnown" && attr->value.find("allKnown") != std::string::npos) {
182 context->GetDiagnostics()->Error(
183 android::DiagMessage(el->line_number)
184 << "If you want to declare 'allKnown' in attribute 'android:configChanges' in <" << el->name
185 << ">, " << attr->value << " is not allowed', allKnown has to be used "
186 << "by itself, for example: 'android:configChanges=allKnown', it cannot be combined with "
187 << "the other flags");
188 return false;
189 }
190
191 if (attr->value == "allKnown") {
192 SymbolTable* symbol_table = context->GetExternalSymbols();
193 const SymbolTable::Symbol* symbol =
194 symbol_table->FindByName(ResourceName("android", ResourceType::kAttr, "configChanges"));
195
196 if (symbol == nullptr) {
197 context->GetDiagnostics()->Error(
198 android::DiagMessage(el->line_number)
199 << "Cannot find symbol for android:configChanges with min sdk: "
200 << context->GetMinSdkVersion());
Brandon Liub9b08c42024-07-12 17:48:56 +0000201 return false;
Brandon Liu7de701f2024-06-11 18:51:39 +0000202 }
203
204 std::stringstream new_value;
205
206 const auto& symbols = symbol->attribute->symbols;
207 for (auto it = symbols.begin(); it != symbols.end(); ++it) {
208 // Skip 'resourcesUnused' which is the flag to fully disable activity restart specifically
209 // for games.
210 if (it->symbol.name.value().entry == "resourcesUnused") {
211 continue;
212 }
213 if (it != symbols.begin()) {
214 new_value << "|";
215 }
216 new_value << it->symbol.name.value().entry;
217 }
218 const auto& old_value = attr->value;
219 auto new_value_str = new_value.str();
220 context->GetDiagnostics()->Note(android::DiagMessage(el->line_number)
221 << "Updating value of 'android:configChanges' from "
222 << old_value << " to " << new_value_str);
223 attr->value = std::move(new_value_str);
224 }
225 return true;
226}
227
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000228static bool RequiredNameIsJavaPackage(xml::Element* el, android::SourcePathDiagnostics* diag) {
Adam Lesinskifca5e422017-12-20 15:03:36 -0800229 xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "name");
230 if (attr == nullptr) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000231 diag->Error(android::DiagMessage(el->line_number)
Adam Lesinskifca5e422017-12-20 15:03:36 -0800232 << "<" << el->name << "> is missing attribute 'android:name'");
233 return false;
Adam Lesinskiceb9b2f2017-02-16 12:05:42 -0800234 }
Adam Lesinskifca5e422017-12-20 15:03:36 -0800235
236 if (!util::IsJavaPackageName(attr->value)) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000237 diag->Error(android::DiagMessage(el->line_number) << "attribute 'android:name' in <" << el->name
238 << "> tag must be a valid Java package name");
Adam Lesinskifca5e422017-12-20 15:03:36 -0800239 return false;
240 }
241 return true;
Adam Lesinskiceb9b2f2017-02-16 12:05:42 -0800242}
243
Adam Lesinskib5dc4bd2017-02-22 19:29:29 -0800244static xml::XmlNodeAction::ActionFuncWithDiag RequiredAndroidAttribute(const std::string& attr) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000245 return [=](xml::Element* el, android::SourcePathDiagnostics* diag) -> bool {
Adam Lesinskib5dc4bd2017-02-22 19:29:29 -0800246 if (el->FindAttribute(xml::kSchemaAndroid, attr) == nullptr) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000247 diag->Error(android::DiagMessage(el->line_number)
Adam Lesinskib5dc4bd2017-02-22 19:29:29 -0800248 << "<" << el->name << "> is missing required attribute 'android:" << attr << "'");
249 return false;
250 }
251 return true;
252 };
253}
254
Todd Kennedyce3e1292020-10-29 17:14:24 -0700255static xml::XmlNodeAction::ActionFuncWithDiag RequiredOneAndroidAttribute(
256 const std::string& attrName1, const std::string& attrName2) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000257 return [=](xml::Element* el, android::SourcePathDiagnostics* diag) -> bool {
Todd Kennedyce3e1292020-10-29 17:14:24 -0700258 xml::Attribute* attr1 = el->FindAttribute(xml::kSchemaAndroid, attrName1);
259 xml::Attribute* attr2 = el->FindAttribute(xml::kSchemaAndroid, attrName2);
260 if (attr1 == nullptr && attr2 == nullptr) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000261 diag->Error(android::DiagMessage(el->line_number)
Todd Kennedyce3e1292020-10-29 17:14:24 -0700262 << "<" << el->name << "> is missing required attribute 'android:" << attrName1
263 << "' or 'android:" << attrName2 << "'");
264 return false;
265 }
266 if (attr1 != nullptr && attr2 != nullptr) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000267 diag->Error(android::DiagMessage(el->line_number)
Todd Kennedyce3e1292020-10-29 17:14:24 -0700268 << "<" << el->name << "> can only specify one of attribute 'android:" << attrName1
269 << "' or 'android:" << attrName2 << "'");
270 return false;
271 }
272 return true;
273 };
274}
275
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000276static bool AutoGenerateIsFeatureSplit(xml::Element* el, android::SourcePathDiagnostics* diag) {
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800277 constexpr const char* kFeatureSplit = "featureSplit";
278 constexpr const char* kIsFeatureSplit = "isFeatureSplit";
279
280 xml::Attribute* attr = el->FindAttribute({}, kFeatureSplit);
281 if (attr != nullptr) {
282 // Rewrite the featureSplit attribute to be "split". This is what the
283 // platform recognizes.
284 attr->name = "split";
285
286 // Now inject the android:isFeatureSplit="true" attribute.
287 xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, kIsFeatureSplit);
288 if (attr != nullptr) {
Ryan Mitchell4382e442021-07-14 12:53:01 -0700289 if (!ResourceUtils::ParseBool(attr->value).value_or(false)) {
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800290 // The isFeatureSplit attribute is false, which conflicts with the use
291 // of "featureSplit".
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000292 diag->Error(android::DiagMessage(el->line_number)
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800293 << "attribute 'featureSplit' used in <manifest> but 'android:isFeatureSplit' "
294 "is not 'true'");
295 return false;
296 }
297
298 // The attribute is already there and set to true, nothing to do.
299 } else {
300 el->attributes.push_back(xml::Attribute{xml::kSchemaAndroid, kIsFeatureSplit, "true"});
301 }
302 }
303 return true;
304}
305
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000306static bool AutoGenerateIsSplitRequired(xml::Element* el, android::SourcePathDiagnostics* diag) {
Jackal Guo0c01abb2021-07-30 22:17:43 +0800307 constexpr const char* kRequiredSplitTypes = "requiredSplitTypes";
308 constexpr const char* kIsSplitRequired = "isSplitRequired";
309
310 xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, kRequiredSplitTypes);
311 if (attr != nullptr) {
312 // Now inject the android:isSplitRequired="true" attribute.
313 xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, kIsSplitRequired);
314 if (attr != nullptr) {
315 if (!ResourceUtils::ParseBool(attr->value).value_or(false)) {
316 // The isFeatureSplit attribute is false, which conflicts with the use
317 // of "featureSplit".
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000318 diag->Error(android::DiagMessage(el->line_number)
Jackal Guo0c01abb2021-07-30 22:17:43 +0800319 << "attribute 'requiredSplitTypes' used in <manifest> but "
320 "'android:isSplitRequired' is not 'true'");
321 return false;
322 }
323 // The attribute is already there and set to true, nothing to do.
324 } else {
325 el->attributes.push_back(xml::Attribute{xml::kSchemaAndroid, kIsSplitRequired, "true"});
326 }
327 }
328 return true;
329}
330
Rhed Jao2c434422020-11-12 10:48:03 +0800331static bool VerifyManifest(xml::Element* el, xml::XmlActionExecutorPolicy policy,
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000332 android::SourcePathDiagnostics* diag) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700333 xml::Attribute* attr = el->FindAttribute({}, "package");
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700334 if (!attr) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000335 diag->Error(android::DiagMessage(el->line_number)
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700336 << "<manifest> tag is missing 'package' attribute");
337 return false;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700338 } else if (ResourceUtils::IsReference(attr->value)) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000339 diag->Error(android::DiagMessage(el->line_number)
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800340 << "attribute 'package' in <manifest> tag must not be a reference");
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700341 return false;
Adam Lesinski96ea08f2017-11-06 10:44:46 -0800342 } else if (!util::IsAndroidPackageName(attr->value)) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000343 android::DiagMessage error_msg(el->line_number);
Rhed Jao2c434422020-11-12 10:48:03 +0800344 error_msg << "attribute 'package' in <manifest> tag is not a valid Android package name: '"
345 << attr->value << "'";
346 if (policy == xml::XmlActionExecutorPolicy::kAllowListWarning) {
347 // Treat the error only as a warning.
348 diag->Warn(error_msg);
349 } else {
350 diag->Error(error_msg);
351 return false;
352 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700353 }
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800354
355 attr = el->FindAttribute({}, "split");
356 if (attr) {
357 if (!util::IsJavaPackageName(attr->value)) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000358 diag->Error(android::DiagMessage(el->line_number)
359 << "attribute 'split' in <manifest> tag is not a "
360 "valid split name");
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800361 return false;
362 }
363 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700364 return true;
Adam Lesinski52364f72016-01-11 13:10:24 -0800365}
366
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800367// The coreApp attribute in <manifest> is not a regular AAPT attribute, so type
368// checking on it is manual.
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000369static bool FixCoreAppAttribute(xml::Element* el, android::SourcePathDiagnostics* diag) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700370 if (xml::Attribute* attr = el->FindAttribute("", "coreApp")) {
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800371 std::unique_ptr<BinaryPrimitive> result = ResourceUtils::TryParseBool(attr->value);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700372 if (!result) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000373 diag->Error(android::DiagMessage(el->line_number) << "attribute coreApp must be a boolean");
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700374 return false;
Adam Lesinski6b17d2c2016-08-10 11:37:06 -0700375 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700376 attr->compiled_value = std::move(result);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700377 }
378 return true;
Adam Lesinski6b17d2c2016-08-10 11:37:06 -0700379}
380
Adam Lesinski86d67df2017-01-31 13:47:27 -0800381// Checks that <uses-feature> has android:glEsVersion or android:name, not both (or neither).
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000382static bool VerifyUsesFeature(xml::Element* el, android::SourcePathDiagnostics* diag) {
Adam Lesinski86d67df2017-01-31 13:47:27 -0800383 bool has_name = false;
384 if (xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "name")) {
385 if (attr->value.empty()) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000386 diag->Error(android::DiagMessage(el->line_number)
Adam Lesinski86d67df2017-01-31 13:47:27 -0800387 << "android:name in <uses-feature> must not be empty");
388 return false;
389 }
390 has_name = true;
391 }
392
393 bool has_gl_es_version = false;
Yi Kongd6507882023-12-05 17:06:08 +0900394 if (el->FindAttribute(xml::kSchemaAndroid, "glEsVersion")) {
Adam Lesinski86d67df2017-01-31 13:47:27 -0800395 if (has_name) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000396 diag->Error(android::DiagMessage(el->line_number)
Adam Lesinski86d67df2017-01-31 13:47:27 -0800397 << "cannot define both android:name and android:glEsVersion in <uses-feature>");
398 return false;
399 }
400 has_gl_es_version = true;
401 }
402
403 if (!has_name && !has_gl_es_version) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000404 diag->Error(android::DiagMessage(el->line_number)
Adam Lesinski86d67df2017-01-31 13:47:27 -0800405 << "<uses-feature> must have either android:name or android:glEsVersion attribute");
406 return false;
407 }
408 return true;
409}
410
Donald Chai6e497352019-05-19 21:07:50 -0700411// Ensure that 'ns_decls' contains a declaration for 'uri', using 'prefix' as
412// the xmlns prefix if possible.
413static void EnsureNamespaceIsDeclared(const std::string& prefix, const std::string& uri,
414 std::vector<xml::NamespaceDecl>* ns_decls) {
415 if (std::find_if(ns_decls->begin(), ns_decls->end(), [&](const xml::NamespaceDecl& ns_decl) {
416 return ns_decl.uri == uri;
417 }) != ns_decls->end()) {
418 return;
419 }
420
421 std::set<std::string> used_prefixes;
422 for (const auto& ns_decl : *ns_decls) {
423 used_prefixes.insert(ns_decl.prefix);
424 }
425
426 // Make multiple attempts in the unlikely event that 'prefix' is already taken.
427 std::string disambiguator;
428 for (int i = 0; i < used_prefixes.size() + 1; i++) {
429 std::string attempted_prefix = prefix + disambiguator;
430 if (used_prefixes.find(attempted_prefix) == used_prefixes.end()) {
431 ns_decls->push_back(xml::NamespaceDecl{attempted_prefix, uri});
432 return;
433 }
434 disambiguator = std::to_string(i);
435 }
436}
437
Brandon Liu7de701f2024-06-11 18:51:39 +0000438bool ManifestFixer::BuildRules(xml::XmlActionExecutor* executor, IAaptContext* context) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700439 // First verify some options.
Brandon Liu7de701f2024-06-11 18:51:39 +0000440 android::IDiagnostics* diag = context->GetDiagnostics();
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700441 if (options_.rename_manifest_package) {
442 if (!util::IsJavaPackageName(options_.rename_manifest_package.value())) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000443 diag->Error(android::DiagMessage() << "invalid manifest package override '"
444 << options_.rename_manifest_package.value() << "'");
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700445 return false;
446 }
447 }
448
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700449 if (options_.rename_instrumentation_target_package) {
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800450 if (!util::IsJavaPackageName(options_.rename_instrumentation_target_package.value())) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000451 diag->Error(android::DiagMessage()
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700452 << "invalid instrumentation target package override '"
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000453 << options_.rename_instrumentation_target_package.value() << "'");
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700454 return false;
455 }
456 }
457
Roshan Piusae12ce42020-04-25 16:08:55 -0700458 if (options_.rename_overlay_target_package) {
459 if (!util::IsJavaPackageName(options_.rename_overlay_target_package.value())) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000460 diag->Error(android::DiagMessage() << "invalid overlay target package override '"
461 << options_.rename_overlay_target_package.value() << "'");
Roshan Piusae12ce42020-04-25 16:08:55 -0700462 return false;
463 }
464 }
465
Adam Lesinski86d67df2017-01-31 13:47:27 -0800466 // Common <intent-filter> actions.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700467 xml::XmlNodeAction intent_filter_action;
Brandon Liu3cff2552022-10-19 18:51:07 +0000468 intent_filter_action.Action(VerifyDeepLinkIntentAction);
Adam Lesinskifca5e422017-12-20 15:03:36 -0800469 intent_filter_action["action"].Action(RequiredNameIsNotEmpty);
470 intent_filter_action["category"].Action(RequiredNameIsNotEmpty);
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700471 intent_filter_action["data"];
William Lohd3145842023-12-06 11:11:19 -0800472 intent_filter_action["uri-relative-filter-group"];
473 intent_filter_action["uri-relative-filter-group"]["data"];
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700474
Adam Lesinski86d67df2017-01-31 13:47:27 -0800475 // Common <meta-data> actions.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700476 xml::XmlNodeAction meta_data_action;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700477
Todd Kennedyce3e1292020-10-29 17:14:24 -0700478 // Common <property> actions.
479 xml::XmlNodeAction property_action;
480 property_action.Action(RequiredOneAndroidAttribute("resource", "value"));
481
Adam Lesinski86d67df2017-01-31 13:47:27 -0800482 // Common <uses-feature> actions.
483 xml::XmlNodeAction uses_feature_action;
484 uses_feature_action.Action(VerifyUsesFeature);
485
486 // Common component actions.
487 xml::XmlNodeAction component_action;
488 component_action.Action(RequiredNameIsJavaClassName);
Brandon Liu7de701f2024-06-11 18:51:39 +0000489 component_action.Action(
490 [context](xml::Element* el) -> bool { return UpdateConfigChangesIfNeeded(el, context); });
Adam Lesinski86d67df2017-01-31 13:47:27 -0800491 component_action["intent-filter"] = intent_filter_action;
Ryan Mitchell28afe682018-09-07 14:33:14 -0700492 component_action["preferred"] = intent_filter_action;
Adam Lesinski86d67df2017-01-31 13:47:27 -0800493 component_action["meta-data"] = meta_data_action;
Todd Kennedyce3e1292020-10-29 17:14:24 -0700494 component_action["property"] = property_action;
Adam Lesinski86d67df2017-01-31 13:47:27 -0800495
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700496 // Manifest actions.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700497 xml::XmlNodeAction& manifest_action = (*executor)["manifest"];
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800498 manifest_action.Action(AutoGenerateIsFeatureSplit);
Jackal Guo0c01abb2021-07-30 22:17:43 +0800499 manifest_action.Action(AutoGenerateIsSplitRequired);
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700500 manifest_action.Action(VerifyManifest);
501 manifest_action.Action(FixCoreAppAttribute);
Ryan Prichardcbcff742024-05-06 20:25:16 -0700502 manifest_action.Action([this, diag](xml::Element* el) -> bool {
Donald Chai6e497352019-05-19 21:07:50 -0700503 EnsureNamespaceIsDeclared("android", xml::kSchemaAndroid, &el->namespace_decls);
504
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700505 if (options_.version_name_default) {
Colin Crossdcd58c42018-05-25 22:46:35 -0700506 if (options_.replace_version) {
507 el->RemoveAttribute(xml::kSchemaAndroid, "versionName");
508 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700509 if (el->FindAttribute(xml::kSchemaAndroid, "versionName") == nullptr) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700510 el->attributes.push_back(
511 xml::Attribute{xml::kSchemaAndroid, "versionName",
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700512 options_.version_name_default.value()});
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700513 }
Adam Lesinskicc5609d2016-04-05 12:41:07 -0700514 }
515
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700516 if (options_.version_code_default) {
Colin Crossdcd58c42018-05-25 22:46:35 -0700517 if (options_.replace_version) {
518 el->RemoveAttribute(xml::kSchemaAndroid, "versionCode");
519 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700520 if (el->FindAttribute(xml::kSchemaAndroid, "versionCode") == nullptr) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700521 el->attributes.push_back(
522 xml::Attribute{xml::kSchemaAndroid, "versionCode",
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700523 options_.version_code_default.value()});
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700524 }
Adam Lesinskicc5609d2016-04-05 12:41:07 -0700525 }
Ryan Mitchell7cb82a82018-05-10 15:35:31 -0700526
Ryan Mitchell704090e2018-07-31 14:59:25 -0700527 if (options_.version_code_major_default) {
528 if (options_.replace_version) {
529 el->RemoveAttribute(xml::kSchemaAndroid, "versionCodeMajor");
530 }
531 if (el->FindAttribute(xml::kSchemaAndroid, "versionCodeMajor") == nullptr) {
532 el->attributes.push_back(
533 xml::Attribute{xml::kSchemaAndroid, "versionCodeMajor",
534 options_.version_code_major_default.value()});
535 }
536 }
537
Rhed Jaob9ccb8a42020-11-30 21:42:16 +0800538 if (options_.revision_code_default) {
539 if (options_.replace_version) {
540 el->RemoveAttribute(xml::kSchemaAndroid, "revisionCode");
541 }
542 if (el->FindAttribute(xml::kSchemaAndroid, "revisionCode") == nullptr) {
543 el->attributes.push_back(xml::Attribute{xml::kSchemaAndroid, "revisionCode",
544 options_.revision_code_default.value()});
545 }
546 }
547
Mark Punzalancc694e52024-04-02 20:43:23 +0000548 if (options_.non_updatable_system) {
549 if (el->FindAttribute(xml::kSchemaAndroid, "versionCode") == nullptr) {
550 el->RemoveAttribute("", "updatableSystem");
551 el->attributes.push_back(xml::Attribute{"", "updatableSystem", "false"});
552 } else {
553 diag->Note(android::DiagMessage(el->line_number)
554 << "Ignoring --non-updatable-system because the manifest has a versionCode");
555 }
556 }
557
Adam Lesinski2ae4a872015-11-02 16:10:55 -0800558 return true;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700559 });
560
561 // Meta tags.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700562 manifest_action["eat-comment"];
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700563
564 // Uses-sdk actions.
Ryan Prichardcbcff742024-05-06 20:25:16 -0700565 manifest_action["uses-sdk"].Action([this](xml::Element* el) -> bool {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700566 if (options_.min_sdk_version_default &&
567 el->FindAttribute(xml::kSchemaAndroid, "minSdkVersion") == nullptr) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700568 // There was no minSdkVersion defined and we have a default to assign.
569 el->attributes.push_back(
570 xml::Attribute{xml::kSchemaAndroid, "minSdkVersion",
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700571 options_.min_sdk_version_default.value()});
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700572 }
573
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700574 if (options_.target_sdk_version_default &&
575 el->FindAttribute(xml::kSchemaAndroid, "targetSdkVersion") == nullptr) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700576 // There was no targetSdkVersion defined and we have a default to assign.
577 el->attributes.push_back(
578 xml::Attribute{xml::kSchemaAndroid, "targetSdkVersion",
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700579 options_.target_sdk_version_default.value()});
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700580 }
581 return true;
582 });
Anton Hanssonb2f709d2020-01-09 10:25:23 +0000583 manifest_action["uses-sdk"]["extension-sdk"];
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700584
585 // Instrumentation actions.
Adam Lesinski86d67df2017-01-31 13:47:27 -0800586 manifest_action["instrumentation"].Action(RequiredNameIsJavaClassName);
Ryan Prichardcbcff742024-05-06 20:25:16 -0700587 manifest_action["instrumentation"].Action([this](xml::Element* el) -> bool {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700588 if (!options_.rename_instrumentation_target_package) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700589 return true;
590 }
591
592 if (xml::Attribute* attr =
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700593 el->FindAttribute(xml::kSchemaAndroid, "targetPackage")) {
594 attr->value = options_.rename_instrumentation_target_package.value();
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700595 }
596 return true;
597 });
Adam Lesinski86d67df2017-01-31 13:47:27 -0800598 manifest_action["instrumentation"]["meta-data"] = meta_data_action;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700599
Philip P. Moltmann12ac3f42020-03-05 15:01:29 -0800600 manifest_action["attribution"];
601 manifest_action["attribution"]["inherit-from"];
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700602 manifest_action["original-package"];
Ryan Prichardcbcff742024-05-06 20:25:16 -0700603 manifest_action["overlay"].Action([this](xml::Element* el) -> bool {
Jeremy Meyer6b05b7d2022-09-30 22:22:24 +0000604 if (options_.rename_overlay_target_package) {
605 if (xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "targetPackage")) {
606 attr->value = options_.rename_overlay_target_package.value();
607 }
Roshan Piusae12ce42020-04-25 16:08:55 -0700608 }
Jeremy Meyer6b05b7d2022-09-30 22:22:24 +0000609 if (options_.rename_overlay_category) {
610 if (xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "category")) {
611 attr->value = options_.rename_overlay_category.value();
612 } else {
613 el->attributes.push_back(xml::Attribute{xml::kSchemaAndroid, "category",
614 options_.rename_overlay_category.value()});
615 }
Roshan Piusae12ce42020-04-25 16:08:55 -0700616 }
617 return true;
618 });
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700619 manifest_action["protected-broadcast"];
Alan Viverettecf5326f2018-01-05 16:03:50 -0500620 manifest_action["adopt-permissions"];
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700621 manifest_action["uses-permission"];
Sergey Nikolaienkov65f90992020-09-30 08:17:09 +0000622 manifest_action["uses-permission"]["required-feature"].Action(RequiredNameIsNotEmpty);
623 manifest_action["uses-permission"]["required-not-feature"].Action(RequiredNameIsNotEmpty);
Adam Lesinski4b585db2017-05-12 15:25:50 -0700624 manifest_action["uses-permission-sdk-23"];
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700625 manifest_action["permission"];
Ryan Mitchell66f6cfb2018-07-25 16:15:17 -0700626 manifest_action["permission"]["meta-data"] = meta_data_action;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700627 manifest_action["permission-tree"];
628 manifest_action["permission-group"];
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700629 manifest_action["uses-configuration"];
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700630 manifest_action["supports-screens"];
Adam Lesinski86d67df2017-01-31 13:47:27 -0800631 manifest_action["uses-feature"] = uses_feature_action;
632 manifest_action["feature-group"]["uses-feature"] = uses_feature_action;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700633 manifest_action["compatible-screens"];
634 manifest_action["compatible-screens"]["screen"];
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700635 manifest_action["supports-gl-texture"];
Ryan Mitchell66f6cfb2018-07-25 16:15:17 -0700636 manifest_action["restrict-update"];
MÃ¥rten Kongstadb0502bb2022-05-16 15:23:40 +0200637 manifest_action["install-constraints"]["fingerprint-prefix"];
Ryan Mitchell66f6cfb2018-07-25 16:15:17 -0700638 manifest_action["package-verifier"];
Adam Lesinski5119e512016-12-05 19:48:20 -0800639 manifest_action["meta-data"] = meta_data_action;
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800640 manifest_action["uses-split"].Action(RequiredNameIsJavaPackage);
Patrick Baumanna4ffb452019-06-24 15:01:49 -0700641 manifest_action["queries"]["package"].Action(RequiredNameIsJavaPackage);
642 manifest_action["queries"]["intent"] = intent_filter_action;
Patrick Baumann99181232020-01-28 10:55:25 -0800643 manifest_action["queries"]["provider"].Action(RequiredAndroidAttribute("authorities"));
Patrick Baumanna4ffb452019-06-24 15:01:49 -0700644 // TODO: more complicated component name tag
Adam Lesinski5119e512016-12-05 19:48:20 -0800645
Adam Lesinski87f1e0f2017-06-27 16:21:58 -0700646 manifest_action["key-sets"]["key-set"]["public-key"];
647 manifest_action["key-sets"]["upgrade-key-set"];
648
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700649 // Application actions.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700650 xml::XmlNodeAction& application_action = manifest_action["application"];
651 application_action.Action(OptionalNameIsJavaClassName);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700652
Adam Lesinskifca5e422017-12-20 15:03:36 -0800653 application_action["uses-library"].Action(RequiredNameIsNotEmpty);
Jiyong Park6a5b8b12020-06-30 13:23:36 +0900654 application_action["uses-native-library"].Action(RequiredNameIsNotEmpty);
Adam Lesinskifca5e422017-12-20 15:03:36 -0800655 application_action["library"].Action(RequiredNameIsNotEmpty);
Chris Craik335b5652019-04-04 12:46:47 -0700656 application_action["profileable"];
Todd Kennedyce3e1292020-10-29 17:14:24 -0700657 application_action["property"] = property_action;
Adam Lesinskib5dc4bd2017-02-22 19:29:29 -0800658
659 xml::XmlNodeAction& static_library_action = application_action["static-library"];
660 static_library_action.Action(RequiredNameIsJavaPackage);
661 static_library_action.Action(RequiredAndroidAttribute("version"));
662
663 xml::XmlNodeAction& uses_static_library_action = application_action["uses-static-library"];
664 uses_static_library_action.Action(RequiredNameIsJavaPackage);
665 uses_static_library_action.Action(RequiredAndroidAttribute("version"));
666 uses_static_library_action.Action(RequiredAndroidAttribute("certDigest"));
Ryan Mitchell66f6cfb2018-07-25 16:15:17 -0700667 uses_static_library_action["additional-certificate"];
Adam Lesinskib5dc4bd2017-02-22 19:29:29 -0800668
Alex Buynytskyya16137052021-12-02 13:26:54 +0000669 xml::XmlNodeAction& sdk_library_action = application_action["sdk-library"];
670 sdk_library_action.Action(RequiredNameIsJavaPackage);
671 sdk_library_action.Action(RequiredAndroidAttribute("versionMajor"));
672
673 xml::XmlNodeAction& uses_sdk_library_action = application_action["uses-sdk-library"];
674 uses_sdk_library_action.Action(RequiredNameIsJavaPackage);
675 uses_sdk_library_action.Action(RequiredAndroidAttribute("versionMajor"));
676 uses_sdk_library_action.Action(RequiredAndroidAttribute("certDigest"));
677 uses_sdk_library_action["additional-certificate"];
678
Dianne Hackborn813d7502018-10-02 16:59:46 -0700679 xml::XmlNodeAction& uses_package_action = application_action["uses-package"];
680 uses_package_action.Action(RequiredNameIsJavaPackage);
681 uses_package_action["additional-certificate"];
682
Ryan Mitchelle5b38a62018-03-23 13:35:00 -0700683 if (options_.debug_mode) {
Ryan Prichardcbcff742024-05-06 20:25:16 -0700684 application_action.Action([](xml::Element* el) -> bool {
Ryan Mitchelle5b38a62018-03-23 13:35:00 -0700685 xml::Attribute *attr = el->FindOrCreateAttribute(xml::kSchemaAndroid, "debuggable");
686 attr->value = "true";
687 return true;
688 });
689 }
690
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700691 application_action["meta-data"] = meta_data_action;
Adam Lesinski7a917a22017-06-02 12:55:24 -0700692
Dianne Hackbornfc0839a2020-01-31 11:02:28 -0800693 application_action["processes"];
694 application_action["processes"]["deny-permission"];
695 application_action["processes"]["allow-permission"];
696 application_action["processes"]["process"]["deny-permission"];
697 application_action["processes"]["process"]["allow-permission"];
698
Adam Lesinski86d67df2017-01-31 13:47:27 -0800699 application_action["activity"] = component_action;
Adam Lesinski7a917a22017-06-02 12:55:24 -0700700 application_action["activity"]["layout"];
701
Adam Lesinski86d67df2017-01-31 13:47:27 -0800702 application_action["activity-alias"] = component_action;
703 application_action["service"] = component_action;
704 application_action["receiver"] = component_action;
Gavin Corkeryad5d4ba2021-10-26 12:24:43 +0100705 application_action["apex-system-service"] = component_action;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700706
707 // Provider actions.
Adam Lesinski86d67df2017-01-31 13:47:27 -0800708 application_action["provider"] = component_action;
Adam Lesinskic10c0d02017-04-28 12:54:08 -0700709 application_action["provider"]["grant-uri-permission"];
Adam Lesinski25783ca2017-04-24 13:33:47 -0700710 application_action["provider"]["path-permission"];
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700711
Ryan Mitchell28afe682018-09-07 14:33:14 -0700712 manifest_action["package"] = manifest_action;
713
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700714 return true;
Adam Lesinski2ae4a872015-11-02 16:10:55 -0800715}
716
Yurii Zubrytskyia5775142022-11-02 17:49:49 -0700717static void FullyQualifyClassName(StringPiece package, StringPiece attr_ns, StringPiece attr_name,
718 xml::Element* el) {
Adam Lesinski23034b92017-11-29 16:27:44 -0800719 xml::Attribute* attr = el->FindAttribute(attr_ns, attr_name);
720 if (attr != nullptr) {
Ryan Mitchell4382e442021-07-14 12:53:01 -0700721 if (std::optional<std::string> new_value =
722 util::GetFullyQualifiedClassName(package, attr->value)) {
Adam Lesinski23034b92017-11-29 16:27:44 -0800723 attr->value = std::move(new_value.value());
Adam Lesinski52364f72016-01-11 13:10:24 -0800724 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700725 }
Adam Lesinski23034b92017-11-29 16:27:44 -0800726}
Adam Lesinski52364f72016-01-11 13:10:24 -0800727
Yurii Zubrytskyia5775142022-11-02 17:49:49 -0700728static bool RenameManifestPackage(StringPiece package_override, xml::Element* manifest_el) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700729 xml::Attribute* attr = manifest_el->FindAttribute({}, "package");
Adam Lesinski52364f72016-01-11 13:10:24 -0800730
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700731 // We've already verified that the manifest element is present, with a package
732 // name specified.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700733 CHECK(attr != nullptr);
Adam Lesinski52364f72016-01-11 13:10:24 -0800734
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700735 std::string original_package = std::move(attr->value);
Yurii Zubrytskyia5775142022-11-02 17:49:49 -0700736 attr->value.assign(package_override);
Adam Lesinski52364f72016-01-11 13:10:24 -0800737
Adam Lesinski23034b92017-11-29 16:27:44 -0800738 xml::Element* application_el = manifest_el->FindChild({}, "application");
739 if (application_el != nullptr) {
740 FullyQualifyClassName(original_package, xml::kSchemaAndroid, "name", application_el);
741 FullyQualifyClassName(original_package, xml::kSchemaAndroid, "backupAgent", application_el);
742
743 for (xml::Element* child_el : application_el->GetChildElements()) {
744 if (child_el->namespace_uri.empty()) {
745 if (child_el->name == "activity" || child_el->name == "activity-alias" ||
746 child_el->name == "provider" || child_el->name == "receiver" ||
747 child_el->name == "service") {
748 FullyQualifyClassName(original_package, xml::kSchemaAndroid, "name", child_el);
Makoto Onuki808fd192021-12-10 09:40:54 -0800749 continue;
Adam Lesinski23034b92017-11-29 16:27:44 -0800750 }
751
752 if (child_el->name == "activity-alias") {
753 FullyQualifyClassName(original_package, xml::kSchemaAndroid, "targetActivity", child_el);
Makoto Onuki808fd192021-12-10 09:40:54 -0800754 continue;
755 }
756
757 if (child_el->name == "processes") {
758 for (xml::Element* grand_child_el : child_el->GetChildElements()) {
759 if (grand_child_el->name == "process") {
760 FullyQualifyClassName(original_package, xml::kSchemaAndroid, "name", grand_child_el);
761 }
762 }
763 continue;
Adam Lesinski23034b92017-11-29 16:27:44 -0800764 }
765 }
766 }
767 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700768 return true;
Adam Lesinski52364f72016-01-11 13:10:24 -0800769}
770
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700771bool ManifestFixer::Consume(IAaptContext* context, xml::XmlResource* doc) {
Fabien Sanglard2d34e762019-02-21 15:13:29 -0800772 TRACE_CALL();
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700773 xml::Element* root = xml::FindRootElement(doc->root.get());
774 if (!root || !root->namespace_uri.empty() || root->name != "manifest") {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000775 context->GetDiagnostics()->Error(android::DiagMessage(doc->file.source)
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700776 << "root tag must be <manifest>");
777 return false;
778 }
Adam Lesinski2ae4a872015-11-02 16:10:55 -0800779
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800780 if ((options_.min_sdk_version_default || options_.target_sdk_version_default) &&
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700781 root->FindChild({}, "uses-sdk") == nullptr) {
Adam Lesinskie343eb12016-10-27 16:31:58 -0700782 // Auto insert a <uses-sdk> element. This must be inserted before the
783 // <application> tag. The device runtime PackageParser will make SDK version
784 // decisions while parsing <application>.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700785 std::unique_ptr<xml::Element> uses_sdk = util::make_unique<xml::Element>();
786 uses_sdk->name = "uses-sdk";
Adam Lesinskie343eb12016-10-27 16:31:58 -0700787 root->InsertChild(0, std::move(uses_sdk));
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700788 }
Adam Lesinski2ae4a872015-11-02 16:10:55 -0800789
Alan Viverette07287be2023-05-02 16:34:27 -0400790 if (!options_.no_compile_sdk_metadata && options_.compile_sdk_version) {
Adam Lesinskic6284372017-12-04 13:46:23 -0800791 xml::Attribute* attr = root->FindOrCreateAttribute(xml::kSchemaAndroid, "compileSdkVersion");
792
793 // Make sure we un-compile the value if it was set to something else.
794 attr->compiled_value = {};
Adam Lesinskic6284372017-12-04 13:46:23 -0800795 attr->value = options_.compile_sdk_version.value();
Ryan Mitchellaada89c2019-02-12 08:06:26 -0800796
797 attr = root->FindOrCreateAttribute("", "platformBuildVersionCode");
798
799 // Make sure we un-compile the value if it was set to something else.
800 attr->compiled_value = {};
801 attr->value = options_.compile_sdk_version.value();
Adam Lesinskic6284372017-12-04 13:46:23 -0800802 }
803
Alan Viverette07287be2023-05-02 16:34:27 -0400804 if (!options_.no_compile_sdk_metadata && options_.compile_sdk_version_codename) {
Adam Lesinskic6284372017-12-04 13:46:23 -0800805 xml::Attribute* attr =
806 root->FindOrCreateAttribute(xml::kSchemaAndroid, "compileSdkVersionCodename");
807
808 // Make sure we un-compile the value if it was set to something else.
809 attr->compiled_value = {};
Ryan Mitchellaada89c2019-02-12 08:06:26 -0800810 attr->value = options_.compile_sdk_version_codename.value();
Adam Lesinskic6284372017-12-04 13:46:23 -0800811
Ryan Mitchellaada89c2019-02-12 08:06:26 -0800812 attr = root->FindOrCreateAttribute("", "platformBuildVersionName");
813
814 // Make sure we un-compile the value if it was set to something else.
815 attr->compiled_value = {};
Adam Lesinskic6284372017-12-04 13:46:23 -0800816 attr->value = options_.compile_sdk_version_codename.value();
817 }
818
Andrei Onea7109b702023-02-23 17:43:25 +0000819 if (!options_.fingerprint_prefixes.empty()) {
820 xml::Element* install_constraints_el = root->FindChild({}, "install-constraints");
821 if (install_constraints_el == nullptr) {
822 std::unique_ptr<xml::Element> install_constraints = std::make_unique<xml::Element>();
823 install_constraints->name = "install-constraints";
824 install_constraints_el = install_constraints.get();
825 root->AppendChild(std::move(install_constraints));
826 }
827 for (const std::string& prefix : options_.fingerprint_prefixes) {
828 std::unique_ptr<xml::Element> prefix_el = std::make_unique<xml::Element>();
829 prefix_el->name = "fingerprint-prefix";
830 xml::Attribute* attr = prefix_el->FindOrCreateAttribute(xml::kSchemaAndroid, "value");
831 attr->value = prefix;
832 install_constraints_el->AppendChild(std::move(prefix_el));
833 }
834 }
835
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700836 xml::XmlActionExecutor executor;
Brandon Liu7de701f2024-06-11 18:51:39 +0000837 if (!BuildRules(&executor, context)) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700838 return false;
839 }
Adam Lesinskicc5609d2016-04-05 12:41:07 -0700840
Izabela Orlowskaad9e1322017-12-19 16:22:42 +0000841 xml::XmlActionExecutorPolicy policy = options_.warn_validation
Ryan Mitchell4ea90752020-07-31 08:21:43 -0700842 ? xml::XmlActionExecutorPolicy::kAllowListWarning
843 : xml::XmlActionExecutorPolicy::kAllowList;
Izabela Orlowskaad9e1322017-12-19 16:22:42 +0000844 if (!executor.Execute(policy, context->GetDiagnostics(), doc)) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700845 return false;
846 }
Adam Lesinskicc5609d2016-04-05 12:41:07 -0700847
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700848 if (options_.rename_manifest_package) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700849 // Rename manifest package outside of the XmlActionExecutor.
Adam Lesinskie343eb12016-10-27 16:31:58 -0700850 // We need to extract the old package name and FullyQualify all class
851 // names.
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800852 if (!RenameManifestPackage(options_.rename_manifest_package.value(), root)) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700853 return false;
Adam Lesinskicc5609d2016-04-05 12:41:07 -0700854 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700855 }
856 return true;
Adam Lesinski2ae4a872015-11-02 16:10:55 -0800857}
858
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700859} // namespace aapt