blob: cbf2c2fe8a9cd133ff39cf9b2b4d55ddf72bb408 [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());
201 }
202
203 std::stringstream new_value;
204
205 const auto& symbols = symbol->attribute->symbols;
206 for (auto it = symbols.begin(); it != symbols.end(); ++it) {
207 // Skip 'resourcesUnused' which is the flag to fully disable activity restart specifically
208 // for games.
209 if (it->symbol.name.value().entry == "resourcesUnused") {
210 continue;
211 }
212 if (it != symbols.begin()) {
213 new_value << "|";
214 }
215 new_value << it->symbol.name.value().entry;
216 }
217 const auto& old_value = attr->value;
218 auto new_value_str = new_value.str();
219 context->GetDiagnostics()->Note(android::DiagMessage(el->line_number)
220 << "Updating value of 'android:configChanges' from "
221 << old_value << " to " << new_value_str);
222 attr->value = std::move(new_value_str);
223 }
224 return true;
225}
226
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000227static bool RequiredNameIsJavaPackage(xml::Element* el, android::SourcePathDiagnostics* diag) {
Adam Lesinskifca5e422017-12-20 15:03:36 -0800228 xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "name");
229 if (attr == nullptr) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000230 diag->Error(android::DiagMessage(el->line_number)
Adam Lesinskifca5e422017-12-20 15:03:36 -0800231 << "<" << el->name << "> is missing attribute 'android:name'");
232 return false;
Adam Lesinskiceb9b2f2017-02-16 12:05:42 -0800233 }
Adam Lesinskifca5e422017-12-20 15:03:36 -0800234
235 if (!util::IsJavaPackageName(attr->value)) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000236 diag->Error(android::DiagMessage(el->line_number) << "attribute 'android:name' in <" << el->name
237 << "> tag must be a valid Java package name");
Adam Lesinskifca5e422017-12-20 15:03:36 -0800238 return false;
239 }
240 return true;
Adam Lesinskiceb9b2f2017-02-16 12:05:42 -0800241}
242
Adam Lesinskib5dc4bd2017-02-22 19:29:29 -0800243static xml::XmlNodeAction::ActionFuncWithDiag RequiredAndroidAttribute(const std::string& attr) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000244 return [=](xml::Element* el, android::SourcePathDiagnostics* diag) -> bool {
Adam Lesinskib5dc4bd2017-02-22 19:29:29 -0800245 if (el->FindAttribute(xml::kSchemaAndroid, attr) == nullptr) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000246 diag->Error(android::DiagMessage(el->line_number)
Adam Lesinskib5dc4bd2017-02-22 19:29:29 -0800247 << "<" << el->name << "> is missing required attribute 'android:" << attr << "'");
248 return false;
249 }
250 return true;
251 };
252}
253
Todd Kennedyce3e1292020-10-29 17:14:24 -0700254static xml::XmlNodeAction::ActionFuncWithDiag RequiredOneAndroidAttribute(
255 const std::string& attrName1, const std::string& attrName2) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000256 return [=](xml::Element* el, android::SourcePathDiagnostics* diag) -> bool {
Todd Kennedyce3e1292020-10-29 17:14:24 -0700257 xml::Attribute* attr1 = el->FindAttribute(xml::kSchemaAndroid, attrName1);
258 xml::Attribute* attr2 = el->FindAttribute(xml::kSchemaAndroid, attrName2);
259 if (attr1 == nullptr && attr2 == nullptr) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000260 diag->Error(android::DiagMessage(el->line_number)
Todd Kennedyce3e1292020-10-29 17:14:24 -0700261 << "<" << el->name << "> is missing required attribute 'android:" << attrName1
262 << "' or 'android:" << attrName2 << "'");
263 return false;
264 }
265 if (attr1 != nullptr && attr2 != nullptr) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000266 diag->Error(android::DiagMessage(el->line_number)
Todd Kennedyce3e1292020-10-29 17:14:24 -0700267 << "<" << el->name << "> can only specify one of attribute 'android:" << attrName1
268 << "' or 'android:" << attrName2 << "'");
269 return false;
270 }
271 return true;
272 };
273}
274
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000275static bool AutoGenerateIsFeatureSplit(xml::Element* el, android::SourcePathDiagnostics* diag) {
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800276 constexpr const char* kFeatureSplit = "featureSplit";
277 constexpr const char* kIsFeatureSplit = "isFeatureSplit";
278
279 xml::Attribute* attr = el->FindAttribute({}, kFeatureSplit);
280 if (attr != nullptr) {
281 // Rewrite the featureSplit attribute to be "split". This is what the
282 // platform recognizes.
283 attr->name = "split";
284
285 // Now inject the android:isFeatureSplit="true" attribute.
286 xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, kIsFeatureSplit);
287 if (attr != nullptr) {
Ryan Mitchell4382e442021-07-14 12:53:01 -0700288 if (!ResourceUtils::ParseBool(attr->value).value_or(false)) {
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800289 // The isFeatureSplit attribute is false, which conflicts with the use
290 // of "featureSplit".
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000291 diag->Error(android::DiagMessage(el->line_number)
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800292 << "attribute 'featureSplit' used in <manifest> but 'android:isFeatureSplit' "
293 "is not 'true'");
294 return false;
295 }
296
297 // The attribute is already there and set to true, nothing to do.
298 } else {
299 el->attributes.push_back(xml::Attribute{xml::kSchemaAndroid, kIsFeatureSplit, "true"});
300 }
301 }
302 return true;
303}
304
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000305static bool AutoGenerateIsSplitRequired(xml::Element* el, android::SourcePathDiagnostics* diag) {
Jackal Guo0c01abb2021-07-30 22:17:43 +0800306 constexpr const char* kRequiredSplitTypes = "requiredSplitTypes";
307 constexpr const char* kIsSplitRequired = "isSplitRequired";
308
309 xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, kRequiredSplitTypes);
310 if (attr != nullptr) {
311 // Now inject the android:isSplitRequired="true" attribute.
312 xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, kIsSplitRequired);
313 if (attr != nullptr) {
314 if (!ResourceUtils::ParseBool(attr->value).value_or(false)) {
315 // The isFeatureSplit attribute is false, which conflicts with the use
316 // of "featureSplit".
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000317 diag->Error(android::DiagMessage(el->line_number)
Jackal Guo0c01abb2021-07-30 22:17:43 +0800318 << "attribute 'requiredSplitTypes' used in <manifest> but "
319 "'android:isSplitRequired' is not 'true'");
320 return false;
321 }
322 // The attribute is already there and set to true, nothing to do.
323 } else {
324 el->attributes.push_back(xml::Attribute{xml::kSchemaAndroid, kIsSplitRequired, "true"});
325 }
326 }
327 return true;
328}
329
Rhed Jao2c434422020-11-12 10:48:03 +0800330static bool VerifyManifest(xml::Element* el, xml::XmlActionExecutorPolicy policy,
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000331 android::SourcePathDiagnostics* diag) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700332 xml::Attribute* attr = el->FindAttribute({}, "package");
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700333 if (!attr) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000334 diag->Error(android::DiagMessage(el->line_number)
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700335 << "<manifest> tag is missing 'package' attribute");
336 return false;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700337 } else if (ResourceUtils::IsReference(attr->value)) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000338 diag->Error(android::DiagMessage(el->line_number)
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800339 << "attribute 'package' in <manifest> tag must not be a reference");
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700340 return false;
Adam Lesinski96ea08f2017-11-06 10:44:46 -0800341 } else if (!util::IsAndroidPackageName(attr->value)) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000342 android::DiagMessage error_msg(el->line_number);
Rhed Jao2c434422020-11-12 10:48:03 +0800343 error_msg << "attribute 'package' in <manifest> tag is not a valid Android package name: '"
344 << attr->value << "'";
345 if (policy == xml::XmlActionExecutorPolicy::kAllowListWarning) {
346 // Treat the error only as a warning.
347 diag->Warn(error_msg);
348 } else {
349 diag->Error(error_msg);
350 return false;
351 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700352 }
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800353
354 attr = el->FindAttribute({}, "split");
355 if (attr) {
356 if (!util::IsJavaPackageName(attr->value)) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000357 diag->Error(android::DiagMessage(el->line_number)
358 << "attribute 'split' in <manifest> tag is not a "
359 "valid split name");
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800360 return false;
361 }
362 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700363 return true;
Adam Lesinski52364f72016-01-11 13:10:24 -0800364}
365
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800366// The coreApp attribute in <manifest> is not a regular AAPT attribute, so type
367// checking on it is manual.
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000368static bool FixCoreAppAttribute(xml::Element* el, android::SourcePathDiagnostics* diag) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700369 if (xml::Attribute* attr = el->FindAttribute("", "coreApp")) {
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800370 std::unique_ptr<BinaryPrimitive> result = ResourceUtils::TryParseBool(attr->value);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700371 if (!result) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000372 diag->Error(android::DiagMessage(el->line_number) << "attribute coreApp must be a boolean");
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700373 return false;
Adam Lesinski6b17d2c2016-08-10 11:37:06 -0700374 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700375 attr->compiled_value = std::move(result);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700376 }
377 return true;
Adam Lesinski6b17d2c2016-08-10 11:37:06 -0700378}
379
Adam Lesinski86d67df2017-01-31 13:47:27 -0800380// Checks that <uses-feature> has android:glEsVersion or android:name, not both (or neither).
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000381static bool VerifyUsesFeature(xml::Element* el, android::SourcePathDiagnostics* diag) {
Adam Lesinski86d67df2017-01-31 13:47:27 -0800382 bool has_name = false;
383 if (xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "name")) {
384 if (attr->value.empty()) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000385 diag->Error(android::DiagMessage(el->line_number)
Adam Lesinski86d67df2017-01-31 13:47:27 -0800386 << "android:name in <uses-feature> must not be empty");
387 return false;
388 }
389 has_name = true;
390 }
391
392 bool has_gl_es_version = false;
Yi Kongd6507882023-12-05 17:06:08 +0900393 if (el->FindAttribute(xml::kSchemaAndroid, "glEsVersion")) {
Adam Lesinski86d67df2017-01-31 13:47:27 -0800394 if (has_name) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000395 diag->Error(android::DiagMessage(el->line_number)
Adam Lesinski86d67df2017-01-31 13:47:27 -0800396 << "cannot define both android:name and android:glEsVersion in <uses-feature>");
397 return false;
398 }
399 has_gl_es_version = true;
400 }
401
402 if (!has_name && !has_gl_es_version) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000403 diag->Error(android::DiagMessage(el->line_number)
Adam Lesinski86d67df2017-01-31 13:47:27 -0800404 << "<uses-feature> must have either android:name or android:glEsVersion attribute");
405 return false;
406 }
407 return true;
408}
409
Donald Chai6e497352019-05-19 21:07:50 -0700410// Ensure that 'ns_decls' contains a declaration for 'uri', using 'prefix' as
411// the xmlns prefix if possible.
412static void EnsureNamespaceIsDeclared(const std::string& prefix, const std::string& uri,
413 std::vector<xml::NamespaceDecl>* ns_decls) {
414 if (std::find_if(ns_decls->begin(), ns_decls->end(), [&](const xml::NamespaceDecl& ns_decl) {
415 return ns_decl.uri == uri;
416 }) != ns_decls->end()) {
417 return;
418 }
419
420 std::set<std::string> used_prefixes;
421 for (const auto& ns_decl : *ns_decls) {
422 used_prefixes.insert(ns_decl.prefix);
423 }
424
425 // Make multiple attempts in the unlikely event that 'prefix' is already taken.
426 std::string disambiguator;
427 for (int i = 0; i < used_prefixes.size() + 1; i++) {
428 std::string attempted_prefix = prefix + disambiguator;
429 if (used_prefixes.find(attempted_prefix) == used_prefixes.end()) {
430 ns_decls->push_back(xml::NamespaceDecl{attempted_prefix, uri});
431 return;
432 }
433 disambiguator = std::to_string(i);
434 }
435}
436
Brandon Liu7de701f2024-06-11 18:51:39 +0000437bool ManifestFixer::BuildRules(xml::XmlActionExecutor* executor, IAaptContext* context) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700438 // First verify some options.
Brandon Liu7de701f2024-06-11 18:51:39 +0000439 android::IDiagnostics* diag = context->GetDiagnostics();
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700440 if (options_.rename_manifest_package) {
441 if (!util::IsJavaPackageName(options_.rename_manifest_package.value())) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000442 diag->Error(android::DiagMessage() << "invalid manifest package override '"
443 << options_.rename_manifest_package.value() << "'");
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700444 return false;
445 }
446 }
447
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700448 if (options_.rename_instrumentation_target_package) {
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800449 if (!util::IsJavaPackageName(options_.rename_instrumentation_target_package.value())) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000450 diag->Error(android::DiagMessage()
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700451 << "invalid instrumentation target package override '"
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000452 << options_.rename_instrumentation_target_package.value() << "'");
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700453 return false;
454 }
455 }
456
Roshan Piusae12ce42020-04-25 16:08:55 -0700457 if (options_.rename_overlay_target_package) {
458 if (!util::IsJavaPackageName(options_.rename_overlay_target_package.value())) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000459 diag->Error(android::DiagMessage() << "invalid overlay target package override '"
460 << options_.rename_overlay_target_package.value() << "'");
Roshan Piusae12ce42020-04-25 16:08:55 -0700461 return false;
462 }
463 }
464
Adam Lesinski86d67df2017-01-31 13:47:27 -0800465 // Common <intent-filter> actions.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700466 xml::XmlNodeAction intent_filter_action;
Brandon Liu3cff2552022-10-19 18:51:07 +0000467 intent_filter_action.Action(VerifyDeepLinkIntentAction);
Adam Lesinskifca5e422017-12-20 15:03:36 -0800468 intent_filter_action["action"].Action(RequiredNameIsNotEmpty);
469 intent_filter_action["category"].Action(RequiredNameIsNotEmpty);
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700470 intent_filter_action["data"];
William Lohd3145842023-12-06 11:11:19 -0800471 intent_filter_action["uri-relative-filter-group"];
472 intent_filter_action["uri-relative-filter-group"]["data"];
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700473
Adam Lesinski86d67df2017-01-31 13:47:27 -0800474 // Common <meta-data> actions.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700475 xml::XmlNodeAction meta_data_action;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700476
Todd Kennedyce3e1292020-10-29 17:14:24 -0700477 // Common <property> actions.
478 xml::XmlNodeAction property_action;
479 property_action.Action(RequiredOneAndroidAttribute("resource", "value"));
480
Adam Lesinski86d67df2017-01-31 13:47:27 -0800481 // Common <uses-feature> actions.
482 xml::XmlNodeAction uses_feature_action;
483 uses_feature_action.Action(VerifyUsesFeature);
484
485 // Common component actions.
486 xml::XmlNodeAction component_action;
487 component_action.Action(RequiredNameIsJavaClassName);
Brandon Liu7de701f2024-06-11 18:51:39 +0000488 component_action.Action(
489 [context](xml::Element* el) -> bool { return UpdateConfigChangesIfNeeded(el, context); });
Adam Lesinski86d67df2017-01-31 13:47:27 -0800490 component_action["intent-filter"] = intent_filter_action;
Ryan Mitchell28afe682018-09-07 14:33:14 -0700491 component_action["preferred"] = intent_filter_action;
Adam Lesinski86d67df2017-01-31 13:47:27 -0800492 component_action["meta-data"] = meta_data_action;
Todd Kennedyce3e1292020-10-29 17:14:24 -0700493 component_action["property"] = property_action;
Adam Lesinski86d67df2017-01-31 13:47:27 -0800494
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700495 // Manifest actions.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700496 xml::XmlNodeAction& manifest_action = (*executor)["manifest"];
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800497 manifest_action.Action(AutoGenerateIsFeatureSplit);
Jackal Guo0c01abb2021-07-30 22:17:43 +0800498 manifest_action.Action(AutoGenerateIsSplitRequired);
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700499 manifest_action.Action(VerifyManifest);
500 manifest_action.Action(FixCoreAppAttribute);
Ryan Prichardcbcff742024-05-06 20:25:16 -0700501 manifest_action.Action([this, diag](xml::Element* el) -> bool {
Donald Chai6e497352019-05-19 21:07:50 -0700502 EnsureNamespaceIsDeclared("android", xml::kSchemaAndroid, &el->namespace_decls);
503
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700504 if (options_.version_name_default) {
Colin Crossdcd58c42018-05-25 22:46:35 -0700505 if (options_.replace_version) {
506 el->RemoveAttribute(xml::kSchemaAndroid, "versionName");
507 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700508 if (el->FindAttribute(xml::kSchemaAndroid, "versionName") == nullptr) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700509 el->attributes.push_back(
510 xml::Attribute{xml::kSchemaAndroid, "versionName",
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700511 options_.version_name_default.value()});
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700512 }
Adam Lesinskicc5609d2016-04-05 12:41:07 -0700513 }
514
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700515 if (options_.version_code_default) {
Colin Crossdcd58c42018-05-25 22:46:35 -0700516 if (options_.replace_version) {
517 el->RemoveAttribute(xml::kSchemaAndroid, "versionCode");
518 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700519 if (el->FindAttribute(xml::kSchemaAndroid, "versionCode") == nullptr) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700520 el->attributes.push_back(
521 xml::Attribute{xml::kSchemaAndroid, "versionCode",
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700522 options_.version_code_default.value()});
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700523 }
Adam Lesinskicc5609d2016-04-05 12:41:07 -0700524 }
Ryan Mitchell7cb82a82018-05-10 15:35:31 -0700525
Ryan Mitchell704090e2018-07-31 14:59:25 -0700526 if (options_.version_code_major_default) {
527 if (options_.replace_version) {
528 el->RemoveAttribute(xml::kSchemaAndroid, "versionCodeMajor");
529 }
530 if (el->FindAttribute(xml::kSchemaAndroid, "versionCodeMajor") == nullptr) {
531 el->attributes.push_back(
532 xml::Attribute{xml::kSchemaAndroid, "versionCodeMajor",
533 options_.version_code_major_default.value()});
534 }
535 }
536
Rhed Jaob9ccb8a42020-11-30 21:42:16 +0800537 if (options_.revision_code_default) {
538 if (options_.replace_version) {
539 el->RemoveAttribute(xml::kSchemaAndroid, "revisionCode");
540 }
541 if (el->FindAttribute(xml::kSchemaAndroid, "revisionCode") == nullptr) {
542 el->attributes.push_back(xml::Attribute{xml::kSchemaAndroid, "revisionCode",
543 options_.revision_code_default.value()});
544 }
545 }
546
Mark Punzalancc694e52024-04-02 20:43:23 +0000547 if (options_.non_updatable_system) {
548 if (el->FindAttribute(xml::kSchemaAndroid, "versionCode") == nullptr) {
549 el->RemoveAttribute("", "updatableSystem");
550 el->attributes.push_back(xml::Attribute{"", "updatableSystem", "false"});
551 } else {
552 diag->Note(android::DiagMessage(el->line_number)
553 << "Ignoring --non-updatable-system because the manifest has a versionCode");
554 }
555 }
556
Adam Lesinski2ae4a872015-11-02 16:10:55 -0800557 return true;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700558 });
559
560 // Meta tags.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700561 manifest_action["eat-comment"];
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700562
563 // Uses-sdk actions.
Ryan Prichardcbcff742024-05-06 20:25:16 -0700564 manifest_action["uses-sdk"].Action([this](xml::Element* el) -> bool {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700565 if (options_.min_sdk_version_default &&
566 el->FindAttribute(xml::kSchemaAndroid, "minSdkVersion") == nullptr) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700567 // There was no minSdkVersion defined and we have a default to assign.
568 el->attributes.push_back(
569 xml::Attribute{xml::kSchemaAndroid, "minSdkVersion",
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700570 options_.min_sdk_version_default.value()});
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700571 }
572
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700573 if (options_.target_sdk_version_default &&
574 el->FindAttribute(xml::kSchemaAndroid, "targetSdkVersion") == nullptr) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700575 // There was no targetSdkVersion defined and we have a default to assign.
576 el->attributes.push_back(
577 xml::Attribute{xml::kSchemaAndroid, "targetSdkVersion",
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700578 options_.target_sdk_version_default.value()});
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700579 }
580 return true;
581 });
Anton Hanssonb2f709d2020-01-09 10:25:23 +0000582 manifest_action["uses-sdk"]["extension-sdk"];
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700583
584 // Instrumentation actions.
Adam Lesinski86d67df2017-01-31 13:47:27 -0800585 manifest_action["instrumentation"].Action(RequiredNameIsJavaClassName);
Ryan Prichardcbcff742024-05-06 20:25:16 -0700586 manifest_action["instrumentation"].Action([this](xml::Element* el) -> bool {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700587 if (!options_.rename_instrumentation_target_package) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700588 return true;
589 }
590
591 if (xml::Attribute* attr =
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700592 el->FindAttribute(xml::kSchemaAndroid, "targetPackage")) {
593 attr->value = options_.rename_instrumentation_target_package.value();
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700594 }
595 return true;
596 });
Adam Lesinski86d67df2017-01-31 13:47:27 -0800597 manifest_action["instrumentation"]["meta-data"] = meta_data_action;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700598
Philip P. Moltmann12ac3f42020-03-05 15:01:29 -0800599 manifest_action["attribution"];
600 manifest_action["attribution"]["inherit-from"];
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700601 manifest_action["original-package"];
Ryan Prichardcbcff742024-05-06 20:25:16 -0700602 manifest_action["overlay"].Action([this](xml::Element* el) -> bool {
Jeremy Meyer6b05b7d2022-09-30 22:22:24 +0000603 if (options_.rename_overlay_target_package) {
604 if (xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "targetPackage")) {
605 attr->value = options_.rename_overlay_target_package.value();
606 }
Roshan Piusae12ce42020-04-25 16:08:55 -0700607 }
Jeremy Meyer6b05b7d2022-09-30 22:22:24 +0000608 if (options_.rename_overlay_category) {
609 if (xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "category")) {
610 attr->value = options_.rename_overlay_category.value();
611 } else {
612 el->attributes.push_back(xml::Attribute{xml::kSchemaAndroid, "category",
613 options_.rename_overlay_category.value()});
614 }
Roshan Piusae12ce42020-04-25 16:08:55 -0700615 }
616 return true;
617 });
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700618 manifest_action["protected-broadcast"];
Alan Viverettecf5326f2018-01-05 16:03:50 -0500619 manifest_action["adopt-permissions"];
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700620 manifest_action["uses-permission"];
Sergey Nikolaienkov65f90992020-09-30 08:17:09 +0000621 manifest_action["uses-permission"]["required-feature"].Action(RequiredNameIsNotEmpty);
622 manifest_action["uses-permission"]["required-not-feature"].Action(RequiredNameIsNotEmpty);
Adam Lesinski4b585db2017-05-12 15:25:50 -0700623 manifest_action["uses-permission-sdk-23"];
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700624 manifest_action["permission"];
Ryan Mitchell66f6cfb2018-07-25 16:15:17 -0700625 manifest_action["permission"]["meta-data"] = meta_data_action;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700626 manifest_action["permission-tree"];
627 manifest_action["permission-group"];
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700628 manifest_action["uses-configuration"];
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700629 manifest_action["supports-screens"];
Adam Lesinski86d67df2017-01-31 13:47:27 -0800630 manifest_action["uses-feature"] = uses_feature_action;
631 manifest_action["feature-group"]["uses-feature"] = uses_feature_action;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700632 manifest_action["compatible-screens"];
633 manifest_action["compatible-screens"]["screen"];
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700634 manifest_action["supports-gl-texture"];
Ryan Mitchell66f6cfb2018-07-25 16:15:17 -0700635 manifest_action["restrict-update"];
MÃ¥rten Kongstadb0502bb2022-05-16 15:23:40 +0200636 manifest_action["install-constraints"]["fingerprint-prefix"];
Ryan Mitchell66f6cfb2018-07-25 16:15:17 -0700637 manifest_action["package-verifier"];
Adam Lesinski5119e512016-12-05 19:48:20 -0800638 manifest_action["meta-data"] = meta_data_action;
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800639 manifest_action["uses-split"].Action(RequiredNameIsJavaPackage);
Patrick Baumanna4ffb452019-06-24 15:01:49 -0700640 manifest_action["queries"]["package"].Action(RequiredNameIsJavaPackage);
641 manifest_action["queries"]["intent"] = intent_filter_action;
Patrick Baumann99181232020-01-28 10:55:25 -0800642 manifest_action["queries"]["provider"].Action(RequiredAndroidAttribute("authorities"));
Patrick Baumanna4ffb452019-06-24 15:01:49 -0700643 // TODO: more complicated component name tag
Adam Lesinski5119e512016-12-05 19:48:20 -0800644
Adam Lesinski87f1e0f2017-06-27 16:21:58 -0700645 manifest_action["key-sets"]["key-set"]["public-key"];
646 manifest_action["key-sets"]["upgrade-key-set"];
647
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700648 // Application actions.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700649 xml::XmlNodeAction& application_action = manifest_action["application"];
650 application_action.Action(OptionalNameIsJavaClassName);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700651
Adam Lesinskifca5e422017-12-20 15:03:36 -0800652 application_action["uses-library"].Action(RequiredNameIsNotEmpty);
Jiyong Park6a5b8b12020-06-30 13:23:36 +0900653 application_action["uses-native-library"].Action(RequiredNameIsNotEmpty);
Adam Lesinskifca5e422017-12-20 15:03:36 -0800654 application_action["library"].Action(RequiredNameIsNotEmpty);
Chris Craik335b5652019-04-04 12:46:47 -0700655 application_action["profileable"];
Todd Kennedyce3e1292020-10-29 17:14:24 -0700656 application_action["property"] = property_action;
Adam Lesinskib5dc4bd2017-02-22 19:29:29 -0800657
658 xml::XmlNodeAction& static_library_action = application_action["static-library"];
659 static_library_action.Action(RequiredNameIsJavaPackage);
660 static_library_action.Action(RequiredAndroidAttribute("version"));
661
662 xml::XmlNodeAction& uses_static_library_action = application_action["uses-static-library"];
663 uses_static_library_action.Action(RequiredNameIsJavaPackage);
664 uses_static_library_action.Action(RequiredAndroidAttribute("version"));
665 uses_static_library_action.Action(RequiredAndroidAttribute("certDigest"));
Ryan Mitchell66f6cfb2018-07-25 16:15:17 -0700666 uses_static_library_action["additional-certificate"];
Adam Lesinskib5dc4bd2017-02-22 19:29:29 -0800667
Alex Buynytskyya16137052021-12-02 13:26:54 +0000668 xml::XmlNodeAction& sdk_library_action = application_action["sdk-library"];
669 sdk_library_action.Action(RequiredNameIsJavaPackage);
670 sdk_library_action.Action(RequiredAndroidAttribute("versionMajor"));
671
672 xml::XmlNodeAction& uses_sdk_library_action = application_action["uses-sdk-library"];
673 uses_sdk_library_action.Action(RequiredNameIsJavaPackage);
674 uses_sdk_library_action.Action(RequiredAndroidAttribute("versionMajor"));
675 uses_sdk_library_action.Action(RequiredAndroidAttribute("certDigest"));
676 uses_sdk_library_action["additional-certificate"];
677
Dianne Hackborn813d7502018-10-02 16:59:46 -0700678 xml::XmlNodeAction& uses_package_action = application_action["uses-package"];
679 uses_package_action.Action(RequiredNameIsJavaPackage);
680 uses_package_action["additional-certificate"];
681
Ryan Mitchelle5b38a62018-03-23 13:35:00 -0700682 if (options_.debug_mode) {
Ryan Prichardcbcff742024-05-06 20:25:16 -0700683 application_action.Action([](xml::Element* el) -> bool {
Ryan Mitchelle5b38a62018-03-23 13:35:00 -0700684 xml::Attribute *attr = el->FindOrCreateAttribute(xml::kSchemaAndroid, "debuggable");
685 attr->value = "true";
686 return true;
687 });
688 }
689
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700690 application_action["meta-data"] = meta_data_action;
Adam Lesinski7a917a22017-06-02 12:55:24 -0700691
Dianne Hackbornfc0839a2020-01-31 11:02:28 -0800692 application_action["processes"];
693 application_action["processes"]["deny-permission"];
694 application_action["processes"]["allow-permission"];
695 application_action["processes"]["process"]["deny-permission"];
696 application_action["processes"]["process"]["allow-permission"];
697
Adam Lesinski86d67df2017-01-31 13:47:27 -0800698 application_action["activity"] = component_action;
Adam Lesinski7a917a22017-06-02 12:55:24 -0700699 application_action["activity"]["layout"];
700
Adam Lesinski86d67df2017-01-31 13:47:27 -0800701 application_action["activity-alias"] = component_action;
702 application_action["service"] = component_action;
703 application_action["receiver"] = component_action;
Gavin Corkeryad5d4ba2021-10-26 12:24:43 +0100704 application_action["apex-system-service"] = component_action;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700705
706 // Provider actions.
Adam Lesinski86d67df2017-01-31 13:47:27 -0800707 application_action["provider"] = component_action;
Adam Lesinskic10c0d02017-04-28 12:54:08 -0700708 application_action["provider"]["grant-uri-permission"];
Adam Lesinski25783ca2017-04-24 13:33:47 -0700709 application_action["provider"]["path-permission"];
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700710
Ryan Mitchell28afe682018-09-07 14:33:14 -0700711 manifest_action["package"] = manifest_action;
712
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700713 return true;
Adam Lesinski2ae4a872015-11-02 16:10:55 -0800714}
715
Yurii Zubrytskyia5775142022-11-02 17:49:49 -0700716static void FullyQualifyClassName(StringPiece package, StringPiece attr_ns, StringPiece attr_name,
717 xml::Element* el) {
Adam Lesinski23034b92017-11-29 16:27:44 -0800718 xml::Attribute* attr = el->FindAttribute(attr_ns, attr_name);
719 if (attr != nullptr) {
Ryan Mitchell4382e442021-07-14 12:53:01 -0700720 if (std::optional<std::string> new_value =
721 util::GetFullyQualifiedClassName(package, attr->value)) {
Adam Lesinski23034b92017-11-29 16:27:44 -0800722 attr->value = std::move(new_value.value());
Adam Lesinski52364f72016-01-11 13:10:24 -0800723 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700724 }
Adam Lesinski23034b92017-11-29 16:27:44 -0800725}
Adam Lesinski52364f72016-01-11 13:10:24 -0800726
Yurii Zubrytskyia5775142022-11-02 17:49:49 -0700727static bool RenameManifestPackage(StringPiece package_override, xml::Element* manifest_el) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700728 xml::Attribute* attr = manifest_el->FindAttribute({}, "package");
Adam Lesinski52364f72016-01-11 13:10:24 -0800729
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700730 // We've already verified that the manifest element is present, with a package
731 // name specified.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700732 CHECK(attr != nullptr);
Adam Lesinski52364f72016-01-11 13:10:24 -0800733
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700734 std::string original_package = std::move(attr->value);
Yurii Zubrytskyia5775142022-11-02 17:49:49 -0700735 attr->value.assign(package_override);
Adam Lesinski52364f72016-01-11 13:10:24 -0800736
Adam Lesinski23034b92017-11-29 16:27:44 -0800737 xml::Element* application_el = manifest_el->FindChild({}, "application");
738 if (application_el != nullptr) {
739 FullyQualifyClassName(original_package, xml::kSchemaAndroid, "name", application_el);
740 FullyQualifyClassName(original_package, xml::kSchemaAndroid, "backupAgent", application_el);
741
742 for (xml::Element* child_el : application_el->GetChildElements()) {
743 if (child_el->namespace_uri.empty()) {
744 if (child_el->name == "activity" || child_el->name == "activity-alias" ||
745 child_el->name == "provider" || child_el->name == "receiver" ||
746 child_el->name == "service") {
747 FullyQualifyClassName(original_package, xml::kSchemaAndroid, "name", child_el);
Makoto Onuki808fd192021-12-10 09:40:54 -0800748 continue;
Adam Lesinski23034b92017-11-29 16:27:44 -0800749 }
750
751 if (child_el->name == "activity-alias") {
752 FullyQualifyClassName(original_package, xml::kSchemaAndroid, "targetActivity", child_el);
Makoto Onuki808fd192021-12-10 09:40:54 -0800753 continue;
754 }
755
756 if (child_el->name == "processes") {
757 for (xml::Element* grand_child_el : child_el->GetChildElements()) {
758 if (grand_child_el->name == "process") {
759 FullyQualifyClassName(original_package, xml::kSchemaAndroid, "name", grand_child_el);
760 }
761 }
762 continue;
Adam Lesinski23034b92017-11-29 16:27:44 -0800763 }
764 }
765 }
766 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700767 return true;
Adam Lesinski52364f72016-01-11 13:10:24 -0800768}
769
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700770bool ManifestFixer::Consume(IAaptContext* context, xml::XmlResource* doc) {
Fabien Sanglard2d34e762019-02-21 15:13:29 -0800771 TRACE_CALL();
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700772 xml::Element* root = xml::FindRootElement(doc->root.get());
773 if (!root || !root->namespace_uri.empty() || root->name != "manifest") {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000774 context->GetDiagnostics()->Error(android::DiagMessage(doc->file.source)
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700775 << "root tag must be <manifest>");
776 return false;
777 }
Adam Lesinski2ae4a872015-11-02 16:10:55 -0800778
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800779 if ((options_.min_sdk_version_default || options_.target_sdk_version_default) &&
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700780 root->FindChild({}, "uses-sdk") == nullptr) {
Adam Lesinskie343eb12016-10-27 16:31:58 -0700781 // Auto insert a <uses-sdk> element. This must be inserted before the
782 // <application> tag. The device runtime PackageParser will make SDK version
783 // decisions while parsing <application>.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700784 std::unique_ptr<xml::Element> uses_sdk = util::make_unique<xml::Element>();
785 uses_sdk->name = "uses-sdk";
Adam Lesinskie343eb12016-10-27 16:31:58 -0700786 root->InsertChild(0, std::move(uses_sdk));
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700787 }
Adam Lesinski2ae4a872015-11-02 16:10:55 -0800788
Alan Viverette07287be2023-05-02 16:34:27 -0400789 if (!options_.no_compile_sdk_metadata && options_.compile_sdk_version) {
Adam Lesinskic6284372017-12-04 13:46:23 -0800790 xml::Attribute* attr = root->FindOrCreateAttribute(xml::kSchemaAndroid, "compileSdkVersion");
791
792 // Make sure we un-compile the value if it was set to something else.
793 attr->compiled_value = {};
Adam Lesinskic6284372017-12-04 13:46:23 -0800794 attr->value = options_.compile_sdk_version.value();
Ryan Mitchellaada89c2019-02-12 08:06:26 -0800795
796 attr = root->FindOrCreateAttribute("", "platformBuildVersionCode");
797
798 // Make sure we un-compile the value if it was set to something else.
799 attr->compiled_value = {};
800 attr->value = options_.compile_sdk_version.value();
Adam Lesinskic6284372017-12-04 13:46:23 -0800801 }
802
Alan Viverette07287be2023-05-02 16:34:27 -0400803 if (!options_.no_compile_sdk_metadata && options_.compile_sdk_version_codename) {
Adam Lesinskic6284372017-12-04 13:46:23 -0800804 xml::Attribute* attr =
805 root->FindOrCreateAttribute(xml::kSchemaAndroid, "compileSdkVersionCodename");
806
807 // Make sure we un-compile the value if it was set to something else.
808 attr->compiled_value = {};
Ryan Mitchellaada89c2019-02-12 08:06:26 -0800809 attr->value = options_.compile_sdk_version_codename.value();
Adam Lesinskic6284372017-12-04 13:46:23 -0800810
Ryan Mitchellaada89c2019-02-12 08:06:26 -0800811 attr = root->FindOrCreateAttribute("", "platformBuildVersionName");
812
813 // Make sure we un-compile the value if it was set to something else.
814 attr->compiled_value = {};
Adam Lesinskic6284372017-12-04 13:46:23 -0800815 attr->value = options_.compile_sdk_version_codename.value();
816 }
817
Andrei Onea7109b702023-02-23 17:43:25 +0000818 if (!options_.fingerprint_prefixes.empty()) {
819 xml::Element* install_constraints_el = root->FindChild({}, "install-constraints");
820 if (install_constraints_el == nullptr) {
821 std::unique_ptr<xml::Element> install_constraints = std::make_unique<xml::Element>();
822 install_constraints->name = "install-constraints";
823 install_constraints_el = install_constraints.get();
824 root->AppendChild(std::move(install_constraints));
825 }
826 for (const std::string& prefix : options_.fingerprint_prefixes) {
827 std::unique_ptr<xml::Element> prefix_el = std::make_unique<xml::Element>();
828 prefix_el->name = "fingerprint-prefix";
829 xml::Attribute* attr = prefix_el->FindOrCreateAttribute(xml::kSchemaAndroid, "value");
830 attr->value = prefix;
831 install_constraints_el->AppendChild(std::move(prefix_el));
832 }
833 }
834
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700835 xml::XmlActionExecutor executor;
Brandon Liu7de701f2024-06-11 18:51:39 +0000836 if (!BuildRules(&executor, context)) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700837 return false;
838 }
Adam Lesinskicc5609d2016-04-05 12:41:07 -0700839
Izabela Orlowskaad9e1322017-12-19 16:22:42 +0000840 xml::XmlActionExecutorPolicy policy = options_.warn_validation
Ryan Mitchell4ea90752020-07-31 08:21:43 -0700841 ? xml::XmlActionExecutorPolicy::kAllowListWarning
842 : xml::XmlActionExecutorPolicy::kAllowList;
Izabela Orlowskaad9e1322017-12-19 16:22:42 +0000843 if (!executor.Execute(policy, context->GetDiagnostics(), doc)) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700844 return false;
845 }
Adam Lesinskicc5609d2016-04-05 12:41:07 -0700846
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700847 if (options_.rename_manifest_package) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700848 // Rename manifest package outside of the XmlActionExecutor.
Adam Lesinskie343eb12016-10-27 16:31:58 -0700849 // We need to extract the old package name and FullyQualify all class
850 // names.
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800851 if (!RenameManifestPackage(options_.rename_manifest_package.value(), root)) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700852 return false;
Adam Lesinskicc5609d2016-04-05 12:41:07 -0700853 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700854 }
855 return true;
Adam Lesinski2ae4a872015-11-02 16:10:55 -0800856}
857
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700858} // namespace aapt