blob: 61c304b2c048d85100f31a7d56c12a56c04f8585 [file] [log] [blame]
Adam Lesinski330edcd2015-05-04 17:40:56 -07001/*
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 "Debug.h"
Adam Lesinski330edcd2015-05-04 17:40:56 -070018
19#include <algorithm>
20#include <iostream>
21#include <map>
22#include <memory>
Adam Lesinskid13fb242015-05-12 20:40:48 -070023#include <queue>
Adam Lesinski330edcd2015-05-04 17:40:56 -070024#include <set>
25#include <vector>
26
Adam Lesinskice5e56e2016-10-21 17:56:45 -070027#include "android-base/logging.h"
28
29#include "ResourceTable.h"
30#include "ResourceValues.h"
31#include "ValueVisitor.h"
32#include "util/Util.h"
33
Adam Lesinski330edcd2015-05-04 17:40:56 -070034namespace aapt {
35
Adam Lesinski6b372992017-08-09 10:54:23 -070036namespace {
37
Adam Lesinskie59f0d82017-10-13 09:36:53 -070038class PrintVisitor : public ConstValueVisitor {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070039 public:
Adam Lesinskie59f0d82017-10-13 09:36:53 -070040 using ConstValueVisitor::Visit;
Adam Lesinski1ab598f2015-08-14 14:26:04 -070041
Adam Lesinskie59f0d82017-10-13 09:36:53 -070042 void Visit(const Attribute* attr) override {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070043 std::cout << "(attr) type=";
Adam Lesinskice5e56e2016-10-21 17:56:45 -070044 attr->PrintMask(&std::cout);
Adam Lesinskicacb28f2016-10-19 12:18:14 -070045 static constexpr uint32_t kMask =
46 android::ResTable_map::TYPE_ENUM | android::ResTable_map::TYPE_FLAGS;
Adam Lesinskice5e56e2016-10-21 17:56:45 -070047 if (attr->type_mask & kMask) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070048 for (const auto& symbol : attr->symbols) {
49 std::cout << "\n " << symbol.symbol.name.value().entry;
50 if (symbol.symbol.id) {
51 std::cout << " (" << symbol.symbol.id.value() << ")";
Adam Lesinski330edcd2015-05-04 17:40:56 -070052 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -070053 std::cout << " = " << symbol.value;
54 }
Adam Lesinski330edcd2015-05-04 17:40:56 -070055 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -070056 }
Adam Lesinski330edcd2015-05-04 17:40:56 -070057
Adam Lesinskie59f0d82017-10-13 09:36:53 -070058 void Visit(const Style* style) override {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070059 std::cout << "(style)";
60 if (style->parent) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -070061 const Reference& parent_ref = style->parent.value();
Adam Lesinskicacb28f2016-10-19 12:18:14 -070062 std::cout << " parent=";
Adam Lesinskice5e56e2016-10-21 17:56:45 -070063 if (parent_ref.name) {
64 if (parent_ref.private_reference) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070065 std::cout << "*";
Adam Lesinski330edcd2015-05-04 17:40:56 -070066 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -070067 std::cout << parent_ref.name.value() << " ";
Adam Lesinskicacb28f2016-10-19 12:18:14 -070068 }
Adam Lesinski330edcd2015-05-04 17:40:56 -070069
Adam Lesinskice5e56e2016-10-21 17:56:45 -070070 if (parent_ref.id) {
71 std::cout << parent_ref.id.value();
Adam Lesinskicacb28f2016-10-19 12:18:14 -070072 }
73 }
Adam Lesinski330edcd2015-05-04 17:40:56 -070074
Adam Lesinskicacb28f2016-10-19 12:18:14 -070075 for (const auto& entry : style->entries) {
76 std::cout << "\n ";
77 if (entry.key.name) {
78 const ResourceName& name = entry.key.name.value();
79 if (!name.package.empty()) {
80 std::cout << name.package << ":";
Adam Lesinski330edcd2015-05-04 17:40:56 -070081 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -070082 std::cout << name.entry;
83 }
84
85 if (entry.key.id) {
86 std::cout << "(" << entry.key.id.value() << ")";
87 }
88
89 std::cout << "=" << *entry.value;
Adam Lesinski330edcd2015-05-04 17:40:56 -070090 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -070091 }
Adam Lesinski330edcd2015-05-04 17:40:56 -070092
Adam Lesinskie59f0d82017-10-13 09:36:53 -070093 void Visit(const Array* array) override {
Adam Lesinski6b372992017-08-09 10:54:23 -070094 array->Print(&std::cout);
95 }
Adam Lesinski330edcd2015-05-04 17:40:56 -070096
Adam Lesinskie59f0d82017-10-13 09:36:53 -070097 void Visit(const Plural* plural) override {
Adam Lesinski6b372992017-08-09 10:54:23 -070098 plural->Print(&std::cout);
99 }
Adam Lesinski330edcd2015-05-04 17:40:56 -0700100
Adam Lesinskie59f0d82017-10-13 09:36:53 -0700101 void Visit(const Styleable* styleable) override {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700102 std::cout << "(styleable)";
103 for (const auto& attr : styleable->entries) {
104 std::cout << "\n ";
105 if (attr.name) {
106 const ResourceName& name = attr.name.value();
107 if (!name.package.empty()) {
108 std::cout << name.package << ":";
Adam Lesinski355f2852016-02-13 20:26:45 -0800109 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700110 std::cout << name.entry;
111 }
Adam Lesinski330edcd2015-05-04 17:40:56 -0700112
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700113 if (attr.id) {
114 std::cout << "(" << attr.id.value() << ")";
115 }
Adam Lesinski330edcd2015-05-04 17:40:56 -0700116 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700117 }
118
Adam Lesinskie59f0d82017-10-13 09:36:53 -0700119 void VisitItem(const Item* item) override {
Adam Lesinski6b372992017-08-09 10:54:23 -0700120 item->Print(&std::cout);
121 }
Adam Lesinski330edcd2015-05-04 17:40:56 -0700122};
123
Adam Lesinski6b372992017-08-09 10:54:23 -0700124} // namespace
125
Adam Lesinskie59f0d82017-10-13 09:36:53 -0700126void Debug::PrintTable(const ResourceTable& table, const DebugPrintTableOptions& options) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700127 PrintVisitor visitor;
Adam Lesinski355f2852016-02-13 20:26:45 -0800128
Adam Lesinskie59f0d82017-10-13 09:36:53 -0700129 for (const auto& package : table.packages) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700130 std::cout << "Package name=" << package->name;
131 if (package->id) {
132 std::cout << " id=" << std::hex << (int)package->id.value() << std::dec;
133 }
134 std::cout << std::endl;
135
136 for (const auto& type : package->types) {
137 std::cout << "\n type " << type->type;
138 if (type->id) {
139 std::cout << " id=" << std::hex << (int)type->id.value() << std::dec;
140 }
141 std::cout << " entryCount=" << type->entries.size() << std::endl;
142
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700143 std::vector<const ResourceEntry*> sorted_entries;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700144 for (const auto& entry : type->entries) {
145 auto iter = std::lower_bound(
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700146 sorted_entries.begin(), sorted_entries.end(), entry.get(),
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700147 [](const ResourceEntry* a, const ResourceEntry* b) -> bool {
148 if (a->id && b->id) {
149 return a->id.value() < b->id.value();
150 } else if (a->id) {
151 return true;
152 } else {
153 return false;
154 }
155 });
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700156 sorted_entries.insert(iter, entry.get());
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700157 }
158
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700159 for (const ResourceEntry* entry : sorted_entries) {
Adam Lesinski6b372992017-08-09 10:54:23 -0700160 const ResourceId id(package->id.value_or_default(0), type->id.value_or_default(0),
161 entry->id.value_or_default(0));
162 const ResourceName name(package->name, type->type, entry->name);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700163
164 std::cout << " spec resource " << id << " " << name;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700165 switch (entry->symbol_status.state) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700166 case SymbolState::kPublic:
167 std::cout << " PUBLIC";
168 break;
169 case SymbolState::kPrivate:
170 std::cout << " _PRIVATE_";
171 break;
172 default:
173 break;
Adam Lesinski330edcd2015-05-04 17:40:56 -0700174 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700175
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700176 std::cout << std::endl;
Adam Lesinski330edcd2015-05-04 17:40:56 -0700177
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700178 for (const auto& value : entry->values) {
179 std::cout << " (" << value->config << ") ";
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700180 value->value->Accept(&visitor);
181 if (options.show_sources && !value->value->GetSource().path.empty()) {
182 std::cout << " src=" << value->value->GetSource();
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700183 }
184 std::cout << std::endl;
Adam Lesinski330edcd2015-05-04 17:40:56 -0700185 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700186 }
Adam Lesinski330edcd2015-05-04 17:40:56 -0700187 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700188 }
Adam Lesinski330edcd2015-05-04 17:40:56 -0700189}
190
Adam Lesinski6b372992017-08-09 10:54:23 -0700191static size_t GetNodeIndex(const std::vector<ResourceName>& names, const ResourceName& name) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700192 auto iter = std::lower_bound(names.begin(), names.end(), name);
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700193 CHECK(iter != names.end());
194 CHECK(*iter == name);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700195 return std::distance(names.begin(), iter);
Adam Lesinski330edcd2015-05-04 17:40:56 -0700196}
197
Adam Lesinski6b372992017-08-09 10:54:23 -0700198void Debug::PrintStyleGraph(ResourceTable* table, const ResourceName& target_style) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700199 std::map<ResourceName, std::set<ResourceName>> graph;
Adam Lesinski330edcd2015-05-04 17:40:56 -0700200
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700201 std::queue<ResourceName> styles_to_visit;
202 styles_to_visit.push(target_style);
203 for (; !styles_to_visit.empty(); styles_to_visit.pop()) {
204 const ResourceName& style_name = styles_to_visit.front();
205 std::set<ResourceName>& parents = graph[style_name];
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700206 if (!parents.empty()) {
207 // We've already visited this style.
208 continue;
209 }
210
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700211 Maybe<ResourceTable::SearchResult> result = table->FindResource(style_name);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700212 if (result) {
213 ResourceEntry* entry = result.value().entry;
214 for (const auto& value : entry->values) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700215 if (Style* style = ValueCast<Style>(value->value.get())) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700216 if (style->parent && style->parent.value().name) {
217 parents.insert(style->parent.value().name.value());
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700218 styles_to_visit.push(style->parent.value().name.value());
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700219 }
Adam Lesinskid13fb242015-05-12 20:40:48 -0700220 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700221 }
Adam Lesinski330edcd2015-05-04 17:40:56 -0700222 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700223 }
Adam Lesinski330edcd2015-05-04 17:40:56 -0700224
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700225 std::vector<ResourceName> names;
226 for (const auto& entry : graph) {
227 names.push_back(entry.first);
228 }
229
230 std::cout << "digraph styles {\n";
231 for (const auto& name : names) {
Adam Lesinski6b372992017-08-09 10:54:23 -0700232 std::cout << " node_" << GetNodeIndex(names, name) << " [label=\"" << name << "\"];\n";
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700233 }
234
235 for (const auto& entry : graph) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700236 const ResourceName& style_name = entry.first;
237 size_t style_node_index = GetNodeIndex(names, style_name);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700238
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700239 for (const auto& parent_name : entry.second) {
240 std::cout << " node_" << style_node_index << " -> "
241 << "node_" << GetNodeIndex(names, parent_name) << ";\n";
Adam Lesinskid13fb242015-05-12 20:40:48 -0700242 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700243 }
Adam Lesinski330edcd2015-05-04 17:40:56 -0700244
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700245 std::cout << "}" << std::endl;
Adam Lesinski330edcd2015-05-04 17:40:56 -0700246}
247
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700248void Debug::DumpHex(const void* data, size_t len) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700249 const uint8_t* d = (const uint8_t*)data;
250 for (size_t i = 0; i < len; i++) {
Adam Lesinski6b372992017-08-09 10:54:23 -0700251 std::cerr << std::hex << std::setfill('0') << std::setw(2) << (uint32_t)d[i] << " ";
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700252 if (i % 8 == 7) {
253 std::cerr << "\n";
Adam Lesinski52364f72016-01-11 13:10:24 -0800254 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700255 }
Adam Lesinski52364f72016-01-11 13:10:24 -0800256
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700257 if (len - 1 % 8 != 7) {
258 std::cerr << std::endl;
259 }
Adam Lesinski52364f72016-01-11 13:10:24 -0800260}
261
Adam Lesinski5eeaadd2016-08-25 12:26:56 -0700262namespace {
263
Adam Lesinskie59f0d82017-10-13 09:36:53 -0700264class XmlPrinter : public xml::ConstVisitor {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700265 public:
Adam Lesinskie59f0d82017-10-13 09:36:53 -0700266 using xml::ConstVisitor::Visit;
Adam Lesinski5eeaadd2016-08-25 12:26:56 -0700267
Adam Lesinskie59f0d82017-10-13 09:36:53 -0700268 void Visit(const xml::Element* el) override {
Adam Lesinski6b372992017-08-09 10:54:23 -0700269 const size_t previous_size = prefix_.size();
270
271 for (const xml::NamespaceDecl& decl : el->namespace_decls) {
272 std::cerr << prefix_ << "N: " << decl.prefix << "=" << decl.uri
273 << " (line=" << decl.line_number << ")\n";
274 prefix_ += " ";
275 }
276
277 std::cerr << prefix_ << "E: ";
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700278 if (!el->namespace_uri.empty()) {
279 std::cerr << el->namespace_uri << ":";
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700280 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700281 std::cerr << el->name << " (line=" << el->line_number << ")\n";
Adam Lesinski5eeaadd2016-08-25 12:26:56 -0700282
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700283 for (const xml::Attribute& attr : el->attributes) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700284 std::cerr << prefix_ << " A: ";
285 if (!attr.namespace_uri.empty()) {
286 std::cerr << attr.namespace_uri << ":";
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700287 }
Adam Lesinski4ca56972017-04-26 21:49:53 -0700288 std::cerr << attr.name;
289
290 if (attr.compiled_attribute) {
291 std::cerr << "(" << attr.compiled_attribute.value().id.value_or_default(ResourceId(0x0))
292 << ")";
293 }
Shane Farmer6ed40612017-09-06 10:00:07 -0700294 std::cerr << "=";
295 if (attr.compiled_value != nullptr) {
296 std::cerr << *attr.compiled_value;
297 } else {
298 std::cerr << attr.value;
299 }
300 std::cerr << "\n";
Adam Lesinski5eeaadd2016-08-25 12:26:56 -0700301 }
302
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700303 prefix_ += " ";
Adam Lesinskie59f0d82017-10-13 09:36:53 -0700304 xml::ConstVisitor::Visit(el);
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700305 prefix_.resize(previous_size);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700306 }
Adam Lesinski5eeaadd2016-08-25 12:26:56 -0700307
Adam Lesinskie59f0d82017-10-13 09:36:53 -0700308 void Visit(const xml::Text* text) override {
Adam Lesinski6b372992017-08-09 10:54:23 -0700309 std::cerr << prefix_ << "T: '" << text->text << "'\n";
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700310 }
311
312 private:
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700313 std::string prefix_;
Adam Lesinski5eeaadd2016-08-25 12:26:56 -0700314};
315
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700316} // namespace
Adam Lesinski5eeaadd2016-08-25 12:26:56 -0700317
Adam Lesinskie59f0d82017-10-13 09:36:53 -0700318void Debug::DumpXml(const xml::XmlResource& doc) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700319 XmlPrinter printer;
Adam Lesinskie59f0d82017-10-13 09:36:53 -0700320 doc.root->Accept(&printer);
Adam Lesinski5eeaadd2016-08-25 12:26:56 -0700321}
Adam Lesinski52364f72016-01-11 13:10:24 -0800322
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700323} // namespace aapt