blob: 2034c5701492e3962297189298c929536816c376 [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
17#include "ResourceUtils.h"
Adam Lesinski2ae4a872015-11-02 16:10:55 -080018#include "link/ManifestFixer.h"
19#include "util/Util.h"
Adam Lesinski467f1712015-11-16 17:35:44 -080020#include "xml/XmlDom.h"
Adam Lesinski2ae4a872015-11-02 16:10:55 -080021
22namespace aapt {
23
24static bool verifyManifest(IAaptContext* context, const Source& source, xml::Element* manifestEl) {
25 bool error = false;
26
27 xml::Attribute* attr = manifestEl->findAttribute({}, u"package");
28 if (!attr) {
29 context->getDiagnostics()->error(DiagMessage(source.withLine(manifestEl->lineNumber))
30 << "missing 'package' attribute");
31 error = true;
32 } else if (ResourceUtils::isReference(attr->value)) {
33 context->getDiagnostics()->error(DiagMessage(source.withLine(manifestEl->lineNumber))
34 << "value for attribute 'package' must not be a "
35 "reference");
36 error = true;
37 } else if (!util::isJavaPackageName(attr->value)) {
38 context->getDiagnostics()->error(DiagMessage(source.withLine(manifestEl->lineNumber))
39 << "invalid package name '" << attr->value << "'");
40 error = true;
41 }
42
43 return !error;
44}
45
46static bool fixUsesSdk(IAaptContext* context, const Source& source, xml::Element* el,
47 const ManifestFixerOptions& options) {
48 if (options.minSdkVersionDefault &&
49 el->findAttribute(xml::kSchemaAndroid, u"minSdkVersion") == nullptr) {
50 // There was no minSdkVersion defined and we have a default to assign.
51 el->attributes.push_back(xml::Attribute{
52 xml::kSchemaAndroid, u"minSdkVersion", options.minSdkVersionDefault.value() });
53 }
54
55 if (options.targetSdkVersionDefault &&
56 el->findAttribute(xml::kSchemaAndroid, u"targetSdkVersion") == nullptr) {
57 // There was no targetSdkVersion defined and we have a default to assign.
58 el->attributes.push_back(xml::Attribute{
59 xml::kSchemaAndroid, u"targetSdkVersion",
60 options.targetSdkVersionDefault.value() });
61 }
62 return true;
63}
64
Adam Lesinski467f1712015-11-16 17:35:44 -080065bool ManifestFixer::consume(IAaptContext* context, xml::XmlResource* doc) {
Adam Lesinski2ae4a872015-11-02 16:10:55 -080066 xml::Element* root = xml::findRootElement(doc->root.get());
67 if (!root || !root->namespaceUri.empty() || root->name != u"manifest") {
68 context->getDiagnostics()->error(DiagMessage(doc->file.source)
69 << "root tag must be <manifest>");
70 return false;
71 }
72
73 if (!verifyManifest(context, doc->file.source, root)) {
74 return false;
75 }
76
77 bool foundUsesSdk = false;
78 for (xml::Element* el : root->getChildElements()) {
79 if (!el->namespaceUri.empty()) {
80 continue;
81 }
82
83 if (el->name == u"uses-sdk") {
84 foundUsesSdk = true;
85 fixUsesSdk(context, doc->file.source, el, mOptions);
86 }
87 }
88
89 if (!foundUsesSdk && (mOptions.minSdkVersionDefault || mOptions.targetSdkVersionDefault)) {
90 std::unique_ptr<xml::Element> usesSdk = util::make_unique<xml::Element>();
91 usesSdk->name = u"uses-sdk";
92 fixUsesSdk(context, doc->file.source, usesSdk.get(), mOptions);
93 root->addChild(std::move(usesSdk));
94 }
95
96 return true;
97}
98
99} // namespace aapt