1 /*
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
17 #include "link/ManifestFixer.h"
18
19 #include <unordered_set>
20
21 #include "android-base/logging.h"
22
23 #include "ResourceUtils.h"
24 #include "trace/TraceBuffer.h"
25 #include "util/Util.h"
26 #include "xml/XmlActionExecutor.h"
27 #include "xml/XmlDom.h"
28
29 using android::StringPiece;
30
31 namespace aapt {
32
RequiredNameIsNotEmpty(xml::Element * el,SourcePathDiagnostics * diag)33 static bool RequiredNameIsNotEmpty(xml::Element* el, SourcePathDiagnostics* diag) {
34 xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "name");
35 if (attr == nullptr) {
36 diag->Error(DiagMessage(el->line_number)
37 << "<" << el->name << "> is missing attribute 'android:name'");
38 return false;
39 }
40
41 if (attr->value.empty()) {
42 diag->Error(DiagMessage(el->line_number)
43 << "attribute 'android:name' in <" << el->name << "> tag must not be empty");
44 return false;
45 }
46 return true;
47 }
48
49 // This is how PackageManager builds class names from AndroidManifest.xml entries.
NameIsJavaClassName(xml::Element * el,xml::Attribute * attr,SourcePathDiagnostics * diag)50 static bool NameIsJavaClassName(xml::Element* el, xml::Attribute* attr,
51 SourcePathDiagnostics* diag) {
52 // We allow unqualified class names (ie: .HelloActivity)
53 // Since we don't know the package name, we can just make a fake one here and
54 // the test will be identical as long as the real package name is valid too.
55 Maybe<std::string> fully_qualified_class_name =
56 util::GetFullyQualifiedClassName("a", attr->value);
57
58 StringPiece qualified_class_name = fully_qualified_class_name
59 ? fully_qualified_class_name.value()
60 : attr->value;
61
62 if (!util::IsJavaClassName(qualified_class_name)) {
63 diag->Error(DiagMessage(el->line_number)
64 << "attribute 'android:name' in <" << el->name
65 << "> tag must be a valid Java class name");
66 return false;
67 }
68 return true;
69 }
70
OptionalNameIsJavaClassName(xml::Element * el,SourcePathDiagnostics * diag)71 static bool OptionalNameIsJavaClassName(xml::Element* el, SourcePathDiagnostics* diag) {
72 if (xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "name")) {
73 return NameIsJavaClassName(el, attr, diag);
74 }
75 return true;
76 }
77
RequiredNameIsJavaClassName(xml::Element * el,SourcePathDiagnostics * diag)78 static bool RequiredNameIsJavaClassName(xml::Element* el, SourcePathDiagnostics* diag) {
79 xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "name");
80 if (attr == nullptr) {
81 diag->Error(DiagMessage(el->line_number)
82 << "<" << el->name << "> is missing attribute 'android:name'");
83 return false;
84 }
85 return NameIsJavaClassName(el, attr, diag);
86 }
87
RequiredNameIsJavaPackage(xml::Element * el,SourcePathDiagnostics * diag)88 static bool RequiredNameIsJavaPackage(xml::Element* el, SourcePathDiagnostics* diag) {
89 xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "name");
90 if (attr == nullptr) {
91 diag->Error(DiagMessage(el->line_number)
92 << "<" << el->name << "> is missing attribute 'android:name'");
93 return false;
94 }
95
96 if (!util::IsJavaPackageName(attr->value)) {
97 diag->Error(DiagMessage(el->line_number) << "attribute 'android:name' in <" << el->name
98 << "> tag must be a valid Java package name");
99 return false;
100 }
101 return true;
102 }
103
RequiredAndroidAttribute(const std::string & attr)104 static xml::XmlNodeAction::ActionFuncWithDiag RequiredAndroidAttribute(const std::string& attr) {
105 return [=](xml::Element* el, SourcePathDiagnostics* diag) -> bool {
106 if (el->FindAttribute(xml::kSchemaAndroid, attr) == nullptr) {
107 diag->Error(DiagMessage(el->line_number)
108 << "<" << el->name << "> is missing required attribute 'android:" << attr << "'");
109 return false;
110 }
111 return true;
112 };
113 }
114
AutoGenerateIsFeatureSplit(xml::Element * el,SourcePathDiagnostics * diag)115 static bool AutoGenerateIsFeatureSplit(xml::Element* el, SourcePathDiagnostics* diag) {
116 constexpr const char* kFeatureSplit = "featureSplit";
117 constexpr const char* kIsFeatureSplit = "isFeatureSplit";
118
119 xml::Attribute* attr = el->FindAttribute({}, kFeatureSplit);
120 if (attr != nullptr) {
121 // Rewrite the featureSplit attribute to be "split". This is what the
122 // platform recognizes.
123 attr->name = "split";
124
125 // Now inject the android:isFeatureSplit="true" attribute.
126 xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, kIsFeatureSplit);
127 if (attr != nullptr) {
128 if (!ResourceUtils::ParseBool(attr->value).value_or_default(false)) {
129 // The isFeatureSplit attribute is false, which conflicts with the use
130 // of "featureSplit".
131 diag->Error(DiagMessage(el->line_number)
132 << "attribute 'featureSplit' used in <manifest> but 'android:isFeatureSplit' "
133 "is not 'true'");
134 return false;
135 }
136
137 // The attribute is already there and set to true, nothing to do.
138 } else {
139 el->attributes.push_back(xml::Attribute{xml::kSchemaAndroid, kIsFeatureSplit, "true"});
140 }
141 }
142 return true;
143 }
144
VerifyManifest(xml::Element * el,SourcePathDiagnostics * diag)145 static bool VerifyManifest(xml::Element* el, SourcePathDiagnostics* diag) {
146 xml::Attribute* attr = el->FindAttribute({}, "package");
147 if (!attr) {
148 diag->Error(DiagMessage(el->line_number)
149 << "<manifest> tag is missing 'package' attribute");
150 return false;
151 } else if (ResourceUtils::IsReference(attr->value)) {
152 diag->Error(DiagMessage(el->line_number)
153 << "attribute 'package' in <manifest> tag must not be a reference");
154 return false;
155 } else if (!util::IsAndroidPackageName(attr->value)) {
156 diag->Error(DiagMessage(el->line_number)
157 << "attribute 'package' in <manifest> tag is not a valid Android package name: '"
158 << attr->value << "'");
159 return false;
160 }
161
162 attr = el->FindAttribute({}, "split");
163 if (attr) {
164 if (!util::IsJavaPackageName(attr->value)) {
165 diag->Error(DiagMessage(el->line_number) << "attribute 'split' in <manifest> tag is not a "
166 "valid split name");
167 return false;
168 }
169 }
170 return true;
171 }
172
173 // The coreApp attribute in <manifest> is not a regular AAPT attribute, so type
174 // checking on it is manual.
FixCoreAppAttribute(xml::Element * el,SourcePathDiagnostics * diag)175 static bool FixCoreAppAttribute(xml::Element* el, SourcePathDiagnostics* diag) {
176 if (xml::Attribute* attr = el->FindAttribute("", "coreApp")) {
177 std::unique_ptr<BinaryPrimitive> result = ResourceUtils::TryParseBool(attr->value);
178 if (!result) {
179 diag->Error(DiagMessage(el->line_number) << "attribute coreApp must be a boolean");
180 return false;
181 }
182 attr->compiled_value = std::move(result);
183 }
184 return true;
185 }
186
187 // Checks that <uses-feature> has android:glEsVersion or android:name, not both (or neither).
VerifyUsesFeature(xml::Element * el,SourcePathDiagnostics * diag)188 static bool VerifyUsesFeature(xml::Element* el, SourcePathDiagnostics* diag) {
189 bool has_name = false;
190 if (xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "name")) {
191 if (attr->value.empty()) {
192 diag->Error(DiagMessage(el->line_number)
193 << "android:name in <uses-feature> must not be empty");
194 return false;
195 }
196 has_name = true;
197 }
198
199 bool has_gl_es_version = false;
200 if (xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "glEsVersion")) {
201 if (has_name) {
202 diag->Error(DiagMessage(el->line_number)
203 << "cannot define both android:name and android:glEsVersion in <uses-feature>");
204 return false;
205 }
206 has_gl_es_version = true;
207 }
208
209 if (!has_name && !has_gl_es_version) {
210 diag->Error(DiagMessage(el->line_number)
211 << "<uses-feature> must have either android:name or android:glEsVersion attribute");
212 return false;
213 }
214 return true;
215 }
216
217 // Ensure that 'ns_decls' contains a declaration for 'uri', using 'prefix' as
218 // the xmlns prefix if possible.
EnsureNamespaceIsDeclared(const std::string & prefix,const std::string & uri,std::vector<xml::NamespaceDecl> * ns_decls)219 static void EnsureNamespaceIsDeclared(const std::string& prefix, const std::string& uri,
220 std::vector<xml::NamespaceDecl>* ns_decls) {
221 if (std::find_if(ns_decls->begin(), ns_decls->end(), [&](const xml::NamespaceDecl& ns_decl) {
222 return ns_decl.uri == uri;
223 }) != ns_decls->end()) {
224 return;
225 }
226
227 std::set<std::string> used_prefixes;
228 for (const auto& ns_decl : *ns_decls) {
229 used_prefixes.insert(ns_decl.prefix);
230 }
231
232 // Make multiple attempts in the unlikely event that 'prefix' is already taken.
233 std::string disambiguator;
234 for (int i = 0; i < used_prefixes.size() + 1; i++) {
235 std::string attempted_prefix = prefix + disambiguator;
236 if (used_prefixes.find(attempted_prefix) == used_prefixes.end()) {
237 ns_decls->push_back(xml::NamespaceDecl{attempted_prefix, uri});
238 return;
239 }
240 disambiguator = std::to_string(i);
241 }
242 }
243
BuildRules(xml::XmlActionExecutor * executor,IDiagnostics * diag)244 bool ManifestFixer::BuildRules(xml::XmlActionExecutor* executor,
245 IDiagnostics* diag) {
246 // First verify some options.
247 if (options_.rename_manifest_package) {
248 if (!util::IsJavaPackageName(options_.rename_manifest_package.value())) {
249 diag->Error(DiagMessage() << "invalid manifest package override '"
250 << options_.rename_manifest_package.value()
251 << "'");
252 return false;
253 }
254 }
255
256 if (options_.rename_instrumentation_target_package) {
257 if (!util::IsJavaPackageName(options_.rename_instrumentation_target_package.value())) {
258 diag->Error(DiagMessage()
259 << "invalid instrumentation target package override '"
260 << options_.rename_instrumentation_target_package.value()
261 << "'");
262 return false;
263 }
264 }
265
266 if (options_.rename_overlay_target_package) {
267 if (!util::IsJavaPackageName(options_.rename_overlay_target_package.value())) {
268 diag->Error(DiagMessage()
269 << "invalid overlay target package override '"
270 << options_.rename_overlay_target_package.value()
271 << "'");
272 return false;
273 }
274 }
275
276 // Common <intent-filter> actions.
277 xml::XmlNodeAction intent_filter_action;
278 intent_filter_action["action"].Action(RequiredNameIsNotEmpty);
279 intent_filter_action["category"].Action(RequiredNameIsNotEmpty);
280 intent_filter_action["data"];
281
282 // Common <meta-data> actions.
283 xml::XmlNodeAction meta_data_action;
284
285 // Common <uses-feature> actions.
286 xml::XmlNodeAction uses_feature_action;
287 uses_feature_action.Action(VerifyUsesFeature);
288
289 // Common component actions.
290 xml::XmlNodeAction component_action;
291 component_action.Action(RequiredNameIsJavaClassName);
292 component_action["intent-filter"] = intent_filter_action;
293 component_action["preferred"] = intent_filter_action;
294 component_action["meta-data"] = meta_data_action;
295
296 // Manifest actions.
297 xml::XmlNodeAction& manifest_action = (*executor)["manifest"];
298 manifest_action.Action(AutoGenerateIsFeatureSplit);
299 manifest_action.Action(VerifyManifest);
300 manifest_action.Action(FixCoreAppAttribute);
301 manifest_action.Action([&](xml::Element* el) -> bool {
302 EnsureNamespaceIsDeclared("android", xml::kSchemaAndroid, &el->namespace_decls);
303
304 if (options_.version_name_default) {
305 if (options_.replace_version) {
306 el->RemoveAttribute(xml::kSchemaAndroid, "versionName");
307 }
308 if (el->FindAttribute(xml::kSchemaAndroid, "versionName") == nullptr) {
309 el->attributes.push_back(
310 xml::Attribute{xml::kSchemaAndroid, "versionName",
311 options_.version_name_default.value()});
312 }
313 }
314
315 if (options_.version_code_default) {
316 if (options_.replace_version) {
317 el->RemoveAttribute(xml::kSchemaAndroid, "versionCode");
318 }
319 if (el->FindAttribute(xml::kSchemaAndroid, "versionCode") == nullptr) {
320 el->attributes.push_back(
321 xml::Attribute{xml::kSchemaAndroid, "versionCode",
322 options_.version_code_default.value()});
323 }
324 }
325
326 if (options_.version_code_major_default) {
327 if (options_.replace_version) {
328 el->RemoveAttribute(xml::kSchemaAndroid, "versionCodeMajor");
329 }
330 if (el->FindAttribute(xml::kSchemaAndroid, "versionCodeMajor") == nullptr) {
331 el->attributes.push_back(
332 xml::Attribute{xml::kSchemaAndroid, "versionCodeMajor",
333 options_.version_code_major_default.value()});
334 }
335 }
336
337 return true;
338 });
339
340 // Meta tags.
341 manifest_action["eat-comment"];
342
343 // Uses-sdk actions.
344 manifest_action["uses-sdk"].Action([&](xml::Element* el) -> bool {
345 if (options_.min_sdk_version_default &&
346 el->FindAttribute(xml::kSchemaAndroid, "minSdkVersion") == nullptr) {
347 // There was no minSdkVersion defined and we have a default to assign.
348 el->attributes.push_back(
349 xml::Attribute{xml::kSchemaAndroid, "minSdkVersion",
350 options_.min_sdk_version_default.value()});
351 }
352
353 if (options_.target_sdk_version_default &&
354 el->FindAttribute(xml::kSchemaAndroid, "targetSdkVersion") == nullptr) {
355 // There was no targetSdkVersion defined and we have a default to assign.
356 el->attributes.push_back(
357 xml::Attribute{xml::kSchemaAndroid, "targetSdkVersion",
358 options_.target_sdk_version_default.value()});
359 }
360 return true;
361 });
362 manifest_action["uses-sdk"]["extension-sdk"];
363
364 // Instrumentation actions.
365 manifest_action["instrumentation"].Action(RequiredNameIsJavaClassName);
366 manifest_action["instrumentation"].Action([&](xml::Element* el) -> bool {
367 if (!options_.rename_instrumentation_target_package) {
368 return true;
369 }
370
371 if (xml::Attribute* attr =
372 el->FindAttribute(xml::kSchemaAndroid, "targetPackage")) {
373 attr->value = options_.rename_instrumentation_target_package.value();
374 }
375 return true;
376 });
377 manifest_action["instrumentation"]["meta-data"] = meta_data_action;
378
379 // TODO moltmann: Remove
380 manifest_action["feature"];
381 manifest_action["feature"]["inherit-from"];
382
383 manifest_action["attribution"];
384 manifest_action["attribution"]["inherit-from"];
385 manifest_action["original-package"];
386 manifest_action["overlay"].Action([&](xml::Element* el) -> bool {
387 if (!options_.rename_overlay_target_package) {
388 return true;
389 }
390
391 if (xml::Attribute* attr =
392 el->FindAttribute(xml::kSchemaAndroid, "targetPackage")) {
393 attr->value = options_.rename_overlay_target_package.value();
394 }
395 return true;
396 });
397 manifest_action["protected-broadcast"];
398 manifest_action["adopt-permissions"];
399 manifest_action["uses-permission"];
400 manifest_action["uses-permission-sdk-23"];
401 manifest_action["permission"];
402 manifest_action["permission"]["meta-data"] = meta_data_action;
403 manifest_action["permission-tree"];
404 manifest_action["permission-group"];
405 manifest_action["uses-configuration"];
406 manifest_action["supports-screens"];
407 manifest_action["uses-feature"] = uses_feature_action;
408 manifest_action["feature-group"]["uses-feature"] = uses_feature_action;
409 manifest_action["compatible-screens"];
410 manifest_action["compatible-screens"]["screen"];
411 manifest_action["supports-gl-texture"];
412 manifest_action["restrict-update"];
413 manifest_action["package-verifier"];
414 manifest_action["meta-data"] = meta_data_action;
415 manifest_action["uses-split"].Action(RequiredNameIsJavaPackage);
416 manifest_action["queries"]["package"].Action(RequiredNameIsJavaPackage);
417 manifest_action["queries"]["intent"] = intent_filter_action;
418 manifest_action["queries"]["provider"].Action(RequiredAndroidAttribute("authorities"));
419 // TODO: more complicated component name tag
420
421 manifest_action["key-sets"]["key-set"]["public-key"];
422 manifest_action["key-sets"]["upgrade-key-set"];
423
424 // Application actions.
425 xml::XmlNodeAction& application_action = manifest_action["application"];
426 application_action.Action(OptionalNameIsJavaClassName);
427
428 application_action["uses-library"].Action(RequiredNameIsNotEmpty);
429 application_action["library"].Action(RequiredNameIsNotEmpty);
430 application_action["profileable"];
431
432 xml::XmlNodeAction& static_library_action = application_action["static-library"];
433 static_library_action.Action(RequiredNameIsJavaPackage);
434 static_library_action.Action(RequiredAndroidAttribute("version"));
435
436 xml::XmlNodeAction& uses_static_library_action = application_action["uses-static-library"];
437 uses_static_library_action.Action(RequiredNameIsJavaPackage);
438 uses_static_library_action.Action(RequiredAndroidAttribute("version"));
439 uses_static_library_action.Action(RequiredAndroidAttribute("certDigest"));
440 uses_static_library_action["additional-certificate"];
441
442 xml::XmlNodeAction& uses_package_action = application_action["uses-package"];
443 uses_package_action.Action(RequiredNameIsJavaPackage);
444 uses_package_action["additional-certificate"];
445
446 if (options_.debug_mode) {
447 application_action.Action([&](xml::Element* el) -> bool {
448 xml::Attribute *attr = el->FindOrCreateAttribute(xml::kSchemaAndroid, "debuggable");
449 attr->value = "true";
450 return true;
451 });
452 }
453
454 application_action["meta-data"] = meta_data_action;
455
456 application_action["processes"];
457 application_action["processes"]["deny-permission"];
458 application_action["processes"]["allow-permission"];
459 application_action["processes"]["process"]["deny-permission"];
460 application_action["processes"]["process"]["allow-permission"];
461
462 application_action["activity"] = component_action;
463 application_action["activity"]["layout"];
464
465 application_action["activity-alias"] = component_action;
466 application_action["service"] = component_action;
467 application_action["receiver"] = component_action;
468
469 // Provider actions.
470 application_action["provider"] = component_action;
471 application_action["provider"]["grant-uri-permission"];
472 application_action["provider"]["path-permission"];
473
474 manifest_action["package"] = manifest_action;
475
476 return true;
477 }
478
FullyQualifyClassName(const StringPiece & package,const StringPiece & attr_ns,const StringPiece & attr_name,xml::Element * el)479 static void FullyQualifyClassName(const StringPiece& package, const StringPiece& attr_ns,
480 const StringPiece& attr_name, xml::Element* el) {
481 xml::Attribute* attr = el->FindAttribute(attr_ns, attr_name);
482 if (attr != nullptr) {
483 if (Maybe<std::string> new_value = util::GetFullyQualifiedClassName(package, attr->value)) {
484 attr->value = std::move(new_value.value());
485 }
486 }
487 }
488
RenameManifestPackage(const StringPiece & package_override,xml::Element * manifest_el)489 static bool RenameManifestPackage(const StringPiece& package_override, xml::Element* manifest_el) {
490 xml::Attribute* attr = manifest_el->FindAttribute({}, "package");
491
492 // We've already verified that the manifest element is present, with a package
493 // name specified.
494 CHECK(attr != nullptr);
495
496 std::string original_package = std::move(attr->value);
497 attr->value = package_override.to_string();
498
499 xml::Element* application_el = manifest_el->FindChild({}, "application");
500 if (application_el != nullptr) {
501 FullyQualifyClassName(original_package, xml::kSchemaAndroid, "name", application_el);
502 FullyQualifyClassName(original_package, xml::kSchemaAndroid, "backupAgent", application_el);
503
504 for (xml::Element* child_el : application_el->GetChildElements()) {
505 if (child_el->namespace_uri.empty()) {
506 if (child_el->name == "activity" || child_el->name == "activity-alias" ||
507 child_el->name == "provider" || child_el->name == "receiver" ||
508 child_el->name == "service") {
509 FullyQualifyClassName(original_package, xml::kSchemaAndroid, "name", child_el);
510 }
511
512 if (child_el->name == "activity-alias") {
513 FullyQualifyClassName(original_package, xml::kSchemaAndroid, "targetActivity", child_el);
514 }
515 }
516 }
517 }
518 return true;
519 }
520
Consume(IAaptContext * context,xml::XmlResource * doc)521 bool ManifestFixer::Consume(IAaptContext* context, xml::XmlResource* doc) {
522 TRACE_CALL();
523 xml::Element* root = xml::FindRootElement(doc->root.get());
524 if (!root || !root->namespace_uri.empty() || root->name != "manifest") {
525 context->GetDiagnostics()->Error(DiagMessage(doc->file.source)
526 << "root tag must be <manifest>");
527 return false;
528 }
529
530 if ((options_.min_sdk_version_default || options_.target_sdk_version_default) &&
531 root->FindChild({}, "uses-sdk") == nullptr) {
532 // Auto insert a <uses-sdk> element. This must be inserted before the
533 // <application> tag. The device runtime PackageParser will make SDK version
534 // decisions while parsing <application>.
535 std::unique_ptr<xml::Element> uses_sdk = util::make_unique<xml::Element>();
536 uses_sdk->name = "uses-sdk";
537 root->InsertChild(0, std::move(uses_sdk));
538 }
539
540 if (options_.compile_sdk_version) {
541 xml::Attribute* attr = root->FindOrCreateAttribute(xml::kSchemaAndroid, "compileSdkVersion");
542
543 // Make sure we un-compile the value if it was set to something else.
544 attr->compiled_value = {};
545 attr->value = options_.compile_sdk_version.value();
546
547 attr = root->FindOrCreateAttribute("", "platformBuildVersionCode");
548
549 // Make sure we un-compile the value if it was set to something else.
550 attr->compiled_value = {};
551 attr->value = options_.compile_sdk_version.value();
552
553 }
554
555 if (options_.compile_sdk_version_codename) {
556 xml::Attribute* attr =
557 root->FindOrCreateAttribute(xml::kSchemaAndroid, "compileSdkVersionCodename");
558
559 // Make sure we un-compile the value if it was set to something else.
560 attr->compiled_value = {};
561 attr->value = options_.compile_sdk_version_codename.value();
562
563 attr = root->FindOrCreateAttribute("", "platformBuildVersionName");
564
565 // Make sure we un-compile the value if it was set to something else.
566 attr->compiled_value = {};
567 attr->value = options_.compile_sdk_version_codename.value();
568 }
569
570 xml::XmlActionExecutor executor;
571 if (!BuildRules(&executor, context->GetDiagnostics())) {
572 return false;
573 }
574
575 xml::XmlActionExecutorPolicy policy = options_.warn_validation
576 ? xml::XmlActionExecutorPolicy::kWhitelistWarning
577 : xml::XmlActionExecutorPolicy::kWhitelist;
578 if (!executor.Execute(policy, context->GetDiagnostics(), doc)) {
579 return false;
580 }
581
582 if (options_.rename_manifest_package) {
583 // Rename manifest package outside of the XmlActionExecutor.
584 // We need to extract the old package name and FullyQualify all class
585 // names.
586 if (!RenameManifestPackage(options_.rename_manifest_package.value(), root)) {
587 return false;
588 }
589 }
590 return true;
591 }
592
593 } // namespace aapt
594