blob: 53c66a6285684e0e2dd82b9017a1594f6d2f0078 [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
21#include "android-base/logging.h"
22
Adam Lesinskicacb28f2016-10-19 12:18:14 -070023#include "ResourceUtils.h"
Adam Lesinski2ae4a872015-11-02 16:10:55 -080024#include "util/Util.h"
Adam Lesinskicc5609d2016-04-05 12:41:07 -070025#include "xml/XmlActionExecutor.h"
Adam Lesinski467f1712015-11-16 17:35:44 -080026#include "xml/XmlDom.h"
Adam Lesinski2ae4a872015-11-02 16:10:55 -080027
Adam Lesinskid5083f62017-01-16 15:07:21 -080028using android::StringPiece;
29
Adam Lesinski2ae4a872015-11-02 16:10:55 -080030namespace aapt {
31
Adam Lesinskib0c47ef2017-03-06 20:05:57 -080032// This is how PackageManager builds class names from AndroidManifest.xml entries.
Adam Lesinskice5e56e2016-10-21 17:56:45 -070033static bool NameIsJavaClassName(xml::Element* el, xml::Attribute* attr,
Adam Lesinskicc5609d2016-04-05 12:41:07 -070034 SourcePathDiagnostics* diag) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070035 // We allow unqualified class names (ie: .HelloActivity)
36 // Since we don't know the package name, we can just make a fake one here and
37 // the test will be identical as long as the real package name is valid too.
Adam Lesinskice5e56e2016-10-21 17:56:45 -070038 Maybe<std::string> fully_qualified_class_name =
39 util::GetFullyQualifiedClassName("a", attr->value);
Adam Lesinskicc5609d2016-04-05 12:41:07 -070040
Adam Lesinskice5e56e2016-10-21 17:56:45 -070041 StringPiece qualified_class_name = fully_qualified_class_name
42 ? fully_qualified_class_name.value()
43 : attr->value;
Adam Lesinskid0f116b2016-07-08 15:00:32 -070044
Adam Lesinskice5e56e2016-10-21 17:56:45 -070045 if (!util::IsJavaClassName(qualified_class_name)) {
46 diag->Error(DiagMessage(el->line_number)
Adam Lesinskicacb28f2016-10-19 12:18:14 -070047 << "attribute 'android:name' in <" << el->name
48 << "> tag must be a valid Java class name");
Adam Lesinski52364f72016-01-11 13:10:24 -080049 return false;
Adam Lesinskicacb28f2016-10-19 12:18:14 -070050 }
51 return true;
52}
53
Adam Lesinskiceb9b2f2017-02-16 12:05:42 -080054static bool OptionalNameIsJavaClassName(xml::Element* el, SourcePathDiagnostics* diag) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -070055 if (xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "name")) {
56 return NameIsJavaClassName(el, attr, diag);
Adam Lesinskicacb28f2016-10-19 12:18:14 -070057 }
58 return true;
59}
60
Adam Lesinskiceb9b2f2017-02-16 12:05:42 -080061static bool RequiredNameIsJavaClassName(xml::Element* el, SourcePathDiagnostics* diag) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -070062 if (xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "name")) {
63 return NameIsJavaClassName(el, attr, diag);
Adam Lesinskicacb28f2016-10-19 12:18:14 -070064 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -070065 diag->Error(DiagMessage(el->line_number)
Adam Lesinskicacb28f2016-10-19 12:18:14 -070066 << "<" << el->name << "> is missing attribute 'android:name'");
67 return false;
Adam Lesinski52364f72016-01-11 13:10:24 -080068}
69
Adam Lesinskiceb9b2f2017-02-16 12:05:42 -080070static bool RequiredNameIsJavaPackage(xml::Element* el, SourcePathDiagnostics* diag) {
71 if (xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "name")) {
72 return util::IsJavaPackageName(attr->value);
73 }
74 diag->Error(DiagMessage(el->line_number)
75 << "<" << el->name << "> is missing attribute 'android:name'");
76 return false;
77}
78
Adam Lesinskib5dc4bd2017-02-22 19:29:29 -080079static xml::XmlNodeAction::ActionFuncWithDiag RequiredAndroidAttribute(const std::string& attr) {
80 return [=](xml::Element* el, SourcePathDiagnostics* diag) -> bool {
81 if (el->FindAttribute(xml::kSchemaAndroid, attr) == nullptr) {
82 diag->Error(DiagMessage(el->line_number)
83 << "<" << el->name << "> is missing required attribute 'android:" << attr << "'");
84 return false;
85 }
86 return true;
87 };
88}
89
Adam Lesinskib0c47ef2017-03-06 20:05:57 -080090static bool AutoGenerateIsFeatureSplit(xml::Element* el, SourcePathDiagnostics* diag) {
91 constexpr const char* kFeatureSplit = "featureSplit";
92 constexpr const char* kIsFeatureSplit = "isFeatureSplit";
93
94 xml::Attribute* attr = el->FindAttribute({}, kFeatureSplit);
95 if (attr != nullptr) {
96 // Rewrite the featureSplit attribute to be "split". This is what the
97 // platform recognizes.
98 attr->name = "split";
99
100 // Now inject the android:isFeatureSplit="true" attribute.
101 xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, kIsFeatureSplit);
102 if (attr != nullptr) {
103 if (!ResourceUtils::ParseBool(attr->value).value_or_default(false)) {
104 // The isFeatureSplit attribute is false, which conflicts with the use
105 // of "featureSplit".
106 diag->Error(DiagMessage(el->line_number)
107 << "attribute 'featureSplit' used in <manifest> but 'android:isFeatureSplit' "
108 "is not 'true'");
109 return false;
110 }
111
112 // The attribute is already there and set to true, nothing to do.
113 } else {
114 el->attributes.push_back(xml::Attribute{xml::kSchemaAndroid, kIsFeatureSplit, "true"});
115 }
116 }
117 return true;
118}
119
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700120static bool VerifyManifest(xml::Element* el, SourcePathDiagnostics* diag) {
121 xml::Attribute* attr = el->FindAttribute({}, "package");
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700122 if (!attr) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700123 diag->Error(DiagMessage(el->line_number)
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700124 << "<manifest> tag is missing 'package' attribute");
125 return false;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700126 } else if (ResourceUtils::IsReference(attr->value)) {
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800127 diag->Error(DiagMessage(el->line_number)
128 << "attribute 'package' in <manifest> tag must not be a reference");
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700129 return false;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700130 } else if (!util::IsJavaPackageName(attr->value)) {
131 diag->Error(DiagMessage(el->line_number)
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800132 << "attribute 'package' in <manifest> tag is not a valid Java package name: '"
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700133 << attr->value << "'");
134 return false;
135 }
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800136
137 attr = el->FindAttribute({}, "split");
138 if (attr) {
139 if (!util::IsJavaPackageName(attr->value)) {
140 diag->Error(DiagMessage(el->line_number) << "attribute 'split' in <manifest> tag is not a "
141 "valid split name");
142 return false;
143 }
144 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700145 return true;
Adam Lesinski52364f72016-01-11 13:10:24 -0800146}
147
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800148// The coreApp attribute in <manifest> is not a regular AAPT attribute, so type
149// checking on it is manual.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700150static bool FixCoreAppAttribute(xml::Element* el, SourcePathDiagnostics* diag) {
151 if (xml::Attribute* attr = el->FindAttribute("", "coreApp")) {
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800152 std::unique_ptr<BinaryPrimitive> result = ResourceUtils::TryParseBool(attr->value);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700153 if (!result) {
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800154 diag->Error(DiagMessage(el->line_number) << "attribute coreApp must be a boolean");
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700155 return false;
Adam Lesinski6b17d2c2016-08-10 11:37:06 -0700156 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700157 attr->compiled_value = std::move(result);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700158 }
159 return true;
Adam Lesinski6b17d2c2016-08-10 11:37:06 -0700160}
161
Adam Lesinski86d67df2017-01-31 13:47:27 -0800162// Checks that <uses-feature> has android:glEsVersion or android:name, not both (or neither).
163static bool VerifyUsesFeature(xml::Element* el, SourcePathDiagnostics* diag) {
164 bool has_name = false;
165 if (xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "name")) {
166 if (attr->value.empty()) {
167 diag->Error(DiagMessage(el->line_number)
168 << "android:name in <uses-feature> must not be empty");
169 return false;
170 }
171 has_name = true;
172 }
173
174 bool has_gl_es_version = false;
175 if (xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "glEsVersion")) {
176 if (has_name) {
177 diag->Error(DiagMessage(el->line_number)
178 << "cannot define both android:name and android:glEsVersion in <uses-feature>");
179 return false;
180 }
181 has_gl_es_version = true;
182 }
183
184 if (!has_name && !has_gl_es_version) {
185 diag->Error(DiagMessage(el->line_number)
186 << "<uses-feature> must have either android:name or android:glEsVersion attribute");
187 return false;
188 }
189 return true;
190}
191
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700192bool ManifestFixer::BuildRules(xml::XmlActionExecutor* executor,
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700193 IDiagnostics* diag) {
194 // First verify some options.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700195 if (options_.rename_manifest_package) {
196 if (!util::IsJavaPackageName(options_.rename_manifest_package.value())) {
197 diag->Error(DiagMessage() << "invalid manifest package override '"
198 << options_.rename_manifest_package.value()
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700199 << "'");
200 return false;
201 }
202 }
203
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700204 if (options_.rename_instrumentation_target_package) {
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800205 if (!util::IsJavaPackageName(options_.rename_instrumentation_target_package.value())) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700206 diag->Error(DiagMessage()
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700207 << "invalid instrumentation target package override '"
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700208 << options_.rename_instrumentation_target_package.value()
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700209 << "'");
210 return false;
211 }
212 }
213
Adam Lesinski86d67df2017-01-31 13:47:27 -0800214 // Common <intent-filter> actions.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700215 xml::XmlNodeAction intent_filter_action;
216 intent_filter_action["action"];
217 intent_filter_action["category"];
218 intent_filter_action["data"];
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700219
Adam Lesinski86d67df2017-01-31 13:47:27 -0800220 // Common <meta-data> actions.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700221 xml::XmlNodeAction meta_data_action;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700222
Adam Lesinski86d67df2017-01-31 13:47:27 -0800223 // Common <uses-feature> actions.
224 xml::XmlNodeAction uses_feature_action;
225 uses_feature_action.Action(VerifyUsesFeature);
226
227 // Common component actions.
228 xml::XmlNodeAction component_action;
229 component_action.Action(RequiredNameIsJavaClassName);
230 component_action["intent-filter"] = intent_filter_action;
231 component_action["meta-data"] = meta_data_action;
232
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700233 // Manifest actions.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700234 xml::XmlNodeAction& manifest_action = (*executor)["manifest"];
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800235 manifest_action.Action(AutoGenerateIsFeatureSplit);
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700236 manifest_action.Action(VerifyManifest);
237 manifest_action.Action(FixCoreAppAttribute);
238 manifest_action.Action([&](xml::Element* el) -> bool {
239 if (options_.version_name_default) {
240 if (el->FindAttribute(xml::kSchemaAndroid, "versionName") == nullptr) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700241 el->attributes.push_back(
242 xml::Attribute{xml::kSchemaAndroid, "versionName",
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700243 options_.version_name_default.value()});
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700244 }
Adam Lesinskicc5609d2016-04-05 12:41:07 -0700245 }
246
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700247 if (options_.version_code_default) {
248 if (el->FindAttribute(xml::kSchemaAndroid, "versionCode") == nullptr) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700249 el->attributes.push_back(
250 xml::Attribute{xml::kSchemaAndroid, "versionCode",
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700251 options_.version_code_default.value()});
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700252 }
Adam Lesinskicc5609d2016-04-05 12:41:07 -0700253 }
Adam Lesinski2ae4a872015-11-02 16:10:55 -0800254 return true;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700255 });
256
257 // Meta tags.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700258 manifest_action["eat-comment"];
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700259
260 // Uses-sdk actions.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700261 manifest_action["uses-sdk"].Action([&](xml::Element* el) -> bool {
262 if (options_.min_sdk_version_default &&
263 el->FindAttribute(xml::kSchemaAndroid, "minSdkVersion") == nullptr) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700264 // There was no minSdkVersion defined and we have a default to assign.
265 el->attributes.push_back(
266 xml::Attribute{xml::kSchemaAndroid, "minSdkVersion",
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700267 options_.min_sdk_version_default.value()});
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700268 }
269
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700270 if (options_.target_sdk_version_default &&
271 el->FindAttribute(xml::kSchemaAndroid, "targetSdkVersion") == nullptr) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700272 // There was no targetSdkVersion defined and we have a default to assign.
273 el->attributes.push_back(
274 xml::Attribute{xml::kSchemaAndroid, "targetSdkVersion",
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700275 options_.target_sdk_version_default.value()});
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700276 }
277 return true;
278 });
279
280 // Instrumentation actions.
Adam Lesinski86d67df2017-01-31 13:47:27 -0800281 manifest_action["instrumentation"].Action(RequiredNameIsJavaClassName);
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700282 manifest_action["instrumentation"].Action([&](xml::Element* el) -> bool {
283 if (!options_.rename_instrumentation_target_package) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700284 return true;
285 }
286
287 if (xml::Attribute* attr =
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700288 el->FindAttribute(xml::kSchemaAndroid, "targetPackage")) {
289 attr->value = options_.rename_instrumentation_target_package.value();
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700290 }
291 return true;
292 });
Adam Lesinski86d67df2017-01-31 13:47:27 -0800293 manifest_action["instrumentation"]["meta-data"] = meta_data_action;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700294
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700295 manifest_action["original-package"];
296 manifest_action["protected-broadcast"];
297 manifest_action["uses-permission"];
Adam Lesinski4b585db2017-05-12 15:25:50 -0700298 manifest_action["uses-permission-sdk-23"];
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700299 manifest_action["permission"];
300 manifest_action["permission-tree"];
301 manifest_action["permission-group"];
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700302 manifest_action["uses-configuration"];
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700303 manifest_action["supports-screens"];
Adam Lesinski86d67df2017-01-31 13:47:27 -0800304 manifest_action["uses-feature"] = uses_feature_action;
305 manifest_action["feature-group"]["uses-feature"] = uses_feature_action;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700306 manifest_action["compatible-screens"];
307 manifest_action["compatible-screens"]["screen"];
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700308 manifest_action["supports-gl-texture"];
Adam Lesinski5119e512016-12-05 19:48:20 -0800309 manifest_action["meta-data"] = meta_data_action;
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800310 manifest_action["uses-split"].Action(RequiredNameIsJavaPackage);
Adam Lesinski5119e512016-12-05 19:48:20 -0800311
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700312 // Application actions.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700313 xml::XmlNodeAction& application_action = manifest_action["application"];
314 application_action.Action(OptionalNameIsJavaClassName);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700315
Adam Lesinskiceb9b2f2017-02-16 12:05:42 -0800316 application_action["uses-library"].Action(RequiredNameIsJavaPackage);
317 application_action["library"].Action(RequiredNameIsJavaPackage);
Adam Lesinskib5dc4bd2017-02-22 19:29:29 -0800318
319 xml::XmlNodeAction& static_library_action = application_action["static-library"];
320 static_library_action.Action(RequiredNameIsJavaPackage);
321 static_library_action.Action(RequiredAndroidAttribute("version"));
322
323 xml::XmlNodeAction& uses_static_library_action = application_action["uses-static-library"];
324 uses_static_library_action.Action(RequiredNameIsJavaPackage);
325 uses_static_library_action.Action(RequiredAndroidAttribute("version"));
326 uses_static_library_action.Action(RequiredAndroidAttribute("certDigest"));
327
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700328 application_action["meta-data"] = meta_data_action;
Adam Lesinski86d67df2017-01-31 13:47:27 -0800329 application_action["activity"] = component_action;
330 application_action["activity-alias"] = component_action;
331 application_action["service"] = component_action;
332 application_action["receiver"] = component_action;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700333
334 // Provider actions.
Adam Lesinski86d67df2017-01-31 13:47:27 -0800335 application_action["provider"] = component_action;
Adam Lesinskic10c0d02017-04-28 12:54:08 -0700336 application_action["provider"]["grant-uri-permission"];
Adam Lesinski25783ca2017-04-24 13:33:47 -0700337 application_action["provider"]["path-permission"];
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700338
339 return true;
Adam Lesinski2ae4a872015-11-02 16:10:55 -0800340}
341
Adam Lesinski52364f72016-01-11 13:10:24 -0800342class FullyQualifiedClassNameVisitor : public xml::Visitor {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700343 public:
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700344 using xml::Visitor::Visit;
Adam Lesinski52364f72016-01-11 13:10:24 -0800345
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800346 explicit FullyQualifiedClassNameVisitor(const StringPiece& package) : package_(package) {}
Adam Lesinski52364f72016-01-11 13:10:24 -0800347
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700348 void Visit(xml::Element* el) override {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700349 for (xml::Attribute& attr : el->attributes) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700350 if (attr.namespace_uri == xml::kSchemaAndroid &&
351 class_attributes_.find(attr.name) != class_attributes_.end()) {
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800352 if (Maybe<std::string> new_value = util::GetFullyQualifiedClassName(package_, attr.value)) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700353 attr.value = std::move(new_value.value());
Adam Lesinski52364f72016-01-11 13:10:24 -0800354 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700355 }
Adam Lesinski52364f72016-01-11 13:10:24 -0800356 }
357
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700358 // Super implementation to iterate over the children.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700359 xml::Visitor::Visit(el);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700360 }
361
362 private:
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700363 StringPiece package_;
364 std::unordered_set<StringPiece> class_attributes_ = {"name"};
Adam Lesinski52364f72016-01-11 13:10:24 -0800365};
366
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800367static bool RenameManifestPackage(const StringPiece& package_override, xml::Element* manifest_el) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700368 xml::Attribute* attr = manifest_el->FindAttribute({}, "package");
Adam Lesinski52364f72016-01-11 13:10:24 -0800369
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700370 // We've already verified that the manifest element is present, with a package
371 // name specified.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700372 CHECK(attr != nullptr);
Adam Lesinski52364f72016-01-11 13:10:24 -0800373
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700374 std::string original_package = std::move(attr->value);
Adam Lesinskid5083f62017-01-16 15:07:21 -0800375 attr->value = package_override.to_string();
Adam Lesinski52364f72016-01-11 13:10:24 -0800376
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700377 FullyQualifiedClassNameVisitor visitor(original_package);
378 manifest_el->Accept(&visitor);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700379 return true;
Adam Lesinski52364f72016-01-11 13:10:24 -0800380}
381
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700382bool ManifestFixer::Consume(IAaptContext* context, xml::XmlResource* doc) {
383 xml::Element* root = xml::FindRootElement(doc->root.get());
384 if (!root || !root->namespace_uri.empty() || root->name != "manifest") {
385 context->GetDiagnostics()->Error(DiagMessage(doc->file.source)
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700386 << "root tag must be <manifest>");
387 return false;
388 }
Adam Lesinski2ae4a872015-11-02 16:10:55 -0800389
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800390 if ((options_.min_sdk_version_default || options_.target_sdk_version_default) &&
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700391 root->FindChild({}, "uses-sdk") == nullptr) {
Adam Lesinskie343eb12016-10-27 16:31:58 -0700392 // Auto insert a <uses-sdk> element. This must be inserted before the
393 // <application> tag. The device runtime PackageParser will make SDK version
394 // decisions while parsing <application>.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700395 std::unique_ptr<xml::Element> uses_sdk = util::make_unique<xml::Element>();
396 uses_sdk->name = "uses-sdk";
Adam Lesinskie343eb12016-10-27 16:31:58 -0700397 root->InsertChild(0, std::move(uses_sdk));
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700398 }
Adam Lesinski2ae4a872015-11-02 16:10:55 -0800399
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700400 xml::XmlActionExecutor executor;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700401 if (!BuildRules(&executor, context->GetDiagnostics())) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700402 return false;
403 }
Adam Lesinskicc5609d2016-04-05 12:41:07 -0700404
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800405 if (!executor.Execute(xml::XmlActionExecutorPolicy::kWhitelist, context->GetDiagnostics(), doc)) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700406 return false;
407 }
Adam Lesinskicc5609d2016-04-05 12:41:07 -0700408
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700409 if (options_.rename_manifest_package) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700410 // Rename manifest package outside of the XmlActionExecutor.
Adam Lesinskie343eb12016-10-27 16:31:58 -0700411 // We need to extract the old package name and FullyQualify all class
412 // names.
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800413 if (!RenameManifestPackage(options_.rename_manifest_package.value(), root)) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700414 return false;
Adam Lesinskicc5609d2016-04-05 12:41:07 -0700415 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700416 }
417 return true;
Adam Lesinski2ae4a872015-11-02 16:10:55 -0800418}
419
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700420} // namespace aapt