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