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