1a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski/*
2a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski * Copyright (C) 2015 The Android Open Source Project
3a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski *
4a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski * Licensed under the Apache License, Version 2.0 (the "License");
5a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski * you may not use this file except in compliance with the License.
6a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski * You may obtain a copy of the License at
7a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski *
8a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski *      http://www.apache.org/licenses/LICENSE-2.0
9a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski *
10a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski * Unless required by applicable law or agreed to in writing, software
11a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski * distributed under the License is distributed on an "AS IS" BASIS,
12a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski * See the License for the specific language governing permissions and
14a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski * limitations under the License.
15a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski */
16a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski
17ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski#include "java/ProguardRules.h"
181ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
19a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski#include <memory>
20a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski#include <string>
21a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski
22ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include "android-base/macros.h"
23ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
24ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include "util/Util.h"
25ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include "xml/XmlDom.h"
26ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
27a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinskinamespace aapt {
28a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinskinamespace proguard {
29a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski
30a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinskiclass BaseVisitor : public xml::Visitor {
31ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski public:
325c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  using xml::Visitor::Visit;
33a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski
345c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  BaseVisitor(const Source& source, KeepSet* keep_set) : source_(source), keep_set_(keep_set) {
35ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
36ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
375c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  void Visit(xml::Element* node) override {
38ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!node->namespace_uri.empty()) {
39ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      Maybe<xml::ExtractedPackage> maybe_package =
40ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          xml::ExtractPackageFromNamespace(node->namespace_uri);
41ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (maybe_package) {
42ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        // This is a custom view, let's figure out the class name from this.
43ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        std::string package = maybe_package.value().package + "." + node->name;
44ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (util::IsJavaClassName(package)) {
45ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          AddClass(node->line_number, package);
46a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski        }
47ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      }
48ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    } else if (util::IsJavaClassName(node->name)) {
49ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      AddClass(node->line_number, node->name);
50a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski    }
51a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski
52ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    for (const auto& child : node->children) {
53ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      child->Accept(this);
54a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski    }
55ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
56a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski
57ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski protected:
58ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  void AddClass(size_t line_number, const std::string& class_name) {
59ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    keep_set_->AddClass(Source(source_.path, line_number), class_name);
60ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
61a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski
62ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  void AddMethod(size_t line_number, const std::string& method_name) {
63ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    keep_set_->AddMethod(Source(source_.path, line_number), method_name);
64ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
65ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
66ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski private:
67ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  DISALLOW_COPY_AND_ASSIGN(BaseVisitor);
68ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
69ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  Source source_;
70ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  KeepSet* keep_set_;
71a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski};
72a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski
73ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskiclass LayoutVisitor : public BaseVisitor {
74ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski public:
755c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  LayoutVisitor(const Source& source, KeepSet* keep_set) : BaseVisitor(source, keep_set) {
765c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  }
77ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
785c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  void Visit(xml::Element* node) override {
79ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    bool check_class = false;
80ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    bool check_name = false;
81ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (node->namespace_uri.empty()) {
82f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski      if (node->name == "view") {
83f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski        check_class = true;
84f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski      } else if (node->name == "fragment") {
85f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski        check_class = check_name = true;
86f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski      }
87ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    } else if (node->namespace_uri == xml::kSchemaAndroid) {
88ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      check_name = node->name == "fragment";
89a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski    }
90a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski
91ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    for (const auto& attr : node->attributes) {
92ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (check_class && attr.namespace_uri.empty() && attr.name == "class" &&
93ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          util::IsJavaClassName(attr.value)) {
94ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        AddClass(node->line_number, attr.value);
95ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      } else if (check_name && attr.namespace_uri == xml::kSchemaAndroid &&
96ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                 attr.name == "name" && util::IsJavaClassName(attr.value)) {
97ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        AddClass(node->line_number, attr.value);
98ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      } else if (attr.namespace_uri == xml::kSchemaAndroid &&
99ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                 attr.name == "onClick") {
100ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        AddMethod(node->line_number, attr.value);
101ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      }
102ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    }
103a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski
104ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    BaseVisitor::Visit(node);
105ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
106a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski
107ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski private:
108ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  DISALLOW_COPY_AND_ASSIGN(LayoutVisitor);
109a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski};
110a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski
111f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinskiclass MenuVisitor : public BaseVisitor {
112f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski public:
113f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski  MenuVisitor(const Source& source, KeepSet* keep_set) : BaseVisitor(source, keep_set) {
114f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski  }
115f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski
1165c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  void Visit(xml::Element* node) override {
117f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski    if (node->namespace_uri.empty() && node->name == "item") {
118f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski      for (const auto& attr : node->attributes) {
119f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski        if (attr.namespace_uri == xml::kSchemaAndroid) {
120f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski          if ((attr.name == "actionViewClass" || attr.name == "actionProviderClass") &&
121f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski              util::IsJavaClassName(attr.value)) {
122f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski            AddClass(node->line_number, attr.value);
123f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski          } else if (attr.name == "onClick") {
124f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski            AddMethod(node->line_number, attr.value);
125f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski          }
126f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski        }
127f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski      }
128f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski    }
129f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski
130f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski    BaseVisitor::Visit(node);
131f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski  }
132f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski
133f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski private:
134f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski  DISALLOW_COPY_AND_ASSIGN(MenuVisitor);
135f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski};
136f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski
137ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskiclass XmlResourceVisitor : public BaseVisitor {
138ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski public:
1395c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  XmlResourceVisitor(const Source& source, KeepSet* keep_set) : BaseVisitor(source, keep_set) {
1405c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  }
141ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
1425c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  void Visit(xml::Element* node) override {
143ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    bool check_fragment = false;
144ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (node->namespace_uri.empty()) {
145ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      check_fragment =
146ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          node->name == "PreferenceScreen" || node->name == "header";
147a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski    }
148a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski
149ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (check_fragment) {
150ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      xml::Attribute* attr =
151ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          node->FindAttribute(xml::kSchemaAndroid, "fragment");
152ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (attr && util::IsJavaClassName(attr->value)) {
153ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        AddClass(node->line_number, attr->value);
154ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      }
155ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    }
156a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski
157ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    BaseVisitor::Visit(node);
158ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
159a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski
160ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski private:
161ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  DISALLOW_COPY_AND_ASSIGN(XmlResourceVisitor);
162a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski};
163a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski
164ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskiclass TransitionVisitor : public BaseVisitor {
165ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski public:
1665c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  TransitionVisitor(const Source& source, KeepSet* keep_set) : BaseVisitor(source, keep_set) {
1675c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  }
168ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
1695c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  void Visit(xml::Element* node) override {
170ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    bool check_class =
1715c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski        node->namespace_uri.empty() && (node->name == "transition" || node->name == "pathMotion");
172ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (check_class) {
173ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      xml::Attribute* attr = node->FindAttribute({}, "class");
174ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (attr && util::IsJavaClassName(attr->value)) {
175ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        AddClass(node->line_number, attr->value);
176ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      }
177a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski    }
178a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski
179ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    BaseVisitor::Visit(node);
180ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
181a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski
182ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski private:
183ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  DISALLOW_COPY_AND_ASSIGN(TransitionVisitor);
184a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski};
185a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski
186ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskiclass ManifestVisitor : public BaseVisitor {
187ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski public:
188ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ManifestVisitor(const Source& source, KeepSet* keep_set, bool main_dex_only)
189ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      : BaseVisitor(source, keep_set), main_dex_only_(main_dex_only) {}
190ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
1915c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski  void Visit(xml::Element* node) override {
192ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (node->namespace_uri.empty()) {
193ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      bool get_name = false;
194ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (node->name == "manifest") {
195ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        xml::Attribute* attr = node->FindAttribute({}, "package");
196ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (attr) {
197ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          package_ = attr->value;
198ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        }
199ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      } else if (node->name == "application") {
200ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        get_name = true;
2015c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski        xml::Attribute* attr = node->FindAttribute(xml::kSchemaAndroid, "backupAgent");
202ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (attr) {
2035c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski          Maybe<std::string> result = util::GetFullyQualifiedClassName(package_, attr->value);
204ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          if (result) {
205ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski            AddClass(node->line_number, result.value());
206ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          }
207ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        }
208ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (main_dex_only_) {
2095c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski          xml::Attribute* default_process = node->FindAttribute(xml::kSchemaAndroid, "process");
210ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          if (default_process) {
211ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski            default_process_ = default_process->value;
212ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          }
213ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        }
214ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      } else if (node->name == "activity" || node->name == "service" ||
215ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                 node->name == "receiver" || node->name == "provider") {
216ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        get_name = true;
217ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
218ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (main_dex_only_) {
2195c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski          xml::Attribute* component_process = node->FindAttribute(xml::kSchemaAndroid, "process");
220a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski
221ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          const std::string& process =
222ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski              component_process ? component_process->value : default_process_;
223ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          get_name = !process.empty() && process[0] != ':';
224a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski        }
225ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      } else if (node->name == "instrumentation") {
226ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        get_name = true;
227ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      }
228ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
229ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (get_name) {
230ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        xml::Attribute* attr = node->FindAttribute(xml::kSchemaAndroid, "name");
231ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        get_name = attr != nullptr;
232ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
233ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (get_name) {
2345c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski          Maybe<std::string> result = util::GetFullyQualifiedClassName(package_, attr->value);
235ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          if (result) {
236ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski            AddClass(node->line_number, result.value());
237ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          }
238ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        }
239ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      }
240a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski    }
241ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    BaseVisitor::Visit(node);
242ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
243ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
244ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski private:
245ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  DISALLOW_COPY_AND_ASSIGN(ManifestVisitor);
246a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski
247ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::string package_;
248ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  const bool main_dex_only_;
249ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::string default_process_;
250a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski};
251a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski
2525c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinskibool CollectProguardRulesForManifest(const Source& source, xml::XmlResource* res, KeepSet* keep_set,
253ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                                     bool main_dex_only) {
254ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ManifestVisitor visitor(source, keep_set, main_dex_only);
255ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (res->root) {
256ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    res->root->Accept(&visitor);
257ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    return true;
258ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
259ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  return false;
260a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski}
261a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski
2625c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinskibool CollectProguardRules(const Source& source, xml::XmlResource* res, KeepSet* keep_set) {
263ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (!res->root) {
264ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    return false;
265ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
266a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski
267ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  switch (res->file.name.type) {
268ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    case ResourceType::kLayout: {
269ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      LayoutVisitor visitor(source, keep_set);
270ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      res->root->Accept(&visitor);
271ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      break;
272ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    }
273a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski
274ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    case ResourceType::kXml: {
275ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      XmlResourceVisitor visitor(source, keep_set);
276ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      res->root->Accept(&visitor);
277ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      break;
278ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    }
279a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski
280ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    case ResourceType::kTransition: {
281ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      TransitionVisitor visitor(source, keep_set);
282ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      res->root->Accept(&visitor);
283ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      break;
284a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski    }
285ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
286f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski    case ResourceType::kMenu: {
287f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski      MenuVisitor visitor(source, keep_set);
288f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski      res->root->Accept(&visitor);
289f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski      break;
290f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski    }
291f762df257574231ffd08679a69e9cf62fe143dcdAdam Lesinski
292ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    default:
293ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      break;
294ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
295ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  return true;
296a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski}
297a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski
298ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskibool WriteKeepSet(std::ostream* out, const KeepSet& keep_set) {
299ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  for (const auto& entry : keep_set.keep_set_) {
300ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    for (const Source& source : entry.second) {
301ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      *out << "# Referenced at " << source << "\n";
302a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski    }
303ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    *out << "-keep class " << entry.first << " { <init>(...); }\n" << std::endl;
304ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
305a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski
306ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  for (const auto& entry : keep_set.keep_method_set_) {
307ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    for (const Source& source : entry.second) {
308ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      *out << "# Referenced at " << source << "\n";
309a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski    }
3105c33fb5408d6c02dc2c73f53d89d1494fe04f208Adam Lesinski    *out << "-keepclassmembers class * { *** " << entry.first << "(...); }\n" << std::endl;
311ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
312ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  return true;
313a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski}
314a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski
315ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski}  // namespace proguard
316ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski}  // namespace aapt
317