Loading tools/aapt2/Android.mk +1 −0 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ sources := \ BinaryXmlPullParser.cpp \ BindingXmlPullParser.cpp \ ConfigDescription.cpp \ Debug.cpp \ Files.cpp \ Flag.cpp \ JavaClassGenerator.cpp \ Loading tools/aapt2/BinaryResourceParser.cpp +29 −14 Original line number Diff line number Diff line Loading @@ -475,10 +475,17 @@ bool BinaryResourceParser::parsePublic(const ResChunk_header* chunk) { source.line = entry->sourceLine; } if (!mTable->markPublic(name, resId, source)) { if (!mTable->markPublicAllowMangled(name, resId, source)) { return false; } // Add this resource name->id mapping to the index so // that we can resolve all ID references to name references. auto cacheIter = mIdIndex.find(resId); if (cacheIter == mIdIndex.end()) { mIdIndex.insert({ resId, name }); } entry++; } return true; Loading Loading @@ -611,12 +618,12 @@ bool BinaryResourceParser::parseType(const ResChunk_header* chunk) { source.line = sourceBlock->line; } if (!mTable->addResource(name, config, source, std::move(resourceValue))) { if (!mTable->addResourceAllowMangled(name, config, source, std::move(resourceValue))) { return false; } if ((entry->flags & ResTable_entry::FLAG_PUBLIC) != 0) { if (!mTable->markPublic(name, resId, mSource.line(0))) { if (!mTable->markPublicAllowMangled(name, resId, mSource.line(0))) { return false; } } Loading @@ -635,6 +642,10 @@ std::unique_ptr<Item> BinaryResourceParser::parseValue(const ResourceNameRef& na const ConfigDescription& config, const Res_value* value, uint16_t flags) { if (name.type == ResourceType::kId) { return util::make_unique<Id>(); } if (value->dataType == Res_value::TYPE_STRING) { StringPiece16 str = util::getString(mValuePool, value->data); Loading Loading @@ -697,13 +708,6 @@ std::unique_ptr<Item> BinaryResourceParser::parseValue(const ResourceNameRef& na StringPool::Context{ 1, config })); } if (name.type == ResourceType::kId || (value->dataType == Res_value::TYPE_NULL && value->data == Res_value::DATA_NULL_UNDEFINED && (flags & ResTable_entry::FLAG_WEAK) != 0)) { return util::make_unique<Id>(); } // Treat this as a raw binary primitive. return util::make_unique<BinaryPrimitive>(*value); } Loading Loading @@ -789,10 +793,21 @@ std::unique_ptr<Attribute> BinaryResourceParser::parseAttr(const ResourceNameRef continue; } attr->symbols.push_back(Attribute::Symbol{ Reference(mapEntry.name.ident), mapEntry.value.data }); Attribute::Symbol symbol; symbol.value = mapEntry.value.data; if (mapEntry.name.ident == 0) { // The map entry's key (id) is not set. This must be // a symbol reference, so resolve it. ResourceNameRef symbolName; bool result = getSymbol(&mapEntry.name.ident, &symbolName); assert(result); symbol.symbol.name = symbolName.toResourceName(); } else { // The map entry's key (id) is a regular reference. symbol.symbol.id = mapEntry.name.ident; } attr->symbols.push_back(std::move(symbol)); } } Loading tools/aapt2/Debug.cpp 0 → 100644 +181 −0 Original line number Diff line number Diff line /* * Copyright (C) 2015 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "Debug.h" #include "ResourceTable.h" #include "ResourceValues.h" #include "Util.h" #include <algorithm> #include <iostream> #include <map> #include <memory> #include <set> #include <vector> namespace aapt { struct PrintVisitor : ConstValueVisitor { void visit(const Attribute& attr, ValueVisitorArgs&) override { std::cout << "(attr) type="; attr.printMask(std::cout); static constexpr uint32_t kMask = android::ResTable_map::TYPE_ENUM | android::ResTable_map::TYPE_FLAGS; if (attr.typeMask & kMask) { for (const auto& symbol : attr.symbols) { std::cout << "\n " << symbol.symbol.name.entry << " (" << symbol.symbol.id << ") = " << symbol.value; } } } void visit(const Style& style, ValueVisitorArgs&) override { std::cout << "(style)"; if (style.parent.name.isValid() || style.parent.id.isValid()) { std::cout << " parent="; if (style.parent.name.isValid()) { std::cout << style.parent.name << " "; } if (style.parent.id.isValid()) { std::cout << style.parent.id; } } for (const auto& entry : style.entries) { std::cout << "\n "; if (entry.key.name.isValid()) { std::cout << entry.key.name.package << ":" << entry.key.name.entry; } if (entry.key.id.isValid()) { std::cout << "(" << entry.key.id << ")"; } std::cout << "=" << *entry.value; } } void visit(const Array& array, ValueVisitorArgs&) override { array.print(std::cout); } void visit(const Plural& plural, ValueVisitorArgs&) override { plural.print(std::cout); } void visit(const Styleable& styleable, ValueVisitorArgs&) override { styleable.print(std::cout); } void visitItem(const Item& item, ValueVisitorArgs& args) override { item.print(std::cout); } }; void Debug::printTable(const std::shared_ptr<ResourceTable>& table) { std::cout << "Package name=" << table->getPackage(); if (table->getPackageId() != ResourceTable::kUnsetPackageId) { std::cout << " id=" << std::hex << table->getPackageId() << std::dec; } std::cout << std::endl; for (const auto& type : *table) { std::cout << " type " << type->type; if (type->typeId != ResourceTableType::kUnsetTypeId) { std::cout << " id=" << std::hex << type->typeId << std::dec; } std::cout << " entryCount=" << type->entries.size() << std::endl; std::vector<const ResourceEntry*> sortedEntries; for (const auto& entry : type->entries) { auto iter = std::lower_bound(sortedEntries.begin(), sortedEntries.end(), entry.get(), [](const ResourceEntry* a, const ResourceEntry* b) -> bool { return a->entryId < b->entryId; }); sortedEntries.insert(iter, entry.get()); } for (const ResourceEntry* entry : sortedEntries) { ResourceId id = { table->getPackageId(), type->typeId, entry->entryId }; ResourceName name = { table->getPackage(), type->type, entry->name }; std::cout << " spec resource " << id << " " << name; if (entry->publicStatus.isPublic) { std::cout << " PUBLIC"; } std::cout << std::endl; PrintVisitor visitor; for (const auto& value : entry->values) { std::cout << " (" << value.config << ") "; value.value->accept(visitor, {}); std::cout << std::endl; } } } } static size_t getNodeIndex(const std::vector<ResourceName>& names, const ResourceName& name) { auto iter = std::lower_bound(names.begin(), names.end(), name); assert(iter != names.end() && *iter == name); return std::distance(names.begin(), iter); } void Debug::printStyleGraph(const std::shared_ptr<ResourceTable>& table) { std::vector<ResourceName> names; std::map<ResourceName, std::set<ResourceName>> graph; for (const auto& type : *table) { for (const auto& entry : type->entries) { ResourceName name = { table->getPackage(), type->type, entry->name }; for (const auto& value : entry->values) { visitFunc<Style>(*value.value, [&](const Style& style) { if (style.parent.name.isValid()) { names.push_back(style.parent.name); names.push_back(name); graph[style.parent.name].insert(name); } }); } } } std::sort(names.begin(), names.end()); auto it1 = std::unique(names.begin(), names.end()); names.resize(std::distance(names.begin(), it1)); std::cout << "digraph styles {\n"; for (const auto& name : names) { std::cout << " node_" << getNodeIndex(names, name) << " [label=\"" << name.entry << "\"];\n"; } for (const auto& entry : graph) { const ResourceName& parent = entry.first; size_t parentNodeIndex = getNodeIndex(names, parent); for (const auto& childName : entry.second) { std::cout << "node_" << getNodeIndex(names, childName) << " -> " << "node_" << parentNodeIndex << ";\n"; } } std::cout << "}" << std::endl; } } // namespace aapt tools/aapt2/Debug.h 0 → 100644 +33 −0 Original line number Diff line number Diff line /* * Copyright (C) 2015 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef AAPT_DEBUG_H #define AAPT_DEBUG_H #include "ResourceTable.h" #include <memory> namespace aapt { struct Debug { static void printTable(const std::shared_ptr<ResourceTable>& table); static void printStyleGraph(const std::shared_ptr<ResourceTable>& table); }; } // namespace aapt #endif // AAPT_DEBUG_H tools/aapt2/JavaClassGenerator.cpp +9 −4 Original line number Diff line number Diff line Loading @@ -81,23 +81,28 @@ static std::u16string transform(const StringPiece16& symbol) { } struct GenArgs : ValueVisitorArgs { GenArgs(std::ostream* o, std::u16string* e) : out(o), entryName(e) { GenArgs(std::ostream* o, const std::u16string* p, std::u16string* e) : out(o), package(p), entryName(e) { } std::ostream* out; const std::u16string* package; std::u16string* entryName; }; void JavaClassGenerator::visit(const Styleable& styleable, ValueVisitorArgs& a) { const StringPiece finalModifier = mOptions.useFinal ? " final" : ""; std::ostream* out = static_cast<GenArgs&>(a).out; const std::u16string* package = static_cast<GenArgs&>(a).package; std::u16string* entryName = static_cast<GenArgs&>(a).entryName; // This must be sorted by resource ID. std::vector<std::pair<ResourceId, ResourceNameRef>> sortedAttributes; sortedAttributes.reserve(styleable.entries.size()); for (const auto& attr : styleable.entries) { assert(attr.id.isValid() && "no ID set for Styleable entry"); // If we are not encoding final attributes, the styleable entry may have no ID // if we are building a static library. assert((!mOptions.useFinal || attr.id.isValid()) && "no ID set for Styleable entry"); assert(attr.name.isValid() && "no name set for Styleable entry"); sortedAttributes.emplace_back(attr.id, attr.name); } Loading Loading @@ -129,7 +134,7 @@ void JavaClassGenerator::visit(const Styleable& styleable, ValueVisitorArgs& a) // We may reference IDs from other packages, so prefix the entry name with // the package. const ResourceNameRef& itemName = sortedAttributes[i].second; if (itemName.package != mTable->getPackage()) { if (itemName.package != *package) { *out << "_" << transform(itemName.package); } *out << "_" << transform(itemName.entry) << " = " << i << ";" << std::endl; Loading Loading @@ -172,7 +177,7 @@ bool JavaClassGenerator::generateType(const std::u16string& package, size_t pack if (type.type == ResourceType::kStyleable) { assert(!entry->values.empty()); entry->values.front().value->accept(*this, GenArgs{ &out, &unmangledName }); entry->values.front().value->accept(*this, GenArgs{ &out, &package, &unmangledName }); } else { out << " " << "public static" << finalModifier << " int " << transform(unmangledName) << " = " << id << ";" << std::endl; Loading Loading
tools/aapt2/Android.mk +1 −0 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ sources := \ BinaryXmlPullParser.cpp \ BindingXmlPullParser.cpp \ ConfigDescription.cpp \ Debug.cpp \ Files.cpp \ Flag.cpp \ JavaClassGenerator.cpp \ Loading
tools/aapt2/BinaryResourceParser.cpp +29 −14 Original line number Diff line number Diff line Loading @@ -475,10 +475,17 @@ bool BinaryResourceParser::parsePublic(const ResChunk_header* chunk) { source.line = entry->sourceLine; } if (!mTable->markPublic(name, resId, source)) { if (!mTable->markPublicAllowMangled(name, resId, source)) { return false; } // Add this resource name->id mapping to the index so // that we can resolve all ID references to name references. auto cacheIter = mIdIndex.find(resId); if (cacheIter == mIdIndex.end()) { mIdIndex.insert({ resId, name }); } entry++; } return true; Loading Loading @@ -611,12 +618,12 @@ bool BinaryResourceParser::parseType(const ResChunk_header* chunk) { source.line = sourceBlock->line; } if (!mTable->addResource(name, config, source, std::move(resourceValue))) { if (!mTable->addResourceAllowMangled(name, config, source, std::move(resourceValue))) { return false; } if ((entry->flags & ResTable_entry::FLAG_PUBLIC) != 0) { if (!mTable->markPublic(name, resId, mSource.line(0))) { if (!mTable->markPublicAllowMangled(name, resId, mSource.line(0))) { return false; } } Loading @@ -635,6 +642,10 @@ std::unique_ptr<Item> BinaryResourceParser::parseValue(const ResourceNameRef& na const ConfigDescription& config, const Res_value* value, uint16_t flags) { if (name.type == ResourceType::kId) { return util::make_unique<Id>(); } if (value->dataType == Res_value::TYPE_STRING) { StringPiece16 str = util::getString(mValuePool, value->data); Loading Loading @@ -697,13 +708,6 @@ std::unique_ptr<Item> BinaryResourceParser::parseValue(const ResourceNameRef& na StringPool::Context{ 1, config })); } if (name.type == ResourceType::kId || (value->dataType == Res_value::TYPE_NULL && value->data == Res_value::DATA_NULL_UNDEFINED && (flags & ResTable_entry::FLAG_WEAK) != 0)) { return util::make_unique<Id>(); } // Treat this as a raw binary primitive. return util::make_unique<BinaryPrimitive>(*value); } Loading Loading @@ -789,10 +793,21 @@ std::unique_ptr<Attribute> BinaryResourceParser::parseAttr(const ResourceNameRef continue; } attr->symbols.push_back(Attribute::Symbol{ Reference(mapEntry.name.ident), mapEntry.value.data }); Attribute::Symbol symbol; symbol.value = mapEntry.value.data; if (mapEntry.name.ident == 0) { // The map entry's key (id) is not set. This must be // a symbol reference, so resolve it. ResourceNameRef symbolName; bool result = getSymbol(&mapEntry.name.ident, &symbolName); assert(result); symbol.symbol.name = symbolName.toResourceName(); } else { // The map entry's key (id) is a regular reference. symbol.symbol.id = mapEntry.name.ident; } attr->symbols.push_back(std::move(symbol)); } } Loading
tools/aapt2/Debug.cpp 0 → 100644 +181 −0 Original line number Diff line number Diff line /* * Copyright (C) 2015 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "Debug.h" #include "ResourceTable.h" #include "ResourceValues.h" #include "Util.h" #include <algorithm> #include <iostream> #include <map> #include <memory> #include <set> #include <vector> namespace aapt { struct PrintVisitor : ConstValueVisitor { void visit(const Attribute& attr, ValueVisitorArgs&) override { std::cout << "(attr) type="; attr.printMask(std::cout); static constexpr uint32_t kMask = android::ResTable_map::TYPE_ENUM | android::ResTable_map::TYPE_FLAGS; if (attr.typeMask & kMask) { for (const auto& symbol : attr.symbols) { std::cout << "\n " << symbol.symbol.name.entry << " (" << symbol.symbol.id << ") = " << symbol.value; } } } void visit(const Style& style, ValueVisitorArgs&) override { std::cout << "(style)"; if (style.parent.name.isValid() || style.parent.id.isValid()) { std::cout << " parent="; if (style.parent.name.isValid()) { std::cout << style.parent.name << " "; } if (style.parent.id.isValid()) { std::cout << style.parent.id; } } for (const auto& entry : style.entries) { std::cout << "\n "; if (entry.key.name.isValid()) { std::cout << entry.key.name.package << ":" << entry.key.name.entry; } if (entry.key.id.isValid()) { std::cout << "(" << entry.key.id << ")"; } std::cout << "=" << *entry.value; } } void visit(const Array& array, ValueVisitorArgs&) override { array.print(std::cout); } void visit(const Plural& plural, ValueVisitorArgs&) override { plural.print(std::cout); } void visit(const Styleable& styleable, ValueVisitorArgs&) override { styleable.print(std::cout); } void visitItem(const Item& item, ValueVisitorArgs& args) override { item.print(std::cout); } }; void Debug::printTable(const std::shared_ptr<ResourceTable>& table) { std::cout << "Package name=" << table->getPackage(); if (table->getPackageId() != ResourceTable::kUnsetPackageId) { std::cout << " id=" << std::hex << table->getPackageId() << std::dec; } std::cout << std::endl; for (const auto& type : *table) { std::cout << " type " << type->type; if (type->typeId != ResourceTableType::kUnsetTypeId) { std::cout << " id=" << std::hex << type->typeId << std::dec; } std::cout << " entryCount=" << type->entries.size() << std::endl; std::vector<const ResourceEntry*> sortedEntries; for (const auto& entry : type->entries) { auto iter = std::lower_bound(sortedEntries.begin(), sortedEntries.end(), entry.get(), [](const ResourceEntry* a, const ResourceEntry* b) -> bool { return a->entryId < b->entryId; }); sortedEntries.insert(iter, entry.get()); } for (const ResourceEntry* entry : sortedEntries) { ResourceId id = { table->getPackageId(), type->typeId, entry->entryId }; ResourceName name = { table->getPackage(), type->type, entry->name }; std::cout << " spec resource " << id << " " << name; if (entry->publicStatus.isPublic) { std::cout << " PUBLIC"; } std::cout << std::endl; PrintVisitor visitor; for (const auto& value : entry->values) { std::cout << " (" << value.config << ") "; value.value->accept(visitor, {}); std::cout << std::endl; } } } } static size_t getNodeIndex(const std::vector<ResourceName>& names, const ResourceName& name) { auto iter = std::lower_bound(names.begin(), names.end(), name); assert(iter != names.end() && *iter == name); return std::distance(names.begin(), iter); } void Debug::printStyleGraph(const std::shared_ptr<ResourceTable>& table) { std::vector<ResourceName> names; std::map<ResourceName, std::set<ResourceName>> graph; for (const auto& type : *table) { for (const auto& entry : type->entries) { ResourceName name = { table->getPackage(), type->type, entry->name }; for (const auto& value : entry->values) { visitFunc<Style>(*value.value, [&](const Style& style) { if (style.parent.name.isValid()) { names.push_back(style.parent.name); names.push_back(name); graph[style.parent.name].insert(name); } }); } } } std::sort(names.begin(), names.end()); auto it1 = std::unique(names.begin(), names.end()); names.resize(std::distance(names.begin(), it1)); std::cout << "digraph styles {\n"; for (const auto& name : names) { std::cout << " node_" << getNodeIndex(names, name) << " [label=\"" << name.entry << "\"];\n"; } for (const auto& entry : graph) { const ResourceName& parent = entry.first; size_t parentNodeIndex = getNodeIndex(names, parent); for (const auto& childName : entry.second) { std::cout << "node_" << getNodeIndex(names, childName) << " -> " << "node_" << parentNodeIndex << ";\n"; } } std::cout << "}" << std::endl; } } // namespace aapt
tools/aapt2/Debug.h 0 → 100644 +33 −0 Original line number Diff line number Diff line /* * Copyright (C) 2015 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef AAPT_DEBUG_H #define AAPT_DEBUG_H #include "ResourceTable.h" #include <memory> namespace aapt { struct Debug { static void printTable(const std::shared_ptr<ResourceTable>& table); static void printStyleGraph(const std::shared_ptr<ResourceTable>& table); }; } // namespace aapt #endif // AAPT_DEBUG_H
tools/aapt2/JavaClassGenerator.cpp +9 −4 Original line number Diff line number Diff line Loading @@ -81,23 +81,28 @@ static std::u16string transform(const StringPiece16& symbol) { } struct GenArgs : ValueVisitorArgs { GenArgs(std::ostream* o, std::u16string* e) : out(o), entryName(e) { GenArgs(std::ostream* o, const std::u16string* p, std::u16string* e) : out(o), package(p), entryName(e) { } std::ostream* out; const std::u16string* package; std::u16string* entryName; }; void JavaClassGenerator::visit(const Styleable& styleable, ValueVisitorArgs& a) { const StringPiece finalModifier = mOptions.useFinal ? " final" : ""; std::ostream* out = static_cast<GenArgs&>(a).out; const std::u16string* package = static_cast<GenArgs&>(a).package; std::u16string* entryName = static_cast<GenArgs&>(a).entryName; // This must be sorted by resource ID. std::vector<std::pair<ResourceId, ResourceNameRef>> sortedAttributes; sortedAttributes.reserve(styleable.entries.size()); for (const auto& attr : styleable.entries) { assert(attr.id.isValid() && "no ID set for Styleable entry"); // If we are not encoding final attributes, the styleable entry may have no ID // if we are building a static library. assert((!mOptions.useFinal || attr.id.isValid()) && "no ID set for Styleable entry"); assert(attr.name.isValid() && "no name set for Styleable entry"); sortedAttributes.emplace_back(attr.id, attr.name); } Loading Loading @@ -129,7 +134,7 @@ void JavaClassGenerator::visit(const Styleable& styleable, ValueVisitorArgs& a) // We may reference IDs from other packages, so prefix the entry name with // the package. const ResourceNameRef& itemName = sortedAttributes[i].second; if (itemName.package != mTable->getPackage()) { if (itemName.package != *package) { *out << "_" << transform(itemName.package); } *out << "_" << transform(itemName.entry) << " = " << i << ";" << std::endl; Loading Loading @@ -172,7 +177,7 @@ bool JavaClassGenerator::generateType(const std::u16string& package, size_t pack if (type.type == ResourceType::kStyleable) { assert(!entry->values.empty()); entry->values.front().value->accept(*this, GenArgs{ &out, &unmangledName }); entry->values.front().value->accept(*this, GenArgs{ &out, &package, &unmangledName }); } else { out << " " << "public static" << finalModifier << " int " << transform(unmangledName) << " = " << id << ";" << std::endl; Loading