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