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#include "util/Util.h"
19467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski#include "xml/XmlDom.h"
201ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
21a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski#include <memory>
22a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski#include <string>
23a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski
24a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinskinamespace aapt {
25a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinskinamespace proguard {
26a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski
27a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinskiclass BaseVisitor : public xml::Visitor {
28a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinskipublic:
29a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski    BaseVisitor(const Source& source, KeepSet* keepSet) : mSource(source), mKeepSet(keepSet) {
30a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski    }
31a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski
32a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski    virtual void visit(xml::Text*) override {};
33a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski
34a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski    virtual void visit(xml::Namespace* node) override {
35a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski        for (const auto& child : node->children) {
36a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski            child->accept(this);
37a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski        }
38a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski    }
39a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski
40a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski    virtual void visit(xml::Element* node) override {
41a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski        if (!node->namespaceUri.empty()) {
42467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski            Maybe<xml::ExtractedPackage> maybePackage = xml::extractPackageFromNamespace(
43a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski                    node->namespaceUri);
44a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski            if (maybePackage) {
45a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski                // This is a custom view, let's figure out the class name from this.
46467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski                std::u16string package = maybePackage.value().package + u"." + node->name;
47a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski                if (util::isJavaClassName(package)) {
48a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski                    addClass(node->lineNumber, package);
49a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski                }
50a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski            }
51a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski        } else if (util::isJavaClassName(node->name)) {
52a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski            addClass(node->lineNumber, node->name);
53a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski        }
54a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski
55a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski        for (const auto& child: node->children) {
56a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski            child->accept(this);
57a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski        }
58a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski    }
59a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski
60a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinskiprotected:
61a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski    void addClass(size_t lineNumber, const std::u16string& className) {
621ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        mKeepSet->addClass(Source(mSource.path, lineNumber), className);
63a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski    }
64a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski
65a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski    void addMethod(size_t lineNumber, const std::u16string& methodName) {
661ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        mKeepSet->addMethod(Source(mSource.path, lineNumber), methodName);
67a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski    }
68a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski
69a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinskiprivate:
70a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski    Source mSource;
71a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski    KeepSet* mKeepSet;
72a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski};
73a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski
74a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinskistruct LayoutVisitor : public BaseVisitor {
75a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski    LayoutVisitor(const Source& source, KeepSet* keepSet) : BaseVisitor(source, keepSet) {
76a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski    }
77a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski
78a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski    virtual void visit(xml::Element* node) override {
79a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski        bool checkClass = false;
80a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski        bool checkName = false;
81a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski        if (node->namespaceUri.empty()) {
82a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski            checkClass = node->name == u"view" || node->name == u"fragment";
832ae4a877d1623f851040ce69239552c873f1abf0Adam Lesinski        } else if (node->namespaceUri == xml::kSchemaAndroid) {
84a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski            checkName = node->name == u"fragment";
85a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski        }
86a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski
87a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski        for (const auto& attr : node->attributes) {
88a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski            if (checkClass && attr.namespaceUri.empty() && attr.name == u"class" &&
89a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski                    util::isJavaClassName(attr.value)) {
90a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski                addClass(node->lineNumber, attr.value);
912ae4a877d1623f851040ce69239552c873f1abf0Adam Lesinski            } else if (checkName && attr.namespaceUri == xml::kSchemaAndroid &&
922ae4a877d1623f851040ce69239552c873f1abf0Adam Lesinski                    attr.name == u"name" && util::isJavaClassName(attr.value)) {
93a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski                addClass(node->lineNumber, attr.value);
942ae4a877d1623f851040ce69239552c873f1abf0Adam Lesinski            } else if (attr.namespaceUri == xml::kSchemaAndroid && attr.name == u"onClick") {
95a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski                addMethod(node->lineNumber, attr.value);
96a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski            }
97a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski        }
98a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski
99a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski        BaseVisitor::visit(node);
100a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski    }
101a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski};
102a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski
103a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinskistruct XmlResourceVisitor : public BaseVisitor {
104a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski    XmlResourceVisitor(const Source& source, KeepSet* keepSet) : BaseVisitor(source, keepSet) {
105a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski    }
106a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski
107a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski    virtual void visit(xml::Element* node) override {
108a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski        bool checkFragment = false;
109a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski        if (node->namespaceUri.empty()) {
110a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski            checkFragment = node->name == u"PreferenceScreen" || node->name == u"header";
111a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski        }
112a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski
113a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski        if (checkFragment) {
1142ae4a877d1623f851040ce69239552c873f1abf0Adam Lesinski            xml::Attribute* attr = node->findAttribute(xml::kSchemaAndroid, u"fragment");
115a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski            if (attr && util::isJavaClassName(attr->value)) {
116a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski                addClass(node->lineNumber, attr->value);
117a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski            }
118a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski        }
119a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski
120a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski        BaseVisitor::visit(node);
121a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski    }
122a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski};
123a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski
124a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinskistruct TransitionVisitor : public BaseVisitor {
125a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski    TransitionVisitor(const Source& source, KeepSet* keepSet) : BaseVisitor(source, keepSet) {
126a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski    }
127a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski
128a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski    virtual void visit(xml::Element* node) override {
129a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski        bool checkClass = node->namespaceUri.empty() &&
130a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski                (node->name == u"transition" || node->name == u"pathMotion");
131a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski        if (checkClass) {
132a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski            xml::Attribute* attr = node->findAttribute({}, u"class");
133a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski            if (attr && util::isJavaClassName(attr->value)) {
134a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski                addClass(node->lineNumber, attr->value);
135a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski            }
136a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski        }
137a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski
138a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski        BaseVisitor::visit(node);
139a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski    }
140a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski};
141a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski
142a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinskistruct ManifestVisitor : public BaseVisitor {
143a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski    ManifestVisitor(const Source& source, KeepSet* keepSet) : BaseVisitor(source, keepSet) {
144a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski    }
145a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski
146a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski    virtual void visit(xml::Element* node) override {
147a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski        if (node->namespaceUri.empty()) {
148a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski            bool getName = false;
149a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski            if (node->name == u"manifest") {
150a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski                xml::Attribute* attr = node->findAttribute({}, u"package");
151a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski                if (attr) {
152a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski                    mPackage = attr->value;
153a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski                }
154a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski            } else if (node->name == u"application") {
155a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski                getName = true;
1562ae4a877d1623f851040ce69239552c873f1abf0Adam Lesinski                xml::Attribute* attr = node->findAttribute(xml::kSchemaAndroid, u"backupAgent");
157a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski                if (attr) {
158a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski                    Maybe<std::u16string> result = util::getFullyQualifiedClassName(mPackage,
159a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski                                                                                    attr->value);
160a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski                    if (result) {
161a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski                        addClass(node->lineNumber, result.value());
162a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski                    }
163a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski                }
164a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski            } else if (node->name == u"activity" || node->name == u"service" ||
165a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski                    node->name == u"receiver" || node->name == u"provider" ||
166a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski                    node->name == u"instrumentation") {
167a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski                getName = true;
168a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski            }
169a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski
170a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski            if (getName) {
1712ae4a877d1623f851040ce69239552c873f1abf0Adam Lesinski                xml::Attribute* attr = node->findAttribute(xml::kSchemaAndroid, u"name");
172a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski                if (attr) {
173a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski                    Maybe<std::u16string> result = util::getFullyQualifiedClassName(mPackage,
174a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski                                                                                    attr->value);
175a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski                    if (result) {
176a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski                        addClass(node->lineNumber, result.value());
177a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski                    }
178a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski                }
179a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski            }
180a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski        }
181a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski        BaseVisitor::visit(node);
182a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski    }
183a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski
184a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski    std::u16string mPackage;
185a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski};
186a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski
187467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinskibool collectProguardRulesForManifest(const Source& source, xml::XmlResource* res,
188467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski                                     KeepSet* keepSet) {
189a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski    ManifestVisitor visitor(source, keepSet);
1901ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    if (res->root) {
1911ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        res->root->accept(&visitor);
1921ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        return true;
1931ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    }
1941ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    return false;
195a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski}
196a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski
197467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinskibool collectProguardRules(const Source& source, xml::XmlResource* res, KeepSet* keepSet) {
1981ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    if (!res->root) {
1991ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        return false;
2001ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    }
2011ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
2021ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    switch (res->file.name.type) {
203a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski        case ResourceType::kLayout: {
204a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski            LayoutVisitor visitor(source, keepSet);
2051ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            res->root->accept(&visitor);
206a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski            break;
207a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski        }
208a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski
209a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski        case ResourceType::kXml: {
210a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski            XmlResourceVisitor visitor(source, keepSet);
2111ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            res->root->accept(&visitor);
212a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski            break;
213a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski        }
214a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski
215a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski        case ResourceType::kTransition: {
216a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski            TransitionVisitor visitor(source, keepSet);
2171ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            res->root->accept(&visitor);
218a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski            break;
219a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski        }
220a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski
221a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski        default:
222a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski            break;
223a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski    }
224a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski    return true;
225a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski}
226a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski
227a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinskibool writeKeepSet(std::ostream* out, const KeepSet& keepSet) {
228a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski    for (const auto& entry : keepSet.mKeepSet) {
2291ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        for (const Source& source : entry.second) {
23024b8ff0faf7c59323d0171cdd825ca09e712aa1eAdam Lesinski            *out << "# Referenced at " << source << "\n";
231a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski        }
232a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski        *out << "-keep class " << entry.first << " { <init>(...); }\n" << std::endl;
233a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski    }
234a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski
235a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski    for (const auto& entry : keepSet.mKeepMethodSet) {
2361ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        for (const Source& source : entry.second) {
23724b8ff0faf7c59323d0171cdd825ca09e712aa1eAdam Lesinski            *out << "# Referenced at " << source << "\n";
238a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski        }
239a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski        *out << "-keepclassmembers class * { *** " << entry.first << "(...); }\n" << std::endl;
240a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski    }
241a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski    return true;
242a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski}
243a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski
244a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski} // namespace proguard
245a1ad4a812a87642ad259ff4478159e8cc8194680Adam Lesinski} // namespace aapt
246