blob: 5812ec44f1fb0740544351026a21351b12db898a [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 Lesinskifca5e422017-12-20 15:03:36 -080032static bool RequiredNameIsNotEmpty(xml::Element* el, SourcePathDiagnostics* diag) {
33 xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "name");
34 if (attr == nullptr) {
35 diag->Error(DiagMessage(el->line_number)
36 << "<" << el->name << "> is missing attribute 'android:name'");
37 return false;
38 }
39
40 if (attr->value.empty()) {
41 diag->Error(DiagMessage(el->line_number)
42 << "attribute 'android:name' in <" << el->name << "> tag must not be empty");
43 return false;
44 }
45 return true;
46}
47
Adam Lesinskib0c47ef2017-03-06 20:05:57 -080048// This is how PackageManager builds class names from AndroidManifest.xml entries.
Adam Lesinskice5e56e2016-10-21 17:56:45 -070049static bool NameIsJavaClassName(xml::Element* el, xml::Attribute* attr,
Adam Lesinskicc5609d2016-04-05 12:41:07 -070050 SourcePathDiagnostics* diag) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070051 // We allow unqualified class names (ie: .HelloActivity)
52 // Since we don't know the package name, we can just make a fake one here and
53 // the test will be identical as long as the real package name is valid too.
Adam Lesinskice5e56e2016-10-21 17:56:45 -070054 Maybe<std::string> fully_qualified_class_name =
55 util::GetFullyQualifiedClassName("a", attr->value);
Adam Lesinskicc5609d2016-04-05 12:41:07 -070056
Adam Lesinskice5e56e2016-10-21 17:56:45 -070057 StringPiece qualified_class_name = fully_qualified_class_name
58 ? fully_qualified_class_name.value()
59 : attr->value;
Adam Lesinskid0f116b2016-07-08 15:00:32 -070060
Adam Lesinskice5e56e2016-10-21 17:56:45 -070061 if (!util::IsJavaClassName(qualified_class_name)) {
62 diag->Error(DiagMessage(el->line_number)
Adam Lesinskicacb28f2016-10-19 12:18:14 -070063 << "attribute 'android:name' in <" << el->name
64 << "> tag must be a valid Java class name");
Adam Lesinski52364f72016-01-11 13:10:24 -080065 return false;
Adam Lesinskicacb28f2016-10-19 12:18:14 -070066 }
67 return true;
68}
69
Adam Lesinskiceb9b2f2017-02-16 12:05:42 -080070static bool OptionalNameIsJavaClassName(xml::Element* el, SourcePathDiagnostics* diag) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -070071 if (xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "name")) {
72 return NameIsJavaClassName(el, attr, diag);
Adam Lesinskicacb28f2016-10-19 12:18:14 -070073 }
74 return true;
75}
76
Adam Lesinskiceb9b2f2017-02-16 12:05:42 -080077static bool RequiredNameIsJavaClassName(xml::Element* el, SourcePathDiagnostics* diag) {
Adam Lesinskifca5e422017-12-20 15:03:36 -080078 xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "name");
79 if (attr == nullptr) {
80 diag->Error(DiagMessage(el->line_number)
81 << "<" << el->name << "> is missing attribute 'android:name'");
82 return false;
Adam Lesinskicacb28f2016-10-19 12:18:14 -070083 }
Adam Lesinskifca5e422017-12-20 15:03:36 -080084 return NameIsJavaClassName(el, attr, diag);
Adam Lesinski52364f72016-01-11 13:10:24 -080085}
86
Adam Lesinskiceb9b2f2017-02-16 12:05:42 -080087static bool RequiredNameIsJavaPackage(xml::Element* el, SourcePathDiagnostics* diag) {
Adam Lesinskifca5e422017-12-20 15:03:36 -080088 xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "name");
89 if (attr == nullptr) {
90 diag->Error(DiagMessage(el->line_number)
91 << "<" << el->name << "> is missing attribute 'android:name'");
92 return false;
Adam Lesinskiceb9b2f2017-02-16 12:05:42 -080093 }
Adam Lesinskifca5e422017-12-20 15:03:36 -080094
95 if (!util::IsJavaPackageName(attr->value)) {
96 diag->Error(DiagMessage(el->line_number) << "attribute 'android:name' in <" << el->name
97 << "> tag must be a valid Java package name");
98 return false;
99 }
100 return true;
Adam Lesinskiceb9b2f2017-02-16 12:05:42 -0800101}
102
Adam Lesinskib5dc4bd2017-02-22 19:29:29 -0800103static xml::XmlNodeAction::ActionFuncWithDiag RequiredAndroidAttribute(const std::string& attr) {
104 return [=](xml::Element* el, SourcePathDiagnostics* diag) -> bool {
105 if (el->FindAttribute(xml::kSchemaAndroid, attr) == nullptr) {
106 diag->Error(DiagMessage(el->line_number)
107 << "<" << el->name << "> is missing required attribute 'android:" << attr << "'");
108 return false;
109 }
110 return true;
111 };
112}
113
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800114static bool AutoGenerateIsFeatureSplit(xml::Element* el, SourcePathDiagnostics* diag) {
115 constexpr const char* kFeatureSplit = "featureSplit";
116 constexpr const char* kIsFeatureSplit = "isFeatureSplit";
117
118 xml::Attribute* attr = el->FindAttribute({}, kFeatureSplit);
119 if (attr != nullptr) {
120 // Rewrite the featureSplit attribute to be "split". This is what the
121 // platform recognizes.
122 attr->name = "split";
123
124 // Now inject the android:isFeatureSplit="true" attribute.
125 xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, kIsFeatureSplit);
126 if (attr != nullptr) {
127 if (!ResourceUtils::ParseBool(attr->value).value_or_default(false)) {
128 // The isFeatureSplit attribute is false, which conflicts with the use
129 // of "featureSplit".
130 diag->Error(DiagMessage(el->line_number)
131 << "attribute 'featureSplit' used in <manifest> but 'android:isFeatureSplit' "
132 "is not 'true'");
133 return false;
134 }
135
136 // The attribute is already there and set to true, nothing to do.
137 } else {
138 el->attributes.push_back(xml::Attribute{xml::kSchemaAndroid, kIsFeatureSplit, "true"});
139 }
140 }
141 return true;
142}
143
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700144static bool VerifyManifest(xml::Element* el, SourcePathDiagnostics* diag) {
145 xml::Attribute* attr = el->FindAttribute({}, "package");
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700146 if (!attr) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700147 diag->Error(DiagMessage(el->line_number)
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700148 << "<manifest> tag is missing 'package' attribute");
149 return false;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700150 } else if (ResourceUtils::IsReference(attr->value)) {
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800151 diag->Error(DiagMessage(el->line_number)
152 << "attribute 'package' in <manifest> tag must not be a reference");
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700153 return false;
Adam Lesinski96ea08f2017-11-06 10:44:46 -0800154 } else if (!util::IsAndroidPackageName(attr->value)) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700155 diag->Error(DiagMessage(el->line_number)
Adam Lesinski96ea08f2017-11-06 10:44:46 -0800156 << "attribute 'package' in <manifest> tag is not a valid Android package name: '"
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700157 << attr->value << "'");
158 return false;
159 }
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800160
161 attr = el->FindAttribute({}, "split");
162 if (attr) {
163 if (!util::IsJavaPackageName(attr->value)) {
164 diag->Error(DiagMessage(el->line_number) << "attribute 'split' in <manifest> tag is not a "
165 "valid split name");
166 return false;
167 }
168 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700169 return true;
Adam Lesinski52364f72016-01-11 13:10:24 -0800170}
171
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800172// The coreApp attribute in <manifest> is not a regular AAPT attribute, so type
173// checking on it is manual.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700174static bool FixCoreAppAttribute(xml::Element* el, SourcePathDiagnostics* diag) {
175 if (xml::Attribute* attr = el->FindAttribute("", "coreApp")) {
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800176 std::unique_ptr<BinaryPrimitive> result = ResourceUtils::TryParseBool(attr->value);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700177 if (!result) {
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800178 diag->Error(DiagMessage(el->line_number) << "attribute coreApp must be a boolean");
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700179 return false;
Adam Lesinski6b17d2c2016-08-10 11:37:06 -0700180 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700181 attr->compiled_value = std::move(result);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700182 }
183 return true;
Adam Lesinski6b17d2c2016-08-10 11:37:06 -0700184}
185
Adam Lesinski86d67df2017-01-31 13:47:27 -0800186// Checks that <uses-feature> has android:glEsVersion or android:name, not both (or neither).
187static bool VerifyUsesFeature(xml::Element* el, SourcePathDiagnostics* diag) {
188 bool has_name = false;
189 if (xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "name")) {
190 if (attr->value.empty()) {
191 diag->Error(DiagMessage(el->line_number)
192 << "android:name in <uses-feature> must not be empty");
193 return false;
194 }
195 has_name = true;
196 }
197
198 bool has_gl_es_version = false;
199 if (xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "glEsVersion")) {
200 if (has_name) {
201 diag->Error(DiagMessage(el->line_number)
202 << "cannot define both android:name and android:glEsVersion in <uses-feature>");
203 return false;
204 }
205 has_gl_es_version = true;
206 }
207
208 if (!has_name && !has_gl_es_version) {
209 diag->Error(DiagMessage(el->line_number)
210 << "<uses-feature> must have either android:name or android:glEsVersion attribute");
211 return false;
212 }
213 return true;
214}
215
Ryan Mitchelle1de2842019-01-04 10:20:16 -0800216static bool AddDeprecatedUsesFeatures(xml::Element* el, SourcePathDiagnostics* diag) {
217 if (xml::Attribute* attr = el->FindAttribute(xml::kSchemaAndroid, "name")) {
218 if (attr->value.empty()) {
219 return true;
220 }
221
222 // Add "android.hardware.fingerprint" when "android.hardware.biometric.fingerprint" is found,
223 // since the former is deprecated in Q and the latter is not present pre-Q. (see b/115639644)
224 if (attr->value == "android.hardware.biometrics.fingerprint") {
225 auto element = el->CloneElement([&](const xml::Element& el, xml::Element* out_el) {
226 xml::Attribute* cloned_attr = out_el->FindOrCreateAttribute(xml::kSchemaAndroid, "name");
227 cloned_attr->value = "android.hardware.fingerprint";
228 });
229
230 el->parent->AppendChild(std::move(element));
231 }
232 }
233
234 return true;
235}
236
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700237bool ManifestFixer::BuildRules(xml::XmlActionExecutor* executor,
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700238 IDiagnostics* diag) {
239 // First verify some options.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700240 if (options_.rename_manifest_package) {
241 if (!util::IsJavaPackageName(options_.rename_manifest_package.value())) {
242 diag->Error(DiagMessage() << "invalid manifest package override '"
243 << options_.rename_manifest_package.value()
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700244 << "'");
245 return false;
246 }
247 }
248
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700249 if (options_.rename_instrumentation_target_package) {
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800250 if (!util::IsJavaPackageName(options_.rename_instrumentation_target_package.value())) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700251 diag->Error(DiagMessage()
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700252 << "invalid instrumentation target package override '"
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700253 << options_.rename_instrumentation_target_package.value()
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700254 << "'");
255 return false;
256 }
257 }
258
Adam Lesinski86d67df2017-01-31 13:47:27 -0800259 // Common <intent-filter> actions.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700260 xml::XmlNodeAction intent_filter_action;
Adam Lesinskifca5e422017-12-20 15:03:36 -0800261 intent_filter_action["action"].Action(RequiredNameIsNotEmpty);
262 intent_filter_action["category"].Action(RequiredNameIsNotEmpty);
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700263 intent_filter_action["data"];
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700264
Adam Lesinski86d67df2017-01-31 13:47:27 -0800265 // Common <meta-data> actions.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700266 xml::XmlNodeAction meta_data_action;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700267
Adam Lesinski86d67df2017-01-31 13:47:27 -0800268 // Common <uses-feature> actions.
269 xml::XmlNodeAction uses_feature_action;
270 uses_feature_action.Action(VerifyUsesFeature);
Ryan Mitchelle1de2842019-01-04 10:20:16 -0800271 uses_feature_action.Action(AddDeprecatedUsesFeatures);
Adam Lesinski86d67df2017-01-31 13:47:27 -0800272
273 // Common component actions.
274 xml::XmlNodeAction component_action;
275 component_action.Action(RequiredNameIsJavaClassName);
276 component_action["intent-filter"] = intent_filter_action;
Ryan Mitchell28afe682018-09-07 14:33:14 -0700277 component_action["preferred"] = intent_filter_action;
Adam Lesinski86d67df2017-01-31 13:47:27 -0800278 component_action["meta-data"] = meta_data_action;
279
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700280 // Manifest actions.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700281 xml::XmlNodeAction& manifest_action = (*executor)["manifest"];
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800282 manifest_action.Action(AutoGenerateIsFeatureSplit);
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700283 manifest_action.Action(VerifyManifest);
284 manifest_action.Action(FixCoreAppAttribute);
285 manifest_action.Action([&](xml::Element* el) -> bool {
286 if (options_.version_name_default) {
Colin Crossdcd58c42018-05-25 22:46:35 -0700287 if (options_.replace_version) {
288 el->RemoveAttribute(xml::kSchemaAndroid, "versionName");
289 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700290 if (el->FindAttribute(xml::kSchemaAndroid, "versionName") == nullptr) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700291 el->attributes.push_back(
292 xml::Attribute{xml::kSchemaAndroid, "versionName",
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700293 options_.version_name_default.value()});
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700294 }
Adam Lesinskicc5609d2016-04-05 12:41:07 -0700295 }
296
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700297 if (options_.version_code_default) {
Colin Crossdcd58c42018-05-25 22:46:35 -0700298 if (options_.replace_version) {
299 el->RemoveAttribute(xml::kSchemaAndroid, "versionCode");
300 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700301 if (el->FindAttribute(xml::kSchemaAndroid, "versionCode") == nullptr) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700302 el->attributes.push_back(
303 xml::Attribute{xml::kSchemaAndroid, "versionCode",
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700304 options_.version_code_default.value()});
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700305 }
Adam Lesinskicc5609d2016-04-05 12:41:07 -0700306 }
Ryan Mitchell7cb82a82018-05-10 15:35:31 -0700307
Ryan Mitchell704090e2018-07-31 14:59:25 -0700308 if (options_.version_code_major_default) {
309 if (options_.replace_version) {
310 el->RemoveAttribute(xml::kSchemaAndroid, "versionCodeMajor");
311 }
312 if (el->FindAttribute(xml::kSchemaAndroid, "versionCodeMajor") == nullptr) {
313 el->attributes.push_back(
314 xml::Attribute{xml::kSchemaAndroid, "versionCodeMajor",
315 options_.version_code_major_default.value()});
316 }
317 }
318
Ryan Mitchell7cb82a82018-05-10 15:35:31 -0700319 if (el->FindAttribute("", "platformBuildVersionCode") == nullptr) {
320 auto versionCode = el->FindAttribute(xml::kSchemaAndroid, "versionCode");
321 if (versionCode != nullptr) {
322 el->attributes.push_back(xml::Attribute{"", "platformBuildVersionCode",
323 versionCode->value});
324 }
325 }
326
327 if (el->FindAttribute("", "platformBuildVersionName") == nullptr) {
328 auto versionName = el->FindAttribute(xml::kSchemaAndroid, "versionName");
329 if (versionName != nullptr) {
330 el->attributes.push_back(xml::Attribute{"", "platformBuildVersionName",
331 versionName->value});
332 }
333 }
334
Adam Lesinski2ae4a872015-11-02 16:10:55 -0800335 return true;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700336 });
337
338 // Meta tags.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700339 manifest_action["eat-comment"];
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700340
341 // Uses-sdk actions.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700342 manifest_action["uses-sdk"].Action([&](xml::Element* el) -> bool {
343 if (options_.min_sdk_version_default &&
344 el->FindAttribute(xml::kSchemaAndroid, "minSdkVersion") == nullptr) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700345 // There was no minSdkVersion defined and we have a default to assign.
346 el->attributes.push_back(
347 xml::Attribute{xml::kSchemaAndroid, "minSdkVersion",
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700348 options_.min_sdk_version_default.value()});
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700349 }
350
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700351 if (options_.target_sdk_version_default &&
352 el->FindAttribute(xml::kSchemaAndroid, "targetSdkVersion") == nullptr) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700353 // There was no targetSdkVersion defined and we have a default to assign.
354 el->attributes.push_back(
355 xml::Attribute{xml::kSchemaAndroid, "targetSdkVersion",
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700356 options_.target_sdk_version_default.value()});
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700357 }
358 return true;
359 });
360
361 // Instrumentation actions.
Adam Lesinski86d67df2017-01-31 13:47:27 -0800362 manifest_action["instrumentation"].Action(RequiredNameIsJavaClassName);
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700363 manifest_action["instrumentation"].Action([&](xml::Element* el) -> bool {
364 if (!options_.rename_instrumentation_target_package) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700365 return true;
366 }
367
368 if (xml::Attribute* attr =
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700369 el->FindAttribute(xml::kSchemaAndroid, "targetPackage")) {
370 attr->value = options_.rename_instrumentation_target_package.value();
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700371 }
372 return true;
373 });
Adam Lesinski86d67df2017-01-31 13:47:27 -0800374 manifest_action["instrumentation"]["meta-data"] = meta_data_action;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700375
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700376 manifest_action["original-package"];
MÃ¥rten Kongstadc903d2e2016-12-09 00:23:41 +0100377 manifest_action["overlay"];
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700378 manifest_action["protected-broadcast"];
Alan Viverettecf5326f2018-01-05 16:03:50 -0500379 manifest_action["adopt-permissions"];
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700380 manifest_action["uses-permission"];
Adam Lesinski4b585db2017-05-12 15:25:50 -0700381 manifest_action["uses-permission-sdk-23"];
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700382 manifest_action["permission"];
Ryan Mitchell66f6cfb2018-07-25 16:15:17 -0700383 manifest_action["permission"]["meta-data"] = meta_data_action;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700384 manifest_action["permission-tree"];
385 manifest_action["permission-group"];
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700386 manifest_action["uses-configuration"];
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700387 manifest_action["supports-screens"];
Adam Lesinski86d67df2017-01-31 13:47:27 -0800388 manifest_action["uses-feature"] = uses_feature_action;
389 manifest_action["feature-group"]["uses-feature"] = uses_feature_action;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700390 manifest_action["compatible-screens"];
391 manifest_action["compatible-screens"]["screen"];
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700392 manifest_action["supports-gl-texture"];
Ryan Mitchell66f6cfb2018-07-25 16:15:17 -0700393 manifest_action["restrict-update"];
394 manifest_action["package-verifier"];
Adam Lesinski5119e512016-12-05 19:48:20 -0800395 manifest_action["meta-data"] = meta_data_action;
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800396 manifest_action["uses-split"].Action(RequiredNameIsJavaPackage);
Adam Lesinski5119e512016-12-05 19:48:20 -0800397
Adam Lesinski87f1e0f2017-06-27 16:21:58 -0700398 manifest_action["key-sets"]["key-set"]["public-key"];
399 manifest_action["key-sets"]["upgrade-key-set"];
400
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700401 // Application actions.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700402 xml::XmlNodeAction& application_action = manifest_action["application"];
403 application_action.Action(OptionalNameIsJavaClassName);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700404
Adam Lesinskifca5e422017-12-20 15:03:36 -0800405 application_action["uses-library"].Action(RequiredNameIsNotEmpty);
406 application_action["library"].Action(RequiredNameIsNotEmpty);
Adam Lesinskib5dc4bd2017-02-22 19:29:29 -0800407
408 xml::XmlNodeAction& static_library_action = application_action["static-library"];
409 static_library_action.Action(RequiredNameIsJavaPackage);
410 static_library_action.Action(RequiredAndroidAttribute("version"));
411
412 xml::XmlNodeAction& uses_static_library_action = application_action["uses-static-library"];
413 uses_static_library_action.Action(RequiredNameIsJavaPackage);
414 uses_static_library_action.Action(RequiredAndroidAttribute("version"));
415 uses_static_library_action.Action(RequiredAndroidAttribute("certDigest"));
Ryan Mitchell66f6cfb2018-07-25 16:15:17 -0700416 uses_static_library_action["additional-certificate"];
Adam Lesinskib5dc4bd2017-02-22 19:29:29 -0800417
Dianne Hackborn813d7502018-10-02 16:59:46 -0700418 xml::XmlNodeAction& uses_package_action = application_action["uses-package"];
419 uses_package_action.Action(RequiredNameIsJavaPackage);
420 uses_package_action["additional-certificate"];
421
Ryan Mitchelle5b38a62018-03-23 13:35:00 -0700422 if (options_.debug_mode) {
423 application_action.Action([&](xml::Element* el) -> bool {
424 xml::Attribute *attr = el->FindOrCreateAttribute(xml::kSchemaAndroid, "debuggable");
425 attr->value = "true";
426 return true;
427 });
428 }
429
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700430 application_action["meta-data"] = meta_data_action;
Adam Lesinski7a917a22017-06-02 12:55:24 -0700431
Adam Lesinski86d67df2017-01-31 13:47:27 -0800432 application_action["activity"] = component_action;
Adam Lesinski7a917a22017-06-02 12:55:24 -0700433 application_action["activity"]["layout"];
434
Adam Lesinski86d67df2017-01-31 13:47:27 -0800435 application_action["activity-alias"] = component_action;
436 application_action["service"] = component_action;
437 application_action["receiver"] = component_action;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700438
439 // Provider actions.
Adam Lesinski86d67df2017-01-31 13:47:27 -0800440 application_action["provider"] = component_action;
Adam Lesinskic10c0d02017-04-28 12:54:08 -0700441 application_action["provider"]["grant-uri-permission"];
Adam Lesinski25783ca2017-04-24 13:33:47 -0700442 application_action["provider"]["path-permission"];
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700443
Ryan Mitchell28afe682018-09-07 14:33:14 -0700444 manifest_action["package"] = manifest_action;
445
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700446 return true;
Adam Lesinski2ae4a872015-11-02 16:10:55 -0800447}
448
Adam Lesinski23034b92017-11-29 16:27:44 -0800449static void FullyQualifyClassName(const StringPiece& package, const StringPiece& attr_ns,
450 const StringPiece& attr_name, xml::Element* el) {
451 xml::Attribute* attr = el->FindAttribute(attr_ns, attr_name);
452 if (attr != nullptr) {
453 if (Maybe<std::string> new_value = util::GetFullyQualifiedClassName(package, attr->value)) {
454 attr->value = std::move(new_value.value());
Adam Lesinski52364f72016-01-11 13:10:24 -0800455 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700456 }
Adam Lesinski23034b92017-11-29 16:27:44 -0800457}
Adam Lesinski52364f72016-01-11 13:10:24 -0800458
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800459static bool RenameManifestPackage(const StringPiece& package_override, xml::Element* manifest_el) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700460 xml::Attribute* attr = manifest_el->FindAttribute({}, "package");
Adam Lesinski52364f72016-01-11 13:10:24 -0800461
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700462 // We've already verified that the manifest element is present, with a package
463 // name specified.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700464 CHECK(attr != nullptr);
Adam Lesinski52364f72016-01-11 13:10:24 -0800465
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700466 std::string original_package = std::move(attr->value);
Adam Lesinskid5083f62017-01-16 15:07:21 -0800467 attr->value = package_override.to_string();
Adam Lesinski52364f72016-01-11 13:10:24 -0800468
Adam Lesinski23034b92017-11-29 16:27:44 -0800469 xml::Element* application_el = manifest_el->FindChild({}, "application");
470 if (application_el != nullptr) {
471 FullyQualifyClassName(original_package, xml::kSchemaAndroid, "name", application_el);
472 FullyQualifyClassName(original_package, xml::kSchemaAndroid, "backupAgent", application_el);
473
474 for (xml::Element* child_el : application_el->GetChildElements()) {
475 if (child_el->namespace_uri.empty()) {
476 if (child_el->name == "activity" || child_el->name == "activity-alias" ||
477 child_el->name == "provider" || child_el->name == "receiver" ||
478 child_el->name == "service") {
479 FullyQualifyClassName(original_package, xml::kSchemaAndroid, "name", child_el);
480 }
481
482 if (child_el->name == "activity-alias") {
483 FullyQualifyClassName(original_package, xml::kSchemaAndroid, "targetActivity", child_el);
484 }
485 }
486 }
487 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700488 return true;
Adam Lesinski52364f72016-01-11 13:10:24 -0800489}
490
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700491bool ManifestFixer::Consume(IAaptContext* context, xml::XmlResource* doc) {
492 xml::Element* root = xml::FindRootElement(doc->root.get());
493 if (!root || !root->namespace_uri.empty() || root->name != "manifest") {
494 context->GetDiagnostics()->Error(DiagMessage(doc->file.source)
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700495 << "root tag must be <manifest>");
496 return false;
497 }
Adam Lesinski2ae4a872015-11-02 16:10:55 -0800498
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800499 if ((options_.min_sdk_version_default || options_.target_sdk_version_default) &&
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700500 root->FindChild({}, "uses-sdk") == nullptr) {
Adam Lesinskie343eb12016-10-27 16:31:58 -0700501 // Auto insert a <uses-sdk> element. This must be inserted before the
502 // <application> tag. The device runtime PackageParser will make SDK version
503 // decisions while parsing <application>.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700504 std::unique_ptr<xml::Element> uses_sdk = util::make_unique<xml::Element>();
505 uses_sdk->name = "uses-sdk";
Adam Lesinskie343eb12016-10-27 16:31:58 -0700506 root->InsertChild(0, std::move(uses_sdk));
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700507 }
Adam Lesinski2ae4a872015-11-02 16:10:55 -0800508
Adam Lesinskic6284372017-12-04 13:46:23 -0800509 if (options_.compile_sdk_version) {
510 xml::Attribute* attr = root->FindOrCreateAttribute(xml::kSchemaAndroid, "compileSdkVersion");
511
512 // Make sure we un-compile the value if it was set to something else.
513 attr->compiled_value = {};
514
515 attr->value = options_.compile_sdk_version.value();
516 }
517
518 if (options_.compile_sdk_version_codename) {
519 xml::Attribute* attr =
520 root->FindOrCreateAttribute(xml::kSchemaAndroid, "compileSdkVersionCodename");
521
522 // Make sure we un-compile the value if it was set to something else.
523 attr->compiled_value = {};
524
525 attr->value = options_.compile_sdk_version_codename.value();
526 }
527
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700528 xml::XmlActionExecutor executor;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700529 if (!BuildRules(&executor, context->GetDiagnostics())) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700530 return false;
531 }
Adam Lesinskicc5609d2016-04-05 12:41:07 -0700532
Izabela Orlowskaad9e1322017-12-19 16:22:42 +0000533 xml::XmlActionExecutorPolicy policy = options_.warn_validation
534 ? xml::XmlActionExecutorPolicy::kWhitelistWarning
535 : xml::XmlActionExecutorPolicy::kWhitelist;
536 if (!executor.Execute(policy, context->GetDiagnostics(), doc)) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700537 return false;
538 }
Adam Lesinskicc5609d2016-04-05 12:41:07 -0700539
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700540 if (options_.rename_manifest_package) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700541 // Rename manifest package outside of the XmlActionExecutor.
Adam Lesinskie343eb12016-10-27 16:31:58 -0700542 // We need to extract the old package name and FullyQualify all class
543 // names.
Adam Lesinskib0c47ef2017-03-06 20:05:57 -0800544 if (!RenameManifestPackage(options_.rename_manifest_package.value(), root)) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700545 return false;
Adam Lesinskicc5609d2016-04-05 12:41:07 -0700546 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700547 }
548 return true;
Adam Lesinski2ae4a872015-11-02 16:10:55 -0800549}
550
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700551} // namespace aapt